public static MultiPrecision <N> Pow2(MultiPrecision <N> x) { if (x.IsNaN) { return(NaN); } MultiPrecision <N> x_int = Floor(x); if (x_int.Exponent >= UIntUtil.UInt32Bits) { if (x.Sign == Sign.Plus) { return(PositiveInfinity); } else { return(Zero); } } Int64 exponent = x_int.mantissa.Value.Last() >> (UIntUtil.UInt32Bits - (int)x_int.Exponent - 1); if (x_int.Sign == Sign.Minus) { exponent = -exponent; } MultiPrecision <N> x_frac = x - x_int; MultiPrecision <N> v = Ln2 * x_frac; if (v.IsZero || v.Exponent < int.MinValue) { return(new MultiPrecision <N>(Sign.Plus, exponent, Mantissa <N> .One, round: false)); } Accumulator <N> a = Accumulator <N> .One, m = new(v.mantissa, (int)v.Exponent), w = m; foreach (var t in Accumulator <N> .TaylorTable) { Accumulator <N> d = w * t; if (d.Digits < Length) { break; } a += d; w = Accumulator <N> .RightRoundShift(w *m, Mantissa <N> .Bits - 1); } (Mantissa <N> n, int sft) = a.Mantissa; MultiPrecision <N> y = new(Sign.Plus, exponent - sft + 1, n, round : false); return(y); }
private static MultiPrecision <N> SinCurveTaylorApprox(MultiPrecision <N> x) { MultiPrecision <N> x_abs = Abs(x); MultiPrecision <N> x_int = Round(x_abs), x_frac = x_abs - x_int, xpi = x_frac * PI / 2, squa_xpi = xpi * xpi; Int64 cycle = x_int.Exponent < UIntUtil.UInt32Bits / 2 ? ((Int64)x_int) % 4 : (Int64)(x_int % 4); if ((cycle == 0 || cycle == 2) && x_frac.IsZero) { return(Zero); } Accumulator <N> a = Accumulator <N> .One, m = new(squa_xpi.mantissa, squa_xpi.Exponent), w = m; Sign s = Sign.Minus; for (int i = (cycle == 0 || cycle == 2) ? 2 : 1; i + 1 < Accumulator <N> .TaylorTable.Count; i += 2) { Accumulator <N> t = Accumulator <N> .TaylorTable[i]; Accumulator <N> d = w * t; if (s == Sign.Plus) { a += d; s = Sign.Minus; } else { a -= d; s = Sign.Plus; } if (d.Digits < Length) { break; } w = Accumulator <N> .MulShift(w, m); } (Mantissa <N> n, int sft) = a.Mantissa; MultiPrecision <N> y; if (cycle == 0 || cycle == 2) { y = new MultiPrecision <N>((cycle == 0 ^ x.Sign == Sign.Plus) ? Sign.Minus : Sign.Plus, -sft + 1, n, round: false); y *= xpi; } else { y = new MultiPrecision <N>((cycle == 1 ^ x.Sign == Sign.Plus) ? Sign.Minus : Sign.Plus, -sft + 1, n, round: false); } return(y); }
public static bool TryParse(string s, out Accumulator <N> result) { try { result = Parse(s); return(true); } catch (Exception e) when(e is FormatException || e is OverflowException) { result = null; return(false); } }
private static ReadOnlyCollection <Accumulator <N> > GenerateTaylorTable() { List <Accumulator <N> > table = new(); Accumulator <N> v = One, d = 1; while (table.Count < 1 || !(table.Last().IsZero)) { table.Add(RightRoundShift(v, TaylorTableShift)); d += 1; v /= d; } table = table.Take(table.Count - 1).ToList(); return(table.AsReadOnly()); }
public int CompareTo([AllowNull] Accumulator <N> other) { if (other is null) { return(1); } if (this < other) { return(-1); } if (this == other) { return(0); } return(1); }
private static MultiPrecision <N> CreateInteger(Sign sign, Accumulator <N> acc) { (Mantissa <N> n, int sft) = acc.Mantissa; return(new MultiPrecision <N>(sign, (Int64)Accumulator <N> .Bits - sft - 1, n, round: false)); }
public static Accumulator <N> RoundDiv(Accumulator <N> v1, Accumulator <N> v2) { return(new Accumulator <N>(BigUInt <Double <N> > .RoundDiv(v1.value, v2.value))); }
public static Accumulator <N> MulShift(Accumulator <N> v1, Accumulator <N> v2) { Accumulator <N> v = new(BigUInt <Double <N> > .Mul(v1.value, v2.value)); return(RightRoundShift(v, Mantissa <N> .Bits - 1)); }
public static (Accumulator <N> div, Accumulator <N> rem) Div(Accumulator <N> v1, Accumulator <N> v2) { (BigUInt <Double <N> > div, BigUInt <Double <N> > rem) = BigUInt <Double <N> > .Div(v1.value, v2.value); return(new Accumulator <N>(div), new Accumulator <N>(rem)); }
public static Accumulator <N> Mul(Accumulator <N> v1, Accumulator <N> v2) { return(new Accumulator <N>(BigUInt <Double <N> > .Mul(v1.value, v2.value))); }
public static Accumulator <N> Sub(Accumulator <N> v1, UInt32 v2) { return(new Accumulator <N>(BigUInt <Double <N> > .Sub(v1.value, v2))); }
public static MultiPrecision <N> Log2(MultiPrecision <N> x) { if (!(x >= Zero)) { return(NaN); } if (x.IsZero) { return(NegativeInfinity); } if (x == PositiveInfinity) { return(PositiveInfinity); } if (x.mantissa == Mantissa <N> .One) { return(x.Exponent); } Accumulator <N> v = new(x.mantissa); int sft; for (sft = 0; sft < Accumulator <N> .Bits; sft++) { v *= v; if (v.Value[Accumulator <N> .Length - 1] > UIntUtil.UInt32Round) { v = Accumulator <N> .RightRoundBlockShift(v, Mantissa <N> .Length); break; } else { v = Accumulator <N> .RightRoundShift(v, Mantissa <N> .Bits - 1); } } if (sft == Accumulator <N> .Bits) { return(x.Exponent); } UInt32[] mantissa = new UInt32[Mantissa <N> .Length]; UInt32 m = 1; for (int i = mantissa.Length - 1; i >= 0; i--) { for (int j = (i < mantissa.Length - 1) ? 0 : 1; j < UIntUtil.UInt32Bits; j++) { v *= v; m <<= 1; if (v.Value[Accumulator <N> .Length - 1] > UIntUtil.UInt32Round) { v = Accumulator <N> .RightRoundBlockShift(v, Mantissa <N> .Length); m |= 1u; } else { v = Accumulator <N> .RightRoundShift(v, Mantissa <N> .Bits - 1); } } mantissa[i] = m; m = 0; } v *= v; bool round = v.Value[Accumulator <N> .Length - 1] > UIntUtil.UInt32Round; long intpart = x.Exponent; MultiPrecision <N> decpart = new(Sign.Plus, -(Int64)sft - 1, new Mantissa <N>(mantissa, enable_clone: false), round); MultiPrecision <N> y = intpart + decpart; return(y); }