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