publicsympy/sympy

Subversion checkout URL

You can clone with HTTPS or Subversion.

Fresnel Integral Functions#938

Merged
merged 37 commits into from about 2 years ago
+817 22

6 participants

Collaborator

This is a first implementation of the Fresnel integral functions S(x) and C(x).
It's the first part of Issue 2959: "Implement fresnel integrals".

The tests are still missing but I would like to get some feedback
before I proceed. (For example, are the function names ok?)

Owner

Does Sage implement these? If so, what does it call them?

Collaborator

In other CAS the names are:

Maxima: fresnel_s, fresnel_c
Maple: FresnelS, FresnelC
MMA: FresnelS, FresnelC
mpmath: fresnels, fresnelc

Sage probably calls maxima but I don't know.

Maybe we should use lower case only names too.

Collaborator

Collaborator

Hmm, still having trouble with the limit function

In [2]: z = Symbol("z")

In [3]: limit(erf(z), z, oo)
Out[3]: 1

In [4]: limit(fresnels(z), z, oo)
Out[4]: 0


Why does it work for erf but not for fresnels?

Collaborator

(reviewing this ASAP)

commented on the diff
 sympy/functions/special/error_functions.py 
 ((85 lines not shown)) 166 + def _eval_expand_complex(self, deep=True, **hints): 167 + re_part, im_part = self.as_real_imag(deep=deep, **hints) 168 + return re_part + im_part*S.ImaginaryUnit 169 + 170 + 171 +class fresnels(FresnelIntegral): 172 + r""" 173 + Fresnel integral S. 174 + 175 + This function is defined by 176 + 177 + .. math:: \operatorname{S}(z) = \int_0^z \sin{\frac{\pi}{2} t^2} \mathrm{d}t. 178 + 179 + It is an entire function. 180 + 181 + Examples
 sympy/functions/special/error_functions.py 
 ((250 lines not shown)) 331 + ========== 332 + 333 + .. [1] http://en.wikipedia.org/wiki/Fresnel_integral 334 + .. [2] http://dlmf.nist.gov/7 335 + .. [3] http://mathworld.wolfram.com/FresnelIntegrals.html 336 + .. [4] http://functions.wolfram.com/GammaBetaErf/FresnelC 337 + """ 338 + 339 + _trigfunc = C.cos 340 + _sign = S.One 341 + 342 + def _eval_rewrite_as_erf(self, z): 343 + return (S.One-I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) + I*erf((S.One-I)/2*sqrt(pi)*z)) 344 + 345 + def _eval_nseries(self, x, n, logx): 346 + return x*(-x**4)**n*(2**(-2*n)*pi**(2*n))/((4*n+1)*C.factorial(2*n))
 6 Collaborator ness01 added a note January 09, 2012 This shouldn't be necessary (and is not right as it stands anyway - this really should return a series of several terms, and an order. It is usually not necessary if differentiation is implemented, unless there are poles.). Collaborator raoulb added a note January 09, 2012 You are right, it is not necessary. However using diff is probably much slower, isn't it? BTW: Maybe we should add symbolic order differentiation to sympy? Which is the "best" example for this function where I can study how to do this right? Collaborator raoulb added a note January 09, 2012 BTW: The order term is not tight, I get: In [5]: fresnels(z).series(n=12) Out[5]: pi*z**3/6 - pi**3*z**7/336 + pi**5*z**11/42240 + O(z**12)  but it is really O(z**15) which is much better than O(z**12). Collaborator ness01 added a note January 09, 2012 You can look at e.g. the trig functions. The way to go is apparently to implement taylor_term. Personally I don't know if this is worth the hassle (but it probably cannot hurt either :-)). … Collaborator ness01 added a note January 09, 2012 Yeah series code is a mess. … Collaborator raoulb added a note January 09, 2012 Maybe this is a gsoc task to clean up this mess. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/functions/special/error_functions.py 
 ((260 lines not shown)) 341 + 342 + def _eval_rewrite_as_erf(self, z): 343 + return (S.One-I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) + I*erf((S.One-I)/2*sqrt(pi)*z)) 344 + 345 + def _eval_nseries(self, x, n, logx): 346 + return x*(-x**4)**n*(2**(-2*n)*pi**(2*n))/((4*n+1)*C.factorial(2*n)) 347 + 348 + def _eval_aseries(self, n, args0, x, logx): 349 + z = self.args[0] 350 + #e = S.Half*I*pi*z**2 351 + #h1 = C.hyper([S.One,S.Half],[],2*I/(pi*z**2)) 352 + #h2 = C.hyper([S.One,S.Half],[],-2*I/(pi*z**2)) 353 + #return (z**4)**C.Rational(3,4)/(2*z**3) + I/(2*pi*z)*(C.exp(-e)*h1 - C.exp(e)*h2) 354 + return S.Half + 1/(pi*z)*C.sin(S.Half*pi*z**2) 355 + 356 + def _eval_as_leading_term(self, x):
 3 Collaborator ness01 added a note January 09, 2012 I believe this function is not needed either. (In fact I think it should be removed all over sympy, but that might need some more investigation ^^.) Collaborator raoulb added a note January 09, 2012 What is the sympy way to compute leading order behaviour of a function? Just use the first time of series? So you are right and we can remove this function too. If we continue like that there will be not much left in the derived classes ^^ Collaborator ness01 added a note January 09, 2012 There is actually expr.compute_leading_term to do exactly this. You are right the code size might shrink, but that's a good thing :-). … Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/functions/special/error_functions.py 
 ((252 lines not shown)) 333 + .. [1] http://en.wikipedia.org/wiki/Fresnel_integral 334 + .. [2] http://dlmf.nist.gov/7 335 + .. [3] http://mathworld.wolfram.com/FresnelIntegrals.html 336 + .. [4] http://functions.wolfram.com/GammaBetaErf/FresnelC 337 + """ 338 + 339 + _trigfunc = C.cos 340 + _sign = S.One 341 + 342 + def _eval_rewrite_as_erf(self, z): 343 + return (S.One-I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) + I*erf((S.One-I)/2*sqrt(pi)*z)) 344 + 345 + def _eval_nseries(self, x, n, logx): 346 + return x*(-x**4)**n*(2**(-2*n)*pi**(2*n))/((4*n+1)*C.factorial(2*n)) 347 + 348 + def _eval_aseries(self, n, args0, x, logx):
 6 Collaborator ness01 added a note January 09, 2012 Look at the gamma function implementation for what this function should do. (You need to return something oscillatory as you do, which probably means that this is not going to be much good for limits since gruntz cannot handle it.) Collaborator raoulb added a note January 09, 2012 You mean I should look at polygamma or loggamma? Gamma itself does not have this function. Let me see what I can figure out. Collaborator ness01 added a note January 09, 2012 Oh you are right. Either is fine (I think...). … Collaborator raoulb added a note January 09, 2012 Hmm, for fresnel we can express the asymptotic expansion in 'closed' form, see: http://functions.wolfram.com/GammaBetaErf/FresnelS/06/02/ Collaborator raoulb added a note January 09, 2012 Btw, trying something like:  z = self.args[0] result = S.Half + 1/(pi*z)*C.sin(S.Half*pi*z**2) o = C.Order(1/z**3, x) return result._eval_nseries(x, n, logx) + o  to mimic the code of loggamma does only return an O term. I must admit that I do not fully understand what's going on on the sympy side here :-/ Collaborator ness01 added a note January 09, 2012 This is slightly tricky. The correct way to use aseries is a follows: loggamma(1/x).series(x) SymPy does not have a concept of "expansion at infinity". So _eval_aseries should find an asymptotic series expansion as x -> 0, with the understanding that self.args[0] will tend to infinity. … Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/utilities/lambdify.py 
 ... ... @@ -44,7 +44,7 @@ 44 44 #"uppergamma":"upper_gamma", 45 45 "LambertW":"lambertw", 46 46 "Matrix":"matrix", 47 - "conjugate":"conj",
 2 Collaborator ness01 added a note January 09, 2012 I think you should avoid this sort of unrelated change. Collaborator raoulb added a note January 09, 2012 Oops, this is a relict from an earlier commit. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Collaborator

