addoed exponential functions
.NET Test / .NET tests (push) Successful in 1m32s

This commit is contained in:
2026-09-16 23:20:53 +04:00
parent 7084fae174
commit b5a8bd2580
9 changed files with 1255 additions and 86 deletions
+33 -7
View File
@@ -93,7 +93,11 @@ constants. The natural logarithm function is provided separately by `DDMath.Log`
Root functions are implemented on `DoubleDouble` in `DoubleDouble.RootFunctions.cs`:
`Sqrt`, `Cbrt`, `Hypot`, and `RootN` complete `IRootFunctions<DoubleDouble>`.
The additional `InvSqrt` helper and three-argument `Hypot` overload live alongside
them. `DDMath` exposes thin forwarding wrappers; the other mathematical kernels
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 `DDMath` static class provides:
@@ -163,6 +167,20 @@ The `DDMath` static class provides:
components affect range boundaries; representable subnormals are retained.
Either zero maps to one, negative infinity to positive zero, positive infinity
to positive infinity, and NaN to canonical NaN.
- `Exp2(DoubleDouble)`: reduces the argument in base two before evaluating a
bounded natural exponential. Integer powers from -1074 through 1023 are exact.
An exponent-tracked correction preserves sparse lows that would otherwise round
prematurely before final scaling. The exact half-minimum-subnormal threshold
uses both input components. Special-value behavior is the same as `Exp`.
- `Exp10(DoubleDouble)`: subtracts three split `log10(2)` products before converting
the bounded remainder to a natural exponent, avoiding large-argument amplification
of a rounded `ln(10)` product. Special-value behavior is the same as `Exp`.
- `ExpM1(DoubleDouble)`, `Exp2M1(DoubleDouble)`, and `Exp10M1(DoubleDouble)`:
compute the corresponding exponential minus one, using a direct series near
zero to avoid cancellation. Signed zeros are preserved, negative infinity maps
to negative one, positive infinity to positive infinity, and NaN to canonical NaN.
Their tested relative error is measured against the minus-one result itself,
not against the exponential before subtraction.
- `Log(DoubleDouble)`: natural logarithm using binary range reduction and a
centered atanh series. The bounded mantissa avoids denominator overflow for
large inputs; a separate near-one path retains even minimum-subnormal low
@@ -181,7 +199,10 @@ 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 exponential = DDMath.Exp(new DoubleDouble(1.0));
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 preciseExponent = DoubleDouble.FromComponents(0.5, 1e-30);
@@ -225,13 +246,17 @@ additional tests cover extreme magnitudes, near-one cancellation, sparse lows of
either sign, and range-reduction transitions. This is sampled approximate accuracy,
not a universal error proof or a correct-rounding guarantee.
Exponential tests use independent high-precision decimal references evaluated at
Exponential-family tests use independent high-precision decimal references evaluated at
two precisions, with exact integer comparisons of the stored component sum. They
check `2^-100` relative error plus one minimum binary64 subnormal, with a separately
bounded reference-rounding allowance. Integer-power tests use exact rational
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
error bound is `|exact result| * (|exponent| + 1) * 2^-100 + 2^-1074`, not uniform
relative accuracy independent of the exponent. Both functions are approximate;
relative accuracy independent of the exponent. These functions are approximate;
precision decreases near underflow and approximation can affect results extremely
close to a rounding boundary. Final scaling uses the existing allocating exact
boundary machinery where necessary. No performance measurements are claimed.
@@ -342,9 +367,10 @@ bool success = DoubleDouble.TryParse("1.25e-2".AsSpan(), CultureInfo.InvariantCu
## Deferred scope
Natural `DDMath.Log`, `Exp`, and all three `Pow` overloads are implemented.
Natural `DDMath.Log`, the complete exponential family on `DoubleDouble`, and all
three `DDMath.Pow` overloads are implemented.
Logarithms in other bases, generic-math interfaces beyond `ISignedNumber`,
`IFloatingPointConstants`, and `IRootFunctions`, additional text formats/general
`IFloatingPointConstants`, `IRootFunctions`, and `IExponentialFunctions`, additional text formats/general
round-trip formatting, and non-arithmetic performance benchmarks remain deferred.
Replacing allocating arithmetic boundary fallbacks is also deferred; the current
`BigInteger` paths remain in place. That optimization does not require removing