Skip to content

Commit

Permalink
Trac #2567: import MPFR_PREC_MAX from mpfr.h instead of hard coding i…
Browse files Browse the repository at this point in the history
…t to the 32 bit limit

The discussion below is besides the point. The main issue is that we
define MPFR_PREC_MAX in Sage's sources instead of pulling it in from
mpfr.h. We do hard code the 32 bit value, so on 64 bit boxen we limit
the user to much lower precision than is actually technically feasible
as pointed out below.

Cheers,

Michael

{{{
> >  CODE:
>
> >  s = pi.str(3000000*log(10,2))
> >  o = open('/Users/ericahls/Desktop/file.txt','w')
> >  o.write(str(s))
> >  o.close()
>
> >  --- Trying to get out to the farthest decimal point of PI I can.
>
> >  Error message:
>
> >  Traceback (most recent call last):    o.write(str(s))
> >   File "/Applications/sage/local/lib/python2.5/site-packages/sage/
> >  functions/functions.py", line 140, in str
> >     raise ValueError, "Number of bits must be at most 2^23."
> >  ValueError: Number of bits must be at most 2^23.
>
> >  ----If i Put 2000000 instead 0f 3000000 the equation works.  much
over
> >  2 million the equation breaks dwon.
>
> I think that 2^23 is a bound in mpfr, and Sage uses mpfr to
> compute digits of pi.  I don't know if one can compute more than
> about 2^23 digits using mpfr.
>
> William

Yes we can. The issue was that MPFR used the stack instead of the heap
for certain operations [even when told not to use alloca] and would
smash it therefore with large number of digits. That has been fixed in
MPFR 2.3.1 (which we include) and all we need to do is to raise or
remove the limit in our code and do some testing. Care to open a
ticket?

 -- Mabshoff
}}}

URL: https://trac.sagemath.org/2567
Reported by: was
Ticket author(s): Mike Hansen, Frédéric Chapoton
Reviewer(s): Paul Zimmermann, François Bissey
  • Loading branch information
Release Manager committed Dec 28, 2020
2 parents 50b1b1c + e49e83e commit d59a558
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 25 deletions.
6 changes: 3 additions & 3 deletions src/sage/rings/real_mpfr.pxd
Expand Up @@ -3,12 +3,12 @@ from sage.libs.mpfr.types cimport mpfr_rnd_t, mpfr_t
cimport sage.rings.ring
cimport sage.structure.element
from cypari2.types cimport GEN

from sage.libs.mpfr.types cimport mpfr_prec_t

cdef class RealNumber(sage.structure.element.RingElement) # forward decl

cdef class RealField_class(sage.rings.ring.Field):
cdef int __prec
cdef mpfr_prec_t __prec
cdef bint sci_not
cdef mpfr_rnd_t rnd
cdef object rnd_str
Expand All @@ -28,4 +28,4 @@ cdef class RealNumber(sage.structure.element.RingElement):
cdef _set_from_GEN_REAL(self, GEN g)
cdef RealNumber abs(RealNumber self)

cpdef RealField(int prec=*, int sci_not=*, rnd=*)
cpdef RealField(mpfr_prec_t prec=*, int sci_not=*, rnd=*)
47 changes: 25 additions & 22 deletions src/sage/rings/real_mpfr.pyx
Expand Up @@ -208,32 +208,36 @@ def mpfr_prec_min():
3.0
sage: R(4) + R(1)
4.0
sage: R = RealField(0)
Traceback (most recent call last):
...
ValueError: prec (=0) must be >= 1 and <= 2147483391
ValueError: prec (=0) must be >= 1 and <= ...
"""
return MPFR_PREC_MIN

# see Trac #11666 for the origin of this magical constant
cdef int MY_MPFR_PREC_MAX = 2147483647 - 256 # = 2^31-257
def mpfr_prec_max():
"""
TESTS::
Return the mpfr variable ``MPFR_PREC_MAX``.
EXAMPLES::
sage: from sage.rings.real_mpfr import mpfr_prec_max
sage: mpfr_prec_max()
2147483391
sage: R = RealField(2^31-257)
sage: R
2147483391 # 32-bit
9223372036854775551 # 64-bit
sage: R = RealField(2^31-257); R
Real Field with 2147483391 bits of precision
sage: R = RealField(2^31-256)
Traceback (most recent call last):
...
ValueError: prec (=2147483392) must be >= 1 and <= 2147483391
Traceback (most recent call last): # 32-bit
... # 32-bit
ValueError: prec (=...) must be >= 1 and <= ... # 32-bit
"""
global MY_MPFR_PREC_MAX
return MY_MPFR_PREC_MAX
return MPFR_PREC_MAX


def mpfr_get_exp_min():
"""
Expand Down Expand Up @@ -372,7 +376,7 @@ cdef double LOG_TEN_TWO_PLUS_EPSILON = 3.321928094887363 # a small overestimate

