[minor] Add a PreciseNumber storage-type alias package - #232
Merged
Merged
Conversation
Semantics.Quantities.Precise joins Double, Float and Decimal as a props-only satellite, binding every quantity to ktsu.PreciseNumber.PreciseNumber so a consumer writes Mass rather than Mass<PreciseNumber>. It is the first alias package whose storage type comes from a package rather than being a C# keyword, which is the only real difference. The generator script learns to write a fully qualified name into the alias, and the project carries a PackageReference on ktsu.PreciseNumber so the name resolves for a consumer. Semantics.Quantities itself still has no PreciseNumber dependency: the support is opt-in through this package alone. What it buys is exactness. A unit factor is applied at the precision the value carries rather than at the fifteen to seventeen significant digits a double holds, so Length.FromFoot(1).In(Units.Inch) is exactly 12 where double gives 12.000000000000002, and Velocity3D.One.Length() is the square root of three to fifty digits rather than to a double's worth. PreciseNumber is deliberately not added to precision.json. That file feeds PrecisionGenerator, which emits typeof(<storage type>) into StorageTypes in the core ktsu.Semantics.Quantities assembly, so an entry there would force the core to reference ktsu.PreciseNumber and undo the separation this package exists to keep. StorageTypes has no reader anywhere in the repository, so the entry would buy nothing in exchange. Worth revisiting only if StorageTypes acquires a purpose, and then as a decision about where it should live. Testing: PreciseNumberStorageConversionTests runs the shared conversion suite over PreciseNumber with exact assertions, one derived line as the base class intends. Its tolerance for non-terminating answers is 1e-35 rather than something tighter because the limit is the expected literals, not the storage type: the knot is a repeating fraction written to 38 decimal places and PreciseNumber answers it with 50 correct digits, so the residual measured is the truncation of the reference value. That is still ten orders of magnitude tighter than decimal's, so a factor arriving through a double fails it by a wide margin. All 1248 tests pass, the solution builds with no warnings, and rebuilding the generated sources and regenerating the alias props leaves no diff. The package was packed and checked: buildTransitive props, no lib assemblies, no empty symbols package, and dependencies on both ktsu.Semantics.Quantities and ktsu.PreciseNumber for each of net8.0, net9.0 and net10.0. A consumer project built against the props confirmed the aliases resolve and the two values above. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017jrnV7N94UGL8fDRRE8Xt8
|
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Semantics.Quantities.PrecisejoinsDouble,FloatandDecimalas a props-only satellite, binding every quantity toktsu.PreciseNumber.PreciseNumberso a consumer writesMassrather thanMass<PreciseNumber>.It is the first alias package whose storage type comes from a package rather than being a C# keyword, and that is the only real difference. The generator script learns to write a fully qualified name into the alias, and the project carries a
PackageReferenceonktsu.PreciseNumberso the name resolves for a consumer.Semantics.Quantitiesitself still has no PreciseNumber dependency — the support is opt-in through this package alone, as decided when #226 landed.What it buys
A unit factor is applied at the precision the value carries rather than at the 15–17 significant digits a
doubleholds:Both of those are outputs from a real consumer project built against the generated props, not illustrations.
One deviation from the plan, on purpose
PreciseNumber is deliberately not added to
precision.json.That file feeds
PrecisionGenerator, which emitstypeof(<storage type>)into aStorageTypesclass in the corektsu.Semantics.Quantitiesassembly. An entry there would force the core to referencektsu.PreciseNumberand undo the separation this package exists to keep — andStorageTypeshas no reader anywhere in the repository, so the entry would buy nothing in exchange.Worth revisiting only if
StorageTypesacquires a purpose, and then as a decision about where it should live. Happy to add it if you'd rather have it and accept the core dependency.Testing
PreciseNumberStorageConversionTestsruns the shared conversion suite overPreciseNumberwith exact assertions — one derived line, as the base class intends.Its tolerance for non-terminating answers is
1e-35rather than something tighter, and the reason is worth recording: the limit is the expected literals, not the storage type. The knot is a repeating fraction written to 38 decimal places, and PreciseNumber answers it with 50 correct digits, so the residual being measured is the truncation of the reference value.1e-40failed for exactly that reason.1e-35is still ten orders of magnitude tighter thandecimal's, so a factor arriving through adouble— wrong from about the sixteenth digit — fails it by an enormous margin.Verified in this session:
verify-generatedsteps reproduced locally: rebuilding the generated sources and regenerating the alias props leaves no diff.Generated/is untouched, confirming the core is unaffected.buildTransitiveprops, nolib/assemblies, no empty.snupkg(the nuget.org HTTP 400 the sibling csproj warns about), and dependencies on bothktsu.Semantics.Quantitiesandktsu.PreciseNumber 2.0.2for each of net8.0, net9.0 and net10.0.Docs
New package README mirroring the siblings, plus the package table in the root README, the project-layout and regeneration notes in CLAUDE.md, and the "reference exactly one of" list in all three existing alias READMEs.
🤖 Generated with Claude Code
https://claude.ai/code/session_017jrnV7N94UGL8fDRRE8Xt8
Generated by Claude Code