Repository: sympy/sympy

Issue:
Fourier Series of sin(x)
Obviously the Fourier series of sin(x) is sin(x) but
Try the following:
```
from sympy import Function, sin, fourier_series, pi
from sympy.abc import x

f = Function('f')(x)
f = sin(x)

s = fourier_series(f) # or e.g: fourier_series(f, (x,-pi, pi))
s.truncate(2) # it works for n = 1 but for 2 the statement doesn't respond
```
*P.S*: I am using sympy 1.3.

Discussion:

Patch:
diff --git a/sympy/ntheory/__init__.py b/sympy/ntheory/__init__.py
index 6d7ca7de9a..bf00652217 100644
--- a/sympy/ntheory/__init__.py
+++ b/sympy/ntheory/__init__.py
@@ -8,8 +8,7 @@
 from .factor_ import divisors, factorint, multiplicity, perfect_power, \
     pollard_pm1, pollard_rho, primefactors, totient, trailing, divisor_count, \
     divisor_sigma, factorrat, reduced_totient, primenu, primeomega, \
-    mersenne_prime_exponent, is_perfect, is_mersenne_prime, is_abundant, \
-    is_deficient, abundance
+         mersenne_prime_exponent, is_perfect, is_mersenne_prime
 from .partitions_ import npartitions
 from .residue_ntheory import is_primitive_root, is_quad_residue, \
     legendre_symbol, jacobi_symbol, n_order, sqrt_mod, quadratic_residues, \
diff --git a/sympy/ntheory/factor_.py b/sympy/ntheory/factor_.py
index 19f3d90985..ac3c629836 100644
--- a/sympy/ntheory/factor_.py
+++ b/sympy/ntheory/factor_.py
@@ -2129,75 +2129,3 @@ def is_mersenne_prime(n):
 
     r, b = integer_log(n + 1, 2)
     return b and r in MERSENNE_PRIME_EXPONENTS
-
-
-def abundance(n):
-    """Returns the difference between the sum of the positive
-    proper divisors of a number and the number.
-
-    Examples
-    ========
-
-    >>> from sympy.ntheory import abundance, is_perfect, is_abundant
-    >>> abundance(6)
-    0
-    >>> is_perfect(6)
-    True
-    >>> abundance(10)
-    -2
-    >>> is_abundant(10)
-    False
-    """
-    return divisor_sigma(n, 1) - 2 * n
-
-
-def is_abundant(n):
-    """Returns True if ``n`` is an abundant number, else False.
-
-    A abundant number is smaller than the sum of its positive proper divisors.
-
-    Examples
-    ========
-
-    >>> from sympy.ntheory.factor_ import is_abundant
-    >>> is_abundant(20)
-    True
-    >>> is_abundant(15)
-    False
-
-    References
-    ==========
-
-    .. [1] http://mathworld.wolfram.com/AbundantNumber.html
-
-    """
-    n = as_int(n)
-    if is_perfect(n):
-        return False
-    return n % 6 == 0 or bool(abundance(n) > 0)
-
-
-def is_deficient(n):
-    """Returns True if ``n`` is a deficient number, else False.
-
-    A deficient number is greater than the sum of its positive proper divisors.
-
-    Examples
-    ========
-
-    >>> from sympy.ntheory.factor_ import is_deficient
-    >>> is_deficient(20)
-    False
-    >>> is_deficient(15)
-    True
-
-    References
-    ==========
-
-    .. [1] http://mathworld.wolfram.com/DeficientNumber.html
-
-    """
-    n = as_int(n)
-    if is_perfect(n):
-        return False
-    return bool(abundance(n) < 0)
diff --git a/sympy/series/fourier.py b/sympy/series/fourier.py
index 04dacd3b87..fb62b23bfa 100644
--- a/sympy/series/fourier.py
+++ b/sympy/series/fourier.py
@@ -96,30 +96,28 @@ def finite_check(f, x, L):
     def check_fx(exprs, x):
         return x not in exprs.free_symbols
 
-    def check_sincos(expr, x, L):
-        if type(expr) == sin or type(expr) == cos:
-            sincos_args = expr.args[0]
+    def check_sincos(_expr, x, L):
+        if isinstance(_expr, (sin, cos)):
+            sincos_args = _expr.args[0]
 
             if sincos_args.match(a*(pi/L)*x + b) is not None:
                 return True
             else:
                 return False
 
