From e1a90393ca47a2f057cd43231b8f67ec05443748 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Fri, 5 Dec 2014 10:23:33 +0100 Subject: [PATCH] 16203: implement ex.series_variable; disallow ex.series conversion into mismatched PowerSeries ring element --- src/sage/rings/power_series_ring.py | 26 ++++++++++++++------------ src/sage/symbolic/expression.pyx | 23 ++++++++++++++++++++++- src/sage/symbolic/ginac.pxd | 1 + src/sage/symbolic/ginac_wrap.h | 7 +++++++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/sage/rings/power_series_ring.py b/src/sage/rings/power_series_ring.py index 8dd4cdd967e..9277b316b7b 100644 --- a/src/sage/rings/power_series_ring.py +++ b/src/sage/rings/power_series_ring.py @@ -698,17 +698,16 @@ def _element_constructor_(self, f, prec=infinity, check=True): Conversion from symbolic series:: + sage: x,y = var('x,y') + sage: s=(1/(1-x)).series(x,3); s + 1 + 1*x + 1*x^2 + Order(x^3) sage: R. = PowerSeriesRing(QQ) - sage: y=var('y') - sage: ex=(1/(1-y)).series(y,6); R(ex) - 1 + x + x^2 + x^3 + x^4 + x^5 + O(x^6) - sage: ex=(sin(y)).series(y,6); R(ex) - x - 1/6*x^3 + 1/120*x^5 + O(x^6) - sage: R. = PowerSeriesRing(SR) - sage: ex=(log(2-y)).series(y,4); R(ex) - log(2) - 1/2*x - 1/8*x^2 - 1/24*x^3 + O(x^4) - sage: ex=(gamma(1-y)).series(y,3); R(ex) - 1 + euler_gamma*x + (1/2*euler_gamma^2 + 1/12*pi^2)*x^2 + O(x^3) + sage: R(s) + 1 + x + x^2 + O(x^3) + sage: ex=(gamma(1-y)).series(y,3) + sage: R. = PowerSeriesRing(SR) + sage: R(ex) + 1 + euler_gamma*y + (1/2*euler_gamma^2 + 1/12*pi^2)*y^2 + O(y^3) Laurent series with non-negative valuation are accepted (see :trac:`6431`):: @@ -740,8 +739,11 @@ def _element_constructor_(self, f, prec=infinity, check=True): den = self.element_class(self, f.denominator(), prec, check=check) return self.coerce(num/den) elif isinstance(f, Expression) and f.is_series(): - return self.element_class(self, f.list(), - f.degree(f.default_variable()), check=check) + if str(f.series_variable()) is self.variable_name(): + return self.element_class(self, f.list(), + f.degree(f.series_variable()), check=check) + else: + raise TypeError("Can only convert series into ring with same variable name.") return self.element_class(self, f, prec, check=check) def construction(self): diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 762a02924cc..a158ec44c4a 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -3560,7 +3560,28 @@ cdef class Expression(CommutativeRingElement): finally: sig_off() return new_Expression_from_GEx(self._parent, x) - + + def series_variable(self): + """ + Return the expansion variable of this symbolic series. + + EXAMPLES:: + + sage: s=(1/(1-x)).series(x,3); s + 1 + 1*x + 1*x^2 + Order(x^3) + sage: s.series_variable() + x + sage: x.series_variable() + Traceback (most recent call last): + ... + TypeError: Not a series. + """ + cdef GEx x = g_series_var(self._gobj) + cdef Expression ex = new_Expression_from_GEx(self._parent, x) + if ex.is_zero(): + raise TypeError("Not a series.") + return ex + def residue(self, symbol): """ Calculate the residue of ``self`` with respect to ``symbol``. diff --git a/src/sage/symbolic/ginac.pxd b/src/sage/symbolic/ginac.pxd index 29aef54e8b2..dd78dfe40b6 100644 --- a/src/sage/symbolic/ginac.pxd +++ b/src/sage/symbolic/ginac.pxd @@ -133,6 +133,7 @@ cdef extern from "ginac_wrap.h": bint is_a_series "is_a" (GEx e) # you must ensure that is_a_series(e) is true before calling this: bint g_is_a_terminating_series(GEx e) except + + GEx g_series_var(GEx e) except + # Relations ctypedef enum operators "relational::operators": diff --git a/src/sage/symbolic/ginac_wrap.h b/src/sage/symbolic/ginac_wrap.h index ee8f89ea450..520a551c628 100644 --- a/src/sage/symbolic/ginac_wrap.h +++ b/src/sage/symbolic/ginac_wrap.h @@ -76,6 +76,13 @@ bool g_is_a_terminating_series(const ex& e) { return false; } +ex g_series_var(const ex& e) { + if (is_a(e)) { + return (ex_to(e)).get_var(); + } + return NULL; +} + relational::operators relational_operator(const ex& e) { // unsafe cast -- be damn sure the input is a relational. return (ex_to(e)).the_operator();