| 443 | |
| 444 | class Function_lambert_w(BuiltinFunction): |
| 445 | r""" |
| 446 | The principle branch of the Lambert W function `W_0(z)`. |
| 447 | |
| 448 | This function satisfies the equation: |
| 449 | |
| 450 | .. math:: |
| 451 | |
| 452 | z = W_0(z) e^{W_0(z)} |
| 453 | |
| 454 | IMPUT: |
| 455 | |
| 456 | ``z`` - a complex number |
| 457 | |
| 458 | ALGORITHM: |
| 459 | |
| 460 | Numerical evaluation is handled using the mpmath library. |
| 461 | |
| 462 | REFERENCES: |
| 463 | |
| 464 | http://en.wikipedia.org/wiki/Lambert_W_function |
| 465 | |
| 466 | EXAMPLES:: |
| 467 | |
| 468 | sage: lambert_w(1.0) |
| 469 | 0.567143290409784 |
| 470 | sage: lambert_w(-1).n() |
| 471 | -0.318131505204764 + 1.33723570143069*I |
| 472 | sage: lambert_w(-1.5 + 5*I) |
| 473 | 1.17418016254171 + 1.10651494102011*I |
| 474 | |
| 475 | sage: lambert_w(RealField(100)(1)) |
| 476 | 0.56714329040978387299996866221 |
| 477 | |
| 478 | sage: S = solve(e^(5*x)+x==0, x, to_poly_solve=True) |
| 479 | sage: z = S[0].rhs(); z |
| 480 | -1/5*lambert_w(5) |
| 481 | sage: N(z) |
| 482 | -0.265344933048440 |
| 483 | |
| 484 | Check the defining equation numerically at `z=5`:: |
| 485 | |
| 486 | sage: N(lambert_w(5)*exp(lambert_w(5)) - 5) |
| 487 | 0.000000000000000 |
| 488 | |
| 489 | """ |
| 490 | def __init__(self): |
| 491 | """ |
| 492 | See the docstring for :meth:`Function_lambert_w`. |
| 493 | |
| 494 | EXAMPLES:: |
| 495 | |
| 496 | sage: lambert_w(1.0) |
| 497 | 0.567143290409784 |
| 498 | |
| 499 | """ |
| 500 | BuiltinFunction.__init__(self, "lambert_w", nargs=1, latex_name=r'W_0', |
| 501 | conversions=dict(maxima='lambert_w')) |
| 502 | |
| 503 | def _eval_(self, z): |
| 504 | """ |
| 505 | EXAMPLES:: |
| 506 | |
| 507 | sage: lambert_w(0) |
| 508 | lambert_w(0) |
| 509 | sage: x = var('x') |
| 510 | sage: lambert_w(x) |
| 511 | lambert_w(x) |
| 512 | sage: lambert_w(0.0) |
| 513 | 0.000000000000000 |
| 514 | |
| 515 | """ |
| 516 | if not isinstance(z, Expression) and is_inexact(z): |
| 517 | return self._evalf_(z, parent(z)) |
| 518 | |
| 519 | return None |
| 520 | |
| 521 | def _evalf_(self, z, parent=None): |
| 522 | """ |
| 523 | EXAMPLES:: |
| 524 | |
| 525 | sage: N(lambert_w(1)) |
| 526 | 0.567143290409784 |
| 527 | sage: lambert_w(RealField(100)(1)) |
| 528 | 0.56714329040978387299996866221 |
| 529 | |
| 530 | """ |
| 531 | import mpmath |
| 532 | return mpmath_utils.call(mpmath.lambertw, z, parent=parent) |
| 533 | |
| 534 | def _derivative_(self, z, diff_param=None): |
| 535 | """ |
| 536 | The derivative of `W_0(x)` is `W_0(x)/(x \cdot W_0(x) + x)`. |
| 537 | |
| 538 | EXAMPLES:: |
| 539 | |
| 540 | sage: x = var('x') |
| 541 | sage: derivative(lambert_w(x), x) |
| 542 | lambert_w(x)/(x*lambert_w(x) + x) |
| 543 | |
| 544 | """ |
| 545 | return lambert_w(z)/(z*lambert_w(z)+z) |
| 546 | |
| 547 | lambert_w = Function_lambert_w() |
| 548 | |