[major] Make PreciseNumber a value type - #70
Merged
Merged
Conversation
PreciseNumber is now a readonly record struct. Every arithmetic result used to allocate a 40-byte object on top of its BigInteger digits, and that object is gone. A value whose significand fits in an int now allocates nothing for addition, subtraction, multiplication, or comparison, and default(PreciseNumber) equals Zero with no special case. Generic math conversion now works. TryConvertFrom and TryConvertTo in all three modes (checked, saturating, and truncating) cover every BCL numeric type and BigInteger, where they used to throw NotSupportedException. That is what generic code such as T.CreateChecked(0.3048) calls, so PreciseNumber can now be the storage type of a Semantics quantity. Conversion from double keeps the shortest round-trip text, and conversion to double is correctly rounded. Breaking changes, all described in docs/migration-guide-2.0.md: - The type can no longer be derived from, and the copy constructor and As<T>() are removed. - Members that were protected internal are now internal. - Equals, CompareTo, and the TryParse out parameters take PreciseNumber rather than PreciseNumber?, and CompareTo(object) returns 1 for null. - To<int>() truncates toward zero, so 12.9 yields 12 where it used to yield 0. Claude-Session: https://claude.ai/code/session_01K5Bk9UjGdGUtC5C6qK5ZxD
|
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
PreciseNumber is now a
readonly record struct, and generic math conversion works. Arithmetic results stop allocating a wrapper object, andT.CreateCheckedanddouble.CreateCheckedsucceed where they used to throwNotSupportedException. That second change is what lets PreciseNumber be the storage type of a Semantics quantity.Changes
default(PreciseNumber)already equalsZero, because a zero significand, zero exponent, and zero digit count is exactly whatZeroholds. A test pins it.TryConvertFrom*andTryConvertTo*in checked, saturating, and truncating modes cover every BCL numeric type andBigInteger, and returnfalsefor anything else. Conversion fromdoublekeeps the shortest round-trip text, soT.CreateChecked(0.3048)is exactly0.3048. Conversion todouble,float, andHalfis correctly rounded.OverflowException, and in saturating and truncating modes yields zero. Infinity throws in every mode. Both followBigInteger.README.md,CLAUDE.md, and a newdocs/migration-guide-2.0.md.Breaking changes
As<T>()are removed.protected internalare nowinternal.Equals,CompareTo, and theTryParseout parameters takePreciseNumberrather thanPreciseNumber?.CompareTo(object)returns 1 for null.To<int>()truncates toward zero through the new conversions, so12.9yields12where it used to yield0.Performance
Allocation is the reliable part of the local measurements, because they ran with about 1 GB of memory free.
FromInt32,FromDoubleAt 200 digits,
Add,Multiply, andDividealso got two to three times faster. At 8 digits the local timings got slower, and it isn't yet clear whether that's noise or the cost of copying a 24-byte struct. Clean runs of the Benchmarks workflow onmainand on this branch will be linked in a comment before merging.Testing
default == Zero.dotnet packpackage validation fails with the same 148 errors asmain, from staleCompatibilitySuppressions.xmlentries. This change doesn't add any.Follow-up
Semantics.Quantities.Precisealias package once this version publishes.🤖 Generated with Claude Code
https://claude.ai/code/session_01K5Bk9UjGdGUtC5C6qK5ZxD