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