1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2 /* */ 3 /* This file is part of the program and library */ 4 /* SCIP --- Solving Constraint Integer Programs */ 5 /* */ 6 /* Copyright (C) 2002-2022 Konrad-Zuse-Zentrum */ 7 /* fuer Informationstechnik Berlin */ 8 /* */ 9 /* SCIP is distributed under the terms of the ZIB Academic License. */ 10 /* */ 11 /* You should have received a copy of the ZIB Academic License */ 12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */ 13 /* */ 14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15 16 /**@file dbldblarith.h 17 * @brief defines macros for basic operations in double-double arithmetic giving roughly twice the precision of a double 18 * @author Leona Gottwald 19 * 20 */ 21 22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 23 24 #ifndef _SCIP_DBLDBL_ARITH_ 25 #define _SCIP_DBLDBL_ARITH_ 26 27 #include "math.h" 28 29 30 #ifndef DISABLE_QUADPREC 31 32 /* smaller epsilon value for use with quadprecision */ 33 #define QUAD_EPSILON 1e-12 34 35 /* convenience macros for nicer usage of double double arithmetic */ 36 #define QUAD_HI(x) x ## hi 37 #define QUAD_LO(x) x ## lo 38 #define QUAD(x) QUAD_HI(x), QUAD_LO(x) 39 #define QUAD_MEMBER(x) QUAD_HI(x); QUAD_LO(x) 40 #define QUAD_TO_DBL(x) ( QUAD_HI(x) + QUAD_LO(x) ) 41 #define QUAD_SCALE(x, a) do { QUAD_HI(x) *= (a); QUAD_LO(x) *= (a); } while(0) 42 #define QUAD_ASSIGN(a, constant) do { QUAD_HI(a) = (constant); QUAD_LO(a) = 0.0; } while(0) 43 #define QUAD_ASSIGN_Q(a, b) do { QUAD_HI(a) = QUAD_HI(b); QUAD_LO(a) = QUAD_LO(b); } while(0) 44 #define QUAD_ARRAY_SIZE(size) ((size)*2) 45 #define QUAD_ARRAY_LOAD(r, a, idx) do { QUAD_HI(r) = (a)[2*(idx)]; QUAD_LO(r) = (a)[2*(idx) + 1]; } while(0) 46 #define QUAD_ARRAY_STORE(a, idx, x) do { (a)[2*(idx)] = QUAD_HI(x); (a)[2*(idx) + 1] = QUAD_LO(x); } while(0) 47 48 /* define all the SCIPquadprec... macros such that they use the SCIPdbldbl... macros that expands the quad precision arguments using the above macros */ 49 #define SCIPquadprecProdDD(r, a, b) SCIPdbldblProd(QUAD_HI(r), QUAD_LO(r), a, b) 50 #define SCIPquadprecSquareD(r, a) SCIPdbldblSquare(QUAD_HI(r), QUAD_LO(r), a) 51 #define SCIPquadprecSumDD(r, a, b) SCIPdbldblSum(QUAD_HI(r), QUAD_LO(r), a, b) 52 #define SCIPquadprecDivDD(r, a, b) SCIPdbldblDiv(QUAD_HI(r), QUAD_LO(r), a, b) 53 #define SCIPquadprecSumQD(r, a, b) SCIPdbldblSum21(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a), b) 54 #define SCIPquadprecProdQD(r, a, b) SCIPdbldblProd21(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a), b) 55 #define SCIPquadprecDivDQ(r, a, b) SCIPdbldblDiv12(QUAD_HI(r), QUAD_LO(r), a, QUAD_HI(b), QUAD_LO(b)) 56 #define SCIPquadprecDivQD(r, a, b) SCIPdbldblDiv21(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a), b) 57 #define SCIPquadprecProdQQ(r, a, b) SCIPdbldblProd22(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a), QUAD_HI(b), QUAD_LO(b)) 58 #define SCIPquadprecSumQQ(r, a, b) SCIPdbldblSum22(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a), QUAD_HI(b), QUAD_LO(b)) 59 #define SCIPquadprecSquareQ(r, a) SCIPdbldblSquare2(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a)) 60 #define SCIPquadprecDivQQ(r, a, b) SCIPdbldblDiv22(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a), QUAD_HI(b), QUAD_LO(b)) 61 #define SCIPquadprecSqrtD(r, a) SCIPdbldblSqrt(QUAD_HI(r), QUAD_LO(r), a) 62 #define SCIPquadprecSqrtQ(r, a) SCIPdbldblSqrt2(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a)) 63 #define SCIPquadprecAbsQ(r, a) SCIPdbldblAbs2(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a)) 64 #define SCIPquadprecFloorQ(r, a) SCIPdbldblFloor2(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a)) 65 #define SCIPquadprecCeilQ(r, a) SCIPdbldblCeil2(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a)) 66 #define SCIPquadprecEpsFloorQ(r, a, eps) SCIPdbldblEpsFloor2(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a), eps) 67 #define SCIPquadprecEpsCeilQ(r, a, eps) SCIPdbldblEpsCeil2(QUAD_HI(r), QUAD_LO(r), QUAD_HI(a), QUAD_LO(a), eps) 68 69 #else 70 71 /* normal epsilon value if quadprecision is disabled */ 72 #define QUAD_EPSILON 1e-9 73 74 /* dummy macros that use normal arithmetic */ 75 #define QUAD_HI(x) x 76 #define QUAD_LO(x) 0.0 77 #define QUAD(x) x 78 #define QUAD_MEMBER(x) x 79 #define QUAD_TO_DBL(x) (x) 80 #define QUAD_SCALE(x, a) do { (x) *= (a); } while(0) 81 #define QUAD_ASSIGN(a, constant) do { (a) = constant; } while(0) 82 #define QUAD_ASSIGN_Q(a, b) do { (a) = (b); } while(0) 83 #define QUAD_ARRAY_SIZE(size) (size) 84 #define QUAD_ARRAY_LOAD(r, a, idx) do { r = (a)[(idx)]; } while(0) 85 #define QUAD_ARRAY_STORE(a, idx, x) do { (a)[(idx)] = (x); } while(0) 86 87 #define SCIPquadprecProdDD(r, a, b) do { (r) = (a) * (b); } while(0) 88 #define SCIPquadprecSquareD(r, a) do { (r) = (a) * (a); } while(0) 89 #define SCIPquadprecSumDD(r, a, b) do { (r) = (a) + (b); } while(0) 90 #define SCIPquadprecDivDD(r, a, b) do { (r) = (a) / (b); } while(0) 91 #define SCIPquadprecSumQD(r, a, b) do { (r) = (a) + (b); } while(0) 92 #define SCIPquadprecProdQD(r, a, b) do { (r) = (a) * (b); } while(0) 93 #define SCIPquadprecDivDQ(r, a, b) do { (r) = (a) / (b); } while(0) 94 #define SCIPquadprecDivQD(r, a, b) do { (r) = (a) / (b); } while(0) 95 #define SCIPquadprecProdQQ(r, a, b) do { (r) = (a) * (b); } while(0) 96 #define SCIPquadprecSumQQ(r, a, b) do { (r) = (a) + (b); } while(0) 97 #define SCIPquadprecSquareQ(r, a) do { (r) = (a) * (a); } while(0) 98 #define SCIPquadprecDivQQ(r, a, b) do { (r) = (a) / (b); } while(0) 99 #define SCIPquadprecSqrtD(r, a) do { (r) = sqrt(a); } while(0) 100 #define SCIPquadprecSqrtQ(r, a) do { (r) = sqrt(a); } while(0) 101 #define SCIPquadprecAbsQ(r, a) do { (r) = fabs(a); } while(0) 102 #define SCIPquadprecFloorQ(r, a) do { (r) = floor(a); } while(0) 103 #define SCIPquadprecCeilQ(r, a) do { (r) = ceil(a); } while(0) 104 #define SCIPquadprecEpsFloorQ(r, a, eps) do { (r) = floor((a) + (eps)); } while(0) 105 #define SCIPquadprecEpsCeilQ(r, a, eps) do { (r) = ceil((a) - (eps)); } while(0) 106 107 #endif 108 109 #define __SCIPdbldblSplit(rhi, rlo, x) \ 110 do { \ 111 const double __tmp_split_dbl = 134217729.0 * (x); \ 112 (rhi) = __tmp_split_dbl - (__tmp_split_dbl - (x)); \ 113 (rlo) = (x) - (rhi);\ 114 } while(0) 115 116 /** multiply two floating point numbers, both given by one double, and return the result as two doubles. */ 117 #define SCIPdbldblProd(rhi, rlo, a, b) \ 118 do { \ 119 double __tmp_dbldbl_prod_ahi; \ 120 double __tmp_dbldbl_prod_alo; \ 121 double __tmp_dbldbl_prod_bhi; \ 122 double __tmp_dbldbl_prod_blo; \ 123 __SCIPdbldblSplit(__tmp_dbldbl_prod_ahi, __tmp_dbldbl_prod_alo, a); \ 124 __SCIPdbldblSplit(__tmp_dbldbl_prod_bhi, __tmp_dbldbl_prod_blo, b); \ 125 (rhi) = (a) * (b); \ 126 (rlo) = __tmp_dbldbl_prod_alo * __tmp_dbldbl_prod_blo - \ 127 ((((rhi) - __tmp_dbldbl_prod_ahi * __tmp_dbldbl_prod_bhi) \ 128 - __tmp_dbldbl_prod_alo * __tmp_dbldbl_prod_bhi) \ 129 - __tmp_dbldbl_prod_ahi * __tmp_dbldbl_prod_blo); \ 130 } while(0) 131 132 /** square a floating point number given by one double and return the result as two doubles. */ 133 #define SCIPdbldblSquare(rhi, rlo, a) \ 134 do { \ 135 double __tmp_dbldbl_square_ahi; \ 136 double __tmp_dbldbl_square_alo; \ 137 __SCIPdbldblSplit(__tmp_dbldbl_square_ahi, __tmp_dbldbl_square_alo, a); \ 138 (rhi) = (a) * (a); \ 139 (rlo) = __tmp_dbldbl_square_alo * __tmp_dbldbl_square_alo - \ 140 ((((rhi) - __tmp_dbldbl_square_ahi * __tmp_dbldbl_square_ahi) \ 141 - 2.0 * __tmp_dbldbl_square_alo * __tmp_dbldbl_square_ahi)); \ 142 } while(0) 143 144 /** add two floating point numbers, both given by one double, and return the result as two doubles. */ 145 #define SCIPdbldblSum(rhi, rlo, a, b) \ 146 do { \ 147 double __tmp1_dbldbl_sum; \ 148 double __tmp2_dbldbl_sum; \ 149 __tmp2_dbldbl_sum = (a) + (b); \ 150 __tmp1_dbldbl_sum = __tmp2_dbldbl_sum - (a); \ 151 (rlo) = ((a) - (__tmp2_dbldbl_sum - __tmp1_dbldbl_sum)) + ((b) - __tmp1_dbldbl_sum); \ 152 (rhi) = __tmp2_dbldbl_sum; \ 153 } while(0) 154 155 /** divide two floating point numbers, both given by one double, and return the result as two doubles. */ 156 #define SCIPdbldblDiv(rhi, rlo, a, b) \ 157 do { \ 158 double __tmp_dbldbl_div_hi; \ 159 double __tmp_dbldbl_div_lo; \ 160 double __estim_dbldbl_div = (a)/(b); \ 161 SCIPdbldblProd(__tmp_dbldbl_div_hi, __tmp_dbldbl_div_lo, b, __estim_dbldbl_div); \ 162 SCIPdbldblSum21(__tmp_dbldbl_div_hi, __tmp_dbldbl_div_lo, __tmp_dbldbl_div_hi, __tmp_dbldbl_div_lo, -(a)); \ 163 __tmp_dbldbl_div_hi /= (b); \ 164 __tmp_dbldbl_div_lo /= (b); \ 165 SCIPdbldblSum21(rhi, rlo, -__tmp_dbldbl_div_hi, -__tmp_dbldbl_div_lo, __estim_dbldbl_div); \ 166 } while(0) 167 168 /** add two floating point numbers, the first is given by two doubles, the second is given by one double, 169 * and return the result as two doubles. 170 */ 171 #define SCIPdbldblSum21(rhi, rlo, ahi, alo, b) \ 172 do { \ 173 double __tmp_dbldbl_sum21_hi; \ 174 double __tmp_dbldbl_sum21_lo; \ 175 SCIPdbldblSum(__tmp_dbldbl_sum21_hi, __tmp_dbldbl_sum21_lo, ahi, b); \ 176 (rlo) = __tmp_dbldbl_sum21_lo + (alo); \ 177 (rhi) = __tmp_dbldbl_sum21_hi; \ 178 } while(0) 179 180 181 /** multiply two floating point numbers, the first is given by two doubles, the second is given by one double, 182 * and return the result as two doubles. 183 */ 184 #define SCIPdbldblProd21(rhi, rlo, ahi, alo, b) \ 185 do { \ 186 double __tmp_dbldbl_prod21_hi; \ 187 double __tmp_dbldbl_prod21_lo; \ 188 SCIPdbldblProd(__tmp_dbldbl_prod21_hi, __tmp_dbldbl_prod21_lo, ahi, b); \ 189 (rlo) = (alo) * (b) + __tmp_dbldbl_prod21_lo; \ 190 (rhi) = __tmp_dbldbl_prod21_hi; \ 191 } while(0) 192 193 /** divide two floating point numbers, the first is given by one double, the second is given by two doubles, 194 * and return the result as two doubles. 195 */ 196 #define SCIPdbldblDiv12(rhi, rlo, a, bhi, blo) \ 197 do { \ 198 double __tmp_dbldbl_div12_hi; \ 199 double __tmp_dbldbl_div12_lo; \ 200 double __estim_dbldbl_div12 = (a)/(bhi); \ 201 SCIPdbldblProd21(__tmp_dbldbl_div12_hi, __tmp_dbldbl_div12_lo, bhi, blo, __estim_dbldbl_div12); \ 202 SCIPdbldblSum21(__tmp_dbldbl_div12_hi, __tmp_dbldbl_div12_lo, __tmp_dbldbl_div12_hi, __tmp_dbldbl_div12_lo, -(a)); \ 203 __tmp_dbldbl_div12_hi /= (bhi); \ 204 __tmp_dbldbl_div12_lo /= (bhi); \ 205 SCIPdbldblSum21(rhi, rlo, -__tmp_dbldbl_div12_hi, -__tmp_dbldbl_div12_lo, __estim_dbldbl_div12); \ 206 } while(0) 207 208 209 /** divide two floating point numbers, the first is given by two doubles, the second is given by one double, 210 * and return the result as two doubles. 211 */ 212 #define SCIPdbldblDiv21(rhi, rlo, ahi, alo, b) \ 213 do { \ 214 double __tmp_dbldbl_div21_hi; \ 215 double __tmp_dbldbl_div21_lo; \ 216 double __estim_dbldbl_div21_hi; \ 217 double __estim_dbldbl_div21_lo; \ 218 __estim_dbldbl_div21_hi = (ahi)/(b); \ 219 __estim_dbldbl_div21_lo = (alo)/(b); \ 220 SCIPdbldblProd21(__tmp_dbldbl_div21_hi, __tmp_dbldbl_div21_lo, __estim_dbldbl_div21_hi, __estim_dbldbl_div21_lo, b); \ 221 SCIPdbldblSum22(__tmp_dbldbl_div21_hi, __tmp_dbldbl_div21_lo, __tmp_dbldbl_div21_hi, __tmp_dbldbl_div21_lo, -(ahi), -(alo)); \ 222 __tmp_dbldbl_div21_hi /= (b); \ 223 __tmp_dbldbl_div21_lo /= (b); \ 224 SCIPdbldblSum22(rhi, rlo, __estim_dbldbl_div21_hi, __estim_dbldbl_div21_lo, -__tmp_dbldbl_div21_hi, -__tmp_dbldbl_div21_lo); \ 225 } while(0) 226 227 /** multiply two floating point numbers, both given by two doubles, and return the result as two doubles. */ 228 #define SCIPdbldblProd22(rhi, rlo, ahi, alo, bhi, blo) \ 229 do { \ 230 double __tmp_dbldbl_prod22_hi; \ 231 double __tmp_dbldbl_prod22_lo; \ 232 SCIPdbldblProd(__tmp_dbldbl_prod22_hi, __tmp_dbldbl_prod22_lo, ahi, bhi); \ 233 SCIPdbldblSum21(__tmp_dbldbl_prod22_hi, __tmp_dbldbl_prod22_lo, \ 234 __tmp_dbldbl_prod22_hi, __tmp_dbldbl_prod22_lo, (alo) * (bhi)); \ 235 SCIPdbldblSum21(rhi, rlo, \ 236 __tmp_dbldbl_prod22_hi, __tmp_dbldbl_prod22_lo, (ahi) * (blo)); \ 237 } while(0) 238 239 /** add two floating point numbers, both given by two doubles, and return the result as two doubles. */ 240 #define SCIPdbldblSum22(rhi, rlo, ahi, alo, bhi, blo) \ 241 do { \ 242 double __tmp_dbldbl_sum22_hi; \ 243 double __tmp_dbldbl_sum22_lo; \ 244 SCIPdbldblSum21(__tmp_dbldbl_sum22_hi, __tmp_dbldbl_sum22_lo, ahi, alo, bhi); \ 245 SCIPdbldblSum21(rhi, rlo, __tmp_dbldbl_sum22_hi, __tmp_dbldbl_sum22_lo, blo); \ 246 } while(0) 247 248 /** square a floating point number given by two doubles and return the result as two doubles. */ 249 #define SCIPdbldblSquare2(rhi, rlo, ahi, alo) \ 250 do { \ 251 double __tmp_dbldbl_square2_hi; \ 252 double __tmp_dbldbl_square2_lo; \ 253 SCIPdbldblSquare(__tmp_dbldbl_square2_hi, __tmp_dbldbl_square2_lo, (ahi)); \ 254 SCIPdbldblSum21(rhi, rlo, __tmp_dbldbl_square2_hi, __tmp_dbldbl_square2_lo, 2 * (ahi) * (alo)); \ 255 } while(0) 256 257 /** divide two floating point numbers, both given by two doubles, and return the result as two doubles. */ 258 #define SCIPdbldblDiv22(rhi, rlo, ahi, alo, bhi, blo) \ 259 do { \ 260 double __tmp_dbldbl_div22_hi; \ 261 double __tmp_dbldbl_div22_lo; \ 262 double __estim_dbldbl_div22_hi = (ahi) / (bhi); \ 263 double __estim_dbldbl_div22_lo = (alo) / (bhi); \ 264 SCIPdbldblProd22(__tmp_dbldbl_div22_hi, __tmp_dbldbl_div22_lo, \ 265 bhi, blo, __estim_dbldbl_div22_hi, __estim_dbldbl_div22_lo); \ 266 SCIPdbldblSum22(__tmp_dbldbl_div22_hi, __tmp_dbldbl_div22_lo, \ 267 __tmp_dbldbl_div22_hi, __tmp_dbldbl_div22_lo, -(ahi), -(alo)); \ 268 __tmp_dbldbl_div22_hi /= (bhi); \ 269 __tmp_dbldbl_div22_lo /= (bhi); \ 270 SCIPdbldblSum22(rhi, rlo, __estim_dbldbl_div22_hi, __estim_dbldbl_div22_lo, \ 271 -__tmp_dbldbl_div22_hi, -__tmp_dbldbl_div22_lo); \ 272 } while(0) 273 274 275 /** take the square root of a floating point number given by one double and return the result as two doubles. */ 276 #define SCIPdbldblSqrt(rhi, rlo, a) \ 277 do { \ 278 double __estim_dbldbl_sqrt = sqrt(a); \ 279 if( __estim_dbldbl_sqrt != 0.0 ) \ 280 { \ 281 SCIPdbldblDiv(rhi, rlo, a, __estim_dbldbl_sqrt); \ 282 SCIPdbldblSum21(rhi, rlo, rhi, rlo, __estim_dbldbl_sqrt); \ 283 (rhi) *= 0.5; \ 284 (rlo) *= 0.5; \ 285 } \ 286 else \ 287 { \ 288 (rhi) = 0.0; \ 289 (rlo) = 0.0; \ 290 } \ 291 } while(0) 292 293 294 /** take the square root of a floating point number given by two doubles and return the result as two doubles. */ 295 #define SCIPdbldblSqrt2(rhi, rlo, ahi, alo) \ 296 do { \ 297 double __estim_dbldbl_sqrt2 = sqrt(ahi + alo); \ 298 if( __estim_dbldbl_sqrt2 != 0.0 ) \ 299 { \ 300 SCIPdbldblDiv21(rhi, rlo, ahi, alo, __estim_dbldbl_sqrt2); \ 301 SCIPdbldblSum21(rhi, rlo, rhi, rlo, __estim_dbldbl_sqrt2); \ 302 (rhi) *= 0.5; \ 303 (rlo) *= 0.5; \ 304 } \ 305 else \ 306 { \ 307 (rhi) = 0.0; \ 308 (rlo) = 0.0; \ 309 } \ 310 } while(0) 311 312 /** compute the absolute value of the floating point number given by two doubles */ 313 #define SCIPdbldblAbs2(rhi, rlo, ahi, alo) \ 314 do { \ 315 if( ahi < 0.0 ) \ 316 { \ 317 (rhi) = -(ahi); \ 318 (rlo) = -(alo); \ 319 } \ 320 else \ 321 { \ 322 (rhi) = (ahi); \ 323 (rlo) = (alo); \ 324 } \ 325 } while(0) 326 327 /** compute the floored value of the floating point number given by two doubles */ 328 #define SCIPdbldblFloor2(rhi, rlo, ahi, alo) \ 329 do { \ 330 double __tmp_dbldbl_floor; \ 331 __tmp_dbldbl_floor = floor((ahi) + (alo)); \ 332 SCIPdbldblSum21(rhi, rlo, ahi, alo, -__tmp_dbldbl_floor); \ 333 if( ((rhi) - 1.0) + (rlo) < 0.0 && (rhi) + (rlo) >= 0.0 ) \ 334 { \ 335 /* floor in double precision was fine */ \ 336 (rhi) = __tmp_dbldbl_floor; \ 337 (rlo) = 0.0; \ 338 } \ 339 else \ 340 { \ 341 /* floor in double precision needs to be corrected */ \ 342 double __tmp2_dbldbl_floor = floor((rhi) + (rlo)); \ 343 SCIPdbldblSum(rhi, rlo, __tmp_dbldbl_floor, __tmp2_dbldbl_floor); \ 344 } \ 345 } while(0) 346 347 /** compute the ceiled value of the floating point number given by two doubles */ 348 #define SCIPdbldblCeil2(rhi, rlo, ahi, alo) \ 349 do { \ 350 double __tmp_dbldbl_ceil; \ 351 __tmp_dbldbl_ceil = ceil((ahi) + (alo)); \ 352 SCIPdbldblSum21(rhi, rlo, -(ahi), -(alo), __tmp_dbldbl_ceil); \ 353 if( ((rhi) - 1.0) + (rlo) < 0.0 && (rhi) + (rlo) >= 0.0 ) \ 354 { \ 355 /* ceil in double precision was fine */ \ 356 (rhi) = __tmp_dbldbl_ceil; \ 357 (rlo) = 0.0; \ 358 } \ 359 else \ 360 { \ 361 /* ceil in double precision needs to be corrected */ \ 362 double __tmp2_dbldbl_ceil = floor((rhi) + (rlo)); \ 363 SCIPdbldblSum(rhi, rlo, __tmp_dbldbl_ceil, -__tmp2_dbldbl_ceil); \ 364 } \ 365 } while(0) 366 367 /** compute the floored value of the floating point number given by two doubles, add epsilon first for safety */ 368 #define SCIPdbldblEpsFloor2(rhi, rlo, ahi, alo, eps) SCIPdbldblFloor2(rhi, rlo, ahi, (alo) + (eps)) 369 370 /** compute the ceiled value of the floating point number given by two doubles, subtract epsilon first for safety */ 371 #define SCIPdbldblEpsCeil2(rhi, rlo, ahi, alo, eps) SCIPdbldblCeil2(rhi, rlo, ahi, (alo) - (eps)) 372 373 #endif 374