Exemplo n.º 1
0
 /// <summary>
 /// Assigns n2 to 'this'
 /// </summary>
 /// <param name="n2"></param>
 public void Assign(BigInt n2)
 {
     if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);
     sign = n2.sign;
     AssignInt(n2);
 }
Exemplo n.º 2
0
        /// <summary>
        /// Constructs a BigFloat from a BigInt, using the specified precision
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(BigInt value, PrecisionSpec mantissaPrec)
        {
            if (value.IsZero())
            {
                Init(mantissaPrec);
                SetZero();
                return;
            }

            mantissa = new BigInt(value, mantissaPrec);
            exponent = BigInt.GetMSB(value);
            mantissa.Normalise();
        }
Exemplo n.º 3
0
        private void Init(PrecisionSpec mantissaPrec)
        {
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            //For efficiency, we just use a 32-bit exponent
            exponent = 0;
            mantissa = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
        }
Exemplo n.º 4
0
        private void Exp(int numBits)
        {
            if (IsSpecialValue)
            {
                if (SpecialValue == SpecialValueType.ZERO)
                {
                    //e^0 = 1
                    exponent = 0;
                    mantissa.SetHighDigit(0x80000000);
                }
                else if (SpecialValue == SpecialValueType.INF_MINUS)
                {
                    //e^-inf = 0
                    SetZero();
                }

                return;
            }

            PrecisionSpec prec = new PrecisionSpec(numBits, PrecisionSpec.BaseType.BIN);
            numBits = prec.NumBits;

            if (scratch.Precision.NumBits != prec.NumBits)
            {
                scratch = new BigInt(prec);
            }

            if (inverseFactorialCache == null || invFactorialCutoff < numBits)
            {
                CalculateFactorials(numBits);
            }

            //let x = 1 * 'this'.mantissa (i.e. 1 <= x < 2)
            //exp(2^n * x) = e^(2^n * x) = (e^x)^2n = exp(x)^2n

            int oldExponent = 0;

            if (exponent > -4)
            {
                oldExponent = exponent + 4;
                exponent = -4;
            }

            BigFloat thisSave = new BigFloat(this, prec);
            BigFloat temp = new BigFloat(1, prec);
            BigFloat temp2 = new BigFloat(this, prec);
            BigFloat res = new BigFloat(1, prec);
            int length = inverseFactorialCache.Length;

            int iterations;
            for (int i = 1; i < length; i++)
            {
                //temp = x^i
                temp.Mul(thisSave);
                temp2.Assign(inverseFactorialCache[i]);
                temp2.Mul(temp);

                if (temp2.exponent < -(numBits + 4)) { iterations = i; break; }

                res.Add(temp2);
            }

            //res = exp(x)
            //Now... x^(2^n) = (x^2)^(2^(n - 1))
            for (int i = 0; i < oldExponent; i++)
            {
                res.mantissa.SquareHiFast(scratch);
                int shift = res.mantissa.Normalise();
                res.exponent = res.exponent << 1;
                res.exponent += 1 - shift;
            }

            //Deal with +/- inf
            if (res.exponent == Int32.MaxValue)
            {
                res.mantissa.Zero();
            }

            Assign(res);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Constructs a BigFloat from a 64-bit integer
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(Int64 value, PrecisionSpec mantissaPrec)
        {
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            //For efficiency, we just use a 32-bit exponent
            exponent = 0;
            UInt64 uValue;

            if (value < 0)
            {
                if (value == Int64.MinValue)
                {
                    uValue = 0x80000000;
                }
                else
                {
                    uValue = (UInt64)(-value);
                }
            }
            else
            {
                uValue = (UInt64)value;
            }

            mantissa = new BigInt(value, new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));

            int bit = BigInt.GetMSB(uValue);
            if (bit == -1) return;

            int shift = mantissa.Precision.NumBits - (bit + 1);
            if (shift > 0)
            {
                mantissa.LSH(shift);
            }
            else
            {
                mantissa.SetHighDigit((uint)(uValue >> (-shift)));
            }
            exponent = bit;
        }
