/// <summary> /// Checks whether the value of the current <c>Numeric<<typeparamref name="T"/>,<typeparamref name="C"/>></c> /// object is equal to the value of another <c>Numeric<<typeparamref name="T"/>,<typeparamref name="C"/>></c> object. /// </summary> /// <param name="obj">The object to test for equality with.</param> /// <returns>True if values are equal, false otherwise.</returns> public bool Equals(Numeric <T, C> obj) { return(calc.eqv(this.value, obj.value)); }
// ---------------------------------- // ---------- COMPARING ------------- // ---------------------------------- // IComparable /// <summary> /// Compares the current number to another. /// </summary> /// <param name="another">A value for the current number to compare with.</param> /// <returns> /// A positive value if the current number is bigger than the number passed, /// a zero value if they are equal, and a negative value if the second number is bigger. /// </returns> public int CompareTo(Numeric <T, C> another) { return(_compinstnc.Invoke(this, another)); }
public static bool isInfinity(Numeric <T, C> one) { return(calc.isPosInf(one) || calc.isNegInf(one)); }
public static bool isPositiveInfinity(Numeric <T, C> one) { return(calc.isPosInf(one)); }
// -------------------------------------- // ---------------- NaN and Infinities checking // -------------------------------------- public static bool isNaN(Numeric <T, C> one) { return(calc.isNaN(one)); }
/// <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; } } }
/// <summary> /// Performs an Extended Euclidean algorithms on two positive numbers <c>one, two</c>, /// calculates their GCD and finds such integer <c>x, y</c> which satisfy Bezout's identity <c>one*x + two*y = 1</c>. /// </summary> /// <param name="one">The first number.</param> /// <param name="two">The second number.</param> /// <param name="x">The first coefficient in Bezout's identity <c>one*x + two*y = 1</c>.</param> /// <param name="y">The second coefficient in Bezout's identity <c>one*x + two*y = 1</c>.</param> /// <returns>The greatest common divisor of <paramref name="one"/> and <paramref name="two"/>.</returns> public static T ExtendedEuclideanAlgorithm(T one, T two, out T x, out T y) { Contract.Requires <NonIntegerTypeException>(Numeric <T, C> .Calculator.isIntegerCalculator, "The method works only for integer numeric types."); Contract.Requires <ArgumentException>(one != Numeric <T, C> .Zero && two != Numeric <T, C> .Zero, "None of the numbers should be zero."); Contract.Ensures(Contract.Result <T>() > Numeric <T, C> .Zero); Contract.Ensures((Numeric <T, C>)one % Contract.Result <T>() == Numeric <T, C> .Zero); Contract.Ensures((Numeric <T, C>)two % Contract.Result <T>() == Numeric <T, C> .Zero); // Uncomment only on tests // because int often overflows here. // Contract.Ensures((Numeric<T, C>)one * Contract.ValueAtReturn<T>(out x) + (Numeric<T, C>)two * Contract.ValueAtReturn<T>(out y) == Contract.Result<T>()); if (calc.mor(two, one)) { return(ExtendedEuclideanAlgorithm(two, one, out y, out x)); } bool oneLessThanZero = calc.mor(calc.zero, one); bool twoLessThanZero = calc.mor(calc.zero, two); if (oneLessThanZero || twoLessThanZero) { if (oneLessThanZero && twoLessThanZero) { T res = ExtendedEuclideanAlgorithm(calc.negate(one), calc.negate(two), out x, out y); x = calc.negate(x); y = calc.negate(y); return(res); } else if (oneLessThanZero) { T res = ExtendedEuclideanAlgorithm(calc.negate(one), two, out x, out y); x = calc.negate(x); return(res); } else { T res = ExtendedEuclideanAlgorithm(one, calc.negate(two), out x, out y); y = calc.negate(y); return(res); } } Numeric <T, C> a = one; Numeric <T, C> b = two; Numeric <T, C> // tmp, curX = Numeric <T, C> .Zero, curY = Numeric <T, C> ._1, lastX = Numeric <T, C> ._1, lastY = Numeric <T, C> .Zero; while (b != Numeric <T, C> .Zero) { Numeric <T, C> quotient = a / b; tmp = a; a = b; b = tmp % b; tmp = curX; curX = lastX - quotient * curX; lastX = tmp; tmp = curY; curY = lastY - quotient * curY; lastY = tmp; } x = lastX; y = lastY; return(a); }