예제 #1
0
            /// <summary>
            /// Performs the division (with remainder) of two long integer numbers.
            /// </summary>
            /// <param name="one">The first LongInt number.</param>
            /// <param name="two">The second LongInt number.</param>
            /// <param name="remainder">The reference to contain the remainder.</param>
            /// <returns>The result of integral division.</returns>
            public static LongInt <B> Div(LongInt <B> one, LongInt <B> two, out LongInt <B> remainder)
            {
                Contract.Requires <ArgumentNullException>(one != null, "one");
                Contract.Requires <ArgumentNullException>(two != null, "two");

                Contract.Ensures(Contract.ForAll(Contract.Result <LongInt <B> >().Digits, x => (x >= 0)));

                // Проверка на тупые случаи - деление на большее число или деление на единичную цифру.

                if (one.Length < two.Length)
                {
                    remainder = one.Clone() as LongInt <B>;
                    return(new LongInt <B>());                                  // zero number should be returned
                }
                if (two.Length == 1)
                {
                    LongInt <B> result = new LongInt <B>(one.Length);
                    result.Digits.AddRange(new int[one.Length]);

                    int rem = LongIntegerMethods.DivideByInteger(LongInt <B> .BASE, result.Digits, one.Digits, two[0]);

                    // Разберемся с negativeness.

                    remainder = (LongInt <B>)rem;    // convert the result to LongInt...

                    result.Negative    = one.Negative ^ two.Negative;
                    remainder.Negative = one.Negative;

                    result.DealWithZeroes();
                    remainder.DealWithZeroes();

                    return(result);
                }

                LongInt <B> res = new LongInt <B>();

                res.Digits.AddRange(new int[one.Length - two.Length + 1]);

                remainder = new LongInt <B>(two.Length);

                // ----- big bada-boom!

                IList <int> remDigits = LongIntegerMethods.Div(LongInt <B> .BASE, res.Digits, one.Digits, two.Digits);

                // --------------------

                remainder.Digits.AddRange(remDigits);

                // deal with negativeness

                res.Negative       = one.Negative ^ two.Negative;
                remainder.Negative = one.Negative;

                // deal with zeroes

                res.DealWithZeroes();
                remainder.DealWithZeroes();

                return(res);
            }
예제 #2
0
            // THIS SHOULD BE OPTIMIZED FOR KARATSUBA MULTIPLICATION BY METHOD BELOW
            // ---------------------------------------------------------------------

            /// <summary>
            /// The Karatsuba multiplying algorithm.
            /// The lengths of numbers are completed to the nearest bigger power of 2.
            /// </summary>
            /// <param name="one"></param>
            /// <param name="two"></param>
            /// <returns></returns>
            public static LongInt <B> MultiplyKaratsuba(LongInt <B> one, LongInt <B> two)
            {
                LongInt <B> bigger   = one.Length > two.Length ? one : two;
                int         twoPower = 1;

                // Последовательное умножение на два, пока
                // не достигнем нужной длины.

                while (bigger.Length > twoPower)
                {
                    twoPower <<= 1;
                }

                LongInt <B> result = new LongInt <B>();

                result.Negative = one.Negative ^ two.Negative;
                result.Digits.AddRange(new int[twoPower * 2]);

                one.Digits.AddRange(new int[twoPower - one.Length]);
                two.Digits.AddRange(new int[twoPower - two.Length]);

                MultiplyKaratsuba(LongInt <B> .BASE, result.Digits, one.Digits, two.Digits, twoPower);

                result.DealWithZeroes();
                one.DealWithZeroes();
                two.DealWithZeroes();

                return(result);
            }
