Opened 11 years ago

# define symbolic functions for exponential integrals — at Version 27

Reported by: Owned by: kcrisman benjaminfjones major sage-5.3 symbolics ei Ei special function maxima sd32 sd40.5 Benjamin Jones Burcin Erocal, Karl-Dieter Crisman N/A #11513

We're missing some conversions from Maxima. Like exponential integrals of various kinds.

```sage: f(x) = e^(-x) * log(x+1)
sage: uu = integral(f,x,0,oo)
sage: uu
x |--> e*expintegral_e(1, 1)
```

See this ask.sagemath post for some details.

## Current symbol conversion table

From `sage.symbolic.pynac.symbol_table['maxima']` as of Sage-4.7

```Maxima ---> Sage

%gamma ---> euler_gamma
%pi ---> pi
(1+sqrt(5))/2 ---> golden_ratio
acos ---> arccos
acosh ---> arccosh
acot ---> arccot
acoth ---> arccoth
acsc ---> arccsc
acsch ---> arccsch
asec ---> arcsec
asech ---> arcsech
asin ---> arcsin
asinh ---> arcsinh
atan ---> arctan
atan2 ---> arctan2
atanh ---> arctanh
binomial ---> binomial
brun ---> brun
catalan ---> catalan
ceiling ---> ceil
cos ---> cos
delta ---> dirac_delta
elliptic_e ---> elliptic_e
elliptic_ec ---> elliptic_ec
elliptic_eu ---> elliptic_eu
elliptic_f ---> elliptic_f
elliptic_kc ---> elliptic_kc
elliptic_pi ---> elliptic_pi
exp ---> exp
expintegral_e ---> En
factorial ---> factorial
gamma_incomplete ---> gamma
glaisher ---> glaisher
imagpart ---> imag_part
inf ---> +Infinity
infinity ---> Infinity
khinchin ---> khinchin
kron_delta ---> kronecker_delta
li ---> dilog
log ---> log
log(2) ---> log2
mertens ---> mertens
minf ---> -Infinity
psi ---> psi
realpart ---> real_part
signum ---> sgn
sin ---> sin
twinprime ---> twinprime
```

# Summary of missing conversions

## Special functions defined in Maxima

```bessel_j (index, expr)         Bessel function, 1st kind
bessel_y (index, expr)         Bessel function, 2nd kind
bessel_i (index, expr)         Modified Bessel function, 1st kind
bessel_k (index, expr)         Modified Bessel function, 2nd kind
```
• Notes: bessel_I, bessel_J, etc. are functions in Sage for numerical evaluation. There is also the `Bessel` class, but no conversions from Maxima's bessel_i etc. to Sage.
```hankel_1 (v,z)                 Hankel function of the 1st kind
hankel_2 (v,z)                 Hankel function of the 2nd kind
struve_h (v,z)                 Struve H function
struve_l (v,z)                 Struve L function
```
• Notes: None of these functions are currently exposed at the top level in Sage. Evaluation is possible using mpmath.
```assoc_legendre_p[v,u] (z)      Legendre function of degree v and order u
assoc_legendre_q[v,u] (z)      Legendre function, 2nd kind
```
• Notes: In Sage we have `legendre_P(n, x)` and `legendre_Q(n, x)` both described as Legendre functions. It's not clear to me how there are related to Maxima's versions since the number of arguments differs.
```%f[p,q] ([], [], expr)         Generalized Hypergeometric function
hypergeometric(l1, l2, z)      Hypergeometric function
slommel
%m[u,k] (z)                    Whittaker function, 1st kind
%w[u,k] (z)                    Whittaker function, 2nd kind
```
• Notes: `hypergeometric(l1, l2, z)` needs a conversion to Sage's `hypergeometric_U`. The others can be evaluated using mpmath. `slommel` is presumably mpmath's `lommels1()` or `lommels2()` (or both?). This isn't well documented in Maxima.
```expintegral_e (v,z)            Exponential integral E
expintegral_e1 (z)             Exponential integral E1
expintegral_ei (z)             Exponential integral Ei
expintegral_li (z)             Logarithmic integral Li
expintegral_si (z)             Exponential integral Si
expintegral_ci (z)             Exponential integral Ci
expintegral_shi (z)            Exponential integral Shi
expintegral_chi (z)            Exponential integral Chi
erfc (z)                       Complement of the erf function
```
• Notes: The exponential integral functions `expintegral_e1` and `expintegral_ei (z)` are called `exponential_integral_1` and `Ei` resp. in Sage. They both need conversions. The rest need `BuiltinFunction` classes defined for them with evaluation handled by mpmath and the symbol table conversion added. Also, `erfc` is called `error_fcn`, so also needs a conversion.
```kelliptic (z)                  Complete elliptic integral of the first
kind (K)
parabolic_cylinder_d (v,z)     Parabolic cylinder D function
```
• Notes: `kelliptic(z)` needs a conversion to `elliptic_kc` in Sage and `parabolic_cylinder_d (v,z)` does not seem to be exposed at top level. It can be evaluated by mpmath.

