Skip to content

Commit 5d8890e

Browse files
committed
Restore maxima wrapper and comment about Pexpect interface
1 parent a4bf6e2 commit 5d8890e

File tree

5 files changed

+189
-1
lines changed

5 files changed

+189
-1
lines changed

src/sage/interfaces/maxima_abstract.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ class MaximaAbstract(ExtraTabCompletion, Interface):
9292
EXAMPLES:
9393
9494
This class should not be instantiated directly,
95-
but through its subclass MaximaLib (which is a singleton)::
95+
but should be used through its subclass MaximaLib (which is a singleton), or through
96+
the Pexpect interface Maxima.
9697
9798
sage: from sage.interfaces.maxima_abstract import MaximaAbstract
9899
sage: from sage.interfaces.maxima_lib import maxima

src/sage/structure/sage_object.pyx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,14 @@ cdef class SageObject:
549549
def parent(self):
550550
"""
551551
Return the type of ``self`` to support the coercion framework.
552+
553+
EXAMPLES::
554+
555+
sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t # needs sage.symbolic
556+
log(sqrt(2) + 1) + log(sqrt(2) - 1)
557+
sage: u = t.maxima_methods() # needs sage.symbolic
558+
sage: u.parent() # needs sage.symbolic
559+
<class 'sage.symbolic.maxima_wrapper.MaximaWrapper'>
552560
"""
553561
return type(self)
554562

src/sage/symbolic/expression.pyx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10335,6 +10335,23 @@ cdef class Expression(Expression_abc):
1033510335
return [self.parent()(ex)
1033610336
for ex in self._maxima_().partfrac(var).args()]
1033710337

