Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/functions/log.py
4045 views
1
"""
2
Logarithmic functions
3
"""
4
from sage.symbolic.function import GinacFunction, BuiltinFunction, is_inexact
5
from sage.symbolic.pynac import symbol_table
6
from sage.symbolic.constants import e as const_e
7
8
from sage.libs.mpmath import utils as mpmath_utils
9
from sage.structure.coerce import parent as sage_structure_coerce_parent
10
from sage.symbolic.expression import Expression
11
from sage.rings.real_double import RDF
12
from sage.rings.complex_double import CDF
13
from sage.rings.all import Integer
14
15
class Function_exp(GinacFunction):
16
def __init__(self):
17
r"""
18
The exponential function, `\exp(x) = e^x`.
19
20
EXAMPLES::
21
22
sage: exp(-1)
23
e^(-1)
24
sage: exp(2)
25
e^2
26
sage: exp(2).n(100)
27
7.3890560989306502272304274606
28
sage: exp(x^2 + log(x))
29
e^(x^2 + log(x))
30
sage: exp(x^2 + log(x)).simplify()
31
x*e^(x^2)
32
sage: exp(2.5)
33
12.1824939607035
34
sage: exp(float(2.5))
35
12.182493960703473
36
sage: exp(RDF('2.5'))
37
12.1824939607
38
39
To prevent automatic evaluation, use the ``hold`` parameter::
40
41
sage: exp(I*pi,hold=True)
42
e^(I*pi)
43
sage: exp(0,hold=True)
44
e^0
45
46
To then evaluate again, we currently must use Maxima via
47
:meth:`sage.symbolic.expression.Expression.simplify`::
48
49
sage: exp(0,hold=True).simplify()
50
1
51
52
::
53
54
sage: exp(pi*I/2)
55
I
56
sage: exp(pi*I)
57
-1
58
sage: exp(8*pi*I)
59
1
60
sage: exp(7*pi*I/2)
61
-I
62
63
TEST::
64
65
sage: latex(exp(x))
66
e^{x}
67
sage: latex(exp(sqrt(x)))
68
e^{\sqrt{x}}
69
sage: latex(exp)
70
\exp
71
sage: latex(exp(sqrt(x))^x)
72
\left(e^{\sqrt{x}}\right)^{x}
73
sage: latex(exp(sqrt(x)^x))
74
e^{\left(\sqrt{x}^{x}\right)}
75
76
Test conjugates::
77
78
sage: conjugate(exp(x))
79
e^conjugate(x)
80
81
Test simplifications when taking powers of exp, #7264::
82
83
sage: var('a,b,c,II')
84
(a, b, c, II)
85
sage: model_exp = exp(II)**a*(b)
86
sage: sol1_l={b: 5.0, a: 1.1}
87
sage: model_exp.subs(sol1_l)
88
5.00000000000000*(e^II)^1.10000000000000
89
90
::
91
92
sage: exp(3)^II*exp(x)
93
(e^3)^II*e^x
94
sage: exp(x)*exp(x)
95
e^(2*x)
96
sage: exp(x)*exp(a)
97
e^(a + x)
98
sage: exp(x)*exp(a)^2
99
e^(2*a + x)
100
101
Another instance of the same problem, #7394::
102
103
sage: 2*sqrt(e)
104
2*sqrt(e)
105
"""
106
GinacFunction.__init__(self, "exp", latex_name=r"\exp",
107
conversions=dict(maxima='exp'))
108
109
def __call__(self, x, coerce=True, hold=False, prec=None,
110
dont_call_method_on_arg=False):
111
"""
112
Note that the ``prec`` argument is deprecated. The precision for
113
the result is deduced from the precision of the input. Convert
114
the input to a higher precision explicitly if a result with higher
115
precision is desired.::
116
117
sage: t = exp(RealField(100)(2)); t
118
7.3890560989306502272304274606
119
sage: t.prec()
120
100
121
122
TESTS::
123
124
sage: exp(2,prec=100)
125
doctest:...: DeprecationWarning: The prec keyword argument is deprecated. Explicitly set the precision of the input, for example exp(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., exp(1).n(300), instead.
126
7.3890560989306502272304274606
127
"""
128
if prec is not None:
129
from sage.misc.misc import deprecation
130
deprecation("The prec keyword argument is deprecated. Explicitly set the precision of the input, for example exp(RealField(300)(1)), or use the prec argument to .n() for exact inputs, e.g., exp(1).n(300), instead.")
131
x = GinacFunction.__call__(self, x, coerce=coerce, hold=hold,
132
dont_call_method_on_arg=dont_call_method_on_arg)
133
return x.n(prec)
134
return GinacFunction.__call__(self, x, coerce=coerce, hold=hold,
135
dont_call_method_on_arg=dont_call_method_on_arg)
136
137
exp = Function_exp()
138
139
class Function_log(GinacFunction):
140
def __init__(self):
141
r"""
142
The natural logarithm of x. See `log?` for
143
more information about its behavior.
144
145
EXAMPLES::
146
147
sage: ln(e^2)
148
2
149
sage: ln(2)
150
log(2)
151
sage: ln(10)
152
log(10)
153
154
::
155
156
sage: ln(RDF(10))
157
2.30258509299
158
sage: ln(2.718)
159
0.999896315728952
160
sage: ln(2.0)
161
0.693147180559945
162
sage: ln(float(-1))
163
3.141592653589793j
164
sage: ln(complex(-1))
165
3.141592653589793j
166
167
We do not currently support a ``hold`` parameter in functional
168
notation::
169
170
sage: log(SR(-1),hold=True)
171
Traceback (most recent call last):
172
...
173
TypeError: log() got an unexpected keyword argument 'hold'
174
175
This is possible with method notation::
176
177
sage: I.log(hold=True)
178
log(I)
179
sage: I.log(hold=True).simplify()
180
1/2*I*pi
181
182
TESTS::
183
184
sage: latex(x.log())
185
\log\left(x\right)
186
sage: latex(log(1/4))
187
\log\left(\frac{1}{4}\right)
188
sage: loads(dumps(ln(x)+1))
189
log(x) + 1
190
191
``conjugate(log(x))==log(conjugate(x))`` unless on the branch cut which
192
runs along the negative real axis.::
193
194
sage: conjugate(log(x))
195
conjugate(log(x))
196
sage: var('y', domain='positive')
197
y
198
sage: conjugate(log(y))
199
log(y)
200
sage: conjugate(log(y+I))
201
conjugate(log(y + I))
202
sage: conjugate(log(-1))
203
-I*pi
204
sage: log(conjugate(-1))
205
I*pi
206
207
Check if float arguments are handled properly.::
208
209
sage: from sage.functions.log import function_log as log
210
sage: log(float(5))
211
1.6094379124341003
212
sage: log(float(0))
213
-inf
214
sage: log(float(-1))
215
3.141592653589793j
216
sage: log(x).subs(x=float(-1))
217
3.141592653589793j
218
"""
219
GinacFunction.__init__(self, 'log', latex_name=r'\log',
220
conversions=dict(maxima='log'))
221
222
ln = function_log = Function_log()
223
224
def log(x, base=None):
225
"""
226
Return the logarithm of x to the given base.
227
228
Calls the ``log`` method of the object x when computing
229
the logarithm, thus allowing use of logarithm on any object
230
containing a ``log`` method. In other words, log works
231
on more than just real numbers.
232
233
EXAMPLES::
234
235
sage: log(e^2)
236
2
237
sage: log(1024, 2); RDF(log(1024, 2))
238
10
239
10.0
240
sage: log(10, 4); RDF(log(10, 4))
241
log(10)/log(4)
242
1.66096404744
243
244
::
245
246
sage: log(10, 2)
247
log(10)/log(2)
248
sage: n(log(10, 2))
249
3.32192809488736
250
sage: log(10, e)
251
log(10)
252
sage: n(log(10, e))
253
2.30258509299405
254
255
The log function works for negative numbers, complex
256
numbers, and symbolic numbers too, picking the branch
257
with angle between `-pi` and `pi`::
258
259
sage: log(-1+0*I)
260
I*pi
261
sage: log(CC(-1))
262
3.14159265358979*I
263
sage: log(-1.0)
264
3.14159265358979*I
265
266
For input zero, the following behavior occurs::
267
268
sage: log(0)
269
-Infinity
270
sage: log(CC(0))
271
-infinity
272
sage: log(0.0)
273
-infinity
274
275
The log function also works in finite fields as long as the argument lies
276
in the multiplicative group generated by the base::
277
278
sage: F = GF(13); g = F.multiplicative_generator(); g
279
2
280
sage: a = F(8)
281
sage: log(a,g); g^log(a,g)
282
3
283
8
284
sage: log(a,3)
285
Traceback (most recent call last):
286
...
287
ValueError: No discrete log of 8 found to base 3
288
sage: log(F(9), 3)
289
2
290
291
The log function also works for p-adics (see documentation for
292
p-adics for more information)::
293
294
sage: R = Zp(5); R
295
5-adic Ring with capped relative precision 20
296
sage: a = R(16); a
297
1 + 3*5 + O(5^20)
298
sage: log(a)
299
3*5 + 3*5^2 + 3*5^4 + 3*5^5 + 3*5^6 + 4*5^7 + 2*5^8 + 5^9 + 5^11 + 2*5^12 + 5^13 + 3*5^15 + 2*5^16 + 4*5^17 + 3*5^18 + 3*5^19 + O(5^20)
300
"""
301
if base is None:
302
try:
303
return x.log()
304
except AttributeError:
305
return ln(x)
306
else:
307
try:
308
return x.log(base)
309
except (AttributeError, TypeError):
310
return log(x) / log(base)
311
312
313
class Function_polylog(GinacFunction):
314
def __init__(self):
315
r"""
316
The polylog function
317
`\text{Li}_n(z) = \sum_{k=1}^{\infty} z^k / k^n`.
318
319
INPUT:
320
321
- ``n`` - object
322
- ``z`` - object
323
324
EXAMPLES::
325
326
sage: polylog(1, x)
327
-log(-x + 1)
328
sage: polylog(2,1)
329
1/6*pi^2
330
sage: polylog(2,x^2+1)
331
polylog(2, x^2 + 1)
332
sage: polylog(4,0.5)
333
polylog(4, 0.500000000000000)
334
335
sage: f = polylog(4, 1); f
336
1/90*pi^4
337
sage: f.n()
338
1.08232323371114
339
340
sage: polylog(4, 2).n()
341
2.42786280675470 - 0.174371300025453*I
342
sage: complex(polylog(4,2))
343
(2.4278628067547032-0.17437130002545306j)
344
sage: float(polylog(4,0.5))
345
0.5174790616738993
346
347
sage: z = var('z')
348
sage: polylog(2,z).series(z==0, 5)
349
1*z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + Order(z^5)
350
351
sage: loads(dumps(polylog))
352
polylog
353
354
sage: latex(polylog(5, x))
355
{\rm Li}_{5}(x)
356
357
TESTS:
358
359
Check if #8459 is fixed::
360
361
sage: t = maxima(polylog(5,x)).sage(); t
362
polylog(5, x)
363
sage: t.operator() == polylog
364
True
365
sage: t.subs(x=.5).n()
366
0.508400579242269
367
"""
368
GinacFunction.__init__(self, "polylog", nargs=2)
369
370
def _maxima_init_evaled_(self, *args):
371
"""
372
EXAMPLES:
373
374
These are indirect doctests for this function.::
375
376
sage: polylog(2, x)._maxima_()
377
li[2](x)
378
sage: polylog(4, x)._maxima_()
379
polylog(4,x)
380
"""
381
n, x = args
382
if int(n) in [1,2,3]:
383
return 'li[%s](%s)'%(n, x)
384
else:
385
return 'polylog(%s, %s)'%(n, x)
386
387
388
polylog = Function_polylog()
389
390
class Function_dilog(GinacFunction):
391
def __init__(self):
392
r"""
393
The dilogarithm function
394
`\text{Li}_2(z) = \sum_{k=1}^{\infty} z^k / k^2`.
395
396
This is simply an alias for polylog(2, z).
397
398
EXAMPLES::
399
400
sage: dilog(1)
401
1/6*pi^2
402
sage: dilog(1/2)
403
1/12*pi^2 - 1/2*log(2)^2
404
sage: dilog(x^2+1)
405
dilog(x^2 + 1)
406
sage: dilog(-1)
407
-1/12*pi^2
408
sage: dilog(-1.1)
409
-0.890838090262283
410
sage: float(dilog(1))
411
1.6449340668482262
412
sage: var('z')
413
z
414
sage: dilog(z).diff(z, 2)
415
log(-z + 1)/z^2 - 1/((z - 1)*z)
416
sage: dilog(z).series(z==1/2, 3)
417
(1/12*pi^2 - 1/2*log(2)^2) + (-2*log(1/2))*(z - 1/2) + (2*log(1/2) + 2)*(z - 1/2)^2 + Order(1/8*(2*z - 1)^3)
418
419
sage: latex(dilog(z))
420
{\rm Li}_2\left(z\right)
421
422
TESTS:
423
424
``conjugate(dilog(x))==dilog(conjugate(x))`` unless on the branch cuts
425
which run along the positive real axis beginning at 1.::
426
427
sage: conjugate(dilog(x))
428
conjugate(dilog(x))
429
sage: var('y',domain='positive')
430
y
431
sage: conjugate(dilog(y))
432
conjugate(dilog(y))
433
sage: conjugate(dilog(1/19))
434
dilog(1/19)
435
sage: conjugate(dilog(1/2*I))
436
dilog(-1/2*I)
437
sage: dilog(conjugate(1/2*I))
438
dilog(-1/2*I)
439
sage: conjugate(dilog(2))
440
conjugate(dilog(2))
441
"""
442
GinacFunction.__init__(self, 'dilog',
443
conversions=dict(maxima='li[2]'))
444
445
dilog = Function_dilog()
446
447
448
class Function_lambert_w(BuiltinFunction):
449
r"""
450
The integral branches of the Lambert W function `W_n(z)`.
451
452
This function satisfies the equation
453
454
.. math::
455
456
z = W_n(z) e^{W_n(z)}
457
458
INPUT:
459
460
- ``n`` - an integer. `n=0` corresponds to the principal branch.
461
462
- ``z`` - a complex number
463
464
If called with a single argument, that argument is ``z`` and the branch ``n`` is
465
assumed to be 0 (the principal branch).
466
467
ALGORITHM:
468
469
Numerical evaluation is handled using the mpmath and SciPy libraries.
470
471
REFERENCES:
472
473
- http://en.wikipedia.org/wiki/Lambert_W_function
474
475
EXAMPLES:
476
477
Evaluation of the principal branch::
478
479
sage: lambert_w(1.0)
480
0.567143290409784
481
sage: lambert_w(-1).n()
482
-0.318131505204764 + 1.33723570143069*I
483
sage: lambert_w(-1.5 + 5*I)
484
1.17418016254171 + 1.10651494102011*I
485
486
Evaluation of other branches::
487
488
sage: lambert_w(2, 1.0)
489
-2.40158510486800 + 10.7762995161151*I
490
491
Solutions to certain exponential equations are returned in terms of lambert_w::
492
493
sage: S = solve(e^(5*x)+x==0, x, to_poly_solve=True)
494
sage: z = S[0].rhs(); z
495
-1/5*lambert_w(5)
496
sage: N(z)
497
-0.265344933048440
498
499
Check the defining equation numerically at `z=5`::
500
501
sage: N(lambert_w(5)*exp(lambert_w(5)) - 5)
502
0.000000000000000
503
504
There are several special values of the principal branch which
505
are automatically simplified::
506
507
sage: lambert_w(0)
508
0
509
sage: lambert_w(e)
510
1
511
sage: lambert_w(-1/e)
512
-1
513
514
Integration (of the principal branch) is evaluated using Maxima::
515
516
sage: integrate(lambert_w(x), x)
517
(lambert_w(x)^2 - lambert_w(x) + 1)*x/lambert_w(x)
518
sage: integrate(lambert_w(x), x, 0, 1)
519
(lambert_w(1)^2 - lambert_w(1) + 1)/lambert_w(1) - 1
520
sage: integrate(lambert_w(x), x, 0, 1.0)
521
0.330366124762
522
523
Warning: The integral of a non-principal branch is not implemented,
524
neither is numerical integration using GSL. The :meth:`numerical_integral`
525
function does work if you pass a lambda function::
526
527
sage: numerical_integral(lambda x: lambert_w(x), 0, 1)
528
(0.33036612476168054, 3.667800782666048e-15)
529
"""
530
531
def __init__(self):
532
r"""
533
See the docstring for :meth:`Function_lambert_w`.
534
535
EXAMPLES::
536
537
sage: lambert_w(0, 1.0)
538
0.567143290409784
539
"""
540
BuiltinFunction.__init__(self, "lambert_w", nargs=2,
541
conversions={'mathematica':'ProductLog',
542
'maple':'LambertW'})
543
544
def __call__(self, *args, **kwds):
545
r"""
546
Custom call method allows the user to pass one argument or two. If
547
one argument is passed, we assume it is ``z`` and that ``n=0``.
548
549
EXAMPLES::
550
551
sage: lambert_w(1)
552
lambert_w(1)
553
sage: lambert_w(1, 2)
554
lambert_w(1, 2)
555
"""
556
if len(args) == 2:
557
return BuiltinFunction.__call__(self, *args, **kwds)
558
elif len(args) == 1:
559
return BuiltinFunction.__call__(self, 0, args[0], **kwds)
560
else:
561
raise TypeError("lambert_w takes either one or two arguments.")
562
563
def _eval_(self, n, z):
564
"""
565
EXAMPLES::
566
567
sage: lambert_w(6.0)
568
1.43240477589830
569
sage: lambert_w(1)
570
lambert_w(1)
571
sage: lambert_w(x+1)
572
lambert_w(x + 1)
573
574
There are three special values which are automatically simplified::
575
576
sage: lambert_w(0)
577
0
578
sage: lambert_w(e)
579
1
580
sage: lambert_w(-1/e)
581
-1
582
sage: lambert_w(SR(0))
583
0
584
585
The special values only hold on the principal branch::
586
587
sage: lambert_w(1,e)
588
lambert_w(1, e)
589
sage: lambert_w(1, e.n())
590
-0.532092121986380 + 4.59715801330257*I
591
592
TESTS:
593
594
When automatic simplication occurs, the parent of the output value should be
595
either the same as the parent of the input, or a Sage type::
596
597
sage: parent(lambert_w(int(0)))
598
<type 'int'>
599
sage: parent(lambert_w(Integer(0)))
600
Integer Ring
601
sage: parent(lambert_w(e))
602
Integer Ring
603
"""
604
if not isinstance(z, Expression):
605
if is_inexact(z):
606
return self._evalf_(n, z, parent=sage_structure_coerce_parent(z))
607
elif n == 0 and z == 0:
608
return sage_structure_coerce_parent(z)(Integer(0))
609
elif n == 0:
610
if z.is_trivial_zero():
611
return sage_structure_coerce_parent(z)(Integer(0))
612
elif (z-const_e).is_trivial_zero():
613
return sage_structure_coerce_parent(z)(Integer(1))
614
elif (z+1/const_e).is_trivial_zero():
615
return sage_structure_coerce_parent(z)(Integer(-1))
616
return None
617
618
def _evalf_(self, n, z, parent=None):
619
"""
620
EXAMPLES::
621
622
sage: N(lambert_w(1))
623
0.567143290409784
624
sage: lambert_w(RealField(100)(1))
625
0.56714329040978387299996866221
626
627
SciPy is used to evaluate for float, RDF, and CDF inputs::
628
629
sage: lambert_w(RDF(1))
630
0.56714329041
631
"""
632
R = parent or sage_structure_coerce_parent(z)
633
if R is float or R is complex or R is RDF or R is CDF:
634
import scipy.special
635
return scipy.special.lambertw(z, n)
636
else:
637
import mpmath
638
return mpmath_utils.call(mpmath.lambertw, z, n, parent=R)
639
640
def _derivative_(self, n, z, diff_param=None):
641
"""
642
The derivative of `W_n(x)` is `W_n(x)/(x \cdot W_n(x) + x)`.
643
644
EXAMPLES::
645
646
sage: x = var('x')
647
sage: derivative(lambert_w(x), x)
648
lambert_w(x)/(x*lambert_w(x) + x)
649
"""
650
return lambert_w(n, z)/(z*lambert_w(n, z)+z)
651
652
def _maxima_init_evaled_(self, n, z):
653
"""
654
EXAMPLES:
655
656
These are indirect doctests for this function.::
657
658
sage: lambert_w(0, x)._maxima_()
659
lambert_w(x)
660
sage: lambert_w(1, x)._maxima_()
661
Traceback (most recent call last):
662
...
663
NotImplementedError: Non-principal branch lambert_w[1](x) is not implemented in Maxima
664
"""
665
if n == 0:
666
return "lambert_w(%s)" % z
667
else:
668
raise NotImplementedError("Non-principal branch lambert_w[%s](%s) is not implemented in Maxima" % (n, z))
669
670
671
def _print_(self, n, z):
672
"""
673
Custom _print_ method to avoid printing the branch number if
674
it is zero.
675
676
EXAMPLES::
677
678
sage: lambert_w(1)
679
lambert_w(1)
680
sage: lambert_w(0,x)
681
lambert_w(x)
682
"""
683
if n == 0:
684
return "lambert_w(%s)" % z
685
else:
686
return "lambert_w(%s, %s)" % (n,z)
687
688
def _print_latex_(self, n, z):
689
"""
690
Custom _print_latex_ method to avoid printing the branch
691
number if it is zero.
692
693
EXAMPLES::
694
695
sage: latex(lambert_w(1))
696
\operatorname{W_0}(1)
697
sage: latex(lambert_w(0,x))
698
\operatorname{W_0}(x)
699
sage: latex(lambert_w(1,x))
700
\operatorname{W_{1}}(x)
701
"""
702
if n == 0:
703
return r"\operatorname{W_0}(%s)" % z
704
else:
705
return r"\operatorname{W_{%s}}(%s)" % (n,z)
706
707
lambert_w = Function_lambert_w()
708
709