Depends on #11513 and #11885.

Apply trac_11143.patch to the Sage library.

### comment:1 follow-ups: ↓ 3 ↓ 4 Changed 11 years ago by benjaminfjones

As far as I can tell, the general `exponential_e` function isn't available directly in Sage or in PARI (which is used to evaluate the `exponential_integral_1` function in Sage).

Also, it's possible to get maxima to rewrite the exponential integrals in terms of gamma functions like so:

```sage: maxima.eval('expintrep:gamma_incomplete')
'gamma_incomplete'
sage: maxima.integrate(exp(-x)*log(x+1), x, 0, oo)
%e*gamma_incomplete(0,1)
sage: N(e*gamma(0,1), digits=18)
0.596347362323194074
```

But as you see, `gamma_incomplete` isn't defined in Sage either, but the table `sage.symbolic.pynac.symbol_table['maxima']` lists the Sage equivalent `gamma`. Anyway, it should be possible to have the maxima interface (with the help of maxima itself) rewrite any exponential integral that Sage doesn't have in terms of gamma functions.

By the way, the owner on the ticket is @burcin, does that mean they are working on it currently?

### comment:3 in reply to: ↑ 1 Changed 11 years ago by kcrisman

As far as I can tell, the general `exponential_e` function isn't available directly in Sage or in PARI (which is used to evaluate the `exponential_integral_1` function in Sage).

That's unfortunate. However, mpmath seems to have it. So we could create a symbolic version and have the `_eval_` method call mpmath, which we seem to be moving to.

Also, it's possible to get maxima to rewrite the exponential integrals in terms of gamma functions like so:

```sage: maxima.eval('expintrep:gamma_incomplete')
'gamma_incomplete'
sage: maxima.integrate(exp(-x)*log(x+1), x, 0, oo)
%e*gamma_incomplete(0,1)
sage: N(e*gamma(0,1), digits=18)
0.596347362323194074
```

Interesting.

But as you see, `gamma_incomplete` isn't defined in Sage either, but the table `sage.symbolic.pynac.symbol_table['maxima']` lists the Sage equivalent `gamma`.

That should be ok; the whole point of the table is to convert into the Sage equivalent.

By the way, the owner on the ticket is @burcin, does that mean they are working on it currently?

No, that is an automatic thing that happens. It is possible to be designated an 'owner' of a ticket in a given component, which basically means you automatically get updates. If you want to 'own' it, please do! We really have plenty of special functions in Sage, but they are not always well exposed at the top level.

Incidentally, once you comment on a ticket, I believe the default is to copy you in on all replies. So you didn't have to cc: yourself specially :)

### comment:4 in reply to: ↑ 1 Changed 11 years ago by burcin

