Repository: sympy/sympy

Issue:
fresnel limit to infinite gives wrong answer
```
>>> fresnels(oo)    # good

1/2

>>> fresnels(x).limit(x,oo)    # bad!

0
```


Discussion:

Patch:
diff --git a/sympy/functions/special/error_functions.py b/sympy/functions/special/error_functions.py
index 0ac6120e9a..ac643eca5b 100644
--- a/sympy/functions/special/error_functions.py
+++ b/sympy/functions/special/error_functions.py
@@ -2180,22 +2180,27 @@ def _eval_aseries(self, n, args0, x, logx):
         from sympy import Order
         point = args0[0]
 
-        # Expansion at oo
-        if point is S.Infinity:
+        # Expansion at oo and -oo
+        if point in [S.Infinity, -S.Infinity]:
             z = self.args[0]
 
             # expansion of S(x) = S1(x*sqrt(pi/2)), see reference[5] page 1-8
+            # as only real infinities are dealt with, sin and cos are O(1)
             p = [(-1)**k * factorial(4*k + 1) /
                  (2**(2*k + 2) * z**(4*k + 3) * 2**(2*k)*factorial(2*k))
-                 for k in range(0, n)]
+                 for k in range(0, n) if 4*k + 3 < n]
             q = [1/(2*z)] + [(-1)**k * factorial(4*k - 1) /
                  (2**(2*k + 1) * z**(4*k + 1) * 2**(2*k - 1)*factorial(2*k - 1))
-                 for k in range(1, n)]
-
-            p = [-sqrt(2/pi)*t for t in p] + [Order(1/z**n, x)]
-            q = [-sqrt(2/pi)*t for t in q] + [Order(1/z**n, x)]
+                 for k in range(1, n) if 4*k + 1 < n]
 
-            return S.Half + (sin(z**2)*Add(*p) + cos(z**2)*Add(*q)).subs(x, sqrt(2/pi)*x)
+            p = [-sqrt(2/pi)*t for t in p]
+            q = [-sqrt(2/pi)*t for t in q]
+            s = 1 if point is S.Infinity else -1
+            # The expansion at oo is 1/2 + some odd powers of z
+            # To get the expansion at -oo, replace z by -z and flip the sign
+            # The result -1/2 + the same odd powers of z as before.
+            return s*S.Half + (sin(z**2)*Add(*p) + cos(z**2)*Add(*q)
+                ).subs(x, sqrt(2/pi)*x) + Order(1/z**n, x)
 
         # All other points are not handled
         return super(fresnels, self)._eval_aseries(n, args0, x, logx)
@@ -2313,21 +2318,26 @@ def _eval_aseries(self, n, args0, x, logx):
         point = args0[0]
 
         # Expansion at oo
-        if point is S.Infinity:
+        if point in [S.Infinity, -S.Infinity]:
             z = self.args[0]
 
             # expansion of C(x) = C1(x*sqrt(pi/2)), see reference[5] page 1-8
+            # as only real infinities are dealt with, sin and cos are O(1)
             p = [(-1)**k * factorial(4*k + 1) /
                  (2**(2*k + 2) * z**(4*k + 3) * 2**(2*k)*factorial(2*k))
-                 for k in range(0, n)]
+                 for k in range(0, n) if 4*k + 3 < n]
             q = [1/(2*z)] + [(-1)**k * factorial(4*k - 1) /
                  (2**(2*k + 1) * z**(4*k + 1) * 2**(2*k - 1)*factorial(2*k - 1))
-                 for k in range(1, n)]
-
-            p = [-sqrt(2/pi)*t for t in p] + [Order(1/z**n, x)]
-            q = [ sqrt(2/pi)*t for t in q] + [Order(1/z**n, x)]
-
-            return S.Half + (cos(z**2)*Add(*p) + sin(z**2)*Add(*q)).subs(x, sqrt(2/pi)*x)
+                 for k in range(1, n) if 4*k + 1 < n]
+
+            p = [-sqrt(2/pi)*t for t in p]
+            q = [ sqrt(2/pi)*t for t in q]
+            s = 1 if point is S.Infinity else -1
+            # The expansion at oo is 1/2 + some odd powers of z
+            # To get the expansion at -oo, replace z by -z and flip the sign
+            # The result -1/2 + the same odd powers of z as before.
+            return s*S.Half + (cos(z**2)*Add(*p) + sin(z**2)*Add(*q)
+                ).subs(x, sqrt(2/pi)*x) + Order(1/z**n, x)
 
         # All other points are not handled
         return super(fresnelc, self)._eval_aseries(n, args0, x, logx)


