Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Utilities for Sage-mpmath interaction
Also patches some mpmath functions for speed """ from __future__ import print_function, absolute_import
from sage.ext.stdsage cimport PY_NEW
from sage.rings.integer cimport Integer from sage.rings.real_mpfr cimport RealNumber from sage.rings.complex_number cimport ComplexNumber from sage.structure.element cimport Element
from sage.libs.mpfr cimport * from sage.libs.gmp.all cimport *
from sage.rings.complex_field import ComplexField from sage.rings.real_mpfr cimport RealField
cpdef int bitcount(n): """ Bitcount of a Sage Integer or Python int/long.
EXAMPLES::
sage: from mpmath.libmp import bitcount sage: bitcount(0) 0 sage: bitcount(1) 1 sage: bitcount(100) 7 sage: bitcount(-100) 7 sage: bitcount(2r) 2 sage: bitcount(2L) 2
""" cdef Integer m else:
cpdef isqrt(n): """ Square root (rounded to floor) of a Sage Integer or Python int/long. The result is a Sage Integer.
EXAMPLES::
sage: from mpmath.libmp import isqrt sage: isqrt(0) 0 sage: isqrt(100) 10 sage: isqrt(10) 3 sage: isqrt(10r) 3 sage: isqrt(10L) 3
""" cdef Integer m, y else: raise ValueError("square root of negative integer not defined.")
cpdef from_man_exp(man, exp, long prec = 0, str rnd = 'd'): """ Create normalized mpf value tuple from mantissa and exponent.
With prec > 0, rounds the result in the desired direction if necessary.
EXAMPLES::
sage: from mpmath.libmp import from_man_exp sage: from_man_exp(-6, -1) (1, 3, 0, 2) sage: from_man_exp(-6, -1, 1, 'd') (1, 1, 1, 1) sage: from_man_exp(-6, -1, 1, 'u') (1, 1, 2, 1) """ cdef Integer res cdef long bc else:
cpdef normalize(long sign, Integer man, exp, long bc, long prec, str rnd): """ Create normalized mpf value tuple from full list of components.
EXAMPLES::
sage: from mpmath.libmp import normalize sage: normalize(0, 4, 5, 3, 53, 'n') (0, 1, 7, 1) """ cdef long shift cdef Integer res cdef unsigned long trail else: if sign: mpz_cdiv_q_2exp(res.value, man.value, shift) else: mpz_fdiv_q_2exp(res.value, man.value, shift) else: # Strip trailing bits
cdef mpfr_from_mpfval(mpfr_t res, tuple x): """ Set value of an MPFR number (in place) to that of a given mpmath mpf data tuple. """ cdef int sign cdef Integer man cdef long exp cdef long bc else:
cdef mpfr_to_mpfval(mpfr_t value): """ Given an MPFR value, return an mpmath mpf data tuple representing the same number. """ else: cdef unsigned long trailing
def mpmath_to_sage(x, prec): """ Convert any mpmath number (mpf or mpc) to a Sage RealNumber or ComplexNumber of the given precision.
EXAMPLES::
sage: import sage.libs.mpmath.all as a sage: a.mpmath_to_sage(a.mpf('2.5'), 53) 2.50000000000000 sage: a.mpmath_to_sage(a.mpc('2.5','-3.5'), 53) 2.50000000000000 - 3.50000000000000*I sage: a.mpmath_to_sage(a.mpf('inf'), 53) +infinity sage: a.mpmath_to_sage(a.mpf('-inf'), 53) -infinity sage: a.mpmath_to_sage(a.mpf('nan'), 53) NaN sage: a.mpmath_to_sage(a.mpf('0'), 53) 0.000000000000000
A real example::
sage: RealField(100)(pi) 3.1415926535897932384626433833 sage: t = RealField(100)(pi)._mpmath_(); t mpf('3.1415926535897932') sage: a.mpmath_to_sage(t, 100) 3.1415926535897932384626433833
We can ask for more precision, but the result is undefined::
sage: a.mpmath_to_sage(t, 140) # random 3.1415926535897932384626433832793333156440 sage: ComplexField(140)(pi) 3.1415926535897932384626433832795028841972
A complex example::
sage: ComplexField(100)([0, pi]) 3.1415926535897932384626433833*I sage: t = ComplexField(100)([0, pi])._mpmath_(); t mpc(real='0.0', imag='3.1415926535897932') sage: sage.libs.mpmath.all.mpmath_to_sage(t, 100) 3.1415926535897932384626433833*I
Again, we can ask for more precision, but the result is undefined::
sage: sage.libs.mpmath.all.mpmath_to_sage(t, 140) # random 3.1415926535897932384626433832793333156440*I sage: ComplexField(140)([0, pi]) 3.1415926535897932384626433832795028841972*I """ cdef RealNumber y cdef ComplexNumber z else: raise TypeError("cannot convert %r to Sage", x)
def sage_to_mpmath(x, prec): """ Convert any Sage number that can be coerced into a RealNumber or ComplexNumber of the given precision into an mpmath mpf or mpc. Integers are currently converted to int.
Lists, tuples and dicts passed as input are converted recursively.
EXAMPLES::
sage: import sage.libs.mpmath.all as a sage: a.mp.dps = 15 sage: print(a.sage_to_mpmath(2/3, 53)) 0.666666666666667 sage: print(a.sage_to_mpmath(2./3, 53)) 0.666666666666667 sage: print(a.sage_to_mpmath(3+4*I, 53)) (3.0 + 4.0j) sage: print(a.sage_to_mpmath(1+pi, 53)) 4.14159265358979 sage: a.sage_to_mpmath(infinity, 53) mpf('+inf') sage: a.sage_to_mpmath(-infinity, 53) mpf('-inf') sage: a.sage_to_mpmath(NaN, 53) mpf('nan') sage: a.sage_to_mpmath(0, 53) 0 sage: a.sage_to_mpmath([0.5, 1.5], 53) [mpf('0.5'), mpf('1.5')] sage: a.sage_to_mpmath((0.5, 1.5), 53) (mpf('0.5'), mpf('1.5')) sage: a.sage_to_mpmath({'n':0.5}, 53) {'n': mpf('0.5')}
""" cdef RealNumber y else: else:
def call(func, *args, **kwargs): """ Call an mpmath function with Sage objects as inputs and convert the result back to a Sage real or complex number.
By default, a RealNumber or ComplexNumber with the current working precision of mpmath (mpmath.mp.prec) will be returned.
If prec=n is passed among the keyword arguments, the temporary working precision will be set to n and the result will also have this precision.
If parent=P is passed, P.prec() will be used as working precision and the result will be coerced to P (or the corresponding complex field if necessary).
Arguments should be Sage objects that can be coerced into RealField or ComplexField elements. Arguments may also be tuples, lists or dicts (which are converted recursively), or any type that mpmath understands natively (e.g. Python floats, strings for options).
EXAMPLES::
sage: import sage.libs.mpmath.all as a sage: a.mp.prec = 53 sage: a.call(a.erf, 3+4*I) -120.186991395079 - 27.7503372936239*I sage: a.call(a.polylog, 2, 1/3+4/5*I) 0.153548951541433 + 0.875114412499637*I sage: a.call(a.barnesg, 3+4*I) -0.000676375932234244 - 0.0000442236140124728*I sage: a.call(a.barnesg, -4) 0.000000000000000 sage: a.call(a.hyper, [2,3], [4,5], 1/3) 1.10703578162508 sage: a.call(a.hyper, [2,3], [4,(2,3)], 1/3) 1.95762943509305 sage: a.call(a.quad, a.erf, [0,1]) 0.486064958112256 sage: a.call(a.gammainc, 3+4*I, 2/3, 1-pi*I, prec=100) -274.18871130777160922270612331 + 101.59521032382593402947725236*I sage: x = (3+4*I).n(100) sage: y = (2/3).n(100) sage: z = (1-pi*I).n(100) sage: a.call(a.gammainc, x, y, z, prec=100) -274.18871130777160922270612331 + 101.59521032382593402947725236*I sage: a.call(a.erf, infinity) 1.00000000000000 sage: a.call(a.erf, -infinity) -1.00000000000000 sage: a.call(a.gamma, infinity) +infinity sage: a.call(a.polylog, 2, 1/2, parent=RR) 0.582240526465012 sage: a.call(a.polylog, 2, 2, parent=RR) 2.46740110027234 - 2.17758609030360*I sage: a.call(a.polylog, 2, 1/2, parent=RealField(100)) 0.58224052646501250590265632016 sage: a.call(a.polylog, 2, 2, parent=RealField(100)) 2.4674011002723396547086227500 - 2.1775860903036021305006888982*I sage: a.call(a.polylog, 2, 1/2, parent=CC) 0.582240526465012 sage: type(_) <type 'sage.rings.complex_number.ComplexNumber'> sage: a.call(a.polylog, 2, 1/2, parent=RDF) 0.5822405264650125 sage: type(_) <type 'sage.rings.real_double.RealDoubleElement'>
Check that :trac:`11885` is fixed::
sage: a.call(a.ei, 1.0r, parent=float) 1.8951178163559366
Check that :trac:`14984` is fixed::
sage: a.call(a.log, -1.0r, parent=float) 3.141592653589793j
""" pass finally: else: raise TypeError(error) |