@@ -2375,6 +2375,133 @@ def derivative(self, ex, operator):
2375
2375
else :
2376
2376
return operator (* [self (_ ) for _ in ex .operands ()])
2377
2377
2378
+ class Exponentialize (ExpressionTreeWalker ):
2379
+ # Implementation note: this code is executed once at first
2380
+ # reference in the code using it, therefore avoiding rebuilding
2381
+ # the same canned results dictionary at each call.
2382
+ from sage .functions .hyperbolic import sinh , cosh , sech , csch , tanh , coth
2383
+ from sage .functions .log import exp
2384
+ from sage .functions .trig import sin , cos , sec , csc , tan , cot
2385
+ from sage .rings .imaginary_unit import I
2386
+ from sage .symbolic .constants import e
2387
+ from sage .rings .integer import Integer
2388
+ from sage .symbolic .ring import SR
2389
+ from sage .calculus .var import function
2390
+ half = Integer (1 ) / Integer (2 )
2391
+ two = Integer (2 )
2392
+ x = SR .var ("x" )
2393
+ CircDict = {
2394
+ sin : (- half * I * exp (I * x ) + half * I * exp (- I * x )).function (x ),
2395
+ cos : (half * exp (I * x ) + half * exp (- I * x )).function (x ),
2396
+ sec : (two / (exp (I * x ) + exp (- I * x ))).function (x ),
2397
+ csc : (two * I / (exp (I * x ) - exp (- I * x ))).function (x ),
2398
+ tan : (- I * (exp (I * x ) - exp (- I * x ))/ (exp (I * x ) + exp (- I * x ))).function (x ),
2399
+ cot : (I * (exp (I * x ) + exp (- I * x ))/ (exp (I * x ) - exp (- I * x ))).function (x ),
2400
+ sinh : (- half * exp (- x ) + half * exp (x )).function (x ),
2401
+ cosh : (half * exp (- x ) + half * exp (x )).function (x ),
2402
+ sech : (two / (exp (- x ) + exp (x ))).function (x ),
2403
+ csch : (- two / (exp (- x ) - exp (x ))).function (x ),
2404
+ tanh : (- (exp (- x ) - exp (x ))/ (exp (x ) + exp (- x ))).function (x ),
2405
+ coth : (- (exp (- x ) + exp (x ))/ (exp (- x ) - exp (x ))).function (x )
2406
+ }
2407
+ Circs = list (CircDict .keys ())
2408
+
2409
+ def __init__ (self , ex ):
2410
+ """
2411
+ A class that walks a symbolic expression tree and replace circular
2412
+ and hyperbolic functions by their respective exponential
2413
+ expressions.
2414
+
2415
+ EXAMPLES::
2416
+
2417
+ sage: from sage.symbolic.expression_conversions import Exponentialize
2418
+ sage: d=Exponentialize(sin(x))
2419
+ sage: d(sin(x))
2420
+ -1/2*I*e^(I*x) + 1/2*I*e^(-I*x)
2421
+ sage: d(cosh(x))
2422
+ 1/2*e^(-x) + 1/2*e^x
2423
+ """
2424
+ self .ex = ex
2425
+
2426
+ def composition (self , ex , op ):
2427
+ r"""
2428
+ Return the composition of ``self`` with ``ex`` by ``op``.
2429
+
2430
+ EXAMPLES::
2431
+
2432
+ sage: x = SR.var("x")
2433
+ sage: from sage.symbolic.expression_conversions import Exponentialize
2434
+ sage: p = x
2435
+ sage: s = Exponentialize(p)
2436
+ sage: q = sin(x)
2437
+ sage: s.composition(q, q.operator())
2438
+ -1/2*I*e^(I*x) + 1/2*I*e^(-I*x)
2439
+ """
2440
+ if op in self .Circs :
2441
+ return self .CircDict .get (op )(* [self (oper )
2442
+ for oper in ex .operands ()])
2443
+ return super (Exponentialize , self ).composition (ex , op )
2444
+
2445
+ class DeMoivre (ExpressionTreeWalker ):
2446
+ def __init__ (self , ex , force = False ):
2447
+ r"""
2448
+ A class that walks a symbolic expression tree and replaces
2449
+ occurences of complex exponentials (optionally, all
2450
+ exponentials) by their respective trigonometric expressions.
2451
+
2452
+ INPUT:
2453
+
2454
+ - ``force`` -- boolean (default: ``False``); replace `\exp(x)`
2455
+ with `\cosh(x) + \sinh(x)`
2456
+
2457
+ EXAMPLES::
2458
+
2459
+ sage: a, b = SR.var("a, b")
2460
+ sage: from sage.symbolic.expression_conversions import DeMoivre
2461
+ sage: d=DeMoivre(e^a)
2462
+ sage: d(e^(a+I*b))
2463
+ (cos(b) + I*sin(b))*e^a
2464
+ """
2465
+ self .ex = ex
2466
+ self .force = force
2467
+
2468
+ def composition (self , ex , op ):
2469
+ """
2470
+ Return the composition of ``self`` with ``ex`` by ``op``.
2471
+
2472
+ EXAMPLES::
2473
+
2474
+ sage: x, a, b = SR.var('x, a, b')
2475
+ sage: from sage.symbolic.expression_conversions import DeMoivre
2476
+ sage: p = exp(x)
2477
+ sage: s = DeMoivre(p)
2478
+ sage: q = exp(a+I*b)
2479
+ sage: s.composition(q, q.operator())
2480
+ (cos(b) + I*sin(b))*e^a
2481
+ """
2482
+ from sage .functions .log import exp
2483
+ if op is not exp :
2484
+ # return super(DeMoivre, self).composition(ex, op)
2485
+ return op (* [self (oper ) for oper in ex .operands ()])
2486
+
2487
+ from sage .rings .imaginary_unit import I
2488
+ from sage .symbolic .ring import SR
2489
+ from sage .functions .hyperbolic import sinh , cosh
2490
+ from sage .functions .trig import sin , cos
2491
+ arg = self (ex .operands ()[0 ])()
2492
+ w0 , w1 = (SR .wild (u ) for u in range (2 ))
2493
+ D = arg .match (w0 + I * w1 )
2494
+ if D is not None :
2495
+ A = D .get (w1 )
2496
+ return exp (D .get (w0 ))* (cos (A ) + I * sin (A ))
2497
+ D = arg .match (I * w0 )
2498
+ if D is not None :
2499
+ A = D .get (w0 )
2500
+ return cos (A ) + I * sin (A )
2501
+ if self .force :
2502
+ return cosh (arg ) + sinh (arg )
2503
+ return exp (arg )
2504
+
2378
2505
class HoldRemover (ExpressionTreeWalker ):
2379
2506
def __init__ (self , ex , exclude = None ):
2380
2507
"""
0 commit comments