Ticket #9566: mpmath_call.patch

File mpmath_call.patch, 5.0 KB (added by fredrik.johansson, 11 years ago)
  • sage/libs/mpmath/utils.pyx

    # HG changeset patch
    # User Fredrik Johansson <fredrik.johansson@gmail.com>
    # Date 1279734121 -7200
    # Node ID b0c9f1044971db2e28e430a826abaad08838822f
    # Parent  8dec8b43ccca5f104b1e280cb33c8f4c2c1b8f85
    permit parent=something in addition to prec=n in sage.libs.mpmath.call; some code cleanup
    
    diff -r 8dec8b43ccca -r b0c9f1044971 sage/libs/mpmath/utils.pyx
    a b  
    159159    bc = mpz_sizeinbase(man.value, 2)
    160160    return (sign, man, int(exp), bc)
    161161
    162 def mpmath_to_sage(x, prec):
     162def mpmath_to_sage(x, prec, parent=None):
    163163    """
    164164    Convert any mpmath number (mpf or mpc) to a Sage RealNumber or
    165165    ComplexNumber of the given precision.
     
    233233    or ComplexNumber of the given precision into an mpmath mpf or mpc.
    234234    Integers are currently converted to int.
    235235
     236    Lists, tuples and dicts passed as input are converted
     237    recursively.
     238
    236239    EXAMPLES::
    237240
    238241        sage: import sage.libs.mpmath.all as a
     
    241244        0.666666666666667
    242245        sage: print a.sage_to_mpmath(2./3, 53)
    243246        0.666666666666667
    244         sage: print a.sage_to_mpmath(3+4*I, 53) 
     247        sage: print a.sage_to_mpmath(3+4*I, 53)
    245248        (3.0 + 4.0j)
    246249        sage: print a.sage_to_mpmath(1+pi, 53)
    247250        4.14159265358979
     
    249252        mpf('+inf')
    250253        sage: a.sage_to_mpmath(-infinity, 53)
    251254        mpf('-inf')
    252         sage: a.sage_to_mpmath(NaN, 53)     
     255        sage: a.sage_to_mpmath(NaN, 53)
    253256        mpf('nan')
    254         sage: a.sage_to_mpmath(0, 53) 
     257        sage: a.sage_to_mpmath(0, 53)
    255258        0
     259        sage: a.sage_to_mpmath([0.5, 1.5], 53)
     260        [mpf('0.5'), mpf('1.5')]
     261        sage: a.sage_to_mpmath((0.5, 1.5), 53)
     262        (mpf('0.5'), mpf('1.5'))
     263        sage: a.sage_to_mpmath({'n':0.5}, 53)
     264        {'n': mpf('0.5')}
     265
    256266    """
    257267    cdef RealNumber y
    258268    if isinstance(x, Element):
     
    272282                return x._mpmath_()
    273283    if PY_TYPE_CHECK(x, tuple) or PY_TYPE_CHECK(x, list):
    274284        return type(x)([sage_to_mpmath(v, prec) for v in x])
     285    if PY_TYPE_CHECK(x, dict):
     286        return dict([(k, sage_to_mpmath(v, prec)) for (k, v) in x.items()])
    275287    return x
    276288
    277289def call(func, *args, **kwargs):
    278290    """
    279291    Call an mpmath function with Sage objects as inputs and
    280     convert the result back to a Sage real or complex number. Use the
    281     keyword argument prec=n to set the working precision in bits
    282     (by default mpmath's global working precision is used).
     292    convert the result back to a Sage real or complex number.
     293
     294    By default, a RealNumber or ComplexNumber with the current
     295    working precision of mpmath (mpmath.mp.prec) will be returned.
     296
     297    If prec=n is passed among the keyword arguments, the temporary
     298    working precision will be set to n and the result will also
     299    have this precision.
     300
     301    If parent=P is passed, P.prec() will be used as working
     302    precision and the result will be coerced to P (or the
     303    corresponding complex field if necessary).
    283304
    284305    Arguments should be Sage objects that can be coerced into RealField
    285     or ComplexField elements. Arguments may also be tuples/lists (which
    286     are converted recursively), or any type that mpmath understands
    287     natively (e.g. Python floats, strings for options).
     306    or ComplexField elements. Arguments may also be tuples, lists or
     307    dicts (which are converted recursively), or any type that mpmath
     308    understands natively (e.g. Python floats, strings for options).
    288309
    289310    EXAMPLES::
    290311
     
    317338        -1.00000000000000
    318339        sage: a.call(a.gamma, infinity)
    319340        +infinity
     341        sage: a.call(a.polylog, 2, 1/2, parent=RR)           
     342        0.582240526465012
     343        sage: a.call(a.polylog, 2, 2, parent=RR)
     344        2.46740110027234 - 2.17758609030360*I
     345        sage: a.call(a.polylog, 2, 1/2, parent=RealField(100))
     346        0.58224052646501250590265632016
     347        sage: a.call(a.polylog, 2, 2, parent=RealField(100))
     348        2.4674011002723396547086227500 - 2.1775860903036021305006888982*I
     349        sage: a.call(a.polylog, 2, 1/2, parent=CC)
     350        0.582240526465012
     351        sage: type(_)
     352        <type 'sage.rings.complex_number.ComplexNumber'>
     353
    320354    """
    321355    from mpmath import mp
    322356    orig = mp.prec
    323357    prec = kwargs.pop('prec', orig)
     358    parent = kwargs.pop('parent', None)
     359    if parent is not None:
     360        prec = parent.prec()
    324361    prec2 = prec + 20
    325     args = [sage_to_mpmath(x, prec2) for x in args]
    326     if kwargs:
    327         kwargs = dict([(key, sage_to_mpmath(value, prec2)) for (key, value) in \
    328             kwargs.items()])
     362    args = sage_to_mpmath(args, prec2)
     363    kwargs = sage_to_mpmath(kwargs, prec2)
    329364    try:
    330365        mp.prec = prec
    331366        y = func(*args, **kwargs)
    332367    finally:
    333368        mp.prec = orig
    334     return mpmath_to_sage(y, prec)
     369    y = mpmath_to_sage(y, prec)
     370    if parent is None:
     371        return y
     372    try:
     373        return parent(y)
     374    except TypeError:
     375        return parent.complex_field()(y)
    335376
    336