10338+
def maxima_methods(self):
10339+
"""
10340+
Provide easy access to maxima methods, converting the result to a
10341+
Sage expression automatically.
10342+
10343+
EXAMPLES::
10344+
10345+
sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
10346+
log(sqrt(2) + 1) + log(sqrt(2) - 1)
10347+
sage: res = t.maxima_methods().logcontract(); res
10348+
log((sqrt(2) + 1)*(sqrt(2) - 1))
10349+
sage: type(res)
10350+
<class 'sage.symbolic.expression.Expression'>
10351+
"""
10352+
from sage.symbolic.maxima_wrapper import MaximaWrapper
10353+
return MaximaWrapper(self)
10354+
1033810355
def rectform(self):
1033910356
r"""
1034010357
Convert this symbolic expression to rectangular form; that
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
"Access to Maxima methods"
2+
3+
###############################################################################
4+
# Sage: Open Source Mathematical Software
5+
# Copyright (C) 2010 Burcin Erocal <[email protected]>
6+
# Distributed under the terms of the GNU General Public License (GPL),
7+
# version 2 or any later version. The full text of the GPL is available at:
8+
# https://www.gnu.org/licenses/
9+
###############################################################################
10+
11+
from sage.structure.sage_object import SageObject
12+
from sage.interfaces.maxima import MaximaFunctionElement
13+
from sage.misc.instancedoc import instancedoc
14+
15+
16+
@instancedoc
17+
class MaximaFunctionElementWrapper(MaximaFunctionElement):
18+
def __call__(self, *args, **kwds):
19+
"""
20+
Return a Sage expression instead of a Maxima pexpect interface element.
21+
22+
EXAMPLES::
23+
24+
sage: t = sin(x)^2 + cos(x)^2; t
25+
cos(x)^2 + sin(x)^2
26+
sage: res = t.maxima_methods().trigsimp(); res
27+
1
28+
sage: parent(res)
29+
Symbolic Ring
30+
"""
31+
return super().__call__(*args, **kwds).sage()
32+
33+
34+
class MaximaWrapper(SageObject):
35+
def __init__(self, exp):
36+
"""
37+
Wrapper around Sage expressions to give access to Maxima methods.
38+
39+
We convert the given expression to Maxima and convert the return value
40+
back to a Sage expression. Tab completion and help strings of Maxima
41+
methods also work as expected.
42+
43+
EXAMPLES::
44+
45+
sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
46+
log(sqrt(2) + 1) + log(sqrt(2) - 1)
47+
sage: u = t.maxima_methods(); u
48+
MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))
49+
sage: type(u)
50+
<class 'sage.symbolic.maxima_wrapper.MaximaWrapper'>
51+
sage: u.logcontract()
52+
log((sqrt(2) + 1)*(sqrt(2) - 1))
53+
sage: u.logcontract().parent()
54+
Symbolic Ring
55+
56+
TESTS:
57+
58+
Test tab completions::
59+
60+
sage: import sage.interfaces.tab_completion as s
61+
sage: u = t.maxima_methods()
62+
sage: s.completions('u.elliptic_',globals())
63+
['u.elliptic_e', 'u.elliptic_ec', 'u.elliptic_eu', 'u.elliptic_f', 'u.elliptic_kc', 'u.elliptic_pi']
64+
"""
65+
self._exp = exp
66+
self._maxima_exp = None
67+
68+
def __getattr__(self, s):
69+
"""
70+
Direct attempts to get attributes of this wrapper to the corresponding
71+
Maxima expression. This allows tab completion to work as expected.
72+
73+
We wrap the function calls in order to convert results back to Sage.
74+
75+
EXAMPLES::
76+
77+
sage: t = sin(x)^2 + cos(x)^2; t
78+
cos(x)^2 + sin(x)^2
79+
sage: u = t.maxima_methods()
80+
sage: import sage.interfaces.tab_completion as s
81+
sage: s.completions('u.airy_',globals())
82+
['u.airy_ai', 'u.airy_bi', 'u.airy_dai', 'u.airy_dbi']
83+
sage: type(u.airy_ai)
84+
<class 'sage.symbolic.maxima_wrapper.MaximaFunctionElementWrapper'>
85+
sage: u.airy_ai()
86+
airy_ai(cos(x)^2 + sin(x)^2)
87+
"""
88+
if self._maxima_exp is None:
89+
self._maxima_exp = self._exp._maxima_()
90+
if s[0] == '_':
91+
return getattr(self._maxima_exp, s)
92+
# add a wrapper function which converts the result back to
93+
# a Sage expression
94+
return MaximaFunctionElementWrapper(self._maxima_exp, s)
95+
96+
def __dir__(self):
97+
"""
98+
Enable the tab completions.
99+
100+
EXAMPLES::
101+
102+
sage: t = sin(x) + cos(x)
103+
sage: u = t.maxima_methods()
104+
sage: 'zeta' in u.__dir__()
105+
True
106+
"""
107+
return self._maxima_()._tab_completion()
108+
109+
def sage(self):
110+
"""
111+
Return the Sage expression this wrapper corresponds to.
112+
113+
EXAMPLES::
114+
115+
sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
116+
log(sqrt(2) + 1) + log(sqrt(2) - 1)
117+
sage: u = t.maxima_methods().sage()
118+
sage: u is t
119+
True
120+
"""
121+
return self._exp
122+
123+
def _symbolic_(self, parent):
124+
"""
125+
EXAMPLES::
126+
127+
sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
128+
log(sqrt(2) + 1) + log(sqrt(2) - 1)
129+
sage: u = t.maxima_methods()
130+
sage: u._symbolic_(SR) is t
131+
True
132+
sage: SR(u) is t # indirect doctest
133+
True
134+
"""
135+
return parent(self._exp)
136+
137+
def __reduce__(self):
138+
"""
139+
EXAMPLES::
140+
141+
sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
142+
log(sqrt(2) + 1) + log(sqrt(2) - 1)
143+
sage: u = t.maxima_methods(); u
144+
MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))
145+
sage: loads(dumps(u))
146+
MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))
147+
"""
148+
return (MaximaWrapper, (self._exp,))
149+
150+
def _repr_(self):
151+
"""
152+
EXAMPLES::
153+
154+
sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
155+
log(sqrt(2) + 1) + log(sqrt(2) - 1)
156+
sage: u = t.maxima_methods(); u
157+
MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))
158+
sage: u._repr_()
159+
'MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))'
160+
"""
161+
return "MaximaWrapper(%s)" % (self._exp)

src/sage/symbolic/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ py.install_sources(
1717
'function.pxd',
1818
'function.pyx',
1919
'function_factory.py',
20+
'maxima_wrapper.py',
2021
'operators.py',
2122
'pynac_wrap.h',
2223
'random_tests.py',

0 commit comments

Comments
 (0)