logarithmic functions implementation
.NET Test / .NET tests (push) Successful in 2m14s

This commit is contained in:
2026-09-24 01:23:09 +04:00
parent 720fd1e21f
commit cb06df8865
11 changed files with 1944 additions and 22 deletions
+34 -6
View File
@@ -105,8 +105,10 @@ 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. Natural logarithm and power kernels
live in `DoubleDouble.Log.cs` and `DoubleDouble.Pow.cs`; reciprocal lives in
the interface's default minus-one methods. Logarithms live in `DoubleDouble.Log.cs`:
`Log` (natural and arbitrary base), `Log2`, `Log10`, `LogP1`, `Log2P1`, and `Log10P1`
complete `ILogarithmicFunctions<DoubleDouble>`, including cancellation-safe plus-one
overrides. Power kernels live in `DoubleDouble.Pow.cs`; reciprocal lives in
`DoubleDouble.NumberBase.cs`. Arithmetic implementations live in
`DoubleDouble.Arithmetic.cs`, with forwarding operators in `DoubleDouble.Operators.cs`.
@@ -117,7 +119,8 @@ 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`,
all six exponential functions, all logarithms (including `Log(newBase)` and the
three `P1` variants), `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
@@ -232,6 +235,22 @@ DoubleDouble root = magnitude.RootN(2);
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.
- `Log2(DoubleDouble)` and `Log10(DoubleDouble)`: base-two and base-ten logarithms,
using natural-log base conversion with the same domain and special-value rules.
`Log2` returns the exact integer exponent for every representable power of two.
- `Log(DoubleDouble, DoubleDouble)`: arbitrary-base logarithm retaining both
components of both operands. Negative arguments or bases, NaNs, and base one
return canonical NaN. Zero or positive-infinite bases are accepted only for
argument one, returning negative or positive zero respectively. Otherwise the
signs of zero and infinity follow `log(value)/log(newBase)`; bases between zero
and one reverse the sign. Finite results can overflow or underflow when the
base is extremely close to one or the argument is extremely close to one.
- `LogP1(DoubleDouble)`, `Log2P1(DoubleDouble)`, and `Log10P1(DoubleDouble)`:
logarithms of one plus the argument. A direct near-zero series avoids losing
input components by adding one first. Signed zeros are preserved, minus one
returns negative infinity, values below minus one and NaN return canonical NaN,
and positive infinity is preserved. Accuracy is measured relative to the final
logarithm, not to the argument shifted by one.
```csharp
using Just.PreciseMath;
@@ -251,6 +270,8 @@ 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 = DoubleDouble.Log(new DoubleDouble(10.0));
DoubleDouble binaryLogarithm = DoubleDouble.Log2(new DoubleDouble(8.0));
DoubleDouble smallLogarithm = DoubleDouble.LogP1(new DoubleDouble(1e-30));
DoubleDouble fractionalPower = DoubleDouble.Pow(new DoubleDouble(2.0), 0.5);
DoubleDouble preciseExponent = DoubleDouble.FromComponents(0.5, 1e-30);
DoubleDouble precisePower = DoubleDouble.Pow(new DoubleDouble(2.0), preciseExponent);
@@ -295,6 +316,13 @@ 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.
The other bases and plus-one variants use the same tested error bound, with
independent references for exact component sums and exact `1+x`. Tests cover
near-zero series transitions, bases on either side of one (including sparse
subnormal differences), domain/signed-zero behavior, and direct/generic dispatch.
Selected sparse plus-one cases separately pin retained low components. Precision
decreases near underflow; no universal correct-rounding or range-boundary guarantee
is implied by the sampled arbitrary-base checks.
Exponential-family tests use independent high-precision decimal references evaluated at
two precisions, with exact integer comparisons of the stored component sum. They
@@ -429,10 +457,10 @@ bool success = DoubleDouble.TryParse("1.25e-2".AsSpan(), CultureInfo.InvariantCu
## Deferred scope
Natural `DoubleDouble.Log`, the complete exponential family on `DoubleDouble`, and all
The complete logarithmic and exponential families 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-
Generic-math interfaces beyond `ISignedNumber`, `IFloatingPointConstants`,
`IRootFunctions`, `IExponentialFunctions`, `ILogarithmicFunctions`, and `IPowerFunctions`, additional text formats/shortest-
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