/// <summary> /// Нормализует число, делит числитель и знаменатель на НОД, /// делает числитель положительным. /// </summary> private void normalize() { T gcd = WhiteMath <T, C> .GreatestCommonDivisor(WhiteMath <T, C> .Abs(num), WhiteMath <T, C> .Abs(denom)); if (calc.eqv(gcd, calc.zero)) { return; // for infinity-checking cases } num = calc.div(num, gcd); denom = calc.div(denom, gcd); // Если знаменатель меньше нуля if (calc.mor(calc.zero, denom)) { num = calc.negate(num); denom = calc.negate(denom); } }
///----------------------------------- ///----ARITHMETIC OPERATORS----------- ///----------------------------------- public static Rational <T, C> operator +(Rational <T, C> one, Rational <T, C> two) { if (one is Infinities) { if (two is Infinities) { if (one.GetType().Equals(two.GetType())) { return(one); } else { return(NaN); } } return(one); } else if (two is Infinities) { return(two + one); } Rational <T, C> tmp = new Rational <T, C>(); tmp.denom = WhiteMath <T, C> .LowestCommonMultiple(one.denom, two.denom, WhiteMath <T, C> .GreatestCommonDivisor(one.denom, two.denom)); tmp.num = calc.sum(calc.mul(one.num, calc.div(tmp.denom, one.denom)), calc.mul(two.num, calc.div(tmp.denom, two.denom))); if (checkInf(ref tmp)) { tmp.normalize(); } return(tmp); }
public static Dictionary <T, List <T> > RootsOfUnity(T module, IEnumerable <T> rootDegrees, BoundedInterval <T, C>?searchInterval = null) { Contract.Requires <NonIntegerTypeException>(Numeric <T, C> .Calculator.isIntegerCalculator, "This method supports only integral types."); Contract.Requires <ArgumentNullException>(module != null, "module"); Contract.Requires <ArgumentOutOfRangeException>(module > Numeric <T, C> ._1, "The module should be more than 1."); Contract.Requires <ArgumentOutOfRangeException>(Contract.ForAll <T>(rootDegrees, (x => x >= Numeric <T, C> ._1 && x < (Numeric <T, C>)module)), "All of the root degrees specified should be located inside the [1; N-1] interval."); if (!searchInterval.HasValue) { searchInterval = new BoundedInterval <T, C>(Numeric <T, C> .Zero, module - Numeric <T, C> ._1, true, true); } Numeric <T, C> lowerBound = searchInterval.Value.LeftBound; Numeric <T, C> upperBound = searchInterval.Value.RightBound; if (!searchInterval.Value.IsLeftInclusive) { lowerBound++; } if (!searchInterval.Value.IsRightInclusive) { upperBound--; } // Contract.Requires<ArgumentOutOfRangeException>(lowerBound > Numeric<T, C>.Zero && upperBound < module - Numeric<T, C>.CONST_1, "The search interval should be located inside the [0; N-1] interval."); // Нам нужны только уникальные значения // поэтому сгенерируем множество ISet <Numeric <T, C> > rootDegreeSet = new HashSet <Numeric <T, C> >(); foreach (T degree in rootDegrees) { rootDegreeSet.Add(degree); } // ----------------------------- bool evenModule = calc.isEven(module); // Если нижняя граница четная, и модуль четный - по любому взаимно не простые. // Значит число - делитель нуля, и не может быть корнем из единицы ни при каких условиях. // Прибавляем единицу. if (calc.isEven(lowerBound) && evenModule) { lowerBound++; } Dictionary <T, List <T> > result = new Dictionary <T, List <T> >(); for (Numeric <T, C> current = lowerBound; current <= upperBound; current++) { // Если не взаимно просты с модулем - по-любому не может быть // примитивным корнем. if (WhiteMath <T, C> .GreatestCommonDivisor(current, module) != Numeric <T, C> ._1) { goto ENDING; } // Теперь занимаемся тестированием. Numeric <T, C> currentPower = Numeric <T, C> ._1; Numeric <T, C> tmp = current; while (true) { if (tmp == Numeric <T, C> ._1) { // Проверить степень корня if (rootDegreeSet.Contains(currentPower)) { if (!result.ContainsKey(currentPower)) { result.Add(currentPower, new List <T>()); } List <T> currentDegreeRootList = result[currentPower]; currentDegreeRootList.Add(current); } goto ENDING; } else if (tmp == Numeric <T, C> .Zero) { goto ENDING; } tmp = (tmp * tmp) % module; ++currentPower; } ENDING: // Если четный модуль - надо перескочить через два. if (evenModule) { current++; } } return(result); }
public static bool operator >(Rational <T, C> one, Rational <T, C> two) { if (one is NotANumber || two is NotANumber) { return(false); } else if (one is Positive_Infinity || two is Negative_Infinity) { return(true); } else if (two is Positive_Infinity || one is Negative_Infinity) { return(false); } T denomLcm = WhiteMath <T, C> .LowestCommonMultiple(one.denom, two.denom, WhiteMath <T, C> .GreatestCommonDivisor(one.denom, two.denom)); return(calc.mor(calc.mul(one.num, calc.div(denomLcm, one.denom)), calc.mul(two.num, calc.div(denomLcm, two.denom)))); }
public static Rational <T, C> operator -(Rational <T, C> one, Rational <T, C> two) { if (one is Infinities || two is Infinities) { if (one is NotANumber || two is NotANumber) { return(NaN); } else if (one is Positive_Infinity) { if (two is Infinities) { if (two is Negative_Infinity) { return(one); } else { return(NaN); } } return(one); } else if (two is Positive_Infinity) { if (one is Infinities) { if (one is Negative_Infinity) { return(one); } else { return(NaN); } } return(NegativeInfinity); } else if (one is Negative_Infinity) { if (two is Infinities) { if (two is Positive_Infinity) { return(one); } else { return(NaN); } } return(one); } else if (two is Negative_Infinity) { if (one is Infinities) { if (one is Positive_Infinity) { return(one); } else { return(NaN); } } return(PositiveInfinity); } } Rational <T, C> tmp = new Rational <T, C>(); tmp.denom = WhiteMath <T, C> .LowestCommonMultiple(one.denom, two.denom, WhiteMath <T, C> .GreatestCommonDivisor(one.denom, two.denom)); tmp.num = calc.dif(calc.mul(one.num, calc.div(tmp.denom, one.denom)), calc.mul(two.num, calc.div(tmp.denom, two.denom))); if (checkInf(ref tmp)) { tmp.normalize(); } return(tmp); }
/// <summary> /// Returns the value of the Jacobi symbol for /// the two numbers, that is, the multiplication product /// of Legendre symbols with numerators all equal to the Jacobi symbol's /// numerator and denominators taken from the factorization /// of Jacobi symbol's denominator. /// </summary> /// <param name="num">The numerator of the Jacobi symbol.</param> /// <param name="denom">The denominator of the Jacobi symbol. Should be odd and positive.</param> /// <returns>The value of the Jacobi symbol for <paramref name="num"/> and <paramref name="denom"/>.</returns> public static int JacobiSymbol(T num, T denom) { Contract.Requires <NonIntegerTypeException>(Numeric <T, C> .Calculator.isIntegerCalculator, "The method works only for integer numeric types."); Contract.Requires <ArgumentException>(denom > Numeric <T, C> .Zero && !Numeric <T, C> .Calculator.isEven(denom), "The denominator of the Jacobi symbol should be odd and positive."); bool minus = false; // флаг минуса Numeric <T, C> x = num; Numeric <T, C> y = denom; if (y == Numeric <T, C> ._1) { return(1); } if (WhiteMath <T, C> .GreatestCommonDivisor(x, y) != Numeric <T, C> ._1) { return(0); } if (x < Numeric <T, C> .Zero) { // Надо домножить на (-1)^((y-1)/2) // Эта величина равна -1 тогда и только тогда, когда floor(y/2) - четное число. if ((y / Numeric <T, C> ._2).Even) { minus ^= true; } x = -x; } // На этом шаге ни в числителе, // ни в знаменателе не осталось отрицательных чисел. while (true) { // (x; y) = (x mod y; y) ------------------ if (x > y) { x = x % y; } // ---------- избавляемся от четности ----- int t = 0; while (x.Even) { // Надо домножить на (-1)^((y^2 - 1)/8) // Эта величина равна -1 тогда и только тогда, когда y имеет остатки 3 или 5 при делении на 8 ++t; x /= Numeric <T, C> ._2; } if (t % 2 != 0) { Numeric <T, C> rem = y % Numeric <T, C> ._8; if (rem == Numeric <T, C> ._3 || rem == Numeric <T, C> ._5) { minus ^= true; } } // ---------------------------------------- // --- Если x - единица, то надо вернуться. // ---------------------------------------- if (x == Numeric <T, C> ._1) { return(minus ? -1 : 1); } // ---------------------------------------------------- // -- x и y на этом этапе гарантированно взаимно просты // -- и нечетны, поэтому можно использовать свойство (8) из твоей тетрадочки // ---------------------------------------------------- if (x < y) { if (x % Numeric <T, C> ._4 == Numeric <T, C> ._3 && y % Numeric <T, C> ._4 == Numeric <T, C> ._3) { minus ^= true; } Numeric <T, C> tmp = x; x = y; y = tmp; } } }