Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/functions/exp_integral.py
8815 views
1
r"""
2
Exponential Integrals
3
4
AUTHORS:
5
6
- Benjamin Jones (2011-06-12)
7
8
This module provides easy access to many exponential integral
9
special functions. It utilizes Maxima's `special functions package`_ and
10
the `mpmath library`_.
11
12
REFERENCES:
13
14
- [AS]_ Abramowitz and Stegun: *Handbook of Mathematical Functions*
15
- Wikipedia Entry: http://en.wikipedia.org/wiki/Exponential_integral
16
- Online Encyclopedia of Special Function: http://algo.inria.fr/esf/index.html
17
- NIST Digital Library of Mathematical Functions: http://dlmf.nist.gov/
18
- Maxima `special functions package`_
19
- `mpmath library`_
20
21
.. [AS] 'Handbook of Mathematical Functions', Milton Abramowitz and Irene
22
A. Stegun, National Bureau of Standards Applied Mathematics Series, 55.
23
See also http://www.math.sfu.ca/~cbm/aands/.
24
.. _`special functions package`: http://maxima.sourceforge.net/docs/manual/en/maxima_15.html
25
.. _`mpmath library`: http://code.google.com/p/mpmath/
26
27
AUTHORS:
28
29
- Benjamin Jones
30
31
Implementations of the classes ``Function_exp_integral_*``.
32
33
- David Joyner and William Stein
34
35
Authors of the code which was moved from special.py and trans.py.
36
Implementation of :meth:`exp_int` (from sage/functions/special.py).
37
Implementation of :meth:`exponential_integral_1` (from
38
sage/functions/transcendental.py).
39
40
"""
41
42
#*****************************************************************************
43
# Copyright (C) 2011 Benjamin Jones <[email protected]>
44
#
45
# Distributed under the terms of the GNU General Public License (GPL)
46
#
47
# This code is distributed in the hope that it will be useful,
48
# but WITHOUT ANY WARRANTY; without even the implied warranty of
49
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
50
# General Public License for more details.
51
#
52
# The full text of the GPL is available at:
53
#
54
# http://www.gnu.org/licenses/
55
#*****************************************************************************
56
57
import sage.interfaces.all
58
from sage.misc.sage_eval import sage_eval
59
from sage.symbolic.function import BuiltinFunction, is_inexact
60
from sage.calculus.calculus import maxima
61
from sage.symbolic.expression import Expression
62
from sage.structure.parent import Parent
63
from sage.structure.coerce import parent
64
from sage.libs.mpmath import utils as mpmath_utils
65
mpmath_utils_call = mpmath_utils.call # eliminate some overhead in _evalf_
66
67
from sage.rings.rational_field import RationalField
68
from sage.rings.real_mpfr import RealField
69
from sage.rings.complex_field import ComplexField
70
from sage.rings.all import ZZ, QQ, RR, RDF
71
from sage.functions.log import exp, log
72
from sage.functions.trig import sin, cos
73
from sage.functions.hyperbolic import sinh, cosh
74
import math
75
76
77
class Function_exp_integral_e(BuiltinFunction):
78
r"""
79
The generalized complex exponential integral `E_n(z)` defined by
80
81
.. math::
82
83
\operatorname{E_n}(z) = \int_1^{\infty} \frac{e^{-z t}}{t^n} \; dt
84
85
for complex numbers `n` and `z`, see [AS]_ 5.1.4.
86
87
The special case where `n = 1` is denoted in Sage by
88
``exp_integral_e1``.
89
90
EXAMPLES:
91
92
Numerical evaluation is handled using mpmath::
93
94
sage: N(exp_integral_e(1,1))
95
0.219383934395520
96
sage: exp_integral_e(1, RealField(100)(1))
97
0.21938393439552027367716377546
98
99
We can compare this to PARI's evaluation of
100
:meth:`exponential_integral_1`::
101
102
sage: N(exponential_integral_1(1))
103
0.219383934395520
104
105
We can verify one case of [AS]_ 5.1.45, i.e.
106
`E_n(z) = z^{n-1}\Gamma(1-n,z)`::
107
108
sage: N(exp_integral_e(2, 3+I))
109
0.00354575823814662 - 0.00973200528288687*I
110
sage: N((3+I)*gamma(-1, 3+I))
111
0.00354575823814662 - 0.00973200528288687*I
112
113
Maxima returns the following improper integral as a multiple of
114
``exp_integral_e(1,1)``::
115
116
sage: uu = integral(e^(-x)*log(x+1),x,0,oo)
117
sage: uu
118
e*exp_integral_e(1, 1)
119
sage: uu.n(digits=30)
120
0.596347362323194074341078499369
121
122
Symbolic derivatives and integrals are handled by Sage and Maxima::
123
124
sage: x = var('x')
125
sage: f = exp_integral_e(2,x)
126
sage: f.diff(x)
127
-exp_integral_e(1, x)
128
129
sage: f.integrate(x)
130
-exp_integral_e(3, x)
131
132
sage: f = exp_integral_e(-1,x)
133
sage: f.integrate(x)
134
Ei(-x) - gamma(-1, x)
135
136
Some special values of ``exp_integral_e`` can be simplified.
137
[AS]_ 5.1.23::
138
139
sage: exp_integral_e(0,x)
140
e^(-x)/x
141
142
[AS]_ 5.1.24::
143
144
sage: exp_integral_e(6,0)
145
1/5
146
sage: nn = var('nn')
147
sage: assume(nn > 1)
148
sage: f = exp_integral_e(nn,0)
149
sage: f.simplify()
150
1/(nn - 1)
151
152
153
ALGORITHM:
154
155
Numerical evaluation is handled using mpmath, but symbolics are handled
156
by Sage and Maxima.
157
158
"""
159
def __init__(self):
160
"""
161
See the docstring for :meth:`Function_exp_integral_e`.
162
163
EXAMPLES::
164
165
sage: exp_integral_e(1,0)
166
exp_integral_e(1, 0)
167
168
"""
169
BuiltinFunction.__init__(self, "exp_integral_e", nargs=2,
170
latex_name=r'exp_integral_e',
171
conversions=dict(maxima='expintegral_e'))
172
173
def _eval_(self, n, z):
174
"""
175
EXAMPLES::
176
177
sage: exp_integral_e(1.0, x)
178
exp_integral_e(1.00000000000000, x)
179
sage: exp_integral_e(x, 1.0)
180
exp_integral_e(x, 1.00000000000000)
181
sage: exp_integral_e(1.0, 1.0)
182
0.219383934395520
183
184
"""
185
if not isinstance(n, Expression) and not isinstance(z, Expression) and \
186
(is_inexact(n) or is_inexact(z)):
187
coercion_model = sage.structure.element.get_coercion_model()
188
n, z = coercion_model.canonical_coercion(n, z)
189
return self._evalf_(n, z, parent(n))
190
191
z_zero = False
192
# special case: z == 0 and n > 1
193
if isinstance(z, Expression):
194
if z.is_trivial_zero():
195
z_zero = True # for later
196
if n > 1:
197
return 1/(n-1)
198
else:
199
if not z:
200
z_zero = True
201
if n > 1:
202
return 1/(n-1)
203
204
# special case: n == 0
205
if isinstance(n, Expression):
206
if n.is_trivial_zero():
207
if z_zero:
208
return None
209
else:
210
return exp(-z)/z
211
else:
212
if not n:
213
if z_zero:
214
return None
215
else:
216
return exp(-z)/z
217
218
return None # leaves the expression unevaluated
219
220
def _evalf_(self, n, z, parent=None):
221
"""
222
EXAMPLES::
223
224
sage: N(exp_integral_e(1, 1+I))
225
0.000281624451981418 - 0.179324535039359*I
226
sage: exp_integral_e(1, RealField(100)(1))
227
0.21938393439552027367716377546
228
229
"""
230
import mpmath
231
return mpmath_utils.call(mpmath.expint, n, z, parent=parent)
232
233
def _derivative_(self, n, z, diff_param=None):
234
"""
235
If `n` is an integer strictly larger than 0, then the derivative of
236
`E_n(z)` with respect to `z` is
237
`-E_{n-1}(z)`. See [AS]_ 5.1.26.
238
239
EXAMPLES::
240
241
sage: x = var('x')
242
sage: f = exp_integral_e(2,x)
243
sage: f.diff(x)
244
-exp_integral_e(1, x)
245
246
sage: f = exp_integral_e(2,sqrt(x))
247
sage: f.diff(x)
248
-1/2*exp_integral_e(1, sqrt(x))/sqrt(x)
249
250
"""
251
if n in ZZ and n > 0:
252
return -1*exp_integral_e(n-1,z)
253
else:
254
raise NotImplementedError("The derivative of this function is only implemented for n = 1, 2, 3, ...")
255
256
exp_integral_e = Function_exp_integral_e()
257
258
259
class Function_exp_integral_e1(BuiltinFunction):
260
r"""
261
The generalized complex exponential integral `E_1(z)` defined by
262
263
.. math::
264
265
\operatorname{E_1}(z) = \int_z^\infty \frac{e^{-t}}{t}\; dt
266
267
see [AS]_ 5.1.4.
268
269
EXAMPLES:
270
271
Numerical evaluation is handled using mpmath::
272
273
sage: N(exp_integral_e1(1))
274
0.219383934395520
275
sage: exp_integral_e1(RealField(100)(1))
276
0.21938393439552027367716377546
277
278
We can compare this to PARI's evaluation of
279
:meth:`exponential_integral_1`::
280
281
sage: N(exp_integral_e1(2.0))
282
0.0489005107080611
283
sage: N(exponential_integral_1(2.0))
284
0.0489005107080611
285
286
Symbolic derivatives and integrals are handled by Sage and Maxima::
287
288
sage: x = var('x')
289
sage: f = exp_integral_e1(x)
290
sage: f.diff(x)
291
-e^(-x)/x
292
293
sage: f.integrate(x)
294
-exp_integral_e(2, x)
295
296
ALGORITHM:
297
298
Numerical evaluation is handled using mpmath, but symbolics are handled
299
by Sage and Maxima.
300
301
"""
302
def __init__(self):
303
"""
304
See the docstring for :class:`Function_exp_integral_e1`.
305
306
EXAMPLES::
307
308
sage: exp_integral_e1(1)
309
exp_integral_e1(1)
310
311
"""
312
BuiltinFunction.__init__(self, "exp_integral_e1", nargs=1,
313
latex_name=r'exp_integral_e1',
314
conversions=dict(maxima='expintegral_e1'))
315
316
def _eval_(self, z):
317
"""
318
EXAMPLES::
319
320
sage: exp_integral_e1(x)
321
exp_integral_e1(x)
322
sage: exp_integral_e1(1.0)
323
0.219383934395520
324
325
"""
326
if not isinstance(z, Expression) and is_inexact(z):
327
return self._evalf_(z, parent(z))
328
329
return None # leaves the expression unevaluated
330
331
def _evalf_(self, z, parent=None):
332
"""
333
EXAMPLES::
334
335
sage: N(exp_integral_e1(1+I))
336
0.000281624451981418 - 0.179324535039359*I
337
sage: exp_integral_e1(RealField(200)(0.5))
338
0.55977359477616081174679593931508523522684689031635351524829
339
340
"""
341
import mpmath
342
return mpmath_utils_call(mpmath.e1, z, parent=parent)
343
344
def _derivative_(self, z, diff_param=None):
345
"""
346
The derivative of `E_1(z)` is `-e^{-z}/z`. See [AS], 5.1.26.
347
348
EXAMPLES::
349
350
sage: x = var('x')
351
sage: f = exp_integral_e1(x)
352
sage: f.diff(x)
353
-e^(-x)/x
354
355
sage: f = exp_integral_e1(x^2)
356
sage: f.diff(x)
357
-2*e^(-x^2)/x
358
359
"""
360
return -exp(-z)/z
361
362
exp_integral_e1 = Function_exp_integral_e1()
363
364
365
class Function_log_integral(BuiltinFunction):
366
r"""
367
The logarithmic integral `\operatorname{li}(z)` defined by
368
369
.. math::
370
371
\operatorname{li}(x) = \int_0^z \frac{dt}{\ln(t)} = \operatorname{Ei}(\ln(x))
372
373
for x > 1 and by analytic continuation for complex arguments z (see [AS]_ 5.1.3).
374
375
EXAMPLES:
376
377
Numerical evaluation for real and complex arguments is handled using mpmath::
378
379
sage: N(log_integral(3))
380
2.16358859466719
381
sage: N(log_integral(3), digits=30)
382
2.16358859466719197287692236735
383
sage: log_integral(ComplexField(100)(3+I))
384
2.2879892769816826157078450911 + 0.87232935488528370139883806779*I
385
sage: log_integral(0)
386
0
387
388
Symbolic derivatives and integrals are handled by Sage and Maxima::
389
390
sage: x = var('x')
391
sage: f = log_integral(x)
392
sage: f.diff(x)
393
1/log(x)
394
395
sage: f.integrate(x)
396
x*log_integral(x) - Ei(2*log(x))
397
398
Here is a test from the mpmath documentation. There are
399
1,925,320,391,606,803,968,923 many prime numbers less than 1e23. The
400
value of ``log_integral(1e23)`` is very close to this::
401
402
sage: log_integral(1e23)
403
1.92532039161405e21
404
405
ALGORITHM:
406
407
Numerical evaluation is handled using mpmath, but symbolics are handled
408
by Sage and Maxima.
409
410
REFERENCES:
411
412
- http://en.wikipedia.org/wiki/Logarithmic_integral_function
413
- mpmath documentation: `logarithmic-integral`_
414
415
.. _`logarithmic-integral`: http://mpmath.googlecode.com/svn/trunk/doc/build/functions/expintegrals.html#logarithmic-integral
416
417
418
"""
419
def __init__(self):
420
"""
421
See the docstring for ``Function_log_integral``.
422
423
EXAMPLES::
424
425
sage: log_integral(3)
426
log_integral(3)
427
428
"""
429
BuiltinFunction.__init__(self, "log_integral", nargs=1,
430
latex_name=r'log_integral',
431
conversions=dict(maxima='expintegral_li'))
432
433
def _eval_(self, z):
434
"""
435
EXAMPLES::
436
437
sage: z = var('z')
438
sage: log_integral(z)
439
log_integral(z)
440
sage: log_integral(3.0)
441
2.16358859466719
442
sage: log_integral(0)
443
0
444
445
"""
446
if isinstance(z, Expression):
447
if z.is_trivial_zero(): # special case: z = 0
448
return z
449
else:
450
if is_inexact(z):
451
return self._evalf_(z, parent(z))
452
elif not z:
453
return z
454
return None # leaves the expression unevaluated
455
456
def _evalf_(self, z, parent=None):
457
"""
458
EXAMPLES::
459
460
sage: N(log_integral(1e6))
461
78627.5491594622
462
sage: log_integral(RealField(200)(1e6))
463
78627.549159462181919862910747947261161321874382421767074759
464
465
"""
466
import mpmath
467
return mpmath_utils_call(mpmath.li, z, parent=parent)
468
469
def _derivative_(self, z, diff_param=None):
470
r"""
471
The derivative of `\operatorname{li}(z) is `1/log(z)`.
472
473
EXAMPLES::
474
475
sage: x = var('x')
476
sage: f = log_integral(x)
477
sage: f.diff(x)
478
1/log(x)
479
480
sage: f = log_integral(x^2)
481
sage: f.diff(x)
482
2*x/log(x^2)
483
484
"""
485
return 1/log(z)
486
487
li = log_integral = Function_log_integral()
488
489
class Function_log_integral_offset(BuiltinFunction):
490
r"""
491
The offset logarithmic integral, or Eulerian logarithmic integral,
492
`\operatorname{Li}(x)` is defined by
493
494
.. math::
495
496
\operatorname{Li}(x) = \int_2^x \frac{dt}{ln(t)} =
497
\operatorname{li}(x)-\operatorname{li}(2)
498
499
for `x \ge 2`.
500
501
The offset logarithmic integral should also not be confused with the
502
polylogarithm (also denoted by `\operatorname{Li}(x)` ), which is
503
implemented as :class:`sage.functions.log.Function_polylog`.
504
505
`\operatorname{Li}(x)` is identical to `\operatorname{li}(x)` except that
506
the lower limit of integration is `2` rather than `0` to avoid the
507
singularity at `x = 1` of
508
509
.. math::
510
511
\frac{1}{ln(t)}
512
513
See :class:`Function_log_integral` for details of `\operatorname{li}(x)`.
514
Thus `\operatorname{Li}(x)` can also be represented by
515
516
.. math::
517
518
\operatorname{Li}(x) = \operatorname{li}(x)-\operatorname{li}(2)
519
520
So we have::
521
522
sage: li(4.5)-li(2.0)-Li(4.5)
523
0.000000000000000
524
525
`\operatorname{Li}(x)` is extended to complex arguments `z`
526
by analytic continuation (see [AS]_ 5.1.3)::
527
528
sage: Li(6.6+5.4*I)
529
3.97032201503632 + 2.62311237593572*I
530
531
The function `\operatorname{Li}` is an approximation for the number of
532
primes up to `x`. In fact, the famous Riemann Hypothesis is
533
534
.. math::
535
536
|\pi(x) - \operatorname{Li}(x)| \leq \sqrt{x} \log(x).
537
538
For "small" `x`, `\operatorname{Li}(x)` is always slightly bigger
539
than `\pi(x)`. However it is a theorem that there are very
540
large values of `x` (e.g., around `10^{316}`), such that
541
`\exists x: \pi(x) > \operatorname{Li}(x)`. See "A new bound for the
542
smallest x with `\pi(x) > \operatorname{li}(x)`",
543
Bays and Hudson, Mathematics of Computation, 69 (2000) 1285-1296.
544
545
Here is a test from the mpmath documentation.
546
There are 1,925,320,391,606,803,968,923 prime numbers less than 1e23.
547
The value of ``log_integral_offset(1e23)`` is very close to this::
548
549
sage: log_integral_offset(1e23)
550
1.92532039161405e21
551
552
EXAMPLES:
553
554
Numerical evaluation for real and complex arguments is handled using mpmath::
555
556
sage: N(log_integral_offset(3))
557
1.11842481454970
558
sage: N(log_integral_offset(3), digits=30)
559
1.11842481454969918803233347815
560
sage: log_integral_offset(ComplexField(100)(3+I))
561
1.2428254968641898308632562019 + 0.87232935488528370139883806779*I
562
sage: log_integral_offset(2)
563
0
564
sage: for n in range(1,7):
565
... print '%-10s%-10s%-20s'%(10^n, prime_pi(10^n), N(Li(10^n)))
566
10 4 5.12043572466980
567
100 25 29.0809778039621
568
1000 168 176.564494210035
569
10000 1229 1245.09205211927
570
100000 9592 9628.76383727068
571
1000000 78498 78626.5039956821
572
573
Symbolic derivatives are handled by Sage and integration by Maxima::
574
575
sage: x = var('x')
576
sage: f = log_integral_offset(x)
577
sage: f.diff(x)
578
1/log(x)
579
580
sage: f.integrate(x)
581
-x*log_integral(2) + x*log_integral(x) - Ei(2*log(x))
582
583
sage: Li(x).integrate(x,2.0,4.5)
584
-2.5*log_integral(2) + 5.79932114741
585
586
sage: N(f.integrate(x,2.0,3.0))
587
0.601621785860587
588
589
Note: Definite integration returns a part symbolic and part
590
numerical result. This is because when Li(x) is evaluated it is
591
passed as li(x)-li(2).
592
593
ALGORITHM:
594
595
Numerical evaluation is handled using mpmath, but symbolics are handled
596
by Sage and Maxima.
597
598
REFERENCES:
599
600
- http://en.wikipedia.org/wiki/Logarithmic_integral_function
601
- mpmath documentation: `logarithmic-integral`_
602
603
.. _`logarithmic-integral`: http://mpmath.googlecode.com/svn/trunk/doc/build/functions/expintegrals.html#logarithmic-integral
604
"""
605
606
def __init__(self):
607
"""
608
See the docstring for ``Function_log_integral-offset``.
609
610
EXAMPLES::
611
612
sage: log_integral_offset(3)
613
log_integral(3) - log_integral(2)
614
615
"""
616
BuiltinFunction.__init__(self, "log_integral_offset", nargs=1,
617
latex_name=r'log_integral_offset')
618
619
def _eval_(self,z):
620
"""
621
EXAMPLES::
622
623
sage: z = var('z')
624
sage: log_integral_offset(z)
625
-log_integral(2) + log_integral(z)
626
sage: log_integral_offset(3.0)
627
1.11842481454970
628
sage: log_integral_offset(2)
629
0
630
631
"""
632
if not isinstance(z,Expression) and is_inexact(z):
633
return self._evalf_(z,parent(z))
634
if z==2:
635
import sage.symbolic.ring
636
return sage.symbolic.ring.SR(0)
637
return li(z)-li(2)
638
# If we return:(li(z)-li(2)) we get correct symbolic integration.
639
# But on definite integration it returns x.xxxx-li(2).
640
641
def _evalf_(self, z, parent=None):
642
"""
643
EXAMPLES::
644
645
sage: N(log_integral_offset(1e6))
646
78626.5039956821
647
sage: log_integral_offset(RealField(200)(1e6))
648
78626.503995682064427078066159058066548185351766843615873183
649
sage: li(4.5)-li(2.0)-Li(4.5)
650
0.000000000000000
651
652
"""
653
import mpmath
654
return mpmath_utils_call(mpmath.li, z, offset=True, parent=parent)
655
656
def _derivative_(self, z, diff_param=None):
657
"""
658
The derivative of `\operatorname{Li}(z) is `1/log(z)`.
659
660
EXAMPLES::
661
662
sage: x = var('x')
663
sage: f = log_integral_offset(x)
664
sage: f.diff(x)
665
1/log(x)
666
667
sage: f = log_integral_offset(x^2)
668
sage: f.diff(x)
669
2*x/log(x^2)
670
671
"""
672
return 1/log(z)
673
674
Li = log_integral_offset = Function_log_integral_offset()
675
676
class Function_sin_integral(BuiltinFunction):
677
r"""
678
The trigonometric integral `\operatorname{Si}(z)` defined by
679
680
.. math::
681
682
\operatorname{Si}(z) = \int_0^z \frac{\sin(t)}{t}\; dt,
683
684
see [AS]_ 5.2.1.
685
686
EXAMPLES:
687
688
Numerical evaluation for real and complex arguments is handled using mpmath::
689
690
sage: sin_integral(0)
691
0
692
sage: sin_integral(0.0)
693
0.000000000000000
694
sage: sin_integral(3.0)
695
1.84865252799947
696
sage: N(sin_integral(3), digits=30)
697
1.84865252799946825639773025111
698
sage: sin_integral(ComplexField(100)(3+I))
699
2.0277151656451253616038525998 + 0.015210926166954211913653130271*I
700
701
The alias `Si` can be used instead of `sin_integral`::
702
703
sage: Si(3.0)
704
1.84865252799947
705
706
The limit of `\operatorname{Si}(z)` as `z \to \infty` is `\pi/2`::
707
708
sage: N(sin_integral(1e23))
709
1.57079632679490
710
sage: N(pi/2)
711
1.57079632679490
712
713
At 200 bits of precision `\operatorname{Si}(10^{23})` agrees with `\pi/2` up to
714
`10^{-24}`::
715
716
sage: sin_integral(RealField(200)(1e23))
717
1.5707963267948966192313288218697837425815368604836679189519
718
sage: N(pi/2, prec=200)
719
1.5707963267948966192313216916397514420985846996875529104875
720
721
The exponential sine integral is analytic everywhere::
722
723
sage: sin_integral(-1.0)
724
-0.946083070367183
725
sage: sin_integral(-2.0)
726
-1.60541297680269
727
sage: sin_integral(-1e23)
728
-1.57079632679490
729
730
Symbolic derivatives and integrals are handled by Sage and Maxima::
731
732
sage: x = var('x')
733
sage: f = sin_integral(x)
734
sage: f.diff(x)
735
sin(x)/x
736
737
sage: f.integrate(x)
738
x*sin_integral(x) + cos(x)
739
740
sage: integrate(sin(x)/x, x)
741
-1/2*I*Ei(I*x) + 1/2*I*Ei(-I*x)
742
743
744
Compare values of the functions `\operatorname{Si}(x)` and
745
`f(x) = (1/2)i \cdot \operatorname{Ei}(-ix) - (1/2)i \cdot
746
\operatorname{Ei}(ix) - \pi/2`, which are both anti-derivatives of
747
`\sin(x)/x`, at some random positive real numbers::
748
749
sage: f(x) = 1/2*I*Ei(-I*x) - 1/2*I*Ei(I*x) - pi/2
750
sage: g(x) = sin_integral(x)
751
sage: R = [ abs(RDF.random_element()) for i in range(100) ]
752
sage: all(abs(f(x) - g(x)) < 1e-10 for x in R)
753
True
754
755
The Nielsen spiral is the parametric plot of (Si(t), Ci(t))::
756
757
sage: x=var('x')
758
sage: f(x) = sin_integral(x)
759
sage: g(x) = cos_integral(x)
760
sage: P = parametric_plot([f, g], (x, 0.5 ,20))
761
sage: show(P, frame=True, axes=False)
762
763
ALGORITHM:
764
765
Numerical evaluation is handled using mpmath, but symbolics are handled
766
by Sage and Maxima.
767
768
REFERENCES:
769
770
- http://en.wikipedia.org/wiki/Trigonometric_integral
771
- mpmath documentation: `si`_
772
773
.. _`si`: http://mpmath.googlecode.com/svn/trunk/doc/build/functions/expintegrals.html#si
774
775
"""
776
def __init__(self):
777
"""
778
See the docstring for ``Function_sin_integral``.
779
780
EXAMPLES::
781
782
sage: sin_integral(1)
783
sin_integral(1)
784
785
"""
786
BuiltinFunction.__init__(self, "sin_integral", nargs=1,
787
latex_name=r'\operatorname{Si}',
788
conversions=dict(maxima='expintegral_si'))
789
790
def _eval_(self, z):
791
"""
792
EXAMPLES::
793
794
sage: z = var('z')
795
sage: sin_integral(z)
796
sin_integral(z)
797
sage: sin_integral(3.0)
798
1.84865252799947
799
sage: sin_integral(0)
800
0
801
802
"""
803
if not isinstance(z, Expression) and is_inexact(z):
804
return self._evalf_(z, parent(z))
805
806
# special case: z = 0
807
if isinstance(z, Expression):
808
if z.is_trivial_zero():
809
return z
810
else:
811
if not z:
812
return z
813
814
return None # leaves the expression unevaluated
815
816
def _evalf_(self, z, parent=None):
817
"""
818
EXAMPLES:
819
820
The limit `\operatorname{Si}(z)` as `z \to \infty` is `\pi/2`::
821
822
sage: N(sin_integral(1e23) - pi/2)
823
0.000000000000000
824
825
At 200 bits of precision `\operatorname{Si}(10^{23})` agrees with `\pi/2` up to
826
`10^{-24}`::
827
828
sage: sin_integral(RealField(200)(1e23))
829
1.5707963267948966192313288218697837425815368604836679189519
830
sage: N(pi/2, prec=200)
831
1.5707963267948966192313216916397514420985846996875529104875
832
833
The exponential sine integral is analytic everywhere, even on the
834
negative real axis::
835
836
sage: sin_integral(-1.0)
837
-0.946083070367183
838
sage: sin_integral(-2.0)
839
-1.60541297680269
840
sage: sin_integral(-1e23)
841
-1.57079632679490
842
843
"""
844
import mpmath
845
return mpmath_utils_call(mpmath.si, z, parent=parent)
846
847
def _derivative_(self, z, diff_param=None):
848
r"""
849
The derivative of `\operatorname{Si}(z)` is `\sin(z)/z` if `z`
850
is not zero. The derivative at `z = 0` is `1` (but this
851
exception is not currently implemented).
852
853
EXAMPLES::
854
855
sage: x = var('x')
856
sage: f = sin_integral(x)
857
sage: f.diff(x)
858
sin(x)/x
859
860
sage: f = sin_integral(x^2)
861
sage: f.diff(x)
862
2*sin(x^2)/x
863
864
"""
865
return sin(z)/z
866
867
Si = sin_integral = Function_sin_integral()
868
869
870
class Function_cos_integral(BuiltinFunction):
871
r"""
872
The trigonometric integral `\operatorname{Ci}(z)` defined by
873
874
.. math::
875
876
\operatorname{Ci}(z) = \gamma + \log(z) + \int_0^z \frac{\cos(t)-1}{t}\; dt,
877
878
where `\gamma` is the Euler gamma constant (``euler_gamma`` in Sage),
879
see [AS]_ 5.2.1.
880
881
EXAMPLES:
882
883
Numerical evaluation for real and complex arguments is handled using mpmath::
884
885
sage: cos_integral(3.0)
886
0.119629786008000
887
888
The alias `Ci` can be used instead of `cos_integral`::
889
890
sage: Ci(3.0)
891
0.119629786008000
892
893
Compare ``cos_integral(3.0)`` to the definition of the value using
894
numerical integration::
895
896
sage: N(euler_gamma + log(3.0) + integrate((cos(x)-1)/x, x, 0, 3.0) - cos_integral(3.0)) < 1e-14
897
True
898
899
Arbitrary precision and complex arguments are handled::
900
901
sage: N(cos_integral(3), digits=30)
902
0.119629786008000327626472281177
903
sage: cos_integral(ComplexField(100)(3+I))
904
0.078134230477495714401983633057 - 0.37814733904787920181190368789*I
905
906
The limit `\operatorname{Ci}(z)` as `z \to \infty` is zero::
907
908
sage: N(cos_integral(1e23))
909
-3.24053937643003e-24
910
911
Symbolic derivatives and integrals are handled by Sage and Maxima::
912
913
sage: x = var('x')
914
sage: f = cos_integral(x)
915
sage: f.diff(x)
916
cos(x)/x
917
918
sage: f.integrate(x)
919
x*cos_integral(x) - sin(x)
920
921
The Nielsen spiral is the parametric plot of (Si(t), Ci(t))::
922
923
sage: t=var('t')
924
sage: f(t) = sin_integral(t)
925
sage: g(t) = cos_integral(t)
926
sage: P = parametric_plot([f, g], (t, 0.5 ,20))
927
sage: show(P, frame=True, axes=False)
928
929
ALGORITHM:
930
931
Numerical evaluation is handled using mpmath, but symbolics are handled
932
by Sage and Maxima.
933
934
REFERENCES:
935
936
- http://en.wikipedia.org/wiki/Trigonometric_integral
937
- mpmath documentation: `ci`_
938
939
.. _`ci`: http://mpmath.googlecode.com/svn/trunk/doc/build/functions/expintegrals.html#ci
940
941
"""
942
def __init__(self):
943
"""
944
See the docstring for :class:`Function_cos_integral`.
945
946
EXAMPLES::
947
948
sage: cos_integral(1)
949
cos_integral(1)
950
951
"""
952
BuiltinFunction.__init__(self, "cos_integral", nargs=1,
953
latex_name=r'\operatorname{Ci}',
954
conversions=dict(maxima='expintegral_ci'))
955
956
def _eval_(self, z):
957
"""
958
EXAMPLES::
959
960
sage: z = var('z')
961
sage: cos_integral(z)
962
cos_integral(z)
963
sage: cos_integral(3.0)
964
0.119629786008000
965
sage: cos_integral(0)
966
cos_integral(0)
967
sage: N(cos_integral(0))
968
-infinity
969
970
"""
971
if not isinstance(z, Expression) and is_inexact(z):
972
return self._evalf_(z, parent(z))
973
974
return None # leaves the expression unevaluated
975
976
def _evalf_(self, z, parent=None):
977
"""
978
EXAMPLES::
979
980
sage: N(cos_integral(1e23)) < 1e-20
981
True
982
sage: N(cos_integral(1e-10), digits=30)
983
-22.4486352650389235918737540487
984
sage: cos_integral(ComplexField(100)(I))
985
0.83786694098020824089467857943 + 1.5707963267948966192313216916*I
986
987
"""
988
import mpmath
989
return mpmath_utils_call(mpmath.ci, z, parent=parent)
990
991
def _derivative_(self, z, diff_param=None):
992
r"""
993
The derivative of `\operatorname{Ci}(z)` is `\cos(z)/z` if `z` is not zero.
994
995
EXAMPLES::
996
997
sage: x = var('x')
998
sage: f = cos_integral(x)
999
sage: f.diff(x)
1000
cos(x)/x
1001
1002
sage: f = cos_integral(x^2)
1003
sage: f.diff(x)
1004
2*cos(x^2)/x
1005
1006
"""
1007
return cos(z)/z
1008
1009
Ci = cos_integral = Function_cos_integral()
1010
1011
1012
class Function_sinh_integral(BuiltinFunction):
1013
r"""
1014
The trigonometric integral `\operatorname{Shi}(z)` defined by
1015
1016
.. math::
1017
1018
\operatorname{Shi}(z) = \int_0^z \frac{\sinh(t)}{t}\; dt,
1019
1020
see [AS]_ 5.2.3.
1021
1022
EXAMPLES:
1023
1024
Numerical evaluation for real and complex arguments is handled using mpmath::
1025
1026
sage: sinh_integral(3.0)
1027
4.97344047585981
1028
sage: sinh_integral(1.0)
1029
1.05725087537573
1030
sage: sinh_integral(-1.0)
1031
-1.05725087537573
1032
1033
The alias `Shi` can be used instead of `sinh_integral`::
1034
1035
sage: Shi(3.0)
1036
4.97344047585981
1037
1038
Compare ``sinh_integral(3.0)`` to the definition of the value using
1039
numerical integration::
1040
1041
sage: N(integrate((sinh(x))/x, x, 0, 3.0) - sinh_integral(3.0)) < 1e-14
1042
True
1043
1044
Arbitrary precision and complex arguments are handled::
1045
1046
sage: N(sinh_integral(3), digits=30)
1047
4.97344047585980679771041838252
1048
sage: sinh_integral(ComplexField(100)(3+I))
1049
3.9134623660329374406788354078 + 3.0427678212908839256360163759*I
1050
1051
The limit `\operatorname{Shi}(z)` as `z \to \infty` is `\infty`::
1052
1053
sage: N(sinh_integral(Infinity))
1054
+infinity
1055
1056
Symbolic derivatives and integrals are handled by Sage and Maxima::
1057
1058
sage: x = var('x')
1059
sage: f = sinh_integral(x)
1060
sage: f.diff(x)
1061
sinh(x)/x
1062
1063
sage: f.integrate(x)
1064
x*sinh_integral(x) - cosh(x)
1065
1066
Note that due to some problems with the way Maxima handles these
1067
expressions, definite integrals can sometimes give unexpected
1068
results (typically when using inexact endpoints) due to
1069
inconsistent branching::
1070
1071
sage: integrate(sinh_integral(x), x, 0, 1/2)
1072
-cosh(1/2) + 1/2*sinh_integral(1/2) + 1
1073
sage: integrate(sinh_integral(x), x, 0, 1/2).n() # correct
1074
0.125872409703453
1075
sage: integrate(sinh_integral(x), x, 0, 0.5).n() # fixed in maxima 5.29.1
1076
0.125872409703453
1077
1078
ALGORITHM:
1079
1080
Numerical evaluation is handled using mpmath, but symbolics are handled
1081
by Sage and Maxima.
1082
1083
REFERENCES:
1084
1085
- http://en.wikipedia.org/wiki/Trigonometric_integral
1086
- mpmath documentation: `shi`_
1087
1088
.. _`shi`: http://mpmath.googlecode.com/svn/trunk/doc/build/functions/expintegrals.html#shi
1089
1090
"""
1091
def __init__(self):
1092
"""
1093
See the docstring for ``Function_sinh_integral``.
1094
1095
EXAMPLES::
1096
1097
sage: sinh_integral(1)
1098
sinh_integral(1)
1099
1100
"""
1101
BuiltinFunction.__init__(self, "sinh_integral", nargs=1,
1102
latex_name=r'\operatorname{Shi}',
1103
conversions=dict(maxima='expintegral_shi'))
1104
1105
def _eval_(self, z):
1106
"""
1107
EXAMPLES::
1108
1109
sage: z = var('z')
1110
sage: sinh_integral(z)
1111
sinh_integral(z)
1112
sage: sinh_integral(3.0)
1113
4.97344047585981
1114
sage: sinh_integral(0)
1115
0
1116
1117
"""
1118
if not isinstance(z, Expression) and is_inexact(z):
1119
return self._evalf_(z, parent(z))
1120
1121
# special case: z = 0
1122
if isinstance(z, Expression):
1123
if z.is_trivial_zero():
1124
return z
1125
else:
1126
if not z:
1127
return z
1128
1129
return None # leaves the expression unevaluated
1130
1131
def _evalf_(self, z, parent=None):
1132
"""
1133
EXAMPLES::
1134
1135
sage: N(sinh_integral(1e-10), digits=30)
1136
1.00000000000000003643219731550e-10
1137
sage: sinh_integral(ComplexField(100)(I))
1138
0.94608307036718301494135331382*I
1139
1140
"""
1141
import mpmath
1142
return mpmath_utils_call(mpmath.shi, z, parent=parent)
1143
1144
def _derivative_(self, z, diff_param=None):
1145
r"""
1146
The derivative of `\operatorname{Shi}(z)` is `\sinh(z)/z`.
1147
1148
EXAMPLES::
1149
1150
sage: x = var('x')
1151
sage: f = sinh_integral(x)
1152
sage: f.diff(x)
1153
sinh(x)/x
1154
1155
sage: f = sinh_integral(ln(x))
1156
sage: f.diff(x)
1157
sinh(log(x))/(x*log(x))
1158
1159
"""
1160
return sinh(z)/z
1161
1162
Shi = sinh_integral = Function_sinh_integral()
1163
1164
1165
class Function_cosh_integral(BuiltinFunction):
1166
r"""
1167
The trigonometric integral `\operatorname{Chi}(z)` defined by
1168
1169
.. math::
1170
1171
\operatorname{Chi}(z) = \gamma + \log(z) + \int_0^z \frac{\cosh(t)-1}{t}\; dt,
1172
1173
see [AS]_ 5.2.4.
1174
1175
EXAMPLES:
1176
1177
Numerical evaluation for real and complex arguments is handled using mpmath::
1178
1179
sage: cosh_integral(1.0)
1180
0.837866940980208
1181
1182
The alias `Chi` can be used instead of `cosh_integral`::
1183
1184
sage: Chi(1.0)
1185
0.837866940980208
1186
1187
Here is an example from the mpmath documentation::
1188
1189
sage: f(x) = cosh_integral(x)
1190
sage: find_root(f, 0.1, 1.0)
1191
0.5238225713894826
1192
1193
Compare ``cosh_integral(3.0)`` to the definition of the value using
1194
numerical integration::
1195
1196
sage: N(euler_gamma + log(3.0) + integrate((cosh(x)-1)/x, x, 0, 3.0) -
1197
... cosh_integral(3.0)) < 1e-14
1198
True
1199
1200
Arbitrary precision and complex arguments are handled::
1201
1202
sage: N(cosh_integral(3), digits=30)
1203
4.96039209476560976029791763669
1204
sage: cosh_integral(ComplexField(100)(3+I))
1205
3.9096723099686417127843516794 + 3.0547519627014217273323873274*I
1206
1207
The limit of `\operatorname{Chi}(z)` as `z \to \infty` is `\infty`::
1208
1209
sage: N(cosh_integral(Infinity))
1210
+infinity
1211
1212
Symbolic derivatives and integrals are handled by Sage and Maxima::
1213
1214
sage: x = var('x')
1215
sage: f = cosh_integral(x)
1216
sage: f.diff(x)
1217
cosh(x)/x
1218
1219
sage: f.integrate(x)
1220
x*cosh_integral(x) - sinh(x)
1221
1222
ALGORITHM:
1223
1224
Numerical evaluation is handled using mpmath, but symbolics are handled
1225
by Sage and Maxima.
1226
1227
REFERENCES:
1228
1229
- http://en.wikipedia.org/wiki/Trigonometric_integral
1230
- mpmath documentation: `chi`_
1231
1232
.. _`chi`: http://mpmath.googlecode.com/svn/trunk/doc/build/functions/expintegrals.html#chi
1233
1234
"""
1235
def __init__(self):
1236
"""
1237
See the docstring for ``Function_cosh_integral``.
1238
1239
EXAMPLES::
1240
1241
sage: cosh_integral(1)
1242
cosh_integral(1)
1243
1244
"""
1245
BuiltinFunction.__init__(self, "cosh_integral", nargs=1,
1246
latex_name=r'\operatorname{Chi}',
1247
conversions=dict(maxima='expintegral_chi'))
1248
1249
def _eval_(self, z):
1250
"""
1251
EXAMPLES::
1252
1253
sage: z = var('z')
1254
sage: cosh_integral(z)
1255
cosh_integral(z)
1256
sage: cosh_integral(3.0)
1257
4.96039209476561
1258
1259
"""
1260
if not isinstance(z, Expression) and is_inexact(z):
1261
return self._evalf_(z, parent(z))
1262
1263
return None
1264
1265
def _evalf_(self, z, parent=None):
1266
"""
1267
EXAMPLES::
1268
1269
sage: N(cosh_integral(1e-10), digits=30)
1270
-22.4486352650389235918737540487
1271
sage: cosh_integral(ComplexField(100)(I))
1272
0.33740392290096813466264620389 + 1.5707963267948966192313216916*I
1273
1274
"""
1275
import mpmath
1276
return mpmath_utils_call(mpmath.chi, z, parent=parent)
1277
1278
def _derivative_(self, z, diff_param=None):
1279
"""
1280
The derivative of `\operatorname{Chi}(z)` is `\cosh(z)/z`.
1281
1282
EXAMPLES::
1283
1284
sage: x = var('x')
1285
sage: f = cosh_integral(x)
1286
sage: f.diff(x)
1287
cosh(x)/x
1288
1289
sage: f = cosh_integral(ln(x))
1290
sage: f.diff(x)
1291
cosh(log(x))/(x*log(x))
1292
1293
"""
1294
return cosh(z)/z
1295
1296
Chi = cosh_integral = Function_cosh_integral()
1297
1298
1299
###################################################################
1300
## Code below here was moved from sage/functions/transcendental.py
1301
## This occured as part of Trac #11143.
1302
###################################################################
1303
#
1304
# This class has a name which is not specific enough
1305
# see Function_exp_integral_e above, for example, which
1306
# is the "generalized" exponential integral function. We
1307
# are leaving the name the same for backwards compatibility
1308
# purposes.
1309
class Function_exp_integral(BuiltinFunction):
1310
r"""
1311
The generalized complex exponential integral Ei(z) defined by
1312
1313
.. math::
1314
1315
\operatorname{Ei}(x) = \int_{-\infty}^x \frac{e^t}{t}\; dt
1316
1317
for x > 0 and for complex arguments by analytic continuation,
1318
see [AS]_ 5.1.2.
1319
1320
EXAMPLES::
1321
1322
sage: Ei(10)
1323
Ei(10)
1324
sage: Ei(I)
1325
Ei(I)
1326
sage: Ei(3+I)
1327
Ei(I + 3)
1328
sage: Ei(1.3)
1329
2.72139888023202
1330
1331
The branch cut for this function is along the negative real axis::
1332
1333
sage: Ei(-3 + 0.1*I)
1334
-0.0129379427181693 + 3.13993830250942*I
1335
sage: Ei(-3 - 0.1*I)
1336
-0.0129379427181693 - 3.13993830250942*I
1337
1338
ALGORITHM: Uses mpmath.
1339
1340
TESTS:
1341
1342
Show that the evaluation and limit issue in :trac:`13271` is fixed::
1343
1344
sage: var('Z')
1345
Z
1346
sage: (Ei(-Z)).limit(Z=oo)
1347
0
1348
sage: (Ei(-Z)).limit(Z=1000)
1349
Ei(-1000)
1350
sage: (Ei(-Z)).limit(Z=1000).n()
1351
-5.07089306023517e-438
1352
"""
1353
def __init__(self):
1354
"""
1355
Return the value of the complex exponential integral Ei(z) at a
1356
complex number z.
1357
1358
EXAMPLES::
1359
1360
sage: Ei(10)
1361
Ei(10)
1362
sage: Ei(I)
1363
Ei(I)
1364
sage: Ei(3+I)
1365
Ei(I + 3)
1366
sage: Ei(1.3)
1367
2.72139888023202
1368
1369
The branch cut for this function is along the negative real axis::
1370
1371
sage: Ei(-3 + 0.1*I)
1372
-0.0129379427181693 + 3.13993830250942*I
1373
sage: Ei(-3 - 0.1*I)
1374
-0.0129379427181693 - 3.13993830250942*I
1375
1376
ALGORITHM: Uses mpmath.
1377
"""
1378
BuiltinFunction.__init__(self, "Ei",
1379
conversions=dict(maxima='expintegral_ei'))
1380
1381
def _eval_(self, x ):
1382
"""
1383
EXAMPLES::
1384
1385
sage: Ei(10)
1386
Ei(10)
1387
sage: Ei(I)
1388
Ei(I)
1389
sage: Ei(1.3)
1390
2.72139888023202
1391
sage: Ei(10r)
1392
Ei(10)
1393
sage: Ei(1.3r)
1394
2.7213988802320235
1395
"""
1396
if not isinstance(x, Expression) and is_inexact(x):
1397
return self._evalf_(x, parent(x))
1398
return None
1399
1400
def _evalf_(self, x, parent=None):
1401
"""
1402
EXAMPLES::
1403
1404
sage: Ei(10).n()
1405
2492.22897624188
1406
sage: Ei(20).n()
1407
2.56156526640566e7
1408
sage: Ei(I).n()
1409
0.337403922900968 + 2.51687939716208*I
1410
sage: Ei(3+I).n()
1411
7.82313467600158 + 6.09751978399231*I
1412
"""
1413
import mpmath
1414
return mpmath_utils_call(mpmath.ei, x, parent=parent)
1415
1416
def __call__(self, x, prec=None, coerce=True, hold=False ):
1417
"""
1418
Note that the ``prec`` argument is deprecated. The precision for
1419
the result is deduced from the precision of the input. Convert
1420
the input to a higher precision explicitly if a result with higher
1421
precision is desired.
1422
1423
EXAMPLES::
1424
1425
sage: t = Ei(RealField(100)(2.5)); t
1426
7.0737658945786007119235519625
1427
sage: t.prec()
1428
100
1429
1430
sage: Ei(1.1, prec=300)
1431
doctest:...: DeprecationWarning: The prec keyword argument is deprecated. Explicitly set the precision of the input, for example Ei(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., Ei(1).n(300), instead.
1432
See http://trac.sagemath.org/7748 for details.
1433
2.16737827956340306615064476647912607220394065907142504328679588538509331805598360907980986
1434
"""
1435
if prec is not None:
1436
from sage.misc.superseded import deprecation
1437
deprecation(7748, "The prec keyword argument is deprecated. Explicitly set the precision of the input, for example Ei(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., Ei(1).n(300), instead.")
1438
import mpmath
1439
return mpmath_utils_call(mpmath.ei, x, prec=prec)
1440
1441
return BuiltinFunction.__call__(self, x, coerce=coerce, hold=hold)
1442
1443
def _derivative_(self, x, diff_param=None):
1444
"""
1445
EXAMPLES::
1446
1447
sage: Ei(x).diff(x)
1448
e^x/x
1449
sage: Ei(x).diff(x).subs(x=1)
1450
e
1451
sage: Ei(x^2).diff(x)
1452
2*e^(x^2)/x
1453
sage: f = function('f')
1454
sage: Ei(f(x)).diff(x)
1455
e^f(x)*D[0](f)(x)/f(x)
1456
"""
1457
return exp(x)/x
1458
1459
Ei = exp_integral_ei = Function_exp_integral()
1460
1461
1462
# moved here from sage/functions/transcendental.py
1463
def exponential_integral_1(x, n=0):
1464
r"""
1465
Returns the exponential integral `E_1(x)`. If the optional
1466
argument `n` is given, computes list of the first
1467
`n` values of the exponential integral
1468
`E_1(x m)`.
1469
1470
The exponential integral `E_1(x)` is
1471
1472
.. math::
1473
1474
E_1(x) = \int_{x}^{\infty} e^{-t}/t dt
1475
1476
INPUT:
1477
1478
- ``x`` -- a positive real number
1479
1480
- ``n`` -- (default: 0) a nonnegative integer; if
1481
nonzero, then return a list of values ``E_1(x*m)`` for m =
1482
1,2,3,...,n. This is useful, e.g., when computing derivatives of
1483
L-functions.
1484
1485
1486
OUTPUT:
1487
1488
A real number if n is 0 (the default) or a list of reals if n > 0.
1489
The precision is the same as the input, with a default of 53 bits
1490
in case the input is exact.
1491
1492
EXAMPLES::
1493
1494
sage: exponential_integral_1(2)
1495
0.0489005107080611
1496
sage: exponential_integral_1(2,4) # abs tol 1e-18
1497
[0.0489005107080611, 0.00377935240984891, 0.000360082452162659, 0.0000376656228439245]
1498
sage: exponential_integral_1(40,5)
1499
[1.03677326145166e-19, 2.22854325868847e-37, 6.33732515501151e-55, 2.02336191509997e-72, 6.88522610630764e-90]
1500
sage: exponential_integral_1(0)
1501
+Infinity
1502
sage: r = exponential_integral_1(RealField(150)(1))
1503
sage: r
1504
0.21938393439552027367716377546012164903104729
1505
sage: parent(r)
1506
Real Field with 150 bits of precision
1507
sage: exponential_integral_1(RealField(150)(100))
1508
3.6835977616820321802351926205081189876552201e-46
1509
1510
TESTS:
1511
1512
The relative error for a single value should be less than 1 ulp::
1513
1514
sage: for prec in [20..1000]: # long time (22s on sage.math, 2013)
1515
....: R = RealField(prec)
1516
....: S = RealField(prec+64)
1517
....: for t in range(8): # Try 8 values for each precision
1518
....: a = R.random_element(-15,10).exp()
1519
....: x = exponential_integral_1(a)
1520
....: y = exponential_integral_1(S(a))
1521
....: e = float(abs(S(x) - y)/x.ulp())
1522
....: if e >= 1.0:
1523
....: print "exponential_integral_1(%s) with precision %s has error of %s ulp"%(a, prec, e)
1524
1525
The absolute error for a vector should be less than `c 2^{-p}`, where
1526
`p` is the precision in bits of `x` and `c = 2 max(1, exponential_integral_1(x))`::
1527
1528
sage: for prec in [20..128]: # long time (15s on sage.math, 2013)
1529
....: R = RealField(prec)
1530
....: S = RealField(prec+64)
1531
....: a = R.random_element(-15,10).exp()
1532
....: n = 2^ZZ.random_element(14)
1533
....: x = exponential_integral_1(a, n)
1534
....: y = exponential_integral_1(S(a), n)
1535
....: c = RDF(2 * max(1.0, y[0]))
1536
....: for i in range(n):
1537
....: e = float(abs(S(x[i]) - y[i]) << prec)
1538
....: if e >= c:
1539
....: print "exponential_integral_1(%s, %s)[%s] with precision %s has error of %s >= %s"%(a, n, i, prec, e, c)
1540
1541
ALGORITHM: use the PARI C-library function ``eint1``.
1542
1543
REFERENCE:
1544
1545
- See Proposition 5.6.12 of Cohen's book "A Course in
1546
Computational Algebraic Number Theory".
1547
"""
1548
if isinstance(x, Expression):
1549
if x.is_trivial_zero():
1550
from sage.rings.infinity import Infinity
1551
return Infinity
1552
else:
1553
raise NotImplementedError("Use the symbolic exponential integral " +
1554
"function: exp_integral_e1.")
1555
elif not is_inexact(x): # x is exact and not an expression
1556
if not x: # test if exact x == 0 quickly
1557
from sage.rings.infinity import Infinity
1558
return Infinity
1559
1560
# else x is not an exact 0
1561
from sage.libs.pari.all import pari
1562
# Figure out output precision
1563
try:
1564
prec = parent(x).precision()
1565
except AttributeError:
1566
prec = 53
1567
1568
R = RealField(prec)
1569
if n <= 0:
1570
# Add extra bits to the input.
1571
# (experimentally verified -- Jeroen Demeyer)
1572
inprec = prec + math.ceil(math.log(2*prec))
1573
x = RealField(inprec)(x)._pari_()
1574
return R(x.eint1())
1575
else:
1576
# PARI's algorithm is less precise as n grows larger:
1577
# add extra bits.
1578
# (experimentally verified -- Jeroen Demeyer)
1579
inprec = prec + 1 + math.ceil(1.4427 * math.log(n))
1580
x = RealField(inprec)(x)._pari_()
1581
return [R(z) for z in x.eint1(n)]
1582
1583