/qd/dd_inline.h

https://github.com/rudimeier/mprime · C Header · 598 lines · 390 code · 104 blank · 104 comment · 62 complexity · 1812f5b38aca52225177b1a678981296 MD5 · raw file

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