// 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); }
public static LongInt <B> MultiplyFFTComplex(LongInt <B> one, LongInt <B> two) { double junk; // не хотите использовать - не надо! long junky; // ну, что поделать... return(MultiplyFFTComplex(one, two, out junk, out junk, out junky)); }
//! Initialize the LongInt field. /*! * \param data A reference to the LongInt to initialize. * \param bytes Number of bytes to initialize * \param value The value of the LongInt */ private void init(LongInt[] data, int bytes, int value) { for (int i = 0; i < data.Length; i++) { data [i] = new LongInt(bytes, value); } }
/// <summary> /// Returns the integer part of the square root /// of the number. /// </summary> /// <remarks>This method works only for integer numeric types.</remarks> /// <param name="number">A strictly positive number for which the integer part of its square root is to be found.</param> /// <returns>The integer part of the square root of the <paramref name="number"/>.</returns> public static LongInt <B> SquareRootInteger(LongInt <B> number) { Contract.Requires <ArgumentNullException>(number != null, "number"); Contract.Requires <ArgumentOutOfRangeException>(number > 0); LongInt <B> firstEstimate = number; // Имеет смысл находить лучшее, чем само число, // первое приближение, только в том случае, // если число имеет длину более 1. if (number.Length > 1) { // Для курсача - доказать, что это хуже, чем то, что незакомментировано // // firstEstimate = LongInt<B>.CreatePowerOfBase((number.Length + 1) / 2); if (!BASE_IS_FULL_SQUARE || number.Length % 2 == 0) { firstEstimate = LongInt <B> .CreatePowerOfBase((number.Length + 1) / 2); } else { firstEstimate = LongInt <B> .CreatePowerOfBase(number.Length / 2); firstEstimate[firstEstimate.Length - 1] = LongInt <B> .Helper.BASE_SQRT_FLOOR; } } return (WhiteMath <LongInt <B>, CalcLongInt <B> > .SquareRootInteger(number, firstEstimate)); }
/// <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); }
/// <summary> /// Returns the next non-negative <c>LongInt<<typeparamref name="B"/>></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<<typeparamref name="B"/>></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)); }
/// <summary> /// Performs a fast exponentiation of a <c>LongInt</c> number modulo another number. /// </summary> /// <typeparam name="B">A type specifying the numeric base of exponentiated number.</typeparam> /// <typeparam name="T">A type specifying the numeric base of the exponent. It is very recommended that it be an integer power of two for performance reasons.</typeparam> /// <remarks>If <typeparamref name="T"/> <c>IBase</c> type stands for a base that is an integer power of two, the algorithm will speed up significantly.</remarks> /// <param name="number">A <c>LongInt</c> number to be exponentiated.</param> /// <param name="power">A non-negative exponent.</param> /// <param name="modulus">The modulus of the operation.</param> /// <returns>The result of raising <paramref name="number"/> to power <paramref name="power"/> modulo <paramref name="modulus"/>.</returns> public static LongInt <B> PowerIntegerModular <B, T>(LongInt <B> number, LongInt <T> power, LongInt <B> modulus) where B : IBase, new() where T : IBase, new() { Contract.Requires <ArgumentNullException>(number != null, "number"); Contract.Requires <ArgumentNullException>(power != null, "power"); Contract.Requires <ArgumentNullException>(modulus != null, "modulus"); Contract.Requires <ArgumentException>(modulus > 0, "The modulus should be a positive number."); Contract.Requires <ArgumentException>(!power.Negative, "The power should be a non-negativen number."); LongInt <B> result = 1; // результат возведения в степень while (power > 0) { if ((power[0] & 1) == 1) { result = (result * number) % modulus; } power >>= 1; number = (number * number) % modulus; } return(result); }
/// <summary> /// Returns the next non-negative <c>LongInt<<typeparamref name="B"/>></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<<typeparamref name="B"/>></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."); return(NextInclusive(maxExclusive - 1)); }
// -------------------------------------------- // -------------- helper methods -------------- /// <summary> /// Finds the maximum number '<c>k</c>' within a given integer interval of special structure /// such that a predicate holds for this number '<c>k</c>'. /// </summary> /// <typeparam name="B">The numeric base class for the <see cref="LongInt<B>"/> numbers.</typeparam> /// <param name="predicate"> /// A predicate that holds for all numbers, starting with the leftmost bound and ending with the /// desired (sought-for) number, and only for these. /// </param> /// <returns>The maximum number within a given interval for which the <paramref name="predicate"/> holds.</returns> private static LongInt <B> Max_BinarySearch <B>(LongInt <B> leftInclusive, LongInt <B> rightInclusive, Predicate <LongInt <B> > predicate) where B : IBase, new() { Contract.Requires <ArgumentNullException>(leftInclusive != null, "leftInclusive"); Contract.Requires <ArgumentNullException>(rightInclusive != null, "rightInclusive"); Contract.Requires <ArgumentNullException>(predicate != null, "predicate"); Contract.Requires <ArgumentException>(!(leftInclusive > rightInclusive)); LongInt <B> lb = leftInclusive; LongInt <B> rb = rightInclusive; while (!(lb > rb)) { LongInt <B> mid = (lb + rb) / 2; if (predicate(mid)) { lb = mid + 1; } else { rb = mid - 1; } } return(lb - 1); }
/// <summary> /// Returns the next non-negative <c>LongInt<<typeparamref name="B"/>></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<<typeparamref name="B"/>></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 <ArgumentException>(maxExclusive > 0, "The upper exclusive bound should be strictly positive."); return(NextInclusive(maxExclusive - 1)); }
/// <summary> /// Converts a <c>LongInt</c> number into a sequence of bytes. /// </summary> /// <typeparam name="B">The type specifying the digit base of the incoming <c>LongInt<B></c>. Recommended to be <c>B_256</c> for quicker conversion.</typeparam> /// <param name="number">The incoming number.</param> /// <returns>The byte array containing the same numeric values and in the same order as <paramref name="number"/> converted to base 256.</returns> public static byte[] ToByteArray <B>(this LongInt <B> number) where B : IBase, new() { Contract.Requires <ArgumentNullException>(number != null, "number"); Contract.Requires <ArgumentException>(!number.Negative, "The number should not be negative."); byte[] result; if (typeof(B) != typeof(Bases.B_256)) { LongInt <Bases.B_256> converted = number.baseConvert <Bases.B_256>(); result = new byte[converted.Length]; for (int i = 0; i < result.Length; i++) { result[i] = (byte)converted[i]; } } else { result = new byte[number.Length]; for (int i = 0; i < result.Length; i++) { result[i] = (byte)number[i]; } } return(result); }
/// <summary> /// Возвращает true, если число - свидетель простоты. /// Если false, то тестируемое число - составное. /// </summary> private static bool ___millerRabinIsPrimeWitness <B>(LongInt <B> x, LongInt <B> num, LongInt <B> t, long s) where B : IBase, new() { x = LongInt <B> .Helper.PowerIntegerModular(x, t, num); if (x == 1 || x == num - 1) { return(true); } for (int j = 0; j < s - 1; j++) { x = x * x % num; if (x == 1) { return(false); // ни одна скобка далее не разделится (см. обоснование), так что составное. } else if (x == num - 1) // эта скобка разделилась, так что это свидетель простоты. продолжаем. { return(true); } } // Ни одна скобка // не разделилась. Составное. return(false); }
/// <summary> /// Returns the next <c>LongInt<<typeparamref name="B"/>></c> /// which lies in the interval <c>[<paramref name="minInclusive"/>; <paramref name="maxExclusive"/>)</c>. /// </summary> /// <param name="minInclusive">The lower inclusive bound of generated numbers.</param> /// <param name="maxExclusive">The upper exclusive bound of generated numbers.</param> /// <returns> /// A non-negative <c>LongInt<<typeparamref name="B"/>></c> number /// which lies in the interval <c>[<paramref name="minInclusive"/>; <paramref name="maxExclusive"/>)</c>. /// </returns> public LongInt <B> Next(LongInt <B> minInclusive, LongInt <B> maxExclusive) { Contract.Requires <ArgumentNullException>(minInclusive != null, "minInclusive"); Contract.Requires <ArgumentNullException>(maxExclusive != null, "maxExclusive"); Contract.Requires <ArgumentException>(minInclusive < maxExclusive, "The minimum inclusive bound should be less than the maximum exclusive."); return(minInclusive + this.Next(maxExclusive - minInclusive)); }
/// <summary> /// Performs a Solovay-Strassen stochastic primality test of a long integer number /// and returns the probability that the number is composite. /// </summary> /// <typeparam name="B">A class specifying the digit base of <c>LongInt<<typeparamref name="B"/></c> type.</typeparam> /// <param name="num">A number, bigger than 1, to test for primality.</param> /// <param name="gen"> /// A bounded <c>LongInt<<typeparamref name="B"/></c> random generator. /// For probability estimations to be correct, this generator should guarantee uniform distribution /// for any given interval. /// </param> /// <param name="rounds"> /// A positive number of testing rounds. Recommended to be more than <c>log2(<paramref name="num"/>)</c>. /// </param> /// <returns> /// The probability that the <paramref name="num"/> is composite. /// Equals to <c>2^(-<paramref name="rounds"/>)</c>, which is /// worse than for <see cref="IsPrime_MillerRabin<B>"/>. /// </returns> public static double IsPrime_SolovayStrassen <B>(this LongInt <B> num, IRandomBounded <LongInt <B> > gen, long rounds) where B : IBase, new() { Contract.Requires <ArgumentNullException>(num != null, "num"); Contract.Requires <ArgumentNullException>(gen != null, "gen"); Contract.Requires <ArgumentOutOfRangeException>(num > 1, "The tested number should be bigger than 2."); Contract.Requires <ArgumentOutOfRangeException>(rounds > 0, "The number of rounds should be positive."); if (num.IsEven) { if (num == 2) { return(0); } else { return(1); } } else if (num == 3) { return(0); } LongInt <B> half = (num - 1) / 2; for (long i = 0; i < rounds; i++) { LongInt <B> rnd = gen.Next(2, num); int jacobiSymbol = WhiteMath <LongInt <B>, CalcLongInt <B> > .JacobiSymbol(rnd, num); // Символ Якоби равняется нулю, значит, числа не взаимно простые // значит, наше число составное. if (jacobiSymbol == 0) { return(1); } // Иначе еще вот что посмотрим. LongInt <B> powered = LongInt <B> .Helper.PowerIntegerModular(rnd, half, num); if (jacobiSymbol == 1 && powered != 1 || jacobiSymbol == -1 && powered != num - 1) { return(1); } } return(Math.Pow(2, -rounds)); }
/// <summary> /// Decrypts a long integer number using the RSA algorithm. /// </summary> /// <typeparam name="B">An implementation of <c>IBase</c> interface which specifies the digit base of <c>LongInt<<typeparamref name="B"/>></c> numbers.</typeparam> /// <typeparam name="E">An implementation of <see cref="IBase"/> interface which specifies the digit base of the public exponent. Should be a power of 2 for faster encryption.</typeparam> /// <param name="number">The number to encrypt.</param> /// <param name="publicKey">The public key of the RSA algorithm. Should be a product of two prime numbers.</param> /// <param name="secretExponent">The secret exponent of the RSA algorithm.</param> /// <remarks>If <paramref name="secretExponent"/> has digit base which is a power of 2, the decryption process will go faster.</remarks> /// <returns>The result of RSA decryption.</returns> public static LongInt <B> Decrypt <B, E>(LongInt <B> number, LongInt <B> publicKey, LongInt <E> secretExponent) where B : IBase, new() where E : IBase, new() { Contract.Requires <ArgumentNullException>(number != null, "number"); Contract.Requires <ArgumentNullException>(publicKey != null, "publicKey"); Contract.Requires <ArgumentException>(!number.Negative, "The decrypted number should not be negative."); Contract.Requires <ArgumentException>(!publicKey.Negative, "The public key should not be negative."); Contract.Requires <ArgumentException>(secretExponent > 0, "The secret exponent should be positive."); return(LongInt <B> .Helper.PowerIntegerModular(number, secretExponent, publicKey)); }
//--------------------------------------------------------------- //---------------------NUMBER DIVISION--------------------------- //--------------------------------------------------------------- /// <summary> /// Performs the integral division of two long integer numbers. /// </summary> /// <param name="one">The first LongInt number.</param> /// <param name="two">The second LongInt number.</param> /// <returns>The result of integral division without the remainder.</returns> public static LongInt <B> Div(LongInt <B> one, LongInt <B> two) { Contract.Requires <ArgumentNullException>(one != null, "one"); Contract.Requires <ArgumentNullException>(two != null, "two"); Contract.Ensures(Contract.ForAll(Contract.Result <LongInt <B> >().Digits, x => (x >= 0))); LongInt <B> junk; return (Div(one, two, out junk)); }
/// <summary> /// Calculates a public exponent on the basis of /// a pair of primes which form the RSA secret key and /// the number chosen as public exponent. /// </summary> /// <typeparam name="B">An implementation of <c>IBase</c> interface which specifies the digit base of <c>LongInt<<typeparamref name="B"/>></c> numbers.</typeparam> /// <param name="secretKey">A pair of primes which form the RSA secret key.</param> /// <returns>The secret exponent of the RSA algorithm.</returns> public static LongInt <B> GetSecretExponent <B>(Point <LongInt <B> > secretKey, LongInt <B> publicExponent) where B : IBase, new() { Contract.Requires <ArgumentNullException>(publicExponent != null, "publicExponent"); Contract.Requires <ArgumentNullException>(secretKey.X != null, "secretKey.X"); Contract.Requires <ArgumentNullException>(secretKey.Y != null, "secretKey.Y"); LongInt <B> totient = LongInt <B> .Helper.MultiplyFFTComplex(secretKey.X - 1, secretKey.Y - 1); return (WhiteMath <LongInt <B>, CalcLongInt <B> > .MultiplicativeInverse(publicExponent, totient)); }
//! Main constructor. /*! * \param _groups Number of groups. * \param _players Number of players per gruop (total of players = _groups * _players). * \param _weeks Number of weeks. */ public GolfersLongIntCostStrategy(int _groups, int _players, int _weeks) { groups = _groups; players = _players; weeks = _weeks; alldiff = new LongInt(TL, 0); //new_partner = new LongInt(TL, 0); global_partnership = new LongInt(TL, 0); global_partners = new LongInt[TP + 1]; init(global_partners, TL, 0); group_partners = new LongInt[TP + 1]; init(group_partners, TL, 0); }
private static bool difCheck(int BASE, IList <int> res, IList <int> op1, IList <int> op2) { LongInt <B> result = new LongInt <B>(BASE, res, false); LongInt <B> oper1 = new LongInt <B>(BASE, op1, false); LongInt <B> oper2 = new LongInt <B>(BASE, op2, false); if (oper1 - oper2 != result) { // Console.WriteLine("DIF.FAIL: {0} - {1} != {2}", oper1, oper2, result); return(false); } return(true); }
//! Computes the cost of a solution (configuration) /*! * \param solution Solution (configuration) * \return Cost of the given configuration. */ public int solutionCost(Solution solution) { int golfers = TP; //players * groups; int table_length = TL; //golfers / 32 + 1; // how long must be the LongInt init(global_partners, table_length, 0); init(group_partners, table_length, 0); alldiff.deactivateAll(); int cost = 0; for (int w = 0; w < weeks; w++) { for (int g = 0; g < groups; g++) { int start_tournament = (w * TP) + (g * players); int end_tournament = start_tournament + players; for (int i = start_tournament; i < end_tournament; i++) { for (int j = start_tournament; j < end_tournament; j++) { alldiff.activate(solution[i] - 1); // 0-based if (i != j) { //new_partner.deactivateAll(); //new_partner.clearBits();// LongInt new_partner (table_length, 0); //new_partner.activate(configuration[j]); //group_partners[configuration[i]] = group_partners[configuration[i]] | new_partner; group_partners[solution[i]].activate(solution[j] - 1); } } } } for (int i = 0; i < global_partners.Length; i++) { global_partnership.deactivateAll(); global_partnership = global_partners[i] & group_partners[i]; cost += global_partnership.bitCount(); global_partners[i] = global_partners[i] | group_partners[i]; } init(group_partners, table_length, 0); //cout << alldiff.toString() << endl; // all differents cost //int bc = alldiff.bitCount(); cost += (golfers - alldiff.bitCount()) * 10; // Penalization alldiff.deactivateAll(); } // O ( p^2 * g * w ) = O ( p * n ) return(cost); }
/// <summary> /// Performs a Miller-Rabin stochastic primality test of a long integer number /// and returns the probability that the number is composite. /// </summary> /// <typeparam name="B">A class specifying the digit base of <c>LongInt<<typeparamref name="B"/></c> type.</typeparam> /// <param name="num">The number to test for primality. Should be more than 1.</param> /// <param name="gen"> /// A bounded <c>LongInt<<typeparamref name="B"/></c> random generator. /// For probability estimations to be correct, this generator should guarantee uniform distribution /// for any given interval. /// </param> /// <param name="rounds"> /// A positive number of testing rounds. Recommended to be more than <c>log2(<paramref name="num"/>)</c>. /// </param> /// <returns>The probability that the <paramref name="num"/> is composite.</returns> public static double IsPrime_MillerRabin <B>(this LongInt <B> num, IRandomBounded <LongInt <B> > gen, long rounds) where B : IBase, new() { Contract.Requires <ArgumentNullException>(num != null, "num"); Contract.Requires <ArgumentNullException>(gen != null, "gen"); Contract.Requires <ArgumentOutOfRangeException>(num > 1, "The number to test should be bigger than 1."); Contract.Requires <ArgumentOutOfRangeException>(rounds > 0, "The number of rounds should be positive."); if (num.IsEven) { if (num == 2) { return(0); } else { return(1); } } else if (num == 3) { return(0); } // Представим число num - 1 в виде // // num - 1 = 2^s * t LongInt <B> t; long s; ___millerRabinFactorize(num - 1, out t, out s); // ------------------------ // А теперь - куча раундов. // ------------------------ for (int i = 0; i < rounds; i++) { LongInt <B> x = gen.Next(2, num - 1); if (!___millerRabinIsPrimeWitness(x, num, t, s)) { return(1); } } return(Math.Pow(4, -rounds)); }
/* * if n < 1,373,653, it is enough to test a = 2 and 3; * if n < 9,080,191, it is enough to test a = 31 and 73; * if n < 4,759,123,141, it is enough to test a = 2, 7, and 61; * if n < 2,152,302,898,747, it is enough to test a = 2, 3, 5, 7, and 11; * if n < 3,474,749,660,383, it is enough to test a = 2, 3, 5, 7, 11, and 13; * if n < 341,550,071,728,321, it is enough to test a = 2, 3, 5, 7, 11, 13, and 17. * */ /// <summary> /// Performs a Miller's deterministic prime test on a number. /// Goes over all numbers under the <c>floor(ln^2(<paramref name="num"/>))</c> boundary. /// </summary> /// <typeparam name="B"> /// A class specifying the digit base of <c>LongInt<<typeparamref name="B"/></c> type. /// The base should be an integer power of two. /// </typeparam> /// <remarks>This test relies upon Riemann's Generalized Hypothesis, which still remains unproven. Use with caution.</remarks> /// <param name="num">A number, bigger than 1, to test for primality.</param> /// <returns>True if the number is prime according to the test, false otherwise.</returns> public static bool IsPrime_Miller <B>(this LongInt <B> num) where B : IBase, new() { Contract.Requires <ArgumentException>(LongInt <B> .BASE_is_power_of_two, "The digit base of the number should be a strict power of two."); Contract.Requires <ArgumentNullException>(num != null, "num"); Contract.Requires <ArgumentOutOfRangeException>(num > 1, "The tested number should be bigger than 1."); if (num.IsEven) { if (num == 2) { return(true); } else { return(false); } } else if (num == 3) { return(true); } // Представим число num - 1 в виде // // num - 1 = 2^s * t LongInt <B> t; long s; LongInt <B> numDecremented = num - 1; ___millerRabinFactorize(numDecremented, out t, out s); LongInt <B> upperBound = WhiteMath <LongInt <B>, CalcLongInt <B> > .Min(num.LengthInBinaryPlaces *num.LengthInBinaryPlaces, numDecremented); for (LongInt <B> i = 2; i <= upperBound; i++) { if (!___millerRabinIsPrimeWitness(i, num, t, s)) { return(false); } } return(true); }
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); }
/// <summary> /// Creates a pair of two primes which, being multiplied one by another, /// produce a public key of desired length for the RSA algorithm. /// </summary> /// <typeparam name="B">An implementation of <c>IBase</c> interface which specifies the digit base of <c>LongInt<<typeparamref name="B"/>></c> numbers.</typeparam> /// <param name="digits">The desired number of digits in the public key.</param> /// <param name="randomGenerator">A random generator for long integer numbers.</param> /// <param name="primalityTest"></param> /// <returns></returns> public static Point <LongInt <B> > GetKey <B>(int digits, IRandomBounded <LongInt <B> > randomGenerator = null, Func <LongInt <B>, bool> primalityTest = null) where B : IBase, new() { Contract.Requires <ArgumentOutOfRangeException>(digits > 1, "The amount of digits in the key should be more than 1."); /* * Contract.Ensures( * (Contract.Result<Point<LongInt<B>>>().X * Contract.Result<Point<LongInt<B>>>().Y) * .Length == digits); */ long bits = (long)Math.Ceiling(Math.Log(LongInt <B> .BASE, 2)); // сколько бит занимает BASE if (randomGenerator == null) { randomGenerator = new RandomLongIntModular <B>(new RandomMersenneTwister()); } if (primalityTest == null) { primalityTest = (x => __isPrimeOptimized(x)); } LongInt <B> firstPrime, secondPrime; int half = digits / 2; // На текущий момент длина ключа может оказаться МЕНЬШЕ // запланированной. Сделать так, чтобы она всегда была одна. // Нижеуказанный генератор тоже снести. IRandomBoundedUnbounded <int> tmp = new RandomCryptographic(); do { firstPrime = new LongInt <B>(half, tmp, false); }while (!primalityTest(firstPrime)); do { secondPrime = new LongInt <B>(digits - half, tmp, false); }while (!primalityTest(secondPrime)); return(new Point <LongInt <B> >(firstPrime, secondPrime)); }
/// <summary> /// Performs a deterministic primality test on a LongInt number. /// Usually takes an enormous amount of time and is never used in practice. /// </summary> /// <typeparam name="B">A class specifying the digit base of <c>LongInt<<typeparamref name="B"/></c> type.</typeparam> /// <param name="num">A number, bigger than 1, to test for primality.</param> /// <returns> /// True if the number is prime, false otherwise. Nevertheless, if the <paramref name="num"/> is big enough, you aren't to expect this method to return anything. /// It will run until the Universe collapses. /// </returns> public static bool IsPrime_TrialDivision <B>(this LongInt <B> num) where B : IBase, new() { Contract.Requires <ArgumentNullException>(num != null, "num"); Contract.Requires <ArgumentOutOfRangeException>(num > 1, "The tested number should be bigger than 1."); LongInt <B> sqrtNum = LongInt <B> .Helper.SquareRootInteger(num); for (LongInt <B> i = 2; i <= sqrtNum + 1; ++i) { if (num % i == 0) { return(false); } } return(true); }
/// <summary> /// Раскладывает четное число в произведение 2^s * t. /// </summary> private static void ___millerRabinFactorize <B>(LongInt <B> number, out LongInt <B> t, out long s) where B : IBase, new() { // Число должно быть четным. // ------------------------- Contract.Requires(number.IsEven); s = 0; // показатель степени вряд ли будет больше 9223372036854775807, можно long :-) while (number.IsEven) { number >>= 1; s++; } t = number; }
//--------------------------------------------------------------- //---------------------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); }
/// <summary> /// Treats a sequence of <c>LongInt<<typeparamref name="B"/>></c> numbers as /// a single big number which has been encrypted modulo <paramref name="publicKey"/> and /// returns the result of decryption. /// </summary> /// <typeparam name="B">An implementation of <c>IBase</c> interface which specifies the digit base of <c>LongInt<<typeparamref name="B"/>></c> numbers.</typeparam> /// <typeparam name="E">An implementation of <see cref="IBase"/> interface which specifies the digit base of the public exponent. Should be a power of 2 for faster encryption.</typeparam> /// <param name="numberSequence">A sequence of encrypted numbers which are treated as a single number which was bigger than the <paramref name="publicKey"/> during the encryption process.</param> /// <param name="publicKey">The public key which was used during the encryption process. Should be a product of two primes.</param> /// <param name="secretExponent">The secret exponent of the RSA algorithm.</param> /// <param name="bnem">Options which were used during the encryption process. Wrong options will result in a wrong decryption.</param> /// <remarks>If <paramref name="secretExponent"/> has digit base which is a power of 2, the decryption process will go faster.</remarks> /// <returns>With all conditions of the RSA met and correct options specified, the method returns the decrypted number.</returns> public static LongInt <B> DecryptAsSingle <B, E>(IEnumerable <LongInt <B> > numberSequence, LongInt <B> publicKey, LongInt <E> secretExponent, BigNumberEncryptionMethod bnem) where B : IBase, new() where E : IBase, new() { Contract.Requires <ArgumentNullException>(numberSequence != null, "numberSequence"); Contract.Requires <ArgumentException>(numberSequence.Count() > 0, "The sequence should contain at least one encrypted number."); Contract.Requires <ArgumentException>(secretExponent > 0, "The secret exponent should be positive."); Contract.Requires(Contract.ForAll(numberSequence, x => x != null), "At least one number in the sequence is null."); Contract.Requires(Contract.ForAll(numberSequence, x => !x.Negative), "At least one number in the sequence is negative."); int count = numberSequence.Count(); if (count == 1) { return(Decrypt(numberSequence.Single(), publicKey, secretExponent)); } List <LongInt <B> > list = new List <LongInt <B> >(count); foreach (LongInt <B> encryptedNumber in numberSequence) { list.Add(Decrypt(encryptedNumber, publicKey, secretExponent)); } if (bnem == BigNumberEncryptionMethod.Splitting) { return(new LongInt <B>(LongInt <B> .BASE, list.SelectMany(x => x.Digits).ToList(), false)); } else if (bnem == BigNumberEncryptionMethod.Division) { LongInt <B> result = list[list.Count - 1]; for (int i = list.Count - 2; i >= 0; --i) { result = result * publicKey + list[i]; } return(result); } throw new EnumFattenedException("Big number encryption method enum has been fattened, decryption process stuck."); }
public static LongInt <B> PowerIntegerModularSlow <B>(LongInt <B> number, LongInt <B> power, LongInt <B> modulus) where B : IBase, new() { Contract.Requires <ArgumentNullException>(number != null, "number"); Contract.Requires <ArgumentNullException>(power != null, "power"); Contract.Requires <ArgumentNullException>(modulus != null, "modulus"); if (power == 0) { return(1); } LongInt <B> res = number % modulus; for (LongInt <B> i = 1; i < power; ++i) { res = res * number % modulus; } return(res); }
/// <summary> /// Performs fast modular exponentiation of a <c>LongInt</c> number modulo another number. /// </summary> /// <typeparam name="B">A type specifying the numeric base of <c>LongInt</c> digits.</typeparam> /// <param name="number">A <c>LongInt</c> number to be exponentiated.</param> /// <param name="power">A non-negative exponent.</param> /// <param name="modulus">The modulus of the operation.</param> /// <returns>The result of raising <paramref name="number"/> to power <paramref name="power"/> modulo <paramref name="modulus"/>.</returns> public static LongInt <B> PowerIntegerModular <B>(LongInt <B> number, ulong power, LongInt <B> modulus) where B : IBase, new() { Contract.Requires <ArgumentNullException>(number != null, "number"); Contract.Requires <ArgumentNullException>(modulus != null, "modulus"); LongInt <B> result = 1; // результат возведения в степень while (power > 0) { if ((power & 1) == 1) { result = (result * number) % modulus; } power >>= 1; number = (number * number) % modulus; } return(result); }