libelefun.py 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428
  1. """
  2. This module implements computation of elementary transcendental
  3. functions (powers, logarithms, trigonometric and hyperbolic
  4. functions, inverse trigonometric and hyperbolic) for real
  5. floating-point numbers.
  6. For complex and interval implementations of the same functions,
  7. see libmpc and libmpi.
  8. """
  9. import math
  10. from bisect import bisect
  11. from .backend import xrange
  12. from .backend import MPZ, MPZ_ZERO, MPZ_ONE, MPZ_TWO, MPZ_FIVE, BACKEND
  13. from .libmpf import (
  14. round_floor, round_ceiling, round_down, round_up,
  15. round_nearest, round_fast,
  16. ComplexResult,
  17. bitcount, bctable, lshift, rshift, giant_steps, sqrt_fixed,
  18. from_int, to_int, from_man_exp, to_fixed, to_float, from_float,
  19. from_rational, normalize,
  20. fzero, fone, fnone, fhalf, finf, fninf, fnan,
  21. mpf_cmp, mpf_sign, mpf_abs,
  22. mpf_pos, mpf_neg, mpf_add, mpf_sub, mpf_mul, mpf_div, mpf_shift,
  23. mpf_rdiv_int, mpf_pow_int, mpf_sqrt,
  24. reciprocal_rnd, negative_rnd, mpf_perturb,
  25. isqrt_fast
  26. )
  27. from .libintmath import ifib
  28. #-------------------------------------------------------------------------------
  29. # Tuning parameters
  30. #-------------------------------------------------------------------------------
  31. # Cutoff for computing exp from cosh+sinh. This reduces the
  32. # number of terms by half, but also requires a square root which
  33. # is expensive with the pure-Python square root code.
  34. if BACKEND == 'python':
  35. EXP_COSH_CUTOFF = 600
  36. else:
  37. EXP_COSH_CUTOFF = 400
  38. # Cutoff for using more than 2 series
  39. EXP_SERIES_U_CUTOFF = 1500
  40. # Also basically determined by sqrt
  41. if BACKEND == 'python':
  42. COS_SIN_CACHE_PREC = 400
  43. else:
  44. COS_SIN_CACHE_PREC = 200
  45. COS_SIN_CACHE_STEP = 8
  46. cos_sin_cache = {}
  47. # Number of integer logarithms to cache (for zeta sums)
  48. MAX_LOG_INT_CACHE = 2000
  49. log_int_cache = {}
  50. LOG_TAYLOR_PREC = 2500 # Use Taylor series with caching up to this prec
  51. LOG_TAYLOR_SHIFT = 9 # Cache log values in steps of size 2^-N
  52. log_taylor_cache = {}
  53. # prec/size ratio of x for fastest convergence in AGM formula
  54. LOG_AGM_MAG_PREC_RATIO = 20
  55. ATAN_TAYLOR_PREC = 3000 # Same as for log
  56. ATAN_TAYLOR_SHIFT = 7 # steps of size 2^-N
  57. atan_taylor_cache = {}
  58. # ~= next power of two + 20
  59. cache_prec_steps = [22,22]
  60. for k in xrange(1, bitcount(LOG_TAYLOR_PREC)+1):
  61. cache_prec_steps += [min(2**k,LOG_TAYLOR_PREC)+20] * 2**(k-1)
  62. #----------------------------------------------------------------------------#
  63. # #
  64. # Elementary mathematical constants #
  65. # #
  66. #----------------------------------------------------------------------------#
  67. def constant_memo(f):
  68. """
  69. Decorator for caching computed values of mathematical
  70. constants. This decorator should be applied to a
  71. function taking a single argument prec as input and
  72. returning a fixed-point value with the given precision.
  73. """
  74. f.memo_prec = -1
  75. f.memo_val = None
  76. def g(prec, **kwargs):
  77. memo_prec = f.memo_prec
  78. if prec <= memo_prec:
  79. return f.memo_val >> (memo_prec-prec)
  80. newprec = int(prec*1.05+10)
  81. f.memo_val = f(newprec, **kwargs)
  82. f.memo_prec = newprec
  83. return f.memo_val >> (newprec-prec)
  84. g.__name__ = f.__name__
  85. g.__doc__ = f.__doc__
  86. return g
  87. def def_mpf_constant(fixed):
  88. """
  89. Create a function that computes the mpf value for a mathematical
  90. constant, given a function that computes the fixed-point value.
  91. Assumptions: the constant is positive and has magnitude ~= 1;
  92. the fixed-point function rounds to floor.
  93. """
  94. def f(prec, rnd=round_fast):
  95. wp = prec + 20
  96. v = fixed(wp)
  97. if rnd in (round_up, round_ceiling):
  98. v += 1
  99. return normalize(0, v, -wp, bitcount(v), prec, rnd)
  100. f.__doc__ = fixed.__doc__
  101. return f
  102. def bsp_acot(q, a, b, hyperbolic):
  103. if b - a == 1:
  104. a1 = MPZ(2*a + 3)
  105. if hyperbolic or a&1:
  106. return MPZ_ONE, a1 * q**2, a1
  107. else:
  108. return -MPZ_ONE, a1 * q**2, a1
  109. m = (a+b)//2
  110. p1, q1, r1 = bsp_acot(q, a, m, hyperbolic)
  111. p2, q2, r2 = bsp_acot(q, m, b, hyperbolic)
  112. return q2*p1 + r1*p2, q1*q2, r1*r2
  113. # the acoth(x) series converges like the geometric series for x^2
  114. # N = ceil(p*log(2)/(2*log(x)))
  115. def acot_fixed(a, prec, hyperbolic):
  116. """
  117. Compute acot(a) or acoth(a) for an integer a with binary splitting; see
  118. http://numbers.computation.free.fr/Constants/Algorithms/splitting.html
  119. """
  120. N = int(0.35 * prec/math.log(a) + 20)
  121. p, q, r = bsp_acot(a, 0,N, hyperbolic)
  122. return ((p+q)<<prec)//(q*a)
  123. def machin(coefs, prec, hyperbolic=False):
  124. """
  125. Evaluate a Machin-like formula, i.e., a linear combination of
  126. acot(n) or acoth(n) for specific integer values of n, using fixed-
  127. point arithmetic. The input should be a list [(c, n), ...], giving
  128. c*acot[h](n) + ...
  129. """
  130. extraprec = 10
  131. s = MPZ_ZERO
  132. for a, b in coefs:
  133. s += MPZ(a) * acot_fixed(MPZ(b), prec+extraprec, hyperbolic)
  134. return (s >> extraprec)
  135. # Logarithms of integers are needed for various computations involving
  136. # logarithms, powers, radix conversion, etc
  137. @constant_memo
  138. def ln2_fixed(prec):
  139. """
  140. Computes ln(2). This is done with a hyperbolic Machin-type formula,
  141. with binary splitting at high precision.
  142. """
  143. return machin([(18, 26), (-2, 4801), (8, 8749)], prec, True)
  144. @constant_memo
  145. def ln10_fixed(prec):
  146. """
  147. Computes ln(10). This is done with a hyperbolic Machin-type formula.
  148. """
  149. return machin([(46, 31), (34, 49), (20, 161)], prec, True)
  150. r"""
  151. For computation of pi, we use the Chudnovsky series:
  152. oo
  153. ___ k
  154. 1 \ (-1) (6 k)! (A + B k)
  155. ----- = ) -----------------------
  156. 12 pi /___ 3 3k+3/2
  157. (3 k)! (k!) C
  158. k = 0
  159. where A, B, and C are certain integer constants. This series adds roughly
  160. 14 digits per term. Note that C^(3/2) can be extracted so that the
  161. series contains only rational terms. This makes binary splitting very
  162. efficient.
  163. The recurrence formulas for the binary splitting were taken from
  164. ftp://ftp.gmplib.org/pub/src/gmp-chudnovsky.c
  165. Previously, Machin's formula was used at low precision and the AGM iteration
  166. was used at high precision. However, the Chudnovsky series is essentially as
  167. fast as the Machin formula at low precision and in practice about 3x faster
  168. than the AGM at high precision (despite theoretically having a worse
  169. asymptotic complexity), so there is no reason not to use it in all cases.
  170. """
  171. # Constants in Chudnovsky's series
  172. CHUD_A = MPZ(13591409)
  173. CHUD_B = MPZ(545140134)
  174. CHUD_C = MPZ(640320)
  175. CHUD_D = MPZ(12)
  176. def bs_chudnovsky(a, b, level, verbose):
  177. """
  178. Computes the sum from a to b of the series in the Chudnovsky
  179. formula. Returns g, p, q where p/q is the sum as an exact
  180. fraction and g is a temporary value used to save work
  181. for recursive calls.
  182. """
  183. if b-a == 1:
  184. g = MPZ((6*b-5)*(2*b-1)*(6*b-1))
  185. p = b**3 * CHUD_C**3 // 24
  186. q = (-1)**b * g * (CHUD_A+CHUD_B*b)
  187. else:
  188. if verbose and level < 4:
  189. print(" binary splitting", a, b)
  190. mid = (a+b)//2
  191. g1, p1, q1 = bs_chudnovsky(a, mid, level+1, verbose)
  192. g2, p2, q2 = bs_chudnovsky(mid, b, level+1, verbose)
  193. p = p1*p2
  194. g = g1*g2
  195. q = q1*p2 + q2*g1
  196. return g, p, q
  197. @constant_memo
  198. def pi_fixed(prec, verbose=False, verbose_base=None):
  199. """
  200. Compute floor(pi * 2**prec) as a big integer.
  201. This is done using Chudnovsky's series (see comments in
  202. libelefun.py for details).
  203. """
  204. # The Chudnovsky series gives 14.18 digits per term
  205. N = int(prec/3.3219280948/14.181647462 + 2)
  206. if verbose:
  207. print("binary splitting with N =", N)
  208. g, p, q = bs_chudnovsky(0, N, 0, verbose)
  209. sqrtC = isqrt_fast(CHUD_C<<(2*prec))
  210. v = p*CHUD_C*sqrtC//((q+CHUD_A*p)*CHUD_D)
  211. return v
  212. def degree_fixed(prec):
  213. return pi_fixed(prec)//180
  214. def bspe(a, b):
  215. """
  216. Sum series for exp(1)-1 between a, b, returning the result
  217. as an exact fraction (p, q).
  218. """
  219. if b-a == 1:
  220. return MPZ_ONE, MPZ(b)
  221. m = (a+b)//2
  222. p1, q1 = bspe(a, m)
  223. p2, q2 = bspe(m, b)
  224. return p1*q2+p2, q1*q2
  225. @constant_memo
  226. def e_fixed(prec):
  227. """
  228. Computes exp(1). This is done using the ordinary Taylor series for
  229. exp, with binary splitting. For a description of the algorithm,
  230. see:
  231. http://numbers.computation.free.fr/Constants/
  232. Algorithms/splitting.html
  233. """
  234. # Slight overestimate of N needed for 1/N! < 2**(-prec)
  235. # This could be tightened for large N.
  236. N = int(1.1*prec/math.log(prec) + 20)
  237. p, q = bspe(0,N)
  238. return ((p+q)<<prec)//q
  239. @constant_memo
  240. def phi_fixed(prec):
  241. """
  242. Computes the golden ratio, (1+sqrt(5))/2
  243. """
  244. prec += 10
  245. a = isqrt_fast(MPZ_FIVE<<(2*prec)) + (MPZ_ONE << prec)
  246. return a >> 11
  247. mpf_phi = def_mpf_constant(phi_fixed)
  248. mpf_pi = def_mpf_constant(pi_fixed)
  249. mpf_e = def_mpf_constant(e_fixed)
  250. mpf_degree = def_mpf_constant(degree_fixed)
  251. mpf_ln2 = def_mpf_constant(ln2_fixed)
  252. mpf_ln10 = def_mpf_constant(ln10_fixed)
  253. @constant_memo
  254. def ln_sqrt2pi_fixed(prec):
  255. wp = prec + 10
  256. # ln(sqrt(2*pi)) = ln(2*pi)/2
  257. return to_fixed(mpf_log(mpf_shift(mpf_pi(wp), 1), wp), prec-1)
  258. @constant_memo
  259. def sqrtpi_fixed(prec):
  260. return sqrt_fixed(pi_fixed(prec), prec)
  261. mpf_sqrtpi = def_mpf_constant(sqrtpi_fixed)
  262. mpf_ln_sqrt2pi = def_mpf_constant(ln_sqrt2pi_fixed)
  263. #----------------------------------------------------------------------------#
  264. # #
  265. # Powers #
  266. # #
  267. #----------------------------------------------------------------------------#
  268. def mpf_pow(s, t, prec, rnd=round_fast):
  269. """
  270. Compute s**t. Raises ComplexResult if s is negative and t is
  271. fractional.
  272. """
  273. ssign, sman, sexp, sbc = s
  274. tsign, tman, texp, tbc = t
  275. if ssign and texp < 0:
  276. raise ComplexResult("negative number raised to a fractional power")
  277. if texp >= 0:
  278. return mpf_pow_int(s, (-1)**tsign * (tman<<texp), prec, rnd)
  279. # s**(n/2) = sqrt(s)**n
  280. if texp == -1:
  281. if tman == 1:
  282. if tsign:
  283. return mpf_div(fone, mpf_sqrt(s, prec+10,
  284. reciprocal_rnd[rnd]), prec, rnd)
  285. return mpf_sqrt(s, prec, rnd)
  286. else:
  287. if tsign:
  288. return mpf_pow_int(mpf_sqrt(s, prec+10,
  289. reciprocal_rnd[rnd]), -tman, prec, rnd)
  290. return mpf_pow_int(mpf_sqrt(s, prec+10, rnd), tman, prec, rnd)
  291. # General formula: s**t = exp(t*log(s))
  292. # TODO: handle rnd direction of the logarithm carefully
  293. c = mpf_log(s, prec+10, rnd)
  294. return mpf_exp(mpf_mul(t, c), prec, rnd)
  295. def int_pow_fixed(y, n, prec):
  296. """n-th power of a fixed point number with precision prec
  297. Returns the power in the form man, exp,
  298. man * 2**exp ~= y**n
  299. """
  300. if n == 2:
  301. return (y*y), 0
  302. bc = bitcount(y)
  303. exp = 0
  304. workprec = 2 * (prec + 4*bitcount(n) + 4)
  305. _, pm, pe, pbc = fone
  306. while 1:
  307. if n & 1:
  308. pm = pm*y
  309. pe = pe+exp
  310. pbc += bc - 2
  311. pbc = pbc + bctable[int(pm >> pbc)]
  312. if pbc > workprec:
  313. pm = pm >> (pbc-workprec)
  314. pe += pbc - workprec
  315. pbc = workprec
  316. n -= 1
  317. if not n:
  318. break
  319. y = y*y
  320. exp = exp+exp
  321. bc = bc + bc - 2
  322. bc = bc + bctable[int(y >> bc)]
  323. if bc > workprec:
  324. y = y >> (bc-workprec)
  325. exp += bc - workprec
  326. bc = workprec
  327. n = n // 2
  328. return pm, pe
  329. # froot(s, n, prec, rnd) computes the real n-th root of a
  330. # positive mpf tuple s.
  331. # To compute the root we start from a 50-bit estimate for r
  332. # generated with ordinary floating-point arithmetic, and then refine
  333. # the value to full accuracy using the iteration
  334. # 1 / y \
  335. # r = --- | (n-1) * r + ---------- |
  336. # n+1 n \ n r_n**(n-1) /
  337. # which is simply Newton's method applied to the equation r**n = y.
  338. # With giant_steps(start, prec+extra) = [p0,...,pm, prec+extra]
  339. # and y = man * 2**-shift one has
  340. # (man * 2**exp)**(1/n) =
  341. # y**(1/n) * 2**(start-prec/n) * 2**(p0-start) * ... * 2**(prec+extra-pm) *
  342. # 2**((exp+shift-(n-1)*prec)/n -extra))
  343. # The last factor is accounted for in the last line of froot.
  344. def nthroot_fixed(y, n, prec, exp1):
  345. start = 50
  346. try:
  347. y1 = rshift(y, prec - n*start)
  348. r = MPZ(int(y1**(1.0/n)))
  349. except OverflowError:
  350. y1 = from_int(y1, start)
  351. fn = from_int(n)
  352. fn = mpf_rdiv_int(1, fn, start)
  353. r = mpf_pow(y1, fn, start)
  354. r = to_int(r)
  355. extra = 10
  356. extra1 = n
  357. prevp = start
  358. for p in giant_steps(start, prec+extra):
  359. pm, pe = int_pow_fixed(r, n-1, prevp)
  360. r2 = rshift(pm, (n-1)*prevp - p - pe - extra1)
  361. B = lshift(y, 2*p-prec+extra1)//r2
  362. r = (B + (n-1) * lshift(r, p-prevp))//n
  363. prevp = p
  364. return r
  365. def mpf_nthroot(s, n, prec, rnd=round_fast):
  366. """nth-root of a positive number
  367. Use the Newton method when faster, otherwise use x**(1/n)
  368. """
  369. sign, man, exp, bc = s
  370. if sign:
  371. raise ComplexResult("nth root of a negative number")
  372. if not man:
  373. if s == fnan:
  374. return fnan
  375. if s == fzero:
  376. if n > 0:
  377. return fzero
  378. if n == 0:
  379. return fone
  380. return finf
  381. # Infinity
  382. if not n:
  383. return fnan
  384. if n < 0:
  385. return fzero
  386. return finf
  387. flag_inverse = False
  388. if n < 2:
  389. if n == 0:
  390. return fone
  391. if n == 1:
  392. return mpf_pos(s, prec, rnd)
  393. if n == -1:
  394. return mpf_div(fone, s, prec, rnd)
  395. # n < 0
  396. rnd = reciprocal_rnd[rnd]
  397. flag_inverse = True
  398. extra_inverse = 5
  399. prec += extra_inverse
  400. n = -n
  401. if n > 20 and (n >= 20000 or prec < int(233 + 28.3 * n**0.62)):
  402. prec2 = prec + 10
  403. fn = from_int(n)
  404. nth = mpf_rdiv_int(1, fn, prec2)
  405. r = mpf_pow(s, nth, prec2, rnd)
  406. s = normalize(r[0], r[1], r[2], r[3], prec, rnd)
  407. if flag_inverse:
  408. return mpf_div(fone, s, prec-extra_inverse, rnd)
  409. else:
  410. return s
  411. # Convert to a fixed-point number with prec2 bits.
  412. prec2 = prec + 2*n - (prec%n)
  413. # a few tests indicate that
  414. # for 10 < n < 10**4 a bit more precision is needed
  415. if n > 10:
  416. prec2 += prec2//10
  417. prec2 = prec2 - prec2%n
  418. # Mantissa may have more bits than we need. Trim it down.
  419. shift = bc - prec2
  420. # Adjust exponents to make prec2 and exp+shift multiples of n.
  421. sign1 = 0
  422. es = exp+shift
  423. if es < 0:
  424. sign1 = 1
  425. es = -es
  426. if sign1:
  427. shift += es%n
  428. else:
  429. shift -= es%n
  430. man = rshift(man, shift)
  431. extra = 10
  432. exp1 = ((exp+shift-(n-1)*prec2)//n) - extra
  433. rnd_shift = 0
  434. if flag_inverse:
  435. if rnd == 'u' or rnd == 'c':
  436. rnd_shift = 1
  437. else:
  438. if rnd == 'd' or rnd == 'f':
  439. rnd_shift = 1
  440. man = nthroot_fixed(man+rnd_shift, n, prec2, exp1)
  441. s = from_man_exp(man, exp1, prec, rnd)
  442. if flag_inverse:
  443. return mpf_div(fone, s, prec-extra_inverse, rnd)
  444. else:
  445. return s
  446. def mpf_cbrt(s, prec, rnd=round_fast):
  447. """cubic root of a positive number"""
  448. return mpf_nthroot(s, 3, prec, rnd)
  449. #----------------------------------------------------------------------------#
  450. # #
  451. # Logarithms #
  452. # #
  453. #----------------------------------------------------------------------------#
  454. def log_int_fixed(n, prec, ln2=None):
  455. """
  456. Fast computation of log(n), caching the value for small n,
  457. intended for zeta sums.
  458. """
  459. if n in log_int_cache:
  460. value, vprec = log_int_cache[n]
  461. if vprec >= prec:
  462. return value >> (vprec - prec)
  463. wp = prec + 10
  464. if wp <= LOG_TAYLOR_SHIFT:
  465. if ln2 is None:
  466. ln2 = ln2_fixed(wp)
  467. r = bitcount(n)
  468. x = n << (wp-r)
  469. v = log_taylor_cached(x, wp) + r*ln2
  470. else:
  471. v = to_fixed(mpf_log(from_int(n), wp+5), wp)
  472. if n < MAX_LOG_INT_CACHE:
  473. log_int_cache[n] = (v, wp)
  474. return v >> (wp-prec)
  475. def agm_fixed(a, b, prec):
  476. """
  477. Fixed-point computation of agm(a,b), assuming
  478. a, b both close to unit magnitude.
  479. """
  480. i = 0
  481. while 1:
  482. anew = (a+b)>>1
  483. if i > 4 and abs(a-anew) < 8:
  484. return a
  485. b = isqrt_fast(a*b)
  486. a = anew
  487. i += 1
  488. return a
  489. def log_agm(x, prec):
  490. """
  491. Fixed-point computation of -log(x) = log(1/x), suitable
  492. for large precision. It is required that 0 < x < 1. The
  493. algorithm used is the Sasaki-Kanada formula
  494. -log(x) = pi/agm(theta2(x)^2,theta3(x)^2). [1]
  495. For faster convergence in the theta functions, x should
  496. be chosen closer to 0.
  497. Guard bits must be added by the caller.
  498. HYPOTHESIS: if x = 2^(-n), n bits need to be added to
  499. account for the truncation to a fixed-point number,
  500. and this is the only significant cancellation error.
  501. The number of bits lost to roundoff is small and can be
  502. considered constant.
  503. [1] Richard P. Brent, "Fast Algorithms for High-Precision
  504. Computation of Elementary Functions (extended abstract)",
  505. http://wwwmaths.anu.edu.au/~brent/pd/RNC7-Brent.pdf
  506. """
  507. x2 = (x*x) >> prec
  508. # Compute jtheta2(x)**2
  509. s = a = b = x2
  510. while a:
  511. b = (b*x2) >> prec
  512. a = (a*b) >> prec
  513. s += a
  514. s += (MPZ_ONE<<prec)
  515. s = (s*s)>>(prec-2)
  516. s = (s*isqrt_fast(x<<prec))>>prec
  517. # Compute jtheta3(x)**2
  518. t = a = b = x
  519. while a:
  520. b = (b*x2) >> prec
  521. a = (a*b) >> prec
  522. t += a
  523. t = (MPZ_ONE<<prec) + (t<<1)
  524. t = (t*t)>>prec
  525. # Final formula
  526. p = agm_fixed(s, t, prec)
  527. return (pi_fixed(prec) << prec) // p
  528. def log_taylor(x, prec, r=0):
  529. """
  530. Fixed-point calculation of log(x). It is assumed that x is close
  531. enough to 1 for the Taylor series to converge quickly. Convergence
  532. can be improved by specifying r > 0 to compute
  533. log(x^(1/2^r))*2^r, at the cost of performing r square roots.
  534. The caller must provide sufficient guard bits.
  535. """
  536. for i in xrange(r):
  537. x = isqrt_fast(x<<prec)
  538. one = MPZ_ONE << prec
  539. v = ((x-one)<<prec)//(x+one)
  540. sign = v < 0
  541. if sign:
  542. v = -v
  543. v2 = (v*v) >> prec
  544. v4 = (v2*v2) >> prec
  545. s0 = v
  546. s1 = v//3
  547. v = (v*v4) >> prec
  548. k = 5
  549. while v:
  550. s0 += v // k
  551. k += 2
  552. s1 += v // k
  553. v = (v*v4) >> prec
  554. k += 2
  555. s1 = (s1*v2) >> prec
  556. s = (s0+s1) << (1+r)
  557. if sign:
  558. return -s
  559. return s
  560. def log_taylor_cached(x, prec):
  561. """
  562. Fixed-point computation of log(x), assuming x in (0.5, 2)
  563. and prec <= LOG_TAYLOR_PREC.
  564. """
  565. n = x >> (prec-LOG_TAYLOR_SHIFT)
  566. cached_prec = cache_prec_steps[prec]
  567. dprec = cached_prec - prec
  568. if (n, cached_prec) in log_taylor_cache:
  569. a, log_a = log_taylor_cache[n, cached_prec]
  570. else:
  571. a = n << (cached_prec - LOG_TAYLOR_SHIFT)
  572. log_a = log_taylor(a, cached_prec, 8)
  573. log_taylor_cache[n, cached_prec] = (a, log_a)
  574. a >>= dprec
  575. log_a >>= dprec
  576. u = ((x - a) << prec) // a
  577. v = (u << prec) // ((MPZ_TWO << prec) + u)
  578. v2 = (v*v) >> prec
  579. v4 = (v2*v2) >> prec
  580. s0 = v
  581. s1 = v//3
  582. v = (v*v4) >> prec
  583. k = 5
  584. while v:
  585. s0 += v//k
  586. k += 2
  587. s1 += v//k
  588. v = (v*v4) >> prec
  589. k += 2
  590. s1 = (s1*v2) >> prec
  591. s = (s0+s1) << 1
  592. return log_a + s
  593. def mpf_log(x, prec, rnd=round_fast):
  594. """
  595. Compute the natural logarithm of the mpf value x. If x is negative,
  596. ComplexResult is raised.
  597. """
  598. sign, man, exp, bc = x
  599. #------------------------------------------------------------------
  600. # Handle special values
  601. if not man:
  602. if x == fzero: return fninf
  603. if x == finf: return finf
  604. if x == fnan: return fnan
  605. if sign:
  606. raise ComplexResult("logarithm of a negative number")
  607. wp = prec + 20
  608. #------------------------------------------------------------------
  609. # Handle log(2^n) = log(n)*2.
  610. # Here we catch the only possible exact value, log(1) = 0
  611. if man == 1:
  612. if not exp:
  613. return fzero
  614. return from_man_exp(exp*ln2_fixed(wp), -wp, prec, rnd)
  615. mag = exp+bc
  616. abs_mag = abs(mag)
  617. #------------------------------------------------------------------
  618. # Handle x = 1+eps, where log(x) ~ x. We need to check for
  619. # cancellation when moving to fixed-point math and compensate
  620. # by increasing the precision. Note that abs_mag in (0, 1) <=>
  621. # 0.5 < x < 2 and x != 1
  622. if abs_mag <= 1:
  623. # Calculate t = x-1 to measure distance from 1 in bits
  624. tsign = 1-abs_mag
  625. if tsign:
  626. tman = (MPZ_ONE<<bc) - man
  627. else:
  628. tman = man - (MPZ_ONE<<(bc-1))
  629. tbc = bitcount(tman)
  630. cancellation = bc - tbc
  631. if cancellation > wp:
  632. t = normalize(tsign, tman, abs_mag-bc, tbc, tbc, 'n')
  633. return mpf_perturb(t, tsign, prec, rnd)
  634. else:
  635. wp += cancellation
  636. # TODO: if close enough to 1, we could use Taylor series
  637. # even in the AGM precision range, since the Taylor series
  638. # converges rapidly
  639. #------------------------------------------------------------------
  640. # Another special case:
  641. # n*log(2) is a good enough approximation
  642. if abs_mag > 10000:
  643. if bitcount(abs_mag) > wp:
  644. return from_man_exp(exp*ln2_fixed(wp), -wp, prec, rnd)
  645. #------------------------------------------------------------------
  646. # General case.
  647. # Perform argument reduction using log(x) = log(x*2^n) - n*log(2):
  648. # If we are in the Taylor precision range, choose magnitude 0 or 1.
  649. # If we are in the AGM precision range, choose magnitude -m for
  650. # some large m; benchmarking on one machine showed m = prec/20 to be
  651. # optimal between 1000 and 100,000 digits.
  652. if wp <= LOG_TAYLOR_PREC:
  653. m = log_taylor_cached(lshift(man, wp-bc), wp)
  654. if mag:
  655. m += mag*ln2_fixed(wp)
  656. else:
  657. optimal_mag = -wp//LOG_AGM_MAG_PREC_RATIO
  658. n = optimal_mag - mag
  659. x = mpf_shift(x, n)
  660. wp += (-optimal_mag)
  661. m = -log_agm(to_fixed(x, wp), wp)
  662. m -= n*ln2_fixed(wp)
  663. return from_man_exp(m, -wp, prec, rnd)
  664. def mpf_log_hypot(a, b, prec, rnd):
  665. """
  666. Computes log(sqrt(a^2+b^2)) accurately.
  667. """
  668. # If either a or b is inf/nan/0, assume it to be a
  669. if not b[1]:
  670. a, b = b, a
  671. # a is inf/nan/0
  672. if not a[1]:
  673. # both are inf/nan/0
  674. if not b[1]:
  675. if a == b == fzero:
  676. return fninf
  677. if fnan in (a, b):
  678. return fnan
  679. # at least one term is (+/- inf)^2
  680. return finf
  681. # only a is inf/nan/0
  682. if a == fzero:
  683. # log(sqrt(0+b^2)) = log(|b|)
  684. return mpf_log(mpf_abs(b), prec, rnd)
  685. if a == fnan:
  686. return fnan
  687. return finf
  688. # Exact
  689. a2 = mpf_mul(a,a)
  690. b2 = mpf_mul(b,b)
  691. extra = 20
  692. # Not exact
  693. h2 = mpf_add(a2, b2, prec+extra)
  694. cancelled = mpf_add(h2, fnone, 10)
  695. mag_cancelled = cancelled[2]+cancelled[3]
  696. # Just redo the sum exactly if necessary (could be smarter
  697. # and avoid memory allocation when a or b is precisely 1
  698. # and the other is tiny...)
  699. if cancelled == fzero or mag_cancelled < -extra//2:
  700. h2 = mpf_add(a2, b2, prec+extra-min(a2[2],b2[2]))
  701. return mpf_shift(mpf_log(h2, prec, rnd), -1)
  702. #----------------------------------------------------------------------
  703. # Inverse tangent
  704. #
  705. def atan_newton(x, prec):
  706. if prec >= 100:
  707. r = math.atan(int((x>>(prec-53)))/2.0**53)
  708. else:
  709. r = math.atan(int(x)/2.0**prec)
  710. prevp = 50
  711. r = MPZ(int(r * 2.0**53) >> (53-prevp))
  712. extra_p = 50
  713. for wp in giant_steps(prevp, prec):
  714. wp += extra_p
  715. r = r << (wp-prevp)
  716. cos, sin = cos_sin_fixed(r, wp)
  717. tan = (sin << wp) // cos
  718. a = ((tan-rshift(x, prec-wp)) << wp) // ((MPZ_ONE<<wp) + ((tan**2)>>wp))
  719. r = r - a
  720. prevp = wp
  721. return rshift(r, prevp-prec)
  722. def atan_taylor_get_cached(n, prec):
  723. # Taylor series with caching wins up to huge precisions
  724. # To avoid unnecessary precomputation at low precision, we
  725. # do it in steps
  726. # Round to next power of 2
  727. prec2 = (1<<(bitcount(prec-1))) + 20
  728. dprec = prec2 - prec
  729. if (n, prec2) in atan_taylor_cache:
  730. a, atan_a = atan_taylor_cache[n, prec2]
  731. else:
  732. a = n << (prec2 - ATAN_TAYLOR_SHIFT)
  733. atan_a = atan_newton(a, prec2)
  734. atan_taylor_cache[n, prec2] = (a, atan_a)
  735. return (a >> dprec), (atan_a >> dprec)
  736. def atan_taylor(x, prec):
  737. n = (x >> (prec-ATAN_TAYLOR_SHIFT))
  738. a, atan_a = atan_taylor_get_cached(n, prec)
  739. d = x - a
  740. s0 = v = (d << prec) // ((a**2 >> prec) + (a*d >> prec) + (MPZ_ONE << prec))
  741. v2 = (v**2 >> prec)
  742. v4 = (v2 * v2) >> prec
  743. s1 = v//3
  744. v = (v * v4) >> prec
  745. k = 5
  746. while v:
  747. s0 += v // k
  748. k += 2
  749. s1 += v // k
  750. v = (v * v4) >> prec
  751. k += 2
  752. s1 = (s1 * v2) >> prec
  753. s = s0 - s1
  754. return atan_a + s
  755. def atan_inf(sign, prec, rnd):
  756. if not sign:
  757. return mpf_shift(mpf_pi(prec, rnd), -1)
  758. return mpf_neg(mpf_shift(mpf_pi(prec, negative_rnd[rnd]), -1))
  759. def mpf_atan(x, prec, rnd=round_fast):
  760. sign, man, exp, bc = x
  761. if not man:
  762. if x == fzero: return fzero
  763. if x == finf: return atan_inf(0, prec, rnd)
  764. if x == fninf: return atan_inf(1, prec, rnd)
  765. return fnan
  766. mag = exp + bc
  767. # Essentially infinity
  768. if mag > prec+20:
  769. return atan_inf(sign, prec, rnd)
  770. # Essentially ~ x
  771. if -mag > prec+20:
  772. return mpf_perturb(x, 1-sign, prec, rnd)
  773. wp = prec + 30 + abs(mag)
  774. # For large x, use atan(x) = pi/2 - atan(1/x)
  775. if mag >= 2:
  776. x = mpf_rdiv_int(1, x, wp)
  777. reciprocal = True
  778. else:
  779. reciprocal = False
  780. t = to_fixed(x, wp)
  781. if sign:
  782. t = -t
  783. if wp < ATAN_TAYLOR_PREC:
  784. a = atan_taylor(t, wp)
  785. else:
  786. a = atan_newton(t, wp)
  787. if reciprocal:
  788. a = ((pi_fixed(wp)>>1)+1) - a
  789. if sign:
  790. a = -a
  791. return from_man_exp(a, -wp, prec, rnd)
  792. # TODO: cleanup the special cases
  793. def mpf_atan2(y, x, prec, rnd=round_fast):
  794. xsign, xman, xexp, xbc = x
  795. ysign, yman, yexp, ybc = y
  796. if not yman:
  797. if y == fzero and x != fnan:
  798. if mpf_sign(x) >= 0:
  799. return fzero
  800. return mpf_pi(prec, rnd)
  801. if y in (finf, fninf):
  802. if x in (finf, fninf):
  803. return fnan
  804. # pi/2
  805. if y == finf:
  806. return mpf_shift(mpf_pi(prec, rnd), -1)
  807. # -pi/2
  808. return mpf_neg(mpf_shift(mpf_pi(prec, negative_rnd[rnd]), -1))
  809. return fnan
  810. if ysign:
  811. return mpf_neg(mpf_atan2(mpf_neg(y), x, prec, negative_rnd[rnd]))
  812. if not xman:
  813. if x == fnan:
  814. return fnan
  815. if x == finf:
  816. return fzero
  817. if x == fninf:
  818. return mpf_pi(prec, rnd)
  819. if y == fzero:
  820. return fzero
  821. return mpf_shift(mpf_pi(prec, rnd), -1)
  822. tquo = mpf_atan(mpf_div(y, x, prec+4), prec+4)
  823. if xsign:
  824. return mpf_add(mpf_pi(prec+4), tquo, prec, rnd)
  825. else:
  826. return mpf_pos(tquo, prec, rnd)
  827. def mpf_asin(x, prec, rnd=round_fast):
  828. sign, man, exp, bc = x
  829. if bc+exp > 0 and x not in (fone, fnone):
  830. raise ComplexResult("asin(x) is real only for -1 <= x <= 1")
  831. # asin(x) = 2*atan(x/(1+sqrt(1-x**2)))
  832. wp = prec + 15
  833. a = mpf_mul(x, x)
  834. b = mpf_add(fone, mpf_sqrt(mpf_sub(fone, a, wp), wp), wp)
  835. c = mpf_div(x, b, wp)
  836. return mpf_shift(mpf_atan(c, prec, rnd), 1)
  837. def mpf_acos(x, prec, rnd=round_fast):
  838. # acos(x) = 2*atan(sqrt(1-x**2)/(1+x))
  839. sign, man, exp, bc = x
  840. if bc + exp > 0:
  841. if x not in (fone, fnone):
  842. raise ComplexResult("acos(x) is real only for -1 <= x <= 1")
  843. if x == fnone:
  844. return mpf_pi(prec, rnd)
  845. wp = prec + 15
  846. a = mpf_mul(x, x)
  847. b = mpf_sqrt(mpf_sub(fone, a, wp), wp)
  848. c = mpf_div(b, mpf_add(fone, x, wp), wp)
  849. return mpf_shift(mpf_atan(c, prec, rnd), 1)
  850. def mpf_asinh(x, prec, rnd=round_fast):
  851. wp = prec + 20
  852. sign, man, exp, bc = x
  853. mag = exp+bc
  854. if mag < -8:
  855. if mag < -wp:
  856. return mpf_perturb(x, 1-sign, prec, rnd)
  857. wp += (-mag)
  858. # asinh(x) = log(x+sqrt(x**2+1))
  859. # use reflection symmetry to avoid cancellation
  860. q = mpf_sqrt(mpf_add(mpf_mul(x, x), fone, wp), wp)
  861. q = mpf_add(mpf_abs(x), q, wp)
  862. if sign:
  863. return mpf_neg(mpf_log(q, prec, negative_rnd[rnd]))
  864. else:
  865. return mpf_log(q, prec, rnd)
  866. def mpf_acosh(x, prec, rnd=round_fast):
  867. # acosh(x) = log(x+sqrt(x**2-1))
  868. wp = prec + 15
  869. if mpf_cmp(x, fone) == -1:
  870. raise ComplexResult("acosh(x) is real only for x >= 1")
  871. q = mpf_sqrt(mpf_add(mpf_mul(x,x), fnone, wp), wp)
  872. return mpf_log(mpf_add(x, q, wp), prec, rnd)
  873. def mpf_atanh(x, prec, rnd=round_fast):
  874. # atanh(x) = log((1+x)/(1-x))/2
  875. sign, man, exp, bc = x
  876. if (not man) and exp:
  877. if x in (fzero, fnan):
  878. return x
  879. raise ComplexResult("atanh(x) is real only for -1 <= x <= 1")
  880. mag = bc + exp
  881. if mag > 0:
  882. if mag == 1 and man == 1:
  883. return [finf, fninf][sign]
  884. raise ComplexResult("atanh(x) is real only for -1 <= x <= 1")
  885. wp = prec + 15
  886. if mag < -8:
  887. if mag < -wp:
  888. return mpf_perturb(x, sign, prec, rnd)
  889. wp += (-mag)
  890. a = mpf_add(x, fone, wp)
  891. b = mpf_sub(fone, x, wp)
  892. return mpf_shift(mpf_log(mpf_div(a, b, wp), prec, rnd), -1)
  893. def mpf_fibonacci(x, prec, rnd=round_fast):
  894. sign, man, exp, bc = x
  895. if not man:
  896. if x == fninf:
  897. return fnan
  898. return x
  899. # F(2^n) ~= 2^(2^n)
  900. size = abs(exp+bc)
  901. if exp >= 0:
  902. # Exact
  903. if size < 10 or size <= bitcount(prec):
  904. return from_int(ifib(to_int(x)), prec, rnd)
  905. # Use the modified Binet formula
  906. wp = prec + size + 20
  907. a = mpf_phi(wp)
  908. b = mpf_add(mpf_shift(a, 1), fnone, wp)
  909. u = mpf_pow(a, x, wp)
  910. v = mpf_cos_pi(x, wp)
  911. v = mpf_div(v, u, wp)
  912. u = mpf_sub(u, v, wp)
  913. u = mpf_div(u, b, prec, rnd)
  914. return u
  915. #-------------------------------------------------------------------------------
  916. # Exponential-type functions
  917. #-------------------------------------------------------------------------------
  918. def exponential_series(x, prec, type=0):
  919. """
  920. Taylor series for cosh/sinh or cos/sin.
  921. type = 0 -- returns exp(x) (slightly faster than cosh+sinh)
  922. type = 1 -- returns (cosh(x), sinh(x))
  923. type = 2 -- returns (cos(x), sin(x))
  924. """
  925. if x < 0:
  926. x = -x
  927. sign = 1
  928. else:
  929. sign = 0
  930. r = int(0.5*prec**0.5)
  931. xmag = bitcount(x) - prec
  932. r = max(0, xmag + r)
  933. extra = 10 + 2*max(r,-xmag)
  934. wp = prec + extra
  935. x <<= (extra - r)
  936. one = MPZ_ONE << wp
  937. alt = (type == 2)
  938. if prec < EXP_SERIES_U_CUTOFF:
  939. x2 = a = (x*x) >> wp
  940. x4 = (x2*x2) >> wp
  941. s0 = s1 = MPZ_ZERO
  942. k = 2
  943. while a:
  944. a //= (k-1)*k; s0 += a; k += 2
  945. a //= (k-1)*k; s1 += a; k += 2
  946. a = (a*x4) >> wp
  947. s1 = (x2*s1) >> wp
  948. if alt:
  949. c = s1 - s0 + one
  950. else:
  951. c = s1 + s0 + one
  952. else:
  953. u = int(0.3*prec**0.35)
  954. x2 = a = (x*x) >> wp
  955. xpowers = [one, x2]
  956. for i in xrange(1, u):
  957. xpowers.append((xpowers[-1]*x2)>>wp)
  958. sums = [MPZ_ZERO] * u
  959. k = 2
  960. while a:
  961. for i in xrange(u):
  962. a //= (k-1)*k
  963. if alt and k & 2: sums[i] -= a
  964. else: sums[i] += a
  965. k += 2
  966. a = (a*xpowers[-1]) >> wp
  967. for i in xrange(1, u):
  968. sums[i] = (sums[i]*xpowers[i]) >> wp
  969. c = sum(sums) + one
  970. if type == 0:
  971. s = isqrt_fast(c*c - (one<<wp))
  972. if sign:
  973. v = c - s
  974. else:
  975. v = c + s
  976. for i in xrange(r):
  977. v = (v*v) >> wp
  978. return v >> extra
  979. else:
  980. # Repeatedly apply the double-angle formula
  981. # cosh(2*x) = 2*cosh(x)^2 - 1
  982. # cos(2*x) = 2*cos(x)^2 - 1
  983. pshift = wp-1
  984. for i in xrange(r):
  985. c = ((c*c) >> pshift) - one
  986. # With the abs, this is the same for sinh and sin
  987. s = isqrt_fast(abs((one<<wp) - c*c))
  988. if sign:
  989. s = -s
  990. return (c>>extra), (s>>extra)
  991. def exp_basecase(x, prec):
  992. """
  993. Compute exp(x) as a fixed-point number. Works for any x,
  994. but for speed should have |x| < 1. For an arbitrary number,
  995. use exp(x) = exp(x-m*log(2)) * 2^m where m = floor(x/log(2)).
  996. """
  997. if prec > EXP_COSH_CUTOFF:
  998. return exponential_series(x, prec, 0)
  999. r = int(prec**0.5)
  1000. prec += r
  1001. s0 = s1 = (MPZ_ONE << prec)
  1002. k = 2
  1003. a = x2 = (x*x) >> prec
  1004. while a:
  1005. a //= k; s0 += a; k += 1
  1006. a //= k; s1 += a; k += 1
  1007. a = (a*x2) >> prec
  1008. s1 = (s1*x) >> prec
  1009. s = s0 + s1
  1010. u = r
  1011. while r:
  1012. s = (s*s) >> prec
  1013. r -= 1
  1014. return s >> u
  1015. def exp_expneg_basecase(x, prec):
  1016. """
  1017. Computation of exp(x), exp(-x)
  1018. """
  1019. if prec > EXP_COSH_CUTOFF:
  1020. cosh, sinh = exponential_series(x, prec, 1)
  1021. return cosh+sinh, cosh-sinh
  1022. a = exp_basecase(x, prec)
  1023. b = (MPZ_ONE << (prec+prec)) // a
  1024. return a, b
  1025. def cos_sin_basecase(x, prec):
  1026. """
  1027. Compute cos(x), sin(x) as fixed-point numbers, assuming x
  1028. in [0, pi/2). For an arbitrary number, use x' = x - m*(pi/2)
  1029. where m = floor(x/(pi/2)) along with quarter-period symmetries.
  1030. """
  1031. if prec > COS_SIN_CACHE_PREC:
  1032. return exponential_series(x, prec, 2)
  1033. precs = prec - COS_SIN_CACHE_STEP
  1034. t = x >> precs
  1035. n = int(t)
  1036. if n not in cos_sin_cache:
  1037. w = t<<(10+COS_SIN_CACHE_PREC-COS_SIN_CACHE_STEP)
  1038. cos_t, sin_t = exponential_series(w, 10+COS_SIN_CACHE_PREC, 2)
  1039. cos_sin_cache[n] = (cos_t>>10), (sin_t>>10)
  1040. cos_t, sin_t = cos_sin_cache[n]
  1041. offset = COS_SIN_CACHE_PREC - prec
  1042. cos_t >>= offset
  1043. sin_t >>= offset
  1044. x -= t << precs
  1045. cos = MPZ_ONE << prec
  1046. sin = x
  1047. k = 2
  1048. a = -((x*x) >> prec)
  1049. while a:
  1050. a //= k; cos += a; k += 1; a = (a*x) >> prec
  1051. a //= k; sin += a; k += 1; a = -((a*x) >> prec)
  1052. return ((cos*cos_t-sin*sin_t) >> prec), ((sin*cos_t+cos*sin_t) >> prec)
  1053. def mpf_exp(x, prec, rnd=round_fast):
  1054. sign, man, exp, bc = x
  1055. if man:
  1056. mag = bc + exp
  1057. wp = prec + 14
  1058. if sign:
  1059. man = -man
  1060. # TODO: the best cutoff depends on both x and the precision.
  1061. if prec > 600 and exp >= 0:
  1062. # Need about log2(exp(n)) ~= 1.45*mag extra precision
  1063. e = mpf_e(wp+int(1.45*mag))
  1064. return mpf_pow_int(e, man<<exp, prec, rnd)
  1065. if mag < -wp:
  1066. return mpf_perturb(fone, sign, prec, rnd)
  1067. # |x| >= 2
  1068. if mag > 1:
  1069. # For large arguments: exp(2^mag*(1+eps)) =
  1070. # exp(2^mag)*exp(2^mag*eps) = exp(2^mag)*(1 + 2^mag*eps + ...)
  1071. # so about mag extra bits is required.
  1072. wpmod = wp + mag
  1073. offset = exp + wpmod
  1074. if offset >= 0:
  1075. t = man << offset
  1076. else:
  1077. t = man >> (-offset)
  1078. lg2 = ln2_fixed(wpmod)
  1079. n, t = divmod(t, lg2)
  1080. n = int(n)
  1081. t >>= mag
  1082. else:
  1083. offset = exp + wp
  1084. if offset >= 0:
  1085. t = man << offset
  1086. else:
  1087. t = man >> (-offset)
  1088. n = 0
  1089. man = exp_basecase(t, wp)
  1090. return from_man_exp(man, n-wp, prec, rnd)
  1091. if not exp:
  1092. return fone
  1093. if x == fninf:
  1094. return fzero
  1095. return x
  1096. def mpf_cosh_sinh(x, prec, rnd=round_fast, tanh=0):
  1097. """Simultaneously compute (cosh(x), sinh(x)) for real x"""
  1098. sign, man, exp, bc = x
  1099. if (not man) and exp:
  1100. if tanh:
  1101. if x == finf: return fone
  1102. if x == fninf: return fnone
  1103. return fnan
  1104. if x == finf: return (finf, finf)
  1105. if x == fninf: return (finf, fninf)
  1106. return fnan, fnan
  1107. mag = exp+bc
  1108. wp = prec+14
  1109. if mag < -4:
  1110. # Extremely close to 0, sinh(x) ~= x and cosh(x) ~= 1
  1111. if mag < -wp:
  1112. if tanh:
  1113. return mpf_perturb(x, 1-sign, prec, rnd)
  1114. cosh = mpf_perturb(fone, 0, prec, rnd)
  1115. sinh = mpf_perturb(x, sign, prec, rnd)
  1116. return cosh, sinh
  1117. # Fix for cancellation when computing sinh
  1118. wp += (-mag)
  1119. # Does exp(-2*x) vanish?
  1120. if mag > 10:
  1121. if 3*(1<<(mag-1)) > wp:
  1122. # XXX: rounding
  1123. if tanh:
  1124. return mpf_perturb([fone,fnone][sign], 1-sign, prec, rnd)
  1125. c = s = mpf_shift(mpf_exp(mpf_abs(x), prec, rnd), -1)
  1126. if sign:
  1127. s = mpf_neg(s)
  1128. return c, s
  1129. # |x| > 1
  1130. if mag > 1:
  1131. wpmod = wp + mag
  1132. offset = exp + wpmod
  1133. if offset >= 0:
  1134. t = man << offset
  1135. else:
  1136. t = man >> (-offset)
  1137. lg2 = ln2_fixed(wpmod)
  1138. n, t = divmod(t, lg2)
  1139. n = int(n)
  1140. t >>= mag
  1141. else:
  1142. offset = exp + wp
  1143. if offset >= 0:
  1144. t = man << offset
  1145. else:
  1146. t = man >> (-offset)
  1147. n = 0
  1148. a, b = exp_expneg_basecase(t, wp)
  1149. # TODO: optimize division precision
  1150. cosh = a + (b>>(2*n))
  1151. sinh = a - (b>>(2*n))
  1152. if sign:
  1153. sinh = -sinh
  1154. if tanh:
  1155. man = (sinh << wp) // cosh
  1156. return from_man_exp(man, -wp, prec, rnd)
  1157. else:
  1158. cosh = from_man_exp(cosh, n-wp-1, prec, rnd)
  1159. sinh = from_man_exp(sinh, n-wp-1, prec, rnd)
  1160. return cosh, sinh
  1161. def mod_pi2(man, exp, mag, wp):
  1162. # Reduce to standard interval
  1163. if mag > 0:
  1164. i = 0
  1165. while 1:
  1166. cancellation_prec = 20 << i
  1167. wpmod = wp + mag + cancellation_prec
  1168. pi2 = pi_fixed(wpmod-1)
  1169. pi4 = pi2 >> 1
  1170. offset = wpmod + exp
  1171. if offset >= 0:
  1172. t = man << offset
  1173. else:
  1174. t = man >> (-offset)
  1175. n, y = divmod(t, pi2)
  1176. if y > pi4:
  1177. small = pi2 - y
  1178. else:
  1179. small = y
  1180. if small >> (wp+mag-10):
  1181. n = int(n)
  1182. t = y >> mag
  1183. wp = wpmod - mag
  1184. break
  1185. i += 1
  1186. else:
  1187. wp += (-mag)
  1188. offset = exp + wp
  1189. if offset >= 0:
  1190. t = man << offset
  1191. else:
  1192. t = man >> (-offset)
  1193. n = 0
  1194. return t, n, wp
  1195. def mpf_cos_sin(x, prec, rnd=round_fast, which=0, pi=False):
  1196. """
  1197. which:
  1198. 0 -- return cos(x), sin(x)
  1199. 1 -- return cos(x)
  1200. 2 -- return sin(x)
  1201. 3 -- return tan(x)
  1202. if pi=True, compute for pi*x
  1203. """
  1204. sign, man, exp, bc = x
  1205. if not man:
  1206. if exp:
  1207. c, s = fnan, fnan
  1208. else:
  1209. c, s = fone, fzero
  1210. if which == 0: return c, s
  1211. if which == 1: return c
  1212. if which == 2: return s
  1213. if which == 3: return s
  1214. mag = bc + exp
  1215. wp = prec + 10
  1216. # Extremely small?
  1217. if mag < 0:
  1218. if mag < -wp:
  1219. if pi:
  1220. x = mpf_mul(x, mpf_pi(wp))
  1221. c = mpf_perturb(fone, 1, prec, rnd)
  1222. s = mpf_perturb(x, 1-sign, prec, rnd)
  1223. if which == 0: return c, s
  1224. if which == 1: return c
  1225. if which == 2: return s
  1226. if which == 3: return mpf_perturb(x, sign, prec, rnd)
  1227. if pi:
  1228. if exp >= -1:
  1229. if exp == -1:
  1230. c = fzero
  1231. s = (fone, fnone)[bool(man & 2) ^ sign]
  1232. elif exp == 0:
  1233. c, s = (fnone, fzero)
  1234. else:
  1235. c, s = (fone, fzero)
  1236. if which == 0: return c, s
  1237. if which == 1: return c
  1238. if which == 2: return s
  1239. if which == 3: return mpf_div(s, c, prec, rnd)
  1240. # Subtract nearest half-integer (= mod by pi/2)
  1241. n = ((man >> (-exp-2)) + 1) >> 1
  1242. man = man - (n << (-exp-1))
  1243. mag2 = bitcount(man) + exp
  1244. wp = prec + 10 - mag2
  1245. offset = exp + wp
  1246. if offset >= 0:
  1247. t = man << offset
  1248. else:
  1249. t = man >> (-offset)
  1250. t = (t*pi_fixed(wp)) >> wp
  1251. else:
  1252. t, n, wp = mod_pi2(man, exp, mag, wp)
  1253. c, s = cos_sin_basecase(t, wp)
  1254. m = n & 3
  1255. if m == 1: c, s = -s, c
  1256. elif m == 2: c, s = -c, -s
  1257. elif m == 3: c, s = s, -c
  1258. if sign:
  1259. s = -s
  1260. if which == 0:
  1261. c = from_man_exp(c, -wp, prec, rnd)
  1262. s = from_man_exp(s, -wp, prec, rnd)
  1263. return c, s
  1264. if which == 1:
  1265. return from_man_exp(c, -wp, prec, rnd)
  1266. if which == 2:
  1267. return from_man_exp(s, -wp, prec, rnd)
  1268. if which == 3:
  1269. return from_rational(s, c, prec, rnd)
  1270. def mpf_cos(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 1)
  1271. def mpf_sin(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 2)
  1272. def mpf_tan(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 3)
  1273. def mpf_cos_sin_pi(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 0, 1)
  1274. def mpf_cos_pi(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 1, 1)
  1275. def mpf_sin_pi(x, prec, rnd=round_fast): return mpf_cos_sin(x, prec, rnd, 2, 1)
  1276. def mpf_cosh(x, prec, rnd=round_fast): return mpf_cosh_sinh(x, prec, rnd)[0]
  1277. def mpf_sinh(x, prec, rnd=round_fast): return mpf_cosh_sinh(x, prec, rnd)[1]
  1278. def mpf_tanh(x, prec, rnd=round_fast): return mpf_cosh_sinh(x, prec, rnd, tanh=1)
  1279. # Low-overhead fixed-point versions
  1280. def cos_sin_fixed(x, prec, pi2=None):
  1281. if pi2 is None:
  1282. pi2 = pi_fixed(prec-1)
  1283. n, t = divmod(x, pi2)
  1284. n = int(n)
  1285. c, s = cos_sin_basecase(t, prec)
  1286. m = n & 3
  1287. if m == 0: return c, s
  1288. if m == 1: return -s, c
  1289. if m == 2: return -c, -s
  1290. if m == 3: return s, -c
  1291. def exp_fixed(x, prec, ln2=None):
  1292. if ln2 is None:
  1293. ln2 = ln2_fixed(prec)
  1294. n, t = divmod(x, ln2)
  1295. n = int(n)
  1296. v = exp_basecase(t, prec)
  1297. if n >= 0:
  1298. return v << n
  1299. else:
  1300. return v >> (-n)
  1301. if BACKEND == 'sage':
  1302. try:
  1303. import sage.libs.mpmath.ext_libmp as _lbmp
  1304. mpf_sqrt = _lbmp.mpf_sqrt
  1305. mpf_exp = _lbmp.mpf_exp
  1306. mpf_log = _lbmp.mpf_log
  1307. mpf_cos = _lbmp.mpf_cos
  1308. mpf_sin = _lbmp.mpf_sin
  1309. mpf_pow = _lbmp.mpf_pow
  1310. exp_fixed = _lbmp.exp_fixed
  1311. cos_sin_fixed = _lbmp.cos_sin_fixed
  1312. log_int_fixed = _lbmp.log_int_fixed
  1313. except (ImportError, AttributeError):
  1314. print("Warning: Sage imports in libelefun failed")