public Series(Series s, bool cache) { _compute = s._compute; _order = s._order; _degree = s._degree; if (cache && s._cache != null) { _cache = s._cache; _cacheValidTo = s._cacheValidTo; } else { if (cache) { _cache = new Rational[2]; } _cacheValidTo = -1; } }
/// <summary> /// Generates the series f(g(z)), where g(z) has nonzero order. /// </summary> /// <param name="g">A series with nonzero order.</param> /// <returns>The series f(g(z)).</returns> public Series Compose(Series g) { if (g.IsUnit()) throw new ArgumentException("g must have nonzero order"); return new Series((n, s) => { if (n == 0) return this[0]; int high = n; Rational c = Rational.Zero; if (high > this.Degree) high = this.Degree; for (int i = 1; i <= high; i++) { c += this[i] * PowCoefficient(g, i, n, true); } return c; }, order: ExtendedMultiply(this.Order, g.Order), degree: ExtendedMultiply(this.Degree, g.Degree), cache: true); }
public static Series DividePointwise(Series f, Series g) { return new Series((n, s) => f[n] / g[n], order: f.Order, degree: f.Degree); }
/// <summary> /// Computes the coefficient of z^n in f^k, where k is a nonnegative integer. /// </summary> /// <param name="f">A series.</param> /// <param name="k">A nonnegative integer exponent.</param> /// <param name="n">The coefficient index.</param> /// <returns>The coefficient of z^n in f^k.</returns> public static Rational PowCoefficient(Series f, int k, int n, bool nonZeroOrder = false) { if (k == 0) return n == 0 ? Rational.One : Rational.Zero; Rational c = Rational.Zero; int[] buffer = new int[System.Math.Min(n, k) + 1]; int[] input = new int[n + 1]; foreach (var partition in Discrete.Partitions(n, k, buffer)) { if (nonZeroOrder && partition.Count != k) continue; Rational p = Rational.One; int i; Array.Clear(input, 0, n + 1); for (i = 0; i < partition.Count; i++) { p *= f[partition.Array[partition.Offset + i]]; input[partition.Array[partition.Offset + i]]++; } input[0] = k - partition.Count; for (; i < k; i++) { p *= f[0]; } p *= Multinomial(input); c += p; } return c; }
public static Series Divide(Series f, Rational k) { return new Series((n, s) => f[n] / k, order: f.Order, degree: f.Degree); }
public static Series MultiplyPointwise(Series f, Series g) { return new Series((n, s) => f[n] * g[n], order: System.Math.Max(f.Order, g.Order), degree: System.Math.Min(f.Degree, g.Degree)); }
public static Series Subtract(Rational k, Series f) { Rational constant = k - f[0]; int order; if (constant == Rational.Zero) order = System.Math.Max(f.Order, 1); else order = 0; return new Series((n, s) => { if (n == 0) return constant; else return -f[n]; }, order: order, degree: System.Math.Max(f.Degree, 0)); }
public static Series Multiply(Series f, Rational k) { if (k == Rational.Zero) return Zero; else return new Series((n, s) => f[n] * k, order: f.Order, degree: f.Degree); }
public static Series Add(Series f, Rational k) { Rational constant = f[0] + k; int order; if (constant == Rational.Zero) order = System.Math.Max(f.Order, 1); else order = 0; return new Series((n, s) => { if (n == 0) return constant; else return f[n]; }, order: order, degree: System.Math.Max(f.Degree, 0)); }
public static Series Divide(Series f, Series g) { return Multiply(f, g.Inv()); }
public static Series Multiply(Series f, Series g) { return new Series((n, s) => { int low = 0; int high = n; Rational c = Rational.Zero; if (low < f.Order) low = f.Order; if (high > f.Degree) high = f.Degree; if (g.Order == InfinityOrder) high = -1; else if (high > n - g.Order) high = n - g.Order; if (g.Degree == MinusInfinityDegree) low = InfinityDegree; else if (g.Degree != InfinityDegree && low < n - g.Degree) low = n - g.Degree; for (int i = low; i <= high; i++) { c += f[i] * g[n - i]; } return c; }, order: ExtendedAdd(f.Order, g.Order), degree: ExtendedAdd(f.Degree, g.Degree), cache: true); }
public static Series Subtract(Series f, Series g) { return new Series((n, s) => f[n] - g[n], order: System.Math.Min(f.Order, g.Order), degree: System.Math.Max(f.Degree, g.Degree)); }
public static Series Negate(Series f) { return new Series((n, s) => -f[n], order: f.Order, degree: f.Degree); }