public static void baseConvert(IList <int> from, IList <int> to, int fromBase, int newBase) { // проверяем, не кратное ли основание int?power; if (WhiteMath <int, CalcInt> .IsNaturalIntegerPowerOf(fromBase, newBase, out power) || WhiteMath <int, CalcInt> .IsNaturalIntegerPowerOf(newBase, fromBase, out power)) { convertPowered(from, to, fromBase, newBase, power.Value); } // в противном случае - не избежать последовательного деления. else { int k = 0; IList <int> divide = from; while (divide.CountSignificant() > 1 || divide[0] > 0) { int remainder; divide = LongIntegerMethods.DivideByInteger(fromBase, divide, newBase, out remainder); to[k++] = remainder; } } }
/// <summary> /// Gets the amount of polynom sequence's sign variations either /// at positive or negative infinity using polynom's degree and the sign of its higher coefficient. /// /// Works fast. /// </summary> /// <typeparam name="T">The type of polynom coefficients.</typeparam> /// <typeparam name="C">The calculator for the coefficients' type.</typeparam> /// <param name="list">The sequence of polynoms to be evaluated for sign variations.</param> /// <param name="negativeInfinity">If this flag is set to FALSE, the evalution is at positive infinity. Otherwise, at negative infinity.</param> /// <returns>The number of polynom's sign variations.</returns> public static int InfinitySignVariations <T, C>(this IList <Polynom <T, C> > list, bool negativeInfinity) where C : ICalc <T>, new() { int signPrev = 0; int signNew = 0; int k = 0; for (int i = 0; i < list.Count; i++) { if (list[i].Degree == 0) { signNew = WhiteMath <T, C> .Sign(list[i][0]); } else { signNew = WhiteMath <T, C> .Sign(list[i][list[i].Degree]) * (negativeInfinity ? ((list[i].Degree % 2 == 0 ? 1 : -1)) : 1); } if (signNew == 0) { continue; } else if (signNew != signPrev && signPrev != 0) { k++; } signPrev = signNew; } return(k); }
/// <summary> /// Cancels the polynom with integer coefficients by the greatest common divisor of /// its coefficients. /// /// The resulting polynom contains all the same roots, but its value range is less than /// of the current. /// /// If either some of the coefficients isn't integer or GCD = 1, the current polynom will be returned. /// <returns>The polynom with cancelled coefficients containing all the same roots.</returns> /// </summary> public Polynom <T, C> IntegerCoefficientsCancel() { ArgumentException ex = new ArgumentException("Only polynoms with integer coefficients can be cancelled."); if (coefficients[0].FractionalPart != Numeric <T, C> .Zero) { throw ex; } Numeric <T, C> gcd = coefficients[0]; for (int i = 1; i < coefficients.Length; i++) { if (coefficients[i].FractionalPart != Numeric <T, C> .Zero) { throw ex; } else { gcd = WhiteMath <T, C> .GreatestCommonDivisor(gcd, coefficients[i]); } } Numeric <T, C>[] newCoefs = new Numeric <T, C> [coefficients.Length]; for (int i = 0; i < coefficients.Length; i++) { newCoefs[i] = this.coefficients[i] / gcd; } return(new Polynom <T, C>(newCoefs)); }
/// <summary> /// Filters the surges in a sequence whose absolute values deviate from the specified positive value by a /// positive factor specified. /// </summary> /// <typeparam name="T">The type of elements in the incoming sequence.</typeparam> /// <typeparam name="C">The calculator for the sequence elements type.</typeparam> /// <param name="sequence">A calling sequence object.</param> /// <param name="centerValue">A nonnegative value. Sequence elements that deviate from this value by more than <paramref name="allowedDeviationFactor"/> will be filtered out.</param> /// <param name="allowedDeviationFactor">The allowed factor of absolute deviation.</param> /// <param name="deviationType"> /// If deviation type is Downwards, values which are smaller than <paramref name="centerValue"/> /// by a factor of <paramref name="allowedDeviationFactor"/> will be filtered. /// If deviation type is Upwards, values which are bigger than <paramref name="centerValue"/> /// by a factor of <paramref name="allowedDeviationFactor"/> will be filtered. /// If deviation type is EitherSide, all values that differ from the <paramref name="centerValue"/> /// by a factor of <paramref name="allowedDeviationFactor"/> will be filtered. /// </param> /// <param name="filteredValues">A reference to a collection to store the filtered values. May be null.</param> /// <returns>The list containing all incoming values except for the filtered ones.</returns> public static List <T> filterSurgesByAbsoluteFactorDeviationFromValue <T, C>(this IEnumerable <T> sequence, T centerValue, double allowedDeviationFactor, DeviationType deviationType = DeviationType.EitherSide, ICollection <T> filteredValues = null) where C : ICalc <T>, new() { ICalc <T> calc = Numeric <T, C> .Calculator; (centerValue > Numeric <T, C> .Zero).Assert(new ArgumentException("The center value specified should be positive.")); (allowedDeviationFactor > 0).Assert(new ArgumentException("The allowed deviation factor should be positive.")); List <T> result = new List <T>(); foreach (Numeric <T, C> current in sequence) { Numeric <T, C> absCurrent = WhiteMath <T, C> .Abs(current); Numeric <T, C> multipliedValue = (Numeric <T, C>)allowedDeviationFactor * centerValue; Numeric <T, C> multipliedCurrent = (Numeric <T, C>)allowedDeviationFactor * absCurrent; if (deviationType == DeviationType.EitherSide && (absCurrent > multipliedValue || multipliedCurrent < centerValue) || deviationType == DeviationType.Upwards && absCurrent > multipliedValue || deviationType == DeviationType.Downwards && multipliedCurrent < centerValue) { // Filter the surge. if (filteredValues != null) { filteredValues.Add(current); } } else { result.Add(current); } } return(result); }
/// <summary> /// Returns the maximum error for the Simpson integral approximation method /// depending on the interval on which the calculation is performed, /// the maximum absolute value of the function's fourth derivative and the point count (should be even). /// </summary> /// <typeparam name="T">The type of function argument/value.</typeparam> /// <typeparam name="C">The calculator for the function argument.</typeparam> /// <param name="obj">The calling function object. Is not actually used.</param> /// <param name="interval">The interval on which the calculation is performed. No matter if bounds are exclusive, they are considered INCLUSIVE.</param> /// <param name="pointCount">The point count on the interval.</param> /// <param name="maxFourthDerivative">The maximum absolute value of the function's fourth derivative.</param> /// <returns>The maximum error of the simpson method.</returns> public static T IntegralSimpsonMethodError <T, C>(this IFunction <T, T> obj, BoundedInterval <T, C> interval, int pointCount, T maxFourthDerivative) where C : ICalc <T>, new() { Numeric <T, C> big = (Numeric <T, C>) 2880; Numeric <T, C> hFourth = WhiteMath <T, C> .PowerInteger((interval.RightBound - interval.LeftBound) / (Numeric <T, C>)(pointCount / 2), 4); return((interval.RightBound - interval.LeftBound) * hFourth * maxFourthDerivative / big); }
/// <summary> /// Calculates the sample unbiased variation for a sequence of observations. /// </summary> /// <typeparam name="T">The type of observations' values.</typeparam> /// <typeparam name="C">A calculator for the <typeparamref name="T"/> type.</typeparam> /// <param name="values">The sequence of observations.</param> /// <param name="sampleAverage">The sample average for the observations sequence.</param> /// <returns>The sample unbiased variation for the sequence of observations.</returns> public static T SampleUnbiasedVariance <T, C>(this IEnumerable <T> values, T sampleAverage) where C : ICalc <T>, new() { Contract.Requires <ArgumentNullException>(values != null, "values"); Contract.Ensures(Contract.Result <T>() >= Numeric <T, C> ._0, "The variance should not be negative."); int count = values.Count(); if (count == 0) { throw new ArgumentException("Cannot calculate the sample variance for an empty sequence."); } else if (count == 1) { return(Numeric <T, C> .Zero); } Numeric <T, C> sum = Numeric <T, C> .Zero; ICalc <T> calc = Numeric <T, C> .Calculator; foreach (T value in values) { sum += WhiteMath <T, C> .PowerInteger(calc.dif(value, sampleAverage), 2); } return(sum / (Numeric <T, C>)(values.Count() - 1)); }
public static Func <T, T> SigmoidFunction <T, C>(T exponentDelta, int taylorMemberCount = 100) where C : ICalc <T>, new() { return(delegate(T x) { ICalc <T> calc = Numeric <T, C> .Calculator; T temp = WhiteMath <T, C> .Exponent(calc.mul(exponentDelta, x), taylorMemberCount); return Numeric <T, C> ._1 / (Numeric <T, C> ._1 + temp); }); }
/// <summary> /// Calculates a public exponent on the basis of /// a pair of primes which form the RSA secret key and /// the number chosen as public exponent. /// </summary> /// <typeparam name="B">An implementation of <c>IBase</c> interface which specifies the digit base of <c>LongInt<<typeparamref name="B"/>></c> numbers.</typeparam> /// <param name="secretKey">A pair of primes which form the RSA secret key.</param> /// <returns>The secret exponent of the RSA algorithm.</returns> public static LongInt <B> GetSecretExponent <B>(Point <LongInt <B> > secretKey, LongInt <B> publicExponent) where B : IBase, new() { Contract.Requires <ArgumentNullException>(publicExponent != null, "publicExponent"); Contract.Requires <ArgumentNullException>(secretKey.X != null, "secretKey.X"); Contract.Requires <ArgumentNullException>(secretKey.Y != null, "secretKey.Y"); LongInt <B> totient = LongInt <B> .Helper.MultiplyFFTComplex(secretKey.X - 1, secretKey.Y - 1); return (WhiteMath <LongInt <B>, CalcLongInt <B> > .MultiplicativeInverse(publicExponent, totient)); }
/// <summary> /// Performs a Solovay-Strassen stochastic primality test of a long integer number /// and returns the probability that the number is composite. /// </summary> /// <typeparam name="B">A class specifying the digit base of <c>LongInt<<typeparamref name="B"/></c> type.</typeparam> /// <param name="num">A number, bigger than 1, to test for primality.</param> /// <param name="gen"> /// A bounded <c>LongInt<<typeparamref name="B"/></c> random generator. /// For probability estimations to be correct, this generator should guarantee uniform distribution /// for any given interval. /// </param> /// <param name="rounds"> /// A positive number of testing rounds. Recommended to be more than <c>log2(<paramref name="num"/>)</c>. /// </param> /// <returns> /// The probability that the <paramref name="num"/> is composite. /// Equals to <c>2^(-<paramref name="rounds"/>)</c>, which is /// worse than for <see cref="IsPrime_MillerRabin<B>"/>. /// </returns> public static double IsPrime_SolovayStrassen <B>(this LongInt <B> num, IRandomBounded <LongInt <B> > gen, long rounds) where B : IBase, new() { Contract.Requires <ArgumentNullException>(num != null, "num"); Contract.Requires <ArgumentNullException>(gen != null, "gen"); Contract.Requires <ArgumentOutOfRangeException>(num > 1, "The tested number should be bigger than 2."); Contract.Requires <ArgumentOutOfRangeException>(rounds > 0, "The number of rounds should be positive."); if (num.IsEven) { if (num == 2) { return(0); } else { return(1); } } else if (num == 3) { return(0); } LongInt <B> half = (num - 1) / 2; for (long i = 0; i < rounds; i++) { LongInt <B> rnd = gen.Next(2, num); int jacobiSymbol = WhiteMath <LongInt <B>, CalcLongInt <B> > .JacobiSymbol(rnd, num); // Символ Якоби равняется нулю, значит, числа не взаимно простые // значит, наше число составное. if (jacobiSymbol == 0) { return(1); } // Иначе еще вот что посмотрим. LongInt <B> powered = LongInt <B> .Helper.PowerIntegerModular(rnd, half, num); if (jacobiSymbol == 1 && powered != 1 || jacobiSymbol == -1 && powered != num - 1) { return(1); } } return(Math.Pow(2, -rounds)); }
/// <summary> /// Returns the first half of the [rootDegree]th roots of unity series in the BigInteger field. /// Used in the recursive FFT algorithm in LongInt.Helper class. /// /// Root degree should be an exact power of two. /// </summary> /// <param name="rootDegree"></param> /// <returns></returns> public static BigInteger[] rootsOfUnityHalfGalois(int rootDegree, bool inverted) { Contract.Requires <ArgumentOutOfRangeException>(rootDegree > 0, "The degree of the root should be a positive power of two."); Contract.Ensures( Contract.ForAll( Contract.Result <BigInteger[]>(), (x => WhiteMath <BigInteger, CalcBigInteger> .PowerIntegerModular(x, (ulong)rootDegree, NTT_MODULUS) == 1))); BigInteger[] result = new BigInteger[rootDegree / 2]; // The first root of unity is obviously one. // - result[0] = 1; // Now we will learn what k it is in rootDegree == 2^k // - int rootDegreeCopy = rootDegree; int rootDegreeExponent = 0; while (rootDegreeCopy > 1) { rootDegreeCopy /= 2; ++rootDegreeExponent; } // Now we obtain the principal 2^rootDegreeExponent-th root of unity. // - BigInteger principalRoot = WhiteMath <BigInteger, CalcBigInteger> .PowerIntegerModular( NTT_MAX_ROOT_OF_UNITY_2_30, WhiteMath <ulong, CalcULong> .PowerInteger(2, NTT_MAX_ROOT_OF_UNITY_DEGREE_EXPONENT - rootDegreeExponent), NTT_MODULUS); // Calculate the desired roots of unity. // - for (int i = 1; i < rootDegree / 2; i++) { // All the desired roots of unity are obtained as powers of the principal root. // - result[i] = result[i - 1] * principalRoot % NTT_MODULUS; } // If performing the inverse NTT, we should invert the roots. // - if (inverted) { for (int i = 0; i < rootDegree / 2; ++i) { result[i] = WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(result[i], NTT_MODULUS); } } return(result); }
/// <summary> /// TODO: write description /// </summary> /// <typeparam name="T"></typeparam> /// <typeparam name="C"></typeparam> /// <param name="obj"></param> /// <param name="interval"></param> /// <param name="maxError"></param> /// <param name="maxFourthDerivative"></param> /// <returns></returns> public static T IntegralSimpsonNeededPointCount <T, C>(this IFunction <T, T> obj, BoundedInterval <T, C> interval, T maxError, T maxFourthDerivative) where C : ICalc <T>, new() { // N^4 степени. Numeric <T, C> nFourth = (Numeric <T, C>)maxFourthDerivative * WhiteMath <T, C> .PowerInteger(interval.RightBound - interval.LeftBound, 5) / (maxError * (Numeric <T, C>) 2880); // TODO: почему 100 членов в ряде тейлора? // надо вычислять точность. Numeric <T, C> power = (Numeric <T, C>) 0.25; Numeric <T, C> n = WhiteMath <T, C> .SquareRootHeron(WhiteMath <T, C> .SquareRootHeron(nFourth, maxError), maxError); return(Numeric <T, C> ._2 * WhiteMath <T, C> .Ceiling(n)); }
/// <summary> /// Returns the first half of the [rootDegree]th roots of unity series in the BigInteger field. /// Used in the recursive FFT algorithm in LongInt.Helper class. /// /// Root degree should be an exact power of two. /// </summary> /// <param name="rootDegree"></param> /// <returns></returns> internal static BigInteger[] rootsOfUnityHalfGalois( NTTFiniteFieldInfo finiteFieldInfo, int rootDegree, bool inverted) { Contract.Requires <ArgumentOutOfRangeException>(rootDegree > 0, "The degree of the root should be a positive power of two."); Contract.Ensures( Contract.ForAll( Contract.Result <BigInteger[]>(), (x => WhiteMath <BigInteger, CalcBigInteger> .PowerIntegerModular(x, (ulong)rootDegree, finiteFieldInfo.primeModulus) == 1))); BigInteger[] result = new BigInteger[rootDegree / 2]; // The first root of unity is obviously one, // but we start with -1 if we need the inverse roots. // - if (!inverted) { result[0] = 1; } else { result[0] = finiteFieldInfo.primeModulus - 1; } // Calculate the desired roots of unity. // - for (int i = 1; i < rootDegree / 2; ++i) { // All the desired roots of unity are obtained as powers of the principal root. // - result[i] = result[i - 1] * finiteFieldInfo.rootOfUnity % finiteFieldInfo.primeModulus; } // If performing the inverse NTT, we should reverse the array along // with a magic shift by 1 to get the inverted roots in the necessary order. // if (inverted) { result[0] = 1; for (int i = 1; i < rootDegree / 4; ++i) { result.Swap(i, rootDegree / 2 - i); } } return(result); }
/* * if n < 1,373,653, it is enough to test a = 2 and 3; * if n < 9,080,191, it is enough to test a = 31 and 73; * if n < 4,759,123,141, it is enough to test a = 2, 7, and 61; * if n < 2,152,302,898,747, it is enough to test a = 2, 3, 5, 7, and 11; * if n < 3,474,749,660,383, it is enough to test a = 2, 3, 5, 7, 11, and 13; * if n < 341,550,071,728,321, it is enough to test a = 2, 3, 5, 7, 11, 13, and 17. * */ /// <summary> /// Performs a Miller's deterministic prime test on a number. /// Goes over all numbers under the <c>floor(ln^2(<paramref name="num"/>))</c> boundary. /// </summary> /// <typeparam name="B"> /// A class specifying the digit base of <c>LongInt<<typeparamref name="B"/></c> type. /// The base should be an integer power of two. /// </typeparam> /// <remarks>This test relies upon Riemann's Generalized Hypothesis, which still remains unproven. Use with caution.</remarks> /// <param name="num">A number, bigger than 1, to test for primality.</param> /// <returns>True if the number is prime according to the test, false otherwise.</returns> public static bool IsPrime_Miller <B>(this LongInt <B> num) where B : IBase, new() { Contract.Requires <ArgumentException>(LongInt <B> .BASE_is_power_of_two, "The digit base of the number should be a strict power of two."); Contract.Requires <ArgumentNullException>(num != null, "num"); Contract.Requires <ArgumentOutOfRangeException>(num > 1, "The tested number should be bigger than 1."); if (num.IsEven) { if (num == 2) { return(true); } else { return(false); } } else if (num == 3) { return(true); } // Представим число num - 1 в виде // // num - 1 = 2^s * t LongInt <B> t; long s; LongInt <B> numDecremented = num - 1; ___millerRabinFactorize(numDecremented, out t, out s); LongInt <B> upperBound = WhiteMath <LongInt <B>, CalcLongInt <B> > .Min(num.LengthInBinaryPlaces *num.LengthInBinaryPlaces, numDecremented); for (LongInt <B> i = 2; i <= upperBound; i++) { if (!___millerRabinIsPrimeWitness(i, num, t, s)) { return(false); } } return(true); }
/// <summary> /// BACK FFT /// </summary> /// <param name="coefficients"></param> /// <returns></returns> internal static BigInteger[] Recursive_NTT_Inverse(IList <BigInteger> coefficients) { int n = coefficients.Count; BigInteger[] rootsHalf = rootsOfUnityHalfGalois(n, true); BigInteger[] result = Recursive_NTT_Skeleton(coefficients, rootsHalf, 1, 0); // We should multiply the result by the multiplicative inverse of length. // - BigInteger lengthMultiplicativeInverse = WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(n, NTT_MODULUS); for (int i = 0; i < result.Length; i++) { result[i] = (result[i] * lengthMultiplicativeInverse) % NTT_MODULUS; } return(result); }
/// <summary> /// BACK FFT /// </summary> /// <param name="coefficients"></param> /// <returns></returns> internal static BigInteger[] Recursive_NTT_Inverse( IList <BigInteger> coefficients, NTTFiniteFieldInfo finiteFieldInfo) { int n = coefficients.Count; BigInteger[] rootsHalf = rootsOfUnityHalfGalois(finiteFieldInfo, n, true); BigInteger[] result = Recursive_NTT_Skeleton(coefficients, rootsHalf, finiteFieldInfo, 1, 0); // We should multiply the result by the multiplicative inverse of length // in contrast to the forward-NTT. // - BigInteger lengthMultiplicativeInverse = WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(n, finiteFieldInfo.primeModulus); for (int i = 0; i < result.Length; i++) { result[i] = (result[i] * lengthMultiplicativeInverse) % finiteFieldInfo.primeModulus; } return(result); }
/// <summary> /// Adds relative (factor) surges from a symmetric distribution random generator to each value of a numeric sequence /// and returns the nosiy sequence in the form of a list. /// </summary> /// <typeparam name="T">The type of elements in the numeric sequence.</typeparam> /// <typeparam name="C">The calculator for the <typeparamref name="T"/> type.</typeparam> /// <param name="sequence">The calling numeric sequence object.</param> /// <param name="symmetricDistributionGenerator">A random generator providing values of some symmetric distribution.</param> /// <param name="deviationType">Which deviations (positive, negative or both) should be added to the sequence.</param> /// <returns></returns> public static List <T> addRelativeSurgesFromSymmetricDistribution <T, C>(this IEnumerable <T> sequence, IRandomUnbounded <T> symmetricDistributionGenerator, DeviationType deviationType) where C : ICalc <T>, new() { List <T> result = new List <T>(sequence.Count()); foreach (Numeric <T, C> value in sequence) { if (deviationType == DeviationType.EitherSide) { result.Add(value + value * symmetricDistributionGenerator.Next()); } else if (deviationType == DeviationType.Downwards) { result.Add(value - WhiteMath <T, C> .Abs(value * symmetricDistributionGenerator.Next())); } else { result.Add(value + WhiteMath <T, C> .Abs(value * symmetricDistributionGenerator.Next())); } } return(result); }
// -------------------------------------------- // --------- ЗНАК ФУНКЦИИ --------------------- // -------------------------------------------- /// <summary> /// Returns the number of sign variations in the function list for some certain /// point. /// </summary> /// <typeparam name="T">The type of polynom coefficients.</typeparam> /// <typeparam name="C">The type of polynom coefficients' calculator.</typeparam> /// <param name="list">The list of the polynoms to be analyzed.</param> /// <returns>The number of sign variations within the list. Zero values do not count.</returns> public static int SignVariations <T, C>(this IList <IFunction <T, T> > list, Numeric <T, C> point) where C : ICalc <T>, new() { int signPrev = 0; int signNew = 0; int k = 0; for (int i = 0; i < list.Count; i++) { signNew = WhiteMath <T, C> .Sign(list[i].Value(point)); if (signPrev == 0) { if (signNew != 0) { k++; } else { continue; } } else if (signPrev < 0 || signPrev > 0) { if (signNew != 0) { k++; } else { continue; } } signPrev = signNew; } return(k); }
/// <summary> /// For debug purposes. Performs the NTT in a straightforward (quadratic) manner. /// </summary> internal static BigInteger[] __DB_Quadratic_NTT(IList <BigInteger> coefficients, bool back = false) { BigInteger[] rootsOfUnity = __DB__rootsOfUnityGalois(coefficients.Count, back); BigInteger[] result = new BigInteger[coefficients.Count]; for (int i = 0; i < rootsOfUnity.Length; ++i) { BigInteger currentRoot = rootsOfUnity[i]; BigInteger hornerResult = 0; for (int j = coefficients.Count - 1; j >= 0; --j) { hornerResult = (hornerResult * currentRoot + coefficients[j]) % NTT_MODULUS; } result[i] = hornerResult * (back ? WhiteMath <BigInteger, CalcBigInteger> .MultiplicativeInverse(coefficients.Count, NTT_MODULUS) : 1) % NTT_MODULUS; } return(result); }
/// <summary> /// Warning! Works correctly only for the MONOTONOUS (on the interval specified) function! /// Returns the bounded approximation of monotonous function's Riman integral. /// </summary> /// <typeparam name="T">The type of function argument/value.</typeparam> /// <typeparam name="C">The calculator for the argument type.</typeparam> /// <param name="obj">The calling function object.</param> /// <param name="interval">The interval to approximate the integral on.</param> /// <param name="pointCount">The overall point count used to approximate the integral value. The more this value is, the more precise is the calculation.</param> /// <returns>The interval in which the integral's value lies.</returns> public static BoundedInterval <T, C> IntegralRectangleBoundedApproximation <T, C>(this IFunction <T, T> obj, BoundedInterval <T, C> interval, int pointCount) where C : ICalc <T>, new() { ICalc <T> calc = Numeric <T, C> .Calculator; // Если интервал нулевой длины, то ваще забей. if (interval.IsZeroLength) { return(new BoundedInterval <T, C>(calc.zero, calc.zero, true, true)); } // Если нет, то ваще не забей. Point <T>[] table = obj.GetFunctionTable <T, C>(interval, pointCount + 1); Numeric <T, C> step = calc.dif(table[2].X, table[0].X); Numeric <T, C> sumOne = calc.zero; Numeric <T, C> sumTwo = calc.zero; for (int i = 0; i < pointCount; i++) { if (i < pointCount - 1) { sumOne += table[i].Y; } if (i > 0) { sumTwo += table[i].Y; } } Numeric <T, C> res1 = sumOne * step; Numeric <T, C> res2 = sumTwo * step; return(new BoundedInterval <T, C>(WhiteMath <T, C> .Min(res1, res2), WhiteMath <T, C> .Max(res1, res2), true, true)); }
/// <summary> /// Filters the surges in a sequence whose absolute values deviate from the specified positive value by a /// nonnegative value specified. /// </summary> /// <typeparam name="T">The type of elements in the incoming sequence.</typeparam> /// <typeparam name="C">The calculator for the sequence elements type.</typeparam> /// <param name="sequence">A calling sequence object.</param> /// <param name="centerValue">Some value. Sequence elements that deviate from this value by more than <paramref name="allowedEpsilon"/> will be filtered out.</param> /// <param name="allowedEpsilon">The allowed nonnegative value of deviation from <paramref name="centerValue"/>.</param> /// <param name="deviationType"> /// If deviation type is Downwards, values which are smaller than <paramref name="centerValue"/> /// by <paramref name="allowedEpsilon"/> will be filtered. /// If deviation type is Upwards, values which are bigger than <paramref name="centerValue"/> /// by <paramref name="allowedEpsilon"/> will be filtered. /// If deviation type is EitherSide, all values that differ from the <paramref name="centerValue"/> /// by <paramref name="allowedEpsilon"/> will be filtered. /// </param> /// <param name="filteredValues">A reference to a collection to store the filtered values. May be null.</param> /// <returns>The list containing all incoming values except for the filtered ones.</returns> public static List <T> filterSurgesByEpsilonDeviationFromValue <T, C>(this IEnumerable <T> sequence, T centerValue, T allowedEpsilon, DeviationType deviationType = DeviationType.EitherSide, ICollection <T> filteredValues = null) where C : ICalc <T>, new() { ICalc <T> calc = Numeric <T, C> .Calculator; (allowedEpsilon >= Numeric <T, C> .Zero).Assert(new ArgumentException("Allowed deviation epsilon should be a non-negative value.")); List <T> result = new List <T>(); foreach (Numeric <T, C> current in sequence) { if (deviationType == DeviationType.EitherSide && WhiteMath <T, C> .Abs(centerValue - current) < (Numeric <T, C>)allowedEpsilon || deviationType == DeviationType.Downwards && centerValue - current < allowedEpsilon || deviationType == DeviationType.Upwards && current - centerValue < allowedEpsilon) { result.Add(current); } else if (filteredValues != null) { filteredValues.Add(current); } } return(result); }
/// <summary> /// Returns the string representation of the polynomial function /// as an array of coefficients - or, in the functional form /// i.e. 'f(x) = ...'. /// </summary> /// <param name="type">The type of the string representation.</param> /// <returns>The string representation of the current object.</returns> public string ToString(PolynomStringRepresentationType type) { if (type == PolynomStringRepresentationType.Coefficients) { string coefString = ""; for (int i = 0; i < coefficients.Length; i++) { coefString += "|" + this.coefficients[i].ToString(); } coefString += "|"; return(coefString); } else { string functionString = "f(x) = "; Numeric <T, C> one = calc.fromInt(1); for (int i = coefficients.Length - 1; i > 0; i--) { if (coefficients[i] != Numeric <T, C> .Zero) { functionString += string.Format("{0}{1}x{2}", (coefficients[i] >= calc.zero ? (i < coefficients.Length - 1?" + ":"") : (i < coefficients.Length - 1?" - ":"-")), (coefficients[i] != one ? WhiteMath <T, C> .Abs(coefficients[i]).ToString() : ""), (i == 1 ? "" : "^" + i.ToString())); } } if (coefficients[0] != Numeric <T, C> .Zero) { functionString += string.Format(" {0} {1} ", (coefficients[0] > Numeric <T, C> .Zero ? "+" : "-"), WhiteMath <T, C> .Abs(coefficients[0])); } return(functionString); } }
// ------------------- FACTORIZATION ---------------------------- /// <summary> /// Preforms the LUP-factorization of a matrix (let it be A) /// in the form of: /// /// P*A = L*U. /// /// The P is an identity matrix with a plenty of row inversions. /// For the economy of space it is provided as a single-dimensional array of integers: /// /// (0, 1, 2, 3, ..., n). /// /// Element indices of this array stand for matrix rows, and elements value /// mean the position of '1' in a row. /// /// Requirements: works for any square and nonsingular matrix (having a non-zero determinant). /// If these requirements aren't met, either a MatrixSingularException or a MatrixSizeException /// would be thrown. /// </summary> /// <param name="C">The matrix C containing L + U - E. It is clear that both L and U can be easily extracted from this matrix.</param> /// <param name="P">The identity matrix with a plenty of row inversions in the form of array.</param> public void LUP_Factorization(out int[] P, out Matrix_SDA <T, C> C) { if (this.rows != this.columns) { throw new MatrixSizeException("The matrix is not square an thus cannot be factorized."); } int n = this.rows; // размер матрицы C = new Matrix_SDA <T, C>(n, n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { C.setItemAt(i, j, this.getItemAt(i, j)); } } P = new int[n]; P.FillByAssign(delegate(int i) { return(i); }); // ----- пошел ---------- Numeric <T, C> pivot; Numeric <T, C> abs; int pivotIndex; for (int i = 0; i < n; i++) { pivot = Numeric <T, C> .Zero; pivotIndex = -1; for (int row = i; row < n; row++) { abs = WhiteMath <T, C> .Abs(this.getItemAt(row, i)); if (abs > pivot) { pivot = abs; pivotIndex = row; } } if (pivot == Numeric <T, C> .Zero) { throw new MatrixSingularityException("The matrix is singular. It cannot be factorized."); } if (pivotIndex != i) { P.Swap(pivotIndex, i); C.swapRows(pivotIndex, i); } try { for (int j = i + 1; j < n; j++) { C.setItemAt(j, i, C.getItemAt(j, i) / C.getItemAt(i, i)); if (Numeric <T, C> .isInfinity(C.getItemAt(j, i)) || Numeric <T, C> .isNaN(C.getItemAt(j, i))) { throw new DivideByZeroException(); } for (int k = i + 1; k < n; k++) { C.setItemAt(j, k, C.getItemAt(j, k) - C.getItemAt(j, i) * C.getItemAt(i, k)); } } } catch (DivideByZeroException) { throw new MatrixSingularityException("The matrix is singular. It cannot be factorized."); } } return; }
// --------- this is the key to happiness private static T _PositiveLagrangeBound(IList <Numeric <T, C> > coefficients, Func <int, Numeric <T, C>, Numeric <T, C> > selector) { // нули в начале нам совсем не нужны. int minus = 1; while (coefficients[coefficients.Count - minus] == Numeric <T, C> .Zero) { minus++; if (minus > coefficients.Count) { throw new ArgumentException("This polynom contains only zero coefficients. Cannot evaluate the finite roots interval."); } // todo - return INFINITY. } // ------- начальный коэффициент - меньше нуля? // заменяем функцию g(x) = -f(x) и сохраняем корни и нервы. if (selector(coefficients.Count - minus, coefficients[coefficients.Count - minus]) < Numeric <T, C> .Zero) { object target = selector.Target; MethodInfo method = selector.Method; selector = delegate(int i, Numeric <T, C> obj) { return(-(Numeric <T, C>)method.Invoke(target, new object[] { i, obj })); }; } // ----------------- T nCoef = coefficients[coefficients.Count - minus]; T cur; T one = calc.fromInt(1); T max = calc.zero; int index = -1; // индекс первого отрицательного коэффициента bool found = false; // найдены ли отрицательные коэффициенты! for (int i = coefficients.Count - minus; i >= 0; i--) { cur = selector(i, coefficients[i]); if (!found && calc.mor(calc.zero, cur)) { found = true; index = coefficients.Count - i - minus; } // -- здесь cur больше не нужна, а нужно только ее // абсолютное значение. его и используем. cur = WhiteMath <T, C> .Abs(cur); if (calc.mor(cur, max)) { max = cur; } } if (!found) { return(calc.zero); } return(calc.sum(one, WhiteMath <T, C> .Power(calc.div(max, WhiteMath <T, C> .Abs(nCoef)), calc.div(one, calc.fromInt(index))))); }