File indexing completed on 2026-08-06 09:31:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef _QD_DD_INLINE_H
0014 #define _QD_DD_INLINE_H
0015
0016 #include <cmath>
0017 #include <qd/inline.h>
0018
0019 #ifndef QD_INLINE
0020 #define inline
0021 #endif
0022
0023
0024
0025
0026 inline dd_real dd_real::add(double a, double b) {
0027 double s, e;
0028 s = qd::two_sum(a, b, e);
0029 return dd_real(s, e);
0030 }
0031
0032
0033 inline dd_real operator+(const dd_real &a, double b) {
0034 double s1, s2;
0035 s1 = qd::two_sum(a.x[0], b, s2);
0036 s2 += a.x[1];
0037 s1 = qd::quick_two_sum(s1, s2, s2);
0038 return dd_real(s1, s2);
0039 }
0040
0041
0042 inline dd_real dd_real::ieee_add(const dd_real &a, const dd_real &b) {
0043
0044
0045 double s1, s2, t1, t2;
0046
0047 s1 = qd::two_sum(a.x[0], b.x[0], s2);
0048 t1 = qd::two_sum(a.x[1], b.x[1], t2);
0049 s2 += t1;
0050 s1 = qd::quick_two_sum(s1, s2, s2);
0051 s2 += t2;
0052 s1 = qd::quick_two_sum(s1, s2, s2);
0053 return dd_real(s1, s2);
0054 }
0055
0056 inline dd_real dd_real::sloppy_add(const dd_real &a, const dd_real &b) {
0057
0058
0059 double s, e;
0060
0061 s = qd::two_sum(a.x[0], b.x[0], e);
0062 e += (a.x[1] + b.x[1]);
0063 s = qd::quick_two_sum(s, e, e);
0064 return dd_real(s, e);
0065 }
0066
0067 inline dd_real operator+(const dd_real &a, const dd_real &b) {
0068 #ifndef QD_IEEE_ADD
0069 return dd_real::sloppy_add(a, b);
0070 #else
0071 return dd_real::ieee_add(a, b);
0072 #endif
0073 }
0074
0075
0076 inline dd_real operator+(double a, const dd_real &b) {
0077 return (b + a);
0078 }
0079
0080
0081
0082
0083 inline dd_real &dd_real::operator+=(double a) {
0084 double s1, s2;
0085 s1 = qd::two_sum(x[0], a, s2);
0086 s2 += x[1];
0087 x[0] = qd::quick_two_sum(s1, s2, x[1]);
0088 return *this;
0089 }
0090
0091
0092 inline dd_real &dd_real::operator+=(const dd_real &a) {
0093 #ifndef QD_IEEE_ADD
0094 double s, e;
0095 s = qd::two_sum(x[0], a.x[0], e);
0096 e += x[1];
0097 e += a.x[1];
0098 x[0] = qd::quick_two_sum(s, e, x[1]);
0099 return *this;
0100 #else
0101 double s1, s2, t1, t2;
0102 s1 = qd::two_sum(x[0], a.x[0], s2);
0103 t1 = qd::two_sum(x[1], a.x[1], t2);
0104 s2 += t1;
0105 s1 = qd::quick_two_sum(s1, s2, s2);
0106 s2 += t2;
0107 x[0] = qd::quick_two_sum(s1, s2, x[1]);
0108 return *this;
0109 #endif
0110 }
0111
0112
0113
0114 inline dd_real dd_real::sub(double a, double b) {
0115 double s, e;
0116 s = qd::two_diff(a, b, e);
0117 return dd_real(s, e);
0118 }
0119
0120
0121 inline dd_real operator-(const dd_real &a, double b) {
0122 double s1, s2;
0123 s1 = qd::two_diff(a.x[0], b, s2);
0124 s2 += a.x[1];
0125 s1 = qd::quick_two_sum(s1, s2, s2);
0126 return dd_real(s1, s2);
0127 }
0128
0129
0130 inline dd_real operator-(const dd_real &a, const dd_real &b) {
0131 #ifndef QD_IEEE_ADD
0132 double s, e;
0133 s = qd::two_diff(a.x[0], b.x[0], e);
0134 e += a.x[1];
0135 e -= b.x[1];
0136 s = qd::quick_two_sum(s, e, e);
0137 return dd_real(s, e);
0138 #else
0139 double s1, s2, t1, t2;
0140 s1 = qd::two_diff(a.x[0], b.x[0], s2);
0141 t1 = qd::two_diff(a.x[1], b.x[1], t2);
0142 s2 += t1;
0143 s1 = qd::quick_two_sum(s1, s2, s2);
0144 s2 += t2;
0145 s1 = qd::quick_two_sum(s1, s2, s2);
0146 return dd_real(s1, s2);
0147 #endif
0148 }
0149
0150
0151 inline dd_real operator-(double a, const dd_real &b) {
0152 double s1, s2;
0153 s1 = qd::two_diff(a, b.x[0], s2);
0154 s2 -= b.x[1];
0155 s1 = qd::quick_two_sum(s1, s2, s2);
0156 return dd_real(s1, s2);
0157 }
0158
0159
0160
0161 inline dd_real &dd_real::operator-=(double a) {
0162 double s1, s2;
0163 s1 = qd::two_diff(x[0], a, s2);
0164 s2 += x[1];
0165 x[0] = qd::quick_two_sum(s1, s2, x[1]);
0166 return *this;
0167 }
0168
0169
0170 inline dd_real &dd_real::operator-=(const dd_real &a) {
0171 #ifndef QD_IEEE_ADD
0172 double s, e;
0173 s = qd::two_diff(x[0], a.x[0], e);
0174 e += x[1];
0175 e -= a.x[1];
0176 x[0] = qd::quick_two_sum(s, e, x[1]);
0177 return *this;
0178 #else
0179 double s1, s2, t1, t2;
0180 s1 = qd::two_diff(x[0], a.x[0], s2);
0181 t1 = qd::two_diff(x[1], a.x[1], t2);
0182 s2 += t1;
0183 s1 = qd::quick_two_sum(s1, s2, s2);
0184 s2 += t2;
0185 x[0] = qd::quick_two_sum(s1, s2, x[1]);
0186 return *this;
0187 #endif
0188 }
0189
0190
0191 inline dd_real dd_real::operator-() const {
0192 return dd_real(-x[0], -x[1]);
0193 }
0194
0195
0196
0197 inline dd_real dd_real::mul(double a, double b) {
0198 double p, e;
0199 p = qd::two_prod(a, b, e);
0200 return dd_real(p, e);
0201 }
0202
0203
0204 inline dd_real ldexp(const dd_real &a, int exp) {
0205 return dd_real(std::ldexp(a.x[0], exp), std::ldexp(a.x[1], exp));
0206 }
0207
0208
0209 inline dd_real mul_pwr2(const dd_real &a, double b) {
0210 return dd_real(a.x[0] * b, a.x[1] * b);
0211 }
0212
0213
0214 inline dd_real operator*(const dd_real &a, double b) {
0215 double p1, p2;
0216
0217 p1 = qd::two_prod(a.x[0], b, p2);
0218 p2 += (a.x[1] * b);
0219 p1 = qd::quick_two_sum(p1, p2, p2);
0220 return dd_real(p1, p2);
0221 }
0222
0223
0224 inline dd_real operator*(const dd_real &a, const dd_real &b) {
0225 double p1, p2;
0226
0227 p1 = qd::two_prod(a.x[0], b.x[0], p2);
0228 p2 += (a.x[0] * b.x[1] + a.x[1] * b.x[0]);
0229 p1 = qd::quick_two_sum(p1, p2, p2);
0230 return dd_real(p1, p2);
0231 }
0232
0233
0234 inline dd_real operator*(double a, const dd_real &b) {
0235 return (b * a);
0236 }
0237
0238
0239
0240 inline dd_real &dd_real::operator*=(double a) {
0241 double p1, p2;
0242 p1 = qd::two_prod(x[0], a, p2);
0243 p2 += x[1] * a;
0244 x[0] = qd::quick_two_sum(p1, p2, x[1]);
0245 return *this;
0246 }
0247
0248
0249 inline dd_real &dd_real::operator*=(const dd_real &a) {
0250 double p1, p2;
0251 p1 = qd::two_prod(x[0], a.x[0], p2);
0252 p2 += a.x[1] * x[0];
0253 p2 += a.x[0] * x[1];
0254 x[0] = qd::quick_two_sum(p1, p2, x[1]);
0255 return *this;
0256 }
0257
0258
0259 inline dd_real dd_real::div(double a, double b) {
0260 double q1, q2;
0261 double p1, p2;
0262 double s, e;
0263
0264 q1 = a / b;
0265
0266
0267 p1 = qd::two_prod(q1, b, p2);
0268 s = qd::two_diff(a, p1, e);
0269 e -= p2;
0270
0271
0272 q2 = (s + e) / b;
0273
0274 s = qd::quick_two_sum(q1, q2, e);
0275
0276 return dd_real(s, e);
0277 }
0278
0279
0280 inline dd_real operator/(const dd_real &a, double b) {
0281
0282 double q1, q2;
0283 double p1, p2;
0284 double s, e;
0285 dd_real r;
0286
0287 q1 = a.x[0] / b;
0288
0289
0290 p1 = qd::two_prod(q1, b, p2);
0291 s = qd::two_diff(a.x[0], p1, e);
0292 e += a.x[1];
0293 e -= p2;
0294
0295
0296 q2 = (s + e) / b;
0297
0298
0299 r.x[0] = qd::quick_two_sum(q1, q2, r.x[1]);
0300
0301 return r;
0302 }
0303
0304 inline dd_real dd_real::sloppy_div(const dd_real &a, const dd_real &b) {
0305 double s1, s2;
0306 double q1, q2;
0307 dd_real r;
0308
0309 q1 = a.x[0] / b.x[0];
0310
0311
0312 r = b * q1;
0313 s1 = qd::two_diff(a.x[0], r.x[0], s2);
0314 s2 -= r.x[1];
0315 s2 += a.x[1];
0316
0317
0318 q2 = (s1 + s2) / b.x[0];
0319
0320
0321 r.x[0] = qd::quick_two_sum(q1, q2, r.x[1]);
0322 return r;
0323 }
0324
0325 inline dd_real dd_real::accurate_div(const dd_real &a, const dd_real &b) {
0326 double q1, q2, q3;
0327 dd_real r;
0328
0329 q1 = a.x[0] / b.x[0];
0330
0331 r = a - q1 * b;
0332
0333 q2 = r.x[0] / b.x[0];
0334 r -= (q2 * b);
0335
0336 q3 = r.x[0] / b.x[0];
0337
0338 q1 = qd::quick_two_sum(q1, q2, q2);
0339 r = dd_real(q1, q2) + q3;
0340 return r;
0341 }
0342
0343
0344 inline dd_real operator/(const dd_real &a, const dd_real &b) {
0345 #ifdef QD_SLOPPY_DIV
0346 return dd_real::sloppy_div(a, b);
0347 #else
0348 return dd_real::accurate_div(a, b);
0349 #endif
0350 }
0351
0352
0353 inline dd_real operator/(double a, const dd_real &b) {
0354 return dd_real(a) / b;
0355 }
0356
0357 inline dd_real inv(const dd_real &a) {
0358 return 1.0 / a;
0359 }
0360
0361
0362
0363 inline dd_real &dd_real::operator/=(double a) {
0364 *this = *this / a;
0365 return *this;
0366 }
0367
0368
0369 inline dd_real &dd_real::operator/=(const dd_real &a) {
0370 *this = *this / a;
0371 return *this;
0372 }
0373
0374
0375 inline dd_real drem(const dd_real &a, const dd_real &b) {
0376 dd_real n = nint(a / b);
0377 return (a - n * b);
0378 }
0379
0380 inline dd_real divrem(const dd_real &a, const dd_real &b, dd_real &r) {
0381 dd_real n = nint(a / b);
0382 r = a - n * b;
0383 return n;
0384 }
0385
0386
0387 inline dd_real sqr(const dd_real &a) {
0388 double p1, p2;
0389 double s1, s2;
0390 p1 = qd::two_sqr(a.x[0], p2);
0391 p2 += 2.0 * a.x[0] * a.x[1];
0392 p2 += a.x[1] * a.x[1];
0393 s1 = qd::quick_two_sum(p1, p2, s2);
0394 return dd_real(s1, s2);
0395 }
0396
0397 inline dd_real dd_real::sqr(double a) {
0398 double p1, p2;
0399 p1 = qd::two_sqr(a, p2);
0400 return dd_real(p1, p2);
0401 }
0402
0403
0404
0405 inline dd_real dd_real::operator^(int n) {
0406 return npwr(*this, n);
0407 }
0408
0409
0410
0411
0412 inline dd_real &dd_real::operator=(double a) {
0413 x[0] = a;
0414 x[1] = 0.0;
0415 return *this;
0416 }
0417
0418
0419
0420 inline bool operator==(const dd_real &a, double b) {
0421 return (a.x[0] == b && a.x[1] == 0.0);
0422 }
0423
0424
0425 inline bool operator==(const dd_real &a, const dd_real &b) {
0426 return (a.x[0] == b.x[0] && a.x[1] == b.x[1]);
0427 }
0428
0429
0430 inline bool operator==(double a, const dd_real &b) {
0431 return (a == b.x[0] && b.x[1] == 0.0);
0432 }
0433
0434
0435
0436 inline bool operator>(const dd_real &a, double b) {
0437 return (a.x[0] > b || (a.x[0] == b && a.x[1] > 0.0));
0438 }
0439
0440
0441 inline bool operator>(const dd_real &a, const dd_real &b) {
0442 return (a.x[0] > b.x[0] || (a.x[0] == b.x[0] && a.x[1] > b.x[1]));
0443 }
0444
0445
0446 inline bool operator>(double a, const dd_real &b) {
0447 return (a > b.x[0] || (a == b.x[0] && b.x[1] < 0.0));
0448 }
0449
0450
0451
0452 inline bool operator<(const dd_real &a, double b) {
0453 return (a.x[0] < b || (a.x[0] == b && a.x[1] < 0.0));
0454 }
0455
0456
0457 inline bool operator<(const dd_real &a, const dd_real &b) {
0458 return (a.x[0] < b.x[0] || (a.x[0] == b.x[0] && a.x[1] < b.x[1]));
0459 }
0460
0461
0462 inline bool operator<(double a, const dd_real &b) {
0463 return (a < b.x[0] || (a == b.x[0] && b.x[1] > 0.0));
0464 }
0465
0466
0467
0468 inline bool operator>=(const dd_real &a, double b) {
0469 return (a.x[0] > b || (a.x[0] == b && a.x[1] >= 0.0));
0470 }
0471
0472
0473 inline bool operator>=(const dd_real &a, const dd_real &b) {
0474 return (a.x[0] > b.x[0] || (a.x[0] == b.x[0] && a.x[1] >= b.x[1]));
0475 }
0476
0477
0478 inline bool operator>=(double a, const dd_real &b) {
0479 return (b <= a);
0480 }
0481
0482
0483
0484 inline bool operator<=(const dd_real &a, double b) {
0485 return (a.x[0] < b || (a.x[0] == b && a.x[1] <= 0.0));
0486 }
0487
0488
0489 inline bool operator<=(const dd_real &a, const dd_real &b) {
0490 return (a.x[0] < b.x[0] || (a.x[0] == b.x[0] && a.x[1] <= b.x[1]));
0491 }
0492
0493
0494 inline bool operator<=(double a, const dd_real &b) {
0495 return (b >= a);
0496 }
0497
0498
0499
0500 inline bool operator!=(const dd_real &a, double b) {
0501 return (a.x[0] != b || a.x[1] != 0.0);
0502 }
0503
0504
0505 inline bool operator!=(const dd_real &a, const dd_real &b) {
0506 return (a.x[0] != b.x[0] || a.x[1] != b.x[1]);
0507 }
0508
0509
0510 inline bool operator!=(double a, const dd_real &b) {
0511 return (a != b.x[0] || b.x[1] != 0.0);
0512 }
0513
0514
0515
0516 inline bool dd_real::is_zero() const {
0517 return (x[0] == 0.0);
0518 }
0519
0520
0521 inline bool dd_real::is_one() const {
0522 return (x[0] == 1.0 && x[1] == 0.0);
0523 }
0524
0525
0526 inline bool dd_real::is_positive() const {
0527 return (x[0] > 0.0);
0528 }
0529
0530
0531 inline bool dd_real::is_negative() const {
0532 return (x[0] < 0.0);
0533 }
0534
0535
0536 inline dd_real abs(const dd_real &a) {
0537 return (a.x[0] < 0.0) ? -a : a;
0538 }
0539
0540 inline dd_real fabs(const dd_real &a) {
0541 return abs(a);
0542 }
0543
0544
0545 inline dd_real nint(const dd_real &a) {
0546 double hi = qd::nint(a.x[0]);
0547 double lo;
0548
0549 if (hi == a.x[0]) {
0550
0551 lo = qd::nint(a.x[1]);
0552
0553
0554 hi = qd::quick_two_sum(hi, lo, lo);
0555 } else {
0556
0557 lo = 0.0;
0558 if (std::abs(hi-a.x[0]) == 0.5 && a.x[1] < 0.0) {
0559
0560
0561 hi -= 1.0;
0562 }
0563 }
0564
0565 return dd_real(hi, lo);
0566 }
0567
0568 inline dd_real floor(const dd_real &a) {
0569 double hi = std::floor(a.x[0]);
0570 double lo = 0.0;
0571
0572 if (hi == a.x[0]) {
0573
0574 lo = std::floor(a.x[1]);
0575 hi = qd::quick_two_sum(hi, lo, lo);
0576 }
0577
0578 return dd_real(hi, lo);
0579 }
0580
0581 inline dd_real ceil(const dd_real &a) {
0582 double hi = std::ceil(a.x[0]);
0583 double lo = 0.0;
0584
0585 if (hi == a.x[0]) {
0586
0587 lo = std::ceil(a.x[1]);
0588 hi = qd::quick_two_sum(hi, lo, lo);
0589 }
0590
0591 return dd_real(hi, lo);
0592 }
0593
0594 inline dd_real aint(const dd_real &a) {
0595 return (a.x[0] >= 0.0) ? floor(a) : ceil(a);
0596 }
0597
0598
0599 inline double to_double(const dd_real &a) {
0600 return a.x[0];
0601 }
0602
0603
0604 inline int to_int(const dd_real &a) {
0605 return static_cast<int>(a.x[0]);
0606 }
0607
0608
0609 inline dd_real dd_real::rand() {
0610 return ddrand();
0611 }
0612
0613 #endif