You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Every logarithmic scale is generic over its storage type, so Decibels<PreciseNumber> and PH<decimal> compile and read as precise. The conversions to and from their linear counterparts are not: they convert to double, call Math.Log* / Math.Pow, and convert back.
All eight generated scales are affected: Cents, Decibels, DirectionalityIndex, PH, Semitones, SoundIntensityLevel, SoundPowerLevel, SoundPressureLevel.
Why it matters now
This is a documented decision, not an oversight — CLAUDE.md says the logarithmic scales and the hand-written audio types still compute through double. It is worth revisiting because the premise changed twice since:
So a consumer of the Precise alias package gets exact foot-to-inch conversion and a 50-digit vector length, and — with no diagnostic and no difference in how the type is spelled — roughly 16 significant digits for anything that passes through a decibel or a pH. The alias package is precisely the context in which someone has declared they care about the error budget.
The same applies to decimal, which StorageConversionTests<decimal> otherwise holds to 1e-25.
Scope
Math.Log and Math.Pow over an arbitrary INumber<T> are a real piece of work, not a mechanical change, which is presumably why the original decision went the way it did. Options, roughly in increasing order of cost:
Document it at the call site. Cheapest, and stops it being a surprise: an XML <remarks> on each generated scale saying the conversion is computed in double whatever T is, so it shows in IntelliSense rather than only in CLAUDE.md.
Route through the widest available path. Use decimal where T is decimal, keeping double otherwise. Narrow benefit, small change.
Compute the log and the exponential in T's own arithmetic, the way StorageMath.Sqrt already does for roots — seed from the double result and refine. StorageMath is the obvious home, and Sqrt is the precedent for the shape.
Option 1 is worth doing regardless of whether 3 ever happens.
Verification
Whatever the fix, StorageConversionTests<T> is the natural place to pin it: it already runs the same conversions over double and decimal and takes one derived line per storage type, and a PreciseNumber derived class was added in #232.
What happens
Every logarithmic scale is generic over its storage type, so
Decibels<PreciseNumber>andPH<decimal>compile and read as precise. The conversions to and from their linear counterparts are not: they convert todouble, callMath.Log*/Math.Pow, and convert back.Semantics.SourceGenerators/Generators/LogarithmicScalesGenerator.cs:151:and
:174:Which lands in committed generated source —
Semantics.Quantities/Generated/…/LogarithmicScalesGenerator/Decibels.g.cs:39-40:and
:49-50for the way back:All eight generated scales are affected:
Cents,Decibels,DirectionalityIndex,PH,Semitones,SoundIntensityLevel,SoundPowerLevel,SoundPressureLevel.Why it matters now
This is a documented decision, not an oversight — CLAUDE.md says the logarithmic scales and the hand-written audio types still compute through
double. It is worth revisiting because the premise changed twice since:Length()/Distance()compute roots in the storage type's own arithmetic.ktsu.Semantics.Quantities.Precise, which binds every quantity in a project toktsu.PreciseNumber.PreciseNumberthrough a global-using alias.So a consumer of the Precise alias package gets exact foot-to-inch conversion and a 50-digit vector length, and — with no diagnostic and no difference in how the type is spelled — roughly 16 significant digits for anything that passes through a decibel or a pH. The alias package is precisely the context in which someone has declared they care about the error budget.
The same applies to
decimal, whichStorageConversionTests<decimal>otherwise holds to1e-25.Scope
Math.LogandMath.Powover an arbitraryINumber<T>are a real piece of work, not a mechanical change, which is presumably why the original decision went the way it did. Options, roughly in increasing order of cost:<remarks>on each generated scale saying the conversion is computed indoublewhateverTis, so it shows in IntelliSense rather than only in CLAUDE.md.decimalwhereTisdecimal, keepingdoubleotherwise. Narrow benefit, small change.T's own arithmetic, the wayStorageMath.Sqrtalready does for roots — seed from thedoubleresult and refine.StorageMathis the obvious home, andSqrtis the precedent for the shape.Option 1 is worth doing regardless of whether 3 ever happens.
Verification
Whatever the fix,
StorageConversionTests<T>is the natural place to pin it: it already runs the same conversions overdoubleanddecimaland takes one derived line per storage type, and aPreciseNumberderived class was added in #232.