Skip to content

Commit

Permalink
Trac #15888: CC -> PARI: return t_REAL for real numbers
Browse files Browse the repository at this point in the history
When converting Sage complex numbers to PARI, we should return a PARI
`t_REAL` if the original number was actually real. This fixes a problem
with `ellwp()` in #15767. In PARI's floating point model, the number
`1e-19 + 0.0*I` has less precision than the real `1e-19`.

It is also consistent with the PARI philosophy of returning simplified
types (examples: `(1.1*I)^2` and `ellj(1.1*I)` in PARI gives real
numbers).

URL: http://trac.sagemath.org/15888
Reported by: jdemeyer
Ticket author(s): Jeroen Demeyer
Reviewer(s): Peter Bruin
  • Loading branch information
Release Manager authored and vbraun committed Mar 13, 2014
2 parents cd7dff2 + 7067299 commit 426c91d
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 10 deletions.
6 changes: 3 additions & 3 deletions src/sage/libs/pari/gen.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -4862,7 +4862,7 @@ cdef class gen(sage.structure.element.RingElement):
-2.18503986326152
sage: C.<i> = ComplexField()
sage: pari(i).tan()
0.E-19 + 0.761594155955765*I
0.761594155955765*I
"""
pari_catch_sig_on()
return P.new_gen(gtan(x.g, prec_bits_to_words(precision)))
Expand All @@ -4882,7 +4882,7 @@ cdef class gen(sage.structure.element.RingElement):
0.761594155955765
sage: C.<i> = ComplexField()
sage: z = pari(i); z
0.E-19 + 1.00000000000000*I
1.00000000000000*I
sage: result = z.tanh()
sage: result.real() <= 1e-18
True
Expand Down Expand Up @@ -4967,7 +4967,7 @@ cdef class gen(sage.structure.element.RingElement):
1.18920711500272 + 0.E-19*I # 32-bit
1.18920711500272 + 2.71050543121376 E-20*I # 64-bit
sage: pari(i).weber(1)
1.09050773266526 + 0.E-19*I
1.09050773266526
sage: pari(i).weber(2)
1.09050773266526
"""
Expand Down
20 changes: 16 additions & 4 deletions src/sage/rings/complex_double.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1054,21 +1054,33 @@ cdef class ComplexDoubleElement(FieldElement):

cdef GEN _gen(self):
cdef GEN y
y = cgetg(3, t_COMPLEX) # allocate space for a complex number
set_gel(y, 1, pari.double_to_GEN(self._complex.dat[0]))
set_gel(y, 2, pari.double_to_GEN(self._complex.dat[1]))
if self._complex.dat[1] == 0:
# Return t_REAL
y = pari.double_to_GEN(self._complex.dat[0])
else:
# Return t_COMPLEX
y = cgetg(3, t_COMPLEX)
if self._complex.dat[0] == 0:
set_gel(y, 1, gen_0)
else:
set_gel(y, 1, pari.double_to_GEN(self._complex.dat[0]))
set_gel(y, 2, pari.double_to_GEN(self._complex.dat[1]))
return y

def _pari_(self):
"""
Return PARI version of ``self``.
Return PARI version of ``self``, as ``t_COMPLEX`` or ``t_REAL``.
EXAMPLES::
sage: CDF(1,2)._pari_()
1.00000000000000 + 2.00000000000000*I
sage: pari(CDF(1,2))
1.00000000000000 + 2.00000000000000*I
sage: pari(CDF(2.0))
2.00000000000000
sage: pari(CDF(I))
1.00000000000000*I
"""
pari_catch_sig_on()
return pari.new_gen(self._gen())
Expand Down
17 changes: 15 additions & 2 deletions src/sage/rings/complex_number.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,8 @@ cdef class ComplexNumber(sage.structure.element.FieldElement):

def _pari_(self):
r"""
Coerces ``self`` into a Pari ``complex`` object.
Coerces ``self`` into a PARI ``t_COMPLEX`` object,
or a ``t_REAL`` if ``self`` is real.
EXAMPLES:
Expand All @@ -553,14 +554,26 @@ cdef class ComplexNumber(sage.structure.element.FieldElement):
sage: a = ComplexNumber(2,1)
sage: pari(a)
2.00000000000000 + 1.00000000000000*I
sage: pari(a).type()
't_COMPLEX'
sage: type(pari(a))
<type 'sage.libs.pari.gen.gen'>
sage: a._pari_()
2.00000000000000 + 1.00000000000000*I
sage: type(a._pari_())
<type 'sage.libs.pari.gen.gen'>
sage: a = CC(pi)
sage: pari(a)
3.14159265358979
sage: pari(a).type()
't_REAL'
sage: a = CC(-2).sqrt()
sage: pari(a)
1.41421356237310*I
"""
return sage.libs.pari.all.pari.complex(self.real()._pari_(), self.imag()._pari_())
if self.is_real():
return self.real()._pari_()
return sage.libs.pari.all.pari.complex(self.real() or 0, self.imag())

def _mpmath_(self, prec=None, rounding=None):
"""
Expand Down
2 changes: 1 addition & 1 deletion src/sage/schemes/elliptic_curves/heegner.py
Original file line number Diff line number Diff line change
Expand Up @@ -3152,7 +3152,7 @@ def numerical_approx(self, prec=53, algorithm=None):
sage: E = EllipticCurve('37a'); P = E.heegner_point(-40); P
Heegner point of discriminant -40 on elliptic curve of conductor 37
sage: P.numerical_approx()
(-6.68...e-16 + 1.41421356237310*I : 1.00000000000000 - 1.41421356237309*I : 1.00000000000000)
(-6.6...e-16 + 1.41421356237310*I : 1.00000000000000 - 1.41421356237309*I : 1.00000000000000)
A rank 2 curve, where all Heegner points of conductor 1 are 0::
Expand Down

0 comments on commit 426c91d

Please sign in to comment.