Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Semantics.Quantities/AudioEngineering/Cents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// All rights reserved.
// Licensed under the MIT license.

namespace ktsu.Semantics;
namespace ktsu.Semantics.Quantities;

using System.Globalization;
using System.Numerics;
Expand Down Expand Up @@ -43,6 +43,7 @@ public readonly record struct Cents<T>(T Value) : IComparable<Cents<T>>
/// <returns>A new <see cref="Cents{T}"/>.</returns>
public static Cents<T> FromFrequencyRatio(Ratio<T> ratio)
{
ArgumentNullException.ThrowIfNull(ratio);
double r = double.CreateChecked(ratio.Value);
double cents = 1200.0 * Math.Log2(r);
return new(T.CreateChecked(cents));
Expand All @@ -62,7 +63,7 @@ public Ratio<T> ToFrequencyRatio()
{
double cents = double.CreateChecked(Value);
double ratio = Math.Pow(2.0, cents / 1200.0);
return new(T.CreateChecked(ratio));
return Ratio<T>.Create(T.CreateChecked(ratio));
}

/// <summary>Adds two intervals.</summary>
Expand Down
4 changes: 2 additions & 2 deletions Semantics.Quantities/AudioEngineering/Decibels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// All rights reserved.
// Licensed under the MIT license.

namespace ktsu.Semantics;
namespace ktsu.Semantics.Quantities;

using System.Globalization;
using System.Numerics;
Expand Down Expand Up @@ -84,7 +84,7 @@ public Ratio<T> ToPower()
{
double db = double.CreateChecked(Value);
double linear = Math.Pow(10.0, db / 10.0);
return new(T.CreateChecked(linear));
return Ratio<T>.Create(T.CreateChecked(linear));
}

/// <summary>Adds two decibel levels (cascading two stages multiplies their linear gains).</summary>
Expand Down
2 changes: 1 addition & 1 deletion Semantics.Quantities/AudioEngineering/Gain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// All rights reserved.
// Licensed under the MIT license.

namespace ktsu.Semantics;
namespace ktsu.Semantics.Quantities;

using System.Globalization;
using System.Numerics;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// All rights reserved.
// Licensed under the MIT license.

namespace ktsu.Semantics;
namespace ktsu.Semantics.Quantities;

using System.Numerics;

Expand Down
2 changes: 1 addition & 1 deletion Semantics.Quantities/AudioEngineering/ParameterTaper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// All rights reserved.
// Licensed under the MIT license.

namespace ktsu.Semantics;
namespace ktsu.Semantics.Quantities;

/// <summary>
/// Describes how a <see cref="NormalizedParameter{T}"/> maps a host-normalized position in
Expand Down
10 changes: 7 additions & 3 deletions Semantics.Quantities/AudioEngineering/Percent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// All rights reserved.
// Licensed under the MIT license.

namespace ktsu.Semantics;
namespace ktsu.Semantics.Quantities;

using System.Globalization;
using System.Numerics;
Expand Down Expand Up @@ -39,7 +39,11 @@ public readonly record struct Percent<T>(T Value) : IComparable<Percent<T>>
/// </summary>
/// <param name="ratio">The ratio to convert.</param>
/// <returns>A new <see cref="Percent{T}"/>.</returns>
public static Percent<T> FromRatio(Ratio<T> ratio) => ratio.ToPercent();
public static Percent<T> FromRatio(Ratio<T> ratio)
{
ArgumentNullException.ThrowIfNull(ratio);
return FromFraction(ratio.Value);
}

/// <summary>
/// Converts this percentage to a fraction in the range <c>[0, 1]</c> (50% → 0.5).
Expand All @@ -51,7 +55,7 @@ public readonly record struct Percent<T>(T Value) : IComparable<Percent<T>>
/// Converts this percentage to a ratio (100% → 1).
/// </summary>
/// <returns>The equivalent <see cref="Ratio{T}"/>.</returns>
public Ratio<T> ToRatio() => new(ToFraction());
public Ratio<T> ToRatio() => Ratio<T>.Create(ToFraction());

/// <inheritdoc/>
public int CompareTo(Percent<T> other) => Value.CompareTo(other.Value);
Expand Down
2 changes: 1 addition & 1 deletion Semantics.Quantities/AudioEngineering/QFactor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// All rights reserved.
// Licensed under the MIT license.

namespace ktsu.Semantics;
namespace ktsu.Semantics.Quantities;

using System.Globalization;
using System.Numerics;
Expand Down
103 changes: 0 additions & 103 deletions Semantics.Quantities/AudioEngineering/Ratio.cs

This file was deleted.

5 changes: 3 additions & 2 deletions Semantics.Quantities/AudioEngineering/Semitones.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// All rights reserved.
// Licensed under the MIT license.

namespace ktsu.Semantics;
namespace ktsu.Semantics.Quantities;

using System.Globalization;
using System.Numerics;
Expand Down Expand Up @@ -47,6 +47,7 @@ public readonly record struct Semitones<T>(T Value) : IComparable<Semitones<T>>
/// <returns>A new <see cref="Semitones{T}"/>.</returns>
public static Semitones<T> FromFrequencyRatio(Ratio<T> ratio)
{
ArgumentNullException.ThrowIfNull(ratio);
double r = double.CreateChecked(ratio.Value);
double semitones = 12.0 * Math.Log2(r);
return new(T.CreateChecked(semitones));
Expand All @@ -66,7 +67,7 @@ public Ratio<T> ToFrequencyRatio()
{
double semitones = double.CreateChecked(Value);
double ratio = Math.Pow(2.0, semitones / 12.0);
return new(T.CreateChecked(ratio));
return Ratio<T>.Create(T.CreateChecked(ratio));
}

/// <summary>Adds two intervals.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ public record Ratio<T> : PhysicalQuantity<Ratio<T>, T>, IVector0<Ratio<T>, T>
/// Magnitude subtraction stays a magnitude (per the unified-vector model).
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Ratio<T> operator -(Ratio<T> left, Ratio<T> right) => Create(T.Abs(left.Quantity - right.Quantity));
/// <summary>
/// Multiplies Ratio by Ratio to produce Ratio.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static Ratio<T> operator *(Ratio<T> left, Ratio<T> right) => Multiply<Ratio<T>>(left, right);
/// <summary>
/// Multiplies Ratio by SignedRatio to produce SignedRatio.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SignedRatio<T> operator *(Ratio<T> left, SignedRatio<T> right) => Multiply<SignedRatio<T>>(left, right);
/// <summary>
/// Divides Ratio by Duration to produce Frequency.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,13 @@ public record SignedRatio<T> : PhysicalQuantity<SignedRatio<T>, T>, IVector1<Sig
/// </summary>
/// <returns>The non-negative magnitude.</returns>
public Ratio<T> Magnitude() => Ratio<T>.Create(T.Abs(Value));
/// <summary>
/// Multiplies SignedRatio by Ratio to produce SignedRatio.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SignedRatio<T> operator *(SignedRatio<T> left, Ratio<T> right) => Multiply<SignedRatio<T>>(left, right);
/// <summary>
/// Divides SignedRatio by Ratio to produce SignedRatio.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Physics quantity operator")] public static SignedRatio<T> operator /(SignedRatio<T> left, Ratio<T> right) => Divide<SignedRatio<T>>(left, right);
};

4 changes: 3 additions & 1 deletion Semantics.SourceGenerators/Metadata/dimensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
]
}
},
"integrals": [],
"integrals": [
{ "other": "Dimensionless", "result": "Dimensionless" }
],
"derivatives": [],
"dotProducts": [],
"crossProducts": []
Expand Down
14 changes: 13 additions & 1 deletion Semantics.Test/AudioEngineeringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace ktsu.Semantics.Test;

