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