functions.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. from ..libmp.backend import xrange
  2. class SpecialFunctions(object):
  3. """
  4. This class implements special functions using high-level code.
  5. Elementary and some other functions (e.g. gamma function, basecase
  6. hypergeometric series) are assumed to be predefined by the context as
  7. "builtins" or "low-level" functions.
  8. """
  9. defined_functions = {}
  10. # The series for the Jacobi theta functions converge for |q| < 1;
  11. # in the current implementation they throw a ValueError for
  12. # abs(q) > THETA_Q_LIM
  13. THETA_Q_LIM = 1 - 10**-7
  14. def __init__(self):
  15. cls = self.__class__
  16. for name in cls.defined_functions:
  17. f, wrap = cls.defined_functions[name]
  18. cls._wrap_specfun(name, f, wrap)
  19. self.mpq_1 = self._mpq((1,1))
  20. self.mpq_0 = self._mpq((0,1))
  21. self.mpq_1_2 = self._mpq((1,2))
  22. self.mpq_3_2 = self._mpq((3,2))
  23. self.mpq_1_4 = self._mpq((1,4))
  24. self.mpq_1_16 = self._mpq((1,16))
  25. self.mpq_3_16 = self._mpq((3,16))
  26. self.mpq_5_2 = self._mpq((5,2))
  27. self.mpq_3_4 = self._mpq((3,4))
  28. self.mpq_7_4 = self._mpq((7,4))
  29. self.mpq_5_4 = self._mpq((5,4))
  30. self.mpq_1_3 = self._mpq((1,3))
  31. self.mpq_2_3 = self._mpq((2,3))
  32. self.mpq_4_3 = self._mpq((4,3))
  33. self.mpq_1_6 = self._mpq((1,6))
  34. self.mpq_5_6 = self._mpq((5,6))
  35. self.mpq_5_3 = self._mpq((5,3))
  36. self._misc_const_cache = {}
  37. self._aliases.update({
  38. 'phase' : 'arg',
  39. 'conjugate' : 'conj',
  40. 'nthroot' : 'root',
  41. 'polygamma' : 'psi',
  42. 'hurwitz' : 'zeta',
  43. #'digamma' : 'psi0',
  44. #'trigamma' : 'psi1',
  45. #'tetragamma' : 'psi2',
  46. #'pentagamma' : 'psi3',
  47. 'fibonacci' : 'fib',
  48. 'factorial' : 'fac',
  49. })
  50. self.zetazero_memoized = self.memoize(self.zetazero)
  51. # Default -- do nothing
  52. @classmethod
  53. def _wrap_specfun(cls, name, f, wrap):
  54. setattr(cls, name, f)
  55. # Optional fast versions of common functions in common cases.
  56. # If not overridden, default (generic hypergeometric series)
  57. # implementations will be used
  58. def _besselj(ctx, n, z): raise NotImplementedError
  59. def _erf(ctx, z): raise NotImplementedError
  60. def _erfc(ctx, z): raise NotImplementedError
  61. def _gamma_upper_int(ctx, z, a): raise NotImplementedError
  62. def _expint_int(ctx, n, z): raise NotImplementedError
  63. def _zeta(ctx, s): raise NotImplementedError
  64. def _zetasum_fast(ctx, s, a, n, derivatives, reflect): raise NotImplementedError
  65. def _ei(ctx, z): raise NotImplementedError
  66. def _e1(ctx, z): raise NotImplementedError
  67. def _ci(ctx, z): raise NotImplementedError
  68. def _si(ctx, z): raise NotImplementedError
  69. def _altzeta(ctx, s): raise NotImplementedError
  70. def defun_wrapped(f):
  71. SpecialFunctions.defined_functions[f.__name__] = f, True
  72. return f
  73. def defun(f):
  74. SpecialFunctions.defined_functions[f.__name__] = f, False
  75. return f
  76. def defun_static(f):
  77. setattr(SpecialFunctions, f.__name__, f)
  78. return f
  79. @defun_wrapped
  80. def cot(ctx, z): return ctx.one / ctx.tan(z)
  81. @defun_wrapped
  82. def sec(ctx, z): return ctx.one / ctx.cos(z)
  83. @defun_wrapped
  84. def csc(ctx, z): return ctx.one / ctx.sin(z)
  85. @defun_wrapped
  86. def coth(ctx, z): return ctx.one / ctx.tanh(z)
  87. @defun_wrapped
  88. def sech(ctx, z): return ctx.one / ctx.cosh(z)
  89. @defun_wrapped
  90. def csch(ctx, z): return ctx.one / ctx.sinh(z)
  91. @defun_wrapped
  92. def acot(ctx, z):
  93. if not z:
  94. return ctx.pi * 0.5
  95. else:
  96. return ctx.atan(ctx.one / z)
  97. @defun_wrapped
  98. def asec(ctx, z): return ctx.acos(ctx.one / z)
  99. @defun_wrapped
  100. def acsc(ctx, z): return ctx.asin(ctx.one / z)
  101. @defun_wrapped
  102. def acoth(ctx, z):
  103. if not z:
  104. return ctx.pi * 0.5j
  105. else:
  106. return ctx.atanh(ctx.one / z)
  107. @defun_wrapped
  108. def asech(ctx, z): return ctx.acosh(ctx.one / z)
  109. @defun_wrapped
  110. def acsch(ctx, z): return ctx.asinh(ctx.one / z)
  111. @defun
  112. def sign(ctx, x):
  113. x = ctx.convert(x)
  114. if not x or ctx.isnan(x):
  115. return x
  116. if ctx._is_real_type(x):
  117. if x > 0:
  118. return ctx.one
  119. else:
  120. return -ctx.one
  121. return x / abs(x)
  122. @defun
  123. def agm(ctx, a, b=1):
  124. if b == 1:
  125. return ctx.agm1(a)
  126. a = ctx.convert(a)
  127. b = ctx.convert(b)
  128. return ctx._agm(a, b)
  129. @defun_wrapped
  130. def sinc(ctx, x):
  131. if ctx.isinf(x):
  132. return 1/x
  133. if not x:
  134. return x+1
  135. return ctx.sin(x)/x
  136. @defun_wrapped
  137. def sincpi(ctx, x):
  138. if ctx.isinf(x):
  139. return 1/x
  140. if not x:
  141. return x+1
  142. return ctx.sinpi(x)/(ctx.pi*x)
  143. # TODO: tests; improve implementation
  144. @defun_wrapped
  145. def expm1(ctx, x):
  146. if not x:
  147. return ctx.zero
  148. # exp(x) - 1 ~ x
  149. if ctx.mag(x) < -ctx.prec:
  150. return x + 0.5*x**2
  151. # TODO: accurately eval the smaller of the real/imag parts
  152. return ctx.sum_accurately(lambda: iter([ctx.exp(x),-1]),1)
  153. @defun_wrapped
  154. def log1p(ctx, x):
  155. if not x:
  156. return ctx.zero
  157. if ctx.mag(x) < -ctx.prec:
  158. return x - 0.5*x**2
  159. return ctx.log(ctx.fadd(1, x, prec=2*ctx.prec))
  160. @defun_wrapped
  161. def powm1(ctx, x, y):
  162. mag = ctx.mag
  163. one = ctx.one
  164. w = x**y - one
  165. M = mag(w)
  166. # Only moderate cancellation
  167. if M > -8:
  168. return w
  169. # Check for the only possible exact cases
  170. if not w:
  171. if (not y) or (x in (1, -1, 1j, -1j) and ctx.isint(y)):
  172. return w
  173. x1 = x - one
  174. magy = mag(y)
  175. lnx = ctx.ln(x)
  176. # Small y: x^y - 1 ~ log(x)*y + O(log(x)^2 * y^2)
  177. if magy + mag(lnx) < -ctx.prec:
  178. return lnx*y + (lnx*y)**2/2
  179. # TODO: accurately eval the smaller of the real/imag part
  180. return ctx.sum_accurately(lambda: iter([x**y, -1]), 1)
  181. @defun
  182. def _rootof1(ctx, k, n):
  183. k = int(k)
  184. n = int(n)
  185. k %= n
  186. if not k:
  187. return ctx.one
  188. elif 2*k == n:
  189. return -ctx.one
  190. elif 4*k == n:
  191. return ctx.j
  192. elif 4*k == 3*n:
  193. return -ctx.j
  194. return ctx.expjpi(2*ctx.mpf(k)/n)
  195. @defun
  196. def root(ctx, x, n, k=0):
  197. n = int(n)
  198. x = ctx.convert(x)
  199. if k:
  200. # Special case: there is an exact real root
  201. if (n & 1 and 2*k == n-1) and (not ctx.im(x)) and (ctx.re(x) < 0):
  202. return -ctx.root(-x, n)
  203. # Multiply by root of unity
  204. prec = ctx.prec
  205. try:
  206. ctx.prec += 10
  207. v = ctx.root(x, n, 0) * ctx._rootof1(k, n)
  208. finally:
  209. ctx.prec = prec
  210. return +v
  211. return ctx._nthroot(x, n)
  212. @defun
  213. def unitroots(ctx, n, primitive=False):
  214. gcd = ctx._gcd
  215. prec = ctx.prec
  216. try:
  217. ctx.prec += 10
  218. if primitive:
  219. v = [ctx._rootof1(k,n) for k in range(n) if gcd(k,n) == 1]
  220. else:
  221. # TODO: this can be done *much* faster
  222. v = [ctx._rootof1(k,n) for k in range(n)]
  223. finally:
  224. ctx.prec = prec
  225. return [+x for x in v]
  226. @defun
  227. def arg(ctx, x):
  228. x = ctx.convert(x)
  229. re = ctx._re(x)
  230. im = ctx._im(x)
  231. return ctx.atan2(im, re)
  232. @defun
  233. def fabs(ctx, x):
  234. return abs(ctx.convert(x))
  235. @defun
  236. def re(ctx, x):
  237. x = ctx.convert(x)
  238. if hasattr(x, "real"): # py2.5 doesn't have .real/.imag for all numbers
  239. return x.real
  240. return x
  241. @defun
  242. def im(ctx, x):
  243. x = ctx.convert(x)
  244. if hasattr(x, "imag"): # py2.5 doesn't have .real/.imag for all numbers
  245. return x.imag
  246. return ctx.zero
  247. @defun
  248. def conj(ctx, x):
  249. x = ctx.convert(x)
  250. try:
  251. return x.conjugate()
  252. except AttributeError:
  253. return x
  254. @defun
  255. def polar(ctx, z):
  256. return (ctx.fabs(z), ctx.arg(z))
  257. @defun_wrapped
  258. def rect(ctx, r, phi):
  259. return r * ctx.mpc(*ctx.cos_sin(phi))
  260. @defun
  261. def log(ctx, x, b=None):
  262. if b is None:
  263. return ctx.ln(x)
  264. wp = ctx.prec + 20
  265. return ctx.ln(x, prec=wp) / ctx.ln(b, prec=wp)
  266. @defun
  267. def log10(ctx, x):
  268. return ctx.log(x, 10)
  269. @defun
  270. def fmod(ctx, x, y):
  271. return ctx.convert(x) % ctx.convert(y)
  272. @defun
  273. def degrees(ctx, x):
  274. return x / ctx.degree
  275. @defun
  276. def radians(ctx, x):
  277. return x * ctx.degree
  278. def _lambertw_special(ctx, z, k):
  279. # W(0,0) = 0; all other branches are singular
  280. if not z:
  281. if not k:
  282. return z
  283. return ctx.ninf + z
  284. if z == ctx.inf:
  285. if k == 0:
  286. return z
  287. else:
  288. return z + 2*k*ctx.pi*ctx.j
  289. if z == ctx.ninf:
  290. return (-z) + (2*k+1)*ctx.pi*ctx.j
  291. # Some kind of nan or complex inf/nan?
  292. return ctx.ln(z)
  293. import math
  294. import cmath
  295. def _lambertw_approx_hybrid(z, k):
  296. imag_sign = 0
  297. if hasattr(z, "imag"):
  298. x = float(z.real)
  299. y = z.imag
  300. if y:
  301. imag_sign = (-1) ** (y < 0)
  302. y = float(y)
  303. else:
  304. x = float(z)
  305. y = 0.0
  306. imag_sign = 0
  307. # hack to work regardless of whether Python supports -0.0
  308. if not y:
  309. y = 0.0
  310. z = complex(x,y)
  311. if k == 0:
  312. if -4.0 < y < 4.0 and -1.0 < x < 2.5:
  313. if imag_sign:
  314. # Taylor series in upper/lower half-plane
  315. if y > 1.00: return (0.876+0.645j) + (0.118-0.174j)*(z-(0.75+2.5j))
  316. if y > 0.25: return (0.505+0.204j) + (0.375-0.132j)*(z-(0.75+0.5j))
  317. if y < -1.00: return (0.876-0.645j) + (0.118+0.174j)*(z-(0.75-2.5j))
  318. if y < -0.25: return (0.505-0.204j) + (0.375+0.132j)*(z-(0.75-0.5j))
  319. # Taylor series near -1
  320. if x < -0.5:
  321. if imag_sign >= 0:
  322. return (-0.318+1.34j) + (-0.697-0.593j)*(z+1)
  323. else:
  324. return (-0.318-1.34j) + (-0.697+0.593j)*(z+1)
  325. # return real type
  326. r = -0.367879441171442
  327. if (not imag_sign) and x > r:
  328. z = x
  329. # Singularity near -1/e
  330. if x < -0.2:
  331. return -1 + 2.33164398159712*(z-r)**0.5 - 1.81218788563936*(z-r)
  332. # Taylor series near 0
  333. if x < 0.5: return z
  334. # Simple linear approximation
  335. return 0.2 + 0.3*z
  336. if (not imag_sign) and x > 0.0:
  337. L1 = math.log(x); L2 = math.log(L1)
  338. else:
  339. L1 = cmath.log(z); L2 = cmath.log(L1)
  340. elif k == -1:
  341. # return real type
  342. r = -0.367879441171442
  343. if (not imag_sign) and r < x < 0.0:
  344. z = x
  345. if (imag_sign >= 0) and y < 0.1 and -0.6 < x < -0.2:
  346. return -1 - 2.33164398159712*(z-r)**0.5 - 1.81218788563936*(z-r)
  347. if (not imag_sign) and -0.2 <= x < 0.0:
  348. L1 = math.log(-x)
  349. return L1 - math.log(-L1)
  350. else:
  351. if imag_sign == -1 and (not y) and x < 0.0:
  352. L1 = cmath.log(z) - 3.1415926535897932j
  353. else:
  354. L1 = cmath.log(z) - 6.2831853071795865j
  355. L2 = cmath.log(L1)
  356. return L1 - L2 + L2/L1 + L2*(L2-2)/(2*L1**2)
  357. def _lambertw_series(ctx, z, k, tol):
  358. """
  359. Return rough approximation for W_k(z) from an asymptotic series,
  360. sufficiently accurate for the Halley iteration to converge to
  361. the correct value.
  362. """
  363. magz = ctx.mag(z)
  364. if (-10 < magz < 900) and (-1000 < k < 1000):
  365. # Near the branch point at -1/e
  366. if magz < 1 and abs(z+0.36787944117144) < 0.05:
  367. if k == 0 or (k == -1 and ctx._im(z) >= 0) or \
  368. (k == 1 and ctx._im(z) < 0):
  369. delta = ctx.sum_accurately(lambda: [z, ctx.exp(-1)])
  370. cancellation = -ctx.mag(delta)
  371. ctx.prec += cancellation
  372. # Use series given in Corless et al.
  373. p = ctx.sqrt(2*(ctx.e*z+1))
  374. ctx.prec -= cancellation
  375. u = {0:ctx.mpf(-1), 1:ctx.mpf(1)}
  376. a = {0:ctx.mpf(2), 1:ctx.mpf(-1)}
  377. if k != 0:
  378. p = -p
  379. s = ctx.zero
  380. # The series converges, so we could use it directly, but unless
  381. # *extremely* close, it is better to just use the first few
  382. # terms to get a good approximation for the iteration
  383. for l in xrange(max(2,cancellation)):
  384. if l not in u:
  385. a[l] = ctx.fsum(u[j]*u[l+1-j] for j in xrange(2,l))
  386. u[l] = (l-1)*(u[l-2]/2+a[l-2]/4)/(l+1)-a[l]/2-u[l-1]/(l+1)
  387. term = u[l] * p**l
  388. s += term
  389. if ctx.mag(term) < -tol:
  390. return s, True
  391. l += 1
  392. ctx.prec += cancellation//2
  393. return s, False
  394. if k == 0 or k == -1:
  395. return _lambertw_approx_hybrid(z, k), False
  396. if k == 0:
  397. if magz < -1:
  398. return z*(1-z), False
  399. L1 = ctx.ln(z)
  400. L2 = ctx.ln(L1)
  401. elif k == -1 and (not ctx._im(z)) and (-0.36787944117144 < ctx._re(z) < 0):
  402. L1 = ctx.ln(-z)
  403. return L1 - ctx.ln(-L1), False
  404. else:
  405. # This holds both as z -> 0 and z -> inf.
  406. # Relative error is O(1/log(z)).
  407. L1 = ctx.ln(z) + 2j*ctx.pi*k
  408. L2 = ctx.ln(L1)
  409. return L1 - L2 + L2/L1 + L2*(L2-2)/(2*L1**2), False
  410. @defun
  411. def lambertw(ctx, z, k=0):
  412. z = ctx.convert(z)
  413. k = int(k)
  414. if not ctx.isnormal(z):
  415. return _lambertw_special(ctx, z, k)
  416. prec = ctx.prec
  417. ctx.prec += 20 + ctx.mag(k or 1)
  418. wp = ctx.prec
  419. tol = wp - 5
  420. w, done = _lambertw_series(ctx, z, k, tol)
  421. if not done:
  422. # Use Halley iteration to solve w*exp(w) = z
  423. two = ctx.mpf(2)
  424. for i in xrange(100):
  425. ew = ctx.exp(w)
  426. wew = w*ew
  427. wewz = wew-z
  428. wn = w - wewz/(wew+ew-(w+two)*wewz/(two*w+two))
  429. if ctx.mag(wn-w) <= ctx.mag(wn) - tol:
  430. w = wn
  431. break
  432. else:
  433. w = wn
  434. if i == 100:
  435. ctx.warn("Lambert W iteration failed to converge for z = %s" % z)
  436. ctx.prec = prec
  437. return +w
  438. @defun_wrapped
  439. def bell(ctx, n, x=1):
  440. x = ctx.convert(x)
  441. if not n:
  442. if ctx.isnan(x):
  443. return x
  444. return type(x)(1)
  445. if ctx.isinf(x) or ctx.isinf(n) or ctx.isnan(x) or ctx.isnan(n):
  446. return x**n
  447. if n == 1: return x
  448. if n == 2: return x*(x+1)
  449. if x == 0: return ctx.sincpi(n)
  450. return _polyexp(ctx, n, x, True) / ctx.exp(x)
  451. def _polyexp(ctx, n, x, extra=False):
  452. def _terms():
  453. if extra:
  454. yield ctx.sincpi(n)
  455. t = x
  456. k = 1
  457. while 1:
  458. yield k**n * t
  459. k += 1
  460. t = t*x/k
  461. return ctx.sum_accurately(_terms, check_step=4)
  462. @defun_wrapped
  463. def polyexp(ctx, s, z):
  464. if ctx.isinf(z) or ctx.isinf(s) or ctx.isnan(z) or ctx.isnan(s):
  465. return z**s
  466. if z == 0: return z*s
  467. if s == 0: return ctx.expm1(z)
  468. if s == 1: return ctx.exp(z)*z
  469. if s == 2: return ctx.exp(z)*z*(z+1)
  470. return _polyexp(ctx, s, z)
  471. @defun_wrapped
  472. def cyclotomic(ctx, n, z):
  473. n = int(n)
  474. if n < 0:
  475. raise ValueError("n cannot be negative")
  476. p = ctx.one
  477. if n == 0:
  478. return p
  479. if n == 1:
  480. return z - p
  481. if n == 2:
  482. return z + p
  483. # Use divisor product representation. Unfortunately, this sometimes
  484. # includes singularities for roots of unity, which we have to cancel out.
  485. # Matching zeros/poles pairwise, we have (1-z^a)/(1-z^b) ~ a/b + O(z-1).
  486. a_prod = 1
  487. b_prod = 1
  488. num_zeros = 0
  489. num_poles = 0
  490. for d in range(1,n+1):
  491. if not n % d:
  492. w = ctx.moebius(n//d)
  493. # Use powm1 because it is important that we get 0 only
  494. # if it really is exactly 0
  495. b = -ctx.powm1(z, d)
  496. if b:
  497. p *= b**w
  498. else:
  499. if w == 1:
  500. a_prod *= d
  501. num_zeros += 1
  502. elif w == -1:
  503. b_prod *= d
  504. num_poles += 1
  505. #print n, num_zeros, num_poles
  506. if num_zeros:
  507. if num_zeros > num_poles:
  508. p *= 0
  509. else:
  510. p *= a_prod
  511. p /= b_prod
  512. return p
  513. @defun
  514. def mangoldt(ctx, n):
  515. r"""
  516. Evaluates the von Mangoldt function `\Lambda(n) = \log p`
  517. if `n = p^k` a power of a prime, and `\Lambda(n) = 0` otherwise.
  518. **Examples**
  519. >>> from mpmath import *
  520. >>> mp.dps = 25; mp.pretty = True
  521. >>> [mangoldt(n) for n in range(-2,3)]
  522. [0.0, 0.0, 0.0, 0.0, 0.6931471805599453094172321]
  523. >>> mangoldt(6)
  524. 0.0
  525. >>> mangoldt(7)
  526. 1.945910149055313305105353
  527. >>> mangoldt(8)
  528. 0.6931471805599453094172321
  529. >>> fsum(mangoldt(n) for n in range(101))
  530. 94.04531122935739224600493
  531. >>> fsum(mangoldt(n) for n in range(10001))
  532. 10013.39669326311478372032
  533. """
  534. n = int(n)
  535. if n < 2:
  536. return ctx.zero
  537. if n % 2 == 0:
  538. # Must be a power of two
  539. if n & (n-1) == 0:
  540. return +ctx.ln2
  541. else:
  542. return ctx.zero
  543. # TODO: the following could be generalized into a perfect
  544. # power testing function
  545. # ---
  546. # Look for a small factor
  547. for p in (3,5,7,11,13,17,19,23,29,31):
  548. if not n % p:
  549. q, r = n // p, 0
  550. while q > 1:
  551. q, r = divmod(q, p)
  552. if r:
  553. return ctx.zero
  554. return ctx.ln(p)
  555. if ctx.isprime(n):
  556. return ctx.ln(n)
  557. # Obviously, we could use arbitrary-precision arithmetic for this...
  558. if n > 10**30:
  559. raise NotImplementedError
  560. k = 2
  561. while 1:
  562. p = int(n**(1./k) + 0.5)
  563. if p < 2:
  564. return ctx.zero
  565. if p ** k == n:
  566. if ctx.isprime(p):
  567. return ctx.ln(p)
  568. k += 1
  569. @defun
  570. def stirling1(ctx, n, k, exact=False):
  571. v = ctx._stirling1(int(n), int(k))
  572. if exact:
  573. return int(v)
  574. else:
  575. return ctx.mpf(v)
  576. @defun
  577. def stirling2(ctx, n, k, exact=False):
  578. v = ctx._stirling2(int(n), int(k))
  579. if exact:
  580. return int(v)
  581. else:
  582. return ctx.mpf(v)