Beispiel #1
0
        static int Compare(Bignum a, Bignum b)
        {
            Debug.Assert(a.IsClamped());
            Debug.Assert(b.IsClamped());
            int bigit_length_a = a.BigitLength();
            int bigit_length_b = b.BigitLength();

            if (bigit_length_a < bigit_length_b)
            {
                return(-1);
            }
            if (bigit_length_a > bigit_length_b)
            {
                return(+1);
            }
            for (int i = bigit_length_a - 1; i >= System.Math.Min(a.exponent_, b.exponent_); --i)
            {
                uint bigit_a = a.BigitAt(i);
                uint bigit_b = b.BigitAt(i);
                if (bigit_a < bigit_b)
                {
                    return(-1);
                }
                if (bigit_a > bigit_b)
                {
                    return(+1);
                }
                // Otherwise they are equal up to this digit. Try the next digit.
            }

            return(0);
        }
Beispiel #2
0
        void SubtractBignum(Bignum other)
        {
            Debug.Assert(IsClamped());
            Debug.Assert(other.IsClamped());
            // We require this to be bigger than other.
            Debug.Assert(LessEqual(other, this));

            Align(other);

            int  offset = other.exponent_ - exponent_;
            uint borrow = 0;
            int  i;

            for (i = 0; i < other.used_digits_; ++i)
            {
                Debug.Assert((borrow == 0) || (borrow == 1));
                uint difference = bigits_[i + offset] - other.bigits_[i] - borrow;
                bigits_[i + offset] = difference & kBigitMask;
                borrow = difference >> (kChunkSize - 1);
            }

            while (borrow != 0)
            {
                uint difference = bigits_[i + offset] - borrow;
                bigits_[i + offset] = difference & kBigitMask;
                borrow = difference >> (kChunkSize - 1);
                ++i;
            }

            Clamp();
        }
Beispiel #3
0
        internal static int PlusCompare(Bignum a, Bignum b, Bignum c)
        {
            Debug.Assert(a.IsClamped());
            Debug.Assert(b.IsClamped());
            Debug.Assert(c.IsClamped());
            if (a.BigitLength() < b.BigitLength())
            {
                return(PlusCompare(b, a, c));
            }

            if (a.BigitLength() + 1 < c.BigitLength())
            {
                return(-1);
            }
            if (a.BigitLength() > c.BigitLength())
            {
                return(+1);
            }
            // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than
            // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one
            // of 'a'.
            if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength())
            {
                return(-1);
            }

            uint borrow = 0;
            // Starting at min_exponent all digits are == 0. So no need to compare them.
            int min_exponent = System.Math.Min(System.Math.Min(a.exponent_, b.exponent_), c.exponent_);

            for (int i = c.BigitLength() - 1; i >= min_exponent; --i)
            {
                uint chunk_a = a.BigitAt(i);
                uint chunk_b = b.BigitAt(i);
                uint chunk_c = c.BigitAt(i);
                uint sum     = chunk_a + chunk_b;
                if (sum > chunk_c + borrow)
                {
                    return(+1);
                }
                else
                {
                    borrow = chunk_c + borrow - sum;
                    if (borrow > 1)
                    {
                        return(-1);
                    }
                    borrow <<= kBigitSize;
                }
            }

            if (borrow == 0)
            {
                return(0);
            }
            return(-1);
        }
Beispiel #4
0
        // Precondition: this/other < 16bit.
        public uint DivideModuloIntBignum(Bignum other)
        {
            Debug.Assert(IsClamped());
            Debug.Assert(other.IsClamped());
            Debug.Assert(other.used_digits_ > 0);

            // Easy case: if we have less digits than the divisor than the result is 0.
            // Note: this handles the case where this == 0, too.
            if (BigitLength() < other.BigitLength())
            {
                return(0);
            }

            Align(other);

            uint result = 0;

            // Start by removing multiples of 'other' until both numbers have the same
            // number of digits.
            while (BigitLength() > other.BigitLength())
            {
                // This naive approach is extremely inefficient if the this divided other
                // might be big. This function is implemented for doubleToString where
                // the result should be small (less than 10).
                Debug.Assert(other.bigits_[other.used_digits_ - 1] >= (1 << kBigitSize) / 16);
                // Remove the multiples of the first digit.
                // Example this = 23 and other equals 9. -> Remove 2 multiples.
                result += bigits_[used_digits_ - 1];
                SubtractTimes(other, bigits_[used_digits_ - 1]);
            }

            Debug.Assert(BigitLength() == other.BigitLength());

            // Both bignums are at the same length now.
            // Since other has more than 0 digits we know that the access to
            // bigits_[used_digits_ - 1] is safe.
            var this_bigit  = bigits_[used_digits_ - 1];
            var other_bigit = other.bigits_[other.used_digits_ - 1];

            if (other.used_digits_ == 1)
            {
                // Shortcut for easy (and common) case.
                uint quotient = this_bigit / other_bigit;
                bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;
                result += quotient;
                Clamp();
                return(result);
            }

            uint division_estimate = this_bigit / (other_bigit + 1);

            result += division_estimate;
            SubtractTimes(other, division_estimate);

            if (other_bigit * (division_estimate + 1) > this_bigit)
            {
                return(result);
            }

            while (LessEqual(other, this))
            {
                SubtractBignum(other);
                result++;
            }

            return(result);
        }