using ktsu.Semantics.Quantities;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
Expand Down Expand Up @@ -74,11 +75,22 @@ public void Cents_OctaveIsFrequencyRatioOfTwo()
[TestMethod]
public void RatioPercent_RoundTrip()
{
Assert.AreEqual(50.0, Ratio<double>.Create(0.5).ToPercent().Value, Tolerance);
Assert.AreEqual(50.0, Percent<double>.FromRatio(Ratio<double>.Create(0.5)).Value, Tolerance);
Assert.AreEqual(0.5, Percent<double>.Create(50.0).ToRatio().Value, Tolerance);
Assert.AreEqual(0.25, Percent<double>.FromFraction(0.25).ToFraction(), Tolerance);
}

[TestMethod]
public void Ratio_Arithmetic_Comes_From_The_Generator()
{
// The audio-specific Ratio struct is gone; the generated Dimensionless
// Ratio supplies the arithmetic.
Ratio<double> mix = Ratio<double>.Create(0.5) * Ratio<double>.Create(0.5);
Assert.AreEqual(0.25, mix.Value, Tolerance);
// Same-type division yields the raw storage ratio, as for every quantity.
Assert.AreEqual(2.0, Ratio<double>.Create(1.0) / Ratio<double>.Create(0.5), Tolerance);
}

