private void TestDiv(BigInteger i1, BigInteger i2)
        {
            BigInteger q = i1 / i2;
            BigInteger r = BigMath.Remainder(i1, i2);
            BigInteger remainder;
            BigInteger quotient = BigMath.DivideAndRemainder(i1, i2, out remainder);

            Assert.True(q.Equals(quotient), "Divide and DivideAndRemainder do not agree");
            Assert.True(r.Equals(remainder), "Remainder and DivideAndRemainder do not agree");
            Assert.True(q.Sign != 0 || q.Equals(zero), "signum and equals(zero) do not agree on quotient");
            Assert.True(r.Sign != 0 || r.Equals(zero), "signum and equals(zero) do not agree on remainder");
            Assert.True(q.Sign == 0 || q.Sign == i1.Sign * i2.Sign, "wrong sign on quotient");
            Assert.True(r.Sign == 0 || r.Sign == i1.Sign, "wrong sign on remainder");
            Assert.True(BigMath.Abs(r).CompareTo(BigMath.Abs(i2)) < 0, "remainder out of range");
            Assert.True(((BigMath.Abs(q) + one) * BigMath.Abs(i2)).CompareTo(BigMath.Abs(i1)) > 0, "quotient too small");
            Assert.True((BigMath.Abs(q) * BigMath.Abs(i2)).CompareTo(BigMath.Abs(i1)) <= 0, "quotient too large");
            BigInteger p = q * i2;
            BigInteger a = p + r;

            Assert.True(a.Equals(i1), "(a/b)*b+(a%b) != a");
            try {
                BigInteger mod = i1 % i2;
                Assert.True(mod.Sign >= 0, "mod is negative");
                Assert.True(BigMath.Abs(mod).CompareTo(BigMath.Abs(i2)) < 0, "mod out of range");
                Assert.True(r.Sign < 0 || r.Equals(mod), "positive remainder == mod");
                Assert.True(r.Sign >= 0 || r.Equals(mod - i2), "negative remainder == mod - divisor");
            } catch (ArithmeticException e) {
                Assert.True(i2.Sign <= 0, "mod fails on negative divisor only");
            }
        }
 public void RemainderBigInteger()
 {
     Assert.Throws <ArithmeticException>(() => BigMath.Remainder(largePos, zero));
     Assert.Throws <ArithmeticException>(() => BigMath.Remainder(bi1, zero));
     Assert.Throws <ArithmeticException>(() => BigMath.Remainder(-bi3, zero));
     Assert.Throws <ArithmeticException>(() => BigMath.Remainder(zero, zero));
 }
        // TODO: must be verified
        public decimal ToDecimal()
        {
            var scaleDivisor = BigMath.Pow(BigInteger.FromInt64(10), _scale);
            var remainder    = BigMath.Remainder(GetUnscaledValue(), scaleDivisor);
            var scaledValue  = GetUnscaledValue() / scaleDivisor;

            var leftOfDecimal  = (decimal)scaledValue;
            var rightOfDecimal = (remainder) / ((decimal)scaleDivisor);

            return(leftOfDecimal + rightOfDecimal);
        }
Beispiel #4
0
        public static BigInteger Mod(BigInteger value, BigInteger m)
        {
            if (m.Sign <= 0)
            {
                // math.18=BigInteger: modulus not positive
                throw new ArithmeticException(Messages.math18);                 //$NON-NLS-1$
            }
            BigInteger rem = BigMath.Remainder(value, m);

            return((rem.Sign < 0) ? rem + m : rem);
        }
        /**
         * @param m a positive modulus
         * Return the greatest common divisor of op1 and op2,
         *
         * @param op1
         *            must be greater than zero
         * @param op2
         *            must be greater than zero
         * @see BigInteger#gcd(BigInteger)
         * @return {@code GCD(op1, op2)}
         */

        public static BigInteger GcdBinary(BigInteger op1, BigInteger op2)
        {
            // PRE: (op1 > 0) and (op2 > 0)

            /*
             * Divide both number the maximal possible times by 2 without rounding
             * gcd(2*a, 2*b) = 2 * gcd(a,b)
             */
            int lsb1      = op1.LowestSetBit;
            int lsb2      = op2.LowestSetBit;
            int pow2Count = System.Math.Min(lsb1, lsb2);

            BitLevel.InplaceShiftRight(op1, lsb1);
            BitLevel.InplaceShiftRight(op2, lsb2);

            BigInteger swap;

            // I want op2 > op1
            if (op1.CompareTo(op2) == BigInteger.GREATER)
            {
                swap = op1;
                op1  = op2;
                op2  = swap;
            }

            do
            {
                // INV: op2 >= op1 && both are odd unless op1 = 0

                // Optimization for small operands
                // (op2.bitLength() < 64) implies by INV (op1.bitLength() < 64)
                if ((op2.numberLength == 1) ||
                    ((op2.numberLength == 2) && (op2.Digits[1] > 0)))
                {
                    op2 = BigInteger.FromInt64(Division.GcdBinary(op1.ToInt64(),
                                                                  op2.ToInt64()));
                    break;
                }

                // Implements one step of the Euclidean algorithm
                // To reduce one operand if it's much smaller than the other one
                if (op2.numberLength > op1.numberLength * 1.2)
                {
                    op2 = BigMath.Remainder(op2, op1);
                    if (op2.Sign != 0)
                    {
                        BitLevel.InplaceShiftRight(op2, op2.LowestSetBit);
                    }
                }
                else
                {
                    // Use Knuth's algorithm of successive subtract and shifting
                    do
                    {
                        Elementary.inplaceSubtract(op2, op1);                         // both are odd
                        BitLevel.InplaceShiftRight(op2, op2.LowestSetBit);            // op2 is even
                    } while (op2.CompareTo(op1) >= BigInteger.EQUALS);
                }
                // now op1 >= op2
                swap = op2;
                op2  = op1;
                op1  = swap;
            } while (op1.Sign != 0);
            return(op2 << pow2Count);
        }