Test patch:
diff --git a/sympy/functions/special/tests/test_error_functions.py b/sympy/functions/special/tests/test_error_functions.py
index 01d76d20b0..89eec1846c 100644
--- a/sympy/functions/special/tests/test_error_functions.py
+++ b/sympy/functions/special/tests/test_error_functions.py
@@ -629,19 +629,19 @@ def test_fresnel():
     assert fresnelc(z).series(z, n=15) == \
         z - pi**2*z**5/40 + pi**4*z**9/3456 - pi**6*z**13/599040 + O(z**15)
 
-    # issue 6510
-    assert fresnels(z).series(z, S.Infinity) == \
-        (-1/(pi**2*z**3) + O(z**(-6), (z, oo)))*sin(pi*z**2/2) + \
-        (3/(pi**3*z**5) - 1/(pi*z) + O(z**(-6), (z, oo)))*cos(pi*z**2/2) + S.Half
-    assert fresnelc(z).series(z, S.Infinity) == \
-        (-1/(pi**2*z**3) + O(z**(-6), (z, oo)))*cos(pi*z**2/2) + \
-        (-3/(pi**3*z**5) + 1/(pi*z) + O(z**(-6), (z, oo)))*sin(pi*z**2/2) + S.Half
-    assert fresnels(1/z).series(z) == \
-        (-z**3/pi**2 + O(z**6))*sin(pi/(2*z**2)) + (-z/pi + 3*z**5/pi**3 + \
-        O(z**6))*cos(pi/(2*z**2)) + S.Half
-    assert fresnelc(1/z).series(z) == \
-        (-z**3/pi**2 + O(z**6))*cos(pi/(2*z**2)) + (z/pi - 3*z**5/pi**3 + \
-        O(z**6))*sin(pi/(2*z**2)) + S.Half
+    # issues 6510, 10102
+    fs = (S.Half - sin(pi*z**2/2)/(pi**2*z**3)
+        + (-1/(pi*z) + 3/(pi**3*z**5))*cos(pi*z**2/2))
+    fc = (S.Half - cos(pi*z**2/2)/(pi**2*z**3)
+        + (1/(pi*z) - 3/(pi**3*z**5))*sin(pi*z**2/2))
+    assert fresnels(z).series(z, oo) == fs + O(z**(-6), (z, oo))
+    assert fresnelc(z).series(z, oo) == fc + O(z**(-6), (z, oo))
+    assert (fresnels(z).series(z, -oo) + fs.subs(z, -z)).expand().is_Order
+    assert (fresnelc(z).series(z, -oo) + fc.subs(z, -z)).expand().is_Order
+    assert (fresnels(1/z).series(z) - fs.subs(z, 1/z)).expand().is_Order
+    assert (fresnelc(1/z).series(z) - fc.subs(z, 1/z)).expand().is_Order
+    assert ((2*fresnels(3*z)).series(z, oo) - 2*fs.subs(z, 3*z)).expand().is_Order
+    assert ((3*fresnelc(2*z)).series(z, oo) - 3*fc.subs(z, 2*z)).expand().is_Order
 
     assert fresnelc(w).is_real is True
 
diff --git a/sympy/series/tests/test_limits.py b/sympy/series/tests/test_limits.py
index 24624f0215..434296a06d 100644
--- a/sympy/series/tests/test_limits.py
+++ b/sympy/series/tests/test_limits.py
@@ -4,7 +4,7 @@
     limit, exp, oo, log, sqrt, Limit, sin, floor, cos, ceiling,
     atan, gamma, Symbol, S, pi, Integral, Rational, I, EulerGamma,
     tan, cot, integrate, Sum, sign, Function, subfactorial, symbols,
-    binomial, simplify, frac, Float, sec, zoo)
+    binomial, simplify, frac, Float, sec, zoo, fresnelc, fresnels)
 
 from sympy.calculus.util import AccumBounds
 from sympy.core.add import Add
@@ -533,5 +533,15 @@ def test_issue_14456():
 def test_issue_14411():
     assert limit(3*sec(4*pi*x - x/3), x, 3*pi/(24*pi - 2)) == -oo
 
+
 def test_issue_14574():
     assert limit(sqrt(x)*cos(x - x**2) / (x + 1), x, oo) == 0
+
+
+def test_issue_10102():
+    assert limit(fresnels(x), x, oo) == S.Half
+    assert limit(3 + fresnels(x), x, oo) == 3 + S.Half
+    assert limit(5*fresnels(x), x, oo) == 5*S.Half
+    assert limit(fresnelc(x), x, oo) == S.Half
+    assert limit(fresnels(x), x, -oo) == -S.Half
+    assert limit(4*fresnelc(x), x, -oo) == -2