예제 #3
0
        /// <summary>
        /// Returns the next non-negative <c>LongInt&lt;<typeparamref name="B"/>&gt;</c>
        /// number which is less than <paramref name="maxExclusive"/>.
        /// </summary>
        /// <param name="maxExclusive">The upper exclusive bound of generated numbers.</param>
        /// <returns>
        /// A non-negative <c>LongInt&lt;<typeparamref name="B"/>&gt;</c> number which
        /// is less than <paramref name="maxExclusive"/>.
        /// </returns>
        public LongInt <B> Next(LongInt <B> maxExclusive)
        {
            Contract.Requires <ArgumentNullException>(maxExclusive != null, "maxExclusive");
            Contract.Requires <ArgumentOutOfRangeException>(maxExclusive > 0, "The maximum exclusive bound should be a positive number.");

            LongInt <B> basePowered = LongInt <B> .CreatePowerOfBase(maxExclusive.Length);

            LongInt <B> upperBound;

            if (this.lastMaxExclusive != maxExclusive)
            {
                // Мы будем генерировать ВСЕ цифры от 0 до BASE - 1.
                // НО:
                // Мы отбрасываем верхнюю границу, где приведение по модулю maxExclusive
                // даст нам лишнюю неравномерность.
                // Мы можем использовать только интервал, содержащий целое число чисел maxExclusive.
                // Тогда спокойно приводим по модулю и наслаждаемся равномерностью.

                // Например, если мы генерируем цифирки по основанию 10, и хотим число от [0; 12),
                // то нам нужно отбрасывать начиная с floor(10^2 / 12) * 12 = 96.

                upperBound = Max_BinarySearch((LongInt <B>) 1, LongInt <B> .BASE, (res => LongInt <B> .Helper.MultiplyFFTComplex(res, maxExclusive) <= basePowered)) * maxExclusive;

                // upperBound = multiplication(basePowered / maxExclusive, maxExclusive);

                this.lastMaxExclusive = maxExclusive;
                this.lastBound        = upperBound;
            }
            else
            {
                upperBound = this.lastBound;
            }

            LongInt <B> result = new LongInt <B>();

REPEAT:

            result.Digits.Clear();

            for (int i = 0; i < maxExclusive.Length; i++)
            {
                result.Digits.Add(intGenerator.Next(0, LongInt <B> .BASE));
            }

            result.DealWithZeroes();

            if (result >= upperBound)
            {
                ++TotalRejected;
                goto REPEAT;
            }

            // Возвращаем остаток от деления.

            // return result % maxExclusive;

            LongInt <B> divisionResult = Max_BinarySearch((LongInt <B>) 0, LongInt <B> .BASE, (res => LongInt <B> .Helper.MultiplyFFTComplex(res, maxExclusive) <= result));

            return(result - LongInt <B> .Helper.MultiplyFFTComplex(divisionResult, maxExclusive));
        }
예제 #4
0
            public static LongInt <B> MultiplyFFTComplex(LongInt <B> one, LongInt <B> two, out double maxRoundError, out double maxImaginaryPart, out long maxLong)
            {
                LongInt <B> res = new LongInt <B>(one.Length + two.Length);

                res.Negative = one.Negative ^ two.Negative;

                long[] resultOverflowProne = new long[one.Length + two.Length];
                MultiplyFFTComplex(LongInt <B> .BASE, resultOverflowProne, one.Digits, two.Digits, out maxRoundError, out maxImaginaryPart, out maxLong);

                for (int i = 0; i < resultOverflowProne.Length; i++)
                {
                    res.Digits.Add((int)resultOverflowProne[i]);
                }

                res.DealWithZeroes();
                return(res);
            }
예제 #5
0
            //---------------------------------------------------------------
            //---------------------NUMBER MULTIPLICATION---------------------
            //---------------------------------------------------------------

            /// <summary>
            /// Performs a simple, square-complex multiplication of two LongInt numbers.
            /// </summary>
            /// <param name="one"></param>
            /// <param name="two"></param>
            /// <returns></returns>
            public static LongInt <B> MultiplySimple(LongInt <B> one, LongInt <B> two)
            {
                // the resulting number can have double length.

                LongInt <B> res = new LongInt <B>(one.Length + two.Length);

                res.Digits.AddRange(new int[one.Length + two.Length]);
                res.Negative = one.Negative ^ two.Negative;

                // The big one

                LongIntegerMethods.MultiplySimple(LongInt <B> .BASE, res.Digits, one.Digits, two.Digits);

                // Cut the leading zeroes

                res.DealWithZeroes();
                return(res);
            }
예제 #6
0
            /// <summary>
            /// Computes the product of two long integer numbers using NTT in finite fields.
            ///
            /// The numbers are not necessarily required to be of two's power long;
            /// this algorithm performs all needed operations automatically.
            /// </summary>
            /// <param name="one"></param>
            /// <param name="two"></param>
            public static LongInt <B> MultiplyNTT(LongInt <B> one, LongInt <B> two)
            {
                Contract.Requires <ArgumentNullException>(one != null, "one");
                Contract.Requires <ArgumentNullException>(two != null, "two");

                LongInt <B> result = new LongInt <B>(one.Length + two.Length);

                long[] longResult = new long[one.Length + two.Length];

                MultiplyNTT(LongInt <B> .BASE, longResult, one.Digits, two.Digits);

                for (int i = 0; i < longResult.Length; i++)
                {
                    result.Digits.Add((int)longResult[i]);
                }

                result.Negative = one.Negative ^ two.Negative;
                result.DealWithZeroes();

                return(result);
            }
