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