Please add entries for fresnels and fresnelc to hyperexpand() table, so that e.g. integrate(sin(x**2), x, meijerg=True) returns a nice answer. There is an explanation on how to do this in the hyperexpand documentation (sphinx), if unclear ask here.

Regarding limits: there are two functions, "limit" and "gruntz". Limit is basically guesswork/heuristics whereas gruntz implements a "real" algorithm (guess which function I worked on a lot g). gruntz uses series expansions and cannot handle erf [simply because the necessary support code is not written. one needs to implement rewrite_as_tractable by defining a new helper function object, and then implement asymptotic series on the new object. ask if interested]. Making fresnel integrals work with gruntz would probably be non-trivial.

I'm not quite sure how limit works (except that it sometimes calls gruntz). Look there (simpy/series/limit.py) to figure out how to make the "standard" limits work without having to work with gruntz.

commented on the diff
 sympy/functions/special/tests/test_error_functions.py 
 ((43 lines not shown)) 77 + 78 + assert fresnelc(z).diff(z) == cos(pi*z**2/2) 79 + 80 + assert fresnelc(z).as_leading_term(z) == z 81 + 82 + assert fresnelc(z).rewrite(erf) == (S.One-I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) + I*erf((S.One-I)/2*sqrt(pi)*z)) 83 + 84 + assert fresnelc(z)._eval_nseries(z, n, None) == z*(-z**4)**n*(2**(-2*n)*pi**(2*n))/((4*n+1)*factorial(2*n)) 85 + 86 + assert fresnelc(z)._eval_aseries(z, oo, 0, 0) == S.Half + sin(pi*z**2/2)/(pi*z) 87 + 88 + assert fresnelc(w).is_real is True 89 + 90 + assert fresnelc(z).as_real_imag() == ((fresnelc(re(z) - I*re(z)*Abs(im(z))/Abs(re(z)))/2 + fresnelc(re(z) + I*re(z)*Abs(im(z))/Abs(re(z)))/2, 91 + I*(fresnelc(re(z) - I*re(z)*Abs(im(z))/Abs(re(z))) - fresnelc(re(z) + I*re(z)*Abs(im(z))/Abs(re(z))))* 92 + re(z)*Abs(im(z))/(2*im(z)*Abs(re(z)))))
 8 Collaborator ness01 added a note January 09, 2012 Please add tests for numerical evaluation (e.g. test against the integral definition by numerically evaluating an Integral). Collaborator raoulb added a note January 09, 2012 Shouldn't this go into the mpmath testsuite? Because the only thing I do is calling fresnel{s,c} from mpmath. Collaborator ness01 added a note January 09, 2012 Yes. You want to test that numerically evaluating a *sympy* object correctly calls the mpmath functions. (Or at least that's why I add these sorts of tests. I'm not "authoritive" ;) ) … Collaborator raoulb added a note January 09, 2012 Ah ok so testing if we use mpmath correctly. But in our case here we rely on the methods in Function and do not intoduce anything new. For this reason I think there is nothing to test. Collaborator ness01 added a note April 07, 2012 I still think this should be tested numerically. Collaborator ness01 added a note May 11, 2012 Please add from sympy.utilities.randtest import test_numerically test_numerically(re(fresnelc(z)), fresnelc(z).as_real_imag()[0], z) test_numerically(im(fresnelc(z)), fresnelc(z).as_real_imag()[1], z) test_numerically(fresnelc(z), fresnelc(z).rewrite(meijerg), z)  etc Collaborator raoulb added a note May 11, 2012 Done. Do we want even more? (If yes, which ones) Collaborator ness01 added a note May 11, 2012 On 11.05.2012 13:59, raoulb wrote: > + > + assert fresnelc(z).diff(z) == cos(pi*z**2/2) > + > + assert fresnelc(z).as_leading_term(z) == z > + > + assert fresnelc(z).rewrite(erf) == (S.One-I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) + I*erf((S.One-I)/2*sqrt(pi)*z)) > + > + assert fresnelc(z)._eval_nseries(z, n, None) == z*(-z**4)**n*(2**(-2*n)*pi**(2*n))/((4*n+1)*factorial(2*n)) > + > + assert fresnelc(z)._eval_aseries(z, oo, 0, 0) == S.Half + sin(pi*z**2/2)/(pi*z) > + > + assert fresnelc(w).is_real is True > + > + assert fresnelc(z).as_real_imag() == ((fresnelc(re(z) - I*re(z)*Abs(im(z))/Abs(re(z)))/2 + fresnelc(re(z) + I*re(z)*Abs(im(z))/Abs(re(z)))/2, > + I*(fresnelc(re(z) - I*re(z)*Abs(im(z))/Abs(re(z))) - fresnelc(re(z) + I*re(z)*Abs(im(z))/Abs(re(z))))* > + re(z)*Abs(im(z))/(2*im(z)*Abs(re(z))))) Done. Do we want even more? No I think that's enough. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Collaborator

I think a good this to do is some documentation how to add new special functions and what to take care of.
Maybe I will write down some points once I understand this better.

Same applies for the extension of gruntz etc.

Collaborator
Collaborator

About the hyperexpand stuff, I tried but my problem is that I only know fresnels(z) in terms of a 1F2 with argument -pi**2*z**4/16 and not z only:
http://functions.wolfram.com/GammaBetaErf/FresnelS/26/01/ShowAll.html

Hence I tried to transform this to match the form required by add(...) and came up with the rule:

