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