Ticket #12068: trac_12068-numer_denom_ginac-fh.patch

File trac_12068-numer_denom_ginac-fh.patch, 10.6 KB (added by hivert, 10 years ago)
  • sage/libs/ginac/decl.pxi

    # HG changeset patch
    # User Florent Hivert <Florent.Hivert@univ-rouen.fr>
    # Date 1321999338 -3600
    # Node ID b65f8ad495943dd5e8ac6af10fc7fb610ebfe0c1
    # Parent  fcbb634bae62c51df1fa4fc0c2af133cbe47e9f1
    #12068: Numerator for symbolic expression should'nt use maxima
    
    diff --git a/sage/libs/ginac/decl.pxi b/sage/libs/ginac/decl.pxi
    a b cdef extern from "ginac_wrap.h": 
    3636
    3737    object GSymbol_to_str "_to_PyString<symbol>"(GSymbol *s)
    3838
    39     ctypedef struct GExPair "std::pair<ex, ex>"
     39    ctypedef struct GExPair "std::pair<ex, ex>":
     40        pass
    4041    ctypedef struct GExMap "exmap":
    4142        void insert(GExPair e)
    4243
    cdef extern from "ginac_wrap.h": 
    6970        GEx subs_map "subs" (GExMap map) except +
    7071        GEx coeff(GEx expr, int n)    except +
    7172        GEx lcoeff(GEx expr)          except +
    72         GEx tcoeff(GEx expr)          except +       
     73        GEx tcoeff(GEx expr)          except +
     74        GEx numer()                   except +
     75        GEx denom()                   except +
     76        GEx numer_denom()             except +
    7377        int degree(GEx expr)          except +
    7478        int ldegree(GEx expr)         except +
    7579        GEx rhs()                     except +
    cdef extern from "ginac_wrap.h": 
    143147    unsigned info_nonnegint     "GiNaC::info_flags::nonnegint"
    144148    unsigned info_even          "GiNaC::info_flags::even"
    145149    unsigned info_odd           "GiNaC::info_flags::odd"
     150    unsigned info_rational_function "GiNaC::info_flags::rational_function"
    146151
    147152    # Constants
    148153    GEx g_Pi "Pi"
    cdef extern from "ginac_wrap.h": 
    216221    bint is_a_function "is_a<function>" (GEx e)
    217222    bint is_a_ncmul "is_a<ncmul>" (GEx e)
    218223
    219 
    220224    # Arithmetic
    221225    int ginac_error()
    222226    GEx gadd "ADD_WRAP" (GEx left, GEx right) except +
  • sage/symbolic/expression.pyx

    diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
    a b cdef class Expression(CommutativeRingEle 
    18671867        assured that if True or False is returned (and proof is False) then
    18681868        the answer is correct.
    18691869
    1870         INPUT::
     1870        INPUT:
    18711871       
    18721872           ntests -- (default 20) the number of iterations to run
    18731873           domain -- (optional) the domain from which to draw the random values
    cdef class Expression(CommutativeRingEle 
    64156415            ((x - 1)*x + y^2)/(x^2 - 7) + (b + c)/a + 1/(x + 1)
    64166416        """
    64176417        return self.parent()(self._maxima_().combine())
    6418    
    6419     def numerator(self):
    6420         """
    6421         Returns the numerator of this symbolic expression.  If the
    6422         expression is not a quotient, then this will return the
    6423         expression itself.
    6424        
    6425         EXAMPLES::
    6426        
     6418
     6419    def numerator(self, bint normalize = True):
     6420        """
     6421        Returns the numerator of this symbolic expression
     6422
     6423        INPUT:
     6424
     6425        - ``normalize`` -- (default: ``True``) a boolean.
     6426
     6427        If ``normalize`` is ``True``, the expression is first normalized to
     6428        have it as a fraction before getting the numerator.
     6429
     6430        If ``normalize`` is ``False``, the expression is kept and if it is not
     6431        a quotient, then this will return the expression itself.
     6432
     6433        EXAMPLES::
     6434
    64276435            sage: a, x, y = var('a,x,y')
    64286436            sage: f = x*(x-a)/((x^2 - y)*(x-a)); f
    64296437            x/(x^2 - y)
    cdef class Expression(CommutativeRingEle 
    64316439            x
    64326440            sage: f.denominator()
    64336441            x^2 - y
     6442            sage: f.numerator(normalize=False)
     6443            x
     6444            sage: f.denominator(normalize=False)
     6445            x^2 - y
    64346446
    64356447            sage: y = var('y')
    64366448            sage: g = x + y/(x + 2); g
    64376449            x + y/(x + 2)
    64386450            sage: g.numerator()
     6451            x^2 + 2*x + y
     6452            sage: g.denominator()
     6453            x + 2
     6454            sage: g.numerator(normalize=False)
    64396455            x + y/(x + 2)
    6440             sage: g.denominator()
     6456            sage: g.denominator(normalize=False)
    64416457            1
    64426458
    6443         """
    6444         return self.parent()(self._maxima_().num())
    6445 
    6446     def denominator(self):
    6447         """
    6448         Returns the denominator of this symbolic expression.  If the
    6449         expression is not a quotient, then this will just return 1.
    6450        
    6451         EXAMPLES::
    6452        
     6459        TESTS::
     6460
     6461            sage: ((x+y)^2/(x-y)^3*x^3).numerator(normalize=False)
     6462            (x + y)^2*x^3
     6463            sage: ((x+y)^2*x^3).numerator(normalize=False)
     6464            (x + y)^2*x^3
     6465        """
     6466        cdef GExVector vec
     6467        cdef GEx oper, power
     6468        cdef int py_pow
     6469        if normalize:
     6470            return new_Expression_from_GEx(self._parent, self._gobj.numer())
     6471        elif is_a_mul(self._gobj):
     6472            for i from 0 <= i < self._gobj.nops():
     6473                oper = self._gobj.op(i)
     6474                if not is_a_power(oper):
     6475                    vec.push_back(oper)
     6476                else:
     6477                    power = oper.op(1)
     6478                    if not is_a_numeric(power):
     6479                        raise TypeError, "self is not a rational expression"
     6480                    elif py_object_from_numeric(power) >= 0:
     6481                        vec.push_back(oper)
     6482            return new_Expression_from_GEx(self._parent,
     6483                                           g_mul_construct(vec, True))
     6484        else:
     6485            return self
     6486
     6487    def denominator(self, bint normalize=True):
     6488        """
     6489        Returns the denominator of this symbolic expression
     6490
     6491        INPUT:
     6492
     6493        - ``normalize`` -- (default: ``True``) a boolean.
     6494
     6495        If ``normalize`` is ``True``, the expression is first normalized to
     6496        have it as a fraction before getting the denominator.
     6497
     6498        If ``normalize`` is ``False``, the expression is kept and if it is not
     6499        a quotient, then this will just return 1.
     6500
     6501        EXAMPLES::
     6502
    64536503            sage: x, y, z, theta = var('x, y, z, theta')
    64546504            sage: f = (sqrt(x) + sqrt(y) + sqrt(z))/(x^10 - y^10 - sqrt(theta))
     6505            sage: f.numerator()
     6506            sqrt(x) + sqrt(y) + sqrt(z)
    64556507            sage: f.denominator()
     6508            -sqrt(theta) + x^10 - y^10
     6509
     6510            sage: f.numerator(normalize=False)
     6511            -(sqrt(x) + sqrt(y) + sqrt(z))
     6512            sage: f.denominator(normalize=False)
    64566513            sqrt(theta) - x^10 + y^10
    64576514
    64586515            sage: y = var('y')
    64596516            sage: g = x + y/(x + 2); g
    64606517            x + y/(x + 2)
    6461             sage: g.numerator()
     6518            sage: g.numerator(normalize=False)
    64626519            x + y/(x + 2)
    6463             sage: g.denominator()
     6520            sage: g.denominator(normalize=False)
    64646521            1
    6465         """
    6466         return self.parent()(self._maxima_().denom())
     6522
     6523        TESTS::
     6524
     6525            sage: ((x+y)^2/(x-y)^3*x^3).denominator(normalize=False)
     6526            (x - y)^3
     6527            sage: ((x+y)^2*x^3).denominator(normalize=False)
     6528            1
     6529
     6530        """
     6531        cdef GExVector vec
     6532        cdef GEx oper, ex, power
     6533        cdef int py_pow
     6534        if normalize:
     6535            return new_Expression_from_GEx(self._parent, self._gobj.denom())
     6536        elif is_a_mul(self._gobj):
     6537            for i from 0 <= i < self._gobj.nops():
     6538                oper = self._gobj.op(i)
     6539                if is_a_power(oper):
     6540                    ex = oper.op(0)
     6541                    power = oper.op(1)
     6542                    if not is_a_numeric(power):
     6543                        raise TypeError, "self is not a rational expression"
     6544                    else:
     6545                        py_pow = py_object_from_numeric(power)
     6546                        if py_pow == -1:
     6547                            vec.push_back(ex)
     6548                        elif py_pow < 0:
     6549                            vec.push_back(g_pow(ex, g_abs(power)))
     6550            return new_Expression_from_GEx(self._parent,
     6551                                           g_mul_construct(vec, False))
     6552        else:
     6553            return self._parent.one()
     6554
     6555    def numerator_denominator(self, bint normalize=True):
     6556        """
     6557        Returns the numerator and the denominator of this symbolic expression
     6558
     6559        INPUT:
     6560
     6561        - ``normalize`` -- (default: ``True``) a boolean.
     6562
     6563        If ``normalize`` is ``True``, the expression is first normalized to
     6564        have it as a fraction before getting the numerator and denominator.
     6565
     6566        If ``normalize`` is ``False``, the expression is kept and if it is not
     6567        a quotient, then this will return the expression itself together with
     6568        1.
     6569
     6570        EXAMPLE::
     6571
     6572            sage: x, y, a = var("x y a")
     6573            sage: ((x+y)^2/(x-y)^3*x^3).numerator_denominator()
     6574            ((x + y)^2*x^3, (x - y)^3)
     6575
     6576            sage: ((x+y)^2/(x-y)^3*x^3).numerator_denominator(False)
     6577            ((x + y)^2*x^3, (x - y)^3)
     6578
     6579            sage: g = x + y/(x + 2)
     6580            sage: g.numerator_denominator()
     6581            (x^2 + 2*x + y, x + 2)
     6582            sage: g.numerator_denominator(normalize=False)
     6583            (x + y/(x + 2), 1)
     6584
     6585            sage: g = x^2*(x + 2)
     6586            sage: g.numerator_denominator()
     6587            ((x + 2)*x^2, 1)
     6588            sage: g.numerator_denominator(normalize=False)
     6589            ((x + 2)*x^2, 1)
     6590        """
     6591        cdef GExVector vecnum, vecdenom
     6592        cdef GEx oper, ex, power
     6593        cdef int py_pow
     6594        if normalize:
     6595            ex = self._gobj.numer_denom()
     6596            return (new_Expression_from_GEx(self._parent, ex.op(0)),
     6597                    new_Expression_from_GEx(self._parent, ex.op(1)))
     6598        elif is_a_mul(self._gobj):
     6599            for i from 0 <= i < self._gobj.nops():
     6600                oper = self._gobj.op(i)
     6601                if is_a_power(oper):   # oper = ex^power
     6602                    ex = oper.op(0)
     6603                    power = oper.op(1)
     6604                    if not is_a_numeric(power):
     6605                        raise TypeError, "self is not a rational expression"
     6606                    else:
     6607                        py_pow = py_object_from_numeric(power)
     6608                        if py_pow >= 0:
     6609                            vecnum.push_back(oper)
     6610                        elif py_pow == -1:
     6611                            vecdenom.push_back(ex)
     6612                        else:
     6613                            vecdenom.push_back(g_pow(ex, g_abs(power)))
     6614                else:
     6615                    vecnum.push_back(oper)
     6616            return (new_Expression_from_GEx(self._parent,
     6617                                            g_mul_construct(vecnum, False)),
     6618                    new_Expression_from_GEx(self._parent,
     6619                                            g_mul_construct(vecdenom, False)))
     6620        else:
     6621            return (self, self._parent.one())
    64676622
    64686623    def partial_fraction(self, var=None):
    64696624        r"""