Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/structure/coerce.pyx
4057 views
1
r"""
2
The Coercion Model
3
4
The coercion model manages how elements of one parent get related to elements
5
of another. For example, the integer 2 can canonically be viewed as an element
6
of the rational numbers. (The Parent of a non-element is its Python type.)
7
8
::
9
10
sage: ZZ(2).parent()
11
Integer Ring
12
sage: QQ(2).parent()
13
Rational Field
14
15
The most prominent role of the coercion model is to make sense of binary
16
operations between elements that have distinct parents. It does this by
17
finding a parent where both elements make sense, and doing the operation
18
there. For example::
19
20
sage: a = 1/2; a.parent()
21
Rational Field
22
sage: b = ZZ[x].gen(); b.parent()
23
Univariate Polynomial Ring in x over Integer Ring
24
sage: a+b
25
x + 1/2
26
sage: (a+b).parent()
27
Univariate Polynomial Ring in x over Rational Field
28
29
If there is a coercion (see below) from one of the parents to the other,
30
the operation is always performed in the codomain of that coercion. Otherwise
31
a reasonable attempt to create a new parent with coercion maps from both
32
original parents is made. The results of these discoveries are cached.
33
On failure, a TypeError is always raised.
34
35
Some arithmetic operations (such as multiplication) can indicate an action
36
rather than arithmetic in a common parent. For example::
37
38
sage: E = EllipticCurve('37a')
39
sage: P = E(0,0)
40
sage: 5*P
41
(1/4 : -5/8 : 1)
42
43
where there is action of `\ZZ` on the points of `E` given by the additive
44
group law. Parents can specify how they act on or are acted upon by other
45
parents.
46
47
There are two kinds of ways to get from one parent to another, coercions and
48
conversions.
49
50
Coercions are canonical (possibly modulo a finite number of
51
deterministic choices) morphisms, and the set of all coercions between
52
all parents forms a commuting diagram (modulo possibly rounding
53
issues). `\ZZ \rightarrow \QQ` is an example of a
54
coercion. These are invoked implicitly by the coercion model.
55
56
Conversions try to construct an element out of their input if at all possible.
57
Examples include sections of coercions, creating an element from a string or
58
list, etc. and may fail on some inputs of a given type while succeeding on
59
others (i.e. they may not be defined on the whole domain). Conversions are
60
always explicitly invoked, and never used by the coercion model to resolve
61
binary operations.
62
63
For more information on how to specify coercions, conversions, and actions,
64
see the documentation for Parent.
65
"""
66
67
68
#*****************************************************************************
69
# Copyright (C) 2007 Robert Bradshaw <[email protected]>
70
#
71
# Distributed under the terms of the GNU General Public License (GPL)
72
#
73
# http://www.gnu.org/licenses/
74
#*****************************************************************************
75
76
77
include "../ext/stdsage.pxi"
78
include "../ext/python_object.pxi"
79
include "coerce.pxi"
80
81
import operator
82
83
from sage_object cimport SageObject
84
from sage.categories.map cimport Map
85
import sage.categories.morphism
86
from sage.categories.morphism import IdentityMorphism
87
from sage.categories.action import InverseAction, PrecomposedAction
88
from parent import Set_PythonType
89
from coerce_exceptions import CoercionException
90
91
import sys, traceback
92
93
from coerce_actions import LeftModuleAction, RightModuleAction, IntegerMulAction
94
95
cpdef py_scalar_parent(py_type):
96
"""
97
Returns the Sage equivalent of the given python type, if one exists.
98
If there is no equivalent, return None.
99
100
EXAMPLES::
101
102
sage: from sage.structure.coerce import py_scalar_parent
103
sage: py_scalar_parent(int)
104
Integer Ring
105
sage: py_scalar_parent(long)
106
Integer Ring
107
sage: py_scalar_parent(float)
108
Real Double Field
109
sage: py_scalar_parent(complex)
110
Complex Double Field
111
sage: py_scalar_parent(dict),
112
(None,)
113
"""
114
if py_type is int or py_type is long:
115
import sage.rings.integer_ring
116
return sage.rings.integer_ring.ZZ
117
elif py_type is float:
118
import sage.rings.real_double
119
return sage.rings.real_double.RDF
120
elif py_type is complex:
121
import sage.rings.complex_double
122
return sage.rings.complex_double.CDF
123
else:
124
return None
125
126
cdef object _native_coercion_ranks_inv = (bool, int, long, float, complex)
127
cdef object _native_coercion_ranks = dict([(t, k) for k, t in enumerate(_native_coercion_ranks_inv)])
128
129
cdef object _Integer
130
cdef bint is_Integer(x):
131
global _Integer
132
if _Integer is None:
133
from sage.rings.integer import Integer as _Integer
134
return PY_TYPE_CHECK_EXACT(x, _Integer) or PY_TYPE_CHECK_EXACT(x, int)
135
136
cdef class CoercionModel_cache_maps(CoercionModel):
137
"""
138
See also sage.categories.pushout
139
140
EXAMPLES::
141
142
sage: f = ZZ['t','x'].0 + QQ['x'].0 + CyclotomicField(13).gen(); f
143
t + x + (zeta13)
144
sage: f.parent()
145
Multivariate Polynomial Ring in t, x over Cyclotomic Field of order 13 and degree 12
146
sage: ZZ['x','y'].0 + ~Frac(QQ['y']).0
147
(x*y + 1)/y
148
sage: MatrixSpace(ZZ['x'], 2, 2)(2) + ~Frac(QQ['x']).0
149
[(2*x + 1)/x 0]
150
[ 0 (2*x + 1)/x]
151
sage: f = ZZ['x,y,z'].0 + QQ['w,x,z,a'].0; f
152
w + x
153
sage: f.parent()
154
Multivariate Polynomial Ring in w, x, y, z, a over Rational Field
155
sage: ZZ['x,y,z'].0 + ZZ['w,x,z,a'].1
156
2*x
157
158
AUTHOR:
159
160
- Robert Bradshaw
161
"""
162
163
def __init__(self, lookup_dict_size=127, lookup_dict_threshold=.75):
164
"""
165
INPUT:
166
167
- ``lookup_dict_size`` - initial size of the coercion hashtables
168
169
- ``lookup_dict_threshold`` - maximal density of the coercion
170
hashtables before forcing a re-hash
171
172
EXAMPLES::
173
174
sage: from sage.structure.coerce import CoercionModel_cache_maps
175
sage: cm = CoercionModel_cache_maps(4, .95)
176
sage: A = cm.get_action(ZZ, NumberField(x^2-2, 'a'), operator.mul)
177
sage: f, g = cm.coercion_maps(QQ, int)
178
sage: f, g = cm.coercion_maps(ZZ, int)
179
sage: cm.get_stats()
180
((0, 1.0, 4), (0, 0.25, 1))
181
182
.. note::
183
184
In practice 4 would be a really bad number to choose, but
185
it makes the hashing deterministic.
186
"""
187
self.reset_cache(lookup_dict_size, lookup_dict_threshold)
188
189
def reset_cache(self, lookup_dict_size=127, lookup_dict_threshold=.75):
190
"""
191
Clear the coercion cache.
192
193
This should have no impact on the result of arithmetic operations, as
194
the exact same coercions and actions will be re-discovered when needed.
195
196
It may be useful for debugging, and may also free some memory.
197
198
EXAMPLES::
199
200
sage: cm = sage.structure.element.get_coercion_model()
201
sage: cm.get_stats() # random
202
((0, 0.3307086614173229, 3), (0, 0.1496062992125984, 2))
203
sage: cm.reset_cache()
204
sage: cm.get_stats()
205
((0, 0.0, 0), (0, 0.0, 0))
206
"""
207
# This MUST be a mapping of tuples, where each
208
# tuple contains at least two elements that are either
209
# None or of type Map.
210
self._coercion_maps = TripleDict(lookup_dict_size, threshold=lookup_dict_threshold)
211
# This MUST be a mapping to actions.
212
self._action_maps = TripleDict(lookup_dict_size, threshold=lookup_dict_threshold)
213
# This is a mapping from Parents to Parents, storing the result of division in the given parent.
214
self._division_parents = TripleDict(lookup_dict_size, threshold=lookup_dict_threshold)
215
216
def get_cache(self):
217
"""
218
This returns the current cache of coercion maps and actions, primarily
219
useful for debugging and introspection.
220
221
EXAMPLES::
222
223
sage: 1 + 1/2
224
3/2
225
sage: cm = sage.structure.element.get_coercion_model()
226
sage: maps, actions = cm.get_cache()
227
228
Now lets see what happens when we do a binary operations with
229
an integer and a rational::
230
231
sage: left_morphism, right_morphism = maps[ZZ, QQ]
232
sage: print left_morphism
233
Natural morphism:
234
From: Integer Ring
235
To: Rational Field
236
sage: print right_morphism
237
None
238
239
We can see that it coerces the left operand from an integer to a
240
rational, and doesn't do anything to the right.
241
242
Now for some actions::
243
244
sage: R.<x> = ZZ['x']
245
sage: 1/2 * x
246
1/2*x
247
sage: maps, actions = cm.get_cache()
248
sage: act = actions[QQ, R, operator.mul]; act
249
Left scalar multiplication by Rational Field on Univariate Polynomial Ring in x over Integer Ring
250
sage: act.actor()
251
Rational Field
252
sage: act.domain()
253
Univariate Polynomial Ring in x over Integer Ring
254
sage: act.codomain()
255
Univariate Polynomial Ring in x over Rational Field
256
sage: act(1/5, x+10)
257
1/5*x + 2
258
"""
259
return dict([((S, R), mors) for (S, R, op), mors in self._coercion_maps.iteritems()]), \
260
dict(self._action_maps.iteritems())
261
262
def get_stats(self):
263
"""
264
This returns the state of the cache of coercion maps and actions,
265
primarily useful for debugging and introspection.
266
If a class is not part of the coercion system, we should call the
267
__rmul__ method when it makes sense.
268
269
The coercion maps are stored in a specialized TripleDict hashtable,
270
and the stats returned are (min, avg, max) of the number of items
271
per bucket. The lower the better.
272
273
EXAMPLES::
274
275
sage: cm = sage.structure.element.get_coercion_model()
276
sage: cm.get_stats() # random
277
((0, 0.16058394160583941, 2), (0, 0.13138686131386862, 3))
278
"""
279
return self._coercion_maps.stats(), self._action_maps.stats()
280
281
def record_exceptions(self, bint value=True):
282
r"""
283
Enables (or disables) recording of the exceptions suppressed during
284
arithmetic.
285
286
Each time that record_exceptions is called (either enabling or disabling
287
the record), the exception_stack is cleared.
288
289
TESTS::
290
291
sage: cm = sage.structure.element.get_coercion_model()
292
sage: cm.record_exceptions()
293
sage: cm._test_exception_stack()
294
sage: cm.exception_stack()
295
['Traceback (most recent call last):\n File "coerce.pyx", line ...TypeError: just a test']
296
sage: cm.record_exceptions(False)
297
sage: cm._test_exception_stack()
298
sage: cm.exception_stack()
299
[]
300
"""
301
self._record_exceptions = value
302
self._exceptions_cleared = True
303
self._exception_stack = []
304
305
cpdef _record_exception(self):
306
r"""
307
Pushes the last exception that occurred onto the stack for later reference,
308
for internal use.
309
310
If the stack has not yet been flagged as cleared, we clear it now (rather
311
than wasting time to do so for successful operations).
312
313
TEST::
314
315
sage: cm = sage.structure.element.get_coercion_model()
316
sage: cm.record_exceptions()
317
sage: 1+1/2+2 # make sure there aren't any errors hanging around
318
7/2
319
sage: cm.exception_stack()
320
[]
321
sage: cm._test_exception_stack()
322
sage: cm.exception_stack()
323
['Traceback (most recent call last):\n File "coerce.pyx", line ...TypeError: just a test']
324
325
The function _test_exception_stack is executing the following code::
326
327
try:
328
raise TypeError, "just a test"
329
except:
330
cm._record_exception()
331
"""
332
if not self._record_exceptions:
333
return
334
if not self._exceptions_cleared:
335
self._exception_stack = []
336
self._exceptions_cleared = True
337
self._exception_stack.append(traceback.format_exc().strip())
338
339
def _test_exception_stack(self):
340
r"""
341
A function to test the exception stack.
342
343
EXAMPLES::
344
345
sage: cm = sage.structure.element.get_coercion_model()
346
sage: cm.record_exceptions()
347
sage: 1 + 1/11 # make sure there aren't any errors hanging around
348
12/11
349
sage: cm.exception_stack()
350
[]
351
sage: cm._test_exception_stack()
352
sage: cm.exception_stack()
353
['Traceback (most recent call last):\n File "coerce.pyx", line ...TypeError: just a test']
354
"""
355
try:
356
raise TypeError, "just a test"
357
except:
358
self._record_exception()
359
360
def exception_stack(self):
361
r"""
362
Returns the list of exceptions that were caught in the course of
363
executing the last binary operation. Useful for diagnosis when
364
user-defined maps or actions raise exceptions that are caught in
365
the course of coercion detection.
366
367
If all went well, this should be the empty list. If things aren't
368
happening as you expect, this is a good place to check. See also
369
:func:`coercion_traceback`.
370
371
EXAMPLES::
372
373
sage: cm = sage.structure.element.get_coercion_model()
374
sage: cm.record_exceptions()
375
sage: 1/2 + 2
376
5/2
377
sage: cm.exception_stack()
378
[]
379
sage: 1/2 + GF(3)(2)
380
Traceback (most recent call last):
381
...
382
TypeError: unsupported operand parent(s) for '+': 'Rational Field' and 'Finite Field of size 3'
383
384
Now see what the actual problem was::
385
386
sage: import traceback
387
sage: cm.exception_stack()
388
['Traceback (most recent call last):...', 'Traceback (most recent call last):...']
389
sage: print cm.exception_stack()[-1]
390
Traceback (most recent call last):
391
...
392
TypeError: no common canonical parent for objects with parents: 'Rational Field' and 'Finite Field of size 3'
393
394
This is typically accessed via the :func:`coercion_traceback` function.
395
396
::
397
398
sage: coercion_traceback()
399
Traceback (most recent call last):
400
...
401
TypeError: no common canonical parent for objects with parents: 'Rational Field' and 'Finite Field of size 3'
402
"""
403
if not self._exceptions_cleared:
404
self._exception_stack = []
405
self._exceptions_cleared = True
406
return self._exception_stack
407
408
409
def explain(self, xp, yp, op=operator.mul, int verbosity=2):
410
"""
411
This function can be used to understand what coercions will happen
412
for an arithmetic operation between xp and yp (which may be either
413
elements or parents). If the parent of the result can be determined
414
then it will be returned.
415
416
EXAMPLES::
417
418
sage: cm = sage.structure.element.get_coercion_model()
419
420
sage: cm.explain(ZZ, ZZ)
421
Identical parents, arithmetic performed immediately.
422
Result lives in Integer Ring
423
Integer Ring
424
425
sage: cm.explain(QQ, int)
426
Coercion on right operand via
427
Native morphism:
428
From: Set of Python objects of type 'int'
429
To: Rational Field
430
Arithmetic performed after coercions.
431
Result lives in Rational Field
432
Rational Field
433
434
sage: cm.explain(ZZ['x'], QQ)
435
Action discovered.
436
Right scalar multiplication by Rational Field on Univariate Polynomial Ring in x over Integer Ring
437
Result lives in Univariate Polynomial Ring in x over Rational Field
438
Univariate Polynomial Ring in x over Rational Field
439
440
sage: cm.explain(ZZ['x'], QQ, operator.add)
441
Coercion on left operand via
442
Conversion map:
443
From: Univariate Polynomial Ring in x over Integer Ring
444
To: Univariate Polynomial Ring in x over Rational Field
445
Coercion on right operand via
446
Polynomial base injection morphism:
447
From: Rational Field
448
To: Univariate Polynomial Ring in x over Rational Field
449
Arithmetic performed after coercions.
450
Result lives in Univariate Polynomial Ring in x over Rational Field
451
Univariate Polynomial Ring in x over Rational Field
452
453
Sometimes with non-sage types there is not enough information to deduce
454
what will actually happen::
455
456
sage: cm.explain(RealField(100), float, operator.add)
457
Right operand is numeric, will attempt coercion in both directions.
458
Unknown result parent.
459
sage: parent(RealField(100)(1) + float(1))
460
<type 'float'>
461
sage: cm.explain(QQ, float, operator.add)
462
Right operand is numeric, will attempt coercion in both directions.
463
Unknown result parent.
464
sage: parent(QQ(1) + float(1))
465
<type 'float'>
466
467
468
Special care is taken to deal with division::
469
470
sage: cm.explain(ZZ, ZZ, operator.div)
471
Identical parents, arithmetic performed immediately.
472
Result lives in Rational Field
473
Rational Field
474
475
sage: cm.explain(ZZ['x'], QQ['x'], operator.div)
476
Coercion on left operand via
477
Conversion map:
478
From: Univariate Polynomial Ring in x over Integer Ring
479
To: Univariate Polynomial Ring in x over Rational Field
480
Arithmetic performed after coercions.
481
Result lives in Fraction Field of Univariate Polynomial Ring in x over Rational Field
482
Fraction Field of Univariate Polynomial Ring in x over Rational Field
483
484
sage: cm.explain(int, ZZ, operator.div)
485
Coercion on left operand via
486
Native morphism:
487
From: Set of Python objects of type 'int'
488
To: Integer Ring
489
Arithmetic performed after coercions.
490
Result lives in Rational Field
491
Rational Field
492
493
sage: cm.explain(ZZ['x'], ZZ, operator.div)
494
Action discovered.
495
Right inverse action by Rational Field on Univariate Polynomial Ring in x over Integer Ring
496
with precomposition on right by Natural morphism:
497
From: Integer Ring
498
To: Rational Field
499
Result lives in Univariate Polynomial Ring in x over Rational Field
500
Univariate Polynomial Ring in x over Rational Field
501
502
.. note::
503
504
This function is accurate only in so far as analyse is kept
505
in sync with the :meth:`bin_op` and
506
:meth:`canonical_coercion` which are kept separate for
507
maximal efficiency.
508
"""
509
all, res = self.analyse(xp, yp, op)
510
indent = " "*4
511
if verbosity >= 2:
512
print "\n".join([s if isinstance(s, str) else indent+(repr(s).replace("\n", "\n"+indent)) for s in all])
513
elif verbosity >= 1:
514
print "\n".join([s for s in all if isinstance(s, str)])
515
if verbosity >= 1:
516
if res is None:
517
print "Unknown result parent."
518
else:
519
print "Result lives in", res
520
return res
521
522
cpdef analyse(self, xp, yp, op=mul):
523
"""
524
Emulate the process of doing arithmetic between xp and yp, returning
525
a list of steps and the parent that the result will live in. The
526
``explain`` function is easier to use, but if one wants access to
527
the actual morphism and action objects (rather than their string
528
representations) then this is the function to use.
529
530
EXAMPLES::
531
532
sage: cm = sage.structure.element.get_coercion_model()
533
sage: steps, res = cm.analyse(GF(7), ZZ)
534
sage: print steps
535
['Coercion on right operand via', Natural morphism:
536
From: Integer Ring
537
To: Finite Field of size 7, 'Arithmetic performed after coercions.']
538
sage: print res
539
Finite Field of size 7
540
sage: f = steps[1]; type(f)
541
<type 'sage.rings.finite_rings.integer_mod.Integer_to_IntegerMod'>
542
sage: f(100)
543
2
544
"""
545
self._exceptions_cleared = False
546
res = None
547
if not PY_TYPE_CHECK(xp, type) and not PY_TYPE_CHECK(xp, Parent):
548
xp = parent_c(xp)
549
if not PY_TYPE_CHECK(yp, type) and not PY_TYPE_CHECK(yp, Parent):
550
yp = parent_c(yp)
551
552
all = []
553
if xp is yp:
554
all.append("Identical parents, arithmetic performed immediately." % xp)
555
if op is div and PY_TYPE_CHECK(xp, Parent):
556
xp = self.division_parent(xp)
557
return all, xp
558
if xp == yp:
559
all.append("Equal but distinct parents.")
560
561
if (op is not sub) and (op is not isub):
562
action = self.get_action(xp, yp, op)
563
if action is not None:
564
all.append("Action discovered.")
565
all.append(action)
566
return all, action.codomain()
567
568
homs = self.discover_coercion(xp, yp)
569
if homs is not None:
570
x_mor, y_mor = homs
571
if x_mor is not None:
572
all.append("Coercion on left operand via")
573
all.append(x_mor)
574
res = x_mor.codomain()
575
if y_mor is not None:
576
all.append("Coercion on right operand via")
577
all.append(y_mor)
578
if res is not None and res is not y_mor.codomain():
579
raise RuntimeError, ("BUG in coercion model: codomains not equal!", x_mor, y_mor)
580
res = y_mor.codomain()
581
all.append("Arithmetic performed after coercions.")
582
if op is div and PY_TYPE_CHECK(res, Parent):
583
res = self.division_parent(res)
584
return all, res
585
586
if PY_TYPE_CHECK(yp, Parent) and xp in [int, long, float, complex, bool]:
587
mor = yp.coerce_map_from(xp)
588
if mor is not None:
589
all.append("Coercion on numeric left operand via")
590
all.append(mor)
591
if op is div and PY_TYPE_CHECK(yp, Parent):
592
yp = self.division_parent(yp)
593
return all, yp
594
all.append("Left operand is numeric, will attempt coercion in both directions.")
595
elif type(xp) is type:
596
all.append("Left operand is not Sage element, will try _sage_.")
597
598
if PY_TYPE_CHECK(xp, Parent) and yp in [int, long, float, complex, bool]:
599
mor = xp.coerce_map_from(yp)
600
if mor is not None:
601
all.append("Coercion on numeric right operand via")
602
all.append(mor)
603
if op is div and PY_TYPE_CHECK(xp, Parent):
604
xp = self.division_parent(xp)
605
return all, xp
606
all.append("Right operand is numeric, will attempt coercion in both directions.")
607
elif type(yp) is type:
608
all.append("Right operand is not Sage element, will try _sage_.")
609
610
if op is mul or op is imul:
611
all.append("Will try _r_action and _l_action")
612
613
return all, None
614
615
cpdef Parent division_parent(self, Parent parent):
616
r"""
617
Deduces where the result of division in parent lies by calculating
618
the inverse of ``parent.one_element()`` or ``parent.an_element()``.
619
620
The result is cached.
621
622
EXAMPLES::
623
624
sage: cm = sage.structure.element.get_coercion_model()
625
sage: cm.division_parent(ZZ)
626
Rational Field
627
sage: cm.division_parent(QQ)
628
Rational Field
629
sage: cm.division_parent(ZZ['x'])
630
Fraction Field of Univariate Polynomial Ring in x over Integer Ring
631
sage: cm.division_parent(GF(41))
632
Finite Field of size 41
633
sage: cm.division_parent(Integers(100))
634
Ring of integers modulo 100
635
sage: cm.division_parent(SymmetricGroup(5))
636
Symmetric group of order 5! as a permutation group
637
"""
638
try:
639
return self._division_parents.get(parent, None, None)
640
except KeyError:
641
pass
642
try:
643
ret = parent_c(~parent.one_element())
644
except:
645
self._record_exception()
646
ret = parent_c(~parent.an_element())
647
self._division_parents.set(parent, None, None, ret)
648
return ret
649
650
651
cpdef bin_op(self, x, y, op):
652
"""
653
Execute the operation op on x and y. It first looks for an action
654
corresponding to op, and failing that, it tries to coerces x and y
655
into the a common parent and calls op on them.
656
657
If it cannot make sense of the operation, a TypeError is raised.
658
659
INPUT:
660
661
- ``x`` - the left operand
662
663
- ``y`` - the right operand
664
665
- ``op`` - a python function taking 2 arguments
666
667
.. note::
668
669
op is often an arithmetic operation, but need not be so.
670
671
EXAMPLES::
672
673
sage: cm = sage.structure.element.get_coercion_model()
674
sage: cm.bin_op(1/2, 5, operator.mul)
675
5/2
676
677
The operator can be any callable::
678
679
set Rational Field Integer Ring <function <lambda> at 0xc0b2270> None None
680
(Rational Field, Rational Field)
681
sage: R.<x> = ZZ['x']
682
sage: cm.bin_op(x^2-1, x+1, gcd)
683
x + 1
684
685
Actions are detected and performed::
686
687
sage: M = matrix(ZZ, 2, 2, range(4))
688
sage: V = vector(ZZ, [5,7])
689
sage: cm.bin_op(M, V, operator.mul)
690
(7, 31)
691
692
TESTS::
693
694
sage: class Foo:
695
... def __rmul__(self, left):
696
... return 'hello'
697
...
698
sage: H = Foo()
699
sage: print int(3)*H
700
hello
701
sage: print Integer(3)*H
702
hello
703
sage: print H*3
704
Traceback (most recent call last):
705
...
706
TypeError: unsupported operand parent(s) for '*': '<type 'instance'>' and 'Integer Ring'
707
708
sage: class Nonsense:
709
... def __init__(self, s):
710
... self.s = s
711
... def __repr__(self):
712
... return self.s
713
... def __mul__(self, x):
714
... return Nonsense(self.s + chr(x%256))
715
... __add__ = __mul__
716
... def __rmul__(self, x):
717
... return Nonsense(chr(x%256) + self.s)
718
... __radd__ = __rmul__
719
...
720
sage: a = Nonsense('blahblah')
721
sage: a*80
722
blahblahP
723
sage: 80*a
724
Pblahblah
725
sage: a+80
726
blahblahP
727
sage: 80+a
728
Pblahblah
729
730
"""
731
self._exceptions_cleared = False
732
if (op is not sub) and (op is not isub):
733
# Actions take preference over common-parent coercions.
734
xp = parent_c(x)
735
yp = parent_c(y)
736
if xp is yp:
737
return op(x,y)
738
action = self.get_action(xp, yp, op)
739
if action is not None:
740
return (<Action>action)._call_(x, y)
741
742
xy = None
743
try:
744
xy = self.canonical_coercion(x,y)
745
return PyObject_CallObject(op, xy)
746
except TypeError, err:
747
if xy is not None:
748
# The error was in calling, not coercing
749
raise
750
self._record_exception()
751
752
if op is mul or op is imul:
753
754
# elements may also act on non-elements
755
# (e.g. sequences or parents)
756
if not isinstance(y, Element) or not isinstance(x, Element):
757
try:
758
if hasattr(x, '_act_on_'):
759
res = x._act_on_(y, True)
760
if res is not None: return res
761
except CoercionException:
762
self._record_exception()
763
764
try:
765
if hasattr(x, '_acted_upon_'):
766
res = x._acted_upon_(y, True)
767
if res is not None: return res
768
except CoercionException:
769
self._record_exception()
770
771
try:
772
if hasattr(y, '_act_on_'):
773
res = y._act_on_(x, False)
774
if res is not None: return res
775
except CoercionException:
776
self._record_exception()
777
778
try:
779
if hasattr(y, '_acted_upon_'):
780
res = y._acted_upon_(x, False)
781
if res is not None: return res
782
except CoercionException:
783
self._record_exception()
784
785
if not isinstance(y, Element):
786
op_name = op.__name__
787
if op_name[0] == 'i':
788
op_name = op_name[1:]
789
mul_method = getattr3(y, '__r%s__'%op_name, None)
790
if mul_method is not None:
791
res = mul_method(x)
792
if res is not None and res is not NotImplemented:
793
return res
794
795
# We should really include the underlying error.
796
# This causes so much headache.
797
raise TypeError, arith_error_message(x,y,op)
798
799
cpdef canonical_coercion(self, x, y):
800
r"""
801
Given two elements x and y, with parents S and R respectively,
802
find a common parent Z such that there are coercions
803
`f: S \mapsto Z` and `g: R \mapsto Z` and return `f(x), g(y)`
804
which will have the same parent.
805
806
Raises a type error if no such Z can be found.
807
808
EXAMPLES::
809
810
sage: cm = sage.structure.element.get_coercion_model()
811
sage: cm.canonical_coercion(mod(2, 10), 17)
812
(2, 7)
813
sage: x, y = cm.canonical_coercion(1/2, matrix(ZZ, 2, 2, range(4)))
814
sage: x
815
[1/2 0]
816
[ 0 1/2]
817
sage: y
818
[0 1]
819
[2 3]
820
sage: parent(x) is parent(y)
821
True
822
823
There is some support for non-Sage datatypes as well::
824
825
sage: x, y = cm.canonical_coercion(int(5), 10)
826
sage: type(x), type(y)
827
(<type 'sage.rings.integer.Integer'>, <type 'sage.rings.integer.Integer'>)
828
829
830
sage: x, y = cm.canonical_coercion(int(5), complex(3))
831
sage: type(x), type(y)
832
(<type 'complex'>, <type 'complex'>)
833
834
sage: class MyClass:
835
... def _sage_(self):
836
... return 13
837
sage: a, b = cm.canonical_coercion(MyClass(), 1/3)
838
sage: a, b
839
(13, 1/3)
840
sage: type(a)
841
<type 'sage.rings.rational.Rational'>
842
843
We also make an exception for 0, even if $\ZZ$ does not map in::
844
845
sage: canonical_coercion(vector([1, 2, 3]), 0)
846
((1, 2, 3), (0, 0, 0))
847
"""
848
xp = parent_c(x)
849
yp = parent_c(y)
850
if xp is yp:
851
return x,y
852
853
cdef Element x_elt, y_elt
854
coercions = self.coercion_maps(xp, yp)
855
if coercions is not None:
856
x_map, y_map = coercions
857
if x_map is not None:
858
x_elt = (<Map>x_map)._call_(x)
859
else:
860
x_elt = x
861
if y_map is not None:
862
y_elt = (<Map>y_map)._call_(y)
863
else:
864
y_elt = y
865
if x_elt is None:
866
raise RuntimeError, "BUG in map, returned None %s %s %s" % (x, type(x_map), x_map)
867
elif y_elt is None:
868
raise RuntimeError, "BUG in map, returned None %s %s %s" % (y, type(y_map), y_map)
869
if x_elt._parent is y_elt._parent:
870
# We must verify this as otherwise we are prone to
871
# getting into an infinite loop in c, and the above
872
# maps may be written by (imperfect) users.
873
return x_elt,y_elt
874
elif x_elt._parent == y_elt._parent:
875
# TODO: Non-uniqueness of parents strikes again!
876
# print parent_c(x_elt), " is not ", parent_c(y_elt)
877
y_elt = parent_c(x_elt)(y_elt)
878
if x_elt._parent is y_elt._parent:
879
return x_elt,y_elt
880
self._coercion_error(x, x_map, x_elt, y, y_map, y_elt)
881
882
883
cdef bint x_numeric = PY_IS_NUMERIC(x)
884
cdef bint y_numeric = PY_IS_NUMERIC(y)
885
886
if x_numeric and y_numeric:
887
x_rank = _native_coercion_ranks[type(x)]
888
y_rank = _native_coercion_ranks[type(y)]
889
ty = _native_coercion_ranks_inv[max(x_rank, y_rank)]
890
x = ty(x)
891
y = ty(y)
892
return x, y
893
894
# Now handle the native python + sage object cases
895
# that were not taken care of above.
896
elif x_numeric:
897
try:
898
sage_parent = py_scalar_parent(type(x))
899
if sage_parent is None or sage_parent.has_coerce_map_from(yp):
900
return x, x.__class__(y)
901
else:
902
return self.canonical_coercion(sage_parent(x), y)
903
except (TypeError, ValueError):
904
self._record_exception()
905
906
elif y_numeric:
907
try:
908
sage_parent = py_scalar_parent(type(y))
909
if sage_parent is None or sage_parent.has_coerce_map_from(xp):
910
return y.__class__(x), y
911
else:
912
return self.canonical_coercion(x, sage_parent(y))
913
except (TypeError, ValueError):
914
self._record_exception()
915
916
# See if the non-objects define a _sage_ method.
917
if not PY_TYPE_CHECK(x, SageObject) or not PY_TYPE_CHECK(y, SageObject):
918
try:
919
x = x._sage_()
920
y = y._sage_()
921
except AttributeError:
922
self._record_exception()
923
else:
924
return self.canonical_coercion(x, y)
925
926
# Allow coercion of 0 even if no coercion from Z
927
if is_Integer(x) and not x and not PY_TYPE_CHECK_EXACT(yp, type):
928
try:
929
return yp(0), y
930
except:
931
self._record_exception()
932
933
if is_Integer(y) and not y and not PY_TYPE_CHECK_EXACT(xp, type):
934
try:
935
return x, xp(0)
936
except:
937
self._record_exception()
938
939
raise TypeError, "no common canonical parent for objects with parents: '%s' and '%s'"%(xp, yp)
940
941
942
cpdef coercion_maps(self, R, S):
943
r"""
944
Give two parents R and S, return a pair of coercion maps
945
`f: R \rightarrow Z` and `g: S \rightarrow Z` , if such a `Z`
946
can be found.
947
948
In the (common) case that `R=Z` or `S=Z` then ``None`` is returned
949
for `f` or `g` respectively rather than constructing (and subsequently
950
calling) the identity morphism.
951
952
If no suitable `f, g` can be found, a single None is returned.
953
This result is cached.
954
955
EXAMPLES::
956
957
sage: cm = sage.structure.element.get_coercion_model()
958
sage: f, g = cm.coercion_maps(ZZ, QQ)
959
sage: print f
960
Natural morphism:
961
From: Integer Ring
962
To: Rational Field
963
sage: print g
964
None
965
966
sage: f, g = cm.coercion_maps(ZZ['x'], QQ)
967
sage: print f
968
Conversion map:
969
From: Univariate Polynomial Ring in x over Integer Ring
970
To: Univariate Polynomial Ring in x over Rational Field
971
sage: print g
972
Polynomial base injection morphism:
973
From: Rational Field
974
To: Univariate Polynomial Ring in x over Rational Field
975
976
sage: cm.coercion_maps(QQ, GF(7)) == None
977
True
978
979
Note that to break symmetry, if there is a coercion map in both
980
directions, the parent on the left is used::
981
982
sage: V = QQ^3
983
sage: W = V.__class__(QQ, 3)
984
sage: V == W
985
True
986
sage: V is W
987
False
988
sage: cm = sage.structure.element.get_coercion_model()
989
sage: cm.coercion_maps(V, W)
990
(None,
991
Call morphism:
992
From: Vector space of dimension 3 over Rational Field
993
To: Vector space of dimension 3 over Rational Field)
994
sage: cm.coercion_maps(W, V)
995
(None,
996
Call morphism:
997
From: Vector space of dimension 3 over Rational Field
998
To: Vector space of dimension 3 over Rational Field)
999
sage: v = V([1,2,3])
1000
sage: w = W([1,2,3])
1001
sage: parent(v+w) is V
1002
True
1003
sage: parent(w+v) is W
1004
True
1005
"""
1006
try:
1007
return self._coercion_maps.get(R, S, None)
1008
except KeyError:
1009
homs = self.discover_coercion(R, S)
1010
if 0:
1011
# This breaks too many things that are going to change
1012
# in the new coercion model anyways.
1013
# COERCE TODO: Enable it then.
1014
homs = self.verify_coercion_maps(R, S, homs)
1015
else:
1016
if homs is not None:
1017
x_map, y_map = homs
1018
if x_map is not None and not isinstance(x_map, Map):
1019
raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map"
1020
if y_map is not None and not isinstance(y_map, Map):
1021
raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map"
1022
if homs is None:
1023
swap = None
1024
else:
1025
R_map, S_map = homs
1026
if R_map is None and PY_TYPE_CHECK(S, Parent) and (<Parent>S).has_coerce_map_from(R):
1027
swap = None, (<Parent>S).coerce_map_from(R)
1028
else:
1029
swap = S_map, R_map
1030
self._coercion_maps.set(R, S, None, homs)
1031
self._coercion_maps.set(S, R, None, swap)
1032
return homs
1033
1034
cpdef verify_coercion_maps(self, R, S, homs, bint fix=False):
1035
"""
1036
Make sure this is a valid pair of homomorphisms from R and S to a common parent.
1037
This function is used to protect the user against buggy parents.
1038
1039
EXAMPLES::
1040
1041
sage: cm = sage.structure.element.get_coercion_model()
1042
sage: homs = QQ.coerce_map_from(ZZ), None
1043
sage: cm.verify_coercion_maps(ZZ, QQ, homs) == homs
1044
True
1045
sage: homs = QQ.coerce_map_from(ZZ), RR.coerce_map_from(QQ)
1046
sage: cm.verify_coercion_maps(ZZ, QQ, homs) == homs
1047
Traceback (most recent call last):
1048
...
1049
RuntimeError: ('BUG in coercion model, codomains must be identical', Natural morphism:
1050
From: Integer Ring
1051
To: Rational Field, Generic map:
1052
From: Rational Field
1053
To: Real Field with 53 bits of precision)
1054
"""
1055
if homs is None:
1056
return None
1057
cdef Map x_map, y_map
1058
R_map, S_map = homs
1059
if PY_TYPE_CHECK(R, type):
1060
R = Set_PythonType(R)
1061
elif PY_TYPE_CHECK(S, type):
1062
S = Set_PythonType(S)
1063
if R_map is None:
1064
R_map = IdentityMorphism(R)
1065
elif S_map is None:
1066
S_map = IdentityMorphism(S)
1067
# Make sure the domains are correct
1068
if R_map.domain() is not R:
1069
if fix:
1070
connecting = R_map.domain().coerce_map_from(R)
1071
if connecting is not None:
1072
R_map = R_map * connecting
1073
if R_map.domain() is not R:
1074
raise RuntimeError, ("BUG in coercion model, left domain must be original parent", R, R_map)
1075
if S_map is not None and S_map.domain() is not S:
1076
if fix:
1077
connecting = S_map.domain().coerce_map_from(S)
1078
if connecting is not None:
1079
S_map = S_map * connecting
1080
if S_map.domain() is not S:
1081
raise RuntimeError, ("BUG in coercion model, right domain must be original parent", S, S_map)
1082
# Make sure the codomains are correct
1083
if R_map.codomain() is not S_map.codomain():
1084
if fix:
1085
connecting = R_map.codomain().coerce_map_from(S_map.codomain())
1086
if connecting is not None:
1087
S_map = connecting * S_map
1088
else:
1089
connecting = S_map.codomain().coerce_map_from(R_map.codomain())
1090
if connecting is not None:
1091
R_map = connecting * R_map
1092
if R_map.codomain() is not S_map.codomain():
1093
raise RuntimeError, ("BUG in coercion model, codomains must be identical", R_map, S_map)
1094
if PY_TYPE_CHECK(R_map, IdentityMorphism):
1095
R_map = None
1096
elif PY_TYPE_CHECK(S_map, IdentityMorphism):
1097
S_map = None
1098
return R_map, S_map
1099
1100
1101
cpdef discover_coercion(self, R, S):
1102
"""
1103
This actually implements the finding of coercion maps as described in
1104
the ``coercion_maps`` method.
1105
1106
EXAMPLES::
1107
1108
sage: cm = sage.structure.element.get_coercion_model()
1109
1110
If R is S, then two identity morphisms suffice::
1111
1112
sage: cm.discover_coercion(SR, SR)
1113
(None, None)
1114
1115
If there is a coercion map either direction, use that::
1116
1117
sage: cm.discover_coercion(ZZ, QQ)
1118
(Natural morphism:
1119
From: Integer Ring
1120
To: Rational Field, None)
1121
sage: cm.discover_coercion(RR, QQ)
1122
(None,
1123
Generic map:
1124
From: Rational Field
1125
To: Real Field with 53 bits of precision)
1126
1127
Otherwise, try and compute an appropriate cover::
1128
1129
sage: cm.discover_coercion(ZZ['x,y'], RDF)
1130
(Call morphism:
1131
From: Multivariate Polynomial Ring in x, y over Integer Ring
1132
To: Multivariate Polynomial Ring in x, y over Real Double Field,
1133
Polynomial base injection morphism:
1134
From: Real Double Field
1135
To: Multivariate Polynomial Ring in x, y over Real Double Field)
1136
1137
Sometimes there is a reasonable "cover," but no canonical coercion::
1138
1139
sage: sage.categories.pushout.pushout(QQ, QQ^3)
1140
Vector space of dimension 3 over Rational Field
1141
sage: print cm.discover_coercion(QQ, QQ^3)
1142
None
1143
"""
1144
from sage.categories.homset import Hom
1145
if R is S:
1146
return None, None
1147
1148
# See if there is a natural coercion from R to S
1149
if PY_TYPE_CHECK(R, Parent):
1150
mor = (<Parent>R).coerce_map_from(S)
1151
if mor is not None:
1152
return None, mor
1153
1154
# See if there is a natural coercion from S to R
1155
if PY_TYPE_CHECK(S, Parent):
1156
mor = (<Parent>S).coerce_map_from(R)
1157
if mor is not None:
1158
return mor, None
1159
1160
# Try base extending
1161
if PY_TYPE_CHECK(R, Parent) and PY_TYPE_CHECK(S, Parent):
1162
from sage.categories.pushout import pushout
1163
try:
1164
Z = pushout(R, S)
1165
coerce_R = Z.coerce_map_from(R)
1166
coerce_S = Z.coerce_map_from(S)
1167
if coerce_R is None:
1168
raise TypeError, "No coercion from %s to pushout %s" % (R, Z)
1169
if coerce_S is None:
1170
raise TypeError, "No coercion from %s to pushout %s" % (S, Z)
1171
return coerce_R, coerce_S
1172
except:
1173
self._record_exception()
1174
1175
return None
1176
1177
1178
cpdef get_action(self, R, S, op):
1179
"""
1180
Get the action of R on S or S on R associated to the operation op.
1181
1182
EXAMPLES::
1183
1184
sage: cm = sage.structure.element.get_coercion_model()
1185
sage: cm.get_action(ZZ['x'], ZZ, operator.mul)
1186
Right scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Integer Ring
1187
sage: cm.get_action(ZZ['x'], ZZ, operator.imul)
1188
Right scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Integer Ring
1189
sage: cm.get_action(ZZ['x'], QQ, operator.mul)
1190
Right scalar multiplication by Rational Field on Univariate Polynomial Ring in x over Integer Ring
1191
sage: cm.get_action(QQ['x'], int, operator.mul)
1192
Right scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Rational Field
1193
with precomposition on right by Native morphism:
1194
From: Set of Python objects of type 'int'
1195
To: Integer Ring
1196
1197
sage: R.<x> = QQ['x']
1198
sage: A = cm.get_action(R, ZZ, operator.div); A
1199
Right inverse action by Rational Field on Univariate Polynomial Ring in x over Rational Field
1200
with precomposition on right by Natural morphism:
1201
From: Integer Ring
1202
To: Rational Field
1203
sage: A(x+10, 5)
1204
1/5*x + 2
1205
1206
"""
1207
try:
1208
return self._action_maps.get(R, S, op)
1209
except KeyError:
1210
action = self.discover_action(R, S, op)
1211
action = self.verify_action(action, R, S, op)
1212
self._action_maps.set(R, S, op, action)
1213
return action
1214
1215
cpdef verify_action(self, action, R, S, op, bint fix=True):
1216
r"""
1217
Verify that ``action`` takes an element of R on the left and S
1218
on the right, raising an error if not.
1219
1220
This is used for consistency checking in the coercion model.
1221
1222
EXAMPLES::
1223
1224
sage: R.<x> = ZZ['x']
1225
sage: cm = sage.structure.element.get_coercion_model()
1226
sage: cm.verify_action(R.get_action(QQ), R, QQ, operator.mul)
1227
Right scalar multiplication by Rational Field on Univariate Polynomial Ring in x over Integer Ring
1228
sage: cm.verify_action(R.get_action(QQ), RDF, R, operator.mul)
1229
Traceback (most recent call last):
1230
...
1231
RuntimeError: There is a BUG in the coercion model:
1232
Action found for R <built-in function mul> S does not have the correct domains
1233
R = Real Double Field
1234
S = Univariate Polynomial Ring in x over Integer Ring
1235
(should be Univariate Polynomial Ring in x over Integer Ring, Rational Field)
1236
action = Right scalar multiplication by Rational Field on Univariate Polynomial Ring in x over Integer Ring (<type 'sage.structure.coerce_actions.RightModuleAction'>)
1237
"""
1238
if action is None:
1239
return action
1240
elif PY_TYPE_CHECK(action, IntegerMulAction):
1241
return action
1242
cdef bint ok = True
1243
try:
1244
if action.left_domain() is not R:
1245
ok &= PY_TYPE_CHECK(R, type) and action.left_domain()._type is R
1246
if action.right_domain() is not S:
1247
ok &= PY_TYPE_CHECK(S, type) and action.right_domain()._type is S
1248
except AttributeError:
1249
ok = False
1250
if not ok:
1251
if PY_TYPE_CHECK(R, type):
1252
R = Set_PythonType(R)
1253
if PY_TYPE_CHECK(S, type):
1254
S = Set_PythonType(S)
1255
1256
# Non-unique parents
1257
if fix and action.left_domain() is not R and action.left_domain() == R:
1258
action = PrecomposedAction(action, action.left_domain().coerce_map_from(R), None)
1259
if fix and action.right_domain() is not S and action.right_domain() == S:
1260
action = PrecomposedAction(action, None, action.right_domain().coerce_map_from(S))
1261
1262
if action.left_domain() is not R or action.right_domain() is not S:
1263
raise RuntimeError, """There is a BUG in the coercion model:
1264
Action found for R %s S does not have the correct domains
1265
R = %s
1266
S = %s
1267
(should be %s, %s)
1268
action = %s (%s)
1269
""" % (op, R, S, action.left_domain(), action.right_domain(), action, type(action))
1270
1271
return action
1272
1273
cpdef discover_action(self, R, S, op):
1274
"""
1275
INPUT
1276
1277
- ``R`` - the left Parent (or type)
1278
1279
- ``S`` - the right Parent (or type)
1280
1281
- ``op`` - the operand, typically an element of the operator module.
1282
1283
OUTPUT:
1284
1285
- An action A such that s op r is given by A(s,r).
1286
1287
The steps taken are illustrated below.
1288
1289
EXAMPLES::
1290
1291
sage: P.<x> = ZZ['x']
1292
sage: P.get_action(ZZ)
1293
Right scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Integer Ring
1294
sage: ZZ.get_action(P) is None
1295
True
1296
sage: cm = sage.structure.element.get_coercion_model()
1297
1298
If R or S is a Parent, ask it for an action by/on R::
1299
1300
sage: cm.discover_action(ZZ, P, operator.mul)
1301
Left scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Integer Ring
1302
1303
If R or S a type, recursively call get_action with the Sage versions of R and/or S::
1304
1305
sage: cm.discover_action(P, int, operator.mul)
1306
Right scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Integer Ring
1307
with precomposition on right by Native morphism:
1308
From: Set of Python objects of type 'int'
1309
To: Integer Ring
1310
1311
If op in an inplace operation, look for the non-inplace action::
1312
1313
sage: cm.discover_action(P, ZZ, operator.imul)
1314
Right scalar multiplication by Integer Ring on Univariate Polynomial Ring in x over Integer Ring
1315
1316
If op is division, look for action on right by inverse::
1317
1318
sage: cm.discover_action(P, ZZ, operator.div)
1319
Right inverse action by Rational Field on Univariate Polynomial Ring in x over Integer Ring
1320
with precomposition on right by Natural morphism:
1321
From: Integer Ring
1322
To: Rational Field
1323
"""
1324
#print "looking", R, <int><void *>R, op, S, <int><void *>S
1325
1326
if PY_TYPE_CHECK(R, Parent):
1327
action = (<Parent>R).get_action(S, op, True)
1328
if action is not None:
1329
#print "found2", action
1330
return action
1331
1332
if PY_TYPE_CHECK(S, Parent):
1333
action = (<Parent>S).get_action(R, op, False)
1334
if action is not None:
1335
#print "found1", action
1336
return action
1337
1338
if PY_TYPE(R) == <void *>type:
1339
sageR = py_scalar_parent(R)
1340
if sageR is not None:
1341
action = self.discover_action(sageR, S, op)
1342
if action is not None:
1343
if not PY_TYPE_CHECK(action, IntegerMulAction):
1344
action = PrecomposedAction(action, sageR.coerce_map_from(R), None)
1345
return action
1346
1347
if PY_TYPE(S) == <void *>type:
1348
sageS = py_scalar_parent(S)
1349
if sageS is not None:
1350
action = self.discover_action(R, sageS, op)
1351
if action is not None:
1352
if not PY_TYPE_CHECK(action, IntegerMulAction):
1353
action = PrecomposedAction(action, None, sageS.coerce_map_from(S))
1354
return action
1355
1356
if op.__name__[0] == 'i':
1357
try:
1358
a = self.discover_action(R, S, no_inplace_op(op))
1359
if a is not None:
1360
is_inverse = isinstance(a, InverseAction)
1361
if is_inverse: a = ~a
1362
if a is not None and PY_TYPE_CHECK(a, RightModuleAction):
1363
# We want a new instance so that we don't alter the (potentially cached) original
1364
a = RightModuleAction(S, R)
1365
a.is_inplace = 1
1366
if is_inverse: a = ~a
1367
return a
1368
except KeyError:
1369
self._record_exception()
1370
1371
if op is div:
1372
# Division on right is the same acting on right by inverse, if it is so defined.
1373
# To return such an action, we need to verify that it would be an action for the mul
1374
# operator, but the action must be over a parent containing inverse elements.
1375
from sage.rings.ring import is_Ring
1376
if is_Ring(S):
1377
try:
1378
K = S._pseudo_fraction_field()
1379
except (TypeError, AttributeError, NotImplementedError):
1380
K = None
1381
elif PY_TYPE_CHECK(S, Parent):
1382
K = S
1383
else:
1384
# python scalar case handled recursively above
1385
K = None
1386
1387
if K is not None:
1388
action = self.get_action(R, K, mul)
1389
if action is not None and action.actor() is K:
1390
try:
1391
action = ~action
1392
if K is not S:
1393
action = PrecomposedAction(action, None, K.coerce_map_from(S))
1394
return action
1395
except TypeError: # action may not be invertible
1396
self._record_exception()
1397
1398
return None
1399
1400
def _coercion_error(self, x, x_map, x_elt, y, y_map, y_elt):
1401
"""
1402
This function is only called when someone has incorrectly implemented
1403
a user-defined part of the coercion system (usually, a morphism).
1404
1405
EXAMPLE::
1406
1407
sage: cm = sage.structure.element.get_coercion_model()
1408
sage: cm._coercion_error('a', 'f', 'f(a)', 'b', 'g', 'g(b)')
1409
Traceback (most recent call last):
1410
...
1411
RuntimeError: There is a bug in the coercion code in Sage.
1412
Both x (='f(a)') and y (='g(b)') are supposed to have identical parents but they don't.
1413
In fact, x has parent '<type 'str'>'
1414
whereas y has parent '<type 'str'>'
1415
Original elements 'a' (parent <type 'str'>) and 'b' (parent <type 'str'>) and maps
1416
<type 'str'> 'f'
1417
<type 'str'> 'g'
1418
"""
1419
raise RuntimeError, """There is a bug in the coercion code in Sage.
1420
Both x (=%r) and y (=%r) are supposed to have identical parents but they don't.
1421
In fact, x has parent '%s'
1422
whereas y has parent '%s'
1423
Original elements %r (parent %s) and %r (parent %s) and maps
1424
%s %r
1425
%s %r"""%( x_elt, y_elt, parent_c(x_elt), parent_c(y_elt),
1426
x, parent_c(x), y, parent_c(y),
1427
type(x_map), x_map, type(y_map), y_map)
1428
1429
1430
1431