Skip to content

Commit 98b609b

Browse files
Release Managervbraun
Release Manager
authored andcommitted
Trac #25218: Extract roots in NumberField if possible
!NumberField previously evaluated integral powers in the !NumberField, and evaluated all fractional powers in the symbolic ring. This patch makes !NumberField attempt to evaluate the fractional power within the field, and only falls back on the symbolic ring if this fails. There's a few interesting changes in the test suite. Old code: {{{ sage: QQbar((2*I)^(1/2)) 1 + 1*I sage: (2*I)^(1/2) sqrt(2*I) sage: I^(2/3) I^(2/3) }}} New code: {{{ sage: QQbar((2*I)^(1/2)) I + 1 sage: (2*I)^(1/2) I + 1 sage: I^(2/3) -1 }}} The first change is just cosmetic. The second makes good sense, as Sage is now evaluating an expression it didn't before. The third change is more troubling. The explanation lies in the definition of I: {{{ sage: I.parent() Symbolic Ring sage: I.pyobject().parent() Number Field in I with defining polynomial x^2 + 1 }}} In this number field, there is a single cube root of `I` (`-I`). Squaring `-I` gives us `-1`, so `I^(2/3)=-1`. My opinion is that the new behavior of !NumberField is correct and preferred, but perhaps `I` should be defined in QQbar, not in a !NumberField. URL: https://trac.sagemath.org/25218 Reported by: gh-BrentBaccala Ticket author(s): Brent Baccala Reviewer(s): Sébastien Labbé
2 parents db3b41b + 17b93d6 commit 98b609b

File tree

3 files changed

+40
-27
lines changed

3 files changed

+40
-27
lines changed

src/sage/rings/number_field/number_field_element.pyx

+36-23
Original file line numberDiff line numberDiff line change
@@ -2179,8 +2179,12 @@ cdef class NumberFieldElement(FieldElement):
21792179
sage: (1+sqrt2)^-1
21802180
sqrt2 - 1
21812181
2182-
If the exponent is not integral, perform this operation in
2183-
the symbolic ring::
2182+
If the exponent is not integral, attempt this operation in the NumberField:
2183+
2184+
sage: K(2)^(1/2)
2185+
sqrt2
2186+
2187+
If this fails, perform this operation in the symbolic ring::
21842188
21852189
sage: sqrt2^(1/5)
21862190
2^(1/10)
@@ -2213,29 +2217,38 @@ cdef class NumberFieldElement(FieldElement):
22132217
if (isinstance(base, NumberFieldElement) and
22142218
(isinstance(exp, Integer) or type(exp) is int or exp in ZZ)):
22152219
return generic_power(base, exp)
2216-
else:
2217-
cbase, cexp = canonical_coercion(base, exp)
2218-
if not isinstance(cbase, NumberFieldElement):
2219-
return cbase ** cexp
2220-
# Return a symbolic expression.
2221-
# We use the hold=True keyword argument to prevent the
2222-
# symbolics library from trying to simplify this expression
2223-
# again. This would lead to infinite loops otherwise.
2224-
from sage.symbolic.ring import SR
2220+
2221+
if (isinstance(base, NumberFieldElement) and exp in QQ):
2222+
qqexp = QQ(exp)
2223+
n = qqexp.numerator()
2224+
d = qqexp.denominator()
22252225
try:
2226-
res = QQ(base)**QQ(exp)
2227-
except TypeError:
2226+
return base.nth_root(d)**n
2227+
except ValueError:
22282228
pass
2229-
else:
2230-
if res.parent() is not SR:
2231-
return parent(cbase)(res)
2232-
return res
2233-
sbase = SR(base)
2234-
if sbase.operator() is operator.pow:
2235-
nbase, pexp = sbase.operands()
2236-
return nbase.power(pexp * exp, hold=True)
2237-
else:
2238-
return sbase.power(exp, hold=True)
2229+
2230+
cbase, cexp = canonical_coercion(base, exp)
2231+
if not isinstance(cbase, NumberFieldElement):
2232+
return cbase ** cexp
2233+
# Return a symbolic expression.
2234+
# We use the hold=True keyword argument to prevent the
2235+
# symbolics library from trying to simplify this expression
2236+
# again. This would lead to infinite loops otherwise.
2237+
from sage.symbolic.ring import SR
2238+
try:
2239+
res = QQ(base)**QQ(exp)
2240+
except TypeError:
2241+
pass
2242+
else:
2243+
if res.parent() is not SR:
2244+
return parent(cbase)(res)
2245+
return res
2246+
sbase = SR(base)
2247+
if sbase.operator() is operator.pow:
2248+
nbase, pexp = sbase.operands()
2249+
return nbase.power(pexp * exp, hold=True)
2250+
else:
2251+
return sbase.power(exp, hold=True)
22392252

22402253
cdef void _reduce_c_(self):
22412254
"""

src/sage/symbolic/expression.pyx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1461,7 +1461,7 @@ cdef class Expression(CommutativeRingElement):
14611461
sage: AA(-golden_ratio)
14621462
-1.618033988749895?
14631463
sage: QQbar((2*I)^(1/2))
1464-
1 + 1*I
1464+
I + 1
14651465
sage: QQbar(e^(pi*I/3))
14661466
0.50000000000000000? + 0.866025403784439?*I
14671467
@@ -3902,11 +3902,11 @@ cdef class Expression(CommutativeRingElement):
39023902
sage: I^(1/2)
39033903
sqrt(I)
39043904
sage: I^(2/3)
3905-
I^(2/3)
3905+
-1
39063906
sage: 2^(1/2)
39073907
sqrt(2)
39083908
sage: (2*I)^(1/2)
3909-
sqrt(2*I)
3909+
I + 1
39103910
39113911
Test if we can take powers of elements of `\QQ(i)` (:trac:`8659`)::
39123912

src/sage/symbolic/expression_conversions.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,7 @@ def algebraic(ex, field):
10581058
sage: AA(-golden_ratio)
10591059
-1.618033988749895?
10601060
sage: QQbar((2*I)^(1/2))
1061-
1 + 1*I
1061+
I + 1
10621062
sage: QQbar(e^(pi*I/3))
10631063
0.50000000000000000? + 0.866025403784439?*I
10641064

0 commit comments

Comments
 (0)