/// <summary> /// Метод, добавляющий модуль в многомодульное число. /// </summary> /// <param name="comparison"></param> /// <exception cref="InvalidOperationException">Модуль уже присутствует в числе</exception> public void AddModule(Comparison.LinearComparison comparison) { if (Modules.Contains(comparison.M)) { throw new InvalidOperationException("Такой модуль уже присутствует в числе!"); } Values.Add(comparison); Values = Values.OrderByDescending(element => element.M).ToList(); }
/// <summary> /// Вычисление значения многочлена при заданном x в поле Zn. Возвращается вся получившаяся строка значений. /// Используется схема Горнера. /// </summary> /// <param name="x"></param> /// <returns></returns> public int[] GetValueArray(int x) { Comparison.LinearComparison[] ResultArray = new Comparison.LinearComparison[Coefficients.Length]; ResultArray[0] = new Comparison.LinearComparison((int)Coefficients[0].A, Module); for (int i = 1; i < Coefficients.Length; i++) { ResultArray[i] = new Comparison.LinearComparison((int)(ResultArray[i - 1].A * x + (int)Coefficients[i].A), Module); } return(ResultArray.Select(comparison => (int)comparison.A).ToArray()); }
/// <summary> /// Тест Соловея-Штрассена. Имеет числа КарлМайкла /// </summary> /// <param name="source">Число, которое необходмио протестировать</param> /// <param name="count">Число прогонов теста</param> /// <returns></returns> public static PrimalityTestResult SSPT(BigInteger source, BigInteger count) { if (count >= source) { throw new InvalidOperationException("Число прогонов теста не должно быть меньше тестируемого числа."); } if (source == 0) { return(PrimalityTestResult.Composite); } if (source == 1) { return(PrimalityTestResult.Unknown); } if (source < 0 || count <= 0) { throw new InvalidOperationException( "Тестируемое число и число его прогонов должны быть положительными числами!"); } //нам необходимо, чтобы число было нечетным, поэтому мы отсеиваем все четные числа. if (source % 2 == 0) { return(PrimalityTestResult.Composite); } BigInteger[] RestVariants = RD.UniformDistribution(2, source - 1, count); //отрезок [2,n-1] for (int i = 0; i < count; i++) { BigInteger CurrentValue = RestVariants[i]; if (AdvancedEuclidsalgorithm.GCDResult(CurrentValue, source) != 1) { return(PrimalityTestResult.Composite); } //значение символа якоби BigInteger jacobi = JacobiSymbol.Get(CurrentValue, source); Comparison.LinearComparison comparison = new Comparison.LinearComparison(CurrentValue, source); if (Comparison.MultiplicativeInverse.BinaryPowLinearComparison(comparison, (source - 1) / 2).LeastModulo != jacobi) { return(PrimalityTestResult.Composite); } } return(PrimalityTestResult.Unknown); }
/// <summary> /// Fermat Primality Test - тест на основе теоремы Ферма. Имеет псевдопростые числа /// </summary> /// <param name="source">Число, которое необходимо проверить на простотоу</param> /// /// /// <param name="count">Число прогонов теста. Чем больше, тем точнее ответ.</param> /// <returns></returns> /// <exception cref="InvalidOperationException"></exception> public static PrimalityTestResult FPT(int source, int count) { if (count >= source) { throw new InvalidOperationException("Число прогонов теста должно быть меньше тестируемого числа."); } switch (source) { case 0: return(PrimalityTestResult.Composite); case 1: throw new InvalidOperationException("Единица не является ни простым, ни составным числом."); } if (source < 0 || count <= 0) { throw new InvalidOperationException( "Тестируемое число и количество прогонов должны быть положительными числами!"); } BigInteger[] RestVariants = RD.UniformDistribution(2, source - 1, count); //отрезок [2,n-1] for (int i = 1; i <= count; i++) { BigInteger CurrentValue = RestVariants[i - 1]; if (AdvancedEuclidsalgorithm.GCDResult(CurrentValue, source) != 1) { return(PrimalityTestResult.Composite); } Comparison.LinearComparison comparison = new Comparison.LinearComparison(CurrentValue, source); if (Comparison.MultiplicativeInverse.BinaryPowLinearComparison(comparison, source - 1).A != 1) { return(PrimalityTestResult.Composite); } } return(PrimalityTestResult.Unknown); }
/// <summary> /// Тест Рабина Миллера. Имеет сильно псевдопростые числа /// </summary> /// <param name="source"></param> /// <param name="count"></param> /// <returns></returns> public static PrimalityTestResult MRPT(int source, int count) { if (count >= source) { throw new InvalidOperationException("Число прогонов теста не должно быть меньше тестируемого числа."); } switch (source) { case 0: return(PrimalityTestResult.Composite); case 1: throw new InvalidOperationException("Единица не является ни простым, ни составным числом."); } if (source < 0 || count <= 0) { throw new InvalidOperationException( "Тестируемое число и число его прогонов должны быть положительными числами!"); } //нам необходимо, чтобы число было нечетным, поэтому мы отсеиваем все четные числа. if (source % 2 == 0) { return(PrimalityTestResult.Composite); } int t = source - 1; int s = 0; while (t % 2 == 0) { t /= 2; s++; } //n-1 = (2^s) * t BigInteger[] RestVariants = RD.UniformDistribution(2, source - 1, count); //отрезок [2,n-1] for (int i = 0; i < count; i++) { BigInteger CurrentValue = RestVariants[i]; if (AdvancedEuclidsalgorithm.GCDResult(CurrentValue, source) != 1) { return(PrimalityTestResult.Composite); } //значение символа якоби Comparison.LinearComparison comparison = new Comparison.LinearComparison(CurrentValue, source); if (BigInteger.Abs((comparison = Comparison.MultiplicativeInverse.BinaryPowLinearComparison(comparison, t)) .LeastModulo) == 1) { continue; } while (s != 1) { comparison = Comparison.MultiplicativeInverse.BinaryPowLinearComparison(comparison, 2); if (comparison.LeastModulo == -1) { break; } if (--s == 0) { return(PrimalityTestResult.Composite); } } } return(PrimalityTestResult.Unknown); }