But as you see, `gamma_incomplete` isn't defined in Sage either, but the table `sage.symbolic.pynac.symbol_table['maxima']` lists the Sage equivalent `gamma`. Anyway, it should be possible to have the maxima interface (with the help of maxima itself) rewrite any exponential integral that Sage doesn't have in terms of gamma functions.

Incomplete gamma is defined in Sage. You can access it directly though `incomplete_gamma()` or `gamma_inc()`. The top level function `gamma()` behaves like incomplete gamma if you give it two arguments. IIRC, this is similar to maple.

By the way, the owner on the ticket is @burcin, does that mean they are working on it currently?

I am not working on it. The ticket status `assigned` is supposed to indicate that the owner is working on the problem, but we don't use that much either.

### comment:5 follow-up: ↓ 6 Changed 11 years ago by burcin

I guess the point of this ticket is to define symbolic function in Sage to represent exponential integrals, etc. The symbolic function class handles adding stuff to the conversion table automatically.

Can we replace this ticket with several beginner tickets? One for each function we are missing.

### comment:6 in reply to: ↑ 5 Changed 11 years ago by kcrisman

I guess the point of this ticket is to define symbolic function in Sage to represent exponential integrals, etc. The symbolic function class handles adding stuff to the conversion table automatically.

Can we replace this ticket with several beginner tickets? One for each function we are missing.

Well, that would be nice. But we could also presumably do it directly, if that would solve this problem for now. Well, either is fine as long as it were to happen. If you do split this, be sure to give a good template (I mean a link to the template, not write it yourself).

### comment:7 Changed 10 years ago by benjaminfjones

I'm attempting to write a template for the `expintegral_e` function (denoted E_n(z) in A&S). As I'm looking through the code, I see several models used for the functions and classes in `sage/functions/special.py` and `sage/functions/transcendental.py`

• Functions like `Function_exp_integral` (also called `Ei`) are defined as classes that inherit from `BuiltInFunction` and call the mpmath implementation when evaluated. The function `DickmanRho` also does this and includes other nice methods for approximating values and power series.
• Functions like `EllipticE` inherit from `MaximaFunction` which handles evaluation, etc. through Maxima. It seems there is an advantage to the mpmath implementation because presumably the interface is faster and the precision is arbitrary (whereas Maxima is limited to 53 bits).
• Functions like `Li` and `error_fcn` are simply wrapper functions that try to evaluate the input symbolically or numerically depending on context.
• In `sage/functions/trig.py` there is a mixture of classes that derive from `GinacFunction` (and include information in their `__init__` methods about conversions to other systems like Maxima or Mathematica) and also functions that derive from `BuiltinFunction`. It's not clear to me why some functions are Ginac and some are Builtin.

Questions:

• For the purposes of this ticket, what is recommended? @kcrisman 's comment leads me to believe that inheriting from the `BuiltinFunction` class and using `mpmath` for evaluation is preferable.
• Where should the various exponential integral special functions that we are missing go? `sage/functions/special.py`, `sage/functions/transcendental.py`, or somewhere else?

### comment:8 Changed 10 years ago by kcrisman

Those are good questions.

I think the most important thing is to make sure that whatever is implemented has

• good numerical evaluation (perhaps via mpmath)
• translates back and forth to Maxima properly (for integration and limits)

My sense is that BuiltinFunction would be best. GinacFunction probably is only good for things that in fact evaluate in Ginac. This explains trig.py. Ginac page shows that the ones which are GinacFunctions are exactly the ones which Ginac in fact has. I don't think it has most of these other functions.

As for MaximaFunction, it seems to inherit from BuiltinFunction and lives in the special functions file. This dates from the days when Sage had very few options for symbolic stuff and evaluation, and so it just does a few extra things. If we moved to mpmath for a given function, we would probably use BuiltinFunction and then add evaluation options for Maxima and add to the conversion dictionary as needed.

In fact, it wouldn't be a bad idea to have two different eval procedures if possible...

As for where such things go, probably it would make sense to separate a lot of these special functions out into a separate file. The distinction between transcendental and special is not totally obvious, for instance :)

