Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions Sources/AngouriMath/Core/Entity/Continuous/Number/Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ private static EDecimal Hypot(EDecimal a, EDecimal b, EContext context)
else
{
var ratio = small.Divide(large, context);
return ratio.MultiplyAndAdd(ratio, EDecimal.One, context).Sqrt(context).Multiply(large, context);
return ratio.MultiplyAndAdd(ratio, EDecimal.One, context).SqrtByIntegerRoot(context).Multiply(large, context);
}
}

Expand All @@ -332,8 +332,8 @@ public static Complex Sqrt(Complex num)
// From https://source.dot.net/#System.Runtime.Numerics/System/Numerics/Complex.cs,7dc9c2ee4f99814a
if (num is Real { EDecimal: var real })
if (real.IsNegative)
return Complex.Create(0, real.Negate().Sqrt(context));
else return Real.Create(real.Sqrt(context));
return Complex.Create(0, real.Negate().SqrtByIntegerRoot(context));
else return Real.Create(real.SqrtByIntegerRoot(context));
else
{

Expand Down Expand Up @@ -369,12 +369,12 @@ public static Complex Sqrt(Complex num)
EDecimal x, y;
if (!re.IsNegative)
{
x = Hypot(re, im, context).Add(re, context).Divide(2, context).Sqrt(context);
x = Hypot(re, im, context).Add(re, context).Divide(2, context).SqrtByIntegerRoot(context);
y = im.Divide(x.Multiply(2, context), context);
}
else
{
y = Hypot(re, im, context).Subtract(re, context).Divide(2, context).Sqrt(context);
y = Hypot(re, im, context).Subtract(re, context).Divide(2, context).SqrtByIntegerRoot(context);
if (im.IsNegative) y = -y;
x = im.Divide(y.Multiply(2, context), context);
}
Expand Down Expand Up @@ -451,7 +451,7 @@ static Complex BinaryIntPow(Complex num, EInteger val)
&& halfPower.Denominator.Equals(EInteger.FromInt32(2)) && halfPower.Numerator.Abs().CompareTo(EInteger.FromInt32(1 << 20)) <= 0)
{
var halfContext = MathS.Settings.DecimalPrecisionContext;
var root = rootBase.Sqrt(halfContext);
var root = rootBase.SqrtByIntegerRoot(halfContext);
var n = halfPower.Numerator.Abs().ToInt32Checked();
var raised = n == 1 ? root : root.Pow(n, halfContext);
return Real.Create(halfPower.Numerator.Sign < 0 ? EDecimal.One.Divide(raised, halfContext) : raised);
Expand Down Expand Up @@ -737,11 +737,11 @@ public static Complex Cotan(Complex num)
var (x, y) = (num.RealPart.EDecimal, num.ImaginaryPart.EDecimal);
var xp1 = x.Increment();
var xm1 = x.Decrement();
var rho = xp1.MultiplyAndAdd(xp1, y.Multiply(y, context), context).Sqrt(context);
var sigma = xm1.MultiplyAndAdd(xm1, y.Multiply(y, context), context).Sqrt(context);
var rho = xp1.MultiplyAndAdd(xp1, y.Multiply(y, context), context).SqrtByIntegerRoot(context);
var sigma = xm1.MultiplyAndAdd(xm1, y.Multiply(y, context), context).SqrtByIntegerRoot(context);
var alpha = rho.Add(sigma, context).Divide(2, context);
return (rho.Subtract(sigma, context).Divide(2, context),
alpha.MultiplyAndSubtract(alpha, EDecimal.One, context).Sqrt(context).Add(alpha, context).NaturalLogarithm(context).Multiply((y.IsNegative || y.IsZero) ? -1 : 1, context));
alpha.MultiplyAndSubtract(alpha, EDecimal.One, context).SqrtByIntegerRoot(context).Add(alpha, context).NaturalLogarithm(context).Multiply((y.IsNegative || y.IsZero) ? -1 : 1, context));
}

/// <summary>Calculates the exact value of arcsine of num</summary>
Expand Down
34 changes: 34 additions & 0 deletions Sources/AngouriMath/Docs/WhatsNew/version_performance_control.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,40 @@ cent — its measured run-to-run spread on mean time is up to 51.8%. A move of 8
outside that band by a wide margin and agrees in sign and rough size with the allocation column
beside it. The small rows from the same run are still not worth reading, and are not quoted.

## The 2074th: the logarithm and the arctangent reduced by a table, the cosine from the sine, the square root an integer one

After the 2072nd the remaining factor to mpmath was the term count: eighty artanh terms for a
logarithm at a hundred digits, forty-seven for an arctangent after three square-root
halvings, and two series -- the sine's and the cosine's -- for either. The logarithm's
mantissa, already within `[1/sqrt 2, sqrt 2]`, is divided by the nearest `1 + j/64`, whose
logarithm the constant cache holds (built outward from `ln 1 = 0` when first asked, one short
series a step), so the series runs on a quotient within 1/128 of one: twenty-five terms. The
arctangent's argument, within `[0, 1]`, is brought within 1/128 of zero by the nearest `j/64`
the same way, `arctan x = arctan c + arctan((x - c)/(1 + xc))`: thirty terms and no square
root. The cosine at the sine's reduced argument, which is within a twentieth of zero, is
`sqrt(1 - sin^2)` and cancels nothing; the other way round is what lost half the digits in the
2050th. And the square root of a decimal is the integer square root of its mantissa padded to
twice the digits, with a sticky digit so the rounding to the context is the correct one in
every mode, as PeterO's is -- Newton from the root of the top half of the bits, three
divisions at the full width where a power of two above the root took one per bit of the
exponent. The hundred-digit values are the ones pinned before, to the last digit.

| benchmark | 2073rd | 2074th | allocation | time |
|---|--:|--:|--:|--:|
| `EvalTranscendentalFresh` | 59,136 | **34,608** | **−41.5%** | 33 → **16 µs** |
| `EvalTrig` | 82,104 | **69,792** | **−15.0%** | 37 → **32 µs** |
| `EvalTrigPrecise` | 525,289 | **336,360** | **−36.0%** | 617 → **406 µs** |
| `SolveEasy` | 981,996 | **783,622** | **−20.2%** | 491 → **390 µs** |
| `SolveHard` | 11,708,080 | **10,053,640** | **−14.1%** | 68 → 70 ms |
| every other entry | | | within 1.3% | |

Bytes allocated per call, same machine, both columns by the gate in one session; the gate's
baseline was taken from this run. Alone, one probe on both builds: at a hundred digits `ln`
18.0 → 8.4 µs, `arctan` 24.6 → 7.7, `sin` 15.2 → 13.1; at five hundred `ln` 777 → 241 µs,
`sin` 228 → 141, and the square root 41 → 22 (PeterO's against the integer one); at two
thousand digits the square root 441 → 174 µs. mpmath at a hundred digits is `ln` 4.5, `arctan`
3.9, `sin` 5.6.

## The 2073rd: the rational pre-check confirms a maybe, and reads two thousand digits

`EvalTrig` is `sin 1 + cos 1 + tan 1`, and after the 2072nd fifty of its eighty-three
Expand Down
Loading
Loading