Exemplo n.º 6
0
        /// <summary>
        /// Returns a base-10 string representing the number.
        /// 
        /// Note: This is inefficient and possibly inaccurate. Please use with enough
        /// rounding digits (set using the RoundingDigits property) to ensure accuracy
        /// </summary>
        public override string ToString()
        {
            if (IsSpecialValue)
            {
                SpecialValueType s = SpecialValue;
                if (s == SpecialValueType.ZERO)
                {
                    return String.Format("0{0}0", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
                }
                else if (s == SpecialValueType.INF_PLUS)
                {
                    return System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PositiveInfinitySymbol;
                }
                else if (s == SpecialValueType.INF_MINUS)
                {
                    return System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NegativeInfinitySymbol;
                }
                else if (s == SpecialValueType.NAN)
                {
                    return System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NaNSymbol;
                }
                else
                {
                    return "Unrecognised special type";
                }
            }

            if (scratch.Precision.NumBits != mantissa.Precision.NumBits)
            {
                scratch = new BigInt(mantissa.Precision);
            }

            //The mantissa expresses 1.xxxxxxxxxxx
            //The highest possible value for the mantissa without the implicit 1. is 0.9999999...
            scratch.Assign(mantissa);
            //scratch.Round(3);
            scratch.Sign = false;
            BigInt denom = new BigInt("0", mantissa.Precision);
            denom.SetBit(mantissa.Precision.NumBits - 1);

            bool useExponentialNotation = false;
            int halfBits = mantissa.Precision.NumBits / 2;
            if (halfBits > 60) halfBits = 60;
            int precDec = 10;

            if (exponent > 0)
            {
                if (exponent < halfBits)
                {
                    denom.RSH(exponent);
                }
                else
                {
                    useExponentialNotation = true;
                }
            }
            else if (exponent < 0)
            {
                int shift = -(exponent);
                if (shift < precDec)
                {
                    scratch.RSH(shift);
                }
                else
                {
                    useExponentialNotation = true;
                }
            }

            string output;

            if (useExponentialNotation)
            {
                int absExponent = exponent;
                if (absExponent < 0) absExponent = -absExponent;
                int powerOf10 = (int)((double)absExponent * Math.Log10(2.0));

                //Use 1 extra digit of precision (this is actually 32 bits more, nb)
                BigFloat thisFloat = new BigFloat(this, new PrecisionSpec(mantissa.Precision.NumBits + 1, PrecisionSpec.BaseType.BIN));
                thisFloat.mantissa.Sign = false;

                //Multiplicative correction factor to bring number into range.
                BigFloat one = new BigFloat(1, new PrecisionSpec(mantissa.Precision.NumBits + 1, PrecisionSpec.BaseType.BIN));
                BigFloat ten = new BigFloat(10, new PrecisionSpec(mantissa.Precision.NumBits + 1, PrecisionSpec.BaseType.BIN));
                BigFloat tenRCP = ten.Reciprocal();

                //Accumulator for the power of 10 calculation.
                BigFloat acc = new BigFloat(1, new PrecisionSpec(mantissa.Precision.NumBits + 1, PrecisionSpec.BaseType.BIN));

                BigFloat tenToUse;

                if (exponent > 0)
                {
                    tenToUse = new BigFloat(tenRCP, new PrecisionSpec(mantissa.Precision.NumBits + 1, PrecisionSpec.BaseType.BIN));
                }
                else
                {
                    tenToUse = new BigFloat(ten, new PrecisionSpec(mantissa.Precision.NumBits + 1, PrecisionSpec.BaseType.BIN));
                }

                BigFloat tenToPower = new BigFloat(1, new PrecisionSpec(mantissa.Precision.NumBits + 1, PrecisionSpec.BaseType.BIN));

                int powerTemp = powerOf10;

                //Fast power function
                while (powerTemp != 0)
                {
                    tenToPower.Mul(tenToUse);
                    tenToUse.Assign(tenToPower);

                    if ((powerTemp & 1) != 0)
                    {
                        acc.Mul(tenToPower);
                    }

                    powerTemp >>= 1;
                }

                thisFloat.Mul(acc);

                //If we are out of range, correct.           
                if (thisFloat.GreaterThan(ten))
                {
                    thisFloat.Mul(tenRCP);
                    if (exponent > 0)
                    {
                        powerOf10++;
                    }
                    else
                    {
                        powerOf10--;
                    }
                }
                else if (thisFloat.LessThan(one))
                {
                    thisFloat.Mul(ten);
                    if (exponent > 0)
                    {
                        powerOf10--;
                    }
                    else
                    {
                        powerOf10++;
                    }
                }

                //Restore the precision and the sign.
                BigFloat printable = new BigFloat(thisFloat, mantissa.Precision);
                printable.mantissa.Sign = mantissa.Sign;
                output = printable.ToString();

                if (exponent < 0) powerOf10 = -powerOf10;

                output = String.Format("{0}E{1}", output, powerOf10);
            }
            else
            {
                BigInt bigDigit = BigInt.Div(scratch, denom);
                bigDigit.Sign = false;
                scratch.Sub(BigInt.Mul(denom, bigDigit));

                if (mantissa.Sign)
                {
                    output = String.Format("-{0}.", bigDigit);
                }
                else
                {
                    output = String.Format("{0}.", bigDigit);
                }

                denom = BigInt.Div(denom, 10u);

                while (!denom.IsZero())
                {
                    uint digit = (uint)BigInt.Div(scratch, denom);
                    if (digit == 10) digit--;
                    scratch.Sub(BigInt.Mul(denom, digit));
                    output = String.Format("{0}{1}", output, digit);
                    denom = BigInt.Div(denom, 10u);
                }

                output = RoundString(output, RoundingDigits);
            }

            return output;
        }
Exemplo n.º 7
0
        /// <summary>
        /// Constructs a big float from a UInt32 to the required precision
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(UInt32 value, PrecisionSpec mantissaPrec)
        {
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            //For efficiency, we just use a 32-bit exponent
            exponent = 0;

            mantissa = new BigInt(value, new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(mantissa.Precision);

            int bit = BigInt.GetMSB(value);
            if (bit == -1) return;

            int shift = mantissa.Precision.NumBits - (bit + 1);
            mantissa.LSH(shift);
            exponent = bit;
        }
Exemplo n.º 8
0
        /// <summary>
        /// Sign-insensitive greater than comparison. 
        /// unsafe if n1 and n2 disagree in precision
        /// </summary>
        /// <param name="n1"></param>
        /// <param name="n2"></param>
        /// <returns></returns>
        private static bool GtInt(BigInt n1, BigInt n2)
        {
            //MakeSafe(ref n1, ref n2);

            for (int i = n1.digitArray.Length - 1; i >= 0; i--)
            {
                if (n1.digitArray[i] > n2.digitArray[i]) return true;
                if (n1.digitArray[i] < n2.digitArray[i]) return false;
            }

            //equal
            return false;
        }
Exemplo n.º 9
0
 /// <summary>
 /// Makes sure the numbers have matching precisions
 /// </summary>
 /// <param name="n1"></param>
 /// <param name="n2"></param>
 private static void MakeSafe(ref BigInt n1, ref BigInt n2)
 {
     if (n1.digitArray.Length == n2.digitArray.Length)
     {
         return;
     }
     else if (n1.digitArray.Length > n2.digitArray.Length)
     {
         n2 = new BigInt(n2, n1.pres);
     }
     else
     {
         n1 = new BigInt(n1, n2.pres);
     }
 }
Exemplo n.º 10
0
        /// <summary>
        /// Constructs a bigint from the input, matching the new precision provided
        /// </summary>
        public BigInt(BigInt input, PrecisionSpec precision)
        {
            //Casts the input to the new precision.
            Init(precision);
            int Min = (input.digitArray.Length < digitArray.Length) ? input.digitArray.Length : digitArray.Length;

            for (int i = 0; i < Min; i++)
            {
                digitArray[i] = input.digitArray[i];
            }

            sign = input.sign;
        }
Exemplo n.º 11
0
        //********************* ToString members **********************

        /// <summary>
        /// Converts this to a string, in the specified base
        /// </summary>
        /// <param name="numberBase">the base to use (min 2, max 16)</param>
        /// <returns>a string representation of the number</returns>
        public string ToString(int numberBase)
        {
            char[] digitChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

            string output = "";

            BigInt clone = new BigInt(this);
            clone.sign = false;

            int numDigits = 0;
            while (!clone.IsZero())
            {
                if (numberBase == 10 && (numDigits % 3) == 0 && numDigits != 0)
                {
                    output = String.Format(",{0}", output);
                }
                else if (numberBase != 10 && (numDigits % 8) == 0 && numDigits != 0)
                {
                    output = String.Format(" {0}", output);
                }

                BigInt div, mod;
                DivMod(clone, (uint)numberBase, out div, out mod);
                int iMod = (int)mod;
                output = String.Format("{0}{1}", digitChars[(int)mod], output);

                numDigits++;

                clone = div;
            }

            if (output.Length == 0) output = String.Format("0");

            if (sign) output = String.Format("-{0}", output);

            return output;
        }
Exemplo n.º 12
0
        private static BigInt DigitTruncate(BigInt n1, int digits)
        {
            BigInt res = new BigInt(n1);

            for (int i = res.digitArray.Length - 1; i >= digits; i--)
            {
                res.digitArray[i] = 0;
            }

            return res;
        }
Exemplo n.º 13
0
        private static BigInt DigitShiftRight(BigInt n1, int digits)
        {
            BigInt res = new BigInt(n1);

            int Length = res.digitArray.Length;

            for (int i = 0; i < Length - digits; i++)
            {
                res.digitArray[i] = res.digitArray[i + digits];
            }

            for (int i = Length - digits; i < Length; i++)
            {
                res.digitArray[i] = 0;
            }

            return res;
        }
Exemplo n.º 14
0
        /// <summary>
        /// Assign n2 to 'this', safe only if precision-matched
        /// </summary>
        /// <param name="n2"></param>
        /// <returns></returns>
        private void AssignInt(BigInt n2)
        {
            int Length = digitArray.Length;

            for (int i = 0; i < Length; i++)
            {
                digitArray[i] = n2.digitArray[i];
            }
        }
Exemplo n.º 15
0
        /// <summary>
        /// Calculates 'this'^power
        /// </summary>
        /// <param name="power"></param>
        public void Power(BigInt power)
        {
            if (power.IsZero() || power.sign)
            {
                Zero();
                digitArray[0] = 1;
                return;
            }

            BigInt pow = new BigInt(power);
            BigInt temp = new BigInt(this);
            BigInt powTerm = new BigInt(this);

            pow.Decrement();
            for (; !pow.IsZero(); pow.RSH(1))
            {
                if ((pow.digitArray[0] & 1) == 1)
                {
                    temp.Mul(powTerm);
                }

                powTerm.Square();
            }

            Assign(temp);
        }
Exemplo n.º 16
0
 /// <summary>
 /// Makes sure the numbers have matching precisions
 /// </summary>
 /// <param name="n2">the number to match to this</param>
 private void MakeSafe(ref BigInt n2)
 {
     n2 = new BigInt(n2, pres);
     n2.SetNumDigits(digitArray.Length);
 }
Exemplo n.º 17
0
        //************************** Conversions *************************

        /// <summary>
        /// Converts a BigFloat to an BigInt with the specified precision
        /// </summary>
        /// <param name="n1">The number to convert</param>
        /// <param name="precision">The precision to convert it with</param>
        /// <param name="round">Do we round the number if we are truncating the mantissa?</param>
        /// <returns></returns>
        public static BigInt ConvertToInt(BigFloat n1, PrecisionSpec precision, bool round)
        {
            BigInt ret = new BigInt(precision);

            int numBits = n1.mantissa.Precision.NumBits;
            int shift = numBits - (n1.exponent + 1);

            BigFloat copy = new BigFloat(n1);
            bool inc = false;

            //Rounding
            if (copy.mantissa.Precision.NumBits > ret.Precision.NumBits)
            {
                inc = true;

                for (int i = copy.exponent + 1; i <= ret.Precision.NumBits; i++)
                {
                    if (copy.mantissa.GetBitFromTop(i) == 0)
                    {
                        inc = false;
                        break;
                    }
                }
            }

            if (shift > 0)
            {
                copy.mantissa.RSH(shift);
            }
            else if (shift < 0)
            {
                copy.mantissa.LSH(-shift);
            }

            ret.Assign(copy.mantissa);

            if (inc) ret.Increment();

            return ret;
        }
Exemplo n.º 18
0
        //*************** Utility Functions **************

        /// <summary>
        /// Casts a BigInt to the new precision provided.
        /// Note: This will return the input if the precision already matches.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        public static BigInt CastToPrecision(BigInt input, PrecisionSpec precision)
        {
            if (input.pres == precision) return input;
            return new BigInt(input, precision);
        }
Exemplo n.º 19
0
        //************************ Constructors **************************

        /// <summary>
        /// Constructs a 128-bit BigFloat
        /// 
        /// Sets the value to zero
        /// </summary>
        static BigFloat()
        {
            RoundingDigits = 3;
            RoundingMode = RoundingModeType.TRIM;
            scratch = new BigInt(new PrecisionSpec(128, PrecisionSpec.BaseType.BIN));
        }
Exemplo n.º 20
0
        /// <summary>
        /// Subtraction and assignment - without intermediate memory allocation.
        /// </summary>
        /// <param name="n2"></param>
        public uint Sub(BigInt n2)
        {
            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);

            if (sign != n2.sign)
            {
                return AddInternalBits(n2.digitArray);
            }
            else
            {
                bool lessThan = LtInt(this, n2);

                if (lessThan)
                {
                    int Length = digitArray.Length;

                    for (int i = 0; i < Length; i++)
                    {
                        workingSet[i] = digitArray[i];
                        digitArray[i] = n2.digitArray[i];
                    }

                    sign = !sign;
                    return SubInternalBits(workingSet);
                }
                else
                {
                    return SubInternalBits(n2.digitArray);
                }
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// The binary logarithm, log2(x) - for precisions above 1000 bits, use Log() and convert the base.
        /// </summary>
        private void Log2()
        {
            if (scratch.Precision.NumBits != mantissa.Precision.NumBits)
            {
                scratch = new BigInt(mantissa.Precision);
            }

            int bits = mantissa.Precision.NumBits;
            BigFloat temp = new BigFloat(this);
            BigFloat result = new BigFloat(exponent, mantissa.Precision);
            BigFloat pow2 = new BigFloat(1, mantissa.Precision);
            temp.exponent = 0;
            int bitsCalculated = 0;

            while (bitsCalculated < bits)
            {
                int i;
                for (i = 0; (temp.exponent == 0); i++)
                {
                    temp.mantissa.SquareHiFast(scratch);
                    int shift = temp.mantissa.Normalise();
                    temp.exponent += 1 - shift;
                    if (i + bitsCalculated >= bits) break;
                }

                pow2.MulPow2(-i);
                result.Add(pow2);
                temp.exponent = 0;
                bitsCalculated += i;
            }

            this.Assign(result);
        }
Exemplo n.º 22
0
        /// <summary>
        /// Used for floating-point multiplication
        /// Stores the high bits of the multiplication only (the carry bit from the
        /// lower bits is missing, so the true answer might be 1 greater).
        /// </summary>
        /// <param name="n2"></param>
        public void MulHi(BigInt n2)
        {
            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);

            int Length = n2.digitArray.Length;

            //Inner loop zero-mul avoidance
            int maxDigit = 0;
            for (int i = Length - 1; i >= 0; i--)
            {
                if (digitArray[i] != 0)
                {
                    maxDigit = i + 1;
                    break;
                }
            }

            //Result is zero, 'this' is unchanged
            if (maxDigit == 0) return;

            //Temp storage for source (both working sets are used by the calculation)
            uint[] thisTemp = new uint[Length];
            for (int i = 0; i < Length; i++)
            {
                thisTemp[i] = digitArray[i];
                digitArray[i] = 0;
            }

            for (int i = 0; i < Length; i++)
            {
                //Clear the working set
                for (int j = 0; j < Length; j++)
                {
                    workingSet[j] = 0;
                    n2.workingSet[j] = 0;
                }

                n2.workingSet[i] = 0;

                ulong digit = n2.digitArray[i];
                if (digit == 0) continue;

                //Only the high bits
                if (maxDigit + i < Length - 1) continue;

                for (int j = 0; j < maxDigit; j++)
                {
                    if (j + i + 1 < Length) continue;
                    //Multiply n1 by each of the integer digits of n2.
                    ulong temp = (ulong)thisTemp[j] * digit;
                    //n1.workingSet stores the low bits of each piecewise multiplication
                    if (j + i >= Length)
                    {
                        workingSet[j + i - Length] = (uint)(temp & 0xffffffff);
                    }
                    
                    //n2.workingSet stores the high bits of each multiplication
                    n2.workingSet[j + i + 1 - Length] = (uint)(temp >> 32);
                }

                AddInternalBits(workingSet);
                AddInternalBits(n2.workingSet);
            }

            sign = (sign != n2.sign);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Uses the Gauss-Legendre formula for pi
        /// Taken from http://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_algorithm
        /// </summary>
        /// <param name="numBits"></param>
        private static void CalculatePi(int numBits)
        {
            int bits = numBits + 32;
            //Precision extend taken out.
            PrecisionSpec normalPres = new PrecisionSpec(numBits, PrecisionSpec.BaseType.BIN);
            PrecisionSpec extendedPres = new PrecisionSpec(bits, PrecisionSpec.BaseType.BIN);

            if (scratch.Precision.NumBits != bits)
            {
                scratch = new BigInt(extendedPres);
            }

            //a0 = 1
            BigFloat an = new BigFloat(1, extendedPres);

            //b0 = 1/sqrt(2)
            BigFloat bn = new BigFloat(2, extendedPres);
            bn.Sqrt();
            bn.exponent--;

            //to = 1/4
            BigFloat tn = new BigFloat(1, extendedPres);
            tn.exponent -= 2;

            int pn = 0;

            BigFloat anTemp = new BigFloat(extendedPres);

            int iteration = 0;
            int cutoffBits = numBits >> 5;

            for (iteration = 0; ; iteration++)
            {
                //Save a(n)
                anTemp.Assign(an);

                //Calculate new an
                an.Add(bn);
                an.exponent--;

                //Calculate new bn
                bn.Mul(anTemp);
                bn.Sqrt();

                //Calculate new tn
                anTemp.Sub(an);
                anTemp.mantissa.SquareHiFast(scratch);
                anTemp.exponent += anTemp.exponent + pn + 1 - anTemp.mantissa.Normalise();
                tn.Sub(anTemp);

                anTemp.Assign(an);
                anTemp.Sub(bn);

                if (anTemp.exponent < -(bits - cutoffBits)) break;

                //New pn
                pn++;
            }

            an.Add(bn);
            an.mantissa.SquareHiFast(scratch);
            an.exponent += an.exponent + 1 - an.mantissa.Normalise();
            tn.exponent += 2;
            an.Div(tn);

            pi = new BigFloat(an, normalPres);
            piBy2 = new BigFloat(pi);
            piBy2.exponent--;
            twoPi = new BigFloat(pi, normalPres);
            twoPi.exponent++;
            piRecip = new BigFloat(an.Reciprocal(), normalPres);
            twoPiRecip = new BigFloat(piRecip);
            twoPiRecip.exponent--;
            //1/3 is going to be useful for sin.
            threeRecip = new BigFloat((new BigFloat(3, extendedPres)).Reciprocal(), normalPres);
        }
Exemplo n.º 24
0
        /// <summary>
        /// Floating-point helper function.
        /// Squares the number and keeps the high bits of the calculation.
        /// Takes a temporary BigInt as a working set.
        /// </summary>
        public void SquareHiFast(BigInt scratch)
        {
            int Length = digitArray.Length;
            uint[] tempDigits = scratch.digitArray;
            uint[] workingSet2 = scratch.workingSet;

            //Temp storage for source (both working sets are used by the calculation)
            for (int i = 0; i < Length; i++)
            {
                tempDigits[i] = digitArray[i];
                digitArray[i] = 0;
            }

            for (int i = 0; i < Length; i++)
            {
                //Clear the working set
                for (int j = i; j < Length; j++)
                {
                    workingSet[j] = 0;
                    workingSet2[j] = 0;
                }

                if (i - 1 >= 0) workingSet[i - 1] = 0;

                ulong digit = tempDigits[i];
                if (digit == 0) continue;

                for (int j = 0; j < Length; j++)
                {
                    if (j + i + 1 < Length) continue;
                    //Multiply n1 by each of the integer digits of n2.
                    ulong temp = (ulong)tempDigits[j] * digit;
                    //n1.workingSet stores the low bits of each piecewise multiplication
                    if (j + i >= Length)
                    {
                        workingSet[j + i - Length] = (uint)(temp & 0xffffffff);
                    }

                    //n2.workingSet stores the high bits of each multiplication
                    workingSet2[j + i + 1 - Length] = (uint)(temp >> 32);
                }

                AddInternalBits(workingSet);
                AddInternalBits(workingSet2);
            }

            sign = false;
        }
Exemplo n.º 25
0
        /// <summary>
        /// Constructs a BigFloat from a 64-bit unsigned integer
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(UInt64 value, PrecisionSpec mantissaPrec)
        {
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            //For efficiency, we just use a 32-bit exponent
            exponent = 0;

            int bit = BigInt.GetMSB(value);

            mantissa = new BigInt(value, new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(mantissa.Precision);

            int shift = mantissa.Precision.NumBits - (bit + 1);
            if (shift > 0)
            {
                mantissa.LSH(shift);
            }
            else
            {
                mantissa.SetHighDigit((uint)(value >> (-shift)));
            }
            exponent = bit;
        }
Exemplo n.º 26
0
        /// <summary>
        /// This function is used for floating-point division.
        /// </summary>
        /// <param name="n2"></param>
        //Given two numbers:
        //  In floating point 1 <= a, b < 2, meaning that both numbers have their top bits set.
        //  To calculate a / b, maintaining precision, we:
        //    1. Double the number of digits available to both numbers.
        //    2. set a = a * 2^d (where d is the number of digits)
        //    3. calculate the quotient a <- q:  2^(d-1) <= q < 2^(d+1)
        //    4. if a >= 2^d, s = 1, else s = 0
        //    6. shift a down by s, and undo the precision extension
        //    7. return 1 - shift (change necessary to exponent)
        public int DivAndShift(BigInt n2)
        {
            if (n2.IsZero()) return -1;
            if (digitArray.Length != n2.digitArray.Length) MakeSafe(ref n2);

            int oldLength = digitArray.Length;

            //Double the number of digits, and shift a into the higher digits.
            Pad();
            n2.Extend();

            //Do the divide (at double precision, ouch!)
            Div(n2);

            //Shift down if 'this' >= 2^d
            int ret = 1;

            if (digitArray[oldLength] != 0)
            {
                RSH(1);
                ret--;
            }

            SetNumDigits(oldLength);
            n2.SetNumDigits(oldLength);

            return ret;
        }
Exemplo n.º 27
0
        /// <summary>
        /// Construct a BigFloat from a double-precision floating point number
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(double value, PrecisionSpec mantissaPrec)
        {
            if (value == 0.0)
            {
                Init(mantissaPrec);
                return;
            }

            bool sign = (value < 0) ? true : false;

            long bits = BitConverter.DoubleToInt64Bits(value);
            // Note that the shift is sign-extended, hence the test against -1 not 1
            int valueExponent = (int)((bits >> 52) & 0x7ffL);
            long valueMantissa = bits & 0xfffffffffffffL;

            //The mantissa is stored with the top bit implied.
            valueMantissa = valueMantissa | 0x10000000000000L;

            //The exponent is biased by 1023.
            exponent = valueExponent - 1023;

            //Round the number of bits to the nearest word.
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            mantissa = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));

            if (newManBits >= 64)
            {
                //The mantissa is 53 bits now, so add 11 to put it in the right place.
                mantissa.SetHighDigits(valueMantissa << 11);
            }
            else
            {
                //To get the top word of the mantissa, shift up by 11 and down by 32 = down by 21
                mantissa.SetHighDigit((uint)(valueMantissa >> 21));
            }

            mantissa.Sign = sign;
        }
Exemplo n.º 28
0
        /// <summary>
        /// Calculates 'this' mod n2 (using the schoolbook division algorithm as above)
        /// </summary>
        /// <param name="n2"></param>
        public void Mod(BigInt n2)
        {
            if (n2.digitArray.Length != digitArray.Length) MakeSafe(ref n2);

            int OldLength = digitArray.Length;

            //First, we need to prepare the operands for division using Div_32, which requires
            //That the most significant digit of n2 be set. To do this, we need to shift n2 (and therefore n1) up.
            //This operation can potentially increase the precision of the operands.
            int shift = MakeSafeDiv(this, n2);

            BigInt Q = new BigInt(this.pres);
            BigInt R = new BigInt(this.pres);

            Q.digitArray = new UInt32[this.digitArray.Length];
            R.digitArray = new UInt32[this.digitArray.Length];

            Div_32(this, n2, Q, R);

            //Restore n2 to its pre-shift value
            n2.RSH(shift);
            R.RSH(shift);
            R.sign = (sign != n2.sign);
            AssignInt(R);

            //Reset the lengths of the operands
            SetNumDigits(OldLength);
            n2.SetNumDigits(OldLength);
        }
Exemplo n.º 29
0
        //******************** Arithmetic Functions ********************

        /// <summary>
        /// Addition (this = this + n2)
        /// </summary>
        /// <param name="n2">The number to add</param>
        public void Add(BigFloat n2)
        {
            if (SpecialValueAddTest(n2)) return;

            if (scratch.Precision.NumBits != n2.mantissa.Precision.NumBits)
            {
                scratch = new BigInt(n2.mantissa.Precision);
            }

            if (exponent <= n2.exponent)
            {
                int diff = n2.exponent - exponent;
                exponent = n2.exponent;

                if (diff != 0)
                {
                    mantissa.RSH(diff);
                }

                uint carry = mantissa.Add(n2.mantissa);

                if (carry != 0)
                {
                    mantissa.RSH(1);
                    mantissa.SetBit(mantissa.Precision.NumBits - 1);
                    exponent++;
                }

                exponent -= mantissa.Normalise();
            }
            else
            {
                int diff = exponent - n2.exponent;

                scratch.Assign(n2.mantissa);
                scratch.RSH(diff);

                uint carry = scratch.Add(mantissa);

                if (carry != 0)
                {
                    scratch.RSH(1);
                    scratch.SetBit(mantissa.Precision.NumBits - 1);
                    exponent++;
                }

                mantissa.Assign(scratch);

                exponent -= mantissa.Normalise();
            }
        }
Exemplo n.º 30
0
 /// <summary>
 /// Constructs a bigint from the input.
 /// </summary>
 /// <param name="input"></param>
 public BigInt(BigInt input)
 {
     digitArray = new uint[input.digitArray.Length];
     workingSet = new uint[input.digitArray.Length];
     Array.Copy(input.digitArray, digitArray, digitArray.Length);
     sign = input.sign;
     pres = input.pres;
 }