qd_inline.h 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. /*
  2. * include/qd_inline.h
  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-2001
  9. *
  10. * Contains small functions (suitable for inlining) in the quad-double
  11. * arithmetic package.
  12. */
  13. #ifndef _QD_QD_INLINE_H
  14. #define _QD_QD_INLINE_H
  15. #include <cmath>
  16. #include <qd/inline.h>
  17. #ifndef QD_INLINE
  18. #define inline
  19. #endif
  20. /********** Constructors **********/
  21. inline qd_real::qd_real(double x0, double x1, double x2, double x3) {
  22. x[0] = x0;
  23. x[1] = x1;
  24. x[2] = x2;
  25. x[3] = x3;
  26. }
  27. inline qd_real::qd_real(const double *xx) {
  28. x[0] = xx[0];
  29. x[1] = xx[1];
  30. x[2] = xx[2];
  31. x[3] = xx[3];
  32. }
  33. inline qd_real::qd_real(double x0) {
  34. x[0] = x0;
  35. x[1] = x[2] = x[3] = 0.0;
  36. }
  37. inline qd_real::qd_real() {
  38. x[0] = 0.0;
  39. x[1] = 0.0;
  40. x[2] = 0.0;
  41. x[3] = 0.0;
  42. }
  43. inline qd_real::qd_real(const dd_real &a) {
  44. x[0] = a._hi();
  45. x[1] = a._lo();
  46. x[2] = x[3] = 0.0;
  47. }
  48. inline qd_real::qd_real(int i) {
  49. x[0] = static_cast<double>(i);
  50. x[1] = x[2] = x[3] = 0.0;
  51. }
  52. /********** Accessors **********/
  53. inline double qd_real::operator[](int i) const {
  54. return x[i];
  55. }
  56. inline double &qd_real::operator[](int i) {
  57. return x[i];
  58. }
  59. inline bool qd_real::isnan() const {
  60. return QD_ISNAN(x[0]) || QD_ISNAN(x[1]) || QD_ISNAN(x[2]) || QD_ISNAN(x[3]);
  61. }
  62. /********** Renormalization **********/
  63. namespace qd {
  64. inline void quick_renorm(double &c0, double &c1,
  65. double &c2, double &c3, double &c4) {
  66. double t0, t1, t2, t3;
  67. double s;
  68. s = qd::quick_two_sum(c3, c4, t3);
  69. s = qd::quick_two_sum(c2, s , t2);
  70. s = qd::quick_two_sum(c1, s , t1);
  71. c0 = qd::quick_two_sum(c0, s , t0);
  72. s = qd::quick_two_sum(t2, t3, t2);
  73. s = qd::quick_two_sum(t1, s , t1);
  74. c1 = qd::quick_two_sum(t0, s , t0);
  75. s = qd::quick_two_sum(t1, t2, t1);
  76. c2 = qd::quick_two_sum(t0, s , t0);
  77. c3 = t0 + t1;
  78. }
  79. inline void renorm(double &c0, double &c1,
  80. double &c2, double &c3) {
  81. double s0, s1, s2 = 0.0, s3 = 0.0;
  82. if (QD_ISINF(c0)) return;
  83. s0 = qd::quick_two_sum(c2, c3, c3);
  84. s0 = qd::quick_two_sum(c1, s0, c2);
  85. c0 = qd::quick_two_sum(c0, s0, c1);
  86. s0 = c0;
  87. s1 = c1;
  88. if (s1 != 0.0) {
  89. s1 = qd::quick_two_sum(s1, c2, s2);
  90. if (s2 != 0.0)
  91. s2 = qd::quick_two_sum(s2, c3, s3);
  92. else
  93. s1 = qd::quick_two_sum(s1, c3, s2);
  94. } else {
  95. s0 = qd::quick_two_sum(s0, c2, s1);
  96. if (s1 != 0.0)
  97. s1 = qd::quick_two_sum(s1, c3, s2);
  98. else
  99. s0 = qd::quick_two_sum(s0, c3, s1);
  100. }
  101. c0 = s0;
  102. c1 = s1;
  103. c2 = s2;
  104. c3 = s3;
  105. }
  106. inline void renorm(double &c0, double &c1,
  107. double &c2, double &c3, double &c4) {
  108. double s0, s1, s2 = 0.0, s3 = 0.0;
  109. if (QD_ISINF(c0)) return;
  110. s0 = qd::quick_two_sum(c3, c4, c4);
  111. s0 = qd::quick_two_sum(c2, s0, c3);
  112. s0 = qd::quick_two_sum(c1, s0, c2);
  113. c0 = qd::quick_two_sum(c0, s0, c1);
  114. s0 = c0;
  115. s1 = c1;
  116. if (s1 != 0.0) {
  117. s1 = qd::quick_two_sum(s1, c2, s2);
  118. if (s2 != 0.0) {
  119. s2 = qd::quick_two_sum(s2, c3, s3);
  120. if (s3 != 0.0)
  121. s3 += c4;
  122. else
  123. s2 = qd::quick_two_sum(s2, c4, s3);
  124. } else {
  125. s1 = qd::quick_two_sum(s1, c3, s2);
  126. if (s2 != 0.0)
  127. s2 = qd::quick_two_sum(s2, c4, s3);
  128. else
  129. s1 = qd::quick_two_sum(s1, c4, s2);
  130. }
  131. } else {
  132. s0 = qd::quick_two_sum(s0, c2, s1);
  133. if (s1 != 0.0) {
  134. s1 = qd::quick_two_sum(s1, c3, s2);
  135. if (s2 != 0.0)
  136. s2 = qd::quick_two_sum(s2, c4, s3);
  137. else
  138. s1 = qd::quick_two_sum(s1, c4, s2);
  139. } else {
  140. s0 = qd::quick_two_sum(s0, c3, s1);
  141. if (s1 != 0.0)
  142. s1 = qd::quick_two_sum(s1, c4, s2);
  143. else
  144. s0 = qd::quick_two_sum(s0, c4, s1);
  145. }
  146. }
  147. c0 = s0;
  148. c1 = s1;
  149. c2 = s2;
  150. c3 = s3;
  151. }
  152. }
  153. inline void qd_real::renorm() {
  154. qd::renorm(x[0], x[1], x[2], x[3]);
  155. }
  156. inline void qd_real::renorm(double &e) {
  157. qd::renorm(x[0], x[1], x[2], x[3], e);
  158. }
  159. /********** Additions ************/
  160. namespace qd {
  161. inline void three_sum(double &a, double &b, double &c) {
  162. double t1, t2, t3;
  163. t1 = qd::two_sum(a, b, t2);
  164. a = qd::two_sum(c, t1, t3);
  165. b = qd::two_sum(t2, t3, c);
  166. }
  167. inline void three_sum2(double &a, double &b, double &c) {
  168. double t1, t2, t3;
  169. t1 = qd::two_sum(a, b, t2);
  170. a = qd::two_sum(c, t1, t3);
  171. b = t2 + t3;
  172. }
  173. }
  174. /* quad-double + double */
  175. inline qd_real operator+(const qd_real &a, double b) {
  176. double c0, c1, c2, c3;
  177. double e;
  178. c0 = qd::two_sum(a[0], b, e);
  179. c1 = qd::two_sum(a[1], e, e);
  180. c2 = qd::two_sum(a[2], e, e);
  181. c3 = qd::two_sum(a[3], e, e);
  182. qd::renorm(c0, c1, c2, c3, e);
  183. return qd_real(c0, c1, c2, c3);
  184. }
  185. /* quad-double + double-double */
  186. inline qd_real operator+(const qd_real &a, const dd_real &b) {
  187. double s0, s1, s2, s3;
  188. double t0, t1;
  189. s0 = qd::two_sum(a[0], b._hi(), t0);
  190. s1 = qd::two_sum(a[1], b._lo(), t1);
  191. s1 = qd::two_sum(s1, t0, t0);
  192. s2 = a[2];
  193. qd::three_sum(s2, t0, t1);
  194. s3 = qd::two_sum(t0, a[3], t0);
  195. t0 += t1;
  196. qd::renorm(s0, s1, s2, s3, t0);
  197. return qd_real(s0, s1, s2, s3);
  198. }
  199. /* double + quad-double */
  200. inline qd_real operator+(double a, const qd_real &b) {
  201. return (b + a);
  202. }
  203. /* double-double + quad-double */
  204. inline qd_real operator+(const dd_real &a, const qd_real &b) {
  205. return (b + a);
  206. }
  207. namespace qd {
  208. /* s = quick_three_accum(a, b, c) adds c to the dd-pair (a, b).
  209. * If the result does not fit in two doubles, then the sum is
  210. * output into s and (a,b) contains the remainder. Otherwise
  211. * s is zero and (a,b) contains the sum. */
  212. inline double quick_three_accum(double &a, double &b, double c) {
  213. double s;
  214. bool za, zb;
  215. s = qd::two_sum(b, c, b);
  216. s = qd::two_sum(a, s, a);
  217. za = (a != 0.0);
  218. zb = (b != 0.0);
  219. if (za && zb)
  220. return s;
  221. if (!zb) {
  222. b = a;
  223. a = s;
  224. } else {
  225. a = s;
  226. }
  227. return 0.0;
  228. }
  229. }
  230. inline qd_real qd_real::ieee_add(const qd_real &a, const qd_real &b) {
  231. int i, j, k;
  232. double s, t;
  233. double u, v; /* double-length accumulator */
  234. double x[4] = {0.0, 0.0, 0.0, 0.0};
  235. i = j = k = 0;
  236. if (std::abs(a[i]) > std::abs(b[j]))
  237. u = a[i++];
  238. else
  239. u = b[j++];
  240. if (std::abs(a[i]) > std::abs(b[j]))
  241. v = a[i++];
  242. else
  243. v = b[j++];
  244. u = qd::quick_two_sum(u, v, v);
  245. while (k < 4) {
  246. if (i >= 4 && j >= 4) {
  247. x[k] = u;
  248. if (k < 3)
  249. x[++k] = v;
  250. break;
  251. }
  252. if (i >= 4)
  253. t = b[j++];
  254. else if (j >= 4)
  255. t = a[i++];
  256. else if (std::abs(a[i]) > std::abs(b[j])) {
  257. t = a[i++];
  258. } else
  259. t = b[j++];
  260. s = qd::quick_three_accum(u, v, t);
  261. if (s != 0.0) {
  262. x[k++] = s;
  263. }
  264. }
  265. /* add the rest. */
  266. for (k = i; k < 4; k++)
  267. x[3] += a[k];
  268. for (k = j; k < 4; k++)
  269. x[3] += b[k];
  270. qd::renorm(x[0], x[1], x[2], x[3]);
  271. return qd_real(x[0], x[1], x[2], x[3]);
  272. }
  273. inline qd_real qd_real::sloppy_add(const qd_real &a, const qd_real &b) {
  274. /*
  275. double s0, s1, s2, s3;
  276. double t0, t1, t2, t3;
  277. s0 = qd::two_sum(a[0], b[0], t0);
  278. s1 = qd::two_sum(a[1], b[1], t1);
  279. s2 = qd::two_sum(a[2], b[2], t2);
  280. s3 = qd::two_sum(a[3], b[3], t3);
  281. s1 = qd::two_sum(s1, t0, t0);
  282. qd::three_sum(s2, t0, t1);
  283. qd::three_sum2(s3, t0, t2);
  284. t0 = t0 + t1 + t3;
  285. qd::renorm(s0, s1, s2, s3, t0);
  286. return qd_real(s0, s1, s2, s3, t0);
  287. */
  288. /* Same as above, but addition re-organized to minimize
  289. data dependency ... unfortunately some compilers are
  290. not very smart to do this automatically */
  291. double s0, s1, s2, s3;
  292. double t0, t1, t2, t3;
  293. double v0, v1, v2, v3;
  294. double u0, u1, u2, u3;
  295. double w0, w1, w2, w3;
  296. s0 = a[0] + b[0];
  297. s1 = a[1] + b[1];
  298. s2 = a[2] + b[2];
  299. s3 = a[3] + b[3];
  300. v0 = s0 - a[0];
  301. v1 = s1 - a[1];
  302. v2 = s2 - a[2];
  303. v3 = s3 - a[3];
  304. u0 = s0 - v0;
  305. u1 = s1 - v1;
  306. u2 = s2 - v2;
  307. u3 = s3 - v3;
  308. w0 = a[0] - u0;
  309. w1 = a[1] - u1;
  310. w2 = a[2] - u2;
  311. w3 = a[3] - u3;
  312. u0 = b[0] - v0;
  313. u1 = b[1] - v1;
  314. u2 = b[2] - v2;
  315. u3 = b[3] - v3;
  316. t0 = w0 + u0;
  317. t1 = w1 + u1;
  318. t2 = w2 + u2;
  319. t3 = w3 + u3;
  320. s1 = qd::two_sum(s1, t0, t0);
  321. qd::three_sum(s2, t0, t1);
  322. qd::three_sum2(s3, t0, t2);
  323. t0 = t0 + t1 + t3;
  324. /* renormalize */
  325. qd::renorm(s0, s1, s2, s3, t0);
  326. return qd_real(s0, s1, s2, s3);
  327. }
  328. /* quad-double + quad-double */
  329. inline qd_real operator+(const qd_real &a, const qd_real &b) {
  330. #ifndef QD_IEEE_ADD
  331. return qd_real::sloppy_add(a, b);
  332. #else
  333. return qd_real::ieee_add(a, b);
  334. #endif
  335. }
  336. /********** Self-Additions ************/
  337. /* quad-double += double */
  338. inline qd_real &qd_real::operator+=(double a) {
  339. *this = *this + a;
  340. return *this;
  341. }
  342. /* quad-double += double-double */
  343. inline qd_real &qd_real::operator+=(const dd_real &a) {
  344. *this = *this + a;
  345. return *this;
  346. }
  347. /* quad-double += quad-double */
  348. inline qd_real &qd_real::operator+=(const qd_real &a) {
  349. *this = *this + a;
  350. return *this;
  351. }
  352. /********** Unary Minus **********/
  353. inline qd_real qd_real::operator-() const {
  354. return qd_real(-x[0], -x[1], -x[2], -x[3]);
  355. }
  356. /********** Subtractions **********/
  357. inline qd_real operator-(const qd_real &a, double b) {
  358. return (a + (-b));
  359. }
  360. inline qd_real operator-(double a, const qd_real &b) {
  361. return (a + (-b));
  362. }
  363. inline qd_real operator-(const qd_real &a, const dd_real &b) {
  364. return (a + (-b));
  365. }
  366. inline qd_real operator-(const dd_real &a, const qd_real &b) {
  367. return (a + (-b));
  368. }
  369. inline qd_real operator-(const qd_real &a, const qd_real &b) {
  370. return (a + (-b));
  371. }
  372. /********** Self-Subtractions **********/
  373. inline qd_real &qd_real::operator-=(double a) {
  374. return ((*this) += (-a));
  375. }
  376. inline qd_real &qd_real::operator-=(const dd_real &a) {
  377. return ((*this) += (-a));
  378. }
  379. inline qd_real &qd_real::operator-=(const qd_real &a) {
  380. return ((*this) += (-a));
  381. }
  382. inline qd_real operator*(double a, const qd_real &b) {
  383. return (b * a);
  384. }
  385. inline qd_real operator*(const dd_real &a, const qd_real &b) {
  386. return (b * a);
  387. }
  388. inline qd_real mul_pwr2(const qd_real &a, double b) {
  389. return qd_real(a[0] * b, a[1] * b, a[2] * b, a[3] * b);
  390. }
  391. /********** Multiplications **********/
  392. inline qd_real operator*(const qd_real &a, double b) {
  393. double p0, p1, p2, p3;
  394. double q0, q1, q2;
  395. double s0, s1, s2, s3, s4;
  396. p0 = qd::two_prod(a[0], b, q0);
  397. p1 = qd::two_prod(a[1], b, q1);
  398. p2 = qd::two_prod(a[2], b, q2);
  399. p3 = a[3] * b;
  400. s0 = p0;
  401. s1 = qd::two_sum(q0, p1, s2);
  402. qd::three_sum(s2, q1, p2);
  403. qd::three_sum2(q1, q2, p3);
  404. s3 = q1;
  405. s4 = q2 + p2;
  406. qd::renorm(s0, s1, s2, s3, s4);
  407. return qd_real(s0, s1, s2, s3);
  408. }
  409. /* quad-double * double-double */
  410. /* a0 * b0 0
  411. a0 * b1 1
  412. a1 * b0 2
  413. a1 * b1 3
  414. a2 * b0 4
  415. a2 * b1 5
  416. a3 * b0 6
  417. a3 * b1 7 */
  418. inline qd_real operator*(const qd_real &a, const dd_real &b) {
  419. double p0, p1, p2, p3, p4;
  420. double q0, q1, q2, q3, q4;
  421. double s0, s1, s2;
  422. double t0, t1;
  423. p0 = qd::two_prod(a[0], b._hi(), q0);
  424. p1 = qd::two_prod(a[0], b._lo(), q1);
  425. p2 = qd::two_prod(a[1], b._hi(), q2);
  426. p3 = qd::two_prod(a[1], b._lo(), q3);
  427. p4 = qd::two_prod(a[2], b._hi(), q4);
  428. qd::three_sum(p1, p2, q0);
  429. /* Five-Three-Sum */
  430. qd::three_sum(p2, p3, p4);
  431. q1 = qd::two_sum(q1, q2, q2);
  432. s0 = qd::two_sum(p2, q1, t0);
  433. s1 = qd::two_sum(p3, q2, t1);
  434. s1 = qd::two_sum(s1, t0, t0);
  435. s2 = t0 + t1 + p4;
  436. p2 = s0;
  437. p3 = a[2] * b._hi() + a[3] * b._lo() + q3 + q4;
  438. qd::three_sum2(p3, q0, s1);
  439. p4 = q0 + s2;
  440. qd::renorm(p0, p1, p2, p3, p4);
  441. return qd_real(p0, p1, p2, p3);
  442. }
  443. /* quad-double * quad-double */
  444. /* a0 * b0 0
  445. a0 * b1 1
  446. a1 * b0 2
  447. a0 * b2 3
  448. a1 * b1 4
  449. a2 * b0 5
  450. a0 * b3 6
  451. a1 * b2 7
  452. a2 * b1 8
  453. a3 * b0 9 */
  454. inline qd_real qd_real::sloppy_mul(const qd_real &a, const qd_real &b) {
  455. double p0, p1, p2, p3, p4, p5;
  456. double q0, q1, q2, q3, q4, q5;
  457. double t0, t1;
  458. double s0, s1, s2;
  459. p0 = qd::two_prod(a[0], b[0], q0);
  460. p1 = qd::two_prod(a[0], b[1], q1);
  461. p2 = qd::two_prod(a[1], b[0], q2);
  462. p3 = qd::two_prod(a[0], b[2], q3);
  463. p4 = qd::two_prod(a[1], b[1], q4);
  464. p5 = qd::two_prod(a[2], b[0], q5);
  465. /* Start Accumulation */
  466. qd::three_sum(p1, p2, q0);
  467. /* Six-Three Sum of p2, q1, q2, p3, p4, p5. */
  468. qd::three_sum(p2, q1, q2);
  469. qd::three_sum(p3, p4, p5);
  470. /* compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5). */
  471. s0 = qd::two_sum(p2, p3, t0);
  472. s1 = qd::two_sum(q1, p4, t1);
  473. s2 = q2 + p5;
  474. s1 = qd::two_sum(s1, t0, t0);
  475. s2 += (t0 + t1);
  476. /* O(eps^3) order terms */
  477. s1 += a[0]*b[3] + a[1]*b[2] + a[2]*b[1] + a[3]*b[0] + q0 + q3 + q4 + q5;
  478. qd::renorm(p0, p1, s0, s1, s2);
  479. return qd_real(p0, p1, s0, s1);
  480. }
  481. inline qd_real qd_real::accurate_mul(const qd_real &a, const qd_real &b) {
  482. double p0, p1, p2, p3, p4, p5;
  483. double q0, q1, q2, q3, q4, q5;
  484. double p6, p7, p8, p9;
  485. double q6, q7, q8, q9;
  486. double r0, r1;
  487. double t0, t1;
  488. double s0, s1, s2;
  489. p0 = qd::two_prod(a[0], b[0], q0);
  490. p1 = qd::two_prod(a[0], b[1], q1);
  491. p2 = qd::two_prod(a[1], b[0], q2);
  492. p3 = qd::two_prod(a[0], b[2], q3);
  493. p4 = qd::two_prod(a[1], b[1], q4);
  494. p5 = qd::two_prod(a[2], b[0], q5);
  495. /* Start Accumulation */
  496. qd::three_sum(p1, p2, q0);
  497. /* Six-Three Sum of p2, q1, q2, p3, p4, p5. */
  498. qd::three_sum(p2, q1, q2);
  499. qd::three_sum(p3, p4, p5);
  500. /* compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5). */
  501. s0 = qd::two_sum(p2, p3, t0);
  502. s1 = qd::two_sum(q1, p4, t1);
  503. s2 = q2 + p5;
  504. s1 = qd::two_sum(s1, t0, t0);
  505. s2 += (t0 + t1);
  506. /* O(eps^3) order terms */
  507. p6 = qd::two_prod(a[0], b[3], q6);
  508. p7 = qd::two_prod(a[1], b[2], q7);
  509. p8 = qd::two_prod(a[2], b[1], q8);
  510. p9 = qd::two_prod(a[3], b[0], q9);
  511. /* Nine-Two-Sum of q0, s1, q3, q4, q5, p6, p7, p8, p9. */
  512. q0 = qd::two_sum(q0, q3, q3);
  513. q4 = qd::two_sum(q4, q5, q5);
  514. p6 = qd::two_sum(p6, p7, p7);
  515. p8 = qd::two_sum(p8, p9, p9);
  516. /* Compute (t0, t1) = (q0, q3) + (q4, q5). */
  517. t0 = qd::two_sum(q0, q4, t1);
  518. t1 += (q3 + q5);
  519. /* Compute (r0, r1) = (p6, p7) + (p8, p9). */
  520. r0 = qd::two_sum(p6, p8, r1);
  521. r1 += (p7 + p9);
  522. /* Compute (q3, q4) = (t0, t1) + (r0, r1). */
  523. q3 = qd::two_sum(t0, r0, q4);
  524. q4 += (t1 + r1);
  525. /* Compute (t0, t1) = (q3, q4) + s1. */
  526. t0 = qd::two_sum(q3, s1, t1);
  527. t1 += q4;
  528. /* O(eps^4) terms -- Nine-One-Sum */
  529. t1 += a[1] * b[3] + a[2] * b[2] + a[3] * b[1] + q6 + q7 + q8 + q9 + s2;
  530. qd::renorm(p0, p1, s0, t0, t1);
  531. return qd_real(p0, p1, s0, t0);
  532. }
  533. inline qd_real operator*(const qd_real &a, const qd_real &b) {
  534. #ifdef QD_SLOPPY_MUL
  535. return qd_real::sloppy_mul(a, b);
  536. #else
  537. return qd_real::accurate_mul(a, b);
  538. #endif
  539. }
  540. /* quad-double ^ 2 = (x0 + x1 + x2 + x3) ^ 2
  541. = x0 ^ 2 + 2 x0 * x1 + (2 x0 * x2 + x1 ^ 2)
  542. + (2 x0 * x3 + 2 x1 * x2) */
  543. inline qd_real sqr(const qd_real &a) {
  544. double p0, p1, p2, p3, p4, p5;
  545. double q0, q1, q2, q3;
  546. double s0, s1;
  547. double t0, t1;
  548. p0 = qd::two_sqr(a[0], q0);
  549. p1 = qd::two_prod(2.0 * a[0], a[1], q1);
  550. p2 = qd::two_prod(2.0 * a[0], a[2], q2);
  551. p3 = qd::two_sqr(a[1], q3);
  552. p1 = qd::two_sum(q0, p1, q0);
  553. q0 = qd::two_sum(q0, q1, q1);
  554. p2 = qd::two_sum(p2, p3, p3);
  555. s0 = qd::two_sum(q0, p2, t0);
  556. s1 = qd::two_sum(q1, p3, t1);
  557. s1 = qd::two_sum(s1, t0, t0);
  558. t0 += t1;
  559. s1 = qd::quick_two_sum(s1, t0, t0);
  560. p2 = qd::quick_two_sum(s0, s1, t1);
  561. p3 = qd::quick_two_sum(t1, t0, q0);
  562. p4 = 2.0 * a[0] * a[3];
  563. p5 = 2.0 * a[1] * a[2];
  564. p4 = qd::two_sum(p4, p5, p5);
  565. q2 = qd::two_sum(q2, q3, q3);
  566. t0 = qd::two_sum(p4, q2, t1);
  567. t1 = t1 + p5 + q3;
  568. p3 = qd::two_sum(p3, t0, p4);
  569. p4 = p4 + q0 + t1;
  570. qd::renorm(p0, p1, p2, p3, p4);
  571. return qd_real(p0, p1, p2, p3);
  572. }
  573. /********** Self-Multiplication **********/
  574. /* quad-double *= double */
  575. inline qd_real &qd_real::operator*=(double a) {
  576. *this = (*this * a);
  577. return *this;
  578. }
  579. /* quad-double *= double-double */
  580. inline qd_real &qd_real::operator*=(const dd_real &a) {
  581. *this = (*this * a);
  582. return *this;
  583. }
  584. /* quad-double *= quad-double */
  585. inline qd_real &qd_real::operator*=(const qd_real &a) {
  586. *this = *this * a;
  587. return *this;
  588. }
  589. inline qd_real operator/ (const qd_real &a, const dd_real &b) {
  590. #ifdef QD_SLOPPY_DIV
  591. return qd_real::sloppy_div(a, b);
  592. #else
  593. return qd_real::accurate_div(a, b);
  594. #endif
  595. }
  596. inline qd_real operator/(const qd_real &a, const qd_real &b) {
  597. #ifdef QD_SLOPPY_DIV
  598. return qd_real::sloppy_div(a, b);
  599. #else
  600. return qd_real::accurate_div(a, b);
  601. #endif
  602. }
  603. /* double / quad-double */
  604. inline qd_real operator/(double a, const qd_real &b) {
  605. return qd_real(a) / b;
  606. }
  607. /* double-double / quad-double */
  608. inline qd_real operator/(const dd_real &a, const qd_real &b) {
  609. return qd_real(a) / b;
  610. }
  611. /********** Self-Divisions **********/
  612. /* quad-double /= double */
  613. inline qd_real &qd_real::operator/=(double a) {
  614. *this = (*this / a);
  615. return *this;
  616. }
  617. /* quad-double /= double-double */
  618. inline qd_real &qd_real::operator/=(const dd_real &a) {
  619. *this = (*this / a);
  620. return *this;
  621. }
  622. /* quad-double /= quad-double */
  623. inline qd_real &qd_real::operator/=(const qd_real &a) {
  624. *this = (*this / a);
  625. return *this;
  626. }
  627. /********** Exponentiation **********/
  628. inline qd_real qd_real::operator^(int n) const {
  629. return pow(*this, n);
  630. }
  631. /********** Miscellaneous **********/
  632. inline qd_real abs(const qd_real &a) {
  633. return (a[0] < 0.0) ? -a : a;
  634. }
  635. inline qd_real fabs(const qd_real &a) {
  636. return abs(a);
  637. }
  638. /* Quick version. May be off by one when qd is very close
  639. to the middle of two integers. */
  640. inline qd_real quick_nint(const qd_real &a) {
  641. qd_real r = qd_real(qd::nint(a[0]), qd::nint(a[1]),
  642. qd::nint(a[2]), qd::nint(a[3]));
  643. r.renorm();
  644. return r;
  645. }
  646. /*********** Assignments ************/
  647. /* quad-double = double */
  648. inline qd_real &qd_real::operator=(double a) {
  649. x[0] = a;
  650. x[1] = x[2] = x[3] = 0.0;
  651. return *this;
  652. }
  653. /* quad-double = double-double */
  654. inline qd_real &qd_real::operator=(const dd_real &a) {
  655. x[0] = a._hi();
  656. x[1] = a._lo();
  657. x[2] = x[3] = 0.0;
  658. return *this;
  659. }
  660. /********** Equality Comparison **********/
  661. inline bool operator==(const qd_real &a, double b) {
  662. return (a[0] == b && a[1] == 0.0 && a[2] == 0.0 && a[3] == 0.0);
  663. }
  664. inline bool operator==(double a, const qd_real &b) {
  665. return (b == a);
  666. }
  667. inline bool operator==(const qd_real &a, const dd_real &b) {
  668. return (a[0] == b._hi() && a[1] == b._lo() &&
  669. a[2] == 0.0 && a[3] == 0.0);
  670. }
  671. inline bool operator==(const dd_real &a, const qd_real &b) {
  672. return (b == a);
  673. }
  674. inline bool operator==(const qd_real &a, const qd_real &b) {
  675. return (a[0] == b[0] && a[1] == b[1] &&
  676. a[2] == b[2] && a[3] == b[3]);
  677. }
  678. /********** Less-Than Comparison ***********/
  679. inline bool operator<(const qd_real &a, double b) {
  680. return (a[0] < b || (a[0] == b && a[1] < 0.0));
  681. }
  682. inline bool operator<(double a, const qd_real &b) {
  683. return (b > a);
  684. }
  685. inline bool operator<(const qd_real &a, const dd_real &b) {
  686. return (a[0] < b._hi() ||
  687. (a[0] == b._hi() && (a[1] < b._lo() ||
  688. (a[1] == b._lo() && a[2] < 0.0))));
  689. }
  690. inline bool operator<(const dd_real &a, const qd_real &b) {
  691. return (b > a);
  692. }
  693. inline bool operator<(const qd_real &a, const qd_real &b) {
  694. return (a[0] < b[0] ||
  695. (a[0] == b[0] && (a[1] < b[1] ||
  696. (a[1] == b[1] && (a[2] < b[2] ||
  697. (a[2] == b[2] && a[3] < b[3]))))));
  698. }
  699. /********** Greater-Than Comparison ***********/
  700. inline bool operator>(const qd_real &a, double b) {
  701. return (a[0] > b || (a[0] == b && a[1] > 0.0));
  702. }
  703. inline bool operator>(double a, const qd_real &b) {
  704. return (b < a);
  705. }
  706. inline bool operator>(const qd_real &a, const dd_real &b) {
  707. return (a[0] > b._hi() ||
  708. (a[0] == b._hi() && (a[1] > b._lo() ||
  709. (a[1] == b._lo() && a[2] > 0.0))));
  710. }
  711. inline bool operator>(const dd_real &a, const qd_real &b) {
  712. return (b < a);
  713. }
  714. inline bool operator>(const qd_real &a, const qd_real &b) {
  715. return (a[0] > b[0] ||
  716. (a[0] == b[0] && (a[1] > b[1] ||
  717. (a[1] == b[1] && (a[2] > b[2] ||
  718. (a[2] == b[2] && a[3] > b[3]))))));
  719. }
  720. /********** Less-Than-Or-Equal-To Comparison **********/
  721. inline bool operator<=(const qd_real &a, double b) {
  722. return (a[0] < b || (a[0] == b && a[1] <= 0.0));
  723. }
  724. inline bool operator<=(double a, const qd_real &b) {
  725. return (b >= a);
  726. }
  727. inline bool operator<=(const qd_real &a, const dd_real &b) {
  728. return (a[0] < b._hi() ||
  729. (a[0] == b._hi() && (a[1] < b._lo() ||
  730. (a[1] == b._lo() && a[2] <= 0.0))));
  731. }
  732. inline bool operator<=(const dd_real &a, const qd_real &b) {
  733. return (b >= a);
  734. }
  735. inline bool operator<=(const qd_real &a, const qd_real &b) {
  736. return (a[0] < b[0] ||
  737. (a[0] == b[0] && (a[1] < b[1] ||
  738. (a[1] == b[1] && (a[2] < b[2] ||
  739. (a[2] == b[2] && a[3] <= b[3]))))));
  740. }
  741. /********** Greater-Than-Or-Equal-To Comparison **********/
  742. inline bool operator>=(const qd_real &a, double b) {
  743. return (a[0] > b || (a[0] == b && a[1] >= 0.0));
  744. }
  745. inline bool operator>=(double a, const qd_real &b) {
  746. return (b <= a);
  747. }
  748. inline bool operator>=(const qd_real &a, const dd_real &b) {
  749. return (a[0] > b._hi() ||
  750. (a[0] == b._hi() && (a[1] > b._lo() ||
  751. (a[1] == b._lo() && a[2] >= 0.0))));
  752. }
  753. inline bool operator>=(const dd_real &a, const qd_real &b) {
  754. return (b <= a);
  755. }
  756. inline bool operator>=(const qd_real &a, const qd_real &b) {
  757. return (a[0] > b[0] ||
  758. (a[0] == b[0] && (a[1] > b[1] ||
  759. (a[1] == b[1] && (a[2] > b[2] ||
  760. (a[2] == b[2] && a[3] >= b[3]))))));
  761. }
  762. /********** Not-Equal-To Comparison **********/
  763. inline bool operator!=(const qd_real &a, double b) {
  764. return !(a == b);
  765. }
  766. inline bool operator!=(double a, const qd_real &b) {
  767. return !(a == b);
  768. }
  769. inline bool operator!=(const qd_real &a, const dd_real &b) {
  770. return !(a == b);
  771. }
  772. inline bool operator!=(const dd_real &a, const qd_real &b) {
  773. return !(a == b);
  774. }
  775. inline bool operator!=(const qd_real &a, const qd_real &b) {
  776. return !(a == b);
  777. }
  778. inline qd_real aint(const qd_real &a) {
  779. return (a[0] >= 0) ? floor(a) : ceil(a);
  780. }
  781. inline bool qd_real::is_zero() const {
  782. return (x[0] == 0.0);
  783. }
  784. inline bool qd_real::is_one() const {
  785. return (x[0] == 1.0 && x[1] == 0.0 && x[2] == 0.0 && x[3] == 0.0);
  786. }
  787. inline bool qd_real::is_positive() const {
  788. return (x[0] > 0.0);
  789. }
  790. inline bool qd_real::is_negative() const {
  791. return (x[0] < 0.0);
  792. }
  793. inline dd_real to_dd_real(const qd_real &a) {
  794. return dd_real(a[0], a[1]);
  795. }
  796. inline double to_double(const qd_real &a) {
  797. return a[0];
  798. }
  799. inline int to_int(const qd_real &a) {
  800. return static_cast<int>(a[0]);
  801. }
  802. inline qd_real inv(const qd_real &qd) {
  803. return 1.0 / qd;
  804. }
  805. inline qd_real max(const qd_real &a, const qd_real &b) {
  806. return (a > b) ? a : b;
  807. }
  808. inline qd_real max(const qd_real &a, const qd_real &b,
  809. const qd_real &c) {
  810. return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
  811. }
  812. inline qd_real min(const qd_real &a, const qd_real &b) {
  813. return (a < b) ? a : b;
  814. }
  815. inline qd_real min(const qd_real &a, const qd_real &b,
  816. const qd_real &c) {
  817. return (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
  818. }
  819. /* Random number generator */
  820. inline qd_real qd_real::rand() {
  821. return qdrand();
  822. }
  823. inline qd_real ldexp(const qd_real &a, int n) {
  824. return qd_real(std::ldexp(a[0], n), std::ldexp(a[1], n),
  825. std::ldexp(a[2], n), std::ldexp(a[3], n));
  826. }
  827. #endif /* _QD_QD_INLINE_H */