By the way, we certainly want fewer of the wrapper functions! But that will take a lot of tedious work.

### comment:9 Changed 10 years ago by kcrisman

By the way, adding this will really be a great help. Sage has so many of the things almost anybody needs, but if you have to use mpmath or GSL or R or something else directly, it sort of makes Sage a moot point. The idea is having a one-stop shop.

### comment:10 Changed 10 years ago by benjaminfjones

I've uploaded a first shot at a template for the functions we want to add in this ticket. The patch exposes the general complex exponential integral function `En` also called `Function_exp_integral_En` by adding a class to `sage/functions/special.py` (I can change where it goes later on if needed / desired). Numerical evaluation is handled by mpmath and symbolics are handled by Sage (e.g. the derivative) and Maxima (e.g. the antiderivative).

One of the docstring examples shows that the integral of `e^(-x) * log(x+1)` from the ticket description is now evaluated properly.

### comment:11 Changed 10 years ago by benjaminfjones

• Description modified (diff)
• Keywords special function maxima added

### comment:12 Changed 10 years ago by burcin

• Authors set to Benjamin Jones
• Milestone set to sage-4.7.1
• Reviewers set to Burcin Erocal
• Summary changed from Add various Maxima special functions to symbol table to define symbolic functions for exponential integrals

The patch looks great. Thanks for the template. A few suggestions:

• The function name should be more explicit. I suggest `exp_integral_e`.
• In the top level name space `En` can be an alias for this function (though I'd prefer not to take up a two letter name), but we should have the long name available. It is easier to find all these functions by `exp_integral<tab>` than `E<tab>`.
• See _eval_ method of sage.functions.other.Function_gamma_inc for an example of how to find a common parent for the arguments
• The call to mpmath does not require the prec parameter any more. If you pass a Sage element to mpmath it handles the precision correctly. You can delete the code for this in `_evalf_()`.
• You should remove the `__call__()` method altogether. The only purpose of that is to display the deprecation notice. Since you are implementing a new function here, there is nothing being deprecated.
• In `_derivative_()` the call to this function should be `exp_integral_e(n-1, z)`, assuming you change the function name accordingly.

I changed the ticket description to limit this to implementing symbolic functions for exponential integrals. We can use the wiki page for a general overview of the progress on symbolic functions.

### comment:13 Changed 10 years ago by benjaminfjones

Thanks for the feedback, Burcin! I feel like I'm developing an understanding for how symbolic functions are handled in Sage now.

• I agree, the changed the name of the class to `Function_exp_integral_e` and the global function name to `exp_integral_e`. I think it would make sense as part of this ticket to add an alias of `exp_integral_1` for the existing `exponential_integral_1` to be consistent.
• Good point, I didn't think of that.
• The function now correctly coerces the two arguments to the same parent. I also added automatic evaluation of some special cases (n=0 or z=0) as in the `gamma_inc` function.
• I played around with removing the prec argument, but didn't get the results I expected. I found that passing the parent explicitly works. The common parent is determined in _eval_ (as in the `gamma_inc` function).
• Done.
• Done.

Let me know what you think. Once we've agreed on a good template for this one function, I will implement the rest of the exponential integral functions that are now listed on the wiki and upload to this ticket.

### comment:14 Changed 10 years ago by burcin

Perfect! I can only nitpick about documentation. :)

• lines should be < 80 characters long. This helps when viewing help in a terminal.
• I don't know how testing for 0 in `_eval_` effects performance. This is a hard problem. See the `_eval_` methods in `sage/functions/generalized.py` for a workaround if this is too slow.

You're right, we should add an alias `exp_integral_1`.

Thanks for working on this.

### comment:15 follow-up: ↓ 16 Changed 10 years ago by benjaminfjones

• Cc benjaminfjones removed

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.

