Пример #1
0
 /// <summary>
 /// Checks whether the value of the current <c>Numeric&lt;<typeparamref name="T"/>,<typeparamref name="C"/>&gt;</c>
 /// object is equal to the value of another <c>Numeric&lt;<typeparamref name="T"/>,<typeparamref name="C"/>&gt;</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));
 }
Пример #2
0
        // ----------------------------------
        // ---------- 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));
        }
Пример #3
0
 public static bool isInfinity(Numeric <T, C> one)
 {
     return(calc.isPosInf(one) || calc.isNegInf(one));
 }
Пример #4
0
 public static bool isPositiveInfinity(Numeric <T, C> one)
 {
     return(calc.isPosInf(one));
 }
Пример #5
0
        // --------------------------------------
        // ---------------- NaN and Infinities checking
        // --------------------------------------

        public static bool isNaN(Numeric <T, C> one)
        {
            return(calc.isNaN(one));
        }
Пример #6
0
        /// <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;
                }
            }
        }
Пример #7
0
        /// <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);
        }