Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/symbolic/getitem.pyx
4097 views
1
###############################################################################
2
# Sage: Open Source Mathematical Software
3
# Copyright (C) 2011 Burcin Erocal <[email protected]>
4
# Distributed under the terms of the GNU General Public License (GPL),
5
# version 2 or any later version. The full text of the GPL is available at:
6
# http://www.gnu.org/licenses/
7
###############################################################################
8
from sage.libs.ginac cimport GEx, GEx_construct_ex
9
from sage.symbolic.expression cimport new_Expression_from_GEx
10
11
cdef inline int normalize_index(object arg, int nops, object err_msg) except -1:
12
"""
13
Given an index ``arg`` and the number of operands ``nops`` return
14
an integer between 0 and ``nops`` which will be used as the index to fetch
15
the data from the underlying vector.
16
17
TESTS::
18
19
sage: from sage.symbolic.getitem import normalize_index_for_doctests as normalize_index
20
sage: normalize_index(-1, 4)
21
3
22
sage: normalize_index(1, 4)
23
1
24
sage: normalize_index(1.5, 4)
25
Traceback (most recent call last):
26
...
27
TypeError: some error message
28
sage: normalize_index(-5, 4)
29
Traceback (most recent call last):
30
...
31
IndexError: operand index out of range, got -5, expect between -4 and 3
32
sage: normalize_index(5, 4)
33
Traceback (most recent call last):
34
...
35
IndexError: operand index out of range, got 5, expect between -4 and 3
36
"""
37
cdef int i
38
i = arg
39
if i != arg:
40
raise TypeError(err_msg)
41
if i < 0:
42
i = nops + i
43
if i >= nops or i < 0:
44
raise IndexError("operand index out of range, got %s, expect between %s and %s"%(arg,-nops,nops-1))
45
return i
46
47
def normalize_index_for_doctests(arg, nops):
48
"""
49
Wrapper function to test ``normalize_index``.
50
51
TESTS::
52
53
sage: from sage.symbolic.getitem import normalize_index_for_doctests
54
sage: normalize_index_for_doctests(-1, 4)
55
3
56
"""
57
return normalize_index(arg, nops, "some error message")
58
59
cdef class OperandsWrapper(SageObject):
60
"""
61
Operands wrapper for symbolic expressions.
62
63
EXAMPLES::
64
65
sage: x,y,z = var('x,y,z')
66
sage: e = x + x*y + z^y + 3*y*z; e
67
x*y + 3*y*z + z^y + x
68
sage: e.op[1]
69
3*y*z
70
sage: e.op[1,1]
71
z
72
sage: e.op[-1]
73
x
74
sage: e.op[1:]
75
[3*y*z, z^y, x]
76
sage: e.op[:2]
77
[x*y, 3*y*z]
78
sage: e.op[-2:]
79
[z^y, x]
80
sage: e.op[:-2]
81
[x*y, 3*y*z]
82
sage: e.op[-5]
83
Traceback (most recent call last):
84
...
85
IndexError: operand index out of range, got -5, expect between -4 and 3
86
sage: e.op[5]
87
Traceback (most recent call last):
88
...
89
IndexError: operand index out of range, got 5, expect between -4 and 3
90
sage: e.op[1,1,0]
91
Traceback (most recent call last):
92
...
93
TypeError: expressions containing only a numeric coefficient, constant or symbol have no operands
94
sage: e.op[:1.5]
95
Traceback (most recent call last):
96
...
97
TypeError: slice indices must be integers or None or have an __index__ method
98
sage: e.op[:2:1.5]
99
Traceback (most recent call last):
100
...
101
ValueError: step value must be an integer
102
"""
103
def __getitem__(self, arg):
104
"""
105
TESTS::
106
107
sage: t = 1+x+x^2
108
sage: t.op[1:]
109
[x, 1]
110
"""
111
cdef int ind, nops
112
cdef int bind, eind, step
113
cdef GEx cur_ex
114
if isinstance(arg, slice):
115
nops = self._expr._gobj.nops()
116
117
slice_err_msg = "slice indices must be integers or None or have an __index__ method"
118
if arg.start:
119
bind = normalize_index(arg.start, nops, slice_err_msg)
120
else:
121
bind = 0
122
if arg.stop:
123
eind = normalize_index(arg.stop, nops, slice_err_msg)
124
else:
125
eind = nops
126
if arg.step:
127
step = arg.step
128
if step != arg.step:
129
raise ValueError, "step value must be an integer"
130
else:
131
step = 1
132
return [new_Expression_from_GEx(self._expr._parent,
133
self._expr._gobj.op(ind)) for ind in xrange(bind, eind, step)]
134
135
136
ind_err_msg = "index should either be a slice object, an integer or a list of integers"
137
if isinstance(arg, (list, tuple)):
138
# handle nested index
139
if len(arg) == 0: # or not all(lambda x: x in ZZ for t in args):
140
raise TypeError, ind_err_msg
141
GEx_construct_ex(&cur_ex, self._expr._gobj)
142
for x in arg:
143
nops = cur_ex.nops()
144
if nops == 0:
145
raise TypeError, "expressions containing only a numeric coefficient, constant or symbol have no operands"
146
ind = normalize_index(x, nops, ind_err_msg)
147
cur_ex = cur_ex.op(ind)
148
return new_Expression_from_GEx(self._expr._parent, cur_ex)
149
150
ind = normalize_index(arg, self._expr._gobj.nops(), ind_err_msg)
151
return new_Expression_from_GEx(self._expr._parent,
152
self._expr._gobj.op(ind))
153
154
def _repr_(self):
155
"""
156
TESTS::
157
158
sage: (x^2).op
159
Operands of x^2
160
"""
161
return "Operands of %s"%(self._expr)
162
163
def _latex_(self):
164
r"""
165
TESTS::
166
167
sage: latex((x^2).op)
168
\text{Operands wrapper for expression }x^{2}
169
"""
170
return r"\text{Operands wrapper for expression }%s"%(self._expr._latex_())
171
172
def __reduce__(self):
173
"""
174
TESTS::
175
176
sage: (x^2).op.__reduce__()
177
(<built-in function restore_op_wrapper>, (x^2,))
178
sage: loads(dumps((x^2).op))
179
Operands of x^2
180
"""
181
return restore_op_wrapper, (self._expr,)
182
183
def restore_op_wrapper(expr):
184
"""
185
TESTS::
186
187
sage: from sage.symbolic.getitem import restore_op_wrapper
188
sage: restore_op_wrapper(x^2)
189
Operands of x^2
190
"""
191
return expr.op
192
193