Scippy

    SCIP

    Solving Constraint Integer Programs

    dbldblarith.h
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 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