#11143: define symbolic functions for exponential integrals
-----------------------------+----------------------------------------------
Reporter: kcrisman | Owner: burcin
Type: defect | Status: new
Priority: major | Milestone: sage-4.7.1
Component: symbolics | Keywords: ei Ei special function maxima
Work_issues: | Upstream: N/A
Reviewer: Burcin Erocal | Author: Benjamin Jones
Merged: | Dependencies:
-----------------------------+----------------------------------------------
Changes (by benjaminfjones):
* cc: benjaminfjones (removed)
Comment:
The tests similar to `if z == 0` in `_eval_` do make a big difference. I
guess this is well known, but I didn't realize how big the speed
difference is.
I made a little table below of some timings. In the first table , `_eval_`
includes tests `if z == 0 and n > 1` and `if n == 0`. In the second table,
there are no such if statements (so the special cases are not
implemented). In the third table, the special cases are implementes as in
`sage/functions/generalized.py` where an approximation of `z` (or `n`) is
produced and checked instead of the symbol.
{{{
#!rst
with ``if z == 0``
============================================= ========
Test
Time
============================================= ========
sage: timeit("f = exp_integral_e(n,z)") 1.44 ms
sage: timeit("f = exp_integral_e(n,0)") 929 µs
sage: timeit("f = exp_integral_e(0,z)") 1.41 ms
sage: timeit("f = exp_integral_e(1.0,1.0)") 158 µs
============================================= ========
without ``if z == 0``
============================================= ======
Test
Time
============================================= ======
sage: timeit("f = exp_integral_e(n,z)") 541 µs
sage: timeit("f = exp_integral_e(n,0)") 300 µs
sage: timeit("f = exp_integral_e(0,z)") 299 µs
sage: timeit("f = exp_integral_e(1.0,1.0)") 161 µs
============================================= ======
with:
.. code-block:: python
try:
approx_z = ComplexIntervalField()(z)
# if z is zero and n > 1
if bool(approx_z.imag() == 0) and bool(approx_z.real() == 0):
if n > 1:
return 1/(n-1)
except: # z is symbolic
pass
# if n is zero
try:
approx_n = ComplexIntervalField()(n)
if bool(approx_n.imag() == 0) and bool(approx_n.real() == 0):
return exp(-z)/z
except: # n is symbolic
pass
============================================= ======
Test
Time
============================================= ======
sage: timeit("f = exp_integral_e(n,z)") 570 µs
sage: timeit("f = exp_integral_e(n,0)") 576 µs
sage: timeit("f = exp_integral_e(0,z)") 1.05 ms
sage: timeit("f = exp_integral_e(1.0,1.0)") 160 µs
============================================= ======
}}}
Timings in tables 2 and 3 are close except in the case where ``exp(-z)/z``
is
returned, whereas table 1 is anywhere from a factor of 3 to 5 slower than
in table 2 when a symbolic argument is passed. Anyway, I thought I'd
include the above for other beginners such as myself.
--------------
Another thing I discovered is that these two special cases that I was
implementing are known to Maxima:
{{{
sage: f = exp_integral_e(0,x)
sage: f
exp_integral_e(0,x)
sage: f.simplify()
e^(-x)/x
sage: nn = var('nn')
sage: assume(nn > 1)
sage: f = exp_integral_e(nn, 0)
sage: f
exp_integral_e(nn, 0)
sage: f.simplify()
1/(nn - 1)
}}}
So I think in the interest of speedy evaluation it's best to leave the
special
cases out, but point out in the documentation that Maxima knows about
them.
I've uploaded a new patch. I'll start implementing the other exponential
integrals using this as a template.
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/11143#comment:15>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sage-trac?hl=en.