Ticket #14780: trac_14780-embed_tuples_in_SR.patch

File trac_14780-embed_tuples_in_SR.patch, 9.2 KB (added by burcin, 7 years ago)
  • sage/libs/ginac.pxd

    # HG changeset patch
    # User Burcin Erocal <burcin@erocal.org>
    # Date 1372219170 -7200
    #      Wed Jun 26 05:59:30 2013 +0200
    # Node ID 5779e4323648f28320d140c9ffc23837802a8a8a
    # Parent  5d8c13e7b81a1e152855073f97a4d48ee97255d1
    Allow embedding tuples in SR.
    
    diff --git a/sage/libs/ginac.pxd b/sage/libs/ginac.pxd
    a b  
    2020   
    2121    # forward declaration of GEx
    2222    ctypedef struct GEx "ex"
     23    ctypedef struct GExprSeq "exprseq"
    2324
    2425    ctypedef struct GBasic "basic":
    2526        unsigned int gethash()
     
    202203    GEx* GEx_construct_long "Construct_p<ex, long>" (void *mem, long n) except +
    203204    GEx* GEx_construct_double "Construct_p<ex, double>" \
    204205            (void *mem, double d) except +
     206    GEx* GEx_construct_exprseq "Construct_p<ex, exprseq>" \
     207            (void *mem, GExprSeq s)
    205208
    206209    GEx* GEx_construct_pyobject "ASSIGN_WRAP" (GEx mem, object n)       
    207210
     
    228231        int size()
    229232        GEx at(int i)
    230233
     234    ctypedef struct GExprSeq "exprseq":
     235        pass
     236
     237    GExprSeq* GExprSeq_construct_exvector "Construct_p<exprseq, exvector>" \
     238            (void *mem, GExVector m) except +
     239    bint is_a_exprseq "is_a<exprseq>" (GEx e)
     240    bint is_exactly_a_exprseq "is_exactly_a<exprseq>" (GEx e)
     241
     242
    231243    ctypedef struct GExSetIter "std::set<ex, ex_is_less>::const_iterator":
    232244        void inc "operator++" ()
    233245        GEx obj "operator*" ()
  • sage/symbolic/expression.pyx

    diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
    a b  
    44194419            <built-in function gt>
    44204420            sage: (x >= y).operator()
    44214421            <built-in function ge>
     4422            sage: SR._force_pyobject( (x, x + 1, x + 2) ).operator()
     4423            <type 'tuple'>
    44224424        """
    44234425        cdef operators o
    44244426        cdef unsigned serial
     
    44634465                res = FDerivativeOperator(res, parameter_set)
    44644466
    44654467            return res
     4468        elif is_exactly_a_exprseq(self._gobj):
     4469            return tuple
    44664470
    44674471        # self._gobj is either a symbol, constant or numeric
    44684472        return None
  • sage/symbolic/pynac.pyx

    diff --git a/sage/symbolic/pynac.pyx b/sage/symbolic/pynac.pyx
    a b  
    6262    nex._parent = ring.SR
    6363    return nex
    6464
     65cdef public object exprseq_to_PyTuple(GEx seq):
     66    """
     67    Convert an exprseq to a Python tuple.
     68
     69    Used while converting arguments of symbolic functions to Python objects.
     70
     71    EXAMPLES::
     72
     73        sage: from sage.symbolic.function import BuiltinFunction
     74        sage: class TFunc(BuiltinFunction):
     75        ....:     def __init__(self):
     76        ....:         BuiltinFunction.__init__(self, 'tfunc', nargs=0)
     77        ....:
     78        ....:     def _eval_(self, *args):
     79        ....:         print "len(args): %s, types: %s"%(len(args), str(map(type, args)))
     80        ....:         for i, a in enumerate(args):
     81        ....:             if isinstance(a, tuple):
     82        ....:                 print "argument %s is a tuple, with types %s"%(str(i), str(map(type, a)))
     83        ....:
     84        sage: tfunc = TFunc()
     85        sage: u = SR._force_pyobject((1, x+1, 2))
     86        sage: tfunc(u, x, SR._force_pyobject((3.0, 2^x)))
     87        len(args): 3, types: [<type 'tuple'>, <type 'sage.symbolic.expression.Expression'>, <type 'tuple'>]
     88        argument 0 is a tuple, with types [<type 'sage.rings.integer.Integer'>, <type 'sage.symbolic.expression.Expression'>, <type 'sage.rings.integer.Integer'>]
     89        argument 2 is a tuple, with types [<type 'sage.rings.real_mpfr.RealLiteral'>, <type 'sage.symbolic.expression.Expression'>]
     90        tfunc((1, x + 1, 2), x, (3.00000000000000, 2^x))
     91    """
     92    from sage.symbolic.ring import SR
     93    res = []
     94    for i in range(seq.nops()):
     95        if is_a_numeric(seq.op(i)):
     96            res.append(py_object_from_numeric(seq.op(i)))
     97        elif is_exactly_a_exprseq(seq.op(i)):
     98            res.append(exprseq_to_PyTuple(seq.op(i)))
     99        else:
     100            res.append(new_Expression_from_GEx(SR, seq.op(i)))
     101    return tuple(res)
     102
    65103cdef public object exvector_to_PyTuple(GExVector seq):
    66104    """
    67105    Converts arguments list given to a function to a PyTuple.
     
    71109
    72110    We convert Python objects wrapped in symbolic expressions back to regular
    73111    Python objects.
     112
     113    EXAMPLES::
     114
     115        sage: from sage.symbolic.function import BuiltinFunction
     116        sage: class TFunc(BuiltinFunction):
     117        ....:     def __init__(self):
     118        ....:         BuiltinFunction.__init__(self, 'tfunc', nargs=0)
     119        ....:
     120        ....:     def _eval_(self, *args):
     121        ....:         print "len(args): %s, types: %s"%(len(args), str(map(type, args)))
     122        sage: tfunc = TFunc()
     123        sage: u = SR._force_pyobject((1, x+1, 2))
     124        sage: tfunc(u, x, 3.0, 5.0r, 1r)
     125        len(args): 5, types: [<type 'tuple'>, <type 'sage.symbolic.expression.Expression'>, <type 'sage.rings.real_mpfr.RealLiteral'>, <type 'float'>, <type 'int'>]
     126        tfunc((1, x + 1, 2), x, 3.00000000000000, 5.0, 1)
     127
     128    TESTS:
     129
     130    Check if symbolic functions in the arguments are preserved::
     131
     132        sage: tfunc(sin(x), tfunc(1, x^2))
     133        len(args): 2, types: [<type 'sage.rings.integer.Integer'>, <type 'sage.symbolic.expression.Expression'>]
     134        len(args): 2, types: [<type 'sage.symbolic.expression.Expression'>, <type 'sage.symbolic.expression.Expression'>]
     135        tfunc(sin(x), tfunc(1, x^2))
     136
    74137    """
    75138    from sage.symbolic.ring import SR
    76139    res = []
    77140    for i in range(seq.size()):
    78141        if is_a_numeric(seq.at(i)):
    79142            res.append(py_object_from_numeric(seq.at(i)))
     143        elif is_exactly_a_exprseq(seq.at(i)):
     144            res.append(exprseq_to_PyTuple(seq.at(i)))
    80145        else:
    81146            res.append(new_Expression_from_GEx(SR, seq.at(i)))
    82147    return tuple(res)
  • sage/symbolic/ring.pyx

    diff --git a/sage/symbolic/ring.pyx b/sage/symbolic/ring.pyx
    a b  
    285285
    286286        return new_Expression_from_GEx(self, exp)
    287287
    288     def _force_pyobject(self, x):
     288    def _force_pyobject(self, x, bint force=False, bint recursive=True):
    289289        """
    290290        Wrap the given Python object in a symbolic expression even if it
    291291        cannot be coerced to the Symbolic Ring.
    292292
     293        INPUT:
     294
     295        - ``x`` - a Python object
     296
     297        - ``force`` - bool, default ``False``, if True, the Python object
     298          is takes as is without attempting coercion or list traversal
     299
     300        - ``recursive`` - bool, default ``True``, disables recursive
     301          traversal of lists.
     302
    293303        EXAMPLES::
    294304
    295             sage: t = SR._force_pyobject([3,4,5]); t
    296             [3, 4, 5]
     305            sage: t = SR._force_pyobject(QQ); t
     306            Rational Field
    297307            sage: type(t)
    298308            <type 'sage.symbolic.expression.Expression'>
     309
     310        Testing tuples::
     311
     312            sage: t = SR._force_pyobject((1, 2, x, x+1, x+2)); t
     313            (1, 2, x, x + 1, x + 2)
     314            sage: t.subs(x = 2*x^2)
     315            (1, 2, 2*x^2, 2*x^2 + 1, 2*x^2 + 2)
     316            sage: t.op[0]
     317            1
     318            sage: t.op[2]
     319            x
     320
     321        It also works if the argument is a ``list``::
     322
     323            sage: t = SR._force_pyobject([1, 2, x, x+1, x+2]); t
     324            (1, 2, x, x + 1, x + 2)
     325            sage: t.subs(x = 2*x^2)
     326            (1, 2, 2*x^2, 2*x^2 + 1, 2*x^2 + 2)
     327            sage: SR._force_pyobject((QQ, RR, CC))
     328            (Rational Field, Real Field with 53 bits of precision, Complex Field with 53 bits of precision)
     329            sage: t = SR._force_pyobject((QQ, (x, x + 1, x + 2), CC)); t
     330            (Rational Field, (x, x + 1, x + 2), Complex Field with 53 bits of precision)
     331            sage: t.subs(x=x^2)
     332            (Rational Field, (x^2, x^2 + 1, x^2 + 2), Complex Field with 53 bits of precision)
     333
     334        If ``recursive`` is ``False`` the inner tuple is taken as a Python
     335        object. This prevents substitution as above::
     336
     337            sage: t = SR._force_pyobject((QQ, (x, x + 1, x + 2), CC), recursive=False)
     338            sage: t
     339            (Rational Field, (x, x + 1, x + 2), Complex Field with 53 bits
     340            of precision)
     341            sage: t.subs(x=x^2)
     342            (Rational Field, (x, x + 1, x + 2), Complex Field with 53 bits
     343            of precision)
    299344        """
    300345        cdef GEx exp
    301         GEx_construct_pyobject(exp, x)
     346        cdef GExprSeq ex_seq
     347        cdef GExVector ex_v
     348        if force:
     349            GEx_construct_pyobject(exp, x)
     350
     351        else:
     352            # first check if we can do it the nice way
     353            if isinstance(x, Expression):
     354                return x
     355            try:
     356                return self._coerce_(x)
     357            except TypeError:
     358                pass
     359
     360            # tuples can be packed into exprseq
     361            if isinstance(x, (tuple, list)):
     362                for e in x:
     363                    obj = SR._force_pyobject(e, force=(not recursive))
     364                    ex_v.push_back( (<Expression>obj)._gobj )
     365
     366                GExprSeq_construct_exvector(&ex_seq, ex_v)
     367
     368                GEx_construct_exprseq(&exp, ex_seq)
     369            else:
     370                GEx_construct_pyobject(exp, x)
     371
    302372        return new_Expression_from_GEx(self, exp)
    303373
    304374    def wild(self, unsigned int n=0):