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-2024 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