add((S(3)/4,), (S(3)/2,S(7)/4), fresnels(root(-16*z/pi**2, 4)) * 6/(pi*(root(-16*z/pi**2, 4))**3)


The result of the integration is something A*fresnels(B*z) which looks promising
but A and B are big messy constants.

Collaborator

This is a first try. The results seem to be ok IFF these ploar factors can simplify to 1.

If we take principal roots then in the case of fresnels we get a prefactor of I and
the same for the argument. Hence they combine into I*fresnels(I*z) which is fresnels(z).
For the case of fresnelc we get factors of I and -I as -I*fresnelc(I*z) which is fresnelc(z).

So I think the rules are correct. But it would be nice if we can tell sympy to fully simplify.

Collaborator

I started a wiki page (I hope this is the right place and title.):

I plan to fill in the gap while I'm lerning how to do all the parts.

Collaborator

gruntz uses series expansions and cannot handle erf [simply because the necessary support code is not written. one needs to
implement rewrite_as_tractable by defining a new helper function object, and then implement asymptotic series on the new

I tried to make erf traktable by Gruntz, please see my "erf_tractable" branch.
It seems to work ... quite astonishing given my current knowledge about sympy.

But I'm not 100% sure if it really takes the correct codepath, even though I removed
everything from the erf class including direct evaluation at oo and -oo.

I'm not quite sure how limit works (except that it sometimes calls gruntz). Look there (simpy/series/limit.py) to figure out how to
make the "standard" limits work without having to work with gruntz.

Hmm, I don't like these heuristics. (Hardcoded tan/cot ... will cause work to extend when updating my trig branch.)

Collaborator
Collaborator
 sympy/functions/special/error_functions.py 
 ... ... @@ -82,3 +82,281 @@ def _eval_as_leading_term(self, x): 82 82 83 83 def _eval_is_real(self): 84 84 return self.args[0].is_real 85 + 86 +############################################################################### 87 +#################### FRESNEL INTEGRALS ######################################## 88 +############################################################################### 89 + 90 +class FresnelIntegral(Function): 91 + """ Base class for the Fresnel integrals.""" 92 + 93 + nargs = 1 94 + 95 + _trigfunc = None 96 + _sign = None 97 +
Collaborator

Making fresnel integrals work with gruntz would probably be non-trivial.

Maybe, but maybe not. We can rewrite the 'fresnel{s,c}' into 'erf'.
And if erf is tractable meybe we can do the fresnels this way.
It depends if we can do things like erf((1{+,-}I)/2*sqrt(pi)*z).
Currently we can not, Gruntz fails with an

NotImplementedError: Result depends on the sign of -sign((1/2 + I/2)**2)

Collaborator

I fully agree on the second part.

This is for formal reasons (typos, missing imports) etc
and I fixed this for you in my branch erf.

Some very stupid typos ... maybe it was a little bit too late last night.
This should be fixed now. The method was never called during limit
computation and I tested only erf(z), z->oo.

1. Your _eval_aseries is wrong. Try (1-erf(1/x)).rewrite('tractable').replace(erfs, lambda t:erfs(t).series(x)). This will show you the asymptotic expansion of erfc which you should compare to e.g. wikipedia. A "realistic" way to see this is to run gruntz((1-erf(x))*exp(x**2)*x, x, oo) - this should return 1/sqrt(pi) but it does not, because your series starts only at 1/x**3. Wolfram alpha is a neat place to test limits.

I wanted to implement 5.17 of Gruntz, which is what I'm supposed to do
if I understand the text correctly. But obviously failed with the formula here too :-/

Fixed this (at least think so) and the realistic example now returns 1/sqrt(pi).
I'm still not sure about the big-O term.

1. Why the limit still works with your broken code. I was somewhat befuddled by this, since your aseries cannot even be called. But all is well: rewrite_tractable must return a function with only algebraic singularities (except for explicit exp/log terms), and this enough knowledge to evaluate the limit.

Yes, the only function ever called was the rewrite tractable of erf.

1. Cosmetic change. Implement erfs._eval_rewrite_as_intractable (converting back to erf). This is needed so that e.g. gruntz(erf(x), x, 0) does not return the "obscure" erfs. [This is not the most elegant solution to the tractable/intractable rewriting, but the way we currently do it.]

Done.

1. Keep up the great work! If you have the time, please brush up your code and submit it for review.

Thanks! Yes I plan to do further work here, always as time permits.

Maybe I should merge this work into the erf improvement branch now.

And if you are bored, similar extensions are possible for zeta, Ei, and some bessel functions.

Yep :-)
Next to come after erf and fresnel. I plan to do the Airy functions too.

You may wish to consult Gruntz' thesis (see top of gruntz.py file) for extensive lists of examples.

I printed his thesis more than half a year ago but never finished reading it by now.
Maybe I should mention that I once had a lecture given by Dr. D. Gruntz (about software design).
It's a pitty that I never used this chance to talk about his algorithm.

Collaborator
Owner

The wiki is fine. When it gets fleshed out, we can migrate it to Sphinx.

Collaborator

Rebased over master. Now we should review the series code and fix the remaining issues.

BTW: There ecists nice results for the Laplace transform. But sympy can not compute then yet.
What's missing?

Collaborator

Oh yes, I almost forgot this. You should also extend the function _create_lookup_table at the top of sympy/integrals/meijerint.py. I'm afraid there is no documentation on how to do this, but I think it should be self-explanatory.

And then of course add tests for the transforms, and perhaps also some integrals involving fresenel functions (assuming they can be done, of course ^^).

 sympy/functions/special/error_functions.py 
 ((31 lines not shown)) 801 + changed = True 802 + 803 + nz = newarg.extract_multiplicatively(I) 804 + if nz is not None: 805 + prefact = cls._sign*I*prefact 806 + newarg = nz 807 + changed = True 808 + 809 + if changed: 810 + return prefact*cls(newarg) 811 + 812 + # Values at infinities 813 + if z is S.Infinity: 814 + return S.Half 815 + #elif z is S.NegativeInfinity: 816 + # return -S.Half
 3 Collaborator ness01 added a note January 15, 2012 Why is this commented out? Collaborator ness01 added a note January 15, 2012 Ah I guess you extract signs automatically ... if so just delete this. Collaborator raoulb added a note January 15, 2012 Ok. I left a comment explaining why these cases are missing. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/functions/special/error_functions.py 
 ((152 lines not shown)) 922 + ========== 923 + 924 + .. [1] http://en.wikipedia.org/wiki/Fresnel_integral 925 + .. [2] http://dlmf.nist.gov/7 926 + .. [3] http://mathworld.wolfram.com/FresnelIntegrals.html 927 + .. [4] http://functions.wolfram.com/GammaBetaErf/FresnelS 928 + """ 929 + 930 + _trigfunc = C.sin 931 + _sign = -S.One 932 + 933 + def _eval_rewrite_as_erf(self, z): 934 + return (S.One+I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) - I*erf((S.One-I)/2*sqrt(pi)*z)) 935 + 936 + def _eval_nseries(self, x, n, logx): 937 + return x**3*(-x**4)**n*(2**(-2*n-1)*pi**(2*n+1))/((4*n+3)*C.factorial(2*n+1))
 2 Collaborator ness01 added a note January 15, 2012 If you really want to keep this code, implement it using taylor_term. See e.g. the sin function. Collaborator raoulb added a note January 15, 2012 Done. I think is helpful for expressing the whole Taylor sum at once: z = Symbol("z") n = Symbol("n", integer=True) Sum(fresnelc(z).taylor_term(n, z), (n,0,oo))  Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/functions/special/error_functions.py 
 ((153 lines not shown)) 923 + 924 + .. [1] http://en.wikipedia.org/wiki/Fresnel_integral 925 + .. [2] http://dlmf.nist.gov/7 926 + .. [3] http://mathworld.wolfram.com/FresnelIntegrals.html 927 + .. [4] http://functions.wolfram.com/GammaBetaErf/FresnelS 928 + """ 929 + 930 + _trigfunc = C.sin 931 + _sign = -S.One 932 + 933 + def _eval_rewrite_as_erf(self, z): 934 + return (S.One+I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) - I*erf((S.One-I)/2*sqrt(pi)*z)) 935 + 936 + def _eval_nseries(self, x, n, logx): 937 + return x**3*(-x**4)**n*(2**(-2*n-1)*pi**(2*n+1))/((4*n+3)*C.factorial(2*n+1)) 938 +
 2 Collaborator ness01 added a note January 15, 2012 I think the remaining two functions should be deleted. (fresnels is intractable at infinity, but not even introducing a helper function is going to work here since gruntz (afaik) just cannot work with oscillatory limits. It cannot even do gruntz(sin(x)/x,x,oo)) Collaborator raoulb added a note January 15, 2012 Done Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
commented on the diff
 sympy/functions/special/tests/test_error_functions.py 
 ((16 lines not shown)) 223 + 224 + assert fresnels(z).diff(z) == sin(pi*z**2/2) 225 + 226 + assert fresnels(z).as_leading_term(z) == pi*z**3/6 227 + 228 + assert fresnels(z).rewrite(erf) == (S.One+I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) - I*erf((S.One-I)/2*sqrt(pi)*z)) 229 + 230 + assert fresnels(z)._eval_nseries(z, n, None) == z**3*(-z**4)**n*(2**(-2*n-1)*pi**(2*n+1))/((4*n+3)*factorial(2*n+1)) 231 + 232 + assert fresnels(z)._eval_aseries(z, oo, 0, 0) == S.Half - cos(pi*z**2/2)/(pi*z) 233 + 234 + assert fresnels(w).is_real is True 235 + 236 + assert fresnels(z).as_real_imag() == ((fresnels(re(z) - I*re(z)*Abs(im(z))/Abs(re(z)))/2 + fresnels(re(z) + I*re(z)*Abs(im(z))/Abs(re(z)))/2, 237 + I*(fresnels(re(z) - I*re(z)*Abs(im(z))/Abs(re(z))) - fresnels(re(z) + I*re(z)*Abs(im(z))/Abs(re(z))))* 238 + re(z)*Abs(im(z))/(2*im(z)*Abs(re(z)))))
 3 Collaborator ness01 added a note January 15, 2012 consider testing this numerically Collaborator raoulb added a note January 15, 2012 Added a test with concrete numbers. Should I remove the symbolc expression test? Collaborator ness01 added a note January 15, 2012 No, definitely keep the symbolic test. What I meant was something like test_numerically(re(fresnels(z)), fresnels(z).as_real_imag()[0]). [Or, if you don't like random tests, test both sides on some specific value you choose.] Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/functions/special/tests/test_error_functions.py 
 ((8 lines not shown)) 215 + assert fresnels(-oo) == -S.Half 216 + 217 + assert fresnels(z) == fresnels(z) 218 + assert fresnels(-z) == -fresnels(z) 219 + assert fresnels(I*z) == -I*fresnels(z) 220 + assert fresnels(-I*z) == I*fresnels(z) 221 + 222 + assert conjugate(fresnels(z)) == fresnels(conjugate(z)) 223 + 224 + assert fresnels(z).diff(z) == sin(pi*z**2/2) 225 + 226 + assert fresnels(z).as_leading_term(z) == pi*z**3/6 227 + 228 + assert fresnels(z).rewrite(erf) == (S.One+I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) - I*erf((S.One-I)/2*sqrt(pi)*z)) 229 + 230 + assert fresnels(z)._eval_nseries(z, n, None) == z**3*(-z**4)**n*(2**(-2*n-1)*pi**(2*n+1))/((4*n+3)*factorial(2*n+1))
 sympy/simplify/hyperexpand.py 
 ... ... @@ -246,6 +247,14 @@ def fm(a, z): 246 247 Matrix([[1, 0, 0]]), 247 248 Matrix([[-S.Half, S.Half, 0], [0, -S.Half, S.Half], [0, 2*z, 0]])) 248 249 250 + # FresnelS 251 + #add([S(3)/4], [S(3)/2,S(7)/4], fresnels(root(-16*z/pi**2, 4)) * 6/(pi*(root(-16*z/pi**2, 4))**3) ) 252 + add([S(3)/4], [S(3)/2,S(7)/4], fresnels(2/sqrt(pi)*root(-z,4)) * 6/(pi*8*(-z)**(S(3)/4)/pi**(S(3)/2) ) ) 253 + 254 + # FresnelC 255 + #add([S(1)/4], [S(1)/2,S(5)/4], fresnelc(root(-16*z/pi**2, 4)) / (pi*(root(-16*z/pi**2, 4))) ) 256 + add([S(1)/4], [S(1)/2,S(5)/4], fresnelc(2/sqrt(pi)*root(-z,4)) / (2/sqrt(pi)*root(-z,4)) )
