# HG changeset patch
# User Burcin Erocal <burcin@erocal.org>
# Date 1322058047 -3600
# Node ID 962a20a747e5fcde890a2784a9080e621cb5b296
# Parent 9e40411f399429b70f52efd848c0cf8dd7f5350d
trac 12068: denominator() for symbolic expressions recognizes more cases
diff --git a/sage/libs/ginac/decl.pxi b/sage/libs/ginac/decl.pxi
a
|
b
|
|
89 | 89 | |
90 | 90 | GExPair make_pair "std::make_pair" (GEx, GEx) |
91 | 91 | |
| 92 | ctypedef struct GNumeric "numeric": |
| 93 | bint is_positive() except + |
| 94 | bint is_negative() except + |
| 95 | |
92 | 96 | # Numericals |
93 | 97 | bint is_a_numeric "is_a<numeric>" (GEx e) |
| 98 | GNumeric ex_to_numeric "ex_to<numeric>" (GEx e) |
94 | 99 | # given a GEx that is known to be a numeric, return reference to |
95 | 100 | # the underlying PyObject*. |
96 | 101 | object py_object_from_numeric(GEx e) except + |
diff --git a/sage/symbolic/expression.pyx b/sage/symbolic/expression.pyx
a
|
b
|
|
6462 | 6462 | (x + y)^2*x^3 |
6463 | 6463 | sage: ((x+y)^2*x^3).numerator(normalize=False) |
6464 | 6464 | (x + y)^2*x^3 |
| 6465 | sage: (y/x^3).numerator(normalize=False) |
| 6466 | y |
| 6467 | sage: t = y/x^3/(x+y)^(1/2); t |
| 6468 | y/(sqrt(x + y)*x^3) |
| 6469 | sage: t.numerator(normalize=False) |
| 6470 | y |
| 6471 | sage: (1/x^3).numerator(normalize=False) |
| 6472 | 1 |
| 6473 | sage: (x^3).numerator(normalize=False) |
| 6474 | x^3 |
| 6475 | sage: (y*x^sin(x)).numerator(normalize=False) |
| 6476 | Traceback (most recent call last): |
| 6477 | ... |
| 6478 | TypeError: self is not a rational expression |
6465 | 6479 | """ |
6466 | 6480 | cdef GExVector vec |
6467 | 6481 | cdef GEx oper, power |
6468 | | cdef int py_pow |
6469 | 6482 | if normalize: |
6470 | 6483 | return new_Expression_from_GEx(self._parent, self._gobj.numer()) |
6471 | 6484 | elif is_a_mul(self._gobj): |
… |
… |
|
6477 | 6490 | power = oper.op(1) |
6478 | 6491 | if not is_a_numeric(power): |
6479 | 6492 | raise TypeError, "self is not a rational expression" |
6480 | | elif py_object_from_numeric(power) >= 0: |
| 6493 | elif ex_to_numeric(power).is_positive(): |
6481 | 6494 | vec.push_back(oper) |
6482 | 6495 | return new_Expression_from_GEx(self._parent, |
6483 | 6496 | g_mul_construct(vec, True)) |
6484 | | else: |
6485 | | return self |
| 6497 | elif is_a_power(self._gobj): |
| 6498 | power = self._gobj.op(1) |
| 6499 | if is_a_numeric(power) and ex_to_numeric(power).is_negative(): |
| 6500 | return self._parent.one() |
| 6501 | return self |
6486 | 6502 | |
6487 | 6503 | def denominator(self, bint normalize=True): |
6488 | 6504 | """ |
… |
… |
|
6526 | 6542 | (x - y)^3 |
6527 | 6543 | sage: ((x+y)^2*x^3).denominator(normalize=False) |
6528 | 6544 | 1 |
6529 | | |
| 6545 | sage: (y/x^3).denominator(normalize=False) |
| 6546 | x^3 |
| 6547 | sage: t = y/x^3/(x+y)^(1/2); t |
| 6548 | y/(sqrt(x + y)*x^3) |
| 6549 | sage: t.denominator(normalize=False) |
| 6550 | sqrt(x + y)*x^3 |
| 6551 | sage: (1/x^3).denominator(normalize=False) |
| 6552 | x^3 |
| 6553 | sage: (x^3).denominator(normalize=False) |
| 6554 | 1 |
| 6555 | sage: (y*x^sin(x)).denominator(normalize=False) |
| 6556 | Traceback (most recent call last): |
| 6557 | ... |
| 6558 | TypeError: self is not a rational expression |
6530 | 6559 | """ |
6531 | 6560 | cdef GExVector vec |
6532 | 6561 | cdef GEx oper, ex, power |
6533 | | cdef int py_pow |
6534 | 6562 | if normalize: |
6535 | 6563 | return new_Expression_from_GEx(self._parent, self._gobj.denom()) |
6536 | 6564 | elif is_a_mul(self._gobj): |
… |
… |
|
6541 | 6569 | power = oper.op(1) |
6542 | 6570 | if not is_a_numeric(power): |
6543 | 6571 | 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))) |
| 6572 | elif ex_to_numeric(power).is_negative(): |
| 6573 | vec.push_back(g_pow(ex, g_abs(power))) |
6550 | 6574 | return new_Expression_from_GEx(self._parent, |
6551 | 6575 | g_mul_construct(vec, False)) |
6552 | | else: |
6553 | | return self._parent.one() |
| 6576 | elif is_a_power(self._gobj): |
| 6577 | power = self._gobj.op(1) |
| 6578 | if is_a_numeric(power) and ex_to_numeric(power).is_negative(): |
| 6579 | return new_Expression_from_GEx(self._parent, |
| 6580 | g_pow(self._gobj.op(0), g_abs(power))) |
| 6581 | |
| 6582 | return self._parent.one() |
6554 | 6583 | |
6555 | 6584 | def numerator_denominator(self, bint normalize=True): |
6556 | 6585 | """ |