cdef object RealField_cache = sage.misc.weak_dict.WeakValueDictionary()

cpdef RealField(int prec=53, int sci_not=0, rnd=MPFR_RNDN):
cpdef RealField(mpfr_prec_t prec=53, int sci_not=0, rnd=MPFR_RNDN):
"""
RealField(prec, sci_not, rnd):
Expand Down Expand Up @@ -461,7 +465,7 @@ cdef class RealField_class(sage.rings.ring.Field):
See the documentation for the module :mod:`sage.rings.real_mpfr` for more
details.
"""
def __init__(self, int prec=53, int sci_not=0, long rnd=MPFR_RNDN):
def __init__(self, mpfr_prec_t prec=53, int sci_not=0, long rnd=MPFR_RNDN):
"""
Initialize ``self``.
Expand Down Expand Up @@ -520,10 +524,9 @@ cdef class RealField_class(sage.rings.ring.Field):
sage: RealField(10).is_finite()
False
"""
global MY_MPFR_PREC_MAX
if prec < MPFR_PREC_MIN or prec > MY_MPFR_PREC_MAX:
if prec < MPFR_PREC_MIN or prec > MPFR_PREC_MAX:
raise ValueError("prec (=%s) must be >= %s and <= %s" % (
prec, MPFR_PREC_MIN, MY_MPFR_PREC_MAX))
prec, MPFR_PREC_MIN, MPFR_PREC_MAX))
self.__prec = prec
self.sci_not = sci_not

Expand Down Expand Up @@ -991,7 +994,7 @@ cdef class RealField_class(sage.rings.ring.Field):
sage: RealField(20).precision()
20
"""
return self.__prec
return Integer(self.__prec)

prec=precision # an alias

Expand Down Expand Up @@ -2305,7 +2308,7 @@ cdef class RealNumber(sage.structure.element.RingElement):
if sgn == 0:
return z

cdef int prec = (<RealField_class>self._parent).__prec
cdef mpfr_prec_t prec = (<RealField_class>self._parent).__prec

if mpfr_inf_p(self.value):
mpz_set_ui(z.value, EXP_MAX+1-EXP_MIN)
Expand Down Expand Up @@ -2675,7 +2678,7 @@ cdef class RealNumber(sage.structure.element.RingElement):
sage: RealField(101)(-1).precision()
101
"""
return (<RealField_class>self._parent).__prec
return Integer((<RealField_class>self._parent).__prec)

prec = precision # alias

Expand Down Expand Up @@ -3277,7 +3280,7 @@ cdef class RealNumber(sage.structure.element.RingElement):
# wordsize for PARI
cdef unsigned long wordsize = sizeof(long)*8

cdef int prec
cdef mpfr_prec_t prec
prec = (<RealField_class>self._parent).__prec

# We round up the precision to the nearest multiple of wordsize.
Expand Down Expand Up @@ -3613,7 +3616,7 @@ cdef class RealNumber(sage.structure.element.RingElement):
from .real_mpfi import RealIntervalField

cdef mpfr_rnd_t rnd = (<RealField_class>self._parent).rnd
cdef int prec = (<RealField_class>self._parent).__prec
cdef mpfr_prec_t prec = (<RealField_class>self._parent).__prec

cdef RealNumber low, high
cdef int odd
Expand Down Expand Up @@ -5553,7 +5556,7 @@ cdef class RealNumber(sage.structure.element.RingElement):

from .real_mpfi import RealIntervalField

cdef int prec = fld.__prec + 10
cdef mpfr_prec_t prec = fld.__prec + 10

cdef RealNumber lower
cdef RealNumber upper
Expand Down

0 comments on commit d59a558

Please sign in to comment.