dd_real.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. /*
  2. * src/dd_real.cc
  3. *
  4. * This work was supported by the Director, Office of Science, Division
  5. * of Mathematical, Information, and Computational Sciences of the
  6. * U.S. Department of Energy under contract number DE-AC03-76SF00098.
  7. *
  8. * Copyright (c) 2000-2007
  9. *
  10. * Contains implementation of non-inlined functions of double-double
  11. * package. Inlined functions are found in dd_inline.h (in include directory).
  12. */
  13. #include <cstdlib>
  14. #include <cstdio>
  15. #include <cmath>
  16. #include <cstring>
  17. #include <iostream>
  18. #include <iomanip>
  19. #include <string>
  20. #include "config.h"
  21. #include <qd/dd_real.h>
  22. #include "util.h"
  23. #include <qd/bits.h>
  24. #ifndef QD_INLINE
  25. #include <qd/dd_inline.h>
  26. #endif
  27. using std::cout;
  28. using std::cerr;
  29. using std::endl;
  30. using std::ostream;
  31. using std::istream;
  32. using std::ios_base;
  33. using std::string;
  34. using std::setw;
  35. /* This routine is called whenever a fatal error occurs. */
  36. void dd_real::error(const char *msg) {
  37. if (msg) { cerr << "ERROR " << msg << endl; }
  38. }
  39. /* Computes the square root of the double-double number dd.
  40. NOTE: dd must be a non-negative number. */
  41. QD_API dd_real sqrt(const dd_real &a) {
  42. /* Strategy: Use Karp's trick: if x is an approximation
  43. to sqrt(a), then
  44. sqrt(a) = a*x + [a - (a*x)^2] * x / 2 (approx)
  45. The approximation is accurate to twice the accuracy of x.
  46. Also, the multiplication (a*x) and [-]*x can be done with
  47. only half the precision.
  48. */
  49. if (a.is_zero())
  50. return 0.0;
  51. if (a.is_negative()) {
  52. dd_real::error("(dd_real::sqrt): Negative argument.");
  53. return dd_real::_nan;
  54. }
  55. double x = 1.0 / std::sqrt(a.x[0]);
  56. double ax = a.x[0] * x;
  57. return dd_real::add(ax, (a - dd_real::sqr(ax)).x[0] * (x * 0.5));
  58. }
  59. /* Computes the square root of a double in double-double precision.
  60. NOTE: d must not be negative. */
  61. dd_real dd_real::sqrt(double d) {
  62. return ::sqrt(dd_real(d));
  63. }
  64. /* Computes the n-th root of the double-double number a.
  65. NOTE: n must be a positive integer.
  66. NOTE: If n is even, then a must not be negative. */
  67. dd_real nroot(const dd_real &a, int n) {
  68. /* Strategy: Use Newton iteration for the function
  69. f(x) = x^(-n) - a
  70. to find its root a^{-1/n}. The iteration is thus
  71. x' = x + x * (1 - a * x^n) / n
  72. which converges quadratically. We can then find
  73. a^{1/n} by taking the reciprocal.
  74. */
  75. if (n <= 0) {
  76. dd_real::error("(dd_real::nroot): N must be positive.");
  77. return dd_real::_nan;
  78. }
  79. if (n%2 == 0 && a.is_negative()) {
  80. dd_real::error("(dd_real::nroot): Negative argument.");
  81. return dd_real::_nan;
  82. }
  83. if (n == 1) {
  84. return a;
  85. }
  86. if (n == 2) {
  87. return sqrt(a);
  88. }
  89. if (a.is_zero())
  90. return 0.0;
  91. /* Note a^{-1/n} = exp(-log(a)/n) */
  92. dd_real r = abs(a);
  93. dd_real x = std::exp(-std::log(r.x[0]) / n);
  94. /* Perform Newton's iteration. */
  95. x += x * (1.0 - r * npwr(x, n)) / static_cast<double>(n);
  96. if (a.x[0] < 0.0)
  97. x = -x;
  98. return 1.0/x;
  99. }
  100. /* Computes the n-th power of a double-double number.
  101. NOTE: 0^0 causes an error. */
  102. dd_real npwr(const dd_real &a, int n) {
  103. if (n == 0) {
  104. if (a.is_zero()) {
  105. dd_real::error("(dd_real::npwr): Invalid argument.");
  106. return dd_real::_nan;
  107. }
  108. return 1.0;
  109. }
  110. dd_real r = a;
  111. dd_real s = 1.0;
  112. int N = std::abs(n);
  113. if (N > 1) {
  114. /* Use binary exponentiation */
  115. while (N > 0) {
  116. if (N % 2 == 1) {
  117. s *= r;
  118. }
  119. N /= 2;
  120. if (N > 0)
  121. r = sqr(r);
  122. }
  123. } else {
  124. s = r;
  125. }
  126. /* Compute the reciprocal if n is negative. */
  127. if (n < 0)
  128. return (1.0 / s);
  129. return s;
  130. }
  131. dd_real pow(const dd_real &a, int n) {
  132. return npwr(a, n);
  133. }
  134. dd_real pow(const dd_real &a, const dd_real &b) {
  135. return exp(b * log(a));
  136. }
  137. static const int n_inv_fact = 15;
  138. static const double inv_fact[n_inv_fact][2] = {
  139. { 1.66666666666666657e-01, 9.25185853854297066e-18},
  140. { 4.16666666666666644e-02, 2.31296463463574266e-18},
  141. { 8.33333333333333322e-03, 1.15648231731787138e-19},
  142. { 1.38888888888888894e-03, -5.30054395437357706e-20},
  143. { 1.98412698412698413e-04, 1.72095582934207053e-22},
  144. { 2.48015873015873016e-05, 2.15119478667758816e-23},
  145. { 2.75573192239858925e-06, -1.85839327404647208e-22},
  146. { 2.75573192239858883e-07, 2.37677146222502973e-23},
  147. { 2.50521083854417202e-08, -1.44881407093591197e-24},
  148. { 2.08767569878681002e-09, -1.20734505911325997e-25},
  149. { 1.60590438368216133e-10, 1.25852945887520981e-26},
  150. { 1.14707455977297245e-11, 2.06555127528307454e-28},
  151. { 7.64716373181981641e-13, 7.03872877733453001e-30},
  152. { 4.77947733238738525e-14, 4.39920548583408126e-31},
  153. { 2.81145725434552060e-15, 1.65088427308614326e-31}
  154. };
  155. /* Exponential. Computes exp(x) in double-double precision. */
  156. dd_real exp(const dd_real &a) {
  157. /* Strategy: We first reduce the size of x by noting that
  158. exp(kr + m * log(2)) = 2^m * exp(r)^k
  159. where m and k are integers. By choosing m appropriately
  160. we can make |kr| <= log(2) / 2 = 0.347. Then exp(r) is
  161. evaluated using the familiar Taylor series. Reducing the
  162. argument substantially speeds up the convergence. */
  163. const double k = 512.0;
  164. const double inv_k = 1.0 / k;
  165. if (a.x[0] <= -709.0)
  166. return 0.0;
  167. if (a.x[0] >= 709.0)
  168. return dd_real::_inf;
  169. if (a.is_zero())
  170. return 1.0;
  171. if (a.is_one())
  172. return dd_real::_e;
  173. double m = std::floor(a.x[0] / dd_real::_log2.x[0] + 0.5);
  174. dd_real r = mul_pwr2(a - dd_real::_log2 * m, inv_k);
  175. dd_real s, t, p;
  176. p = sqr(r);
  177. s = r + mul_pwr2(p, 0.5);
  178. p *= r;
  179. t = p * dd_real(inv_fact[0][0], inv_fact[0][1]);
  180. int i = 0;
  181. do {
  182. s += t;
  183. p *= r;
  184. ++i;
  185. t = p * dd_real(inv_fact[i][0], inv_fact[i][1]);
  186. } while (std::abs(to_double(t)) > inv_k * dd_real::_eps && i < 5);
  187. s += t;
  188. s = mul_pwr2(s, 2.0) + sqr(s);
  189. s = mul_pwr2(s, 2.0) + sqr(s);
  190. s = mul_pwr2(s, 2.0) + sqr(s);
  191. s = mul_pwr2(s, 2.0) + sqr(s);
  192. s = mul_pwr2(s, 2.0) + sqr(s);
  193. s = mul_pwr2(s, 2.0) + sqr(s);
  194. s = mul_pwr2(s, 2.0) + sqr(s);
  195. s = mul_pwr2(s, 2.0) + sqr(s);
  196. s = mul_pwr2(s, 2.0) + sqr(s);
  197. s += 1.0;
  198. return ldexp(s, static_cast<int>(m));
  199. }
  200. /* Logarithm. Computes log(x) in double-double precision.
  201. This is a natural logarithm (i.e., base e). */
  202. dd_real log(const dd_real &a) {
  203. /* Strategy. The Taylor series for log converges much more
  204. slowly than that of exp, due to the lack of the factorial
  205. term in the denominator. Hence this routine instead tries
  206. to determine the root of the function
  207. f(x) = exp(x) - a
  208. using Newton iteration. The iteration is given by
  209. x' = x - f(x)/f'(x)
  210. = x - (1 - a * exp(-x))
  211. = x + a * exp(-x) - 1.
  212. Only one iteration is needed, since Newton's iteration
  213. approximately doubles the number of digits per iteration. */
  214. if (a.is_one()) {
  215. return 0.0;
  216. }
  217. if (a.x[0] <= 0.0) {
  218. dd_real::error("(dd_real::log): Non-positive argument.");
  219. return dd_real::_nan;
  220. }
  221. dd_real x = std::log(a.x[0]); /* Initial approximation */
  222. x = x + a * exp(-x) - 1.0;
  223. return x;
  224. }
  225. dd_real log10(const dd_real &a) {
  226. return log(a) / dd_real::_log10;
  227. }
  228. static const dd_real _pi16 = dd_real(1.963495408493620697e-01,
  229. 7.654042494670957545e-18);
  230. /* Table of sin(k * pi/16) and cos(k * pi/16). */
  231. static const double sin_table [4][2] = {
  232. {1.950903220161282758e-01, -7.991079068461731263e-18},
  233. {3.826834323650897818e-01, -1.005077269646158761e-17},
  234. {5.555702330196021776e-01, 4.709410940561676821e-17},
  235. {7.071067811865475727e-01, -4.833646656726456726e-17}
  236. };
  237. static const double cos_table [4][2] = {
  238. {9.807852804032304306e-01, 1.854693999782500573e-17},
  239. {9.238795325112867385e-01, 1.764504708433667706e-17},
  240. {8.314696123025452357e-01, 1.407385698472802389e-18},
  241. {7.071067811865475727e-01, -4.833646656726456726e-17}
  242. };
  243. /* Computes sin(a) using Taylor series.
  244. Assumes |a| <= pi/32. */
  245. static dd_real sin_taylor(const dd_real &a) {
  246. const double thresh = 0.5 * std::abs(to_double(a)) * dd_real::_eps;
  247. dd_real r, s, t, x;
  248. if (a.is_zero()) {
  249. return 0.0;
  250. }
  251. int i = 0;
  252. x = -sqr(a);
  253. s = a;
  254. r = a;
  255. do {
  256. r *= x;
  257. t = r * dd_real(inv_fact[i][0], inv_fact[i][1]);
  258. s += t;
  259. i += 2;
  260. } while (i < n_inv_fact && std::abs(to_double(t)) > thresh);
  261. return s;
  262. }
  263. static dd_real cos_taylor(const dd_real &a) {
  264. const double thresh = 0.5 * dd_real::_eps;
  265. dd_real r, s, t, x;
  266. if (a.is_zero()) {
  267. return 1.0;
  268. }
  269. x = -sqr(a);
  270. r = x;
  271. s = 1.0 + mul_pwr2(r, 0.5);
  272. int i = 1;
  273. do {
  274. r *= x;
  275. t = r * dd_real(inv_fact[i][0], inv_fact[i][1]);
  276. s += t;
  277. i += 2;
  278. } while (i < n_inv_fact && std::abs(to_double(t)) > thresh);
  279. return s;
  280. }
  281. static void sincos_taylor(const dd_real &a,
  282. dd_real &sin_a, dd_real &cos_a) {
  283. if (a.is_zero()) {
  284. sin_a = 0.0;
  285. cos_a = 1.0;
  286. return;
  287. }
  288. sin_a = sin_taylor(a);
  289. cos_a = sqrt(1.0 - sqr(sin_a));
  290. }
  291. dd_real sin(const dd_real &a) {
  292. /* Strategy. To compute sin(x), we choose integers a, b so that
  293. x = s + a * (pi/2) + b * (pi/16)
  294. and |s| <= pi/32. Using the fact that
  295. sin(pi/16) = 0.5 * sqrt(2 - sqrt(2 + sqrt(2)))
  296. we can compute sin(x) from sin(s), cos(s). This greatly
  297. increases the convergence of the sine Taylor series. */
  298. if (a.is_zero()) {
  299. return 0.0;
  300. }
  301. // approximately reduce modulo 2*pi
  302. dd_real z = nint(a / dd_real::_2pi);
  303. dd_real r = a - dd_real::_2pi * z;
  304. // approximately reduce modulo pi/2 and then modulo pi/16.
  305. dd_real t;
  306. double q = std::floor(r.x[0] / dd_real::_pi2.x[0] + 0.5);
  307. t = r - dd_real::_pi2 * q;
  308. int j = static_cast<int>(q);
  309. q = std::floor(t.x[0] / _pi16.x[0] + 0.5);
  310. t -= _pi16 * q;
  311. int k = static_cast<int>(q);
  312. int abs_k = std::abs(k);
  313. if (j < -2 || j > 2) {
  314. dd_real::error("(dd_real::sin): Cannot reduce modulo pi/2.");
  315. return dd_real::_nan;
  316. }
  317. if (abs_k > 4) {
  318. dd_real::error("(dd_real::sin): Cannot reduce modulo pi/16.");
  319. return dd_real::_nan;
  320. }
  321. if (k == 0) {
  322. switch (j) {
  323. case 0:
  324. return sin_taylor(t);
  325. case 1:
  326. return cos_taylor(t);
  327. case -1:
  328. return -cos_taylor(t);
  329. default:
  330. return -sin_taylor(t);
  331. }
  332. }
  333. dd_real u(cos_table[abs_k-1][0], cos_table[abs_k-1][1]);
  334. dd_real v(sin_table[abs_k-1][0], sin_table[abs_k-1][1]);
  335. dd_real sin_t, cos_t;
  336. sincos_taylor(t, sin_t, cos_t);
  337. if (j == 0) {
  338. if (k > 0) {
  339. r = u * sin_t + v * cos_t;
  340. } else {
  341. r = u * sin_t - v * cos_t;
  342. }
  343. } else if (j == 1) {
  344. if (k > 0) {
  345. r = u * cos_t - v * sin_t;
  346. } else {
  347. r = u * cos_t + v * sin_t;
  348. }
  349. } else if (j == -1) {
  350. if (k > 0) {
  351. r = v * sin_t - u * cos_t;
  352. } else if (k < 0) {
  353. r = -u * cos_t - v * sin_t;
  354. }
  355. } else {
  356. if (k > 0) {
  357. r = -u * sin_t - v * cos_t;
  358. } else {
  359. r = v * cos_t - u * sin_t;
  360. }
  361. }
  362. return r;
  363. }
  364. dd_real cos(const dd_real &a) {
  365. if (a.is_zero()) {
  366. return 1.0;
  367. }
  368. // approximately reduce modulo 2*pi
  369. dd_real z = nint(a / dd_real::_2pi);
  370. dd_real r = a - z * dd_real::_2pi;
  371. // approximately reduce modulo pi/2 and then modulo pi/16
  372. dd_real t;
  373. double q = std::floor(r.x[0] / dd_real::_pi2.x[0] + 0.5);
  374. t = r - dd_real::_pi2 * q;
  375. int j = static_cast<int>(q);
  376. q = std::floor(t.x[0] / _pi16.x[0] + 0.5);
  377. t -= _pi16 * q;
  378. int k = static_cast<int>(q);
  379. int abs_k = std::abs(k);
  380. if (j < -2 || j > 2) {
  381. dd_real::error("(dd_real::cos): Cannot reduce modulo pi/2.");
  382. return dd_real::_nan;
  383. }
  384. if (abs_k > 4) {
  385. dd_real::error("(dd_real::cos): Cannot reduce modulo pi/16.");
  386. return dd_real::_nan;
  387. }
  388. if (k == 0) {
  389. switch (j) {
  390. case 0:
  391. return cos_taylor(t);
  392. case 1:
  393. return -sin_taylor(t);
  394. case -1:
  395. return sin_taylor(t);
  396. default:
  397. return -cos_taylor(t);
  398. }
  399. }
  400. dd_real sin_t, cos_t;
  401. sincos_taylor(t, sin_t, cos_t);
  402. dd_real u(cos_table[abs_k-1][0], cos_table[abs_k-1][1]);
  403. dd_real v(sin_table[abs_k-1][0], sin_table[abs_k-1][1]);
  404. if (j == 0) {
  405. if (k > 0) {
  406. r = u * cos_t - v * sin_t;
  407. } else {
  408. r = u * cos_t + v * sin_t;
  409. }
  410. } else if (j == 1) {
  411. if (k > 0) {
  412. r = - u * sin_t - v * cos_t;
  413. } else {
  414. r = v * cos_t - u * sin_t;
  415. }
  416. } else if (j == -1) {
  417. if (k > 0) {
  418. r = u * sin_t + v * cos_t;
  419. } else {
  420. r = u * sin_t - v * cos_t;
  421. }
  422. } else {
  423. if (k > 0) {
  424. r = v * sin_t - u * cos_t;
  425. } else {
  426. r = - u * cos_t - v * sin_t;
  427. }
  428. }
  429. return r;
  430. }
  431. void sincos(const dd_real &a, dd_real &sin_a, dd_real &cos_a) {
  432. if (a.is_zero()) {
  433. sin_a = 0.0;
  434. cos_a = 1.0;
  435. return;
  436. }
  437. // approximately reduce modulo 2*pi
  438. dd_real z = nint(a / dd_real::_2pi);
  439. dd_real r = a - dd_real::_2pi * z;
  440. // approximately reduce module pi/2 and pi/16
  441. dd_real t;
  442. double q = std::floor(r.x[0] / dd_real::_pi2.x[0] + 0.5);
  443. t = r - dd_real::_pi2 * q;
  444. int j = static_cast<int>(q);
  445. int abs_j = std::abs(j);
  446. q = std::floor(t.x[0] / _pi16.x[0] + 0.5);
  447. t -= _pi16 * q;
  448. int k = static_cast<int>(q);
  449. int abs_k = std::abs(k);
  450. if (abs_j > 2) {
  451. dd_real::error("(dd_real::sincos): Cannot reduce modulo pi/2.");
  452. cos_a = sin_a = dd_real::_nan;
  453. return;
  454. }
  455. if (abs_k > 4) {
  456. dd_real::error("(dd_real::sincos): Cannot reduce modulo pi/16.");
  457. cos_a = sin_a = dd_real::_nan;
  458. return;
  459. }
  460. dd_real sin_t, cos_t;
  461. dd_real s, c;
  462. sincos_taylor(t, sin_t, cos_t);
  463. if (abs_k == 0) {
  464. s = sin_t;
  465. c = cos_t;
  466. } else {
  467. dd_real u(cos_table[abs_k-1][0], cos_table[abs_k-1][1]);
  468. dd_real v(sin_table[abs_k-1][0], sin_table[abs_k-1][1]);
  469. if (k > 0) {
  470. s = u * sin_t + v * cos_t;
  471. c = u * cos_t - v * sin_t;
  472. } else {
  473. s = u * sin_t - v * cos_t;
  474. c = u * cos_t + v * sin_t;
  475. }
  476. }
  477. if (abs_j == 0) {
  478. sin_a = s;
  479. cos_a = c;
  480. } else if (j == 1) {
  481. sin_a = c;
  482. cos_a = -s;
  483. } else if (j == -1) {
  484. sin_a = -c;
  485. cos_a = s;
  486. } else {
  487. sin_a = -s;
  488. cos_a = -c;
  489. }
  490. }
  491. dd_real atan(const dd_real &a) {
  492. return atan2(a, dd_real(1.0));
  493. }
  494. dd_real atan2(const dd_real &y, const dd_real &x) {
  495. /* Strategy: Instead of using Taylor series to compute
  496. arctan, we instead use Newton's iteration to solve
  497. the equation
  498. sin(z) = y/r or cos(z) = x/r
  499. where r = sqrt(x^2 + y^2).
  500. The iteration is given by
  501. z' = z + (y - sin(z)) / cos(z) (for equation 1)
  502. z' = z - (x - cos(z)) / sin(z) (for equation 2)
  503. Here, x and y are normalized so that x^2 + y^2 = 1.
  504. If |x| > |y|, then first iteration is used since the
  505. denominator is larger. Otherwise, the second is used.
  506. */
  507. if (x.is_zero()) {
  508. if (y.is_zero()) {
  509. /* Both x and y is zero. */
  510. dd_real::error("(dd_real::atan2): Both arguments zero.");
  511. return dd_real::_nan;
  512. }
  513. return (y.is_positive()) ? dd_real::_pi2 : -dd_real::_pi2;
  514. } else if (y.is_zero()) {
  515. return (x.is_positive()) ? dd_real(0.0) : dd_real::_pi;
  516. }
  517. if (x == y) {
  518. return (y.is_positive()) ? dd_real::_pi4 : -dd_real::_3pi4;
  519. }
  520. if (x == -y) {
  521. return (y.is_positive()) ? dd_real::_3pi4 : -dd_real::_pi4;
  522. }
  523. dd_real r = sqrt(sqr(x) + sqr(y));
  524. dd_real xx = x / r;
  525. dd_real yy = y / r;
  526. /* Compute double precision approximation to atan. */
  527. dd_real z = std::atan2(to_double(y), to_double(x));
  528. dd_real sin_z, cos_z;
  529. if (std::abs(xx.x[0]) > std::abs(yy.x[0])) {
  530. /* Use Newton iteration 1. z' = z + (y - sin(z)) / cos(z) */
  531. sincos(z, sin_z, cos_z);
  532. z += (yy - sin_z) / cos_z;
  533. } else {
  534. /* Use Newton iteration 2. z' = z - (x - cos(z)) / sin(z) */
  535. sincos(z, sin_z, cos_z);
  536. z -= (xx - cos_z) / sin_z;
  537. }
  538. return z;
  539. }
  540. dd_real tan(const dd_real &a) {
  541. dd_real s, c;
  542. sincos(a, s, c);
  543. return s/c;
  544. }
  545. dd_real asin(const dd_real &a) {
  546. dd_real abs_a = abs(a);
  547. if (abs_a > 1.0) {
  548. dd_real::error("(dd_real::asin): Argument out of domain.");
  549. return dd_real::_nan;
  550. }
  551. if (abs_a.is_one()) {
  552. return (a.is_positive()) ? dd_real::_pi2 : -dd_real::_pi2;
  553. }
  554. return atan2(a, sqrt(1.0 - sqr(a)));
  555. }
  556. dd_real acos(const dd_real &a) {
  557. dd_real abs_a = abs(a);
  558. if (abs_a > 1.0) {
  559. dd_real::error("(dd_real::acos): Argument out of domain.");
  560. return dd_real::_nan;
  561. }
  562. if (abs_a.is_one()) {
  563. return (a.is_positive()) ? dd_real(0.0) : dd_real::_pi;
  564. }
  565. return atan2(sqrt(1.0 - sqr(a)), a);
  566. }
  567. dd_real sinh(const dd_real &a) {
  568. if (a.is_zero()) {
  569. return 0.0;
  570. }
  571. if (abs(a) > 0.05) {
  572. dd_real ea = exp(a);
  573. return mul_pwr2(ea - inv(ea), 0.5);
  574. }
  575. /* since a is small, using the above formula gives
  576. a lot of cancellation. So use Taylor series. */
  577. dd_real s = a;
  578. dd_real t = a;
  579. dd_real r = sqr(t);
  580. double m = 1.0;
  581. double thresh = std::abs((to_double(a)) * dd_real::_eps);
  582. do {
  583. m += 2.0;
  584. t *= r;
  585. t /= (m-1) * m;
  586. s += t;
  587. } while (abs(t) > thresh);
  588. return s;
  589. }
  590. dd_real cosh(const dd_real &a) {
  591. if (a.is_zero()) {
  592. return 1.0;
  593. }
  594. dd_real ea = exp(a);
  595. return mul_pwr2(ea + inv(ea), 0.5);
  596. }
  597. dd_real tanh(const dd_real &a) {
  598. if (a.is_zero()) {
  599. return 0.0;
  600. }
  601. if (std::abs(to_double(a)) > 0.05) {
  602. dd_real ea = exp(a);
  603. dd_real inv_ea = inv(ea);
  604. return (ea - inv_ea) / (ea + inv_ea);
  605. } else {
  606. dd_real s, c;
  607. s = sinh(a);
  608. c = sqrt(1.0 + sqr(s));
  609. return s / c;
  610. }
  611. }
  612. void sincosh(const dd_real &a, dd_real &s, dd_real &c) {
  613. if (std::abs(to_double(a)) <= 0.05) {
  614. s = sinh(a);
  615. c = sqrt(1.0 + sqr(s));
  616. } else {
  617. dd_real ea = exp(a);
  618. dd_real inv_ea = inv(ea);
  619. s = mul_pwr2(ea - inv_ea, 0.5);
  620. c = mul_pwr2(ea + inv_ea, 0.5);
  621. }
  622. }
  623. dd_real asinh(const dd_real &a) {
  624. return log(a + sqrt(sqr(a) + 1.0));
  625. }
  626. dd_real acosh(const dd_real &a) {
  627. if (a < 1.0) {
  628. dd_real::error("(dd_real::acosh): Argument out of domain.");
  629. return dd_real::_nan;
  630. }
  631. return log(a + sqrt(sqr(a) - 1.0));
  632. }
  633. dd_real atanh(const dd_real &a) {
  634. if (abs(a) >= 1.0) {
  635. dd_real::error("(dd_real::atanh): Argument out of domain.");
  636. return dd_real::_nan;
  637. }
  638. return mul_pwr2(log((1.0 + a) / (1.0 - a)), 0.5);
  639. }
  640. QD_API dd_real fmod(const dd_real &a, const dd_real &b) {
  641. dd_real n = aint(a / b);
  642. return (a - b * n);
  643. }
  644. QD_API dd_real ddrand() {
  645. static const double m_const = 4.6566128730773926e-10; /* = 2^{-31} */
  646. double m = m_const;
  647. dd_real r = 0.0;
  648. double d;
  649. /* Strategy: Generate 31 bits at a time, using lrand48
  650. random number generator. Shift the bits, and reapeat
  651. 4 times. */
  652. for (int i = 0; i < 4; i++, m *= m_const) {
  653. // d = lrand48() * m;
  654. d = std::rand() * m;
  655. r += d;
  656. }
  657. return r;
  658. }
  659. /* polyeval(c, n, x)
  660. Evaluates the given n-th degree polynomial at x.
  661. The polynomial is given by the array of (n+1) coefficients. */
  662. dd_real polyeval(const dd_real *c, int n, const dd_real &x) {
  663. /* Just use Horner's method of polynomial evaluation. */
  664. dd_real r = c[n];
  665. for (int i = n-1; i >= 0; i--) {
  666. r *= x;
  667. r += c[i];
  668. }
  669. return r;
  670. }
  671. /* polyroot(c, n, x0)
  672. Given an n-th degree polynomial, finds a root close to
  673. the given guess x0. Note that this uses simple Newton
  674. iteration scheme, and does not work for multiple roots. */
  675. QD_API dd_real polyroot(const dd_real *c, int n,
  676. const dd_real &x0, int max_iter, double thresh) {
  677. dd_real x = x0;
  678. dd_real f;
  679. dd_real *d = new dd_real[n];
  680. bool conv = false;
  681. int i;
  682. double max_c = std::abs(to_double(c[0]));
  683. double v;
  684. if (thresh == 0.0) thresh = dd_real::_eps;
  685. /* Compute the coefficients of the derivatives. */
  686. for (i = 1; i <= n; i++) {
  687. v = std::abs(to_double(c[i]));
  688. if (v > max_c) max_c = v;
  689. d[i-1] = c[i] * static_cast<double>(i);
  690. }
  691. thresh *= max_c;
  692. /* Newton iteration. */
  693. for (i = 0; i < max_iter; i++) {
  694. f = polyeval(c, n, x);
  695. if (abs(f) < thresh) {
  696. conv = true;
  697. break;
  698. }
  699. x -= (f / polyeval(d, n-1, x));
  700. }
  701. delete [] d;
  702. if (!conv) {
  703. dd_real::error("(dd_real::polyroot): Failed to converge.");
  704. return dd_real::_nan;
  705. }
  706. return x;
  707. }
  708. /* Constructor. Reads a double-double number from the string s
  709. and constructs a double-double number. */
  710. dd_real::dd_real(const char *s) {
  711. if (dd_real::read(s, *this)) {
  712. dd_real::error("(dd_real::dd_real): INPUT ERROR.");
  713. *this = dd_real::_nan;
  714. }
  715. }
  716. dd_real &dd_real::operator=(const char *s) {
  717. if (dd_real::read(s, *this)) {
  718. dd_real::error("(dd_real::operator=): INPUT ERROR.");
  719. *this = dd_real::_nan;
  720. }
  721. return *this;
  722. }
  723. /* Outputs the double-double number dd. */
  724. ostream &operator<<(ostream &os, const dd_real &dd) {
  725. bool showpos = (os.flags() & ios_base::showpos) != 0;
  726. bool uppercase = (os.flags() & ios_base::uppercase) != 0;
  727. return os << dd.to_string(os.precision(), os.width(), os.flags(),
  728. showpos, uppercase, os.fill());
  729. }
  730. /* Reads in the double-double number a. */
  731. istream &operator>>(istream &s, dd_real &a) {
  732. char str[255];
  733. s >> str;
  734. a = dd_real(str);
  735. return s;
  736. }
  737. void dd_real::to_digits(char *s, int &expn, int precision) const {
  738. int D = precision + 1; /* number of digits to compute */
  739. dd_real r = abs(*this);
  740. int e; /* exponent */
  741. int i, d;
  742. if (x[0] == 0.0) {
  743. /* this == 0.0 */
  744. expn = 0;
  745. for (i = 0; i < precision; i++) s[i] = '0';
  746. return;
  747. }
  748. /* First determine the (approximate) exponent. */
  749. e = to_int(std::floor(std::log10(std::abs(x[0]))));
  750. if (e < -300) {
  751. r *= dd_real(10.0) ^ 300;
  752. r /= dd_real(10.0) ^ (e + 300);
  753. } else if (e > 300) {
  754. r = ldexp(r, -53);
  755. r /= dd_real(10.0) ^ e;
  756. r = ldexp(r, 53);
  757. } else {
  758. r /= dd_real(10.0) ^ e;
  759. }
  760. /* Fix exponent if we are off by one */
  761. if (r >= 10.0) {
  762. r /= 10.0;
  763. e++;
  764. } else if (r < 1.0) {
  765. r *= 10.0;
  766. e--;
  767. }
  768. if (r >= 10.0 || r < 1.0) {
  769. dd_real::error("(dd_real::to_digits): can't compute exponent.");
  770. return;
  771. }
  772. /* Extract the digits */
  773. for (i = 0; i < D; i++) {
  774. d = static_cast<int>(r.x[0]);
  775. r -= d;
  776. r *= 10.0;
  777. s[i] = static_cast<char>(d + '0');
  778. }
  779. /* Fix out of range digits. */
  780. for (i = D-1; i > 0; i--) {
  781. if (s[i] < '0') {
  782. s[i-1]--;
  783. s[i] += 10;
  784. } else if (s[i] > '9') {
  785. s[i-1]++;
  786. s[i] -= 10;
  787. }
  788. }
  789. if (s[0] <= '0') {
  790. dd_real::error("(dd_real::to_digits): non-positive leading digit.");
  791. return;
  792. }
  793. /* Round, handle carry */
  794. if (s[D-1] >= '5') {
  795. s[D-2]++;
  796. i = D-2;
  797. while (i > 0 && s[i] > '9') {
  798. s[i] -= 10;
  799. s[--i]++;
  800. }
  801. }
  802. /* If first digit is 10, shift everything. */
  803. if (s[0] > '9') {
  804. e++;
  805. for (i = precision; i >= 2; i--) s[i] = s[i-1];
  806. s[0] = '1';
  807. s[1] = '0';
  808. }
  809. s[precision] = 0;
  810. expn = e;
  811. }
  812. /* Writes the double-double number into the character array s of length len.
  813. The integer d specifies how many significant digits to write.
  814. The string s must be able to hold at least (d+8) characters.
  815. showpos indicates whether to use the + sign, and uppercase indicates
  816. whether the E or e is to be used for the exponent. */
  817. void dd_real::write(char *s, int len, int precision,
  818. bool showpos, bool uppercase) const {
  819. string str = to_string(precision, 0, ios_base::scientific, showpos, uppercase);
  820. std::strncpy(s, str.c_str(), len-1);
  821. s[len-1] = 0;
  822. }
  823. void round_string(char *s, int precision, int *offset){
  824. /*
  825. Input string must be all digits or errors will occur.
  826. */
  827. int i;
  828. int D = precision ;
  829. /* Round, handle carry */
  830. if (D>0 && s[D] >= '5') {
  831. s[D-1]++;
  832. i = D-1;
  833. while (i > 0 && s[i] > '9') {
  834. s[i] -= 10;
  835. s[--i]++;
  836. }
  837. }
  838. /* If first digit is 10, shift everything. */
  839. if (s[0] > '9') {
  840. // e++; // don't modify exponent here
  841. for (i = precision; i >= 1; i--) s[i+1] = s[i];
  842. s[0] = '1';
  843. s[1] = '0';
  844. (*offset)++ ; // now offset needs to be increased by one
  845. precision++ ;
  846. }
  847. s[precision] = 0; // add terminator for array
  848. }
  849. string dd_real::to_string(int precision, int width, ios_base::fmtflags fmt,
  850. bool showpos, bool uppercase, char fill) const {
  851. string s;
  852. bool fixed = (fmt & ios_base::fixed) != 0;
  853. bool sgn = true;
  854. int i, e = 0;
  855. if (isnan()) {
  856. s = uppercase ? "NAN" : "nan";
  857. sgn = false;
  858. } else {
  859. if (*this < 0.0)
  860. s += '-';
  861. else if (showpos)
  862. s += '+';
  863. else
  864. sgn = false;
  865. if (isinf()) {
  866. s += uppercase ? "INF" : "inf";
  867. } else if (*this == 0.0) {
  868. /* Zero case */
  869. s += '0';
  870. if (precision > 0) {
  871. s += '.';
  872. s.append(precision, '0');
  873. }
  874. } else {
  875. /* Non-zero case */
  876. int off = (fixed ? (1 + to_int(floor(log10(abs(*this))))) : 1);
  877. int d = precision + off;
  878. int d_with_extra = d;
  879. if(fixed)
  880. d_with_extra = std::max(60, d); // longer than the max accuracy for DD
  881. // highly special case - fixed mode, precision is zero, abs(*this) < 1.0
  882. // without this trap a number like 0.9 printed fixed with 0 precision prints as 0
  883. // should be rounded to 1.
  884. if(fixed && (precision == 0) && (abs(*this) < 1.0)){
  885. if(abs(*this) >= 0.5)
  886. s += '1';
  887. else
  888. s += '0';
  889. return s;
  890. }
  891. // handle near zero to working precision (but not exactly zero)
  892. if (fixed && d <= 0) {
  893. s += '0';
  894. if (precision > 0) {
  895. s += '.';
  896. s.append(precision, '0');
  897. }
  898. } else { // default
  899. char *t; // = new char[d+1];
  900. int j;
  901. if(fixed){
  902. t = new char[d_with_extra+1];
  903. to_digits(t, e, d_with_extra);
  904. }
  905. else{
  906. t = new char[d+1];
  907. to_digits(t, e, d);
  908. }
  909. off = e + 1;
  910. if (fixed) {
  911. // fix the string if it's been computed incorrectly
  912. // round here in the decimal string if required
  913. round_string(t, d, &off);
  914. if (off > 0) {
  915. for (i = 0; i < off; i++) s += t[i];
  916. if (precision > 0) {
  917. s += '.';
  918. for (j = 0; j < precision; j++, i++) s += t[i];
  919. }
  920. } else {
  921. s += "0.";
  922. if (off < 0) s.append(-off, '0');
  923. for (i = 0; i < d; i++) s += t[i];
  924. }
  925. } else {
  926. s += t[0];
  927. if (precision > 0) s += '.';
  928. for (i = 1; i <= precision; i++)
  929. s += t[i];
  930. }
  931. delete [] t;
  932. }
  933. }
  934. // trap for improper offset with large values
  935. // without this trap, output of values of the for 10^j - 1 fail for j > 28
  936. // and are output with the point in the wrong place, leading to a dramatically off value
  937. if(fixed && (precision > 0)){
  938. // make sure that the value isn't dramatically larger
  939. double from_string = atof(s.c_str());
  940. // if this ratio is large, then we've got problems
  941. if( fabs( from_string / this->x[0] ) > 3.0 ){
  942. int point_position;
  943. char temp;
  944. // loop on the string, find the point, move it up one
  945. // don't act on the first character
  946. for(i=1; i < s.length(); i++){
  947. if(s[i] == '.'){
  948. s[i] = s[i-1] ;
  949. s[i-1] = '.' ;
  950. break;
  951. }
  952. }
  953. from_string = atof(s.c_str());
  954. // if this ratio is large, then the string has not been fixed
  955. if( fabs( from_string / this->x[0] ) > 3.0 ){
  956. dd_real::error("Re-rounding unsuccessful in large number fixed point trap.") ;
  957. }
  958. }
  959. }
  960. if (!fixed && !isinf()) {
  961. /* Fill in exponent part */
  962. s += uppercase ? 'E' : 'e';
  963. append_expn(s, e);
  964. }
  965. }
  966. /* Fill in the blanks */
  967. int len = s.length();
  968. if (len < width) {
  969. int delta = width - len;
  970. if (fmt & ios_base::internal) {
  971. if (sgn)
  972. s.insert(static_cast<string::size_type>(1), delta, fill);
  973. else
  974. s.insert(static_cast<string::size_type>(0), delta, fill);
  975. } else if (fmt & ios_base::left) {
  976. s.append(delta, fill);
  977. } else {
  978. s.insert(static_cast<string::size_type>(0), delta, fill);
  979. }
  980. }
  981. return s;
  982. }
  983. /* Reads in a double-double number from the string s. */
  984. int dd_real::read(const char *s, dd_real &a) {
  985. const char *p = s;
  986. char ch;
  987. int sign = 0;
  988. int point = -1;
  989. int nd = 0;
  990. int e = 0;
  991. bool done = false;
  992. dd_real r = 0.0;
  993. int nread;
  994. /* Skip any leading spaces */
  995. while (*p == ' ')
  996. p++;
  997. while (!done && (ch = *p) != '\0') {
  998. if (ch >= '0' && ch <= '9') {
  999. int d = ch - '0';
  1000. r *= 10.0;
  1001. r += static_cast<double>(d);
  1002. nd++;
  1003. } else {
  1004. switch (ch) {
  1005. case '.':
  1006. if (point >= 0)
  1007. return -1;
  1008. point = nd;
  1009. break;
  1010. case '-':
  1011. case '+':
  1012. if (sign != 0 || nd > 0)
  1013. return -1;
  1014. sign = (ch == '-') ? -1 : 1;
  1015. break;
  1016. case 'E':
  1017. case 'e':
  1018. nread = std::sscanf(p+1, "%d", &e);
  1019. done = true;
  1020. if (nread != 1)
  1021. return -1;
  1022. break;
  1023. default:
  1024. return -1;
  1025. }
  1026. }
  1027. p++;
  1028. }
  1029. if (point >= 0) {
  1030. e -= (nd - point);
  1031. }
  1032. if (e != 0) {
  1033. r *= (dd_real(10.0) ^ e);
  1034. }
  1035. a = (sign == -1) ? -r : r;
  1036. return 0;
  1037. }
  1038. /* Debugging routines */
  1039. void dd_real::dump(const string &name, std::ostream &os) const {
  1040. std::ios_base::fmtflags old_flags = os.flags();
  1041. std::streamsize old_prec = os.precision(19);
  1042. os << std::scientific;
  1043. if (name.length() > 0) os << name << " = ";
  1044. os << "[ " << setw(27) << x[0] << ", " << setw(27) << x[1] << " ]" << endl;
  1045. os.precision(old_prec);
  1046. os.flags(old_flags);
  1047. }
  1048. void dd_real::dump_bits(const string &name, std::ostream &os) const {
  1049. string::size_type len = name.length();
  1050. if (len > 0) {
  1051. os << name << " = ";
  1052. len +=3;
  1053. }
  1054. os << "[ ";
  1055. len += 2;
  1056. print_double_info(os, x[0]);
  1057. os << endl;
  1058. for (string::size_type i = 0; i < len; i++) os << ' ';
  1059. print_double_info(os, x[1]);
  1060. os << " ]" << endl;
  1061. }
  1062. dd_real dd_real::debug_rand() {
  1063. if (std::rand() % 2 == 0)
  1064. return ddrand();
  1065. int expn = 0;
  1066. dd_real a = 0.0;
  1067. double d;
  1068. for (int i = 0; i < 2; i++) {
  1069. d = std::ldexp(static_cast<double>(std::rand()) / RAND_MAX, -expn);
  1070. a += d;
  1071. expn = expn + 54 + std::rand() % 200;
  1072. }
  1073. return a;
  1074. }