dd_inline.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /*
  2. * include/dd_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 double-double
  11. * arithmetic package.
  12. */
  13. #ifndef _QD_DD_INLINE_H
  14. #define _QD_DD_INLINE_H
  15. #include <cmath>
  16. #include <qd/inline.h>
  17. #ifndef QD_INLINE
  18. #define inline
  19. #endif
  20. /*********** Additions ************/
  21. /* double-double = double + double */
  22. inline dd_real dd_real::add(double a, double b) {
  23. double s, e;
  24. s = qd::two_sum(a, b, e);
  25. return dd_real(s, e);
  26. }
  27. /* double-double + double */
  28. inline dd_real operator+(const dd_real &a, double b) {
  29. double s1, s2;
  30. s1 = qd::two_sum(a.x[0], b, s2);
  31. s2 += a.x[1];
  32. s1 = qd::quick_two_sum(s1, s2, s2);
  33. return dd_real(s1, s2);
  34. }
  35. /* double-double + double-double */
  36. inline dd_real dd_real::ieee_add(const dd_real &a, const dd_real &b) {
  37. /* This one satisfies IEEE style error bound,
  38. due to K. Briggs and W. Kahan. */
  39. double s1, s2, t1, t2;
  40. s1 = qd::two_sum(a.x[0], b.x[0], s2);
  41. t1 = qd::two_sum(a.x[1], b.x[1], t2);
  42. s2 += t1;
  43. s1 = qd::quick_two_sum(s1, s2, s2);
  44. s2 += t2;
  45. s1 = qd::quick_two_sum(s1, s2, s2);
  46. return dd_real(s1, s2);
  47. }
  48. inline dd_real dd_real::sloppy_add(const dd_real &a, const dd_real &b) {
  49. /* This is the less accurate version ... obeys Cray-style
  50. error bound. */
  51. double s, e;
  52. s = qd::two_sum(a.x[0], b.x[0], e);
  53. e += (a.x[1] + b.x[1]);
  54. s = qd::quick_two_sum(s, e, e);
  55. return dd_real(s, e);
  56. }
  57. inline dd_real operator+(const dd_real &a, const dd_real &b) {
  58. #ifndef QD_IEEE_ADD
  59. return dd_real::sloppy_add(a, b);
  60. #else
  61. return dd_real::ieee_add(a, b);
  62. #endif
  63. }
  64. /* double + double-double */
  65. inline dd_real operator+(double a, const dd_real &b) {
  66. return (b + a);
  67. }
  68. /*********** Self-Additions ************/
  69. /* double-double += double */
  70. inline dd_real &dd_real::operator+=(double a) {
  71. double s1, s2;
  72. s1 = qd::two_sum(x[0], a, s2);
  73. s2 += x[1];
  74. x[0] = qd::quick_two_sum(s1, s2, x[1]);
  75. return *this;
  76. }
  77. /* double-double += double-double */
  78. inline dd_real &dd_real::operator+=(const dd_real &a) {
  79. #ifndef QD_IEEE_ADD
  80. double s, e;
  81. s = qd::two_sum(x[0], a.x[0], e);
  82. e += x[1];
  83. e += a.x[1];
  84. x[0] = qd::quick_two_sum(s, e, x[1]);
  85. return *this;
  86. #else
  87. double s1, s2, t1, t2;
  88. s1 = qd::two_sum(x[0], a.x[0], s2);
  89. t1 = qd::two_sum(x[1], a.x[1], t2);
  90. s2 += t1;
  91. s1 = qd::quick_two_sum(s1, s2, s2);
  92. s2 += t2;
  93. x[0] = qd::quick_two_sum(s1, s2, x[1]);
  94. return *this;
  95. #endif
  96. }
  97. /*********** Subtractions ************/
  98. /* double-double = double - double */
  99. inline dd_real dd_real::sub(double a, double b) {
  100. double s, e;
  101. s = qd::two_diff(a, b, e);
  102. return dd_real(s, e);
  103. }
  104. /* double-double - double */
  105. inline dd_real operator-(const dd_real &a, double b) {
  106. double s1, s2;
  107. s1 = qd::two_diff(a.x[0], b, s2);
  108. s2 += a.x[1];
  109. s1 = qd::quick_two_sum(s1, s2, s2);
  110. return dd_real(s1, s2);
  111. }
  112. /* double-double - double-double */
  113. inline dd_real operator-(const dd_real &a, const dd_real &b) {
  114. #ifndef QD_IEEE_ADD
  115. double s, e;
  116. s = qd::two_diff(a.x[0], b.x[0], e);
  117. e += a.x[1];
  118. e -= b.x[1];
  119. s = qd::quick_two_sum(s, e, e);
  120. return dd_real(s, e);
  121. #else
  122. double s1, s2, t1, t2;
  123. s1 = qd::two_diff(a.x[0], b.x[0], s2);
  124. t1 = qd::two_diff(a.x[1], b.x[1], t2);
  125. s2 += t1;
  126. s1 = qd::quick_two_sum(s1, s2, s2);
  127. s2 += t2;
  128. s1 = qd::quick_two_sum(s1, s2, s2);
  129. return dd_real(s1, s2);
  130. #endif
  131. }
  132. /* double - double-double */
  133. inline dd_real operator-(double a, const dd_real &b) {
  134. double s1, s2;
  135. s1 = qd::two_diff(a, b.x[0], s2);
  136. s2 -= b.x[1];
  137. s1 = qd::quick_two_sum(s1, s2, s2);
  138. return dd_real(s1, s2);
  139. }
  140. /*********** Self-Subtractions ************/
  141. /* double-double -= double */
  142. inline dd_real &dd_real::operator-=(double a) {
  143. double s1, s2;
  144. s1 = qd::two_diff(x[0], a, s2);
  145. s2 += x[1];
  146. x[0] = qd::quick_two_sum(s1, s2, x[1]);
  147. return *this;
  148. }
  149. /* double-double -= double-double */
  150. inline dd_real &dd_real::operator-=(const dd_real &a) {
  151. #ifndef QD_IEEE_ADD
  152. double s, e;
  153. s = qd::two_diff(x[0], a.x[0], e);
  154. e += x[1];
  155. e -= a.x[1];
  156. x[0] = qd::quick_two_sum(s, e, x[1]);
  157. return *this;
  158. #else
  159. double s1, s2, t1, t2;
  160. s1 = qd::two_diff(x[0], a.x[0], s2);
  161. t1 = qd::two_diff(x[1], a.x[1], t2);
  162. s2 += t1;
  163. s1 = qd::quick_two_sum(s1, s2, s2);
  164. s2 += t2;
  165. x[0] = qd::quick_two_sum(s1, s2, x[1]);
  166. return *this;
  167. #endif
  168. }
  169. /*********** Unary Minus ***********/
  170. inline dd_real dd_real::operator-() const {
  171. return dd_real(-x[0], -x[1]);
  172. }
  173. /*********** Multiplications ************/
  174. /* double-double = double * double */
  175. inline dd_real dd_real::mul(double a, double b) {
  176. double p, e;
  177. p = qd::two_prod(a, b, e);
  178. return dd_real(p, e);
  179. }
  180. /* double-double * (2.0 ^ exp) */
  181. inline dd_real ldexp(const dd_real &a, int exp) {
  182. return dd_real(std::ldexp(a.x[0], exp), std::ldexp(a.x[1], exp));
  183. }
  184. /* double-double * double, where double is a power of 2. */
  185. inline dd_real mul_pwr2(const dd_real &a, double b) {
  186. return dd_real(a.x[0] * b, a.x[1] * b);
  187. }
  188. /* double-double * double */
  189. inline dd_real operator*(const dd_real &a, double b) {
  190. double p1, p2;
  191. p1 = qd::two_prod(a.x[0], b, p2);
  192. p2 += (a.x[1] * b);
  193. p1 = qd::quick_two_sum(p1, p2, p2);
  194. return dd_real(p1, p2);
  195. }
  196. /* double-double * double-double */
  197. inline dd_real operator*(const dd_real &a, const dd_real &b) {
  198. double p1, p2;
  199. p1 = qd::two_prod(a.x[0], b.x[0], p2);
  200. p2 += (a.x[0] * b.x[1] + a.x[1] * b.x[0]);
  201. p1 = qd::quick_two_sum(p1, p2, p2);
  202. return dd_real(p1, p2);
  203. }
  204. /* double * double-double */
  205. inline dd_real operator*(double a, const dd_real &b) {
  206. return (b * a);
  207. }
  208. /*********** Self-Multiplications ************/
  209. /* double-double *= double */
  210. inline dd_real &dd_real::operator*=(double a) {
  211. double p1, p2;
  212. p1 = qd::two_prod(x[0], a, p2);
  213. p2 += x[1] * a;
  214. x[0] = qd::quick_two_sum(p1, p2, x[1]);
  215. return *this;
  216. }
  217. /* double-double *= double-double */
  218. inline dd_real &dd_real::operator*=(const dd_real &a) {
  219. double p1, p2;
  220. p1 = qd::two_prod(x[0], a.x[0], p2);
  221. p2 += a.x[1] * x[0];
  222. p2 += a.x[0] * x[1];
  223. x[0] = qd::quick_two_sum(p1, p2, x[1]);
  224. return *this;
  225. }
  226. /*********** Divisions ************/
  227. inline dd_real dd_real::div(double a, double b) {
  228. double q1, q2;
  229. double p1, p2;
  230. double s, e;
  231. q1 = a / b;
  232. /* Compute a - q1 * b */
  233. p1 = qd::two_prod(q1, b, p2);
  234. s = qd::two_diff(a, p1, e);
  235. e -= p2;
  236. /* get next approximation */
  237. q2 = (s + e) / b;
  238. s = qd::quick_two_sum(q1, q2, e);
  239. return dd_real(s, e);
  240. }
  241. /* double-double / double */
  242. inline dd_real operator/(const dd_real &a, double b) {
  243. double q1, q2;
  244. double p1, p2;
  245. double s, e;
  246. dd_real r;
  247. q1 = a.x[0] / b; /* approximate quotient. */
  248. /* Compute this - q1 * d */
  249. p1 = qd::two_prod(q1, b, p2);
  250. s = qd::two_diff(a.x[0], p1, e);
  251. e += a.x[1];
  252. e -= p2;
  253. /* get next approximation. */
  254. q2 = (s + e) / b;
  255. /* renormalize */
  256. r.x[0] = qd::quick_two_sum(q1, q2, r.x[1]);
  257. return r;
  258. }
  259. inline dd_real dd_real::sloppy_div(const dd_real &a, const dd_real &b) {
  260. double s1, s2;
  261. double q1, q2;
  262. dd_real r;
  263. q1 = a.x[0] / b.x[0]; /* approximate quotient */
  264. /* compute this - q1 * dd */
  265. r = b * q1;
  266. s1 = qd::two_diff(a.x[0], r.x[0], s2);
  267. s2 -= r.x[1];
  268. s2 += a.x[1];
  269. /* get next approximation */
  270. q2 = (s1 + s2) / b.x[0];
  271. /* renormalize */
  272. r.x[0] = qd::quick_two_sum(q1, q2, r.x[1]);
  273. return r;
  274. }
  275. inline dd_real dd_real::accurate_div(const dd_real &a, const dd_real &b) {
  276. double q1, q2, q3;
  277. dd_real r;
  278. q1 = a.x[0] / b.x[0]; /* approximate quotient */
  279. r = a - q1 * b;
  280. q2 = r.x[0] / b.x[0];
  281. r -= (q2 * b);
  282. q3 = r.x[0] / b.x[0];
  283. q1 = qd::quick_two_sum(q1, q2, q2);
  284. r = dd_real(q1, q2) + q3;
  285. return r;
  286. }
  287. /* double-double / double-double */
  288. inline dd_real operator/(const dd_real &a, const dd_real &b) {
  289. #ifdef QD_SLOPPY_DIV
  290. return dd_real::sloppy_div(a, b);
  291. #else
  292. return dd_real::accurate_div(a, b);
  293. #endif
  294. }
  295. /* double / double-double */
  296. inline dd_real operator/(double a, const dd_real &b) {
  297. return dd_real(a) / b;
  298. }
  299. inline dd_real inv(const dd_real &a) {
  300. return 1.0 / a;
  301. }
  302. /*********** Self-Divisions ************/
  303. /* double-double /= double */
  304. inline dd_real &dd_real::operator/=(double a) {
  305. *this = *this / a;
  306. return *this;
  307. }
  308. /* double-double /= double-double */
  309. inline dd_real &dd_real::operator/=(const dd_real &a) {
  310. *this = *this / a;
  311. return *this;
  312. }
  313. /********** Remainder **********/
  314. inline dd_real drem(const dd_real &a, const dd_real &b) {
  315. dd_real n = nint(a / b);
  316. return (a - n * b);
  317. }
  318. inline dd_real divrem(const dd_real &a, const dd_real &b, dd_real &r) {
  319. dd_real n = nint(a / b);
  320. r = a - n * b;
  321. return n;
  322. }
  323. /*********** Squaring **********/
  324. inline dd_real sqr(const dd_real &a) {
  325. double p1, p2;
  326. double s1, s2;
  327. p1 = qd::two_sqr(a.x[0], p2);
  328. p2 += 2.0 * a.x[0] * a.x[1];
  329. p2 += a.x[1] * a.x[1];
  330. s1 = qd::quick_two_sum(p1, p2, s2);
  331. return dd_real(s1, s2);
  332. }
  333. inline dd_real dd_real::sqr(double a) {
  334. double p1, p2;
  335. p1 = qd::two_sqr(a, p2);
  336. return dd_real(p1, p2);
  337. }
  338. /********** Exponentiation **********/
  339. inline dd_real dd_real::operator^(int n) {
  340. return npwr(*this, n);
  341. }
  342. /*********** Assignments ************/
  343. /* double-double = double */
  344. inline dd_real &dd_real::operator=(double a) {
  345. x[0] = a;
  346. x[1] = 0.0;
  347. return *this;
  348. }
  349. /*********** Equality Comparisons ************/
  350. /* double-double == double */
  351. inline bool operator==(const dd_real &a, double b) {
  352. return (a.x[0] == b && a.x[1] == 0.0);
  353. }
  354. /* double-double == double-double */
  355. inline bool operator==(const dd_real &a, const dd_real &b) {
  356. return (a.x[0] == b.x[0] && a.x[1] == b.x[1]);
  357. }
  358. /* double == double-double */
  359. inline bool operator==(double a, const dd_real &b) {
  360. return (a == b.x[0] && b.x[1] == 0.0);
  361. }
  362. /*********** Greater-Than Comparisons ************/
  363. /* double-double > double */
  364. inline bool operator>(const dd_real &a, double b) {
  365. return (a.x[0] > b || (a.x[0] == b && a.x[1] > 0.0));
  366. }
  367. /* double-double > double-double */
  368. inline bool operator>(const dd_real &a, const dd_real &b) {
  369. return (a.x[0] > b.x[0] || (a.x[0] == b.x[0] && a.x[1] > b.x[1]));
  370. }
  371. /* double > double-double */
  372. inline bool operator>(double a, const dd_real &b) {
  373. return (a > b.x[0] || (a == b.x[0] && b.x[1] < 0.0));
  374. }
  375. /*********** Less-Than Comparisons ************/
  376. /* double-double < double */
  377. inline bool operator<(const dd_real &a, double b) {
  378. return (a.x[0] < b || (a.x[0] == b && a.x[1] < 0.0));
  379. }
  380. /* double-double < double-double */
  381. inline bool operator<(const dd_real &a, const dd_real &b) {
  382. return (a.x[0] < b.x[0] || (a.x[0] == b.x[0] && a.x[1] < b.x[1]));
  383. }
  384. /* double < double-double */
  385. inline bool operator<(double a, const dd_real &b) {
  386. return (a < b.x[0] || (a == b.x[0] && b.x[1] > 0.0));
  387. }
  388. /*********** Greater-Than-Or-Equal-To Comparisons ************/
  389. /* double-double >= double */
  390. inline bool operator>=(const dd_real &a, double b) {
  391. return (a.x[0] > b || (a.x[0] == b && a.x[1] >= 0.0));
  392. }
  393. /* double-double >= double-double */
  394. inline bool operator>=(const dd_real &a, const dd_real &b) {
  395. return (a.x[0] > b.x[0] || (a.x[0] == b.x[0] && a.x[1] >= b.x[1]));
  396. }
  397. /* double >= double-double */
  398. inline bool operator>=(double a, const dd_real &b) {
  399. return (b <= a);
  400. }
  401. /*********** Less-Than-Or-Equal-To Comparisons ************/
  402. /* double-double <= double */
  403. inline bool operator<=(const dd_real &a, double b) {
  404. return (a.x[0] < b || (a.x[0] == b && a.x[1] <= 0.0));
  405. }
  406. /* double-double <= double-double */
  407. inline bool operator<=(const dd_real &a, const dd_real &b) {
  408. return (a.x[0] < b.x[0] || (a.x[0] == b.x[0] && a.x[1] <= b.x[1]));
  409. }
  410. /* double <= double-double */
  411. inline bool operator<=(double a, const dd_real &b) {
  412. return (b >= a);
  413. }
  414. /*********** Not-Equal-To Comparisons ************/
  415. /* double-double != double */
  416. inline bool operator!=(const dd_real &a, double b) {
  417. return (a.x[0] != b || a.x[1] != 0.0);
  418. }
  419. /* double-double != double-double */
  420. inline bool operator!=(const dd_real &a, const dd_real &b) {
  421. return (a.x[0] != b.x[0] || a.x[1] != b.x[1]);
  422. }
  423. /* double != double-double */
  424. inline bool operator!=(double a, const dd_real &b) {
  425. return (a != b.x[0] || b.x[1] != 0.0);
  426. }
  427. /*********** Micellaneous ************/
  428. /* this == 0 */
  429. inline bool dd_real::is_zero() const {
  430. return (x[0] == 0.0);
  431. }
  432. /* this == 1 */
  433. inline bool dd_real::is_one() const {
  434. return (x[0] == 1.0 && x[1] == 0.0);
  435. }
  436. /* this > 0 */
  437. inline bool dd_real::is_positive() const {
  438. return (x[0] > 0.0);
  439. }
  440. /* this < 0 */
  441. inline bool dd_real::is_negative() const {
  442. return (x[0] < 0.0);
  443. }
  444. /* Absolute value */
  445. inline dd_real abs(const dd_real &a) {
  446. return (a.x[0] < 0.0) ? -a : a;
  447. }
  448. inline dd_real fabs(const dd_real &a) {
  449. return abs(a);
  450. }
  451. /* Round to Nearest integer */
  452. inline dd_real nint(const dd_real &a) {
  453. double hi = qd::nint(a.x[0]);
  454. double lo;
  455. if (hi == a.x[0]) {
  456. /* High word is an integer already. Round the low word.*/
  457. lo = qd::nint(a.x[1]);
  458. /* Renormalize. This is needed if x[0] = some integer, x[1] = 1/2.*/
  459. hi = qd::quick_two_sum(hi, lo, lo);
  460. } else {
  461. /* High word is not an integer. */
  462. lo = 0.0;
  463. if (std::abs(hi-a.x[0]) == 0.5 && a.x[1] < 0.0) {
  464. /* There is a tie in the high word, consult the low word
  465. to break the tie. */
  466. hi -= 1.0; /* NOTE: This does not cause INEXACT. */
  467. }
  468. }
  469. return dd_real(hi, lo);
  470. }
  471. inline dd_real floor(const dd_real &a) {
  472. double hi = std::floor(a.x[0]);
  473. double lo = 0.0;
  474. if (hi == a.x[0]) {
  475. /* High word is integer already. Round the low word. */
  476. lo = std::floor(a.x[1]);
  477. hi = qd::quick_two_sum(hi, lo, lo);
  478. }
  479. return dd_real(hi, lo);
  480. }
  481. inline dd_real ceil(const dd_real &a) {
  482. double hi = std::ceil(a.x[0]);
  483. double lo = 0.0;
  484. if (hi == a.x[0]) {
  485. /* High word is integer already. Round the low word. */
  486. lo = std::ceil(a.x[1]);
  487. hi = qd::quick_two_sum(hi, lo, lo);
  488. }
  489. return dd_real(hi, lo);
  490. }
  491. inline dd_real aint(const dd_real &a) {
  492. return (a.x[0] >= 0.0) ? floor(a) : ceil(a);
  493. }
  494. /* Cast to double. */
  495. inline double to_double(const dd_real &a) {
  496. return a.x[0];
  497. }
  498. /* Cast to int. */
  499. inline int to_int(const dd_real &a) {
  500. return static_cast<int>(a.x[0]);
  501. }
  502. /* Random number generator */
  503. inline dd_real dd_real::rand() {
  504. return ddrand();
  505. }
  506. #endif /* _QD_DD_INLINE_H */