```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.

### comment:16 in reply to: ↑ 15 Changed 10 years ago by burcin

The timings are really instructive, we should link to them from wiki page. Thank you for this careful study.

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 think your timings show that using the CIF approximation is not such a big penalty. Note that your timings also reflect the construction of the result and not just including that change. It is better if Sage can do the evaluation automatically without having to pass through a `simplify()` call. I'd like them in, with the approximation approach.

Since this approximation is being called so often, we should make it a method of symbolic expressions. I opened a new ticket for this: #11513. This ticket should depend on that.

I will provide a preliminary patch for #11513 soon.

### comment:17 Changed 10 years ago by burcin

I attached a very simple patch to #11513. Now we can write the check for zero as:

```def is_zero(z):
if isinstance(z, Expression):
return z._is_numerically_zero()
else:
return not z
```

It would be nice if we could simplify this further, but I need to go and do other things now. :)

### comment:18 Changed 10 years ago by benjaminfjones

The patch now depends on #11513

Here are new timings for the _eval_ method with _is_numerically_zero():

```.. code-block:: python

# special case: *quickly* test if (z == 0 and n > 1)
if isinstance(z, Expression):
if z._is_numerically_zero():
z_zero = True # for later
if n > 1:
return 1/(n-1)
else:
if not z:
z_zero = True
if n > 1:
return 1/(n-1)

======================================================  =======
Test                                                   Time
======================================================  =======
sage: timeit("f = exp_integral_e(n,z)")                 535 µs
sage: timeit("f = exp_integral_e(n,0)")                 482 µs
sage: assume(n > 1); timeit("f = exp_integral_e(n,0)")  3.56 ms
sage: timeit("f = exp_integral_e(0,z)")                 968 µs
sage: timeit("f = exp_integral_e(1.0,1.0)")             160 µs
======================================================  =======
```

I realized that in row 2 of the previous timings I neglected to assume n > 1 so those timings aren't giving much information since the expression is left unevaluated like in row 1. The new row 3 includes that assumption so that the simplified result 1/(n-1) is created and returned.

I'll update the timings above and move these tables to the wiki.

### Changed 10 years ago by benjaminfjones

added the symbolic function `exp_integral_e`

### comment:19 follow-up: ↓ 20 Changed 10 years ago by benjaminfjones

• Owner changed from burcin to benjaminfjones

In the patch, I'm added a function to `sage/functions/special.py`. But with the six new functions, this is going to be *a lot* of code in the one file.

I was thinking of moving the six new functions to a new file `sage/functions/exp_integral.py`. Any thoughts? If that seems like a good idea, does it also make sense to move the exp integrals that already exist in Sage to the same place (e.g. `exponential_integral_1` lives now in `sage/functions/transcendental.py`.

### comment:20 in reply to: ↑ 19 Changed 10 years ago by kcrisman

I was thinking of moving the six new functions to a new file `sage/functions/exp_integral.py`. Any thoughts? If that seems like a good idea, does it also make sense to move the exp integrals that already exist in Sage to the same place (e.g. `exponential_integral_1` lives now in `sage/functions/transcendental.py`.

Yes, absolutely. The functions/ folder needs to be reorganized, though obviously this is lower priority. Make sure that it still shows up in the reference manual, that all imports work fine, etc. But these functions are all supposed to be accessed through the top level namespace anyway, so this is a great idea to make it easier to organize.

### comment:21 Changed 10 years ago by benjaminfjones

I've uploaded a new partial patch for the ticket. I wanted to post this now before I finish the patch so people can comment on the consolidation of exponential functions in the new file `sage/functions/exp_integral.py` and/or anything else.

If the basic organisation looks good, I'll finish up adding the remaining exponential integrals and upload a new patch.

### comment:22 Changed 10 years ago by kcrisman

• Dependencies set to #11513
• Reviewers changed from Burcin Erocal to Burcin Erocal, Karl-Dieter Crisman

A few comment:

• This will conflict (slightly) with #11043, I think. You can help their cause by doing
```from sage.plot.all import plot
```
I believe. The point is making sure we don't import numpy and other things like that on startup. It's possible that some of the other imports will have this problem, but hopefully not (?).
• I don't really understand coercion, so I'm reluctant to comment on the coercion stuff in `_eval_`, though I'd be glad if you explained that (I don't recall seeing it in these types of functions before).
• This seems to depend on #11513 still, so I'm adding that. But that still does not have positive review. Just pointing it out.
• Line 260: ` raise NotImplementedError("The derivative of is only implemented for n = 1, 2, 3, ...") ` seems to be missing something.

On a cursory reading, this looks really nice. Certainly you should go ahead with the full reorganization, that will help a lot.

### comment:24 follow-up: ↓ 25 Changed 10 years ago by benjaminfjones

Trying to finish up the patch, I've run into a problem evaluating any of my new functions at python floats. For example, apply the patch and try:

```sage: exp_integral_e1(float(1))
ERROR: An unexpected error occurred while tokenizing input
The following traceback may be corrupted or invalid
The error message is: ('EOF in multi-line statement', (690, 0))

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/Users/jonesbe/sage/sage-4.7.2.alpha2/devel/sage-test/sage/<ipython console> in <module>()

