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