Ticket #14058: 14058-weak-binop.patch

File 14058-weak-binop.patch, 4.8 KB (added by robertwb, 9 years ago)
  • sage/structure/coerce.pyx

    # HG changeset patch
    # User Robert Bradshaw <robertwb@gmail.com>
    # Date 1360058161 28800
    # Node ID 4c451c85cec37528a9fb8761eb882ba0da12c983
    # Parent  b936e7334beb18eafcfc2e5533be7836da061900
    Remove strong references to parents used in binary operations in the coercion model.
    
    diff --git a/sage/structure/coerce.pyx b/sage/structure/coerce.pyx
    a b  
    8080
    8181import operator
    8282
     83from cpython.weakref cimport PyWeakref_GetObject, PyWeakref_NewRef
     84
    8385from sage_object cimport SageObject
    8486from sage.categories.map cimport Map
    8587import sage.categories.morphism
     
    9294
    9395from coerce_actions import LeftModuleAction, RightModuleAction, IntegerMulAction
    9496
     97cdef object coerce_to_left = "coerce_to_left"
     98cdef object coerce_to_right = "coerce_to_right"
     99
    95100cpdef py_scalar_parent(py_type):
    96101    """
    97102    Returns the Sage equivalent of the given python type, if one exists.
     
    228233        Now lets see what happens when we do a binary operations with
    229234        an integer and a rational::
    230235       
    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
     236            sage: maps[ZZ, QQ]
     237            'coerce_to_right'
    238238           
    239239        We can see that it coerces the left operand from an integer to a
    240240        rational, and doesn't do anything to the right.
     
    10631063            True
    10641064        """
    10651065        try:
    1066             return self._coercion_maps.get(R, S, None)
     1066            result = self._coercion_maps.get(R, S, None)
     1067            if result is None:
     1068                return None
     1069            elif result is coerce_to_left:
     1070                return None, R.coerce_map_from(S)
     1071            elif result is coerce_to_right:
     1072                return S.coerce_map_from(R), None
     1073            else:
     1074                codomain = <object>PyWeakref_GetObject(result)
     1075                if codomain is not None:
     1076                    return codomain.coerce_map_from(R), codomain.coerce_map_from(S)
    10671077        except KeyError:
    1068             homs = self.discover_coercion(R, S)
    1069             if 0:
    1070                 # This breaks too many things that are going to change
    1071                 # in the new coercion model anyways.
    1072                 # COERCE TODO: Enable it then.
    1073                 homs = self.verify_coercion_maps(R, S, homs)
     1078            pass
     1079        homs = self.discover_coercion(R, S)
     1080        if 0:
     1081            # This breaks too many things that are going to change
     1082            # in the new coercion model anyways.
     1083            # COERCE TODO: Enable it then.
     1084            homs = self.verify_coercion_maps(R, S, homs)
     1085        else:
     1086            if homs is not None:
     1087                x_map, y_map = homs
     1088                if x_map is not None and not isinstance(x_map, Map):
     1089                    raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map"
     1090                if y_map is not None and not isinstance(y_map, Map):
     1091                    raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map"
     1092        if homs is None:
     1093            result = None
     1094            swap = None
     1095        else:
     1096            R_map, S_map = homs
     1097            if R_map is None:
     1098                result = coerce_to_left
     1099                if PY_TYPE_CHECK(S, Parent) and (<Parent>S).has_coerce_map_from(R):
     1100                    swap = coerce_to_left
     1101                else:
     1102                    swap = coerce_to_right
     1103            elif S_map is None:
     1104                result = coerce_to_right
     1105                swap = coerce_to_left
    10741106            else:
    1075                 if homs is not None:
    1076                     x_map, y_map = homs
    1077                     if x_map is not None and not isinstance(x_map, Map):
    1078                         raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map"
    1079                     if y_map is not None and not isinstance(y_map, Map):
    1080                         raise RuntimeError, "BUG in coercion model: coerce_map_from must return a Map"
    1081             if homs is None:
    1082                 swap = None
    1083             else:
    1084                 R_map, S_map = homs
    1085                 if R_map is None and PY_TYPE_CHECK(S, Parent) and (<Parent>S).has_coerce_map_from(R):
    1086                     swap = None, (<Parent>S).coerce_map_from(R)
    1087                 else:
    1088                     swap = S_map, R_map
    1089             self._coercion_maps.set(R, S, None, homs)
    1090             self._coercion_maps.set(S, R, None, swap)
     1107                result = swap = PyWeakref_NewRef(R_map.codomain(), None)
     1108        self._coercion_maps.set(R, S, None, result)
     1109        self._coercion_maps.set(S, R, None, swap)
    10911110        return homs
    10921111       
    10931112    cpdef verify_coercion_maps(self, R, S, homs, bint fix=False):