Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/interfaces/interface.py
8814 views
1
r"""
2
Common Interface Functionality
3
4
See the examples in the other sections for how to use specific
5
interfaces. The interface classes all derive from the generic
6
interface that is described in this section.
7
8
AUTHORS:
9
10
- William Stein (2005): initial version
11
12
- William Stein (2006-03-01): got rid of infinite loop on startup if
13
client system missing
14
15
- Felix Lawrence (2009-08-21): edited ._sage_() to support lists and float exponents in foreign notation.
16
17
- Simon King (2010-09-25): Expect._local_tmpfile() depends on
18
Expect.pid() and is cached; Expect.quit() clears that cache,
19
which is important for forking.
20
21
- Jean-Pierre Flori (2010,2011): Split non Pexpect stuff into a parent class.
22
"""
23
24
#*****************************************************************************
25
# Copyright (C) 2005 William Stein <[email protected]>
26
#
27
# Distributed under the terms of the GNU General Public License (GPL)
28
#
29
# This code is distributed in the hope that it will be useful,
30
# but WITHOUT ANY WARRANTY; without even the implied warranty of
31
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32
# General Public License for more details.
33
#
34
# The full text of the GPL is available at:
35
#
36
# http://www.gnu.org/licenses/
37
#*****************************************************************************
38
39
import operator
40
41
from sage.structure.sage_object import SageObject
42
from sage.structure.parent_base import ParentWithBase
43
from sage.structure.element import RingElement
44
45
import sage.misc.sage_eval
46
47
48
class AsciiArtString(str):
49
def __repr__(self):
50
return str(self)
51
52
53
class Interface(ParentWithBase):
54
"""
55
Interface interface object.
56
"""
57
def __init__(self, name):
58
self.__name = name
59
self.__coerce_name = '_' + name.lower() + '_'
60
self.__seq = -1
61
self._available_vars = []
62
ParentWithBase.__init__(self, self)
63
64
def _repr_(self):
65
return self.__name.capitalize()
66
67
def name(self, new_name=None):
68
return self.__name
69
70
def interact(self):
71
r"""
72
This allows you to interactively interact with the child
73
interpreter. Press Ctrl-D or type 'quit' or 'exit' to exit and
74
return to Sage.
75
76
.. note::
77
78
This is completely different than the console() member
79
function. The console function opens a new copy of the
80
child interpreter, whereas the interact function gives you
81
interactive access to the interpreter that is being used by
82
Sage. Use sage(xxx) or interpretername(xxx) to pull objects
83
in from sage to the interpreter.
84
"""
85
from sage.misc.interpreter import interface_shell_embed
86
shell = interface_shell_embed(self)
87
try:
88
ipython = get_ipython()
89
except NameError:
90
shell()
91
else:
92
shell(local_ns=dict(ipython.user_ns))
93
94
def _pre_interact(self):
95
pass
96
97
def _post_interact(self):
98
pass
99
100
def __del__(self):
101
pass
102
103
def cputime(self):
104
"""
105
CPU time since this process started running.
106
"""
107
raise NotImplementedError
108
109
def read(self, filename):
110
r"""
111
EXAMPLES::
112
113
sage: filename = tmp_filename()
114
sage: f = open(filename, 'w')
115
sage: f.write('x = 2\n')
116
sage: f.close()
117
sage: octave.read(filename) # optional - octave
118
sage: octave.get('x') #optional
119
' 2'
120
sage: import os
121
sage: os.unlink(filename)
122
"""
123
self.eval(self._read_in_file_command(filename))
124
125
def _read_in_file_command(self, filename):
126
raise NotImplementedError
127
128
def eval(self, code, locals=None, **kwds):
129
"""
130
INPUT:
131
132
133
- ``code`` - text to evaluate
134
135
- ``locals`` - None (ignored); this is used for compatibility with the
136
Sage notebook's generic system interface.
137
138
- ``**kwds`` - All other arguments are passed onto
139
the _eval_line method. An often useful example is
140
reformat=False.
141
"""
142
143
if not isinstance(code, basestring):
144
raise TypeError, 'input code must be a string.'
145
146
#Remove extra whitespace
147
code = code.strip()
148
149
try:
150
pass
151
# DO NOT CATCH KeyboardInterrupt, as it is being caught
152
# by _eval_line
153
# In particular, do NOT call self._keyboard_interrupt()
154
except TypeError, s:
155
raise TypeError, 'error evaluating "%s":\n%s'%(code,s)
156
157
_eval_line = eval
158
159
def execute(self, *args, **kwds):
160
return self.eval(*args, **kwds)
161
162
def __call__(self, x, name=None):
163
164
r"""
165
Create a new object in self from x.
166
167
The object X returned can be used like any Sage object, and
168
wraps an object in self. The standard arithmetic operators
169
work. Moreover if foo is a function then
170
X.foo(y,z,...)
171
calls foo(X, y, z, ...) and returns the corresponding object.
172
173
EXAMPLES::
174
175
sage: gp(2)
176
2
177
sage: gp('2')
178
2
179
sage: a = gp(2); gp(a) is a
180
True
181
182
"""
183
cls = self._object_class()
184
185
#Handle the case when x is an object
186
#in some interface.
187
if isinstance(x, InterfaceElement):
188
if x.parent() is self:
189
return x
190
191
#We convert x into an object in this
192
#interface by first going through Sage.
193
try:
194
return self(x._sage_())
195
except (NotImplementedError, TypeError):
196
pass
197
198
if isinstance(x, basestring):
199
return cls(self, x, name=name)
200
try:
201
return self._coerce_from_special_method(x)
202
except TypeError:
203
raise
204
except AttributeError, msg:
205
pass
206
try:
207
return self._coerce_impl(x, use_special=False)
208
except TypeError, msg:
209
try:
210
return cls(self, str(x), name=name)
211
except TypeError, msg2:
212
raise TypeError, msg
213
214
def _coerce_from_special_method(self, x):
215
"""
216
Tries to coerce to self by calling a special underscore method.
217
218
If no such method is defined, raises an AttributeError instead of a
219
TypeError.
220
"""
221
s = '_%s_'%self.name()
222
if s == '_maxima_lib_':
223
s = '_maxima_'
224
if s == '_pari_':
225
s = '_gp_'
226
try:
227
return (x.__getattribute__(s))(self)
228
except AttributeError:
229
return self(x._interface_init_())
230
231
def _coerce_impl(self, x, use_special=True):
232
if isinstance(x, (int, long)):
233
import sage.rings.all
234
return self(sage.rings.all.Integer(x))
235
elif isinstance(x, float):
236
import sage.rings.all
237
return self(sage.rings.all.RDF(x))
238
if use_special:
239
try:
240
return self._coerce_from_special_method(x)
241
except AttributeError, msg:
242
pass
243
244
if isinstance(x, (list, tuple)):
245
A = []
246
z = []
247
cls = self._object_class()
248
for v in x:
249
if isinstance(v, cls):
250
A.append(v.name())
251
z.append(v)
252
else:
253
w = self(v)
254
A.append(w.name())
255
z.append(w)
256
X = ','.join(A)
257
r = self.new('%s%s%s'%(self._left_list_delim(), X, self._right_list_delim()))
258
r.__sage_list = z # do this to avoid having the entries of the list be garbage collected
259
return r
260
261
raise TypeError, "unable to coerce element into %s"%self.name()
262
263
def new(self, code):
264
return self(code)
265
266
###################################################################
267
# these should all be appropriately overloaded by the derived class
268
###################################################################
269
270
def _left_list_delim(self):
271
return "["
272
273
def _right_list_delim(self):
274
return "]"
275
276
def _left_func_delim(self):
277
return "("
278
279
def _right_func_delim(self):
280
return ")"
281
282
def _assign_symbol(self):
283
return "="
284
285
def _equality_symbol(self):
286
raise NotImplementedError
287
288
# For efficiency purposes, you should definitely override these
289
# in your derived class.
290
def _true_symbol(self):
291
try:
292
return self.__true_symbol
293
except AttributeError:
294
self.__true_symbol = self.eval('1 %s 1'%self._equality_symbol())
295
296
def _false_symbol(self):
297
try:
298
return self.__false_symbol
299
except AttributeError:
300
self.__false_symbol = self.eval('1 %s 2'%self._equality_symbol())
301
302
def _lessthan_symbol(self):
303
return '<'
304
305
def _greaterthan_symbol(self):
306
return '>'
307
308
def _inequality_symbol(self):
309
return '!='
310
311
def _relation_symbols(self):
312
"""
313
Returns a dictionary with operators as the keys and their
314
string representation as the values.
315
316
EXAMPLES::
317
318
sage: import operator
319
sage: symbols = mathematica._relation_symbols()
320
sage: symbols[operator.eq]
321
'=='
322
"""
323
return dict([(operator.eq, self._equality_symbol()), (operator.ne, self._inequality_symbol()),
324
(operator.lt, self._lessthan_symbol()), (operator.le, "<="),
325
(operator.gt, self._greaterthan_symbol()), (operator.ge, ">=")])
326
327
def _exponent_symbol(self):
328
"""
329
Return the symbol used to denote *10^ in floats, e.g 'e' in 1.5e6
330
331
EXAMPLES::
332
333
sage: from sage.interfaces.expect import Expect
334
sage: Expect('nonexistent_interface', 'fake')._exponent_symbol()
335
'e'
336
"""
337
return 'e'
338
339
############################################################
340
# Functions for working with variables.
341
# The first three must be overloaded by derived classes,
342
# and the definition depends a lot on the class. But
343
# the functionality one gets from this is very nice.
344
############################################################
345
346
def set(self, var, value):
347
"""
348
Set the variable var to the given value.
349
"""
350
cmd = '%s%s%s;'%(var,self._assign_symbol(), value)
351
self.eval(cmd)
352
353
def get(self, var):
354
"""
355
Get the value of the variable var.
356
"""
357
return self.eval(var)
358
359
def get_using_file(self, var):
360
r"""
361
Return the string representation of the variable var in self,
362
possibly using a file. Use this if var has a huge string
363
representation, since it may be way faster.
364
365
.. warning::
366
367
In fact unless a special derived class implements this, it
368
will *not* be any faster. This is the case for this class
369
if you're reading it through introspection and seeing this.
370
"""
371
return self.get(var)
372
373
def clear(self, var):
374
"""
375
Clear the variable named var.
376
"""
377
self._available_vars.append(var)
378
379
def _next_var_name(self):
380
if len(self._available_vars) != 0:
381
v = self._available_vars[0]
382
del self._available_vars[0]
383
return v
384
self.__seq += 1
385
return "sage%s"%self.__seq
386
387
def _create(self, value, name=None):
388
name = self._next_var_name() if name is None else name
389
self.set(name, value)
390
return name
391
392
def _object_class(self):
393
"""
394
EXAMPLES::
395
396
sage: from sage.interfaces.expect import Expect
397
sage: Expect._object_class(maxima)
398
<class 'sage.interfaces.expect.ExpectElement'>
399
"""
400
return InterfaceElement
401
402
def _function_class(self):
403
"""
404
EXAMPLES::
405
406
sage: from sage.interfaces.interface import Interface
407
sage: Interface._function_class(maxima)
408
<class 'sage.interfaces.interface.InterfaceFunction'>
409
"""
410
return InterfaceFunction
411
412
def _function_element_class(self):
413
"""
414
EXAMPLES::
415
416
sage: from sage.interfaces.interface import Interface
417
sage: Interface._function_element_class(maxima)
418
<class 'sage.interfaces.interface.InterfaceFunctionElement'>
419
"""
420
return InterfaceFunctionElement
421
422
def _convert_args_kwds(self, args=None, kwds=None):
423
"""
424
Converts all of the args and kwds to be elements of this
425
interface.
426
427
EXAMPLES::
428
429
sage: args = [5]
430
sage: kwds = {'x': 6}
431
sage: args, kwds = gap._convert_args_kwds(args, kwds)
432
sage: args
433
[5]
434
sage: map(type, args)
435
[<class 'sage.interfaces.gap.GapElement'>]
436
sage: type(kwds['x'])
437
<class 'sage.interfaces.gap.GapElement'>
438
"""
439
args = [] if args is None else args
440
kwds = {} if kwds is None else kwds
441
if not isinstance(args, list):
442
args = [args]
443
for i, arg in enumerate(args):
444
if not isinstance(arg, InterfaceElement) or arg.parent() is not self:
445
args[i] = self(arg)
446
for key, value in kwds.iteritems():
447
if not isinstance(value, InterfaceElement) or value.parent() is not self:
448
kwds[key] = self(value)
449
450
return args, kwds
451
452
def _check_valid_function_name(self, function):
453
"""
454
Checks to see if function is a valid function name in this
455
interface. If it is not, an exception is raised. Otherwise, nothing
456
is done.
457
458
EXAMPLES::
459
460
sage: gap._check_valid_function_name('SymmetricGroup')
461
sage: gap._check_valid_function_name('')
462
Traceback (most recent call last):
463
...
464
ValueError: function name must be nonempty
465
sage: gap._check_valid_function_name('__foo')
466
Traceback (most recent call last):
467
...
468
AttributeError
469
"""
470
if function == '':
471
raise ValueError, "function name must be nonempty"
472
if function[:2] == "__":
473
raise AttributeError
474
475
def function_call(self, function, args=None, kwds=None):
476
"""
477
EXAMPLES::
478
479
sage: maxima.quad_qags(x, x, 0, 1, epsrel=1e-4)
480
[0.5,5.5511151231257...e-15,21,0]
481
sage: maxima.function_call('quad_qags', [x, x, 0, 1], {'epsrel':'1e-4'})
482
[0.5,5.5511151231257...e-15,21,0]
483
"""
484
args, kwds = self._convert_args_kwds(args, kwds)
485
self._check_valid_function_name(function)
486
s = self._function_call_string(function,
487
[s.name() for s in args],
488
['%s=%s'%(key,value.name()) for key, value in kwds.items()])
489
return self.new(s)
490
491
def _function_call_string(self, function, args, kwds):
492
"""
493
Returns the string used to make function calls.
494
495
EXAMPLES::
496
497
sage: maxima._function_call_string('diff', ['f(x)', 'x'], [])
498
'diff(f(x),x)'
499
"""
500
return "%s(%s)"%(function, ",".join(list(args) + list(kwds)))
501
502
def call(self, function_name, *args, **kwds):
503
return self.function_call(function_name, args, kwds)
504
505
def _contains(self, v1, v2):
506
raise NotImplementedError
507
508
def __getattr__(self, attrname):
509
"""
510
TESTS::
511
512
sage: ParentWithBase.__getattribute__(singular, '_coerce_map_from_')
513
<built-in method _coerce_map_from_ of Singular object at ...>
514
"""
515
try:
516
return ParentWithBase.__getattribute__(self, attrname)
517
except AttributeError:
518
if attrname[:1] == "_":
519
raise
520
return self._function_class()(self, attrname)
521
522
def __cmp__(self, other):
523
"""
524
Compare two pseudo-tty interfaces. Two interfaces compare
525
equal if and only if they are identical objects (this is a
526
critical constraint so that caching of representations of
527
objects in interfaces works correctly). Otherwise they are
528
never equal.
529
530
EXAMPLES::
531
532
sage: Maxima() == maxima
533
False
534
sage: maxima == maxima
535
True
536
"""
537
if self is other:
538
return 0
539
c = cmp(type(self), type(other))
540
if c:
541
return c
542
return -1 # sucky, but I can't think of anything better; it is important that different interfaces to the same system still compare differently; unfortunately there is nothing to distinguish them.
543
544
def console(self):
545
raise NotImplementedError
546
547
def help(self, s):
548
return AsciiArtString('No help on %s available'%s)
549
550
551
class InterfaceFunction(SageObject):
552
"""
553
Interface function.
554
"""
555
def __init__(self, parent, name):
556
self._parent = parent
557
self._name = name
558
559
def __repr__(self):
560
return "%s"%self._name
561
562
def __call__(self, *args, **kwds):
563
return self._parent.function_call(self._name, list(args), kwds)
564
565
def _sage_doc_(self):
566
"""
567
EXAMPLES::
568
569
sage: gp.gcd._sage_doc_()
570
'gcd(x,{y}): greatest common divisor of x and y.'
571
"""
572
M = self._parent
573
return M.help(self._name)
574
575
576
class InterfaceFunctionElement(SageObject):
577
"""
578
Interface function element.
579
"""
580
def __init__(self, obj, name):
581
self._obj = obj
582
self._name = name
583
584
def __repr__(self):
585
return "%s"%self._name
586
587
def __call__(self, *args, **kwds):
588
return self._obj.parent().function_call(self._name, [self._obj] + list(args), kwds)
589
590
def help(self):
591
print self._sage_doc_()
592
593
def _sage_doc_(self):
594
"""
595
EXAMPLES::
596
597
sage: gp(2).gcd._sage_doc_()
598
'gcd(x,{y}): greatest common divisor of x and y.'
599
"""
600
M = self._obj.parent()
601
return M.help(self._name)
602
603
604
605
def is_InterfaceElement(x):
606
return isinstance(x, InterfaceElement)
607
608
class InterfaceElement(RingElement):
609
"""
610
Interface element.
611
"""
612
def __init__(self, parent, value, is_name=False, name=None):
613
RingElement.__init__(self, parent)
614
self._create = value
615
if parent is None: return # means "invalid element"
616
# idea: Joe Wetherell -- try to find out if the output
617
# is too long and if so get it using file, otherwise
618
# don't.
619
620
if is_name:
621
self._name = value
622
else:
623
try:
624
self._name = parent._create(value, name=name)
625
except (TypeError, RuntimeError, ValueError), x:
626
raise TypeError, x
627
628
def _latex_(self):
629
# return "\\begin{verbatim}%s\\end{verbatim}"%self
630
string = str(self)
631
if not '|' in string:
632
delim = '|'
633
elif not '#' in string:
634
delim = '#'
635
elif not '@' in string:
636
delim = '@'
637
elif not '~' in string:
638
delim = '~'
639
return "\\verb%s%s%s"%(delim, string, delim)
640
641
def __iter__(self):
642
for i in range(1, len(self)+1):
643
yield self[i]
644
645
def __len__(self):
646
"""
647
Call self.sage() and return the length of that sage object.
648
649
This approach is inefficient - each interface should override
650
this method with one that calls the external program's length
651
function.
652
653
EXAMPLES::
654
655
sage: len(gp([1,2,3]))
656
3
657
658
AUTHORS:
659
660
- Felix Lawrence (2009-08-21)
661
"""
662
return len(self.sage())
663
664
def __reduce__(self):
665
return reduce_load, (self.parent(), self._reduce())
666
667
def _reduce(self):
668
return repr(self)
669
670
def __call__(self, *args):
671
self._check_valid()
672
P = self.parent()
673
return getattr(P, self.name())(*args)
674
675
def __contains__(self, x):
676
P = self._check_valid()
677
if not isinstance(x, InterfaceElement) or x.parent() is not self.parent():
678
x = P.new(x)
679
return P._contains(x.name(), self.name())
680
681
682
def _sage_doc_(self):
683
"""
684
EXAMPLES::
685
686
sage: gp(2)._sage_doc_()
687
'2'
688
"""
689
return str(self)
690
691
def __hash__(self):
692
"""
693
Returns the hash of self. This is a default implementation of hash
694
which just takes the hash of the string of self.
695
"""
696
return hash('%s'%(self))
697
698
def __cmp__(self, other):
699
"""
700
Comparison is done by GAP.
701
702
GAP may raise an error when comparing objects. We catch these
703
errors. Moreover, GAP does not recognise certain objects as
704
equal even if there definitions are identical.
705
706
TESTS:
707
708
Here are examples in which GAP succeeds with a comparison::
709
710
sage: gap('SymmetricGroup(8)')==gap('SymmetricGroup(8)')
711
True
712
sage: gap('SymmetricGroup(8)')>gap('AlternatingGroup(8)')
713
False
714
sage: gap('SymmetricGroup(8)')<gap('AlternatingGroup(8)')
715
True
716
717
Here, GAP fails to compare, and so ``False`` is returned.
718
In previous Sage versions, this example actually resulted
719
in an error; compare #5962.
720
::
721
722
sage: gap('DihedralGroup(8)')==gap('DihedralGroup(8)')
723
False
724
725
"""
726
P = self.parent()
727
try:
728
if P.eval("%s %s %s"%(self.name(), P._equality_symbol(),
729
other.name())) == P._true_symbol():
730
return 0
731
except RuntimeError:
732
pass
733
try:
734
if P.eval("%s %s %s"%(self.name(), P._lessthan_symbol(), other.name())) == P._true_symbol():
735
return -1
736
except RuntimeError:
737
pass
738
try:
739
if P.eval("%s %s %s"%(self.name(), P._greaterthan_symbol(), other.name())) == P._true_symbol():
740
return 1
741
except Exception:
742
pass
743
744
# everything is supposed to be comparable in Python, so we define
745
# the comparison thus when no comparison is available in interfaced system.
746
if (hash(self) < hash(other)):
747
return -1
748
else:
749
return 1
750
751
def _matrix_(self, R):
752
raise NotImplementedError
753
754
def _vector_(self, R):
755
raise NotImplementedError
756
757
def _check_valid(self):
758
"""
759
Check that this object is valid, i.e., the session in which this
760
object is defined is still running. This is relevant for
761
interpreters that can't be interrupted via ctrl-C, hence get
762
restarted.
763
"""
764
try:
765
P = self.parent()
766
if P is None:
767
raise ValueError, "The %s session in which this object was defined is no longer running."%P.name()
768
except AttributeError:
769
raise ValueError, "The session in which this object was defined is no longer running."
770
return P
771
772
def __del__(self):
773
try:
774
self._check_valid()
775
except ValueError:
776
return
777
if hasattr(self,'_name'):
778
P = self.parent()
779
if not (P is None):
780
P.clear(self._name)
781
782
def _sage_repr(self):
783
"""
784
Return a sage-friendly string representation of the object.
785
786
Some programs use different notation to Sage, e.g. Mathematica
787
writes lists with {} instead of []. This method calls repr(self)
788
then converts the foreign notation into Sage's notation.
789
790
OUTPUT:
791
792
A string representation of the object that is ready for
793
sage_eval().
794
795
EXAMPLES::
796
797
sage: repr(mathematica([1,2,3])) # optional - mathematica
798
'{1, 2, 3}'
799
sage: mathematica([1,2,3])._sage_repr() # optional - mathematica
800
'[1, 2, 3]'
801
802
::
803
804
sage: gp(10.^80)._sage_repr()
805
'1.0000000000000000000000000000000000000e80' # 64-bit
806
'1.000000000000000000000000000e80' # 32-bit
807
sage: mathematica('10.^80')._sage_repr() # optional - mathematica
808
'1.e80'
809
810
AUTHORS:
811
812
- Felix Lawrence (2009-08-21)
813
"""
814
#TO DO: this could use file transfers when self.is_remote()
815
816
string = repr(self).replace('\n',' ').replace('\r', '')
817
# Translate the external program's function notation to Sage's
818
lfd = self.parent()._left_func_delim()
819
if '(' != lfd: string = string.replace(lfd, '(')
820
rfd = self.parent()._right_func_delim()
821
if ')' != rfd: string = string.replace(rfd, ')')
822
# Translate the external program's list formatting to Sage's
823
lld = self.parent()._left_list_delim()
824
if '[' != lld: string = string.replace(lld, '[')
825
rld = self.parent()._right_list_delim()
826
if ']' != rld: string = string.replace(rld, ']')
827
# Translate the external program's exponent formatting
828
expl = self.parent()._exponent_symbol()
829
if 'e' != expl: string = string.replace(expl, 'e')
830
return string
831
832
def _sage_(self):
833
"""
834
Attempt to return a Sage version of this object.
835
This is a generic routine that just tries to evaluate
836
the repr(self).
837
838
EXAMPLES::
839
840
sage: gp(1/2)._sage_()
841
1/2
842
sage: _.parent()
843
Rational Field
844
845
AUTHORS:
846
847
- William Stein
848
849
- Felix Lawrence (2009-08-21)
850
"""
851
string = self._sage_repr()
852
try:
853
return sage.misc.sage_eval.sage_eval(string)
854
except Exception:
855
raise NotImplementedError, "Unable to parse output: %s" % string
856
857
858
def sage(self):
859
"""
860
Attempt to return a Sage version of this object.
861
862
EXAMPLES::
863
864
sage: gp(1/2).sage()
865
1/2
866
sage: _.parent()
867
Rational Field
868
"""
869
return self._sage_()
870
871
def __repr__(self):
872
self._check_valid()
873
try:
874
if self._get_using_file:
875
s = self.parent().get_using_file(self._name)
876
except AttributeError:
877
s = self.parent().get(self._name)
878
if s.__contains__(self._name):
879
if hasattr(self, '__custom_name'):
880
s = s.replace(self._name, self.__dict__['__custom_name'])
881
return s
882
883
def __getattr__(self, attrname):
884
P = self._check_valid()
885
if attrname[:1] == "_":
886
raise AttributeError
887
return P._function_element_class()(self, attrname)
888
889
def get_using_file(self):
890
"""
891
Return this element's string representation using a file. Use this
892
if self has a huge string representation. It'll be way faster.
893
894
EXAMPLES::
895
896
sage: a = maxima(str(2^1000))
897
sage: a.get_using_file()
898
'10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376'
899
"""
900
try:
901
self._check_valid()
902
except ValueError:
903
return '(invalid object -- defined in terms of closed session)'
904
return self.parent().get_using_file(self._name)
905
906
def hasattr(self, attrname):
907
"""
908
Returns whether the given attribute is already defined by this
909
object, and in particular is not dynamically generated.
910
911
EXAMPLES::
912
913
sage: m = maxima('2')
914
sage: m.hasattr('integral')
915
True
916
sage: m.hasattr('gcd')
917
False
918
"""
919
return not isinstance(getattr(self, attrname), InterfaceFunctionElement)
920
921
def attribute(self, attrname):
922
"""
923
If this wraps the object x in the system, this returns the object
924
x.attrname. This is useful for some systems that have object
925
oriented attribute access notation.
926
927
EXAMPLES::
928
929
sage: g = gap('SO(1,4,7)')
930
sage: k = g.InvariantQuadraticForm()
931
sage: k.attribute('matrix')
932
[ [ 0*Z(7), Z(7)^0, 0*Z(7), 0*Z(7) ], [ 0*Z(7), 0*Z(7), 0*Z(7), 0*Z(7) ],
933
[ 0*Z(7), 0*Z(7), Z(7), 0*Z(7) ], [ 0*Z(7), 0*Z(7), 0*Z(7), Z(7)^0 ] ]
934
935
::
936
937
sage: e = gp('ellinit([0,-1,1,-10,-20])')
938
sage: e.attribute('j')
939
-122023936/161051
940
"""
941
P = self._check_valid()
942
return P('%s.%s'%(self.name(), attrname))
943
944
def __getitem__(self, n):
945
P = self._check_valid()
946
if not isinstance(n, tuple):
947
return P.new('%s[%s]'%(self._name, n))
948
else:
949
return P.new('%s[%s]'%(self._name, str(n)[1:-1]))
950
951
def __int__(self):
952
"""
953
EXAMPLES::
954
955
sage: int(maxima('1'))
956
1
957
sage: type(_)
958
<type 'int'>
959
"""
960
return int(repr(self))
961
962
def bool(self):
963
P = self.parent()
964
t = P._true_symbol()
965
cmd = '%s %s %s'%(self._name, P._equality_symbol(), t)
966
return P.eval(cmd) == t
967
968
def __nonzero__(self):
969
"""
970
EXAMPLES::
971
972
sage: bool(maxima(0))
973
False
974
sage: bool(maxima(1))
975
True
976
"""
977
return self.bool()
978
979
def __long__(self):
980
"""
981
EXAMPLES::
982
983
sage: m = maxima('1')
984
sage: long(m)
985
1L
986
"""
987
return long(repr(self))
988
989
def __float__(self):
990
"""
991
EXAMPLES::
992
993
sage: m = maxima('1/2')
994
sage: m.__float__()
995
0.5
996
sage: float(m)
997
0.5
998
"""
999
return float(repr(self))
1000
1001
def _integer_(self, ZZ=None):
1002
"""
1003
EXAMPLES::
1004
1005
sage: m = maxima('1')
1006
sage: m._integer_()
1007
1
1008
sage: _.parent()
1009
Integer Ring
1010
sage: QQ(m)
1011
1
1012
"""
1013
import sage.rings.all
1014
return sage.rings.all.Integer(repr(self))
1015
1016
def _rational_(self):
1017
"""
1018
EXAMPLES::
1019
1020
sage: m = maxima('1/2')
1021
sage: m._rational_()
1022
1/2
1023
sage: _.parent()
1024
Rational Field
1025
sage: QQ(m)
1026
1/2
1027
"""
1028
import sage.rings.all
1029
return sage.rings.all.Rational(repr(self))
1030
1031
def name(self, new_name=None):
1032
"""
1033
Returns the name of self. If new_name is passed in, then this
1034
function returns a new object identical to self whose name is
1035
new_name.
1036
1037
Note that this can overwrite existing variables in the system.
1038
1039
EXAMPLES::
1040
1041
sage: x = r([1,2,3]); x
1042
[1] 1 2 3
1043
sage: x.name()
1044
'sage3'
1045
sage: x = r([1,2,3]).name('x'); x
1046
[1] 1 2 3
1047
sage: x.name()
1048
'x'
1049
1050
::
1051
1052
sage: s5 = gap.SymmetricGroup(5).name('s5')
1053
sage: s5
1054
SymmetricGroup( [ 1 .. 5 ] )
1055
sage: s5.name()
1056
's5'
1057
"""
1058
if new_name is not None:
1059
if not isinstance(new_name, str):
1060
raise TypeError, "new_name must be a string"
1061
p = self.parent()
1062
p.set(new_name, self._name)
1063
return p._object_class()(p, new_name, is_name=True)
1064
1065
return self._name
1066
1067
def gen(self, n):
1068
P = self._check_valid()
1069
return P.new('%s.%s'%(self._name, int(n)))
1070
1071
def _operation(self, operation, right):
1072
P = self._check_valid()
1073
try:
1074
return P.new('%s %s %s'%(self._name, operation, right._name))
1075
except Exception, msg:
1076
raise TypeError, msg
1077
1078
def _add_(self, right):
1079
"""
1080
EXAMPLES::
1081
1082
sage: f = maxima.cos(x)
1083
sage: g = maxima.sin(x)
1084
sage: f + g
1085
sin(x)+cos(x)
1086
sage: f + 2
1087
cos(x)+2
1088
sage: 2 + f
1089
cos(x)+2
1090
"""
1091
return self._operation("+", right)
1092
1093
def _sub_(self, right):
1094
"""
1095
EXAMPLES::
1096
1097
sage: f = maxima.cos(x)
1098
sage: g = maxima.sin(x)
1099
sage: f - g
1100
cos(x)-sin(x)
1101
sage: f - 2
1102
cos(x)-2
1103
sage: 2 - f
1104
2-cos(x)
1105
"""
1106
return self._operation('-', right)
1107
1108
def _mul_(self, right):
1109
"""
1110
EXAMPLES::
1111
1112
sage: f = maxima.cos(x)
1113
sage: g = maxima.sin(x)
1114
sage: f*g
1115
cos(x)*sin(x)
1116
sage: 2*f
1117
2*cos(x)
1118
"""
1119
return self._operation('*', right)
1120
1121
def _div_(self, right):
1122
"""
1123
EXAMPLES::
1124
1125
sage: f = maxima.cos(x)
1126
sage: g = maxima.sin(x)
1127
sage: f/g
1128
cos(x)/sin(x)
1129
sage: f/2
1130
cos(x)/2
1131
"""
1132
return self._operation("/", right)
1133
1134
def __pow__(self, n):
1135
"""
1136
EXAMPLES::
1137
1138
sage: a = maxima('2')
1139
sage: a^(3/4)
1140
2^(3/4)
1141
"""
1142
P = self._check_valid()
1143
if not hasattr(n, 'parent') or P is not n.parent():
1144
n = P(n)
1145
return self._operation("^", n)
1146
1147
def reduce_load(parent, x):
1148
return parent(x)
1149
1150