Collaborator

Now the only things missing are related to the hyperexpand and meijerg stuff. I'll try to
do these soon.

@ness01 : Big Thanks for reviewing my branches!

 sympy/functions/special/error_functions.py 
 ((151 lines not shown)) 921 + .. [1] http://en.wikipedia.org/wiki/Fresnel_integral 922 + .. [2] http://dlmf.nist.gov/7 923 + .. [3] http://mathworld.wolfram.com/FresnelIntegrals.html 924 + .. [4] http://functions.wolfram.com/GammaBetaErf/FresnelS 925 + """ 926 + 927 + _trigfunc = C.sin 928 + _sign = -S.One 929 + 930 + @staticmethod 931 + def taylor_term(n, x, *previous_terms): 932 + if n < 0: 933 + return S.Zero 934 + else: 935 + x = sympify(x) 936 + return x**3*(-x**4)**n*(S(2)**(-2*n-1)*pi**(2*n+1))/((4*n+3)*C.factorial(2*n+1))
 1 Collaborator ness01 added a note January 15, 2012 I think it is costumary to declare this function @cacheit. Moreover, you should really use previous_terms ... if you want very many terms, evaluating the factorials and powers is probably slowest. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Collaborator
Collaborator

Rebased on master

Collaborator

Just as a reminder what I think has to be done before this can be pushed:

