def _eval_terms(self, n): """ Returns the first `n` terms of the product formal power series. Term by term logic is implemented here. Examples ======== >>> from sympy import fps, sin, exp, convolution >>> from sympy.abc import x >>> f1 = fps(sin(x)) >>> f2 = fps(exp(x)) >>> fprod = f1.product(f2, x) >>> fprod._eval_terms(4) x**3/3 + x**2 + x See Also ======== sympy.series.formal.FormalPowerSeries.product """ coeff1, coeff2 = self.coeff1, self.coeff2 aks = convolution(coeff1[:n], coeff2[:n]) terms = [] for i in range(0, n): terms.append(aks[i] * self.ffps.xk.coeff(i)) return Add(*terms)
def test_cyclic_convolution(): # fft a = [1, S(5)/3, sqrt(3), S(7)/5] b = [9, 5, 5, 4, 3, 2] assert convolution([1, 2, 3], [4, 5, 6], cycle=0) == \ convolution([1, 2, 3], [4, 5, 6], cycle=5) == \ convolution([1, 2, 3], [4, 5, 6]) assert convolution([1, 2, 3], [4, 5, 6], cycle=3) == [31, 31, 28] a = [S(1)/3, S(7)/3, S(5)/9, S(2)/7, S(5)/8] b = [S(3)/5, S(4)/7, S(7)/8, S(8)/9] assert convolution(a, b, cycle=0) == \ convolution(a, b, cycle=len(a) + len(b) - 1) assert convolution(a, b, cycle=4) == [S(87277)/26460, S(30521)/11340, S(11125)/4032, S(3653)/1080] assert convolution(a, b, cycle=6) == [S(20177)/20160, S(676)/315, S(47)/24, S(3053)/1080, S(16397)/5292, S(2497)/2268] assert convolution(a, b, cycle=9) == \ convolution(a, b, cycle=0) + [S.Zero] # ntt a = [2313, 5323532, S(3232), 42142, 42242421] b = [S(33456), 56757, 45754, 432423] assert convolution(a, b, prime=19*2**10 + 1, cycle=0) == \ convolution(a, b, prime=19*2**10 + 1, cycle=8) == \ convolution(a, b, prime=19*2**10 + 1) assert convolution(a, b, prime=19*2**10 + 1, cycle=5) == [96, 17146, 2664, 15534, 3517] assert convolution(a, b, prime=19*2**10 + 1, cycle=7) == [4643, 3458, 1260, 15534, 3517, 16314, 13688] assert convolution(a, b, prime=19*2**10 + 1, cycle=9) == \ convolution(a, b, prime=19*2**10 + 1) + [0] # fwht u, v, w, x, y = symbols('u v w x y') p, q, r, s, t = symbols('p q r s t') c = [u, v, w, x, y] d = [p, q, r, s, t] assert convolution(a, b, dyadic=True, cycle=3) == \ [2499522285783, 19861417974796, 4702176579021] assert convolution(a, b, dyadic=True, cycle=5) == [2718149225143, 2114320852171, 20571217906407, 246166418903, 1413262436976] assert convolution(c, d, dyadic=True, cycle=4) == \ [p*u + p*y + q*v + r*w + s*x + t*u + t*y, p*v + q*u + q*y + r*x + s*w + t*v, p*w + q*x + r*u + r*y + s*v + t*w, p*x + q*w + r*v + s*u + s*y + t*x] assert convolution(c, d, dyadic=True, cycle=6) == \ [p*u + q*v + r*w + r*y + s*x + t*w + t*y, p*v + q*u + r*x + s*w + s*y + t*x, p*w + q*x + r*u + s*v, p*x + q*w + r*v + s*u, p*y + t*u, q*y + t*v] # subset assert convolution(a, b, subset=True, cycle=7) == [18266671799811, 178235365533, 213958794, 246166418903, 1413262436976, 2397553088697, 1932759730434] assert convolution(a[1:], b, subset=True, cycle=4) == \ [178104086592, 302255835516, 244982785880, 3717819845434] assert convolution(a, b[:-1], subset=True, cycle=6) == [1932837114162, 178235365533, 213958794, 245166224504, 1413262436976, 2397553088697] assert convolution(c, d, subset=True, cycle=3) == \ [p*u + p*x + q*w + r*v + r*y + s*u + t*w, p*v + p*y + q*u + s*y + t*u + t*x, p*w + q*y + r*u + t*v] assert convolution(c, d, subset=True, cycle=5) == \ [p*u + q*y + t*v, p*v + q*u + r*y + t*w, p*w + r*u + s*y + t*x, p*x + q*w + r*v + s*u, p*y + t*u]
def test_convolution(): # fft a = [1, S(5)/3, sqrt(3), S(7)/5] b = [9, 5, 5, 4, 3, 2] c = [3, 5, 3, 7, 8] d = [1422, 6572, 3213, 5552] assert convolution(a, b) == convolution_fft(a, b) assert convolution(a, b, dps=9) == convolution_fft(a, b, dps=9) assert convolution(a, d, dps=7) == convolution_fft(d, a, dps=7) assert convolution(a, d[1:], dps=3) == convolution_fft(d[1:], a, dps=3) # prime moduli of the form (m*2**k + 1), sequence length # should be a divisor of 2**k p = 7*17*2**23 + 1 q = 19*2**10 + 1 # ntt assert convolution(d, b, prime=q) == convolution_ntt(b, d, prime=q) assert convolution(c, b, prime=p) == convolution_ntt(b, c, prime=p) assert convolution(d, c, prime=p) == convolution_ntt(c, d, prime=p) raises(TypeError, lambda: convolution(b, d, dps=5, prime=q)) raises(TypeError, lambda: convolution(b, d, dps=6, prime=q)) # fwht assert convolution(a, b, dyadic=True) == convolution_fwht(a, b) assert convolution(a, b, dyadic=False) == convolution(a, b) raises(TypeError, lambda: convolution(b, d, dps=2, dyadic=True)) raises(TypeError, lambda: convolution(b, d, prime=p, dyadic=True)) raises(TypeError, lambda: convolution(a, b, dps=2, dyadic=True)) raises(TypeError, lambda: convolution(b, c, prime=p, dyadic=True)) # subset assert convolution(a, b, subset=True) == convolution_subset(a, b) == \ convolution(a, b, subset=True, dyadic=False) == \ convolution(a, b, subset=True) assert convolution(a, b, subset=False) == convolution(a, b) raises(TypeError, lambda: convolution(a, b, subset=True, dyadic=True)) raises(TypeError, lambda: convolution(c, d, subset=True, dps=6)) raises(TypeError, lambda: convolution(a, c, subset=True, prime=q))
def test_convolution(): # fft a = [1, Rational(5, 3), sqrt(3), Rational(7, 5)] b = [9, 5, 5, 4, 3, 2] c = [3, 5, 3, 7, 8] d = [1422, 6572, 3213, 5552] assert convolution(a, b) == convolution_fft(a, b) assert convolution(a, b, dps=9) == convolution_fft(a, b, dps=9) assert convolution(a, d, dps=7) == convolution_fft(d, a, dps=7) assert convolution(a, d[1:], dps=3) == convolution_fft(d[1:], a, dps=3) # prime moduli of the form (m*2**k + 1), sequence length # should be a divisor of 2**k p = 7*17*2**23 + 1 q = 19*2**10 + 1 # ntt assert convolution(d, b, prime=q) == convolution_ntt(b, d, prime=q) assert convolution(c, b, prime=p) == convolution_ntt(b, c, prime=p) assert convolution(d, c, prime=p) == convolution_ntt(c, d, prime=p) raises(TypeError, lambda: convolution(b, d, dps=5, prime=q)) raises(TypeError, lambda: convolution(b, d, dps=6, prime=q)) # fwht assert convolution(a, b, dyadic=True) == convolution_fwht(a, b) assert convolution(a, b, dyadic=False) == convolution(a, b) raises(TypeError, lambda: convolution(b, d, dps=2, dyadic=True)) raises(TypeError, lambda: convolution(b, d, prime=p, dyadic=True)) raises(TypeError, lambda: convolution(a, b, dps=2, dyadic=True)) raises(TypeError, lambda: convolution(b, c, prime=p, dyadic=True)) # subset assert convolution(a, b, subset=True) == convolution_subset(a, b) == \ convolution(a, b, subset=True, dyadic=False) == \ convolution(a, b, subset=True) assert convolution(a, b, subset=False) == convolution(a, b) raises(TypeError, lambda: convolution(a, b, subset=True, dyadic=True)) raises(TypeError, lambda: convolution(c, d, subset=True, dps=6)) raises(TypeError, lambda: convolution(a, c, subset=True, prime=q))
def test_cyclic_convolution(): # fft a = [1, Rational(5, 3), sqrt(3), Rational(7, 5)] b = [9, 5, 5, 4, 3, 2] assert convolution([1, 2, 3], [4, 5, 6], cycle=0) == \ convolution([1, 2, 3], [4, 5, 6], cycle=5) == \ convolution([1, 2, 3], [4, 5, 6]) assert convolution([1, 2, 3], [4, 5, 6], cycle=3) == [31, 31, 28] a = [Rational(1, 3), Rational(7, 3), Rational(5, 9), Rational(2, 7), Rational(5, 8)] b = [Rational(3, 5), Rational(4, 7), Rational(7, 8), Rational(8, 9)] assert convolution(a, b, cycle=0) == \ convolution(a, b, cycle=len(a) + len(b) - 1) assert convolution(a, b, cycle=4) == [Rational(87277, 26460), Rational(30521, 11340), Rational(11125, 4032), Rational(3653, 1080)] assert convolution(a, b, cycle=6) == [Rational(20177, 20160), Rational(676, 315), Rational(47, 24), Rational(3053, 1080), Rational(16397, 5292), Rational(2497, 2268)] assert convolution(a, b, cycle=9) == \ convolution(a, b, cycle=0) + [S.Zero] # ntt a = [2313, 5323532, S(3232), 42142, 42242421] b = [S(33456), 56757, 45754, 432423] assert convolution(a, b, prime=19*2**10 + 1, cycle=0) == \ convolution(a, b, prime=19*2**10 + 1, cycle=8) == \ convolution(a, b, prime=19*2**10 + 1) assert convolution(a, b, prime=19*2**10 + 1, cycle=5) == [96, 17146, 2664, 15534, 3517] assert convolution(a, b, prime=19*2**10 + 1, cycle=7) == [4643, 3458, 1260, 15534, 3517, 16314, 13688] assert convolution(a, b, prime=19*2**10 + 1, cycle=9) == \ convolution(a, b, prime=19*2**10 + 1) + [0] # fwht u, v, w, x, y = symbols('u v w x y') p, q, r, s, t = symbols('p q r s t') c = [u, v, w, x, y] d = [p, q, r, s, t] assert convolution(a, b, dyadic=True, cycle=3) == \ [2499522285783, 19861417974796, 4702176579021] assert convolution(a, b, dyadic=True, cycle=5) == [2718149225143, 2114320852171, 20571217906407, 246166418903, 1413262436976] assert convolution(c, d, dyadic=True, cycle=4) == \ [p*u + p*y + q*v + r*w + s*x + t*u + t*y, p*v + q*u + q*y + r*x + s*w + t*v, p*w + q*x + r*u + r*y + s*v + t*w, p*x + q*w + r*v + s*u + s*y + t*x] assert convolution(c, d, dyadic=True, cycle=6) == \ [p*u + q*v + r*w + r*y + s*x + t*w + t*y, p*v + q*u + r*x + s*w + s*y + t*x, p*w + q*x + r*u + s*v, p*x + q*w + r*v + s*u, p*y + t*u, q*y + t*v] # subset assert convolution(a, b, subset=True, cycle=7) == [18266671799811, 178235365533, 213958794, 246166418903, 1413262436976, 2397553088697, 1932759730434] assert convolution(a[1:], b, subset=True, cycle=4) == \ [178104086592, 302255835516, 244982785880, 3717819845434] assert convolution(a, b[:-1], subset=True, cycle=6) == [1932837114162, 178235365533, 213958794, 245166224504, 1413262436976, 2397553088697] assert convolution(c, d, subset=True, cycle=3) == \ [p*u + p*x + q*w + r*v + r*y + s*u + t*w, p*v + p*y + q*u + s*y + t*u + t*x, p*w + q*y + r*u + t*v] assert convolution(c, d, subset=True, cycle=5) == \ [p*u + q*y + t*v, p*v + q*u + r*y + t*w, p*w + r*u + s*y + t*x, p*x + q*w + r*v + s*u, p*y + t*u] raises(ValueError, lambda: convolution([1, 2, 3], [4, 5, 6], cycle=-1))
def product(self, other, x=None, n=6): """Multiplies two Formal Power Series, using discrete convolution and return the truncated terms upto specified order. Parameters ========== n : Number, optional Specifies the order of the term up to which the polynomial should be truncated. Examples ======== >>> from sympy import fps, sin, exp, convolution >>> from sympy.abc import x >>> f1 = fps(sin(x)) >>> f2 = fps(exp(x)) >>> f1.product(f2, x, 4) x + x**2 + x**3/3 + O(x**4) See Also ======== sympy.discrete.convolutions """ if x is None: x = self.x if n is None: return iter(self) other = sympify(other) if not isinstance(other, FormalPowerSeries): raise ValueError( "Both series should be an instance of FormalPowerSeries" " class.") if self.dir != other.dir: raise ValueError("Both series should be calculated from the" " same direction.") elif self.x0 != other.x0: raise ValueError("Both series should be calculated about the" " same point.") elif self.x != other.x: raise ValueError("Both series should have the same symbol.") k = self.ak.variables[0] coeff1 = sequence(self.ak.formula, (k, 0, oo)) k = other.ak.variables[0] coeff2 = sequence(other.ak.formula, (k, 0, oo)) conv_coeff = convolution(coeff1[:n], coeff2[:n]) conv_seq = sequence(tuple(conv_coeff), (k, 0, oo)) k = self.xk.variables[0] xk_seq = sequence(self.xk.formula, (k, 0, oo)) terms_seq = xk_seq * conv_seq return Add(*(terms_seq[:n])) + Order(self.xk.coeff(n), (self.x, self.x0))