This commit is contained in:
@@ -22,8 +22,11 @@ already-normalized results. Mathematical constants use precomputed high/low pair
|
||||
checked against independently computed high-precision values; accessing them does
|
||||
not perform double-double arithmetic or allocate on the heap.
|
||||
|
||||
- Arithmetic: unary `+`/`-`, binary `+`, `-`, `*`, `/`, and both operand orders with
|
||||
a `double`. Addition retains residuals under cancellation; multiplication uses
|
||||
- Arithmetic: static `Add`, `Subtract`, `Multiply`, and `Divide` methods accept
|
||||
`DoubleDouble` pairs and both operand orders with a `double`. `Plus` and `Negate`
|
||||
provide unary operations. The arithmetic operators (`+`, `-`, `*`, `/`, unary
|
||||
`+`/`-`, and `++`/`--`) are thin wrappers around these methods.
|
||||
Addition retains residuals under cancellation; multiplication uses
|
||||
fused multiply-add; division uses residual corrections. Mixed `double` operators
|
||||
use specialized scalar paths rather than promoting the scalar to `DoubleDouble`.
|
||||
Division retains the complete first remainder and applies two quotient corrections,
|
||||
@@ -92,7 +95,7 @@ DoubleDouble quarterTurn = DoubleDouble.PiOver2;
|
||||
The factors avoid deriving constants at runtime; the multiplication itself remains
|
||||
approximate DD arithmetic, so conversions are not guaranteed exact round trips.
|
||||
The list is mathematical and dimensionless, not a table of unit-dependent physical
|
||||
constants. The natural logarithm function is provided separately by `DDMath.Log`.
|
||||
constants. The natural logarithm function is provided separately by `DoubleDouble.Log`.
|
||||
|
||||
## Mathematical functions
|
||||
|
||||
@@ -102,16 +105,40 @@ The additional `InvSqrt` helper and three-argument `Hypot` overload live alongsi
|
||||
them. Exponential functions live in `DoubleDouble.ExponentialFunctions.cs`:
|
||||
`Exp`, `Exp2`, `Exp10`, `ExpM1`, `Exp2M1`, and `Exp10M1` complete
|
||||
`IExponentialFunctions<DoubleDouble>`, including cancellation-safe overrides of
|
||||
the interface's default minus-one methods. `DDMath` exposes thin forwarding
|
||||
wrappers for roots and exponentials; logarithm, power, and reciprocal kernels
|
||||
remain in `DDMath`.
|
||||
the interface's default minus-one methods. Natural logarithm and power kernels
|
||||
live in `DoubleDouble.Log.cs` and `DoubleDouble.Pow.cs`; reciprocal lives in
|
||||
`DoubleDouble.NumberBase.cs`. Arithmetic implementations live in
|
||||
`DoubleDouble.Arithmetic.cs`, with forwarding operators in `DoubleDouble.Operators.cs`.
|
||||
|
||||
The `DDMath` static class provides:
|
||||
All mathematical functions are static members of `DoubleDouble`. The former
|
||||
`DDMath` facade has been removed: migrate `DDMath.Function(...)` calls to
|
||||
`DoubleDouble.Function(...)`. This is a breaking API change; no compatibility
|
||||
facade is provided.
|
||||
|
||||
`DoubleDoubleExtensions`, in the same `Just.PreciseMath` namespace, also provides
|
||||
instance-style calls for `Abs`, `Square`, `Reciprocal`, `Sqrt`, `InvSqrt`, `Cbrt`,
|
||||
all six exponential functions, `Log`, `RootN(int)`, and `Pow` with `int`, `double`,
|
||||
or `DoubleDouble` exponents. These extensions return a result without modifying
|
||||
the receiver and forward directly to the corresponding static method, preserving
|
||||
its numerical contract and component bits. Arithmetic remains available through
|
||||
operators and named static methods; `Hypot` remains a static multi-operand function.
|
||||
|
||||
```csharp
|
||||
using Just.PreciseMath;
|
||||
|
||||
DoubleDouble value = new(-4.0);
|
||||
DoubleDouble magnitude = value.Abs();
|
||||
DoubleDouble inverse = value.Abs().Square().Sqrt().Reciprocal();
|
||||
DoubleDouble power = magnitude.Pow(3);
|
||||
DoubleDouble root = magnitude.RootN(2);
|
||||
// value is still -4; inverse is 0.25.
|
||||
```
|
||||
|
||||
`DoubleDouble` provides:
|
||||
|
||||
- `Abs(DoubleDouble)`: preserves both components, maps either signed zero to
|
||||
positive zero and either infinity to positive infinity, and returns canonical NaN.
|
||||
It shares the existing `DoubleDouble.Abs` implementation.
|
||||
- `Square(DoubleDouble)`: forwards to the specialized `DoubleDouble.Square` kernel.
|
||||
- `Square(DoubleDouble)`: uses a specialized double-double squaring kernel.
|
||||
It combines the equal cross terms with FMA, normalizes, then incorporates the
|
||||
low-component square without losing selected exactly representable tails.
|
||||
Either signed zero maps to positive zero, either infinity to positive infinity,
|
||||
@@ -216,17 +243,17 @@ DoubleDouble cubeRoot = DoubleDouble.Cbrt(new DoubleDouble(-8.0));
|
||||
DoubleDouble distance = DoubleDouble.Hypot(new DoubleDouble(3.0), new DoubleDouble(4.0));
|
||||
DoubleDouble norm3D = DoubleDouble.Hypot(new DoubleDouble(2.0), new DoubleDouble(3.0), new DoubleDouble(6.0));
|
||||
DoubleDouble fifthRoot = DoubleDouble.RootN(new DoubleDouble(2.0), 5);
|
||||
DoubleDouble reciprocal = DDMath.Reciprocal(new DoubleDouble(3.0));
|
||||
DoubleDouble magnitude = DDMath.Abs(-root);
|
||||
DoubleDouble smallPower = DDMath.Pow(new DoubleDouble(2.0), -1024);
|
||||
DoubleDouble reciprocal = DoubleDouble.Reciprocal(new DoubleDouble(3.0));
|
||||
DoubleDouble magnitude = DoubleDouble.Abs(-root);
|
||||
DoubleDouble smallPower = DoubleDouble.Pow(new DoubleDouble(2.0), -1024);
|
||||
DoubleDouble exponential = DoubleDouble.Exp(new DoubleDouble(1.0));
|
||||
DoubleDouble binaryPower = DoubleDouble.Exp2(new DoubleDouble(-1000.0));
|
||||
DoubleDouble decimalPower = DoubleDouble.Exp10(new DoubleDouble(0.5));
|
||||
DoubleDouble tinyChange = DoubleDouble.ExpM1(new DoubleDouble(1e-30));
|
||||
DoubleDouble logarithm = DDMath.Log(new DoubleDouble(10.0));
|
||||
DoubleDouble fractionalPower = DDMath.Pow(new DoubleDouble(2.0), 0.5);
|
||||
DoubleDouble logarithm = DoubleDouble.Log(new DoubleDouble(10.0));
|
||||
DoubleDouble fractionalPower = DoubleDouble.Pow(new DoubleDouble(2.0), 0.5);
|
||||
DoubleDouble preciseExponent = DoubleDouble.FromComponents(0.5, 1e-30);
|
||||
DoubleDouble precisePower = DDMath.Pow(new DoubleDouble(2.0), preciseExponent);
|
||||
DoubleDouble precisePower = DoubleDouble.Pow(new DoubleDouble(2.0), preciseExponent);
|
||||
```
|
||||
|
||||
Reciprocal tests check bitwise equivalence with `1.0 / value` and independently
|
||||
@@ -254,7 +281,7 @@ at 450 and 650 digits, including `int.MinValue` and `int.MaxValue`.
|
||||
`RootN(x, -1)` retains the reciprocal contract, including its subnormal error floor.
|
||||
Hypotenuse tests use exact squared inequalities with `2^-100` relative error plus
|
||||
one minimum binary64 subnormal. Tests also check exact binary cases, sparse lows,
|
||||
special-value signs, facade component-bit agreement, and constrained generic dispatch.
|
||||
special-value signs and constrained generic dispatch.
|
||||
The 2D and 3D hypotenuse overflow tests bracket the exact threshold, including scaled
|
||||
55/48/73 and 1/2/2/3 Pythagorean cases at the midpoint. Three-coordinate tests include
|
||||
all signs and permutations of boundary cases and sparse corrections, including
|
||||
@@ -275,9 +302,9 @@ check `2^-100` relative error plus one minimum binary64 subnormal, with a separa
|
||||
bounded reference-rounding allowance. The base-two/base-ten and minus-one fixtures
|
||||
are checked at 450/650 digits, including adjacent lows at true range boundaries,
|
||||
series transitions, and tiny inputs. Additional component checks pin sparse
|
||||
base-two corrections; constrained generic calls and facade calls match direct
|
||||
calls bit-for-bit. Integer-power tests use exact rational
|
||||
references and high-precision fixtures for large exponents; their tested absolute
|
||||
base-two corrections; constrained generic calls match direct calls bit-for-bit.
|
||||
Integer-power tests use exact rational references and high-precision fixtures for
|
||||
large exponents; their tested absolute
|
||||
error bound is `|exact result| * (|exponent| + 1) * 2^-100 + 2^-1074`, not uniform
|
||||
relative accuracy independent of the exponent. These functions are approximate;
|
||||
precision decreases near underflow and approximation can affect results extremely
|
||||
@@ -402,8 +429,8 @@ bool success = DoubleDouble.TryParse("1.25e-2".AsSpan(), CultureInfo.InvariantCu
|
||||
|
||||
## Deferred scope
|
||||
|
||||
Natural `DDMath.Log`, the complete exponential family on `DoubleDouble`, and all
|
||||
three `DDMath.Pow` overloads are implemented.
|
||||
Natural `DoubleDouble.Log`, the complete exponential family on `DoubleDouble`, and all
|
||||
three `DoubleDouble.Pow` overloads are implemented.
|
||||
Logarithms in other bases, generic-math interfaces beyond `ISignedNumber`,
|
||||
`IFloatingPointConstants`, `IRootFunctions`, and `IExponentialFunctions`, additional text formats/shortest-
|
||||
round-trip formatting, and non-arithmetic performance benchmarks remain deferred.
|
||||
|
||||
Reference in New Issue
Block a user