• Fix the hyperexpand table entries (bases, coefficients); test that expressions for fresnel(cs) in terms of hypergeometric functions come out "nice". Also test contiguous functions (i.e. demonstrate that the basis is "nice").
• As a culmination of this, make sure integral(sin(x**2)) etc work as expected.
• Add a numerical test for fresnel(sc).as_real_imag.
• Add tests for integration of fresnel(sc) (i.e. test your meijerg table entries).
Collaborator

As a culmination of this, make sure integral(sin(x**2)) etc work as expected.

Done, but some nasty gamma remain. They should cancel to 1.

Add tests for integration of fresnel(sc) (i.e. test your meijerg table entries).

The command

integrate(fresnels(x), x)

gives me a strange error, not sure yet whats wrong here.

Collaborator
 sympy/functions/special/error_functions.py 
 ((63 lines not shown)) 886 + if deep: 887 + hints['complex'] = False 888 + return (self.expand(deep, **hints), S.Zero) 889 + else: 890 + return (self, S.Zero) 891 + if deep: 892 + re, im = self.args[0].expand(deep, **hints).as_real_imag() 893 + else: 894 + re, im = self.args[0].as_real_imag() 895 + return (re, im) 896 + 897 + def as_real_imag(self, deep=True, **hints): 898 + x, y = self._as_real_imag(deep=deep, **hints) 899 + sq = -y**2/x**2 900 + re = S.Half*(self.func(x+x*sqrt(sq))+self.func(x-x*sqrt(sq))) 901 + im = x/(2*y) * sqrt(sq) * (self.func(x-x*sqrt(sq)) - self.func(x+x*sqrt(sq)))
 4 Collaborator ness01 added a note April 07, 2012 Can you add a comment where this comes from? Collaborator raoulb added a note April 07, 2012 These are from here:  # Fresnel S # http://functions.wolfram.com/06.32.19.0003.01 # http://functions.wolfram.com/06.32.19.0006.01 # Fresnel C # http://functions.wolfram.com/06.33.19.0003.01 # http://functions.wolfram.com/06.33.19.0006.01  Should I put this into the code? Do we want links like these inside the code? Collaborator ness01 added a note April 07, 2012 I'm not sure. @asmeurer ? Owner asmeurer added a note April 07, 2012 I think it's fine. The Wolfram Functions site is a solid resource. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/functions/special/error_functions.py 
 ((156 lines not shown)) 979 + 980 + _trigfunc = C.sin 981 + _sign = -S.One 982 + 983 + @staticmethod 984 + @cacheit 985 + def taylor_term(n, x, *previous_terms): 986 + if n < 0: 987 + return S.Zero 988 + else: 989 + x = sympify(x) 990 + if len(previous_terms) > 1: 991 + p = previous_terms[-1] 992 + return (-pi**2*x**4*(4*n - 1)/(8*n*(2*n + 1)*(4*n + 3))) * p 993 + else: 994 + return x**3*(-x**4)**n*(S(2)**(-2*n-1)*pi**(2*n+1))/((4*n+3)*C.factorial(2*n+1))
 sympy/functions/special/tests/test_error_functions.py 
 ((29 lines not shown)) 257 + assert fresnels(2+3*I).as_real_imag() == (fresnels(2 + 3*I)/2 + fresnels(2 - 3*I)/2, I*(fresnels(2 - 3*I) - fresnels(2 + 3*I))/2) 258 + 259 + assert fresnelc(0) == 0 260 + assert fresnelc(oo) == S.Half 261 + assert fresnelc(-oo) == -S.Half 262 + 263 + assert fresnelc(z) == fresnelc(z) 264 + assert fresnelc(-z) == -fresnelc(z) 265 + assert fresnelc(I*z) == I*fresnelc(z) 266 + assert fresnelc(-I*z) == -I*fresnelc(z) 267 + 268 + assert conjugate(fresnelc(z)) == fresnelc(conjugate(z)) 269 + 270 + assert fresnelc(z).diff(z) == cos(pi*z**2/2) 271 + 272 + assert fresnelc(z).rewrite(erf) == (S.One-I)/4 * (erf((S.One+I)/2*sqrt(pi)*z) + I*erf((S.One-I)/2*sqrt(pi)*z))
 sympy/integrals/tests/test_meijerint.py 
 ... ... @@ -586,3 +586,10 @@ def test_3153(): 586 586 assert not expr.has(hyper) 587 587 # XXX the expression is a mess, but actually upon differentiation and 588 588 # putting in numerical values seems to work... 589 + 590 + 591 +def test_fresnel(): 592 + from sympy import fresnels, fresnelc 593 + 594 + assert integrate(sin(pi*x**2/2),x) == 3*fresnels(x)*gamma(S(3)/4)/(4*gamma(S(7)/4))
Collaborator

Regarding the strange integration problem: this is because of the prefactors you put in. They are more complicated my code can handle, and moreover they are not right here. You will see that there is an expression like t**(9/4)*(t**2)**(3/4)*(-t)**(-3/4). Note the unnatural way in which the exponents are written, etc. This is because on the wolfram function site, the variable is an ordinary complex number, and all the exponentiation is ordinary complex exponentiation, with branch cuts and everything. We are using polar numbers, so you can most likely just replace -1 by polar_lift(-1) throughout and then simplify "naively".

