Esempio n. 1
0
        /// <summary>
        /// Finds the maximum number '<c>k</c>' within a given integer interval such that a predicate
        /// holds for this number '<c>k</c>'.
        /// </summary>
        /// <typeparam name="T">The type of numbers contained inside the interval.</typeparam>
        /// <typeparam name="C">A calculator for the <typeparamref name="T"/> type.</typeparam>
        /// <param name="interval">
        /// An integer interval, containing at least one number for which the <paramref name="predicate"/>
        /// holds.
        /// </param>
        /// <param name="predicate">
        /// A predicate that should hold for the desired number and not for every number that is bigger and located
        /// inside the interval.
        /// </param>
        /// <remarks>
        /// This method takes <c>O(n)</c> time for intervals of length '<c>n</c>'. Thus, it usually works significantly
        /// slower than <see cref="Max_BinarySearch&lt;T,C&gt;"/>, but does not put any restrictions
        /// on the <paramref name="interval"/> object passed.
        /// </remarks>
        /// <returns>
        /// A <c>PotentialResult&lt;Numeric&lt;T, C&gt;&gt;</c> object which will store
        /// the maximum number within a given interval for which the <paramref name="predicate"/> holds, if the algorithm
        /// finds one.
        /// </returns>
        public static PotentialResult <Numeric <T, C> > Max_LinearSearch <T, C>(this BoundedInterval <T, C> interval, Predicate <T> predicate)
            where C : ICalc <T>, new()
        {
            Contract.Requires <ArgumentException>(Numeric <T, C> .Calculator.isIntegerCalculator, "This method works only for integer numbers.");
            Contract.Requires <ArgumentNullException>(predicate != null, "predicate");
            Contract.Requires <ArgumentException>(!interval.IsEmptyInteger, "The interval should contain at least one integer point.");

            BoundedInterval <T, C> inclusive = interval.ToInclusiveIntegerInterval();

            bool found = false;

            Numeric <T, C> max = Numeric <T, C> .Zero;

            for (Numeric <T, C> current = inclusive.LeftBound; current <= inclusive.RightBound; ++current)
            {
                if (predicate(current))
                {
                    found = true;
                    max   = current;
                }
            }

            if (!found)
            {
                return(PotentialResult <Numeric <T, C> > .CreateFailure());
            }
            else
            {
                return(PotentialResult <Numeric <T, C> > .CreateSuccess(max));
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Finds the maximum number '<c>k</c>' within a given integer interval of special structure
        /// such that a predicate holds for this number '<c>k</c>'.
        /// </summary>
        /// <typeparam name="T">The type of numbers contained inside the interval.</typeparam>
        /// <typeparam name="C">A calculator for the <typeparamref name="T"/> type.</typeparam>
        /// <param name="interval">
        /// <para>
        /// An integer interval which has a structure such that all numbers, starting with the leftmost inclusive bound and
        /// ending with the desired (sought-for) number, satisfy the predicate (and only these).
        /// In other words, the leftmost 'tail' of the interval should satisfy the predicate,
        /// and the rightmost 'tail' should not; the rightmost tail, though, may be empty.
        /// </para>
        /// <para>
        /// It should be KNOWN that the interval has such structure and that at least the leftmost inclusive bound satisfies the predicate.
        /// Otherwise, the behaviour of the function is undefined.
        /// </para>
        /// </param>
        /// <param name="predicate">
        /// A predicate that should hold for all numbers, starting with the leftmost bound and ending with the
        /// desired (sought-for) number, and only for these.
        /// </param>
        /// <returns>The maximum number within a given interval for which the <paramref name="predicate"/> holds.</returns>
        public static T Max_BinarySearch <T, C>(this BoundedInterval <T, C> interval, Predicate <T> predicate)
            where C : ICalc <T>, new()
        {
            Contract.Requires <NonIntegerTypeException>(Numeric <T, C> .Calculator.isIntegerCalculator, "This method works only for integer numbers.");
            Contract.Requires <ArgumentException>(!interval.IsEmptyInteger, "The interval should contain at least one integer point.");

            Numeric <T, C> lb = (interval.IsLeftInclusive ? interval.LeftBound : interval.LeftBound + Numeric <T, C> ._1);
            Numeric <T, C> rb = (interval.IsRightInclusive ? interval.RightBound : interval.RightBound - Numeric <T, C> ._1);

            Numeric <T, C> one = Numeric <T, C> ._1;
            Numeric <T, C> two = Numeric <T, C> ._2;

            while (!(lb > rb))
            {
                Numeric <T, C> mid = (lb + rb) / two;

                if (predicate(mid))
                {
                    lb = mid + one;
                }
                else
                {
                    rb = mid - one;
                }
            }

            return(lb - one);
        }
Esempio n. 3
0
        public override bool Equals(object obj)
        {
            if (!(obj is BoundedInterval <T, C>))
            {
                return(false);
            }

            BoundedInterval <T, C> interval = (BoundedInterval <T, C>)obj;

            return
                (this.IsLeftInclusive == interval.IsLeftInclusive &&
                 this.IsRightInclusive == interval.IsRightInclusive &&
                 calc.eqv(this.RightBound, interval.RightBound) &&
                 calc.eqv(this.LeftBound, interval.LeftBound));
        }
Esempio n. 4
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);
        }