public static MultiPrecision <N> ReadMultiPrecision <N>(this BinaryReader reader) where N : struct, IConstant { Sign sign = (Sign)reader.ReadByte(); if (!Enum.IsDefined(typeof(Sign), sign)) { throw new FormatException(nameof(sign)); } UInt32 exponent = (UInt32)reader.ReadUInt32(); UInt32[] mantissa = new UInt32[MultiPrecision <N> .Length]; for (int i = 0; i < MultiPrecision <N> .Length; i++) { mantissa[i] = reader.ReadUInt32(); } if (UIntUtil.IsZero(mantissa)) { if (exponent != MultiPrecision <N> .ExponentMin && exponent != MultiPrecision <N> .ExponentMax) { throw new FormatException(nameof(exponent)); } } else { if (UIntUtil.LeadingZeroCount(mantissa) != 0u) { throw new FormatException(nameof(mantissa)); } } return(new MultiPrecision <N>(sign, exponent, new Mantissa <N>(mantissa, enable_clone: false))); }
public static MultiPrecision <N> Truncate(MultiPrecision <N> x) { if (!x.IsFinite) { return(NaN); } if (x.Exponent >= Mantissa <N> .Bits) { throw new ArgumentException( "The Truncate function was given an input value with no decimal precision.", nameof(x) ); } if (x.Exponent < 0) { return(Zero); } UInt32[] vs = x.mantissa.Value.ToArray(); UIntUtil.FlushLSB(vs, (int)x.Exponent); MultiPrecision <N> y = new(x.Sign, x.exponent, new Mantissa <N>(vs, enable_clone: false)); return(y); }
public static MultiPrecision <N> Add(MultiPrecision <N> a, long b) { if (b == 0) { return(a); } if (a.IsNaN) { return(NaN); } if (a.IsZero) { return(b); } if (!a.IsFinite) { return(a); } UInt64 b_abs = UIntUtil.Abs(b); if (a.Sign == UIntUtil.Sign(b)) { (Mantissa <N> n, Int64 exponent, bool round) = Add(a.mantissa, b_abs, -a.Exponent); return(new MultiPrecision <N>(a.Sign, exponent + a.Exponent, n, round)); } else { (Mantissa <N> n, Int64 exponent, bool round, Sign sign) = Diff(a.mantissa, b_abs, -a.Exponent); return(new MultiPrecision <N>(sign == Sign.Plus ? a.Sign : UIntUtil.Sign(b), exponent + a.Exponent, n, round)); } }
public static MultiPrecision <N> Random(Random random) { Accumulator <N> acc = new(new Mantissa <N>(UIntUtil.Random(random, Length, Bits), enable_clone: false)); (Mantissa <N> n, int sft) = acc.Mantissa; return(new MultiPrecision <N>(Sign.Plus, Mantissa <N> .Bits - sft - 1, n, round: false)); }
public static MultiPrecision <N> Div(MultiPrecision <N> a, long b) { if (a.IsNaN) { return(NaN); } if (a.IsZero) { if (b == 0) { return(NaN); } return((a.Sign == UIntUtil.Sign(b)) ? Zero : MinusZero); } if (!a.IsFinite) { return((a.Sign == UIntUtil.Sign(b)) ? PositiveInfinity : NegativeInfinity); } if (b == 0) { return((a.Sign == Sign.Plus) ? PositiveInfinity : NegativeInfinity); } if (b == 1) { return(a); } if (b == -1) { return(Neg(a)); } UInt64 b_abs = UIntUtil.Abs(b); if (UIntUtil.IsPower2(b_abs)) { MultiPrecision <N> a_power2 = Ldexp(a, -UIntUtil.Power2(b_abs)); return(b >= 0 ? a_power2 : Neg(a_power2)); } int expands = BigUInt <Plus4 <N> > .Length - BigUInt <N> .Length; BigUInt <Plus4 <N> > acc = new(a.mantissa.Value.ToArray(), expands); acc /= b_abs; int lzc = acc.LeadingZeroCount; acc <<= lzc; Int64 exponent = a.Exponent - lzc; Sign sign = (a.Sign == UIntUtil.Sign(b)) ? Sign.Plus : Sign.Minus; bool round = acc[expands - 1] > UIntUtil.UInt32Round; Mantissa <N> mantissa = new(acc.Value.Skip(expands).ToArray(), enable_clone : false); return(new MultiPrecision <N>(sign, exponent, mantissa, round)); }
public static BigUInt <N> RightRoundShift(BigUInt <N> n, int sft) { BigUInt <N> ret = n.Copy(); ret.RightShift(sft); if (sft >= 1 && sft <= Bits && UIntUtil.GetLSB(n.value, sft - 1) != 0) { ret.CarryAdd(0, 1); } return(ret); }
public override string ToString() { int bin_digits = (int)Digits, dec_digits = 0; // dec_digits <= bin_digits * digits(2^32 - 1) / digits(10^9 - 1) + 2 UInt32[] dec = new UInt32[checked (bin_digits * 10 / 9 + 2)]; for (int j = bin_digits - 1; j >= 0; j--) { UInt32 carry = value[j]; for (int i = 0; i < dec_digits; i++) { UInt64 res = UIntUtil.Pack(dec[i], carry); (carry, dec[i]) = UIntUtil.DecimalUnpack(res);
public static int MatchBits(BigUInt <N> a, BigUInt <N> b) { return(UIntUtil.MatchBits(Length, a.value, b.value)); }
public static bool operator ==(BigUInt <N> a, BigUInt <N> b) { return(UIntUtil.Equal(Length, a.value, b.value)); }
public static bool operator >=(BigUInt <N> a, BigUInt <N> b) { return(UIntUtil.GreaterThanOrEqual(Length, a.value, b.value)); }
public BigUInt(UInt64 v) : this() { (this.value[1], this.value[0]) = UIntUtil.Unpack(v); }
/// <summary>Shift uint32 array v >>= sft</summary> private unsafe void RightShift(int sft) { UIntUtil.RightShift(value, sft); }
/// <summary>Shift uint32 array v <<= sft</summary> private unsafe void LeftShift(int sft) { UIntUtil.LeftShift(value, sft); }
/// <summary>Shift uint32 array v >>= sft * UInt32Bits</summary> private void RightBlockShift(int sft) { UIntUtil.RightBlockShift(value, sft); }