I understand that it may not at all be clear what to do, neither about the meijerint nor the hyperexpand table. If you want me to, I can write these entries for you (it's not trivial and will probably take one or two hours) and perhaps an extended documentation at the same time. Of course, if you want to "figure it out yourself", even better :-).

Collaborator
commented

SymPy Bot Summary: There were test failures.

@raoulb: Please fix the test failures.

Test results html report: http://reviews.sympy.org/report/agZzeW1weTNyDAsSBFRhc2sY-OEWDA

Interpreter: /usr/bin/python (2.7.2-final-0)
Architecture: Linux (64-bit)
Cache: yes
Test command: setup.py test
master hash: 8426fe8
branch hash: 3609cc6

Automatic review by SymPy Bot.

Collaborator
commented

SymPy Bot Summary: There were test failures.

@raoulb: Please fix the test failures.

Test results html report: http://reviews.sympy.org/report/agZzeW1weTNyDAsSBFRhc2sYp6sWDA

Interpreter: /usr/bin/python (2.7.0-final-0)
Architecture: Linux (32-bit)
Cache: yes
Test command: setup.py test
master hash: 8426fe8
branch hash: 3609cc6

Automatic review by SymPy Bot.

Collaborator
commented

SymPy Bot Summary: There were test failures.

@raoulb: Please fix the test failures.

Test results html report: http://reviews.sympy.org/report/agZzeW1weTNyDAsSBFRhc2sYzpUYDA

Interpreter: /usr/bin/python (2.7.3-candidate-2)
Architecture: Linux (32-bit)
Cache: yes
Test command: setup.py test
master hash: 25904b8
branch hash: 0089534

Automatic review by SymPy Bot.

Collaborator
commented

This PR should be ready for a new final review.

There are still some (or rather many) nice integrals we can not solve.
For example S(z)^2, C(z)^2, S(z^2), C(z^2), S(z)*C(z) ...
All have solutions in terms of Fresenl and trigonometric functions.

Collaborator
commented

This needs to be rebased.

Collaborator
commented

Rebased

 sympy/core/expr.py 
 ... ... @@ -554,7 +554,7 @@ def _eval_is_positive(self): 554 554 return False 555 555 try: 556 556 # check to see that we can get a value 557 - n2 = self._eval_evalf(1) 557 + n2 = self.n(1)
 1 Collaborator ness01 added a note May 11, 2012 I'm somewhat unsure about this. The problem manifests as follows: gamma(3*exp_polar(I*pi)/2)._eval_evalf throws some mpmath internal exception. The problem is that _eval_evalf evaluates the argument to 1 binary digit accuracy, which apparently is -1, and then evaluates gamma at -1, causing the exception. I believe calling n instead alleviates the problem, since then a special routine for evaluating the gamma function is called, which knows about the exception, and tries evaluating at higher precision. [Which works, of course.] I wonder if something else should be fixed. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
commented on the diff
 sympy/functions/__init__.py 
 ... ... @@ -23,9 +22,8 @@ 23 22 asinh, acosh, atanh, acoth) 24 23 from sympy.functions.elementary.integers import floor, ceiling 25 24 from sympy.functions.elementary.piecewise import Piecewise, piecewise_fold 26 - 27 -from sympy.functions.special.error_functions import (erf, Ei, expint, E1, 28 - Si, Ci, Shi, Chi) 25 +from sympy.functions.special.error_functions import (erf, Ei, expint,
 2 Collaborator ness01 added a note May 11, 2012 Can you add the sympy. back in? I know it does not really matter, but I don't see why we should break the pattern either. Collaborator raoulb added a note May 11, 2012 Should be ok with latest push Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
commented on the diff
 sympy/functions/special/error_functions.py 
 ((123 lines not shown)) 950 + -fresnels(z) 951 + 952 + >>> fresnels(I*z) 953 + -I*fresnels(z) 954 + 955 + The Fresnel S integral obeys the mirror symmetry: 956 + 957 + >>> from sympy import conjugate 958 + >>> conjugate(fresnels(z)) 959 + fresnels(conjugate(z)) 960 + 961 + Differentiation with respect to z is supported: 962 + 963 + >>> from sympy import diff 964 + >>> diff(fresnels(z), z) 965 + sin(pi*z**2/2)
 2 Collaborator ness01 added a note May 11, 2012 Maybe add an integration example as well? Not too important. Collaborator raoulb added a note May 11, 2012 Done, I just used the defining integral. We could also show the Laplace transform. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/functions/special/tests/test_error_functions.py 
 ... ... @@ -1,6 +1,6 @@ 1 -from sympy import (symbols, expand, erf, nan, oo, Float, conjugate, sqrt, exp, pi, O, I, Ei, 2 - exp_polar, polar_lift, Symbol, I, exp, uppergamma, expint, log, loggamma, limit, 3 - meijerg, gamma, S, Shi, Chi, Si, Ci, E1, sin, cos, sinh, cosh) 1 +from sympy import (symbols, expand, expand_func, erf, nan, oo, Float, conjugate, sqrt, sin, cos, pi, re, im, Abs, O, 2 + factorial, exp_polar, polar_lift, Symbol, I, integrate, exp, uppergamma, expint, log, loggamma, limit, 3 + hyper, meijerg, gamma, S, Shi, Chi, Si, Ci, E1, Ei, sin, cos, sinh, cosh, fresnels, fresnelc)
 sympy/integrals/tests/test_transforms.py 
 ((12 lines not shown)) 478 487 def test_inverse_laplace_transform(): 479 488 from sympy import (expand, sinh, cosh, besselj, besseli, exp_polar, 480 - unpolarify, simplify) 489 + unpolarify, simplify, fresnels, fresnelc)
 2 Collaborator ness01 added a note May 11, 2012 This does not seem necessary? [presumably you meant to check inverse transforms and realised they did not work ^^] Collaborator raoulb added a note May 11, 2012 No, just pasted into the wrong function and forgot about it. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
 sympy/simplify/hyperexpand.py 
 ... ... @@ -162,6 +163,13 @@ def addb(ap, bq, B, C, M): 162 163 # This one is redundant. 163 164 add([-S.Half], [S.Half], exp(z) - sqrt(pi*z)*(-I)*erf(I*sqrt(z))) 164 165 166 + # Added to get nice results for Laplace transform of Fresnel functions 167 + # http://functions.wolfram.com/07.22.03.6437.01 168 + add([1], [S(3)/4, S(5)/4], 169 + sqrt(pi) * (cos(2*sqrt(polar_lift(-1)*z))*fresnelc(2*root(polar_lift(-1)*z,4)/sqrt(pi)) + 170 + sin(2*sqrt(polar_lift(-1)*z))*fresnels(2*root(polar_lift(-1)*z,4)/sqrt(pi))) 171 + / (2*root(polar_lift(-1)*z,4)))
 4 Collaborator ness01 added a note May 11, 2012 I hate to say this, but you should convert this entry to addb format ... Collaborator raoulb added a note May 11, 2012 I tried to do, but it was not so obvious to me what to put into the basis. I have only three slots in the basis but a few more function-terms which could be put there. Maybe we should discuss this on irc. But I won't be there tonight. Collaborator ness01 added a note May 11, 2012 Let w = exp(I*pi/4). I believe sqrt(pi)/(2*w) z**(-1/4) * (cosh(2*sqrt(z))*fresnelc(2*w*z**(1/4)/sqr(pi)) + I*sinh(2*sqrt(z))*fresnels(2*w/sqrt(pi)*z**(1/4))) sqrt(pi)/(2*w) z**(1/4) * (sinh(2*sqrt(z))*fresnelc(2*w*z**(1/4)/sqr(pi)) + I*cosh(2*sqrt(z))*fresnels(2*w/sqrt(pi)*z**(1/4))) 1  (the constant function 1) should make a good basis. Then the first row of M would be something like [-1/4, 1, 1/4], the last row would be [0, 0, 0] and the middle row (as well as checking my first row) I leave to you :-). Collaborator raoulb added a note May 12, 2012 Thanks, that was helpful! I didn't notice that grouping the terms this way leads to a good basis. Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
