# 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
|
|
159 | 159 | bc = mpz_sizeinbase(man.value, 2) |
160 | 160 | return (sign, man, int(exp), bc) |
161 | 161 | |
162 | | def mpmath_to_sage(x, prec): |
| 162 | def mpmath_to_sage(x, prec, parent=None): |
163 | 163 | """ |
164 | 164 | Convert any mpmath number (mpf or mpc) to a Sage RealNumber or |
165 | 165 | ComplexNumber of the given precision. |
… |
… |
|
233 | 233 | or ComplexNumber of the given precision into an mpmath mpf or mpc. |
234 | 234 | Integers are currently converted to int. |
235 | 235 | |
| 236 | Lists, tuples and dicts passed as input are converted |
| 237 | recursively. |
| 238 | |
236 | 239 | EXAMPLES:: |
237 | 240 | |
238 | 241 | sage: import sage.libs.mpmath.all as a |
… |
… |
|
241 | 244 | 0.666666666666667 |
242 | 245 | sage: print a.sage_to_mpmath(2./3, 53) |
243 | 246 | 0.666666666666667 |
244 | | sage: print a.sage_to_mpmath(3+4*I, 53) |
| 247 | sage: print a.sage_to_mpmath(3+4*I, 53) |
245 | 248 | (3.0 + 4.0j) |
246 | 249 | sage: print a.sage_to_mpmath(1+pi, 53) |
247 | 250 | 4.14159265358979 |
… |
… |
|
249 | 252 | mpf('+inf') |
250 | 253 | sage: a.sage_to_mpmath(-infinity, 53) |
251 | 254 | mpf('-inf') |
252 | | sage: a.sage_to_mpmath(NaN, 53) |
| 255 | sage: a.sage_to_mpmath(NaN, 53) |
253 | 256 | mpf('nan') |
254 | | sage: a.sage_to_mpmath(0, 53) |
| 257 | sage: a.sage_to_mpmath(0, 53) |
255 | 258 | 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 | |
256 | 266 | """ |
257 | 267 | cdef RealNumber y |
258 | 268 | if isinstance(x, Element): |
… |
… |
|
272 | 282 | return x._mpmath_() |
273 | 283 | if PY_TYPE_CHECK(x, tuple) or PY_TYPE_CHECK(x, list): |
274 | 284 | 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()]) |
275 | 287 | return x |
276 | 288 | |
277 | 289 | def call(func, *args, **kwargs): |
278 | 290 | """ |
279 | 291 | 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). |
283 | 304 | |
284 | 305 | 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). |
288 | 309 | |
289 | 310 | EXAMPLES:: |
290 | 311 | |
… |
… |
|
317 | 338 | -1.00000000000000 |
318 | 339 | sage: a.call(a.gamma, infinity) |
319 | 340 | +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 | |
320 | 354 | """ |
321 | 355 | from mpmath import mp |
322 | 356 | orig = mp.prec |
323 | 357 | prec = kwargs.pop('prec', orig) |
| 358 | parent = kwargs.pop('parent', None) |
| 359 | if parent is not None: |
| 360 | prec = parent.prec() |
324 | 361 | 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) |
329 | 364 | try: |
330 | 365 | mp.prec = prec |
331 | 366 | y = func(*args, **kwargs) |
332 | 367 | finally: |
333 | 368 | 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) |
335 | 376 | |
336 | | |