Ticket #11576: trac_11576-indexed_expression.20130107.patch

File trac_11576-indexed_expression.20130107.patch, 9.1 KB (added by burcin, 6 years ago)
  • sage/libs/ginac.pxd

    # HG changeset patch
    # User Burcin Erocal <burcin@erocal.org>
    # Date 1321619725 -3600
    # Node ID d12a393276054f80d87b91b0eb1165315a20077d
    # Parent  eb51641224f8d44c88f176e62b7cc1625d86f892
    Prototype implementation for indexed symbolic expressions.
    
    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 GExVector "exvector"
    2324
    2425    ctypedef struct GBasic "basic":
    2526        unsigned int gethash()
     
    101102        bint info(unsigned)           except +
    102103        void dbgprint()
    103104        void dbgprinttree()
     105        GEx simplify_indexed(unsigned int options) except +
     106        GExVector get_free_indices()  except +
    104107
    105108    GExPair make_pair "std::make_pair" (GEx, GEx)
    106109
     
    236239
    237240    void g_list_symbols "list_symbols" (GEx e, GExSet s)
    238241
     242    # indexed expressions
     243    ctypedef struct GIdx "idx":
     244        GEx get_value()
     245        GEx get_dim()
     246
     247    GIdx ginac_idx "GiNaC::idx" (GEx v, GEx d) except +
     248    GEx ginac_indexed_p "GiNaC::indexed" (GEx v, GIdx i) except +
     249    GEx ginac_indexed_pp "GiNaC::indexed" (GEx v, GIdx i, GIdx j) except +
     250    bint is_a_idx "is_a<idx>" (GEx e)
     251    GIdx ex_to_idx "ex_to<idx>" (GEx e)
     252
    239253    # more is_a tests
    240254    bint is_a_add "is_a<add>" (GEx e)
    241255    bint is_a_mul "is_a<mul>" (GEx e)
  • sage/symbolic/expression.pyx

    diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
    a b  
    141141import sage.rings.integer
    142142import sage.rings.rational
    143143from sage.structure.element cimport ModuleElement, RingElement, Element
    144 from sage.symbolic.getitem cimport OperandsWrapper
     144from sage.symbolic.pynac cimport exvector_to_PyTuple
     145from sage.symbolic.getitem cimport OperandsWrapper, IndexWrapper
    145146from sage.symbolic.function import get_sfunction_from_serial, SymbolicFunction
    146147from sage.rings.rational import Rational  # Used for sqrt.
    147148from sage.misc.derivative import multi_derivative
     
    43764377            res._expr = self
    43774378            return res
    43784379
     4380    property ind:
     4381        def __get__(self):
     4382            """
     4383            sage: ex = x + 1
     4384            sage: id = ex.ind[Permutation([2,1,3])]
     4385            sage: id.get_index()
     4386            """
     4387            cdef IndexWrapper res = IndexWrapper.__new__(IndexWrapper)
     4388            res._expr = self
     4389            return res
     4390
     4391    def simplify_indexed(self):
     4392        from sage.symbolic.ring import SR
     4393        return new_Expression_from_GEx(SR, self._gobj.simplify_indexed(0))
     4394
     4395    def get_free_indices(self):
     4396        cdef GExVector vec = self._gobj.get_free_indices()
     4397        return exvector_to_PyTuple(vec)
     4398
    43794399    def _numerical_approx(self, prec=None, digits=None):
    43804400        """
    43814401        Return a numerical approximation this symbolic expression as
  • sage/symbolic/getitem.pxd

    diff --git a/sage/symbolic/getitem.pxd b/sage/symbolic/getitem.pxd
    a b  
    33
    44cdef class OperandsWrapper(SageObject):
    55    cdef Expression _expr
     6
     7cdef class IndexWrapper(SageObject):
     8    cdef Expression _expr
  • sage/symbolic/getitem.pyx

    diff --git a/sage/symbolic/getitem.pyx b/sage/symbolic/getitem.pyx
    a b  
    11###############################################################################
    22#   Sage: Open Source Mathematical Software
    3 #       Copyright (C) 2011 Burcin Erocal <burcin@erocal.org>
     3#       Copyright (C) 2011-2013 Burcin Erocal <burcin@erocal.org>
    44#  Distributed under the terms of the GNU General Public License (GPL),
    55#  version 2 or any later version.  The full text of the GPL is available at:
    66#                  http://www.gnu.org/licenses/
    77###############################################################################
    8 from sage.libs.ginac cimport GEx, GEx_construct_ex
     8from sage.libs.ginac cimport GEx, GEx_construct_ex, GIdx, is_a_idx, ex_to_idx, \
     9    is_a_numeric, py_object_from_numeric, ginac_idx, ginac_indexed_p
    910from sage.symbolic.expression cimport new_Expression_from_GEx
    1011
    1112cdef inline int normalize_index(object arg, int nops, object err_msg) except -1:
     
    5657    """
    5758    return normalize_index(arg, nops, "some error message")
    5859
     60cdef extract_object(object parent, GEx arg):
     61    """
     62    TEST::
     63
     64        sage: ex = x + 1
     65        sage: p = Permutation([2,1,3])
     66        sage: id = ex.ind[p]
     67        sage: id.op[1] # indirect doctest
     68        [2, 1, 3]
     69        sage: id.op[1] is p
     70        True
     71    """
     72    cdef GEx res
     73    if is_a_idx(arg):
     74        res = ex_to_idx(arg).get_value()
     75        if is_a_numeric(res):
     76            return py_object_from_numeric(res)
     77        return new_Expression_from_GEx(parent, res)
     78    return new_Expression_from_GEx(parent, arg)
     79
    5980cdef class OperandsWrapper(SageObject):
    6081    """
    6182    Operands wrapper for symbolic expressions.
     
    129150                    raise ValueError, "step value must be an integer"
    130151            else:
    131152                step = 1
    132             return [new_Expression_from_GEx(self._expr._parent,
     153            return [extract_object(self._expr._parent,
    133154                self._expr._gobj.op(ind)) for ind in xrange(bind, eind, step)]
    134155
    135156
     
    145166                    raise TypeError, "expressions containing only a numeric coefficient, constant or symbol have no operands"
    146167                ind = normalize_index(x, nops, ind_err_msg)
    147168                cur_ex = cur_ex.op(ind)
    148             return new_Expression_from_GEx(self._expr._parent, cur_ex)
     169            return extract_object(self._expr._parent, cur_ex)
    149170
    150171        ind = normalize_index(arg, self._expr._gobj.nops(), ind_err_msg)
    151         return new_Expression_from_GEx(self._expr._parent,
     172        return extract_object(self._expr._parent,
    152173                self._expr._gobj.op(ind))
    153174
    154175    def _repr_(self):
     
    165186        TESTS::
    166187
    167188            sage: latex((x^2).op)
    168             \text{Operands wrapper for expression }x^{2}
     189            \text{Operands of expression }x^{2}
    169190        """
    170         return r"\text{Operands wrapper for expression }%s"%(self._expr._latex_())
     191        return r"\text{Operands of expression }%s"%(self._expr._latex_())
    171192
    172193    def __reduce__(self):
    173194        """
     
    189210        Operands of x^2
    190211    """
    191212    return expr.op
     213
     214cdef object dummy_ind = None
     215
     216cdef object get_dummy_ind_symbol():
     217    global dummy_ind
     218    if dummy_ind is None:
     219        from sage.symbolic.ring import SR
     220        dummy_ind = SR.symbol()
     221    return dummy_ind
     222
     223cdef class IndexWrapper(SageObject):
     224    """
     225    """
     226    def __getitem__(self, arg):
     227        """
     228        argument must be a hashable python object or a slice with variable and
     229        dimension, for example, i:3
     230
     231
     232        TESTS::
     233
     234           sage: t = 1+x+x^2
     235           sage: t.ind[1:]
     236           [x, 1]
     237        """
     238        cdef Expression py_ind, py_dim
     239        cdef GIdx g_ind
     240        if isinstance(arg, tuple):
     241            raise NotImplementedError("don't know what to do with multiple indices yet!")
     242        elif isinstance(arg, slice):
     243            if arg.step:
     244                raise ValueError("only variable and dimension expected in slice")
     245            ind = arg.start
     246            if arg.stop is None: # handle t.ind[1:]
     247                raise ValueError("variable dimension must be specified when using slice syntax")
     248            try:
     249                py_dim = self._expr.coerce_in(arg.stop)
     250            except TypeError:
     251                py_dim = self._expr._parent._force_pyobject(arg.stop)
     252        else:
     253            ind = arg
     254            py_dim = get_dummy_ind_symbol()
     255
     256        try:
     257            py_ind = self._expr.coerce_in(ind)
     258        except TypeError:
     259            py_ind = self._expr._parent._force_pyobject(ind)
     260        g_ind = ginac_idx(py_ind._gobj, py_dim._gobj)
     261        from sage.symbolic.ring import SR
     262        return new_Expression_from_GEx(SR,
     263                ginac_indexed_p(self._expr._gobj, g_ind))
     264
     265    def _repr_(self):
     266        """
     267        TESTS::
     268
     269            sage: (x^2).ind
     270            Index wrapper for expression x^2
     271        """
     272        return "Index wrapper for expression %s"%(self._expr)
     273
     274    def _latex_(self):
     275        r"""
     276        TESTS::
     277
     278            sage: latex((x^2).ind)
     279            \text{Index wrapper for expression }x^{2}
     280        """
     281        return r"\text{Index wrapper for expression }%s"%(self._expr._latex_())
     282
     283    def __reduce__(self):
     284        """
     285        TESTS::
     286
     287            sage: (x^2).ind.__reduce__()
     288            (<built-in function restore_ind_wrapper>, (x^2,))
     289            sage: loads(dumps((x^2).ind))
     290            Index wrapper for expression x^2
     291        """
     292        return restore_op_wrapper, (self._expr,)
     293
     294def restore_ind_wrapper(expr):
     295    """
     296    TESTS::
     297
     298        sage: from sage.symbolic.getitem import restore_op_wrapper
     299        sage: restore_ind_wrapper(x^2)
     300        Index wrapper for expression x^2
     301    """
     302    return expr.ind
  • new file sage/symbolic/pynac.pxd

    diff --git a/sage/symbolic/pynac.pxd b/sage/symbolic/pynac.pxd
    new file mode 100644
    - +  
     1from sage.libs.ginac cimport GExVector
     2
     3cdef public object exvector_to_PyTuple(GExVector seq)