Exemple #1
0
        /// POWER INTEGER
        ///
        /// <summary>
        /// Performs the quick mathematical power operation.
        /// Works only for integer exponent values.
        ///
        /// WARNING! The power value here should be an integer number,
        /// that is, the calculator method 'integerPower(power)' should
        /// return the same value as power. Otherwise, the result
        /// would be unpredictable AND INCORRECT.
        /// </summary>
        /// <param name="number">The number to raise to the power.</param>
        /// <param name="power">The INTEGER exponent of the power.</param>
        /// <returns>The number raised to the integer power.</returns>
        public static T PowerInteger_Generic(T number, T power)
        {
            power = calc.intPart(power);

            if (power == Numeric <T, C> .Zero)
            {
                return(calc.fromInt(1));
            }

            else if (power < Numeric <T, C> .Zero)
            {
                if (number <= Numeric <T, C> .Zero)
                {
                    throw new ArgumentException("Cannot raise a non-positive number to a negative power.");
                }
                return(calc.div(calc.fromInt(1), PowerInteger_Generic(number, calc.negate(power))));
            }

            // Ноль в любой степени будет ноль:

            if (calc.eqv(number, calc.zero))
            {
                return(calc.zero);
            }

            Numeric <T, C> res  = calc.fromInt(1);            // результат возведения в степень
            Numeric <T, C> copy = calc.getCopy(number);       // изменяемая копия (переданное число может быть ссылочным типом)

            T two = calc.fromInt(2);
            T one = calc.fromInt(1);

            while (power > Numeric <T, C> .Zero)
            {
                // Если остаток от деления на 2 равен 1
                if (calc.eqv(WhiteMath <T, C> .Modulus(power, two), one))
                {
                    res *= copy;
                }

                copy *= copy;
                power = calc.intPart(calc.div(power, two));
            }

            return(res);
        }
Exemple #2
0
        /// <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);
            }
        }
Exemple #3
0
        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))));
        }
Exemple #4
0
        ///-----------------------------------
        ///----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);
        }
Exemple #5
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        /// <summary>
        /// Finds the greatest common divisor of two integer-like numbers
        /// using the simple Euclid algorithm.
        ///
        /// The calculator for the numbers is recommended to provide reasonable implementation
        /// of the remainder operation (%) - otherwise, the function
        /// Modulus from whiteMath class will be used.
        ///
        /// Will work with floating-point type numbers only if they are integers;
        /// In case of division errors the result will be rounded and thus not guaranteed.
        /// </summary>
        /// <param name="one"></param>
        /// <param name="two"></param>
        /// <returns></returns>
        public static T GreatestCommonDivisor(T one, T two)
        {
            Contract.Requires <ArgumentException>(one != Numeric <T, C> .Zero && two != Numeric <T, C> .Zero, "None of the numbers may 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);

            // T может быть ссылочным типом, поэтому необходимо
            // предостеречь объекты от изменения
            // а также отсечь знаки по необходимости

            T oneTmp;
            T twoTmp;

            if (calc.mor(calc.zero, one))
            {
                oneTmp = calc.negate(one);
            }
            else
            {
                oneTmp = calc.getCopy(one);
            }

            if (calc.mor(calc.zero, two))
            {
                twoTmp = calc.negate(two);
            }
            else
            {
                twoTmp = calc.getCopy(two);
            }

            try
            {
                while (!calc.eqv(oneTmp, calc.zero) && !calc.eqv(twoTmp, calc.zero))
                {
                    if (calc.mor(oneTmp, twoTmp))
                    {
                        oneTmp = calc.rem(oneTmp, twoTmp);
                    }
                    else
                    {
                        twoTmp = calc.rem(twoTmp, oneTmp);
                    }
                }
            }
            catch   // calculator throws exception - working with fp's.
            {
                oneTmp = calc.intPart(oneTmp);
                twoTmp = calc.intPart(twoTmp);

                while (!calc.eqv(oneTmp, calc.zero) && !calc.eqv(twoTmp, calc.zero))
                {
                    if (calc.mor(oneTmp, twoTmp))
                    {
                        oneTmp = WhiteMath <T, C> .Round(WhiteMath <T, C> .Modulus(oneTmp, twoTmp));
                    }
                    else
                    {
                        twoTmp = WhiteMath <T, C> .Round(WhiteMath <T, C> .Modulus(twoTmp, oneTmp));
                    }
                }
            }

            return(calc.sum(oneTmp, twoTmp));
        }
Exemple #8
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;
                }
            }
        }