@@ -75,11 +75,11 @@ 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. Precomputed logarithms do not imply a general `Log` function is implemented.
|
||||
constants. The natural logarithm function is provided separately by `DDMath.Log`.
|
||||
|
||||
## Mathematical functions
|
||||
|
||||
The initial `DDMath` static class provides:
|
||||
The `DDMath` static class provides:
|
||||
|
||||
- `Abs(DoubleDouble)`: preserves both components, maps either signed zero to
|
||||
positive zero and either infinity to positive infinity, and returns canonical NaN.
|
||||
@@ -88,12 +88,40 @@ The initial `DDMath` static class provides:
|
||||
to retain extended precision, including for subnormal inputs, without squaring
|
||||
an unscaled estimate near the exponent limits. Signed zero and positive infinity
|
||||
are preserved; negative nonzero inputs and NaN return canonical NaN.
|
||||
- `Pow(DoubleDouble, int)`: exponentiation by squaring with a separately tracked
|
||||
binary exponent. Supports the full `int` domain, including `int.MinValue`, and
|
||||
reciprocates a bounded significand before final scaling for negative exponents.
|
||||
Any value to power zero is one (including NaN and signed zero). Other NaNs
|
||||
propagate; zero/infinity signs follow integer-power parity and exponent sign.
|
||||
- `Pow(DoubleDouble, double)` and `Pow(DoubleDouble, DoubleDouble)`: arbitrary
|
||||
real powers, retaining the base's low component and, for the DD overload, the
|
||||
exponent's low component. For finite exponents, negative finite bases require integers;
|
||||
integrality and odd/even parity use the complete exponent, even above `2^53`.
|
||||
Integer-valued exponents within `int` range reuse the integer implementation.
|
||||
Other finite cases share `Log`'s range-scaled finite kernel, followed by `Exp`.
|
||||
Near-one bases retain tiny low components before multiplication by large powers.
|
||||
- `Exp(DoubleDouble)`: binary range reduction with three components of `ln(2)`,
|
||||
followed by a [12/12] Padé approximation and power-of-two scaling. Both input
|
||||
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.
|
||||
- `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
|
||||
components. Either zero maps to negative infinity, one to positive zero,
|
||||
positive infinity to itself, and negative nonzero inputs or NaN to canonical NaN.
|
||||
|
||||
```csharp
|
||||
using Just.PreciseMath;
|
||||
|
||||
DoubleDouble root = DDMath.Sqrt(new DoubleDouble(2.0));
|
||||
DoubleDouble magnitude = DDMath.Abs(-root);
|
||||
DoubleDouble smallPower = DDMath.Pow(new DoubleDouble(2.0), -1024);
|
||||
DoubleDouble exponential = DDMath.Exp(new DoubleDouble(1.0));
|
||||
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);
|
||||
DoubleDouble precisePower = DDMath.Pow(new DoubleDouble(2.0), preciseExponent);
|
||||
```
|
||||
|
||||
Square-root tests compare the exact component sum against a `2^-100` relative
|
||||
@@ -102,6 +130,44 @@ exponent, boundary neighbors, both signs of the low component, and exact binary
|
||||
squares. This is a tested approximate-accuracy contract, not exhaustive coverage
|
||||
of all component pairs or a guarantee of correctly rounded results.
|
||||
|
||||
Logarithm tests compare exact component sums with independently generated
|
||||
120-digit decimal references, requiring agreement at 450 and 650 digits. They
|
||||
check `2^-100` relative error plus one minimum binary64 subnormal, with an explicit
|
||||
reference-rounding allowance. Powers of two cover every finite binary64 exponent;
|
||||
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
|
||||
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
|
||||
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;
|
||||
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.
|
||||
|
||||
For real powers, `x^±0 = 1` and `1^y = 1`, including NaN in the other operand;
|
||||
other NaNs propagate. Infinite exponents compare the complete `|x|` with one,
|
||||
with `(-1)^±∞ = 1`. Zero and infinite bases yield a negative sign only for odd
|
||||
integer exponents; negative powers exchange zero and infinity. Finite negative
|
||||
bases with non-integer finite exponents return canonical NaN.
|
||||
|
||||
Real-power reference tests check `2^-90` relative error plus one minimum binary64
|
||||
subnormal for the logarithm/Exp path, with an explicit reference-rounding allowance.
|
||||
Integer dispatch retains the exponent-dependent bound above. These are tested
|
||||
approximate-accuracy contracts, not universal error proofs or correct-rounding
|
||||
guarantees. Reference inputs are exact component sums; logarithms/exponentials
|
||||
are independently evaluated at 450 and 650 decimal digits.
|
||||
|
||||
**Known real-power limitations:** extremely close to the range boundaries, the
|
||||
logarithm/Exp path can return infinity for a mathematically finite result, or a
|
||||
minimum subnormal where zero is expected. The latter can also break monotonicity
|
||||
across integer-exponent dispatch. These issues remain unresolved; passing the
|
||||
sampled error bounds does not guarantee correct range decisions for every input.
|
||||
|
||||
## Conversions and formatting
|
||||
|
||||
- Explicit conversions support `double`, `float`, `int`, `long`, and `decimal`
|
||||
@@ -189,8 +255,8 @@ bool success = DoubleDouble.TryParse("1.25e-2".AsSpan(), CultureInfo.InvariantCu
|
||||
|
||||
## Deferred scope
|
||||
|
||||
The `DDMath.Pow`, `DDMath.Exp`, and `DDMath.Log` functions remain unimplemented.
|
||||
Generic-math interfaces beyond `ISignedNumber`,
|
||||
Natural `DDMath.Log`, `Exp`, and all three `Pow` overloads are implemented.
|
||||
Logarithms in other bases, generic-math interfaces beyond `ISignedNumber`,
|
||||
additional text formats/general round-trip formatting, and non-arithmetic performance
|
||||
benchmarks remain deferred.
|
||||
Replacing allocating arithmetic boundary fallbacks is also deferred; the current
|
||||
|
||||
Reference in New Issue
Block a user