/Users/jonesbe/sage/latest/local/lib/python2.6/site-packages/sage/symbolic/function.so in sage.symbolic.function.Function.__call__ (sage/symbolic/function.cpp:4599)()

/Users/jonesbe/sage/latest/local/lib/python2.6/site-packages/sage/functions/exp_integral.pyc in _eval_(self, z)
335         """
336         if not isinstance(z, Expression) and is_inexact(z):
--> 337             return self._evalf_(z, parent(z))
338
339         return None # leaves the expression unevaluated

/Users/jonesbe/sage/latest/local/lib/python2.6/site-packages/sage/functions/exp_integral.pyc in _evalf_(self, z, parent)
350         """
351         import mpmath
--> 352         return mpmath_utils.call(mpmath.e1, z, parent=parent)
353
354     def _derivative_(self, z, diff_param=None):

/Users/jonesbe/sage/latest/local/lib/python2.6/site-packages/sage/libs/mpmath/utils.so in sage.libs.mpmath.utils.call (sage/libs/mpmath/utils.c:5277)()

AttributeError: type object 'float' has no attribute 'prec'
```

You also get the error if you try to plot any of the exponential integral functions as they are written unless you wrap the input with `RDF` or something similar.

The error is being raised inside the `call` function in `sage/libs/mpmath/util.pyx`. I've looked through that code and thought about what would happen if the `prec` option is not specified (as in my code) and the parent is `None` (as when a python float is passed), but I can't figure out why it doesn't work to pass a float.

On the other hand, changing the lines in the `_evalf` method

```import mpmath
return mpmath_utils.call(mpmath.e1, z, parent=parent)
```

to

```import mpmath
if isinstance(parent, Parent) and hasattr(parent, 'prec'):
prec = parent.prec()
else:
prec = 53
return mpmath_utils.call(mpmath.si, z, prec=prec)
```

fixes the error.

What do people think? Is this a bug in the `call` function (which claims it will accept any type that mpmath handles natively like python floats) or is there something wrong with my code?

### comment:25 in reply to: ↑ 24 Changed 10 years ago by burcin

What do people think? Is this a bug in the `call` function (which claims it will accept any type that mpmath handles natively like python floats) or is there something wrong with my code?

It would be better to fix the `mpmath_call()` function. This is called from many places and duplicating the code to check if `parent` has a `prec()` method everywhere is error prone.

Thanks for your work on this so far. I will try to come up with an acceptable implementation for #11513 next week. I hope it doesn't hold this up for long.

### comment:26 Changed 10 years ago by benjaminfjones

Ok, I've created a new ticket #11885 to fix the issue with `mpmath.utils.call` and uploaded a patch there. I'll upload the finished patch for #11143 that depends on it later this afternoon.

### comment:27 Changed 10 years ago by benjaminfjones

• Description modified (diff)
Note: See TracTickets for help on using tickets.