/// <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)); }
/// <summary> /// Returns the polynom that is the integral of the current polynom, /// which satisfies the condition of passing the specified point. /// </summary> /// <param name="point"></param> /// <returns></returns> public Polynom <T, C> Integral(Point <T> point) { Polynom <T, C> newPolynom = this.Integral(Numeric <T, C> .Zero); newPolynom.coefficients[0] = calc.dif(point.Y, newPolynom.Value(point.X)); return(newPolynom); }
// ---------------------------------------- private LagrangePolynom(IList <Point <T> > points, bool checkSorted, bool createMatrix) { this.points = points.ToArray(); IComparer <Point <T> > comparer = Point <T> .GetComparerOnX(Numeric <T, C> .TComparer); // Если списокъ не отсортированъ, // то это нужно сделать сей же часъ. if (checkSorted && !this.points.IsSorted(comparer)) { this.points.SortShell(comparer); } // Создаем матрицу разностей. if (createMatrix) { int n = this.points.Length; difMatrix = new Matrix_SDA <T, C>(n, n); for (int i = 0; i < n; i++) { difMatrix[i, i] = Numeric <T, C> .Zero; for (int j = 0; j < i; j++) { difMatrix[i, j] = calc.dif(this.points[i].X, this.points[j].X); } } // Теперь заполняем то, что выше главной диагонали, противоположными значениями. for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { difMatrix[i, j] = -difMatrix[j, i]; } } } }
// -------------------------------------------- // --------- РАВЕНСТВО ФУНКЦИЙ ---------------- // -------------------------------------------- /// <summary> /// Checks whether the current function is equal to another at least within the /// finite set of points. /// </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.</param> /// <param name="another">The function object to test equality with.</param> /// <param name="epsilon">The upper epsilon bound of 'equality' criteria. If |f(x) - g(x)| < eps, two functions are considered equal.</param> /// <param name="points">The points list to test equality on.</param> /// <returns>True if the functions are epsilon-equal within the points list passed, false otherwise.</returns> public static bool PointwiseEquals <T, C>(this IFunction <T, T> obj, IFunction <T, T> another, T epsilon, IList <T> points) where C : ICalc <T>, new() { Func <T, T> abs = WhiteMath <T, C> .Abs; ICalc <T> calc = Numeric <T, C> .Calculator; for (int i = 0; i < points.Count; i++) { if (!calc.mor(epsilon, abs(calc.dif(obj.Value(points[i]), another.Value(points[i]))))) { return(false); } } return(true); }
/// <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> /// Creates a continuous natural cubic spline of defect 1. /// Max. continuous derivative of the spline is second. /// </summary> /// <param name="points"></param> /// <param name="defaultValue"></param> /// <returns></returns> public static PieceFunction <T, C> CreateNaturalCubicSpline(IList <Point <T> > points, T defaultValue) { int n = points.Count - 1; // количество точек Numeric <T, C>[] a = new Numeric <T, C> [n]; Numeric <T, C>[] c = new Numeric <T, C> [n]; DefaultList <Numeric <T, C> > b = new DefaultList <Numeric <T, C> >(new Numeric <T, C> [n], Numeric <T, C> .Zero); Numeric <T, C>[] delta = new Numeric <T, C> [n]; Numeric <T, C>[] lambda = new Numeric <T, C> [n]; Numeric <T, C>[] h = new Numeric <T, C> [n]; Numeric <T, C>[] fDiv = new Numeric <T, C> [n]; KeyValuePair <BoundedInterval <T, C>, IFunction <T, T> >[] pieces = new KeyValuePair <BoundedInterval <T, C>, IFunction <T, T> > [n]; // count h and fDiv for (int i = 0; i < n; i++) { h[i] = calc.dif(points[i + 1].X, points[i].X); fDiv[i] = calc.dif(points[i + 1].Y, points[i].Y) / h[i]; } // h идут не от 1 до n // а от 0 до n-1. delta[0] = (Numeric <T, C>)(-0.5) * h[1] / (h[0] + h[1]); lambda[0] = (Numeric <T, C>)(1.5) * (fDiv[1] - fDiv[0]) / (h[0] + h[1]); // calculating lambda Numeric <T, C> two = (Numeric <T, C>) 2; Numeric <T, C> three = (Numeric <T, C>) 3; for (int i = 2; i < n; i++) { delta[i - 1] = -h[i] / (two * (h[i - 1] + h[i]) + h[i - 1] * delta[i - 2]); lambda[i - 1] = (three * (fDiv[i] - fDiv[i - 1]) - h[i - 1] * lambda[i - 2]) / (two * (h[i - 1] + h[i]) + h[i - 1] * delta[i - 2]); } // calculating b b[n - 1] = Numeric <T, C> .Zero; for (int i = n - 1; i > 0; i--) { b[i - 1] = delta[i - 1] * b[i] + lambda[i - 1]; } // calculating others for (int i = 0; i < n; i++) { a[i] = (b[i] - b[i - 1]) / (three * h[i]); c[i] = fDiv[i] + two * h[i] * b[i] / three + h[i] * b[i - 1] / three; pieces[i] = new KeyValuePair <BoundedInterval <T, C>, IFunction <T, T> >( new BoundedInterval <T, C>(points[i].X, points[i + 1].X, true, false), new CubicFunction <T, C> (a[i], b[i], c[i], points[i + 1].Y, points[i + 1].X)); } PieceFunction <T, C> function = new PieceFunction <T, C>(defaultValue, pieces); function.Type = PieceFunctionType.NaturalCubicSpline; return(new PieceFunction <T, C>(defaultValue, pieces)); }
/// <summary> /// Returns the fractional part of the number. /// </summary> /// <typeparam name="T">The type of numbers for the calculator.</typeparam> /// <param name="calculator">The calling calculator object.</param> /// <param name="num">The number which fractional part is to be returned.</param> /// <returns>The fractional part of the number.</returns> public static T fracPart <T>(this ICalc <T> calculator, T num) { return(calculator.dif(num, calculator.intPart(num))); }