예제 #7
0
        /// <summary>
        /// Returns the next non-negative <c>LongInt&lt;<typeparamref name="B"/>&gt;</c>
        /// number which is not bigger than <paramref name="maxInclusive"/>.
        /// </summary>
        /// <param name="maxInclusive">The upper inclusive bound of generated numbers.</param>
        /// <returns>
        /// A non-negative <c>LongInt&lt;<typeparamref name="B"/>&gt;</c> number which
        /// is not bigger than <paramref name="maxInclusive"/>.
        /// </returns>
        public LongInt <B> NextInclusive(LongInt <B> maxInclusive)
        {
            Contract.Requires <ArgumentNullException>(maxInclusive != null, "maxInclusive");
            Contract.Requires <ArgumentOutOfRangeException>(!maxInclusive.Negative, "The maximum inclusive number should not be negative.");

            // Будем генерировать числа длины такой же, как maxInclusive.
            // Все цифры - от 0 до BASE - 1

            LongInt <B> result = new LongInt <B>();

            result.Digits.Clear();
            result.Digits.AddRange(new int[maxInclusive.Length]);

            bool flag = true;  // есть ли ограничение по цифрам

REPEAT:

            for (int i = maxInclusive.Length - 1; i >= 0; i--)
            {
                result.Digits[i] = intGenerator.Next(0, LongInt <B> .BASE);

                if (flag)
                {
                    if (result[i] > maxInclusive[i])
                    {
                        ++TotalRejected;
                        goto REPEAT;
                    }

                    else if (result[i] < maxInclusive[i])
                    {
                        flag = false;
                    }
                }
            }

            result.DealWithZeroes();

            return(result);
        }
예제 #8
0
        /// <summary>
        /// Returns the next non-negative <c>LongInt&lt;<typeparamref name="B"/>&gt;</c>
        /// number which is less than <paramref name="maxExclusive"/>.
        /// </summary>
        /// <param name="maxExclusive">The upper exclusive bound of generated numbers.</param>
        /// <returns>
        /// A non-negative <c>LongInt&lt;<typeparamref name="B"/>&gt;</c> number which
        /// is less than <paramref name="maxExclusive"/>.
        /// </returns>
        public LongInt <B> Next(LongInt <B> maxExclusive)
        {
            Contract.Requires <ArgumentNullException>(maxExclusive != null, "maxExclusive");
            Contract.Requires <ArgumentOutOfRangeException>(maxExclusive > 0, "The maximum exclusive bound should be a positive number.");

            // Мы будем генерировать ВСЕ цифры от 0 до BASE - 1.
            // НО:
            // Мы отбрасываем верхнюю границу, где приведение по модулю maxExclusive
            // даст нам лишнюю неравномерность.
            // Мы можем использовать только интервал, содержащий целое число чисел maxExclusive.
            // Тогда спокойно приводим по модулю и наслаждаемся равномерностью.

            // Например, если мы генерируем цифирки по основанию 10, и хотим число от [0; 12),
            // то нам нужно отбрасывать начиная с floor(10^2 / 12) * 12 = 96.

            LongInt <B> upperBound = (LongInt <B> .CreatePowerOfBase(maxExclusive.Length) / maxExclusive) * maxExclusive;

            LongInt <B> result = new LongInt <B>();

REPEAT:

            result.Digits.Clear();

            for (int i = 0; i < maxExclusive.Length; i++)
            {
                result.Digits.Add(intGenerator.Next(0, LongInt <B> .BASE));
            }

            result.DealWithZeroes();

            if (result >= upperBound)
            {
                ++TotalRejected;
                goto REPEAT;
            }

            return(result % maxExclusive);
        }
예제 #9
0
        /// <summary>
        /// Returns the next non-negative <c>LongInt&lt;<typeparamref name="B"/>&gt;</c>
        /// number which is not bigger than <paramref name="maxInclusive"/>.
        /// </summary>
        /// <param name="maxInclusive">The upper inclusive bound of generated numbers.</param>
        /// <returns>
        /// A non-negative <c>LongInt&lt;<typeparamref name="B"/>&gt;</c> number which
        /// is not bigger than <paramref name="maxInclusive"/>.
        /// </returns>
        public LongInt <B> NextInclusive(LongInt <B> maxInclusive)
        {
            Contract.Requires <ArgumentNullException>(maxInclusive != null, "maxInclusive");
            Contract.Requires <ArgumentException>(!maxInclusive.Negative, "The maximum inclusive bound should not be negative.");

            LongInt <B> result = new LongInt <B>();

            result.Digits.Clear();
            result.Digits.AddRange(new int[maxInclusive.Length]);

            // Флаг, сигнализирующий о том, что мы пока генерируем
            // только цифры нашей верхней границы.
            // Как только сгенерировали что-то меньшее, все остальное
            // можно генерировать в пределах от 0 до BASE-1.

            bool flag = true;

            for (int i = result.Length - 1; i >= 0; i--)
            {
                if (flag)
                {
                    result[i] = intGenerator.Next(0, maxInclusive[i] + 1);

                    if (result[i] < maxInclusive[i])
                    {
                        flag = false;
                    }
                }
                else
                {
                    result[i] = intGenerator.Next(0, LongInt <B> .BASE);
                }
            }

            result.DealWithZeroes();

            return(result);
        }