[TestMethod]
public void QFactor_FromBandwidth_AndBack()
{
Expand Down
16 changes: 9 additions & 7 deletions docs/migration-guide-2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ For the architecture behind these changes see

## Quick checklist

1. Update the namespace: quantities moved from `ktsu.Semantics` to
`ktsu.Semantics.Quantities` (unit singletons live in
`ktsu.Semantics.Quantities.Units`). The audio-engineering types
(`Decibels`, `Gain`, `NormalizedParameter`, …) remain in `ktsu.Semantics`.
1. Update the namespace: quantities — including the audio-engineering types
(`Decibels`, `Gain`, `NormalizedParameter`, …) — moved from
`ktsu.Semantics` to `ktsu.Semantics.Quantities` (unit singletons live in
`ktsu.Semantics.Quantities.Units`).
2. Rename vector-capable quantities to their explicit form — `Force<double>`
becomes `ForceMagnitude<double>` (or `Force1D`/`Force2D`/`Force3D` if you
were tracking sign or direction). The full table is below.
Expand All @@ -38,7 +38,7 @@ For the architecture behind these changes see
|---|---|
| `ktsu.Semantics` (quantity types) | `ktsu.Semantics.Quantities` |
| `ktsu.Semantics` (unit registry) | `ktsu.Semantics.Quantities.Units` |
| `ktsu.Semantics` (audio engineering: `Decibels`, `Gain`, `Cents`, `Semitones`, `Percent`, `QFactor`, `Ratio` (audio), `NormalizedParameter`, `ParameterTaper`) | unchanged |
| `ktsu.Semantics` (audio engineering: `Decibels`, `Gain`, `Cents`, `Semitones`, `Percent`, `QFactor`, `NormalizedParameter`, `ParameterTaper`) | `ktsu.Semantics.Quantities` |
| `ktsu.Semantics.Strings`, `ktsu.Semantics.Paths` | unchanged |

## Quantity type renames
Expand Down Expand Up @@ -204,14 +204,16 @@ different dimensions throws `ArgumentException`; equality across dimensions is
| `MolesPerSecond` unit on `ReactionRate` | none — `ReactionRate` is volumetric (mol/(m³·s)); the 1.x unit was mislabelled |
| `PhysicalConstants.Conversion.*` | conversions are baked into factories; raw factors live in `conversions.json` |
| `SoundPressureLevel.AWeighted()` / `EquivalentLevel` | none (1.x implementations were placeholders) |
| audio-engineering `Ratio<T>` | the generated `Ratio<T>` (Dimensionless V0; non-negative, `Ratio × Ratio` generated, same-type `/` yields the storage value); percentage bridging lives on `Percent<T>.FromRatio`/`ToRatio` |

## What didn't change

- `Semantics.Strings` and `Semantics.Paths` — same namespaces, same types;
2.0 only adds validation attributes.
- The audio-engineering types added late in 1.x (`Decibels`, `Gain`,
`NormalizedParameter`, `ParameterTaper`, …) ship unchanged in
`ktsu.Semantics`.
`NormalizedParameter`, `ParameterTaper`, …) keep their APIs, but move to
`ktsu.Semantics.Quantities` and exchange ratios through the generated
`Ratio<T>`.
- Target frameworks: `net7.0` through `net10.0`.
- Quantities remain generic over the numeric storage type
(`where T : struct, INumber<T>`).
Expand Down
Loading