commented on the diff
 sympy/utilities/lambdify.py 
 ... ... @@ -50,7 +50,7 @@ 50 50 "Shi":"shi", 51 51 "Chi":"chi", 52 52 "Si":"si", 53 - "Ci":"ci", 53 + "Ci":"ci"
Collaborator
commented

(I'm waiting for the test runner but to come round once more)

 raoulb First implementation of Fresnel integrals fb2b533 raoulb Complex expansion for Fresnel integrals 7d75819 raoulb Asymptotic series expansions for Fresnel integrals b5d6444 raoulb Leading term expansion for Fresnel integrals 9dc7c0f raoulb Numerical evaluation for Fresnel integrals using mpmath ab67ab7 raoulb Series expansions for Fresnel integrals e5f83d9 raoulb Documentation and examples for Fresnel integrals bc3fb2d raoulb Better asymptotic series expansions for Fresnel integrals e4953d0 raoulb Examples in an IPython notebook 75c3ed3 raoulb Fixed numerical evaluation of Fresnel integrals. 5f909a4 raoulb Updated examples in an IPython notebook 8c5a8e2 raoulb Renamed Fresnel integrals to 'fresnels' and 'fresnelc' 379873a raoulb Add testcases for the Fresnel integrals 5080d5a raoulb Adding Fresnel integrals to the hyperexpand Tables a4e7985 raoulb Declared the Fresnel integrals to be unbranched. 53c03b1 raoulb Apply comments from pull request review cd79acc raoulb Added Meijer G representation of Fresnel Integrals e3b854a raoulb Caching 'taylor_term' functions 19685ac raoulb Improved Taylor terms of Fresnel integrals 86741fe raoulb Test integrals defining Fresnel functions e002dd8 raoulb Addressing latest comments on code 0cf95a1 raoulb Rules to rewrite fresnel{s,c} functions in terms of 1F2 hypergeometri… …c functions b9d4933 raoulb Fixed hypergeometric formula for Fresnel functions 694d99d raoulb Fix test_args test failures d26024f raoulb Fix integration of Fresnel functions a44422f raoulb Add tests for Fresnel integration 92f48ca
Collaborator
commented

With this change, I hope the Fresnel stuff is finished now.

Collaborator
commented

Actually, no. Something you did makes test_cg hang. I have no idea what, but you'll have to bisect this. [Note that the test runs in less then a few seconds in master.]

Collaborator
commented

Ah, so I'm responsible that it hangs :-/

Collaborator
commented

Collaborator
commented

Well it could just as easily be one of the patches I sent you, but it is confined to your branch, yes.

Collaborator
commented

This one hangs:

cg_simp(2 * Sum(CG(1,alpha,0,0,1,alpha), (alpha,-1,1))) == 6

Collaborator
commented

Actually, I think I found it to be your patch for the gamma poles.
At least without this change it runs fine.

Collaborator
commented
Collaborator
commented

Can you try this patch instead of the problematic commit:

diff --git a/sympy/core/function.py b/sympy/core/function.py
index 01c942d..22eb252 100644
--- a/sympy/core/function.py
+++ b/sympy/core/function.py
@@ -366,8 +366,12 @@ def _eval_evalf(self, prec):
return

# Convert all args to mpf or mpc
+        # Convert the arguments to *higher* precision than requested for the
+        # final result.
+        # XXX + 5 is a guess, it is similar to what is used in evalf.py. Should
+        #     we be more intelligent about it?
try:
-            args = [arg._to_mpmath(prec) for arg in self.args]
+            args = [arg._to_mpmath(prec + 5) for arg in self.args]
except ValueError:
return

 raoulb Tests for the gamma pole patch 2f579d2 raoulb A new rule in hyperexpand to get nice results for the Laplace transfo… …rm of Fresnel functions Examples without this formula: laplace_transform(fresnels(t), t, s, noconds=True) ⎛ ⎛ │ 4 ⎞ ⎛ 2⎞ ⎛ 2⎞⎞ ⎜ ┌─ ⎜ 1 │ -s ⎟ ⎜ s ⎟ ⎜ s ⎟⎟ -⎜2⋅s⋅ ├─ ⎜ │ ─────⎟ - π⋅sin⎜───⎟ - π⋅cos⎜───⎟⎟ ⎜ 1╵ 2 ⎜3/4, 5/4 │ 2⎟ ⎝2⋅π⎠ ⎝2⋅π⎠⎟ ⎝ ⎝ │ 16⋅π ⎠ ⎠ ──────────────────────────────────────────────────────── 2⋅π⋅s laplace_transform(fresnelc(t), t, s, noconds=True) ⎛ │ 4 ⎞ ⎛ 2⎞ ⎛ 2⎞ 3 ┌─ ⎜ 1 │ -s ⎟ 2 ⎜ s ⎟ 2 ⎜ s ⎟ 2⋅s ⋅ ├─ ⎜ │ ─────⎟ - 3⋅π ⋅sin⎜───⎟ + 3⋅π ⋅cos⎜───⎟ 1╵ 2 ⎜5/4, 7/4 │ 2⎟ ⎝2⋅π⎠ ⎝2⋅π⎠ ⎝ │ 16⋅π ⎠ ──────────────────────────────────────────────────────────── 2 6⋅π ⋅s And with this formula we can expand the 1F2 above: laplace_transform(fresnels(t), t, s, noconds=True) ⎛ 2⎞ ⎛ 2⎞ ⎛ 2⎞ ⎛ 2⎞ ⎜ s ⎟ ⎛s⎞ ⎜ s ⎟ ⎜ s ⎟ ⎛s⎞ ⎜ s ⎟ sin⎜───⎟⋅fresnels⎜─⎟ sin⎜───⎟ cos⎜───⎟⋅fresnelc⎜─⎟ cos⎜───⎟ ⎝2⋅π⎠ ⎝π⎠ ⎝2⋅π⎠ ⎝2⋅π⎠ ⎝π⎠ ⎝2⋅π⎠ - ──────────────────── + ──────── - ──────────────────── + ──────── s 2⋅s s 2⋅s laplace_transform(fresnelc(t), t, s, noconds=True) ⎛ 2⎞ ⎛ 2⎞ ⎛ 2⎞ ⎛ 2⎞ ⎜ s ⎟ ⎛s⎞ ⎜ s ⎟ ⎜ s ⎟ ⎛s⎞ ⎜ s ⎟ sin⎜───⎟⋅fresnelc⎜─⎟ sin⎜───⎟ cos⎜───⎟⋅fresnels⎜─⎟ cos⎜───⎟ ⎝2⋅π⎠ ⎝π⎠ ⎝2⋅π⎠ ⎝2⋅π⎠ ⎝π⎠ ⎝2⋅π⎠ ──────────────────── - ──────── - ──────────────────── + ──────── s 2⋅s s 2⋅s This result is nice and correct. 14ddbc1 raoulb Adapt tests to new Laplace transformations of Fresnels 2a47c0b raoulb Fix a remaining test failure 748d08b raoulb Rewrite Fresnel functions in terms of Meijer G e370757 raoulb Tests for Fresnel rewrites 248365e raoulb A different patch for the gamma pole issue (by ness) f3d3bc6 raoulb Fresnel function latex printing b3ba93f raoulb Add integral example to Fresnel docstring 62bd77c raoulb Addressed points from review discussion 008560c raoulb Manually tuned rule for Laplace transform of Fresnels 56c6af0
Collaborator
commented

SymPy Bot Summary: All tests have passed.

Test results html report: http://reviews.sympy.org/report/agZzeW1weTNyDAsSBFRhc2sYh7AXDA

Interpreter: /usr/bin/python (2.7.3-candidate-2)
Architecture: Linux (32-bit)
Cache: yes
Test command: setup.py test
master hash: 4c213da
branch hash: 56c6af0

Automatic review by SymPy Bot.

Collaborator
commented

Seems to work ok.

Collaborator
commented

SymPy Bot Summary: All tests have passed.

Test results html report: http://reviews.sympy.org/report/agZzeW1weTNyDAsSBFRhc2sYyO4XDA

Interpreter: /usr/bin/python (2.7.3-candidate-2)
Architecture: Linux (64-bit)
Cache: yes
Test command: setup.py test
master hash: 4c213da
branch hash: 56c6af0

Automatic review by SymPy Bot.

merged commit 30cb220 into from
closed this
Collaborator
commented

This is in. Good work!

Collaborator
commented

Thanks :-)
And also thanks for your support.