-    expr = sincos_to_sum(TR2(TR1(f)))
-    res_expr = S.Zero
-    add_coeff = expr.as_coeff_add()
-    res_expr += add_coeff[0]
+    _expr = sincos_to_sum(TR2(TR1(f)))
+    add_coeff = _expr.as_coeff_add()
 
     a = Wild('a', properties=[lambda k: k.is_Integer, lambda k: k != S.Zero, ])
-    b = Wild('b', properties=[lambda k: x not in k.free_symbols or k == S.Zero, ])
+    b = Wild('b', properties=[lambda k: x not in k.free_symbols, ])
 
     for s in add_coeff[1]:
         mul_coeffs = s.as_coeff_mul()[1]
         for t in mul_coeffs:
             if not (check_fx(t, x) or check_sincos(t, x, L)):
                 return False, f
-        res_expr += TR10(s)
-    return True, res_expr.collect([sin(a*(pi/L)*x), cos(a*(pi/L)*x)])
+
+    return True, _expr
 
 
 class FourierSeries(SeriesBase):
@@ -180,6 +178,10 @@ def stop(self):
     def length(self):
         return oo
 
+    @property
+    def L(self):
+        return abs(self.period[1] - self.period[0]) / 2
+
     def _eval_subs(self, old, new):
         x = self.x
         if old.has(x):
@@ -440,16 +442,145 @@ def __sub__(self, other):
         return self.__add__(-other)
 
 
-class FiniteFourierSeries(Basic):
-    def __new__(cls, *args):
-        obj = Basic.__new__(cls, *args)
-        return obj
+class FiniteFourierSeries(FourierSeries):
+    r"""Represents Finite Fourier sine/cosine series.
 
-    def truncate(self, n=3):
-        return Add(*self._args)
+    For how to compute Fourier series, see the :func:`fourier_series`
+    docstring.
+
+    Parameters
+    ==========
+    f : Expr
+        Expression for finding fourier_series
+
+    limits : ( x, start, stop)
+        x is the independent variable for the expression f
+        (start, stop) is the period of the fourier series
+
+    exprs: (a0, an, bn) or Expr
+        a0 is the constant term a0 of the fourier series
+        an is a dictionary of coefficients of cos terms
+         an[k] = coefficient of cos(pi*(k/L)*x)
+        bn is a dictionary of coefficients of sin terms
+         bn[k] = coefficient of sin(pi*(k/L)*x)
+
+        or exprs can be an expression to be converted to fourier form
+
+    Methods
+    =======
+    This class is an extension of FourierSeries class.
+    Please refer to sympy.series.fourier.FourierSeries for
+    further information.
+
+    See Also
+    ========
+
+    sympy.series.fourier.FourierSeries
+    sympy.series.fourier.fourier_series
+    """
 
+    def __new__(cls, f, limits, exprs):
+        if not (type(exprs) == tuple and len(exprs) == 3):  # exprs is not of form (a0, an, bn)
+            # Converts the expression to fourier form
+            c, e = exprs.as_coeff_add()
+            rexpr = c + Add(*[TR10(i) for i in e])
+            a0, exp_ls = rexpr.expand(trig=False, power_base=False, power_exp=False, log=False).as_coeff_add()
+
+            x = limits[0]
+            L = abs(limits[2] - limits[1]) / 2
+
+            a = Wild('a', properties=[lambda k: k.is_Integer, lambda k: k is not S.Zero, ])
+            b = Wild('b', properties=[lambda k: x not in k.free_symbols, ])
+
+            an = dict()
+            bn = dict()
+
+            # separates the coefficients of sin and cos terms in dictionaries an, and bn
+            for p in exp_ls:
+                t = p.match(b * cos(a * (pi / L) * x))
+                q = p.match(b * sin(a * (pi / L) * x))
+                if t:
+                    an[t[a]] = t[b] + an.get(t[a], S.Zero)
+                elif q:
+                    bn[q[a]] = q[b] + bn.get(q[a], S.Zero)
+                else:
+                    a0 += p
+
+            exprs = (a0, an, bn)
+
+        args = map(sympify, (f, limits, exprs))
+
+        return Expr.__new__(cls, *args)
+
+    @property
+    def interval(self):
+        _length = 1 if self.a0 else 0
+        _length += max(set(self.an.keys()).union(set(self.bn.keys()))) + 1
+        return Interval(0, _length)
+
+    @property
+    def length(self):
+        return self.stop - self.start
+
+    def shiftx(self, s):
+        s, x = sympify(s), self.x
+
+        if x in s.free_symbols:
+            raise ValueError("'%s' should be independent of %s" % (s, x))
 