referenced this pull request
Closed

Added Fresnel integrals into functions/special/error_functions.py #1252

Showing 37 unique commits by 1 author.

May 12, 2012
First implementation of Fresnel integrals fb2b533
Complex expansion for Fresnel integrals 7d75819
Asymptotic series expansions for Fresnel integrals b5d6444
Leading term expansion for Fresnel integrals 9dc7c0f
Numerical evaluation for Fresnel integrals using mpmath ab67ab7
Series expansions for Fresnel integrals e5f83d9
Documentation and examples for Fresnel integrals bc3fb2d
Better asymptotic series expansions for Fresnel integrals e4953d0
Examples in an IPython notebook 75c3ed3
Fixed numerical evaluation of Fresnel integrals. 5f909a4
Updated examples in an IPython notebook 8c5a8e2
Renamed Fresnel integrals to 'fresnels' and 'fresnelc' 379873a
Add testcases for the Fresnel integrals 5080d5a
Adding Fresnel integrals to the hyperexpand Tables a4e7985
Declared the Fresnel integrals to be unbranched. 53c03b1
Apply comments from pull request review cd79acc
Added Meijer G representation of Fresnel Integrals e3b854a
Caching 'taylor_term' functions 19685ac
Improved Taylor terms of Fresnel integrals 86741fe
Test integrals defining Fresnel functions e002dd8
Addressing latest comments on code 0cf95a1
Rules to rewrite fresnel{s,c} functions in terms of 1F2 hypergeometri…
…c functions
b9d4933
Fixed hypergeometric formula for Fresnel functions 694d99d
Fix test_args test failures d26024f
Fix integration of Fresnel functions a44422f
Add tests for Fresnel integration 92f48ca
Tests for the gamma pole patch 2f579d2
A new rule in hyperexpand to get nice results for the Laplace transfo…
…rm of Fresnel functions

Examples without this formula:

laplace_transform(fresnels(t), t, s, noconds=True)

⎛         ⎛         │    4 ⎞        ⎛  2⎞        ⎛  2⎞⎞
⎜     ┌─  ⎜   1     │  -s  ⎟        ⎜ s ⎟        ⎜ s ⎟⎟
-⎜2⋅s⋅ ├─  ⎜         │ ─────⎟ - π⋅sin⎜───⎟ - π⋅cos⎜───⎟⎟
⎜    1╵ 2 ⎜3/4, 5/4 │     2⎟        ⎝2⋅π⎠        ⎝2⋅π⎠⎟
⎝         ⎝         │ 16⋅π ⎠                          ⎠
────────────────────────────────────────────────────────
2⋅π⋅s

laplace_transform(fresnelc(t), t, s, noconds=True)

⎛         │    4 ⎞           ⎛  2⎞           ⎛  2⎞
3  ┌─  ⎜   1     │  -s  ⎟      2    ⎜ s ⎟      2    ⎜ s ⎟
2⋅s ⋅ ├─  ⎜         │ ─────⎟ - 3⋅π ⋅sin⎜───⎟ + 3⋅π ⋅cos⎜───⎟
1╵ 2 ⎜5/4, 7/4 │     2⎟           ⎝2⋅π⎠           ⎝2⋅π⎠
⎝         │ 16⋅π ⎠
────────────────────────────────────────────────────────────
2
6⋅π ⋅s

And with this formula we can expand the 1F2 above:

laplace_transform(fresnels(t), t, s, noconds=True)

⎛  2⎞                  ⎛  2⎞      ⎛  2⎞                  ⎛  2⎞
⎜ s ⎟         ⎛s⎞      ⎜ s ⎟      ⎜ s ⎟         ⎛s⎞      ⎜ s ⎟
sin⎜───⎟⋅fresnels⎜─⎟   sin⎜───⎟   cos⎜───⎟⋅fresnelc⎜─⎟   cos⎜───⎟
⎝2⋅π⎠         ⎝π⎠      ⎝2⋅π⎠      ⎝2⋅π⎠         ⎝π⎠      ⎝2⋅π⎠
- ──────────────────── + ──────── - ──────────────────── + ────────
s               2⋅s               s               2⋅s

laplace_transform(fresnelc(t), t, s, noconds=True)

⎛  2⎞                  ⎛  2⎞      ⎛  2⎞                  ⎛  2⎞
⎜ s ⎟         ⎛s⎞      ⎜ s ⎟      ⎜ s ⎟         ⎛s⎞      ⎜ s ⎟
sin⎜───⎟⋅fresnelc⎜─⎟   sin⎜───⎟   cos⎜───⎟⋅fresnels⎜─⎟   cos⎜───⎟
⎝2⋅π⎠         ⎝π⎠      ⎝2⋅π⎠      ⎝2⋅π⎠         ⎝π⎠      ⎝2⋅π⎠
──────────────────── - ──────── - ──────────────────── + ────────
s               2⋅s               s               2⋅s

This result is nice and correct.
14ddbc1
Adapt tests to new Laplace transformations of Fresnels 2a47c0b
Fix a remaining test failure 748d08b
Rewrite Fresnel functions in terms of Meijer G e370757
Tests for Fresnel rewrites 248365e
A different patch for the gamma pole issue (by ness) f3d3bc6
Fresnel function latex printing b3ba93f
Add integral example to Fresnel docstring 62bd77c
Addressed points from review discussion 008560c
Manually tuned rule for Laplace transform of Fresnels 56c6af0