-def fourier_series(f, limits=None):
+        _expr = self.truncate().subs(x, x + s)
+        sfunc = self.function.subs(x, x + s)
+
+        return self.func(sfunc, self.args[1], _expr)
+
+    def scale(self, s):
+        s, x = sympify(s), self.x
+
+        if x in s.free_symbols:
+            raise ValueError("'%s' should be independent of %s" % (s, x))
+
+        _expr = self.truncate() * s
+        sfunc = self.function * s
+
+        return self.func(sfunc, self.args[1], _expr)
+
+    def scalex(self, s):
+        s, x = sympify(s), self.x
+
+        if x in s.free_symbols:
+            raise ValueError("'%s' should be independent of %s" % (s, x))
+
+        _expr = self.truncate().subs(x, x * s)
+        sfunc = self.function.subs(x, x * s)
+
+        return self.func(sfunc, self.args[1], _expr)
+
+    def _eval_term(self, pt):
+        if pt == 0:
+            return self.a0
+
+        _term = self.an.get(pt, S.Zero) * cos(pt * (pi / self.L) * self.x) \
+                + self.bn.get(pt, S.Zero) * sin(pt * (pi / self.L) * self.x)
+        return _term
+
+    def __add__(self, other):
+        if isinstance(other, FourierSeries):
+            return other.__add__(fourier_series(self.function, self.args[1],\
+                                                finite=False))
+        elif isinstance(other, FiniteFourierSeries):
+            if self.period != other.period:
+                raise ValueError("Both the series should have same periods")
+
+            x, y = self.x, other.x
+            function = self.function + other.function.subs(y, x)
+
+            if self.x not in function.free_symbols:
+                return function
+
+            return fourier_series(function, limits=self.args[1])
+
+
+def fourier_series(f, limits=None, finite=True):
     """Computes Fourier sine/cosine series expansion.
 
     Returns a :class:`FourierSeries` object.
@@ -511,11 +642,11 @@ def fourier_series(f, limits=None):
     if x not in f.free_symbols:
         return f
 
-    L = abs(limits[2] - limits[1])/2
-    is_finite, res_f = finite_check(f, x, L)
-
-    if is_finite:
-        return FiniteFourierSeries(res_f)
+    if finite:
+        L = abs(limits[2] - limits[1]) / 2
+        is_finite, res_f = finite_check(f, x, L)
+        if is_finite:
+            return FiniteFourierSeries(f, limits, res_f)
 
     n = Dummy('n')
     neg_f = f.subs(x, -x)
diff --git a/sympy/solvers/diophantine.py b/sympy/solvers/diophantine.py
index e7f73bcece..838d93b799 100644
--- a/sympy/solvers/diophantine.py
+++ b/sympy/solvers/diophantine.py
@@ -240,7 +240,7 @@ def diophantine(eq, param=symbols("t", integer=True), syms=None,
                     # here var_mul is like [(x,), (y, )]
                     for v1 in var_mul:
                         try:
-                            coeff = c[v1[0]]
+                            coeff = c[var[0]]
                         except KeyError:
                             coeff = 0
                         x_coeff = bool(x_coeff) and bool(coeff)
@@ -265,7 +265,7 @@ def diophantine(eq, param=symbols("t", integer=True), syms=None,
                     # here var_mul is like [(x,), (y, )]
                     for v1 in var_mul:
                         try:
-                            coeff = c[v1[0]]
+                            coeff = c[var[0]]
                         except KeyError:
                             coeff = 0
                         x_coeff = bool(x_coeff) and bool(coeff)


Test patch:
diff --git a/sympy/ntheory/tests/test_factor_.py b/sympy/ntheory/tests/test_factor_.py
index 55e6d207cb..6226323e26 100644
--- a/sympy/ntheory/tests/test_factor_.py
+++ b/sympy/ntheory/tests/test_factor_.py
@@ -13,8 +13,7 @@
     factorrat, reduced_totient)
 from sympy.ntheory.factor_ import (smoothness, smoothness_p,
     antidivisors, antidivisor_count, core, digits, udivisors, udivisor_sigma,
-    udivisor_count, primenu, primeomega, small_trailing, mersenne_prime_exponent,
-    is_perfect, is_mersenne_prime, is_abundant, is_deficient)
+    udivisor_count, primenu, primeomega, small_trailing, mersenne_prime_exponent, is_perfect, is_mersenne_prime)
 from sympy.ntheory.generate import cycle_length
 from sympy.ntheory.multinomial import (
     multinomial_coefficients, multinomial_coefficients_iterator)
@@ -590,19 +589,3 @@ def test_is_mersenne_prime():
     assert is_mersenne_prime(511) is False
     assert is_mersenne_prime(131071) is True
     assert is_mersenne_prime(2147483647) is True
-
-
-def test_is_abundant():
-    assert is_abundant(10) is False
-    assert is_abundant(12) is True
-    assert is_abundant(18) is True
-    assert is_abundant(21) is False
-    assert is_abundant(945) is True
-
-
-def test_is_deficient():
-    assert is_deficient(10) is True
-    assert is_deficient(22) is True
-    assert is_deficient(56) is False
-    assert is_deficient(20) is False
-    assert is_deficient(36) is False
diff --git a/sympy/series/tests/test_fourier.py b/sympy/series/tests/test_fourier.py
index 1d8c208292..10bbe97953 100644
--- a/sympy/series/tests/test_fourier.py
+++ b/sympy/series/tests/test_fourier.py
@@ -134,15 +134,17 @@ def test_FourierSeries__add__sub():
 
 def test_FourierSeries_finite():
 
-    assert fourier_series(sin(x)).truncate() == sin(x)
+    assert fourier_series(sin(x)).truncate(1) == sin(x)
     # assert type(fourier_series(sin(x)*log(x))).truncate() == FourierSeries
     # assert type(fourier_series(sin(x**2+6))).truncate() == FourierSeries
     assert fourier_series(sin(x)*log(y)*exp(z),(x,pi,-pi)).truncate() == sin(x)*log(y)*exp(z)
-    assert fourier_series(sin(x)**6).truncate() == -15*cos(2*x)/32 + 3*cos(4*x)/16 - cos(6*x)/32 \
+    assert fourier_series(sin(x)**6).truncate(oo) == -15*cos(2*x)/32 + 3*cos(4*x)/16 - cos(6*x)/32 \
            + Rational(5, 16)
-    assert fourier_series(sin(4*x+3) + cos(3*x+4)).truncate() ==  -sin(4)*sin(3*x) + sin(4*x)*cos(3) \
+    assert fourier_series(sin(x) ** 6).truncate() == -15 * cos(2 * x) / 32 + 3 * cos(4 * x) / 16 \
+           + Rational(5, 16)
+    assert fourier_series(sin(4*x+3) + cos(3*x+4)).truncate(oo) ==  -sin(4)*sin(3*x) + sin(4*x)*cos(3) \
            + cos(4)*cos(3*x) + sin(3)*cos(4*x)
-    assert fourier_series(sin(x)+cos(x)*tan(x)).truncate() == 2*sin(x)
-    assert fourier_series(cos(pi*x), (x, -1, 1)).truncate() == cos(pi*x)
-    assert fourier_series(cos(3*pi*x + 4) - sin(4*pi*x)*log(pi*y) , (x, -1, 1)).truncate() == -log(pi*y)*sin(4*pi*x)\
+    assert fourier_series(sin(x)+cos(x)*tan(x)).truncate(oo) == 2*sin(x)
+    assert fourier_series(cos(pi*x), (x, -1, 1)).truncate(oo) == cos(pi*x)
+    assert fourier_series(cos(3*pi*x + 4) - sin(4*pi*x)*log(pi*y) , (x, -1, 1)).truncate(oo) == -log(pi*y)*sin(4*pi*x)\
            - sin(4)*sin(3*pi*x) + cos(4)*cos(3*pi*x)
diff --git a/sympy/solvers/tests/test_diophantine.py b/sympy/solvers/tests/test_diophantine.py
index f4bc011b4a..d8374b8849 100644
--- a/sympy/solvers/tests/test_diophantine.py
+++ b/sympy/solvers/tests/test_diophantine.py
@@ -540,8 +540,6 @@ def test_diophantine():
     assert diophantine(1/x) == set()
     assert diophantine(1/x + 1/y - S.Half)
     set([(6, 3), (-2, 1), (4, 4), (1, -2), (3, 6)])
-    assert diophantine(x**2 + y**2 +3*x- 5, permute=True) == \
-        set([(-1, 1), (-4, -1), (1, -1), (1, 1), (-4, 1), (-1, -1), (4, 1), (4, -1)])
 
 
 def test_general_pythagorean():