Scippy

SCIP

Solving Constraint Integer Programs

intervalarith.c
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-2014 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file intervalarith.c
17  * @brief interval arithmetics for provable bounds
18  * @author Tobias Achterberg
19  * @author Stefan Vigerske
20  * @author Kati Wolter
21  */
22 
23 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
24 
25 #include <stdlib.h>
26 #include <assert.h>
27 
28 #include "scip/def.h"
29 #include "scip/intervalarith.h"
30 #include "scip/pub_message.h"
31 #include "scip/misc.h"
32 
33 #ifdef ROUNDING_FE
34 #define ROUNDING
35 /*
36  * Linux rounding operations
37  */
38 
39 #include <fenv.h>
40 
41 /** Linux rounding mode settings */
42 #define SCIP_ROUND_DOWNWARDS FE_DOWNWARD /**< round always down */
43 #define SCIP_ROUND_UPWARDS FE_UPWARD /**< round always up */
44 #define SCIP_ROUND_NEAREST FE_TONEAREST /**< round always to nearest */
45 #define SCIP_ROUND_ZERO FE_TOWARDZERO /**< round always towards 0.0 */
46 
47 /** returns whether rounding mode control is available */
49  void
50  )
51 {
52  return TRUE;
53 }
54 
55 /** sets rounding mode of floating point operations */
57  SCIP_ROUNDMODE roundmode /**< rounding mode to activate */
58  )
59 {
60  if( fesetround(roundmode) != 0 )
61  {
62  SCIPerrorMessage("error setting rounding mode to %d\n", roundmode);
63  SCIPABORT();
64  }
65 }
66 
67 /** gets current rounding mode of floating point operations */
69  void
70  )
71 {
72  return (SCIP_ROUNDMODE)fegetround();
73 }
74 
75 #endif
76 
77 
78 
79 #ifdef ROUNDING_FP
80 #define ROUNDING
81 /*
82  * OSF rounding operations
83  */
84 
85 #include <float.h>
86 
87 /** OSF rounding mode settings */
88 #define SCIP_ROUND_DOWNWARDS FP_RND_RM /**< round always down */
89 #define SCIP_ROUND_UPWARDS FP_RND_RP /**< round always up */
90 #define SCIP_ROUND_NEAREST FP_RND_RN /**< round always to nearest */
91 #define SCIP_ROUND_ZERO FP_RND_RZ /**< round always towards 0.0 */
92 
93 /** returns whether rounding mode control is available */
95  void
96  )
97 {
98  return TRUE;
99 }
100 
101 /** sets rounding mode of floating point operations */
103  SCIP_ROUNDMODE roundmode /**< rounding mode to activate */
104  )
105 {
106  if( write_rnd(roundmode) != 0 )
107  {
108  SCIPerrorMessage("error setting rounding mode to %d\n", roundmode);
109  SCIPABORT();
110  }
111 }
112 
113 /** gets current rounding mode of floating point operations */
115  void
116  )
117 {
118  return read_rnd();
119 }
120 
121 #endif
122 
123 
124 
125 #ifdef ROUNDING_MS
126 #define ROUNDING
127 /*
128  * Microsoft compiler rounding operations
129  */
130 
131 #include <float.h>
132 
133 /** Microsoft rounding mode settings */
134 #define SCIP_ROUND_DOWNWARDS RC_DOWN /**< round always down */
135 #define SCIP_ROUND_UPWARDS RC_UP /**< round always up */
136 #define SCIP_ROUND_NEAREST RC_NEAR /**< round always to nearest */
137 #define SCIP_ROUND_ZERO RC_CHOP /**< round always towards zero */
138 
139 /** returns whether rounding mode control is available */
141  void
142  )
143 {
144  return TRUE;
145 }
146 
147 /** sets rounding mode of floating point operations */
149  SCIP_ROUNDMODE roundmode /**< rounding mode to activate */
150  )
151 {
152  if( (_controlfp(roundmode, _MCW_RC) & _MCW_RC) != roundmode )
153  {
154  SCIPerrorMessage("error setting rounding mode to %x\n", roundmode);
155  SCIPABORT();
156  }
157 }
158 
159 /** gets current rounding mode of floating point operations */
161  void
162  )
163 {
164  return _controlfp(0, 0) & _MCW_RC;
165 }
166 #endif
167 
168 
169 
170 #ifndef ROUNDING
171 /*
172  * rouding operations not available
173  */
174 #define SCIP_ROUND_DOWNWARDS 0 /**< round always down */
175 #define SCIP_ROUND_UPWARDS 1 /**< round always up */
176 #define SCIP_ROUND_NEAREST 2 /**< round always to nearest */
177 #define SCIP_ROUND_ZERO 3 /**< round always towards zero */
178 
179 /** returns whether rounding mode control is available */
181  void
182  )
183 {
184  return FALSE;
185 }
186 
187 /** sets rounding mode of floating point operations */
189  SCIP_ROUNDMODE roundmode /**< rounding mode to activate */
190  )
191 { /*lint --e{715}*/
192  SCIPerrorMessage("setting rounding mode not available - interval arithmetic is invalid!\n");
193 }
194 
195 /** gets current rounding mode of floating point operations */
197  void
198  )
199 {
200  return SCIP_ROUND_NEAREST;
201 }
202 #else
203 #undef ROUNDING
204 #endif
205 
206 
207 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) /* gcc or icc compiler on x86 32bit or 64bit */
208 
209 /** gets the negation of a double
210  * Do this in a way that the compiler does not "optimize" it away, which usually does not considers rounding modes.
211  * However, compiling with -frounding-math would allow to return -x here.
212  */
213 static
214 double negate(
215  /* we explicitely use double here, since I'm not sure the assembler code would work as it for other float's */
216  double x /**< number that should be negated */
217  )
218 {
219  /* The following line of code is taken from GAOL, http://sourceforge.net/projects/gaol. */
220  asm volatile ("fldl %1; fchs; fstpl %0" : "=m" (x) : "m" (x));
221  return x;
222 }
223 
224 /* cl or icl compiler on 32bit windows or icl compiler on 64bit windows
225  * cl on 64bit windows does not seem to support inline assembler
226  */
227 #elif defined(_MSC_VER) && (defined(__INTEL_COMPILER) || !defined(_M_X64))
228 
229 /** gets the negation of a double
230  * Do this in a way that the compiler does not "optimize" it away, which usually does not considers rounding modes.
231  */
232 static
233 double negate(
234  /* we explicitely use double here, since I'm not sure the assembler code would work as it for other float's */
235  double x /**< number that should be negated */
236  )
237 {
238  /* The following lines of code are taken from GAOL, http://sourceforge.net/projects/gaol. */
239  __asm {
240  fld x
241  fchs
242  fstp x
243  }
244  return x;
245 }
246 
247 /* for the MS compiler, the function nextafter is named _nextafter */
248 #ifndef NO_NEXTAFTER
249 #define nextafter(x,y) _nextafter(x,y)
250 #endif
251 
252 #else /* unknown compiler or MSVS 64bit */
253 
254 /* for the MS compiler, the function nextafter is named _nextafter */
255 #if defined(_MSC_VER) && defined(_M_X64) && !defined(NO_NEXTAFTER)
256 #define nextafter(x,y) _nextafter(x,y)
257 #endif
258 
259 /** gets the negation of a double
260  *
261  * Fallback implementation that calls the negation method from misc.o.
262  * Having the implementation in a different object file will hopefully prevent
263  * it from being "optimized away".
264  */
265 static
267  SCIP_Real x /**< number that should be negated */
268  )
269 {
270  return SCIPnegateReal(x);
271 }
272 
273 #endif
274 
275 /* on systems where the function nextafter is not defined, we provide an implementation from Sun */
276 #ifdef NO_NEXTAFTER
277 /* The following implementation of the routine nextafter() comes with the following license:
278  *
279  * ====================================================
280  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
281  *
282  * Developed at SunSoft, a Sun Microsystems, Inc. business.
283  * Permission to use, copy, modify, and distribute this
284  * software is freely granted, provided that this notice
285  * is preserved.
286  * ====================================================
287  */
288 
289 #define __HI(x) *(1+(int*)&x)
290 #define __LO(x) *(int*)&x
291 #define __HIp(x) *(1+(int*)x)
292 #define __LOp(x) *(int*)x
293 
294 static
295 double nextafter(double x, double y)
296 {
297  int hx;
298  int hy;
299  int ix;
300  int iy;
301  unsigned lx;
302  unsigned ly;
303 
304  hx = __HI(x); /* high word of x */
305  lx = __LO(x); /* low word of x */
306  hy = __HI(y); /* high word of y */
307  ly = __LO(y); /* low word of y */
308  ix = hx&0x7fffffff; /* |x| */
309  iy = hy&0x7fffffff; /* |y| */
310 
311  if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) || /* x is nan */
312  ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 )) /* y is nan */
313  return x + y;
314 
315  /* x == y, return x */
316  if( x == y )
317  return x;
318 
319  /* x == 0 */
320  if( (ix|lx) == 0 )
321  {
322  /* return +-minsubnormal */
323  __HI(x) = hy&0x80000000;
324  __LO(x) = 1;
325  y = x * x;
326  if ( y == x )
327  return y;
328  else
329  return x; /* raise underflow flag */
330  }
331  /* x > 0 */
332  if( hx >= 0 )
333  {
334  /* x > y, x -= ulp */
335  if( hx > hy || ((hx == hy) && (lx > ly)) )
336  {
337  if ( lx == 0 )
338  hx -= 1;
339  lx -= 1;
340  }
341  else
342  {
343  /* x < y, x += ulp */
344  lx += 1;
345  if ( lx == 0 )
346  hx += 1;
347  }
348  }
349  else
350  {
351  /* x < 0 */
352  if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
353  {
354  /* x < y, x -= ulp */
355  if ( lx == 0 )
356  hx -= 1;
357  lx -= 1;
358  }
359  else
360  {
361  /* x > y, x += ulp */
362  lx += 1;
363  if( lx == 0 )
364  hx += 1;
365  }
366  }
367  hy = hx&0x7ff00000;
368  /* overflow */
369  if( hy >= 0x7ff00000 )
370  return x + x;
371  if( hy < 0x00100000 )
372  {
373  /* underflow */
374  y = x*x;
375  if( y != x )
376  {
377  /* raise underflow flag */
378  __HI(y) = hx;
379  __LO(y) = lx;
380  return y;
381  }
382  }
383  __HI(x) = hx;
384  __LO(x) = lx;
385  return x;
386 }
387 #endif
388 
389 /** sets rounding mode of floating point operations to downwards rounding */
391  void
392  )
393 {
395 }
396 
397 /** sets rounding mode of floating point operations to upwards rounding */
399  void
400  )
401 {
403 }
404 
405 /** sets rounding mode of floating point operations to nearest rounding */
407  void
408  )
409 {
411 }
412 
413 /** sets rounding mode of floating point operations to towards zero rounding */
415  void
416  )
417 {
419 }
420 
421 /** negates a number in a way that the compiler does not optimize it away */
423  SCIP_Real x /**< number to negate */
424  )
425 {
426  return negate((double)x);
427 }
428 
429 /*
430  * Interval arithmetic operations
431  */
432 
433 /* In debug mode, the following methods are implemented as function calls to ensure
434  * type validity.
435  * In optimized mode, the methods are implemented as defines to improve performance.
436  * However, we want to have them in the library anyways, so we have to undef the defines.
437  */
438 
439 #undef SCIPintervalGetInf
440 #undef SCIPintervalGetSup
441 #undef SCIPintervalSet
442 #undef SCIPintervalSetBounds
443 #undef SCIPintervalSetEmpty
444 #undef SCIPintervalIsEmpty
445 #undef SCIPintervalSetEntire
446 #undef SCIPintervalIsEntire
447 #undef SCIPintervalIsPositiveInfinity
448 #undef SCIPintervalIsNegativeInfinity
449 
450 /** returns infimum of interval */
452  SCIP_INTERVAL interval /**< interval */
453  )
454 {
455  return interval.inf;
456 }
457 
458 /** returns supremum of interval */
460  SCIP_INTERVAL interval /**< interval */
461  )
462 {
463  return interval.sup;
464 }
465 
466 /** stores given value as interval */
468  SCIP_INTERVAL* resultant, /**< interval to store value into */
469  SCIP_Real value /**< value to store */
470  )
471 {
472  assert(resultant != NULL);
473 
474  resultant->inf = value;
475  resultant->sup = value;
476 }
477 
478 /** stores given infimum and supremum as interval */
480  SCIP_INTERVAL* resultant, /**< interval to store value into */
481  SCIP_Real inf, /**< value to store as infimum */
482  SCIP_Real sup /**< value to store as supremum */
483  )
484 {
485  assert(resultant != NULL);
486  assert(inf <= sup);
487 
488  resultant->inf = inf;
489  resultant->sup = sup;
490 }
491 
492 /** sets interval to empty interval, which will be [infinity, -infinity] */
494  SCIP_INTERVAL* resultant /**< resultant interval of operation */
495  )
496 {
497  assert(resultant != NULL);
498 
499  resultant->inf = 1.0;
500  resultant->sup = -1.0;
501 }
502 
503 /** indicates whether interval is empty, i.e., whether inf > sup */
505  SCIP_INTERVAL operand /**< operand of operation */
506  )
507 {
508  return operand.sup < operand.inf;
509 }
510 
511 /** sets interval to entire [-infinity, +infinity] */
513  SCIP_Real infinity, /**< value for infinity */
514  SCIP_INTERVAL* resultant /**< resultant interval of operation */
515  )
516 {
517  assert(resultant != NULL);
518 
519  resultant->inf = -infinity;
520  resultant->sup = infinity;
521 }
522 
523 /** indicates whether interval is entire, i.e., whether inf <= -infinity and sup >= infinity */
525  SCIP_Real infinity, /**< value for infinity */
526  SCIP_INTERVAL operand /**< operand of operation */
527  )
528 {
529  return operand.inf <= -infinity && operand.sup >= infinity;
530 }
531 
532 /** indicates whether interval is positive infinity, i.e., [infinity, infinity] */
534  SCIP_Real infinity, /**< value for infinity */
535  SCIP_INTERVAL operand /**< operand of operation */
536  )
537 {
538  return operand.inf >= infinity && operand.sup >= operand.inf;
539 }
540 
541 /** indicates whether interval is negative infinity, i.e., [-infinity, -infinity] */
543  SCIP_Real infinity, /**< value for infinity */
544  SCIP_INTERVAL operand /**< operand of operation */
545  )
546 {
547  return operand.sup <= -infinity && operand.inf <= operand.sup;
548 }
549 
550 /** indicates whether operand1 is contained in operand2 */
552  SCIP_Real infinity, /**< value for infinity */
553  SCIP_INTERVAL operand1, /**< first operand of operation */
554  SCIP_INTERVAL operand2 /**< second operand of operation */
555  )
556 {
557  /* the empty interval is contained everywhere */
558  if( operand1.inf > operand1.sup )
559  return TRUE;
560 
561  /* something not-empty is not contained in the empty interval */
562  if( operand2.inf > operand2.sup )
563  return FALSE;
564 
565  return (MAX(-infinity, operand1.inf) >= operand2.inf) &&
566  ( MIN( infinity, operand1.sup) <= operand2.sup);
567 }
568 
569 /** indicates whether operand1 and operand2 are disjoint */
571  SCIP_INTERVAL operand1, /**< first operand of operation */
572  SCIP_INTERVAL operand2 /**< second operand of operation */
573  )
574 {
575  return (operand1.sup < operand2.inf) || (operand2.sup < operand1.inf);
576 }
577 
578 /** intersection of two intervals */
580  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
581  SCIP_INTERVAL operand1, /**< first operand of operation */
582  SCIP_INTERVAL operand2 /**< second operand of operation */
583  )
584 {
585  assert(resultant != NULL);
586 
587  resultant->inf = MAX(operand1.inf, operand2.inf);
588  resultant->sup = MIN(operand1.sup, operand2.sup);
589 }
590 
591 /** interval enclosure of the union of two intervals */
593  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
594  SCIP_INTERVAL operand1, /**< first operand of operation */
595  SCIP_INTERVAL operand2 /**< second operand of operation */
596  )
597 {
598  assert(resultant != NULL);
599 
600  if( operand1.inf > operand1.sup )
601  {
602  /* operand1 is empty */
603  *resultant = operand2;
604  return;
605  }
606 
607  if( operand2.inf > operand2.sup )
608  {
609  /* operand2 is empty */
610  *resultant = operand1;
611  return;
612  }
613 
614  resultant->inf = MIN(operand1.inf, operand2.inf);
615  resultant->sup = MAX(operand1.sup, operand2.sup);
616 }
617 
618 /** adds operand1 and operand2 and stores infimum of result in infimum of resultant */
620  SCIP_Real infinity, /**< value for infinity */
621  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
622  SCIP_INTERVAL operand1, /**< first operand of operation */
623  SCIP_INTERVAL operand2 /**< second operand of operation */
624  )
625 {
627  assert(resultant != NULL);
628 
629  /* [a,...] + [-inf,...] = [-inf,...] for all a, in particular, [+inf,...] + [-inf,...] = [-inf,...] */
630  if( operand1.inf <= -infinity || operand2.inf <= -infinity )
631  {
632  resultant->inf = -infinity;
633  }
634  /* [a,...] + [+inf,...] = [+inf,...] for all a > -inf */
635  else if( operand1.inf >= infinity || operand2.inf >= infinity )
636  {
637  resultant->inf = infinity;
638  }
639  else
640  {
641  resultant->inf = operand1.inf + operand2.inf;
642  }
643 }
644 
645 /** adds operand1 and operand2 and stores supremum of result in supremum of resultant */
647  SCIP_Real infinity, /**< value for infinity */
648  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
649  SCIP_INTERVAL operand1, /**< first operand of operation */
650  SCIP_INTERVAL operand2 /**< second operand of operation */
651  )
652 {
654  assert(resultant != NULL);
655 
656  /* [...,b] + [...,+inf] = [...,+inf] for all b, in particular, [...,-inf] + [...,+inf] = [...,+inf] */
657  if( operand1.sup >= infinity || operand2.sup >= infinity )
658  {
659  resultant->sup = infinity;
660  }
661  /* [...,b] + [...,-inf] = [...,-inf] for all b < +inf */
662  else if( operand1.sup <= -infinity || operand2.sup <= -infinity )
663  {
664  resultant->sup = -infinity;
665  }
666  else
667  {
668  resultant->sup = operand1.sup + operand2.sup;
669  }
670 }
671 
672 /** adds operand1 and operand2 and stores result in resultant */
674  SCIP_Real infinity, /**< value for infinity */
675  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
676  SCIP_INTERVAL operand1, /**< first operand of operation */
677  SCIP_INTERVAL operand2 /**< second operand of operation */
678  )
679 {
680  SCIP_ROUNDMODE roundmode;
681 
682  assert(resultant != NULL);
683  assert(operand1.inf <= operand1.sup);
684  assert(operand2.inf <= operand2.sup);
685 
686  roundmode = SCIPintervalGetRoundingMode();
687 
688  /* compute infimum of result */
690  SCIPintervalAddInf(infinity, resultant, operand1, operand2);
691 
692  /* compute supremum of result */
694  SCIPintervalAddSup(infinity, resultant, operand1, operand2);
695 
696  SCIPintervalSetRoundingMode(roundmode);
697 }
698 
699 /** adds operand1 and scalar operand2 and stores result in resultant */
701  SCIP_Real infinity, /**< value for infinity */
702  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
703  SCIP_INTERVAL operand1, /**< first operand of operation */
704  SCIP_Real operand2 /**< second operand of operation */
705  )
706 {
707  SCIP_ROUNDMODE roundmode;
708 
709  assert(resultant != NULL);
710  assert(operand1.inf <= operand1.sup);
711 
712  roundmode = SCIPintervalGetRoundingMode();
713 
714  /* -inf + something >= -inf */
715  if( operand1.inf <= -infinity || operand2 <= -infinity )
716  {
717  resultant->inf = -infinity;
718  }
719  else if( operand1.inf >= infinity || operand2 >= infinity )
720  {
721  /* inf + finite = inf, inf + inf = inf */
722  resultant->inf = infinity;
723  }
724  else
725  {
727  resultant->inf = operand1.inf + operand2;
728  }
729 
730  /* inf + something <= inf */
731  if( operand1.sup >= infinity || operand2 >= infinity )
732  {
733  resultant->sup = infinity;
734  }
735  else if( operand1.sup <= -infinity || operand2 <= -infinity )
736  {
737  /* -inf + finite = -inf, -inf + (-inf) = -inf */
738  resultant->sup = -infinity;
739  }
740  else
741  {
743  resultant->sup = operand1.sup + operand2;
744  }
745 
746  SCIPintervalSetRoundingMode(roundmode);
747 }
748 
749 /** adds vector operand1 and vector operand2 and stores result in vector resultant */
751  SCIP_Real infinity, /**< value for infinity */
752  SCIP_INTERVAL* resultant, /**< array of resultant intervals of operation */
753  int length, /**< length of arrays */
754  SCIP_INTERVAL* operand1, /**< array of first operands of operation */
755  SCIP_INTERVAL* operand2 /**< array of second operands of operation */
756  )
757 {
758  SCIP_ROUNDMODE roundmode;
759  int i;
760 
761  roundmode = SCIPintervalGetRoundingMode();
762 
763  /* compute infimums of resultant array */
765  for( i = 0; i < length; ++i )
766  {
767  SCIPintervalAddInf(infinity, &resultant[i], operand1[i], operand2[i]);
768  }
769  /* compute supremums of result array */
771  for( i = 0; i < length; ++i )
772  {
773  SCIPintervalAddSup(infinity, &resultant[i], operand1[i], operand2[i]);
774  }
775 
776  SCIPintervalSetRoundingMode(roundmode);
777 }
778 
779 /** subtracts operand2 from operand1 and stores result in resultant */
781  SCIP_Real infinity, /**< value for infinity */
782  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
783  SCIP_INTERVAL operand1, /**< first operand of operation */
784  SCIP_INTERVAL operand2 /**< second operand of operation */
785  )
786 {
787  SCIP_ROUNDMODE roundmode;
788 
789  assert(resultant != NULL);
790  assert(operand1.inf <= operand1.sup);
791  assert(operand2.inf <= operand2.sup);
792 
793  roundmode = SCIPintervalGetRoundingMode();
794 
795  if( operand1.inf <= -infinity || operand2.sup >= infinity )
796  resultant->inf = -infinity;
797  /* [a,b] - [-inf,-inf] = [+inf,+inf] */
798  else if( operand1.inf >= infinity || operand2.sup <= -infinity )
799  {
800  resultant->inf = infinity;
801  resultant->sup = infinity;
802  return;
803  }
804  else
805  {
807  resultant->inf = operand1.inf - operand2.sup;
808  }
809 
810  if( operand1.sup >= infinity || operand2.inf <= -infinity )
811  resultant->sup = infinity;
812  /* [a,b] - [+inf,+inf] = [-inf,-inf] */
813  else if( operand1.sup <= -infinity || operand2.inf >= infinity )
814  {
815  assert(resultant->inf == -infinity); /* should be set above, since operand1.inf <= operand1.sup <= -infinity */ /*lint !e777*/
816  resultant->sup = -infinity;
817  }
818  else
819  {
821  resultant->sup = operand1.sup - operand2.inf;
822  }
823 
824  SCIPintervalSetRoundingMode(roundmode);
825 }
826 
827 /** subtracts scalar operand2 from operand1 and stores result in resultant */
829  SCIP_Real infinity, /**< value for infinity */
830  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
831  SCIP_INTERVAL operand1, /**< first operand of operation */
832  SCIP_Real operand2 /**< second operand of operation */
833  )
834 {
835  SCIPintervalAddScalar(infinity, resultant, operand1, -operand2);
836 }
837 
838 /** multiplies operand1 with operand2 and stores infimum of result in infimum of resultant */
840  SCIP_Real infinity, /**< value for infinity */
841  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
842  SCIP_INTERVAL operand1, /**< first operand of operation; can be +/-inf */
843  SCIP_INTERVAL operand2 /**< second operand of operation; can be +/-inf */
844  )
845 {
846  assert(resultant != NULL);
847  assert(operand1.inf <= operand1.sup);
848  assert(operand2.inf <= operand2.sup);
850 
851  if( operand1.inf >= infinity )
852  {
853  /* operand1 is infinity scalar */
854  assert(operand1.sup >= infinity);
855  SCIPintervalMulScalarInf(infinity, resultant, operand2, infinity);
856  }
857  else if( operand2.inf >= infinity )
858  {
859  /* operand2 is infinity scalar */
860  assert(operand2.sup >= infinity);
861  SCIPintervalMulScalarInf(infinity, resultant, operand1, infinity);
862  }
863  else if( operand1.sup <= -infinity )
864  {
865  /* operand1 is -infinity scalar */
866  assert(operand1.inf <= -infinity);
867  SCIPintervalMulScalarInf(infinity, resultant, operand2, -infinity);
868  }
869  else if( operand2.sup <= -infinity )
870  {
871  /* operand2 is -infinity scalar */
872  assert(operand2.inf <= -infinity);
873  SCIPintervalMulScalarInf(infinity, resultant, operand1, -infinity);
874  }
875  else if( ( operand1.inf <= -infinity && operand2.sup > 0.0 )
876  || ( operand1.sup > 0.0 && operand2.inf <= -infinity )
877  || ( operand1.inf < 0.0 && operand2.sup >= infinity )
878  || ( operand1.sup >= infinity && operand2.inf < 0.0 ) )
879  {
880  resultant->inf = -infinity;
881  }
882  else
883  {
884  SCIP_Real cand1;
885  SCIP_Real cand2;
886  SCIP_Real cand3;
887  SCIP_Real cand4;
888 
889  cand1 = operand1.inf * operand2.inf;
890  cand2 = operand1.inf * operand2.sup;
891  cand3 = operand1.sup * operand2.inf;
892  cand4 = operand1.sup * operand2.sup;
893  resultant->inf = MIN(MIN(cand1, cand2), MIN(cand3, cand4));
894  }
895 }
896 
897 /** multiplies operand1 with operand2 and stores supremum of result in supremum of resultant */
899  SCIP_Real infinity, /**< value for infinity */
900  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
901  SCIP_INTERVAL operand1, /**< first operand of operation; can be +/-inf */
902  SCIP_INTERVAL operand2 /**< second operand of operation; can be +/-inf */
903  )
904 {
905  assert(resultant != NULL);
906  assert(operand1.inf <= operand1.sup);
907  assert(operand2.inf <= operand2.sup);
909 
910  if( operand1.inf >= infinity )
911  {
912  /* operand1 is infinity scalar */
913  assert(operand1.sup >= infinity);
914  SCIPintervalMulScalarSup(infinity, resultant, operand2, infinity);
915  }
916  else if( operand2.inf >= infinity )
917  {
918  /* operand2 is infinity scalar */
919  assert(operand2.sup >= infinity);
920  SCIPintervalMulScalarSup(infinity, resultant, operand1, infinity);
921  }
922  else if( operand1.sup <= -infinity )
923  {
924  /* operand1 is -infinity scalar */
925  assert(operand1.inf <= -infinity);
926  SCIPintervalMulScalarSup(infinity, resultant, operand2, -infinity);
927  }
928  else if( operand2.sup <= -infinity )
929  {
930  /* operand2 is -infinity scalar */
931  assert(operand2.inf <= -infinity);
932  SCIPintervalMulScalarSup(infinity, resultant, operand1, -infinity);
933  }
934  else if( ( operand1.inf <= -infinity && operand2.inf < 0.0 )
935  || ( operand1.inf < 0.0 && operand2.inf <= -infinity )
936  || ( operand1.sup > 0.0 && operand2.sup >= infinity )
937  || ( operand1.sup >= infinity && operand2.sup > 0.0 ) )
938  {
939  resultant->sup = infinity;
940  }
941  else
942  {
943  SCIP_Real cand1;
944  SCIP_Real cand2;
945  SCIP_Real cand3;
946  SCIP_Real cand4;
947 
948  cand1 = operand1.inf * operand2.inf;
949  cand2 = operand1.inf * operand2.sup;
950  cand3 = operand1.sup * operand2.inf;
951  cand4 = operand1.sup * operand2.sup;
952  resultant->sup = MAX(MAX(cand1, cand2), MAX(cand3, cand4));
953  }
954 }
955 
956 /** multiplies operand1 with operand2 and stores result in resultant */
958  SCIP_Real infinity, /**< value for infinity */
959  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
960  SCIP_INTERVAL operand1, /**< first operand of operation; can be +/-inf */
961  SCIP_INTERVAL operand2 /**< second operand of operation; can be +/-inf */
962  )
963 {
964  SCIP_ROUNDMODE roundmode;
965 
966  assert(resultant != NULL);
967  assert(operand1.inf <= operand1.sup);
968  assert(operand2.inf <= operand2.sup);
969 
970  roundmode = SCIPintervalGetRoundingMode();
971 
972  /* compute infimum result */
974  SCIPintervalMulInf(infinity, resultant, operand1, operand2);
975 
976  /* compute supremum of result */
978  SCIPintervalMulSup(infinity, resultant, operand1, operand2);
979 
980  SCIPintervalSetRoundingMode(roundmode);
981 }
982 
983 /** multiplies operand1 with scalar operand2 and stores infimum of result in infimum of resultant */
985  SCIP_Real infinity, /**< value for infinity */
986  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
987  SCIP_INTERVAL operand1, /**< first operand of operation */
988  SCIP_Real operand2 /**< second operand of operation; can be +/- inf */
989  )
990 {
992  assert(resultant != NULL);
993  assert(operand1.inf <= operand1.sup);
994 
995  if( operand2 >= infinity )
996  {
997  /* result.inf defined by sign of operand1.inf */
998  if( operand1.inf > 0 )
999  resultant->inf = infinity;
1000  else if( operand1.inf < 0 )
1001  resultant->inf = -infinity;
1002  else
1003  resultant->inf = 0.0;
1004  }
1005  else if( operand2 <= -infinity )
1006  {
1007  /* result.inf defined by sign of operand1.sup */
1008  if( operand1.sup > 0 )
1009  resultant->inf = -infinity;
1010  else if( operand1.sup < 0 )
1011  resultant->inf = infinity;
1012  else
1013  resultant->inf = 0.0;
1014  }
1015  else if( operand2 == 0.0 )
1016  {
1017  resultant->inf = 0.0;
1018  }
1019  else if( operand2 > 0.0 )
1020  {
1021  if( operand1.inf <= -infinity )
1022  resultant->inf = -infinity;
1023  else if( operand1.inf >= infinity )
1024  resultant->inf = infinity;
1025  else
1026  resultant->inf = operand1.inf * operand2;
1027  }
1028  else
1029  {
1030  if( operand1.sup >= infinity )
1031  resultant->inf = -infinity;
1032  else if( operand1.sup <= -infinity )
1033  resultant->inf = infinity;
1034  else
1035  resultant->inf = operand1.sup * operand2;
1036  }
1037 }
1038 
1039 /** multiplies operand1 with scalar operand2 and stores supremum of result in supremum of resultant */
1041  SCIP_Real infinity, /**< value for infinity */
1042  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1043  SCIP_INTERVAL operand1, /**< first operand of operation */
1044  SCIP_Real operand2 /**< second operand of operation; can be +/- inf */
1045  )
1046 {
1048  assert(resultant != NULL);
1049  assert(operand1.inf <= operand1.sup);
1050 
1051  if( operand2 >= infinity )
1052  {
1053  /* result.sup defined by sign of operand1.sup */
1054  if( operand1.sup > 0 )
1055  resultant->sup = infinity;
1056  else if( operand1.sup < 0 )
1057  resultant->sup = -infinity;
1058  else
1059  resultant->sup = 0.0;
1060  }
1061  else if( operand2 <= -infinity )
1062  {
1063  /* result.sup defined by sign of operand1.inf */
1064  if( operand1.inf > 0 )
1065  resultant->sup = -infinity;
1066  else if( operand1.inf < 0 )
1067  resultant->sup = infinity;
1068  else
1069  resultant->sup = 0.0;
1070  }
1071  else if( operand2 == 0.0 )
1072  {
1073  resultant->sup = 0.0;
1074  }
1075  else if( operand2 > 0.0 )
1076  {
1077  if( operand1.sup >= infinity )
1078  resultant->sup = infinity;
1079  else if( operand1.sup <= -infinity )
1080  resultant->sup = -infinity;
1081  else
1082  resultant->sup = operand1.sup * operand2;
1083  }
1084  else
1085  {
1086  if( operand1.inf <= -infinity )
1087  resultant->sup = infinity;
1088  else if( operand1.inf >= infinity )
1089  resultant->sup = -infinity;
1090  else
1091  resultant->sup = operand1.inf * operand2;
1092  }
1093 }
1094 
1095 /** multiplies operand1 with scalar operand2 and stores result in resultant */
1097  SCIP_Real infinity, /**< value for infinity */
1098  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1099  SCIP_INTERVAL operand1, /**< first operand of operation */
1100  SCIP_Real operand2 /**< second operand of operation */
1101  )
1102 {
1103  SCIP_ROUNDMODE roundmode;
1104 
1105  assert(resultant != NULL);
1106  assert(operand1.inf <= operand1.sup);
1107 
1108  roundmode = SCIPintervalGetRoundingMode();
1109 
1110  /* compute infimum result */
1112  SCIPintervalMulScalarInf(infinity, resultant, operand1, operand2);
1113 
1114  /* compute supremum of result */
1116  SCIPintervalMulScalarSup(infinity, resultant, operand1, operand2);
1117 
1118  SCIPintervalSetRoundingMode(roundmode);
1119 }
1120 
1121 /** divides operand1 by operand2 and stores result in resultant */
1123  SCIP_Real infinity, /**< value for infinity */
1124  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1125  SCIP_INTERVAL operand1, /**< first operand of operation */
1126  SCIP_INTERVAL operand2 /**< second operand of operation */
1127  )
1128 {
1129  SCIP_ROUNDMODE roundmode;
1130  SCIP_INTERVAL intmed;
1131 
1132  assert(resultant != NULL);
1133  assert(operand1.inf <= operand1.sup);
1134  assert(operand2.inf <= operand2.sup);
1135 
1136  if( operand2.inf <= 0.0 && operand2.sup >= 0.0 )
1137  { /* division by [0,0] or interval containing 0 gives [-inf, +inf] */
1138  resultant->inf = -infinity;
1139  resultant->sup = infinity;
1140  return;
1141  }
1142 
1143  if( operand1.inf == 0.0 && operand1.sup == 0.0 )
1144  { /* division of [0,0] by something nonzero */
1145  SCIPintervalSet(resultant, 0.0);
1146  return;
1147  }
1148 
1149  roundmode = SCIPintervalGetRoundingMode();
1150 
1151  /* division by nonzero: resultant = x * (1/y) */
1152  if( operand2.sup >= infinity || operand2.sup <= -infinity )
1153  {
1154  intmed.inf = 0.0;
1155  }
1156  else
1157  {
1159  intmed.inf = 1.0 / operand2.sup;
1160  }
1161  if( operand2.inf <= -infinity || operand2.inf >= infinity )
1162  {
1163  intmed.sup = 0.0;
1164  }
1165  else
1166  {
1168  intmed.sup = 1.0 / operand2.inf;
1169  }
1170  SCIPintervalMul(infinity, resultant, operand1, intmed);
1171 
1172  SCIPintervalSetRoundingMode(roundmode);
1173 }
1174 
1175 /** divides operand1 by scalar operand2 and stores result in resultant */
1177  SCIP_Real infinity, /**< value for infinity */
1178  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1179  SCIP_INTERVAL operand1, /**< first operand of operation */
1180  SCIP_Real operand2 /**< second operand of operation */
1181  )
1182 {
1183  SCIP_ROUNDMODE roundmode;
1184 
1185  assert(resultant != NULL);
1186  assert(operand1.inf <= operand1.sup);
1187 
1188  roundmode = SCIPintervalGetRoundingMode();
1189 
1190  if( operand2 >= infinity || operand2 <= -infinity )
1191  {
1192  /* division by +/-infinity is 0.0 */
1193  resultant->inf = 0.0;
1194  resultant->sup = 0.0;
1195  }
1196  else if( operand2 > 0.0 )
1197  {
1198  if( operand1.inf <= -infinity )
1199  resultant->inf = -infinity;
1200  else if( operand1.inf >= infinity )
1201  {
1202  /* infinity / + = infinity */
1203  resultant->inf = infinity;
1204  }
1205  else
1206  {
1208  resultant->inf = operand1.inf / operand2;
1209  }
1210 
1211  if( operand1.sup >= infinity )
1212  resultant->sup = infinity;
1213  else if( operand1.sup <= -infinity )
1214  {
1215  /* -infinity / + = -infinity */
1216  resultant->sup = -infinity;
1217  }
1218  else
1219  {
1221  resultant->sup = operand1.sup / operand2;
1222  }
1223  }
1224  else if( operand2 < 0.0 )
1225  {
1226  if( operand1.sup >= infinity )
1227  resultant->inf = -infinity;
1228  else if( operand1.sup <= -infinity )
1229  {
1230  /* -infinity / - = infinity */
1231  resultant->inf = infinity;
1232  }
1233  else
1234  {
1236  resultant->inf = operand1.sup / operand2;
1237  }
1238 
1239  if( operand1.inf <= -infinity )
1240  resultant->sup = infinity;
1241  else if( operand1.inf >= infinity )
1242  {
1243  /* infinity / - = -infinity */
1244  resultant->sup = -infinity;
1245  }
1246  else
1247  {
1249  resultant->sup = operand1.inf / operand2;
1250  }
1251  }
1252  else
1253  { /* division by 0.0 */
1254  if( operand1.inf >= 0 )
1255  {
1256  /* [+,+] / [0,0] = [+inf, +inf] */
1257  resultant->inf = infinity;
1258  resultant->sup = infinity;
1259  }
1260  else if( operand1.sup <= 0 )
1261  {
1262  /* [-,-] / [0,0] = [-inf, -inf] */
1263  resultant->inf = -infinity;
1264  resultant->sup = -infinity;
1265  }
1266  else
1267  {
1268  /* [-,+] / [0,0] = [-inf, +inf] */
1269  resultant->inf = -infinity;
1270  resultant->sup = infinity;
1271  }
1272  return;
1273  }
1274 
1275  SCIPintervalSetRoundingMode(roundmode);
1276 }
1277 
1278 /** computes the scalar product of two vectors of intervals and stores result in resultant */
1280  SCIP_Real infinity, /**< value for infinity */
1281  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1282  int length, /**< length of vectors */
1283  SCIP_INTERVAL* operand1, /**< first vector as array of intervals; can have +/-inf entries */
1284  SCIP_INTERVAL* operand2 /**< second vector as array of intervals; can have +/-inf entries */
1285  )
1286 {
1287  SCIP_ROUNDMODE roundmode;
1288  SCIP_INTERVAL prod;
1289  int i;
1290 
1291  roundmode = SCIPintervalGetRoundingMode();
1292 
1293  resultant->inf = 0.0;
1294  resultant->sup = 0.0;
1295 
1296  /* compute infimum of resultant */
1298  for( i = 0; i < length && resultant->inf > -infinity; ++i )
1299  {
1300  SCIPintervalSetEntire(infinity, &prod);
1301  SCIPintervalMulInf(infinity, &prod, operand1[i], operand2[i]);
1302  SCIPintervalAddInf(infinity, resultant, *resultant, prod);
1303  }
1304  assert(resultant->sup == 0.0);
1305 
1306  /* compute supremum of resultant */
1308  for( i = 0; i < length && resultant->sup < infinity ; ++i )
1309  {
1310  SCIPintervalSetEntire(infinity, &prod);
1311  SCIPintervalMulSup(infinity, &prod, operand1[i], operand2[i]);
1312  SCIPintervalAddSup(infinity, resultant, *resultant, prod);
1313  }
1314 
1315  SCIPintervalSetRoundingMode(roundmode);
1316 }
1317 
1318 /** computes scalar product of a vector of intervals and a vector of scalars and stores infimum of result in infimum of
1319  * resultant
1320  */
1322  SCIP_Real infinity, /**< value for infinity */
1323  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1324  int length, /**< length of vectors */
1325  SCIP_INTERVAL* operand1, /**< first vector as array of intervals */
1326  SCIP_Real* operand2 /**< second vector as array of scalars; can have +/-inf entries */
1327  )
1328 {
1329  SCIP_INTERVAL prod;
1330  int i;
1331 
1333 
1334  resultant->inf = 0.0;
1335 
1336  /* compute infimum of resultant */
1337  SCIPintervalSetEntire(infinity, &prod);
1338  for( i = 0; i < length && resultant->inf > -infinity; ++i )
1339  {
1340  SCIPintervalMulScalarInf(infinity, &prod, operand1[i], operand2[i]);
1341  assert(prod.sup >= infinity);
1342  SCIPintervalAddInf(infinity, resultant, *resultant, prod);
1343  }
1344 }
1345 
1346 /** computes the scalar product of a vector of intervals and a vector of scalars and stores supremum of result in
1347  * supremum of resultant
1348  */
1350  SCIP_Real infinity, /**< value for infinity */
1351  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1352  int length, /**< length of vectors */
1353  SCIP_INTERVAL* operand1, /**< first vector as array of intervals */
1354  SCIP_Real* operand2 /**< second vector as array of scalars; can have +/-inf entries */
1355  )
1356 {
1357  SCIP_INTERVAL prod;
1358  int i;
1359 
1361 
1362  resultant->sup = 0.0;
1363 
1364  /* compute supremum of resultant */
1365  SCIPintervalSetEntire(infinity, &prod);
1366  for( i = 0; i < length && resultant->sup < infinity; ++i )
1367  {
1368  SCIPintervalMulScalarSup(infinity, &prod, operand1[i], operand2[i]);
1369  assert(prod.inf <= -infinity);
1370  SCIPintervalAddSup(infinity, resultant, *resultant, prod);
1371  }
1372 }
1373 
1374 /** computes the scalar product of a vector of intervals and a vector of scalars and stores result in resultant */
1376  SCIP_Real infinity, /**< value for infinity */
1377  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1378  int length, /**< length of vectors */
1379  SCIP_INTERVAL* operand1, /**< first vector as array of intervals */
1380  SCIP_Real* operand2 /**< second vector as array of scalars; can have +/-inf entries */
1381  )
1382 {
1383  SCIP_ROUNDMODE roundmode;
1384 
1385  roundmode = SCIPintervalGetRoundingMode();
1386 
1387  resultant->inf = 0.0;
1388  resultant->sup = 0.0;
1389 
1390  /* compute infimum of resultant */
1392  SCIPintervalScalprodScalarsInf(infinity, resultant, length, operand1, operand2);
1393  assert(resultant->sup == 0.0);
1394 
1395  /* compute supremum of resultant */
1397  SCIPintervalScalprodScalarsSup(infinity, resultant, length, operand1, operand2);
1398 
1399  SCIPintervalSetRoundingMode(roundmode);
1400 }
1401 
1402 /** squares operand and stores result in resultant */
1404  SCIP_Real infinity, /**< value for infinity */
1405  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1406  SCIP_INTERVAL operand /**< operand of operation */
1407  )
1408 {
1409  SCIP_ROUNDMODE roundmode;
1410 
1411  assert(resultant != NULL);
1412  assert(operand.inf <= operand.sup);
1413 
1414  roundmode = SCIPintervalGetRoundingMode();
1415 
1416  if( operand.sup <= 0.0 )
1417  { /* operand is left of 0.0 */
1418  if( operand.sup <= -infinity )
1419  resultant->inf = infinity;
1420  else
1421  {
1423  resultant->inf = operand.sup * operand.sup;
1424  }
1425 
1426  if( operand.inf <= -infinity )
1427  resultant->sup = infinity;
1428  else
1429  {
1431  resultant->sup = operand.inf * operand.inf;
1432  }
1433  }
1434  else if( operand.inf >= 0.0 )
1435  { /* operand is right of 0.0 */
1436  if( operand.inf >= infinity )
1437  resultant->inf = infinity;
1438  else
1439  {
1441  resultant->inf = operand.inf * operand.inf;
1442  }
1443 
1444  if( operand.sup >= infinity )
1445  resultant->sup = infinity;
1446  else
1447  {
1449  resultant->sup = operand.sup * operand.sup;
1450  }
1451  }
1452  else
1453  { /* [-,+]^2 */
1454  resultant->inf = 0.0;
1455  if( operand.inf <= -infinity || operand.sup >= infinity )
1456  resultant->sup = infinity;
1457  else
1458  {
1459  SCIP_Real x;
1460  SCIP_Real y;
1461 
1463  x = operand.inf * operand.inf;
1464  y = operand.sup * operand.sup;
1465  resultant->sup = MAX(x, y);
1466  }
1467  }
1468 
1469  SCIPintervalSetRoundingMode(roundmode);
1470 }
1471 
1472 /** stores (positive part of) square root of operand in resultant
1473  * @attention we assume a correctly rounded sqrt(double) function when rounding is to nearest
1474  */
1476  SCIP_Real infinity, /**< value for infinity */
1477  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1478  SCIP_INTERVAL operand /**< operand of operation */
1479  )
1480 {
1481  assert(resultant != NULL);
1482  assert(operand.inf <= operand.sup);
1483 
1484  if( operand.sup < 0.0 )
1485  {
1486  SCIPintervalSetEmpty(resultant);
1487  return;
1488  }
1489 
1490  if( operand.inf == operand.sup ) /*lint !e777 */
1491  {
1492  if( operand.inf >= infinity )
1493  {
1494  resultant->inf = infinity;
1495  resultant->sup = infinity;
1496  }
1497  else
1498  {
1499  SCIP_Real tmp;
1500 
1501  assert(SCIPintervalGetRoundingMode() == SCIP_ROUND_NEAREST); /* usually, no-one should have changed rounding mode */
1502  tmp = sqrt(operand.inf);
1503  resultant->inf = nextafter(tmp, SCIP_REAL_MIN);
1504  resultant->sup = nextafter(tmp, SCIP_REAL_MAX);
1505  }
1506 
1507  return;
1508  }
1509 
1510  if( operand.inf <= 0.0 )
1511  resultant->inf = 0.0;
1512  else if( operand.inf >= infinity )
1513  {
1514  resultant->inf = infinity;
1515  resultant->sup = infinity;
1516  }
1517  else
1518  {
1519  assert(SCIPintervalGetRoundingMode() == SCIP_ROUND_NEAREST); /* usually, no-one should have changed rounding mode */
1520  resultant->inf = nextafter(sqrt(operand.inf), SCIP_REAL_MIN);
1521  }
1522 
1523  if( operand.sup >= infinity )
1524  resultant->sup = infinity;
1525  else
1526  {
1527  assert(SCIPintervalGetRoundingMode() == SCIP_ROUND_NEAREST); /* usually, no-one should have changed rounding mode */
1528  resultant->sup = nextafter(sqrt(operand.sup), SCIP_REAL_MAX);
1529  }
1530 }
1531 
1532 /** stores operand1 to the power of operand2 in resultant
1533  *
1534  * uses SCIPintervalPowerScalar if operand2 is a scalar, otherwise computes exp(op2*log(op1))
1535  */
1537  SCIP_Real infinity, /**< value for infinity */
1538  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1539  SCIP_INTERVAL operand1, /**< first operand of operation */
1540  SCIP_INTERVAL operand2 /**< second operand of operation */
1541  )
1542 { /*lint --e{777}*/
1543  assert(resultant != NULL);
1544  assert(operand1.inf <= operand1.sup);
1545  assert(operand2.inf <= operand2.sup);
1546 
1547  if( operand2.inf == operand2.sup )
1548  { /* operand is number */
1549  SCIPintervalPowerScalar(infinity, resultant, operand1, operand2.inf);
1550  return;
1551  }
1552 
1553  /* resultant := log(op1) */
1554  SCIPintervalLog(infinity, resultant, operand1);
1555  if( SCIPintervalIsEmpty(*resultant) )
1556  return;
1557 
1558  /* resultant := op2 * resultant */
1559  SCIPintervalMul(infinity, resultant, operand2, *resultant);
1560 
1561  /* resultant := exp(resultant) */
1562  SCIPintervalExp(infinity, resultant, *resultant);
1563 }
1564 
1565 /** computes lower bound on power of a scalar operand1 to an integer operand2
1566  * both operands need to be finite numbers
1567  * need to have operand1 >= 0 and need to have operand2 >= 0 if operand1 == 0
1568  */
1570  SCIP_Real operand1, /**< first operand of operation */
1571  int operand2 /**< second operand of operation */
1572  )
1573 {
1574  SCIP_ROUNDMODE roundmode;
1575  SCIP_Real result;
1576 
1577  assert(operand1 >= 0.0);
1578 
1579  if( operand1 == 0.0 )
1580  {
1581  assert(operand2 >= 0);
1582  if( operand2 == 0 )
1583  return 1.0; /* 0^0 = 1 */
1584  else
1585  return 0.0; /* 0^positive = 0 */
1586  }
1587 
1588  /* 1^n = 1, x^0 = 1 */
1589  if( operand1 == 1.0 || operand2 == 0 )
1590  return 1.0;
1591 
1592  if( operand2 < 0 )
1593  {
1594  /* x^n = 1 / x^(-n) */
1595  result = SCIPintervalPowerScalarIntegerSup(operand1, -operand2);
1596  assert(result != 0.0);
1597 
1598  roundmode = SCIPintervalGetRoundingMode();
1600  result = 1.0 / result;
1601  SCIPintervalSetRoundingMode(roundmode);
1602  }
1603  else
1604  {
1605  unsigned int n;
1606  SCIP_Real z;
1607 
1608  roundmode = SCIPintervalGetRoundingMode();
1609 
1610  result = 1.0;
1611  n = (unsigned int)operand2;
1612  z = operand1;
1613 
1615 
1616  /* use a binary exponentiation algorithm:
1617  * consider the binary representation of n: n = sum_i 2^i d_i with d_i \in {0,1}
1618  * then x^n = prod_{i:d_i=1} x^(2^i)
1619  * in the following, we loop over i=1,..., thereby storing x^(2^i) in z
1620  * whenever d_i is 1, we multiply result with x^(2^i) (the current z)
1621  * at the last (highest) i with d_i = 1 we stop, thus having x^n stored in result
1622  *
1623  * the binary representation of n and bit shifting is used for the loop
1624  */
1625  assert(n >= 1);
1626  do
1627  {
1628  if( n & 1 ) /* n is odd (d_i=1), so multiply result with current z (=x^{2^i}) */
1629  {
1630  result = result * z;
1631  n >>= 1;
1632  if( n == 0 )
1633  break;
1634  }
1635  else
1636  n >>= 1;
1637  z = z * z;
1638  }
1639  while( TRUE ); /*lint !e506 */
1640 
1641  SCIPintervalSetRoundingMode(roundmode);
1642  }
1643 
1644  return result;
1645 }
1646 
1647 /** computes upper bound on power of a scalar operand1 to an integer operand2
1648  * both operands need to be finite numbers
1649  * need to have operand1 >= 0 and need to have operand2 >= 0 if operand1 == 0
1650  */
1652  SCIP_Real operand1, /**< first operand of operation */
1653  int operand2 /**< second operand of operation */
1654  )
1655 {
1656  SCIP_ROUNDMODE roundmode;
1657  SCIP_Real result;
1658 
1659  assert(operand1 >= 0.0);
1660 
1661  if( operand1 == 0.0 )
1662  {
1663  assert(operand2 >= 0);
1664  if( operand2 == 0 )
1665  return 1.0; /* 0^0 = 1 */
1666  else
1667  return 0.0; /* 0^positive = 0 */
1668  }
1669 
1670  /* 1^n = 1, x^0 = 1 */
1671  if( operand1 == 1.0 || operand2 == 0 )
1672  return 1.0;
1673 
1674  if( operand2 < 0 )
1675  {
1676  /* x^n = 1 / x^(-n) */
1677  result = SCIPintervalPowerScalarIntegerInf(operand1, -operand2);
1678  assert(result != 0.0);
1679 
1680  roundmode = SCIPintervalGetRoundingMode();
1682  result = 1.0 / result;
1683  SCIPintervalSetRoundingMode(roundmode);
1684  }
1685  else
1686  {
1687  unsigned int n;
1688  SCIP_Real z;
1689 
1690  roundmode = SCIPintervalGetRoundingMode();
1691 
1692  result = 1.0;
1693  n = (unsigned int)operand2;
1694  z = operand1;
1695 
1697 
1698  /* use a binary exponentiation algorithm... see comments in SCIPintervalPowerScalarIntegerInf */
1699  assert(n >= 1);
1700  do
1701  {
1702  if( n&1 )
1703  {
1704  result = result * z;
1705  n >>= 1;
1706  if( n == 0 )
1707  break;
1708  }
1709  else
1710  n >>= 1;
1711  z = z * z;
1712  }
1713  while( TRUE ); /*lint !e506 */
1714 
1715  SCIPintervalSetRoundingMode(roundmode);
1716  }
1717 
1718  return result;
1719 }
1720 
1721 /** computes bounds on power of a scalar operand1 to an integer operand2
1722  * both operands need to be finite numbers
1723  * need to have operand1 >= 0 and need to have operand2 >= 0 if operand1 == 0
1724  */
1726  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1727  SCIP_Real operand1, /**< first operand of operation */
1728  int operand2 /**< second operand of operation */
1729  )
1730 {
1731  SCIP_ROUNDMODE roundmode;
1732 
1733  assert(operand1 >= 0.0);
1734 
1735  if( operand1 == 0.0 )
1736  {
1737  assert(operand2 >= 0);
1738  if( operand2 == 0 )
1739  {
1740  SCIPintervalSet(resultant, 1.0); /* 0^0 = 1 */
1741  return;
1742  }
1743  else
1744  {
1745  SCIPintervalSet(resultant, 0.0); /* 0^positive = 0 */
1746  return;
1747  }
1748  }
1749 
1750  /* 1^n = 1, x^0 = 1 */
1751  if( operand1 == 1.0 || operand2 == 0 )
1752  {
1753  SCIPintervalSet(resultant, 1.0);
1754  return;
1755  }
1756 
1757  if( operand2 < 0 )
1758  {
1759  /* x^n = 1 / x^(-n) */
1760  SCIPintervalPowerScalarInteger(resultant, operand1, -operand2);
1761  assert(resultant->inf > 0.0 || resultant->sup < 0.0);
1762  SCIPintervalReciprocal(SCIP_REAL_MAX, resultant, *resultant); /* value for infinity does not matter, since there should be no 0.0 in the interval, so just use something large enough */
1763  }
1764  else
1765  {
1766  unsigned int n;
1767  SCIP_Real z_inf;
1768  SCIP_Real z_sup;
1769  SCIP_Real result_sup;
1770  SCIP_Real result_inf;
1771 
1772  roundmode = SCIPintervalGetRoundingMode();
1773 
1774  result_inf = 1.0;
1775  result_sup = 1.0;
1776  z_inf = operand1;
1777  z_sup = operand1;
1778  n = (unsigned int)operand2;
1779 
1781 
1782  /* use a binary exponentiation algorithm... see comments in SCIPintervalPowerScalarIntegerInf
1783  * we compute lower and upper bounds within the same loop
1784  * to get correct lower bounds while rounding mode is upwards, we negate arguments */
1785  assert(n >= 1);
1786  do
1787  {
1788  if( n & 1 )
1789  {
1790  result_inf = negate(negate(result_inf) * z_inf);
1791  result_sup = result_sup * z_sup;
1792  n >>= 1;
1793  if( n == 0 )
1794  break;
1795  }
1796  else
1797  n >>= 1;
1798  z_inf = negate(negate(z_inf) * z_inf);
1799  z_sup = z_sup * z_sup;
1800  }
1801  while( TRUE ); /*lint !e506 */
1802 
1803  SCIPintervalSetRoundingMode(roundmode);
1804 
1805  resultant->inf = result_inf;
1806  resultant->sup = result_sup;
1807  assert(resultant->inf <= resultant->sup);
1808  }
1809 }
1810 
1811 /** stores bounds on the power of a scalar operand1 to a scalar operand2 in resultant
1812  * both operands need to be finite numbers
1813  * need to have operand1 >= 0 or operand2 integer and need to have operand2 >= 0 if operand1 == 0
1814  * @attention we assume a correctly rounded pow(double) function when rounding is to nearest
1815  */
1817  SCIP_INTERVAL* resultant, /**< resultant of operation */
1818  SCIP_Real operand1, /**< first operand of operation */
1819  SCIP_Real operand2 /**< second operand of operation */
1820  )
1821 {
1822  SCIP_Real result;
1823 
1824  assert(resultant != NULL);
1825 
1826  if( operand1 == 0.0 )
1827  {
1828  assert(operand2 >= 0);
1829  if( operand2 == 0 )
1830  {
1831  SCIPintervalSet(resultant, 1.0); /* 0^0 = 1 */
1832  return;
1833  }
1834  else
1835  {
1836  SCIPintervalSet(resultant, 0.0); /* 0^positive = 0 */
1837  return;
1838  }
1839  }
1840 
1841  /* 1^n = 1, x^0 = 1 */
1842  if( operand1 == 1.0 || operand2 == 0 )
1843  {
1844  SCIPintervalSet(resultant, 1.0);
1845  return;
1846  }
1847 
1848  assert(SCIPintervalGetRoundingMode() == SCIP_ROUND_NEAREST); /* usually, no-one should have changed rounding mode */
1849  result = pow(operand1, operand2);
1850 
1851  /* to get safe bounds, get the floating point numbers just below and above result */
1852  resultant->inf = nextafter(result, SCIP_REAL_MIN);
1853  resultant->sup = nextafter(result, SCIP_REAL_MAX);
1854 }
1855 
1856 /** stores operand1 to the power of the scalar operand2 in resultant
1857  * @attention we assume a correctly rounded pow(double) function when rounding is to nearest
1858  */
1860  SCIP_Real infinity, /**< value for infinity */
1861  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
1862  SCIP_INTERVAL operand1, /**< first operand of operation */
1863  SCIP_Real operand2 /**< second operand of operation */
1864  )
1865 { /*lint --e{777}*/
1866  SCIP_Bool op2isint;
1867 
1868  assert(resultant != NULL);
1869  assert(operand1.inf <= operand1.sup);
1870 
1871  if( operand2 == infinity )
1872  {
1873  /* 0^infinity = 0
1874  * +^infinity = infinity
1875  * -^infinity = -infinity
1876  */
1877  if( operand1.inf < 0.0 )
1878  resultant->inf = -infinity;
1879  else
1880  resultant->inf = 0.0;
1881  if( operand1.sup > 0.0 )
1882  resultant->sup = infinity;
1883  else
1884  resultant->sup = 0.0;
1885  return;
1886  }
1887 
1888  if( operand2 == 0.0 )
1889  { /* special case, since x^0 = 1 for x != 0, but 0^0 = 0 */
1890  if( operand1.inf == 0.0 && operand1.sup == 0.0 )
1891  {
1892  resultant->inf = 0.0;
1893  resultant->sup = 0.0;
1894  }
1895  else if( operand1.inf <= 0.0 || operand1.sup >= 0.0 )
1896  { /* 0.0 in x gives [0,1] */
1897  resultant->inf = 0.0;
1898  resultant->sup = 1.0;
1899  }
1900  else
1901  { /* 0.0 outside x gives [1,1] */
1902  resultant->inf = 1.0;
1903  resultant->sup = 1.0;
1904  }
1905  return;
1906  }
1907 
1908  if( operand2 == 1.0 )
1909  {
1910  /* x^1 = x */
1911  *resultant = operand1;
1912  return;
1913  }
1914 
1915  op2isint = (ceil(operand2) == operand2);
1916 
1917  if( !op2isint && operand1.inf < 0.0 )
1918  { /* x^n with x negative not defined for n not integer*/
1919  operand1.inf = 0.0;
1920  if( operand1.sup < operand1.inf )
1921  {
1922  SCIPintervalSetEmpty(resultant);
1923  return;
1924  }
1925  }
1926 
1927  if( operand1.inf >= 0.0 )
1928  { /* easy case: x^n with x >= 0 */
1929  if( operand2 >= 0.0 )
1930  {
1931  /* inf^+ = inf */
1932  if( operand1.inf >= infinity )
1933  resultant->inf = infinity;
1934  else if( operand1.inf > 0.0 )
1935  {
1936  assert(SCIPintervalGetRoundingMode() == SCIP_ROUND_NEAREST); /* usually, no-one should have changed rounding mode */
1937  resultant->inf = nextafter(pow(operand1.inf, operand2), SCIP_REAL_MIN);
1938  }
1939  else
1940  resultant->inf = 0.0;
1941 
1942  if( operand1.sup >= infinity )
1943  resultant->sup = infinity;
1944  else if( operand1.sup > 0.0 )
1945  {
1946  assert(SCIPintervalGetRoundingMode() == SCIP_ROUND_NEAREST); /* usually, no-one should have changed rounding mode */
1947  resultant->sup = nextafter(pow(operand1.sup, operand2), SCIP_REAL_MAX);
1948  }
1949  else
1950  resultant->sup = 0.0;
1951  }
1952  else
1953  {
1954  if( operand1.sup >= infinity )
1955  resultant->inf = 0.0;
1956  else if( operand1.sup == 0.0 )
1957  {
1958  /* x^(negative even) = infinity for x->0 (from both sides),
1959  * but x^(negative odd) = -infinity for x->0 from left side */
1960  if( ceil(operand2/2) == operand2/2 )
1961  resultant->inf = infinity;
1962  else
1963  resultant->inf = -infinity;
1964  }
1965  else
1966  {
1967  assert(SCIPintervalGetRoundingMode() == SCIP_ROUND_NEAREST); /* usually, no-one should have changed rounding mode */
1968  resultant->inf = nextafter(pow(operand1.sup, operand2), SCIP_REAL_MIN);
1969  }
1970 
1971  /* 0^(negative) = infinity */
1972  if( operand1.inf == 0.0 )
1973  resultant->sup = infinity;
1974  else
1975  {
1976  assert(SCIPintervalGetRoundingMode() == SCIP_ROUND_NEAREST); /* usually, no-one should have changed rounding mode */
1977  resultant->sup = nextafter(pow(operand1.inf, operand2), SCIP_REAL_MAX);
1978  }
1979  }
1980  }
1981  else if( operand1.sup <= 0.0 )
1982  { /* more difficult case: x^n with x < 0; we now know, that n is integer */
1983  assert(op2isint);
1984  if( operand2 >= 0.0 && ceil(operand2/2) == operand2/2 )
1985  {
1986  /* x^n with n>=2 and even -> x^n is monotonically decreasing for x < 0 */
1987  if( operand1.sup == -infinity )
1988  /* (-inf)^n = inf */
1989  resultant->inf = infinity;
1990  else
1991  resultant->inf = SCIPintervalPowerScalarIntegerInf(-operand1.sup, (int)operand2);
1992 
1993  if( operand1.inf <= -infinity )
1994  resultant->sup = infinity;
1995  else
1996  resultant->sup = SCIPintervalPowerScalarIntegerSup(-operand1.inf, (int)operand2);
1997  }
1998  else if( operand2 <= 0.0 && ceil(operand2/2) != operand2/2 )
1999  {
2000  /* x^n with n<=-1 and odd -> x^n = 1/x^(-n) is monotonically decreasing for x<0 */
2001  if( operand1.sup == -infinity )
2002  /* (-inf)^n = 1/(-inf)^(-n) = 1/(-inf) = 0 */
2003  resultant->inf = 0.0;
2004  else if( operand1.sup == 0.0 )
2005  /* x^n -> -infinity for x->0 from left */
2006  resultant->inf = -infinity;
2007  else
2008  resultant->inf = -SCIPintervalPowerScalarIntegerSup(-operand1.sup, (int)operand2);
2009 
2010  if( operand1.inf <= -infinity )
2011  /* (-inf)^n = 1/(-inf)^(-n) = 1/(-inf) = 0 */
2012  resultant->sup = 0.0;
2013  else if( operand1.inf == 0.0 )
2014  /* x^n -> infinity for x->0 from right */
2015  resultant->sup = infinity;
2016  else
2017  resultant->sup = -SCIPintervalPowerScalarIntegerInf(-operand1.inf, (int)operand2);
2018  }
2019  else if( operand2 >= 0.0 )
2020  {
2021  /* x^n with n>0 and odd -> x^n is monotonically increasing for x<0 */
2022  if( operand1.inf <= -infinity )
2023  resultant->inf = -infinity;
2024  else
2025  resultant->inf = -SCIPintervalPowerScalarIntegerSup(-operand1.inf, (int)operand2);
2026 
2027  if( operand1.sup <= -infinity )
2028  resultant->sup = -infinity;
2029  else
2030  resultant->sup = -SCIPintervalPowerScalarIntegerInf(-operand1.sup, (int)operand2);
2031  }
2032  else
2033  {
2034  /* x^n with n<0 and even -> x^n is monotonically increasing for x<0 */
2035  if( operand1.inf <= -infinity )
2036  resultant->inf = 0.0;
2037  else if( operand1.inf == 0.0 )
2038  /* x^n -> infinity for x->0 from both sides */
2039  resultant->inf = infinity;
2040  else
2041  resultant->inf = SCIPintervalPowerScalarIntegerSup(-operand1.inf, (int)operand2);
2042 
2043  if( operand1.sup <= -infinity )
2044  resultant->sup = 0.0;
2045  else if( operand1.sup == 0.0 )
2046  /* x^n -> infinity for x->0 from both sides */
2047  resultant->sup = infinity;
2048  else
2049  resultant->sup = SCIPintervalPowerScalarIntegerSup(-operand1.sup, (int)operand2);
2050  }
2051  assert(resultant->inf <= resultant->sup || resultant->inf >= infinity || resultant->sup <= -infinity);
2052  }
2053  else
2054  { /* similar difficult case: x^n with x in [<0, >0], but n is integer */
2055  assert(op2isint); /* otherwise we had set operand1.inf == 0.0, which was handled in first case */
2056  if( operand2 >= 0.0 && operand2/2 == ceil(operand2/2) )
2057  {
2058  /* n even positive integer */
2059  resultant->inf = 0.0;
2060  if( operand1.inf == -infinity || operand1.sup == infinity )
2061  resultant->sup = infinity;
2062  else
2063  resultant->sup = SCIPintervalPowerScalarIntegerSup(MAX(-operand1.inf, operand1.sup), (int)operand2);
2064  }
2065  else if( operand2 <= 0.0 && ceil(operand2/2) != operand2/2 )
2066  {
2067  /* n even negative integer */
2068  resultant->sup = infinity; /* since 0^n = infinity */
2069  if( operand1.inf == -infinity || operand1.sup == infinity )
2070  resultant->inf = 0.0;
2071  else
2072  resultant->inf = SCIPintervalPowerScalarIntegerInf(MAX(-operand1.inf, operand1.sup), (int)operand2);
2073  }
2074  else if( operand2 >= 0.0 )
2075  {
2076  /* n odd positive integer, so monotonically increasing function */
2077  if( operand1.inf == -infinity )
2078  resultant->inf = -infinity;
2079  else
2080  resultant->inf = -SCIPintervalPowerScalarIntegerSup(-operand1.inf, (int)operand2);
2081  if( operand1.sup == infinity )
2082  resultant->sup = infinity;
2083  else
2084  resultant->sup = SCIPintervalPowerScalarIntegerSup(operand1.sup, (int)operand2);
2085  }
2086  else
2087  {
2088  /* n odd negative integer:
2089  * x^n -> -infinity for x->0 from left
2090  * x^n -> infinity for x->0 from right */
2091  resultant->inf = -infinity;
2092  resultant->sup = infinity;
2093  }
2094  }
2095 
2096  /* if value for infinity is too small, relax intervals so they do not appear empty */
2097  if( resultant->inf > infinity )
2098  resultant->inf = infinity;
2099  if( resultant->sup < -infinity )
2100  resultant->sup = -infinity;
2101 }
2102 
2103 /** given an interval for the image of a power operation, computes an interval for the origin
2104  * that is, for y = x^p with p = exponent a given scalar and y = image a given interval,
2105  * computes a subinterval x of basedomain such that y in x^p and such that for all z in basedomain less x, z^p not in y
2106  */
2108  SCIP_Real infinity, /**< value for infinity */
2109  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2110  SCIP_INTERVAL basedomain, /**< domain of base */
2111  SCIP_Real exponent, /**< exponent */
2112  SCIP_INTERVAL image /**< interval image of power */
2113  )
2114 {
2115  SCIP_INTERVAL tmp;
2116  SCIP_INTERVAL exprecip;
2117 
2118  assert(resultant != NULL);
2119  assert(image.inf <= image.sup);
2120  assert(basedomain.inf <= basedomain.sup);
2121 
2122  if( exponent == 0.0 )
2123  {
2124  /* exponent is 0.0 */
2125  if( image.inf <= 1.0 && image.sup >= 1.0 )
2126  {
2127  /* 1 in image -> resultant = entire */
2128  *resultant = basedomain;
2129  }
2130  else if( image.inf <= 0.0 && image.sup >= 0.0 )
2131  {
2132  /* 0 in image, 1 not in image -> resultant = 0 (provided 0^0 = 0 ???)
2133  * -> resultant = {0} intersected with basedomain */
2134  SCIPintervalSetBounds(resultant, MAX(0.0, basedomain.inf), MIN(0.0, basedomain.sup));
2135  }
2136  else
2137  {
2138  /* 0 and 1 not in image -> resultant = empty */
2139  SCIPintervalSetEmpty(resultant);
2140  }
2141  return;
2142  }
2143 
2144  /* i = b^e
2145  * i >= 0 -> b = i^(1/e) [union -i^(1/e), if e is even]
2146  * i < 0, e odd integer -> b = -(-i)^(1/e)
2147  * i < 0, e even integer or fractional -> empty
2148  */
2149 
2150  SCIPintervalSetBounds(&exprecip, exponent, exponent);
2151  SCIPintervalReciprocal(infinity, &exprecip, exprecip);
2152 
2153  /* invert positive part of image, if any */
2154  if( image.sup >= 0.0 )
2155  {
2156  SCIPintervalSetBounds(&tmp, MAX(image.inf, 0.0), image.sup);
2157  SCIPintervalPower(infinity, resultant, tmp, exprecip);
2158  if( basedomain.inf <= -resultant->inf && EPSISINT(exponent, 0.0) && (int)exponent % 2 == 0 ) /*lint !e835 */
2159  {
2160  if( basedomain.sup < resultant->inf )
2161  SCIPintervalSetBounds(resultant, -resultant->sup, -resultant->inf);
2162  else
2163  SCIPintervalSetBounds(resultant, -resultant->sup, resultant->sup);
2164  }
2165 
2166  SCIPintervalIntersect(resultant, *resultant, basedomain);
2167  }
2168  else
2169  SCIPintervalSetEmpty(resultant);
2170 
2171  /* invert negative part of image, if any and if base can take negative value and if exponent is such that negative values are possible */
2172  if( image.inf < 0.0 && basedomain.inf < 0.0 && EPSISINT(exponent, 0.0) && ((int)exponent % 2 != 0) ) /*lint !e835 */
2173  {
2174  SCIPintervalSetBounds(&tmp, MAX(-image.sup, 0.0), -image.inf);
2175  SCIPintervalPower(infinity, &tmp, tmp, exprecip);
2176  SCIPintervalSetBounds(&tmp, -tmp.sup, -tmp.inf);
2177  SCIPintervalIntersect(&tmp, basedomain, tmp);
2178  SCIPintervalUnify(resultant, *resultant, tmp);
2179  }
2180 }
2181 
2182 /** stores operand1 to the signed power of the scalar positive operand2 in resultant
2183  *
2184  * the signed power of x w.r.t. an exponent n >= 0 is given as sign(x) * abs(x)^n
2185  *
2186  * @attention we assume correctly rounded sqrt(double) and pow(double) functions when rounding is to nearest
2187  */
2189  SCIP_Real infinity, /**< value for infinity */
2190  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2191  SCIP_INTERVAL operand1, /**< first operand of operation */
2192  SCIP_Real operand2 /**< second operand of operation */
2193  )
2194 {
2195  SCIP_ROUNDMODE roundmode;
2196  assert(resultant != NULL);
2197 
2198  assert(operand1.inf <= operand1.sup);
2199  assert(operand2 >= 0.0);
2200 
2201  if( operand2 == infinity ) /*lint !e777 */
2202  {
2203  /* 0^infinity = 0
2204  * +^infinity = infinity
2205  *-+^infinity = -infinity
2206  */
2207  if( operand1.inf < 0.0 )
2208  resultant->inf = -infinity;
2209  else
2210  resultant->inf = 0.0;
2211  if( operand1.sup > 0.0 )
2212  resultant->sup = infinity;
2213  else
2214  resultant->sup = 0.0;
2215  return;
2216  }
2217 
2218  if( operand2 == 0.0 )
2219  {
2220  /* special case, since x^0 = 1 for x != 0, but 0^0 = 0 */
2221  if( operand1.inf < 0.0 )
2222  resultant->inf = -1.0;
2223  else if( operand1.inf == 0.0 )
2224  resultant->inf = 0.0;
2225  else
2226  resultant->inf = 1.0;
2227 
2228  if( operand1.sup < 0.0 )
2229  resultant->sup = -1.0;
2230  else if( operand1.sup == 0.0 )
2231  resultant->sup = 0.0;
2232  else
2233  resultant->sup = 1.0;
2234 
2235  return;
2236  }
2237 
2238  if( operand2 == 1.0 )
2239  { /* easy case that should run fast */
2240  *resultant = operand1;
2241  return;
2242  }
2243 
2244  roundmode = SCIPintervalGetRoundingMode();
2245 
2246  if( operand2 == 2.0 )
2247  { /* common case where pow can easily be avoided */
2248  if( operand1.inf <= -infinity )
2249  {
2250  resultant->inf = -infinity;
2251  }
2252  else if( operand1.inf >= infinity )
2253  {
2254  resultant->inf = infinity;
2255  }
2256  else if( operand1.inf > 0.0 )
2257  {
2259  resultant->inf = operand1.inf * operand1.inf;
2260  }
2261  else
2262  {
2263  /* need upwards since we negate result of multiplication */
2265  resultant->inf = negate(operand1.inf * operand1.inf);
2266  }
2267 
2268  if( operand1.sup >= infinity )
2269  {
2270  resultant->sup = infinity;
2271  }
2272  else if( operand1.sup <= -infinity )
2273  {
2274  resultant->sup = -infinity;
2275  }
2276  else if( operand1.sup > 0.0 )
2277  {
2279  resultant->sup = operand1.sup * operand1.sup;
2280  }
2281  else
2282  {
2283  /* need downwards since we negate result of multiplication */
2285  resultant->sup = negate(operand1.sup * operand1.sup);
2286  }
2287  assert(resultant->inf <= resultant->sup);
2288  }
2289  else if( operand2 == 0.5 )
2290  { /* another common case where pow can easily be avoided */
2291  if( operand1.inf <= -infinity )
2292  resultant->inf = -infinity;
2293  else if( operand1.inf >= infinity )
2294  resultant->inf = infinity;
2295  else if( operand1.inf >= 0.0 )
2296  {
2298  resultant->inf = nextafter(sqrt( operand1.inf), SCIP_REAL_MIN);
2299  }
2300  else
2301  {
2303  resultant->inf = -nextafter(sqrt(-operand1.inf), SCIP_REAL_MAX);
2304  }
2305 
2306  if( operand1.sup >= infinity )
2307  resultant->sup = infinity;
2308  else if( operand1.sup <= -infinity )
2309  resultant->sup = -infinity;
2310  else if( operand1.sup > 0.0 )
2311  {
2313  resultant->sup = nextafter(sqrt( operand1.sup), SCIP_REAL_MAX);
2314  }
2315  else
2316  {
2318  resultant->sup = -nextafter(sqrt(-operand1.sup), SCIP_REAL_MAX);
2319  }
2320  assert(resultant->inf <= resultant->sup);
2321  }
2322  else
2323  {
2324  if( operand1.inf <= -infinity )
2325  resultant->inf = -infinity;
2326  else if( operand1.inf >= infinity )
2327  resultant->inf = infinity;
2328  else if( operand1.inf > 0.0 )
2329  {
2331  resultant->inf = nextafter(pow( operand1.inf, operand2), SCIP_REAL_MIN);
2332  }
2333  else
2334  {
2336  resultant->inf = -nextafter(pow(-operand1.inf, operand2), SCIP_REAL_MAX);
2337  }
2338 
2339  if( operand1.sup >= infinity )
2340  resultant->sup = infinity;
2341  else if( operand1.sup <= -infinity )
2342  resultant->sup = -infinity;
2343  else if( operand1.sup > 0.0 )
2344  {
2346  resultant->sup = nextafter(pow( operand1.sup, operand2), SCIP_REAL_MAX);
2347  }
2348  else
2349  {
2351  resultant->sup = -nextafter(pow(-operand1.sup, operand2), SCIP_REAL_MIN);
2352  }
2353  }
2354 
2355  SCIPintervalSetRoundingMode(roundmode);
2356 }
2357 
2358 /** computes the reciprocal of an interval
2359  */
2361  SCIP_Real infinity, /**< value for infinity */
2362  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2363  SCIP_INTERVAL operand /**< operand of operation */
2364  )
2365 {
2366  SCIP_ROUNDMODE roundmode;
2367 
2368  assert(resultant != NULL);
2369  assert(operand.inf <= operand.sup);
2370 
2371  if( operand.inf == 0.0 && operand.sup == 0.0 )
2372  { /* 1/0 = [-inf,inf] */
2373  resultant->inf = infinity;
2374  resultant->sup = -infinity;
2375  return;
2376  }
2377 
2378  roundmode = SCIPintervalGetRoundingMode();
2379 
2380  if( operand.inf >= 0.0 )
2381  { /* 1/x with x >= 0 */
2382  if( operand.sup >= infinity )
2383  resultant->inf = 0.0;
2384  else
2385  {
2387  resultant->inf = 1.0 / operand.sup;
2388  }
2389 
2390  if( operand.inf >= infinity )
2391  resultant->sup = 0.0;
2392  else if( operand.inf == 0.0 )
2393  resultant->sup = infinity;
2394  else
2395  {
2397  resultant->sup = 1.0 / operand.inf;
2398  }
2399 
2400  SCIPintervalSetRoundingMode(roundmode);
2401  }
2402  else if( operand.sup <= 0.0 )
2403  { /* 1/x with x <= 0 */
2404  if( operand.sup <= -infinity )
2405  resultant->inf = 0.0;
2406  else if( operand.sup == 0.0 )
2407  resultant->inf = -infinity;
2408  else
2409  {
2411  resultant->inf = 1.0 / operand.sup;
2412  }
2413 
2414  if( operand.inf <= -infinity )
2415  resultant->sup = infinity;
2416  else
2417  {
2419  resultant->sup = 1.0 / operand.inf;
2420  }
2421  SCIPintervalSetRoundingMode(roundmode);
2422  }
2423  else
2424  { /* 1/x with x in [-,+] is division by zero */
2425  resultant->inf = -infinity;
2426  resultant->sup = infinity;
2427  }
2428 }
2429 
2430 /** stores exponential of operand in resultant
2431  * @attention we assume a correctly rounded exp(double) function when rounding is to nearest
2432  */
2434  SCIP_Real infinity, /**< value for infinity */
2435  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2436  SCIP_INTERVAL operand /**< operand of operation */
2437  )
2438 {
2439  assert(resultant != NULL);
2440  assert(operand.inf <= operand.sup);
2441 
2442  if( operand.sup <= -infinity )
2443  {
2444  resultant->inf = 0.0;
2445  resultant->sup = 0.0;
2446  return;
2447  }
2448 
2449  if( operand.inf >= infinity )
2450  {
2451  resultant->inf = infinity;
2452  resultant->sup = infinity;
2453  return;
2454  }
2455 
2456  if( operand.inf == operand.sup ) /*lint !e777 */
2457  {
2458  if( operand.inf == 0.0 )
2459  {
2460  resultant->inf = 1.0;
2461  resultant->sup = 1.0;
2462  }
2463  else
2464  {
2465  SCIP_Real tmp;
2466 
2468  tmp = exp(operand.inf);
2469  resultant->inf = nextafter(tmp, SCIP_REAL_MIN);
2470  resultant->sup = nextafter(tmp, SCIP_REAL_MAX);
2471 
2472  return;
2473  }
2474  }
2475 
2476  if( operand.inf <= -infinity )
2477  {
2478  resultant->inf = 0.0;
2479  }
2480  else if( operand.inf == 0.0 )
2481  {
2482  resultant->inf = 1.0;
2483  }
2484  else
2485  {
2487  resultant->inf = nextafter(exp(operand.inf), SCIP_REAL_MIN);
2488  /* make sure we do not exceed value for infinity, so interval is not declared as empty if inf and sup are both > infinity */
2489  if( resultant->inf >= infinity )
2490  resultant->inf = infinity;
2491  }
2492 
2493  if( operand.sup >= infinity )
2494  {
2495  resultant->sup = infinity;
2496  }
2497  else if( operand.sup == 0.0 )
2498  {
2499  resultant->sup = 1.0;
2500  }
2501  else
2502  {
2504  resultant->sup = nextafter(exp(operand.sup), SCIP_REAL_MAX);
2505  if( resultant->sup < -infinity )
2506  resultant->sup = -infinity;
2507  }
2508 }
2509 
2510 /** stores natural logarithm of operand in resultant
2511  * @attention we assume a correctly rounded log(double) function when rounding is to nearest
2512  */
2514  SCIP_Real infinity, /**< value for infinity */
2515  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2516  SCIP_INTERVAL operand /**< operand of operation */
2517  )
2518 {
2519  assert(resultant != NULL);
2520  assert(operand.inf <= operand.sup);
2521 
2522  if( operand.sup < 0.0 )
2523  {
2524  SCIPintervalSetEmpty(resultant);
2525  return;
2526  }
2527 
2528  if( operand.inf == operand.sup ) /*lint !e777 */
2529  {
2530  if( operand.sup <= 0.0 )
2531  {
2532  resultant->inf = -infinity;
2533  resultant->sup = -infinity;
2534  }
2535  else if( operand.sup == 1.0 )
2536  {
2537  resultant->inf = 0.0;
2538  resultant->sup = 0.0;
2539  }
2540  else
2541  {
2542  SCIP_Real tmp;
2543 
2545  tmp = log(operand.inf);
2546  resultant->inf = nextafter(tmp, SCIP_REAL_MIN);
2547  resultant->sup = nextafter(tmp, SCIP_REAL_MAX);
2548  }
2549 
2550  return;
2551  }
2552 
2553  if( operand.inf <= 0.0 )
2554  {
2555  resultant->inf = -infinity;
2556  }
2557  else if( operand.inf == 1.0 )
2558  {
2559  resultant->inf = 0.0;
2560  }
2561  else
2562  {
2564  resultant->inf = nextafter(log(operand.inf), SCIP_REAL_MIN);
2565  }
2566 
2567  if( operand.sup >= infinity )
2568  {
2569  resultant->sup = infinity;
2570  }
2571  else if( operand.sup == 1.0 )
2572  {
2573  resultant->sup = 0.0;
2574  }
2575  else if( operand.sup == 0.0 )
2576  {
2577  resultant->sup = -infinity;
2578  }
2579  else
2580  {
2582  resultant->sup = nextafter(log(operand.sup), SCIP_REAL_MAX);
2583  }
2584 }
2585 
2586 /** stores minimum of operands in resultant */
2588  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2589  SCIP_INTERVAL operand1, /**< first operand of operation */
2590  SCIP_INTERVAL operand2 /**< second operand of operation */
2591  )
2592 {
2593  assert(resultant != NULL);
2594  assert(operand1.inf <= operand1.sup);
2595  assert(operand2.inf <= operand2.sup);
2596 
2597  resultant->inf = MIN(operand1.inf, operand2.inf);
2598  resultant->sup = MIN(operand1.sup, operand2.sup);
2599 }
2600 
2601 /** stores maximum of operands in resultant */
2603  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2604  SCIP_INTERVAL operand1, /**< first operand of operation */
2605  SCIP_INTERVAL operand2 /**< second operand of operation */
2606  )
2607 {
2608  assert(resultant != NULL);
2609  assert(operand1.inf <= operand1.sup);
2610  assert(operand2.inf <= operand2.sup);
2611 
2612  resultant->inf = MAX(operand1.inf, operand2.inf);
2613  resultant->sup = MAX(operand1.sup, operand2.sup);
2614 }
2615 
2616 /** stores absolute value of operand in resultant */
2618  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2619  SCIP_INTERVAL operand /**< operand of operation */
2620  )
2621 {
2622  assert(resultant != NULL);
2623  assert(operand.inf <= operand.sup);
2624 
2625  if( operand.inf <= 0.0 && operand.sup >= 0.0)
2626  {
2627  resultant->inf = 0.0;
2628  resultant->sup = MAX(-operand.inf, operand.sup);
2629  }
2630  else if( operand.inf > 0.0 )
2631  {
2632  *resultant = operand;
2633  }
2634  else
2635  {
2636  resultant->inf = -operand.sup;
2637  resultant->sup = -operand.inf;
2638  }
2639 }
2640 
2641 /** stores sign of operand in resultant */
2643  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2644  SCIP_INTERVAL operand /**< operand of operation */
2645  )
2646 {
2647  assert(resultant != NULL);
2648  assert(operand.inf <= operand.sup);
2649 
2650  if( operand.sup < 0.0 )
2651  {
2652  resultant->inf = -1.0;
2653  resultant->sup = -1.0;
2654  }
2655  else if( operand.inf >= 0.0 )
2656  {
2657  resultant->inf = 1.0;
2658  resultant->sup = 1.0;
2659  }
2660  else
2661  {
2662  resultant->inf = -1.0;
2663  resultant->sup = 1.0;
2664  }
2665 }
2666 
2667 /** computes exact upper bound on \f$ a x^2 + b x \f$ for x in [xlb, xub], b an interval, and a scalar
2668  *
2669  * Uses Algorithm 2.2 from Domes and Neumaier: Constraint propagation on quadratic constraints (2008) */
2671  SCIP_Real infinity, /**< value for infinity */
2672  SCIP_Real a, /**< coefficient of x^2 */
2673  SCIP_INTERVAL b_, /**< coefficient of x */
2674  SCIP_INTERVAL x /**< range of x */
2675  )
2676 {
2677  SCIP_Real b;
2678  SCIP_Real u;
2679 
2680  assert(!SCIPintervalIsEmpty(x));
2681  assert(b_.inf < infinity);
2682  assert(b_.sup > -infinity);
2683  assert( x.inf < infinity);
2684  assert( x.sup > -infinity);
2685 
2686  /* handle b*x separately */
2687  if( a == 0.0 )
2688  {
2689  if( (b_.inf <= -infinity && x.inf < 0.0 ) ||
2690  ( b_.inf < 0.0 && x.inf <= -infinity) ||
2691  ( b_.sup > 0.0 && x.sup >= infinity) ||
2692  ( b_.sup >= infinity && x.sup > 0.0 ) )
2693  {
2694  u = infinity;
2695  }
2696  else
2697  {
2698  SCIP_ROUNDMODE roundmode;
2699  SCIP_Real cand1, cand2, cand3, cand4;
2700 
2701  roundmode = SCIPintervalGetRoundingMode();
2703  cand1 = b_.inf * x.inf;
2704  cand2 = b_.inf * x.sup;
2705  cand3 = b_.sup * x.inf;
2706  cand4 = b_.sup * x.sup;
2707  u = MAX(MAX(cand1, cand2), MAX(cand3, cand4));
2708 
2709  SCIPintervalSetRoundingMode(roundmode);
2710  }
2711 
2712  return u;
2713  }
2714 
2715  if( x.sup <= 0.0 )
2716  { /* change sign of x: enclose a*x^2 + [-bub, -blb]*(-x) for (-x) in [-xub, -xlb] */
2717  u = x.sup;
2718  x.sup = -x.inf;
2719  x.inf = -u;
2720  b = -b_.inf;
2721  }
2722  else
2723  {
2724  b = b_.sup;
2725  }
2726 
2727  if( x.inf >= 0.0 )
2728  { /* upper bound for a*x^2 + b*x */
2729  SCIP_ROUNDMODE roundmode;
2730  SCIP_Real s,t;
2731 
2732  if( b >= infinity )
2733  return infinity;
2734 
2735  roundmode = SCIPintervalGetRoundingMode();
2737 
2738  u = MAX(x.inf * (a*x.inf + b), x.sup * (a*x.sup + b));
2739  s = b/2;
2740  t = s/negate(a);
2741  if( t > x.inf && negate(2*a)*x.sup > b && s*t > u )
2742  u = s*t;
2743 
2744  SCIPintervalSetRoundingMode(roundmode);
2745  return u;
2746  }
2747  else
2748  {
2749  SCIP_INTERVAL xlow = x;
2750  SCIP_Real cand1;
2751  SCIP_Real cand2;
2752  assert(x.inf < 0.0 && x.sup > 0);
2753 
2754  xlow.sup = 0; /* so xlow is lower part of interval */
2755  x.inf = 0; /* so x is upper part of interval now */
2756  cand1 = SCIPintervalQuadUpperBound(infinity, a, b_, xlow);
2757  cand2 = SCIPintervalQuadUpperBound(infinity, a, b_, x);
2758  return MAX(cand1, cand2);
2759  }
2760 }
2761 
2762 /** stores range of quadratic term in resultant
2763  *
2764  * given scalar a and intervals b and x, computes interval for \f$ a x^2 + b x \f$ */
2766  SCIP_Real infinity, /**< value for infinity */
2767  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2768  SCIP_Real sqrcoeff, /**< coefficient of x^2 */
2769  SCIP_INTERVAL lincoeff, /**< coefficient of x */
2770  SCIP_INTERVAL xrng /**< range of x */
2771  )
2772 {
2773  SCIP_Real tmp;
2774 
2775  if( SCIPintervalIsEmpty(xrng) )
2776  {
2777  SCIPintervalSetEmpty(resultant);
2778  return;
2779  }
2780  if( sqrcoeff == 0.0 )
2781  {
2782  SCIPintervalMul(infinity, resultant, lincoeff, xrng);
2783  return;
2784  }
2785 
2786  resultant->sup = SCIPintervalQuadUpperBound(infinity, sqrcoeff, lincoeff, xrng);
2787 
2788  tmp = lincoeff.inf;
2789  lincoeff.inf = -lincoeff.sup;
2790  lincoeff.sup = -tmp;
2791  resultant->inf = -SCIPintervalQuadUpperBound(infinity, -sqrcoeff, lincoeff, xrng);
2792 
2793  assert(resultant->sup >= resultant->inf);
2794 }
2795 
2796 /** computes interval with positive solutions of a quadratic equation with interval coefficients
2797  *
2798  * Given intervals a, b, and c, this function computes an interval that contains all positive solutions of \f$ a x^2 + b x \in c\f$.
2799  */
2801  SCIP_Real infinity, /**< value for infinity */
2802  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2803  SCIP_INTERVAL sqrcoeff, /**< coefficient of x^2 */
2804  SCIP_INTERVAL lincoeff, /**< coefficient of x */
2805  SCIP_INTERVAL rhs /**< right hand side of equation */
2806  )
2807 {
2808  assert(resultant != NULL);
2809 
2810  /* find x>=0 s.t. a.inf x^2 + b.inf x <= c.sup -> -a.inf x^2 - b.inf x >= -c.sup */
2811  if( lincoeff.inf <= -infinity || rhs.sup >= infinity || sqrcoeff.inf <= -infinity )
2812  {
2813  resultant->inf = 0.0;
2814  resultant->sup = infinity;
2815  }
2816  else
2817  {
2818  SCIPintervalSolveUnivariateQuadExpressionPositiveAllScalar(infinity, resultant, -sqrcoeff.inf, -lincoeff.inf, -rhs.sup);
2819  SCIPdebugMessage("solve %g*x^2 + %g*x >= %g gives [%.20f, %.20f]\n", -sqrcoeff.inf, -lincoeff.inf, -rhs.sup, resultant->inf, resultant->sup);
2820  }
2821 
2822  /* find x>=0 s.t. a.sup x^2 + b.sup x >= c.inf */
2823  if( lincoeff.sup < infinity && rhs.inf > -infinity && sqrcoeff.sup < infinity )
2824  {
2825  SCIP_INTERVAL res2;
2826  SCIPintervalSolveUnivariateQuadExpressionPositiveAllScalar(infinity, &res2, sqrcoeff.sup, lincoeff.sup, rhs.inf);
2827  SCIPdebugMessage("solve %g*x^2 + %g*x >= %g gives [%.20f, %.20f]\n", sqrcoeff.sup, lincoeff.sup, rhs.inf, res2.inf, res2.sup);
2828  SCIPdebugMessage("intersection of [%.20f, %.20f] and [%.20f, %.20f]", resultant->inf, resultant->sup, res2.inf, res2.sup);
2829  /* intersect both results */
2830  SCIPintervalIntersect(resultant, *resultant, res2);
2831  SCIPdebugPrintf(" gives [%.20f, %.20f]\n", resultant->inf, resultant->sup);
2832  }
2833  /* else res2 = [0, infty] */
2834 
2835  if( resultant->inf >= infinity || resultant->sup <= -infinity )
2836  {
2837  SCIPintervalSetEmpty(resultant);
2838  }
2839 }
2840 
2841 /** computes positive solutions of a quadratic equation with scalar coefficients
2842  *
2843  * Given scalar a, b, and c, this function computes an interval that contains all positive solutions of \f$ a x^2 + b x \geq c\f$.
2844  * Implements Algorithm 3.2 from Domes and Neumaier: Constraint propagation on quadratic constraints (2008).
2845  */
2847  SCIP_Real infinity, /**< value for infinity */
2848  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2849  SCIP_Real sqrcoeff, /**< coefficient of x^2 */
2850  SCIP_Real lincoeff, /**< coefficient of x */
2851  SCIP_Real rhs /**< right hand side of equation */
2852  )
2853 {
2854  SCIP_ROUNDMODE roundmode;
2855  SCIP_Real b;
2856  SCIP_Real delta;
2857  SCIP_Real z;
2858 
2859  assert(resultant != NULL);
2860  assert(sqrcoeff < infinity);
2861  assert(sqrcoeff > -infinity);
2862 
2863  resultant->inf = 0.0;
2864  resultant->sup = infinity;
2865 
2866  roundmode = SCIPintervalGetRoundingMode();
2867 
2869  b = lincoeff / 2.0;
2870 
2871  if( lincoeff >= 0.0 )
2872  { /* b >= 0.0 */
2873  /*SCIPintervalSetRoundingMode(SCIP_ROUND_UPWARDS); */
2874  if( rhs > 0.0 )
2875  { /* b >= 0.0 and c > 0.0 */
2876  delta = b*b + sqrcoeff*rhs;
2877  if( delta < 0.0 || (sqrcoeff == 0.0 && lincoeff == 0.0) )
2878  {
2879  SCIPintervalSetEmpty(resultant);
2880  }
2881  else
2882  {
2884  z = nextafter(sqrt(delta), SCIP_REAL_MAX);
2886  z += b;
2887  resultant->inf = negate(negate(rhs)/z);
2888  if( sqrcoeff < 0.0 )
2889  resultant->sup = z / negate(sqrcoeff);
2890  }
2891  }
2892  else
2893  { /* b >= 0.0 and c <= 0.0 */
2894  if( sqrcoeff < 0.0 )
2895  {
2896  delta = b*b + sqrcoeff*rhs;
2898  z = nextafter(sqrt(delta), SCIP_REAL_MAX);
2900  z += b;
2901  resultant->sup = z / negate(sqrcoeff);
2902  }
2903  }
2904  }
2905  else
2906  { /* b < 0.0 */
2907  if( rhs > 0.0 )
2908  { /* b < 0.0 and c > 0.0 */
2909  if( sqrcoeff > 0.0 )
2910  {
2912  delta = b*b + sqrcoeff*rhs;
2914  z = nextafter(sqrt(delta), SCIP_REAL_MAX);
2916  z += negate(b);
2917  resultant->inf = z / sqrcoeff;
2918  }
2919  else
2920  {
2921  SCIPintervalSetEmpty(resultant);
2922  }
2923  }
2924  else
2925  { /* b < 0.0 and c <= 0.0 */
2926  /* SCIPintervalSetRoundingMode(SCIP_ROUND_DOWNWARDS); */
2927  delta = b*b + sqrcoeff * rhs;
2928  if( delta >= 0.0 && sqrcoeff <= 0.0 )
2929  {
2931  z = nextafter(sqrt(delta), SCIP_REAL_MAX);
2933  z += negate(b);
2934  resultant->sup = negate(rhs/z);
2935  }
2936  /* @todo actually we could generate a hole here */
2937  }
2938  }
2939 
2940  SCIPintervalSetRoundingMode(roundmode);
2941 }
2942 
2943 /** solves a quadratic equation with interval coefficients
2944  *
2945  * Given intervals a, b and c, this function computes an interval that contains all solutions of \f$ a x^2 + b x \in c\f$
2946  */
2948  SCIP_Real infinity, /**< value for infinity */
2949  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2950  SCIP_INTERVAL sqrcoeff, /**< coefficient of x^2 */
2951  SCIP_INTERVAL lincoeff, /**< coefficient of x */
2952  SCIP_INTERVAL rhs /**< right hand side of equation */
2953  )
2954 {
2955  SCIP_Real tmp;
2956  SCIP_INTERVAL xpos;
2957  SCIP_INTERVAL xneg;
2958 
2959  assert(resultant != NULL);
2960 
2961  if( sqrcoeff.inf == 0.0 && sqrcoeff.sup == 0.0 )
2962  { /* relatively easy case: x \in rhs / lincoeff */
2963  if( lincoeff.inf == 0.0 && lincoeff.sup == 0.0 )
2964  { /* equation became 0.0 \in rhs */
2965  if( rhs.inf <= 0.0 && rhs.sup >= 0.0 )
2966  SCIPintervalSetEntire(infinity, resultant);
2967  else
2968  SCIPintervalSetEmpty(resultant);
2969  }
2970  else
2971  SCIPintervalDiv(infinity, resultant, rhs, lincoeff);
2972  SCIPdebugMessage(" solving [%g,%g]*x in [%g,%g] gives [%g,%g]\n", SCIPintervalGetInf(lincoeff), SCIPintervalGetSup(lincoeff), SCIPintervalGetInf(rhs), SCIPintervalGetSup(rhs), SCIPintervalGetInf(*resultant), SCIPintervalGetSup(*resultant));
2973  return;
2974  }
2975 
2976  if( lincoeff.inf == 0.0 && lincoeff.sup == 0.0 )
2977  { /* easy case: x \in +/- sqrt(rhs/a) */
2978  SCIPintervalDiv(infinity, resultant, rhs, sqrcoeff);
2979  SCIPintervalSquareRoot(infinity, resultant, *resultant);
2980  resultant->inf = -resultant->sup;
2981  return;
2982  }
2983 
2984  /* find all x>=0 such that a*x^2+b*x = c */
2985  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &xpos, sqrcoeff, lincoeff, rhs);
2986  SCIPdebugMessage(" positive solutions of [%g,%g]*x^2 + [%g,%g]*x in [%g,%g] are [%g,%g]\n",
2987  sqrcoeff.inf, sqrcoeff.sup, lincoeff.inf, lincoeff.sup, rhs.inf, rhs.sup, xpos.inf, xpos.sup);
2988 
2989  tmp = lincoeff.inf;
2990  lincoeff.inf = -lincoeff.sup;
2991  lincoeff.sup = -tmp;
2992 
2993  /* find all x>=0 such that a*x^2-b*x = c */
2994  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &xneg, sqrcoeff, lincoeff, rhs);
2995  tmp = xneg.inf;
2996  xneg.inf = -xneg.sup;
2997  xneg.sup = -tmp;
2998  SCIPdebugMessage(" negative solutions of [%g,%g]*x^2 + [%g,%g]*x in [%g,%g] are [%g,%g]\n",
2999  sqrcoeff.inf, sqrcoeff.sup, lincoeff.inf, lincoeff.sup, rhs.inf, rhs.sup, xneg.inf, xneg.sup);
3000 
3001  SCIPintervalUnify(resultant, xpos, xneg);
3002  SCIPdebugMessage(" unify gives [%g,%g]\n", SCIPintervalGetInf(*resultant), SCIPintervalGetSup(*resultant));
3003 }
3004 
3005 /** stores range of bivariate quadratic term in resultant
3006  * given scalars ax, ay, axy, bx, and by and intervals for x and y, computes interval for \f$ ax x^2 + ay y^2 + axy x y + bx x + by y \f$
3007  * NOTE: the operations are not applied rounding-safe here
3008  */
3010  SCIP_Real infinity, /**< value for infinity in interval arithmetics */
3011  SCIP_INTERVAL* resultant, /**< buffer where to store result of operation */
3012  SCIP_Real ax, /**< square coefficient of x */
3013  SCIP_Real ay, /**< square coefficient of y */
3014  SCIP_Real axy, /**< bilinear coefficients */
3015  SCIP_Real bx, /**< linear coefficient of x */
3016  SCIP_Real by, /**< linear coefficient of y */
3017  SCIP_INTERVAL xbnds, /**< bounds on x */
3018  SCIP_INTERVAL ybnds /**< bounds on y */
3019  )
3020 {
3021  /* we use double double precision and finally widen the computed range by 1e-8% to compensate for not computing rounding-safe here */
3022  SCIP_Real minval;
3023  SCIP_Real maxval;
3024  SCIP_Real val;
3025  SCIP_Real x;
3026  SCIP_Real y;
3027  SCIP_Real denom;
3028 
3029  assert(resultant != NULL);
3030  assert(xbnds.inf <= xbnds.sup);
3031  assert(ybnds.inf <= ybnds.sup);
3032 
3033  /* if we are separable, then fall back to use SCIPintervalQuad two times and add */
3034  if( axy == 0.0 )
3035  {
3036  SCIP_INTERVAL tmp;
3037 
3038  SCIPintervalSet(&tmp, bx);
3039  SCIPintervalQuad(infinity, resultant, ax, tmp, xbnds);
3040 
3041  SCIPintervalSet(&tmp, by);
3042  SCIPintervalQuad(infinity, &tmp, ay, tmp, ybnds);
3043 
3044  SCIPintervalAdd(infinity, resultant, *resultant, tmp);
3045 
3046  return;
3047  }
3048 
3049  SCIPintervalSet(resultant, 0.0);
3050 
3051  minval = infinity;
3052  maxval = -infinity;
3053 
3054  /* check minima/maxima of expression */
3055  denom = 4.0 * ax * ay - axy * axy;
3056  if( REALABS(denom) > 1e-9 )
3057  {
3058  x = (axy * by - 2.0 * ay * bx) / denom;
3059  y = (axy * bx - 2.0 * ax * by) / denom;
3060  if( xbnds.inf <= x && x <= xbnds.sup && ybnds.inf <= y && y <= ybnds.sup )
3061  {
3062  val = (axy * bx * by - ay * bx * bx - ax * by * by) / denom;
3063  minval = MIN(val, minval);
3064  maxval = MAX(val, maxval);
3065  }
3066  }
3067  else if( REALABS(2.0 * ay * bx - axy * by) <= 1e-9 )
3068  {
3069  /* The whole line (x, -bx/axy - (axy/2ay) x) defines an extreme point with value -ay bx^2 / axy^2
3070  * If x is unbounded, then there is an (x,y) with y in ybnds where the extreme value is assumed.
3071  * If x is bounded on at least one side, then we can rely that the checks below for x at one of its bounds will check this extreme point.
3072  */
3073  if( xbnds.inf <= -infinity && xbnds.sup >= infinity )
3074  {
3075  val = -ay * bx * bx / (axy * axy);
3076  minval = MIN(val, minval);
3077  maxval = MAX(val, maxval);
3078  }
3079  }
3080 
3081  /* check boundary of box xbnds x ybnds */
3082 
3083  if( xbnds.inf <= -infinity )
3084  {
3085  /* check value for x -> -infinity */
3086  if( ax > 0.0 )
3087  maxval = infinity;
3088  else if( ax < 0.0 )
3089  minval = -infinity;
3090  else if( ax == 0.0 )
3091  {
3092  /* bivar(x,y) tends to -(bx+axy y) * infinity */
3093 
3094  if( ybnds.inf <= -infinity )
3095  val = (axy < 0.0 ? -infinity : infinity);
3096  else if( bx + axy * ybnds.inf < 0.0 )
3097  val = infinity;
3098  else
3099  val = -infinity;
3100  minval = MIN(val, minval);
3101  maxval = MAX(val, maxval);
3102 
3103  if( ybnds.sup >= infinity )
3104  val = (axy < 0.0 ? infinity : -infinity);
3105  else if( bx + axy * ybnds.sup < 0.0 )
3106  val = infinity;
3107  else
3108  val = -infinity;
3109  minval = MIN(val, minval);
3110  maxval = MAX(val, maxval);
3111  }
3112  }
3113  else
3114  {
3115  /* get range of bivar(xbnds.inf, y) for y in ybnds */
3116  SCIP_INTERVAL tmp;
3117  SCIP_INTERVAL ycoef;
3118 
3119  SCIPintervalSet(&ycoef, axy * xbnds.inf + by);
3120  SCIPintervalQuad(infinity, &tmp, ay, ycoef, ybnds);
3121  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ax * xbnds.inf * xbnds.inf + bx * xbnds.inf));
3122  minval = MIN(tmp.inf, minval);
3123  maxval = MAX(tmp.sup, maxval);
3124  }
3125 
3126  if( xbnds.sup >= infinity )
3127  {
3128  /* check value for x -> infinity */
3129  if( ax > 0.0 )
3130  maxval = infinity;
3131  else if( ax < 0.0 )
3132  minval = -infinity;
3133  else if( ax == 0.0 )
3134  {
3135  /* bivar(x,y) tends to (bx+axy y) * infinity */
3136 
3137  if( ybnds.inf <= -infinity )
3138  val = (axy > 0.0 ? -infinity : infinity);
3139  else if( bx + axy * ybnds.inf > 0.0 )
3140  val = infinity;
3141  else
3142  val = -infinity;
3143  minval = MIN(val, minval);
3144  maxval = MAX(val, maxval);
3145 
3146  if( ybnds.sup >= infinity )
3147  val = (axy > 0.0 ? infinity : -infinity);
3148  else if( bx + axy * ybnds.sup > 0.0 )
3149  val = infinity;
3150  else
3151  val = -infinity;
3152  minval = MIN(val, minval);
3153  maxval = MAX(val, maxval);
3154  }
3155  }
3156  else
3157  {
3158  /* get range of bivar(xbnds.sup, y) for y in ybnds */
3159  SCIP_INTERVAL tmp;
3160  SCIP_INTERVAL ycoef;
3161 
3162  SCIPintervalSet(&ycoef, axy * xbnds.sup + by);
3163  SCIPintervalQuad(infinity, &tmp, ay, ycoef, ybnds);
3164  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ax * xbnds.sup * xbnds.sup + bx * xbnds.sup));
3165  minval = MIN(tmp.inf, minval);
3166  maxval = MAX(tmp.sup, maxval);
3167  }
3168 
3169  if( ybnds.inf <= -infinity )
3170  {
3171  /* check value for y -> -infinity */
3172  if( ay > 0.0 )
3173  maxval = infinity;
3174  else if( ay < 0.0 )
3175  minval = -infinity;
3176  else if( ay == 0.0 )
3177  {
3178  /* bivar(x,y) tends to -(by+axy x) * infinity */
3179 
3180  if( xbnds.inf <= -infinity )
3181  val = (axy < 0.0 ? -infinity : infinity);
3182  else if( by + axy * xbnds.inf < 0.0 )
3183  val = infinity;
3184  else
3185  val = -infinity;
3186  minval = MIN(val, minval);
3187  maxval = MAX(val, maxval);
3188 
3189  if( xbnds.sup >= infinity )
3190  val = (axy < 0.0 ? infinity : -infinity);
3191  else if( by + axy * xbnds.sup < 0.0 )
3192  val = infinity;
3193  else
3194  val = -infinity;
3195  minval = MIN(val, minval);
3196  maxval = MAX(val, maxval);
3197  }
3198  }
3199  else
3200  {
3201  /* get range of bivar(x, ybnds.inf) for x in xbnds */
3202  SCIP_INTERVAL tmp;
3203  SCIP_INTERVAL xcoef;
3204 
3205  SCIPintervalSet(&xcoef, axy * ybnds.inf + bx);
3206  SCIPintervalQuad(infinity, &tmp, ax, xcoef, xbnds);
3207  SCIPintervalAddScalar(infinity, &tmp, tmp, ay * ybnds.inf * ybnds.inf + by * ybnds.inf);
3208  minval = MIN(tmp.inf, minval);
3209  maxval = MAX(tmp.sup, maxval);
3210  }
3211 
3212  if( ybnds.sup >= infinity )
3213  {
3214  /* check value for y -> infinity */
3215  if( ay > 0.0 )
3216  maxval = infinity;
3217  else if( ay < 0.0 )
3218  minval = -infinity;
3219  else if( ay == 0.0 )
3220  {
3221  /* bivar(x,y) tends to (by+axy x) * infinity */
3222 
3223  if( xbnds.inf <= -infinity )
3224  val = (axy > 0.0 ? -infinity : infinity);
3225  else if( by + axy * xbnds.inf > 0.0 )
3226  val = infinity;
3227  else
3228  val = -infinity;
3229  minval = MIN(val, minval);
3230  maxval = MAX(val, maxval);
3231 
3232  if( xbnds.sup >= infinity )
3233  val = (axy > 0.0 ? infinity : -infinity);
3234  else if( by + axy * xbnds.sup > 0.0 )
3235  val = infinity;
3236  else
3237  val = -infinity;
3238  minval = MIN(val, minval);
3239  maxval = MAX(val, maxval);
3240  }
3241  }
3242  else
3243  {
3244  /* get range of bivar(x, ybnds.sup) for x in xbnds */
3245  SCIP_INTERVAL tmp;
3246  SCIP_INTERVAL xcoef;
3247 
3248  SCIPintervalSet(&xcoef, axy * ybnds.sup + bx);
3249  SCIPintervalQuad(infinity, &tmp, ax, xcoef, xbnds);
3250  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ay * ybnds.sup * ybnds.sup + by * ybnds.sup));
3251  minval = MIN(tmp.inf, minval);
3252  maxval = MAX(tmp.sup, maxval);
3253  }
3254 
3255  minval -= 1e-10 * REALABS(minval);
3256  maxval += 1e-10 * REALABS(maxval);
3257  SCIPintervalSetBounds(resultant, (SCIP_Real)minval, (SCIP_Real)maxval);
3258 
3259  SCIPdebugMessage("range for %gx^2 + %gy^2 + %gxy + %gx + %gy = [%g, %g] for x = [%g, %g], y=[%g, %g]\n",
3260  ax, ay, axy, bx, by, minval, maxval, xbnds.inf, xbnds.sup, ybnds.inf, ybnds.sup);
3261 }
3262 
3263 /** solves a bivariate quadratic equation for the first variable
3264  * given scalars ax, ay, axy, bx and by, and intervals for x, y, and rhs,
3265  * computes \f$ \{ x \in \mathbf{x} : \exists y \in \mathbf{y} : a_x x^2 + a_y y^2 + a_{xy} x y + b_x x + b_y y \in \mathbf{\mbox{rhs}} \} \f$
3266  * NOTE: the operations are not applied rounding-safe here
3267  */
3269  SCIP_Real infinity, /**< value for infinity in interval arithmetics */
3270  SCIP_INTERVAL* resultant, /**< buffer where to store result of operation */
3271  SCIP_Real ax, /**< square coefficient of x */
3272  SCIP_Real ay, /**< square coefficient of y */
3273  SCIP_Real axy, /**< bilinear coefficients */
3274  SCIP_Real bx, /**< linear coefficient of x */
3275  SCIP_Real by, /**< linear coefficient of y */
3276  SCIP_INTERVAL rhs, /**< right-hand-side of equation */
3277  SCIP_INTERVAL xbnds, /**< bounds on x */
3278  SCIP_INTERVAL ybnds /**< bounds on y */
3279  )
3280 {
3281  /* we use double double precision and finally widen the computed range by 1e-8% to compensate for not computing rounding-safe here */
3282  SCIP_Real val;
3283 
3284  assert(resultant != NULL);
3285 
3286  if( axy == 0.0 )
3287  {
3288  /* if axy == 0, fall back to SCIPintervalSolveUnivariateQuadExpression */
3289  SCIP_INTERVAL ytermrng;
3290  SCIP_INTERVAL sqrcoef;
3291  SCIP_INTERVAL lincoef;
3292  SCIP_INTERVAL pos;
3293  SCIP_INTERVAL neg;
3294 
3295  SCIPintervalSet(&lincoef, by);
3296  SCIPintervalQuad(infinity, &ytermrng, ay, lincoef, ybnds);
3297  SCIPintervalSub(infinity, &rhs, rhs, ytermrng);
3298 
3299  SCIPintervalSet(&sqrcoef, ax);
3300 
3301  /* get positive solutions, if of interest */
3302  if( xbnds.sup >= 0.0 )
3303  {
3304  SCIPintervalSet(&lincoef, bx);
3305  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &pos, sqrcoef, lincoef, rhs);
3306  SCIPintervalIntersect(&pos, pos, xbnds);
3307  }
3308  else
3309  SCIPintervalSetEmpty(&pos);
3310 
3311  /* get negative solutions, if of interest */
3312  if( xbnds.inf < 0.0 )
3313  {
3314  SCIPintervalSet(&lincoef, -bx);
3315  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &neg, sqrcoef, lincoef, rhs);
3316  if( !SCIPintervalIsEmpty(neg) )
3317  {
3318  SCIPintervalSetBounds(&neg, -neg.sup, -neg.inf);
3319  SCIPintervalIntersect(&neg, neg, xbnds);
3320  }
3321  }
3322  else
3323  SCIPintervalSetEmpty(&neg);
3324 
3325  SCIPintervalUnify(resultant, pos, neg);
3326 
3327  return;
3328  }
3329 
3330  if( ax < 0.0 )
3331  {
3332  SCIP_Real tmp;
3333  tmp = rhs.inf;
3334  rhs.inf = -rhs.sup;
3335  rhs.sup = -tmp;
3336 
3337  SCIPintervalSolveBivariateQuadExpressionAllScalar(infinity, resultant, -ax, -ay, -axy, -bx, -by, rhs, xbnds, ybnds);
3338  return;
3339  }
3340  assert(ax >= 0.0);
3341 
3342  *resultant = xbnds;
3343 
3344  if( ax > 0.0 )
3345  {
3346  SCIP_Real sqrtax;
3347  SCIP_Real minvalleft;
3348  SCIP_Real maxvalleft;
3349  SCIP_Real minvalright;
3350  SCIP_Real maxvalright;
3351  SCIP_Real ymin;
3352  SCIP_Real rcoef_y;
3353  SCIP_Real rcoef_yy;
3354  SCIP_Real rcoef_const;
3355 
3356  sqrtax = sqrt(ax);
3357 
3358  /* rewrite equation as (sqrt(ax)x + b(y))^2 \in r(rhs,y), where
3359  * b(y) = (bx + axy y)/(2sqrt(ax)), r(rhs,y) = rhs - ay y^2 - by y + b(y)^2
3360  *
3361  * -> r(rhs,y) = bx^2/(4ax) + rhs + (axy bx/(2ax) - by)*y + (axy^2/(4ax) - ay)*y^2
3362  */
3363  rcoef_y = axy * bx / (2.0*ax) - by;
3364  rcoef_yy = axy * axy / (4.0*ax) - ay;
3365  rcoef_const = bx * bx / (4.0*ax);
3366 
3367 #define CALCB(y) ((bx + axy * (y)) / (2.0 * sqrtax))
3368 #define CALCR(c,y) (rcoef_const + (c) + (rcoef_y + rcoef_yy * (y)) * (y))
3369 
3370  /* check whether r(rhs,y) is always negative */
3371  if( rhs.sup < infinity )
3372  {
3373  SCIP_INTERVAL ycoef;
3374  SCIP_Real ub;
3375 
3376  SCIPintervalSet(&ycoef, (SCIP_Real)rcoef_y);
3377  ub = (SCIP_Real)(SCIPintervalQuadUpperBound(infinity, (SCIP_Real)rcoef_yy, ycoef, ybnds) + rhs.sup + rcoef_const);
3378 
3379  if( EPSN(ub, 1e-9) )
3380  {
3381  SCIPintervalSetEmpty(resultant);
3382  return;
3383  }
3384  }
3385 
3386  /* we have sqrt(ax)x \in (-sqrt(r(rhs,y))-b(y)) \cup (sqrt(r(rhs,y))-b(y))
3387  * compute minima and maxima of both functions such that
3388  *
3389  * [minvalleft, maxvalleft ] = -sqrt(r(rhs,y))-b(y)
3390  * [minvalright, maxvalright] = sqrt(r(rhs,y))-b(y)
3391  */
3392 
3393  minvalleft = infinity;
3394  maxvalleft = -infinity;
3395  minvalright = infinity;
3396  maxvalright = -infinity;
3397 
3398  if( rhs.sup >= infinity )
3399  {
3400  /* we can't do much if rhs.sup is infinite
3401  * but we may to a bit of xbnds isn't too huge and rhs.inf > -infinity */
3402  minvalleft = -infinity;
3403  maxvalright = infinity;
3404  }
3405 
3406  /* evaluate at lower bound of y, as long as r(rhs,ylb) > 0 */
3407  if( ybnds.inf <= -infinity )
3408  {
3409  /* check limit of +/-sqrt(r(rhs,y))-b(y) for y -> -infty */
3410  if( !EPSZ(ay, 1e-9) && axy * axy >= 4.0 * ax * ay )
3411  {
3412  if( axy < 0.0 || ay < 0.0 )
3413  minvalleft = -infinity;
3414 
3415  if( axy < 0.0 && ay > 0.0 )
3416  maxvalleft = infinity;
3417 
3418  if( axy > 0.0 && ay > 0.0 )
3419  minvalleft = -infinity;
3420 
3421  if( axy > 0.0 || ay < 0.0 )
3422  maxvalright = infinity;
3423  }
3424  else if( !EPSZ(ay, 1e-9) )
3425  {
3426  /* here axy * axy < 4 * ax * ay, so need to check for zeros of r(rhs,y), which is done below */
3427  }
3428  else
3429  {
3430  /* here ay = 0.0, which gives a limit of -by/2 for -sqrt(r(rhs,y))-b(y) */
3431  minvalleft = -by / 2.0;
3432  maxvalleft = -by / 2.0;
3433  /* here ay = 0.0, which gives a limit of +infinity for sqrt(r(rhs,y))-b(y) */
3434  maxvalright = infinity;
3435  }
3436  }
3437  else
3438  {
3439  SCIP_Real b;
3440  SCIP_Real c;
3441 
3442  b = CALCB(ybnds.inf);
3443 
3444  if( rhs.sup < infinity )
3445  {
3446  c = CALCR(rhs.sup, ybnds.inf);
3447 
3448  if( c > 0.0 )
3449  {
3450  SCIP_Real sqrtc;
3451 
3452  sqrtc = sqrt(c);
3453  minvalleft = MIN(-sqrtc - b, minvalleft);
3454  maxvalright = MAX( sqrtc - b, maxvalright);
3455  }
3456  }
3457 
3458  if( rhs.inf > -infinity )
3459  {
3460  c = CALCR(rhs.inf, ybnds.inf);
3461 
3462  if( c > 0.0 )
3463  {
3464  SCIP_Real sqrtc;
3465 
3466  sqrtc = sqrt(c);
3467  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3468  minvalright = MIN( sqrtc - b, minvalright);
3469  }
3470  }
3471  }
3472 
3473  /* evaluate at upper bound of y, as long as r(rhs, yub) > 0 */
3474  if( ybnds.sup >= infinity )
3475  {
3476  /* check limit of +/-sqrt(r(rhs,y))-b(y) for y -> +infty */
3477  if( !EPSZ(ay, 1e-9) && axy * axy >= 4.0 * ax * ay )
3478  {
3479  if( axy > 0.0 || ay < 0.0 )
3480  minvalleft = -infinity;
3481 
3482  if( axy < 0.0 && ay > 0.0 )
3483  maxvalleft = infinity;
3484 
3485  if( axy > 0.0 && ay > 0.0 )
3486  minvalright = -infinity;
3487 
3488  if( axy < 0.0 || ay < 0.0 )
3489  maxvalright = infinity;
3490  }
3491  else if( !EPSZ(ay, 1e-9) )
3492  {
3493  /* here axy * axy < 4 * ax * ay, so need to check for zeros of r(rhs,y), which will happen below */
3494  }
3495  else
3496  {
3497  /* here ay = 0.0, which gives a limit of -infinity for -sqrt(r(rhs,y))-b(y) */
3498  minvalleft = -infinity;
3499  /* here ay = 0.0, which gives a limit of -by/2 for sqrt(r(rhs,y))-b(y) */
3500  minvalright = MIN(minvalright, -by / 2.0);
3501  maxvalright = MAX(maxvalright, -by / 2.0);
3502  }
3503  }
3504  else
3505  {
3506  SCIP_Real b;
3507  SCIP_Real c;
3508 
3509  b = CALCB(ybnds.sup);
3510 
3511  if( rhs.sup < infinity )
3512  {
3513  c = CALCR(rhs.sup, ybnds.sup);
3514 
3515  if( c > 0.0 )
3516  {
3517  SCIP_Real sqrtc;
3518 
3519  sqrtc = sqrt(c);
3520  minvalleft = MIN(-sqrtc - b, minvalleft);
3521  maxvalright = MAX( sqrtc - b, maxvalright);
3522  }
3523  }
3524 
3525  if( rhs.inf > -infinity )
3526  {
3527  c = CALCR(rhs.inf, ybnds.sup);
3528 
3529  if( c > 0.0 )
3530  {
3531  SCIP_Real sqrtc;
3532 
3533  sqrtc = sqrt(c);
3534  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3535  minvalright = MIN( sqrtc - b, minvalright);
3536  }
3537  }
3538  }
3539 
3540  /* evaluate at ymin = y_{_,+}, if inside ybnds
3541  * if ay = 0 or 2ay*bx == axy*by, then there is no ymin */
3542  if( !EPSZ(ay, 1e-9) )
3543  {
3544  if( REALABS(axy*axy - 4.0*ax*ay) > 1e-9 )
3545  {
3546  SCIP_Real sqrtterm;
3547 
3548  if( rhs.sup < infinity )
3549  {
3550  sqrtterm = axy * axy * ay * (ay * bx * bx - axy * bx * by + ax * by * by - axy * axy * rhs.sup + 4.0 * ax * ay * rhs.sup);
3551  if( !EPSN(sqrtterm, 1e-9) )
3552  {
3553  sqrtterm = sqrt(MAX(sqrtterm, 0.0));
3554  /* check first candidate for extreme points of +/-sqrt(rhs(r,y))-b(y) */
3555  ymin = axy * ay * bx - 2.0 * ax * ay * by - sqrtterm;
3556  ymin /= ay;
3557  ymin /= 4.0 * ax * ay - axy * axy;
3558 
3559  if( ymin > ybnds.inf && ymin < ybnds.sup )
3560  {
3561  SCIP_Real b;
3562  SCIP_Real c;
3563 
3564  b = CALCB(ymin);
3565  c = CALCR(rhs.sup, ymin);
3566 
3567  if( c > 0.0 )
3568  {
3569  SCIP_Real sqrtc;
3570 
3571  sqrtc = sqrt(c);
3572  minvalleft = MIN(-sqrtc - b, minvalleft);
3573  maxvalright = MAX( sqrtc - b, maxvalright);
3574  }
3575  }
3576 
3577  /* check second candidate for extreme points of +/-sqrt(rhs(r,y))-b(y) */
3578  ymin = axy * ay * bx - 2.0 * ax * ay * by + sqrtterm;
3579  ymin /= ay;
3580  ymin /= 4.0 * ax * ay - axy * axy;
3581 
3582  if( ymin > ybnds.inf && ymin < ybnds.sup )
3583  {
3584  SCIP_Real b;
3585  SCIP_Real c;
3586 
3587  b = CALCB(ymin);
3588  c = CALCR(rhs.sup, ymin);
3589 
3590  if( c > 0.0 )
3591  {
3592  SCIP_Real sqrtc;
3593 
3594  sqrtc = sqrt(c);
3595  minvalleft = MIN(-sqrtc - b, minvalleft);
3596  maxvalright = MAX( sqrtc - b, maxvalright);
3597  }
3598  }
3599  }
3600  }
3601 
3602  if( rhs.inf > -infinity )
3603  {
3604  sqrtterm = axy * axy * ay * (ay * bx * bx - axy * bx * by + ax * by * by - axy * axy * rhs.inf + 4.0 * ax * ay * rhs.inf);
3605  if( !EPSN(sqrtterm, 1e-9) )
3606  {
3607  sqrtterm = sqrt(MAX(sqrtterm, 0.0));
3608  /* check first candidate for extreme points of +/-sqrt(r(rhs,y))-b(y) */
3609  ymin = axy * ay * bx - 2.0 * ax * ay * by - sqrtterm;
3610  ymin /= ay;
3611  ymin /= 4.0 * ax * ay - axy * axy;
3612 
3613  if( ymin > ybnds.inf && ymin < ybnds.sup )
3614  {
3615  SCIP_Real b;
3616  SCIP_Real c;
3617 
3618  b = CALCB(ymin);
3619  c = CALCR(rhs.inf, ymin);
3620 
3621  if( c > 0.0 )
3622  {
3623  SCIP_Real sqrtc;
3624 
3625  sqrtc = sqrt(c);
3626  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3627  minvalright = MIN( sqrtc - b, minvalright);
3628  }
3629  }
3630 
3631  /* check second candidate for extreme points of +/-sqrt(c(y))-b(y) */
3632  ymin = axy * ay * bx - 2.0 * ax * ay * by + sqrtterm;
3633  ymin /= ay;
3634  ymin /= 4.0 * ax * ay - axy * axy;
3635 
3636  if( ymin > ybnds.inf && ymin < ybnds.sup )
3637  {
3638  SCIP_Real b;
3639  SCIP_Real c;
3640 
3641  b = CALCB(ymin);
3642  c = CALCR(rhs.inf, ymin);
3643 
3644  if( c > 0.0 )
3645  {
3646  SCIP_Real sqrtc;
3647 
3648  sqrtc = sqrt(c);
3649  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3650  minvalright = MIN( sqrtc - b, minvalright);
3651  }
3652  }
3653  }
3654  }
3655 
3656  }
3657  else if( REALABS(2.0 * ay * bx - axy * by) > 1e-9 )
3658  {
3659  if( rhs.sup < infinity )
3660  {
3661  ymin = - (4.0 * ay * bx * by - axy * by * by + 4.0 * axy * ay * rhs.sup);
3662  ymin /= 4.0 * ay;
3663  ymin /= 2.0 * ay * bx - axy * by;
3664 
3665  if( ymin > ybnds.inf && ymin < ybnds.sup )
3666  {
3667  SCIP_Real b;
3668  SCIP_Real c;
3669 
3670  b = CALCB(ymin);
3671  c = CALCR(rhs.sup, ymin);
3672 
3673  if( c > 0.0 )
3674  {
3675  SCIP_Real sqrtc;
3676 
3677  sqrtc = sqrt(c);
3678  minvalleft = MIN(-sqrtc - b, minvalleft);
3679  maxvalright = MAX( sqrtc - b, maxvalright);
3680  }
3681  }
3682  }
3683 
3684  if( rhs.inf > -infinity )
3685  {
3686  ymin = - (4.0 * ay * bx * by - axy * by * by + 4.0 * axy * ay * rhs.inf);
3687  ymin /= 4.0 * ay;
3688  ymin /= 2.0 * ay * bx - axy * by;
3689 
3690  if( ymin > ybnds.inf && ymin < ybnds.sup )
3691  {
3692  SCIP_Real b;
3693  SCIP_Real c;
3694 
3695  b = CALCB(ymin);
3696  c = CALCR(rhs.inf, ymin);
3697 
3698  if( c > 0.0 )
3699  {
3700  SCIP_Real sqrtc;
3701 
3702  sqrtc = sqrt(c);
3703  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3704  minvalright = MIN( sqrtc - b, minvalright);
3705  }
3706  }
3707  }
3708  }
3709  }
3710 
3711  /* evaluate the case r(rhs,y) = 0, which is to min/max -b(y) w.r.t. r(rhs,y) = 0, y in ybnds
3712  * with the above assigments
3713  * rcoef_y = axy * bx / (2.0*ax) - by;
3714  * rcoef_yy = axy * axy / (4.0*ax) - ay;
3715  * rcoef_const = bx * bx / (4.0*ax);
3716  * we have r(rhs,y) = rhs + rcoef_const + rcoef_y * y + rcoef_yy * y^2
3717  *
3718  * thus, r(rhs,y) = 0 <-> rcoef_y * y + rcoef_yy * y^2 in -rhs - rcoef_const
3719  *
3720  */
3721  {
3722  SCIP_INTERVAL rcoef_yy_int;
3723  SCIP_INTERVAL rcoef_y_int;
3724  SCIP_INTERVAL rhs2;
3725  SCIP_Real b;
3726 
3727  /* setup rcoef_yy, rcoef_y and -rhs-rcoef_const as intervals */
3728  SCIPintervalSet(&rcoef_yy_int, (SCIP_Real)rcoef_yy);
3729  SCIPintervalSet(&rcoef_y_int, (SCIP_Real)rcoef_y);
3730  SCIPintervalSetBounds(&rhs2, (SCIP_Real)(-rhs.sup - rcoef_const), (SCIP_Real)(-rhs.inf - rcoef_const));
3731 
3732  /* first find all y >= 0 such that rcoef_y * y + rcoef_yy * y^2 in -rhs2, if ybnds.sup > 0.0
3733  * and evaluate -b(y) w.r.t. these values */
3734  if( ybnds.sup > 0.0 )
3735  {
3736  SCIP_INTERVAL ypos;
3737 
3738  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &ypos, rcoef_yy_int, rcoef_y_int, rhs2);
3739  SCIPintervalIntersect(&ypos, ypos, ybnds);
3740  if( !SCIPintervalIsEmpty(ypos) )
3741  {
3742  assert(ypos.inf >= 0.0); /* we computed only positive solutions above */
3743  b = CALCB(ypos.inf);
3744  minvalleft = MIN(minvalleft, -b);
3745  maxvalleft = MAX(maxvalleft, -b);
3746  minvalright = MIN(minvalright, -b);
3747  maxvalright = MAX(maxvalright, -b);
3748 
3749  if( ypos.sup < infinity )
3750  {
3751  b = CALCB(ypos.sup);
3752  minvalleft = MIN(minvalleft, -b);
3753  maxvalleft = MAX(maxvalleft, -b);
3754  minvalright = MIN(minvalright, -b);
3755  maxvalright = MAX(maxvalright, -b);
3756  }
3757  else
3758  {
3759  /* -b(y) = - (bx + axy * y) / (2.0 * sqrt(ax)) -> -sign(axy)*infinity for y -> infinity */
3760  if( axy > 0.0 )
3761  {
3762  minvalleft = -infinity;
3763  minvalright = -infinity;
3764  }
3765  else
3766  {
3767  maxvalleft = infinity;
3768  maxvalright = infinity;
3769  }
3770  }
3771  }
3772  }
3773 
3774  /* next find all y <= 0 such that rcoef_y * y + rcoef_yy * y^2 in -rhs2, if ybnds.inf < 0.0
3775  * and evaluate -b(y) w.r.t. these values */
3776  if( ybnds.inf < 0.0 )
3777  {
3778  SCIP_INTERVAL yneg;
3779 
3780  /* find all y >= 0 such that -rcoef_y * y + rcoef_yy * y^2 in -rhs2 and then negate y */
3781  SCIPintervalSet(&rcoef_y_int, -(SCIP_Real)rcoef_y);
3782  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &yneg, rcoef_yy_int, rcoef_y_int, rhs2);
3783  if( !SCIPintervalIsEmpty(yneg) )
3784  {
3785  SCIPintervalSetBounds(&yneg, -yneg.sup, -yneg.inf);
3786  SCIPintervalIntersect(&yneg, yneg, ybnds);
3787  }
3788  if( !SCIPintervalIsEmpty(yneg) )
3789  {
3790  if( yneg.inf > -infinity )
3791  {
3792  b = CALCB(yneg.inf);
3793  minvalleft = MIN(minvalleft, -b);
3794  maxvalleft = MAX(maxvalleft, -b);
3795  minvalright = MIN(minvalright, -b);
3796  maxvalright = MAX(maxvalright, -b);
3797  }
3798  else
3799  {
3800  /* -b(y) = - (bx + axy * y) / (2.0 * sqrt(ax)) -> sign(axy)*infinity for y -> -infinity */
3801  if( axy > 0.0 )
3802  {
3803  maxvalleft = infinity;
3804  maxvalright = infinity;
3805  }
3806  else
3807  {
3808  minvalleft = -infinity;
3809  minvalright = -infinity;
3810  }
3811  }
3812 
3813  assert(yneg.sup <= 0.0); /* we computed only negative solutions above */
3814  b = CALCB(yneg.sup);
3815  minvalleft = MIN(minvalleft, -b);
3816  maxvalleft = MAX(maxvalleft, -b);
3817  minvalright = MIN(minvalright, -b);
3818  maxvalright = MAX(maxvalright, -b);
3819  }
3820  }
3821  }
3822 
3823  if( rhs.inf > -infinity && xbnds.inf > -infinity && EPSGT(xbnds.inf, maxvalleft / sqrtax, 1e-9) )
3824  {
3825  /* if sqrt(ax)*x > -sqrt(r(rhs,y))-b(y), then tighten lower bound of sqrt(ax)*x to lower bound of sqrt(r(rhs,y))-b(y)
3826  * this is only possible if rhs.inf > -infinity, otherwise the value for maxvalleft is not valid (but tightening wouldn't be possible for sure anyway) */
3827  assert(EPSGE(minvalright, minvalleft, 1e-9)); /* right interval should not be above lower bound of left interval */
3828  if( minvalright > -infinity )
3829  resultant->inf = (SCIP_Real)(minvalright / sqrtax);
3830  }
3831  else
3832  {
3833  /* otherwise, tighten lower bound of sqrt(ax)*x to lower bound of -sqrt(r(rhs,y))-b(y) */
3834  if( minvalleft > -infinity )
3835  resultant->inf = (SCIP_Real)(minvalleft / sqrtax);
3836  }
3837 
3838  if( rhs.inf > -infinity && xbnds.sup < infinity && EPSLT(xbnds.sup, minvalright / sqrtax, 1e-9) )
3839  {
3840  /* if sqrt(ax)*x < sqrt(r(rhs,y))-b(y), then tighten upper bound of sqrt(ax)*x to upper bound of -sqrt(r(rhs,y))-b(y)
3841  * this is only possible if rhs.inf > -infinity, otherwise the value for minvalright is not valid (but tightening wouldn't be possible for sure anyway) */
3842  assert(EPSLE(maxvalleft, maxvalright, 1e-9)); /* left interval should not be above upper bound of right interval */
3843  if( maxvalleft < infinity )
3844  resultant->sup = (SCIP_Real)(maxvalleft / sqrtax);
3845  }
3846  else
3847  {
3848  /* otherwise, tighten upper bound of sqrt(ax)*x to upper bound of sqrt(r(rhs,y))-b(y) */
3849  if( maxvalright < infinity )
3850  resultant->sup = (SCIP_Real)(maxvalright / sqrtax);
3851  }
3852 
3853  resultant->inf -= 1e-10 * REALABS(resultant->inf);
3854  resultant->sup += 1e-10 * REALABS(resultant->sup);
3855 
3856 #undef CALCB
3857 #undef CALCR
3858  }
3859  else
3860  {
3861  /* case ax == 0 */
3862 
3863  SCIP_Real c;
3864  SCIP_Real d;
3865  SCIP_Real ymin;
3866  SCIP_Real minval;
3867  SCIP_Real maxval;
3868 
3869  /* consider -bx / axy in ybnds, i.e., bx + axy y can be 0 */
3870  if( EPSGE(-bx / axy, ybnds.inf, 1e-9) && EPSLE(-bx / axy, ybnds.sup, 1e-9) )
3871  {
3872  /* write as (bx + axy y) * x \in (c - ay y^2 - by y)
3873  * and estimate bx + axy y and c - ay y^2 - by y by intervals independently
3874  * @todo can we do better, as in the case where bx + axy y is bounded away from 0?
3875  */
3876  SCIP_INTERVAL lincoef;
3877  SCIP_INTERVAL myrhs;
3878  SCIP_INTERVAL tmp;
3879 
3880  if( xbnds.inf < 0.0 && xbnds.sup > 0.0 )
3881  {
3882  /* if (bx + axy y) can be arbitrary small and x be both positive and negative,
3883  * then nothing we can tighten here
3884  */
3885  SCIPintervalSetBounds(resultant, xbnds.inf, xbnds.sup);
3886  return;
3887  }
3888 
3889  /* store interval for (bx + axy y) in lincoef */
3890  SCIPintervalMulScalar(infinity, &lincoef, ybnds, axy);
3891  SCIPintervalAddScalar(infinity, &lincoef, lincoef, bx);
3892 
3893  /* store interval for (c - ay y^2 - by y) in myrhs */
3894  SCIPintervalSet(&tmp, by);
3895  SCIPintervalQuad(infinity, &tmp, ay, tmp, ybnds);
3896  SCIPintervalSub(infinity, &myrhs, rhs, tmp);
3897 
3898  if( lincoef.inf == 0.0 && lincoef.sup == 0.0 )
3899  {
3900  /* equation became 0.0 \in myrhs */
3901  if( myrhs.inf <= 0.0 && myrhs.sup >= 0.0 )
3902  SCIPintervalSetEntire(infinity, resultant);
3903  else
3904  SCIPintervalSetEmpty(resultant);
3905  }
3906  else if( xbnds.inf >= 0.0 )
3907  {
3908  SCIP_INTERVAL a_;
3909 
3910  /* need only positive solutions */
3911  SCIPintervalSet(&a_, 0.0);
3912  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, resultant, a_, lincoef, myrhs);
3913  }
3914  else
3915  {
3916  SCIP_INTERVAL a_;
3917 
3918  assert(xbnds.sup <= 0.0);
3919 
3920  /* need only negative solutions */
3921  SCIPintervalSet(&a_, 0.0);
3922  SCIPintervalSetBounds(&lincoef, -lincoef.sup, -lincoef.inf);
3923  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, resultant, a_, lincoef, myrhs);
3924  if( !SCIPintervalIsEmpty(*resultant) )
3925  SCIPintervalSetBounds(resultant, -resultant->sup, -resultant->inf);
3926  }
3927 
3928  SCIPintervalIntersect(resultant, xbnds, *resultant);
3929 
3930  return;
3931  }
3932 
3933  minval = infinity;
3934  maxval = -infinity;
3935 
3936  /* compute a lower bound on x */
3937  if( bx + axy * (axy > 0.0 ? ybnds.inf : ybnds.sup) > 0.0 )
3938  c = rhs.inf;
3939  else
3940  c = rhs.sup;
3941 
3942  if( c > -infinity && c < infinity )
3943  {
3944  if( ybnds.inf <= -infinity )
3945  {
3946  /* limit is ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
3947  if( EPSZ(ay, 1e-9) )
3948  minval = -by / axy;
3949  else if( ay * axy < 0.0 )
3950  minval = -infinity;
3951  }
3952  else
3953  {
3954  val = (c - ay * ybnds.inf * ybnds.inf - by * ybnds.inf) / (bx + axy * ybnds.inf);
3955  minval = MIN(val, minval);
3956  }
3957 
3958  if( ybnds.sup >= infinity )
3959  {
3960  /* limit is -ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
3961  if( EPSZ(ay, 1e-9) )
3962  minval = MIN(minval, -by / axy);
3963  else if( ay * axy > 0.0 )
3964  minval = -infinity;
3965  }
3966  else
3967  {
3968  val = (c - ay * ybnds.sup * ybnds.sup - by * ybnds.sup) / (bx + axy * ybnds.sup);
3969  minval = MIN(val, minval);
3970  }
3971 
3972  if( !EPSZ(ay, 1e-9) )
3973  {
3974  d = ay * (ay * bx * bx - axy * (bx * by + axy * c));
3975  if( !EPSN(d, 1e-9) )
3976  {
3977  ymin = -ay * bx + sqrt(MAX(d, 0.0));
3978  ymin /= axy * ay;
3979 
3980  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
3981  minval = MIN(val, minval);
3982 
3983  ymin = -ay * bx - sqrt(MAX(d, 0.0));
3984  ymin /= axy * ay;
3985 
3986  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
3987  minval = MIN(val, minval);
3988  }
3989  }
3990  }
3991  else
3992  {
3993  minval = -infinity;
3994  }
3995 
3996  /* compute an upper bound on x */
3997  if( bx + axy * (axy > 0.0 ? ybnds.inf : ybnds.sup) > 0.0 )
3998  c = rhs.sup;
3999  else
4000  c = rhs.inf;
4001 
4002  if( c > -infinity && c < infinity )
4003  {
4004  if( ybnds.inf <= -infinity )
4005  {
4006  /* limit is ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4007  if( EPSZ(ay, 1e-9) )
4008  maxval = -by / axy;
4009  else if( ay * axy > 0.0 )
4010  maxval = infinity;
4011  }
4012  else
4013  {
4014  val = (c - ay * ybnds.inf * ybnds.inf - by * ybnds.inf) / (bx + axy * ybnds.inf);
4015  maxval = MAX(val, maxval);
4016  }
4017 
4018  if( ybnds.sup >= infinity )
4019  {
4020  /* limit is -ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4021  if( EPSZ(ay, 1e-9) )
4022  maxval = MAX(maxval, -by / axy);
4023  else if( ay * axy < 0.0 )
4024  maxval = infinity;
4025  }
4026  else
4027  {
4028  val = (c - ay * ybnds.sup * ybnds.sup - by * ybnds.sup) / (bx + axy * ybnds.sup);
4029  maxval = MAX(val, maxval);
4030  }
4031 
4032  if( !EPSZ(ay, 1e-9) )
4033  {
4034  d = ay * (ay * bx * bx - axy * (bx * by + axy * c));
4035  if( !EPSN(d, 1e-9) )
4036  {
4037  ymin = ay * bx + sqrt(MAX(d, 0.0));
4038  ymin /= axy * ay;
4039 
4040  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4041  maxval = MAX(val, maxval);
4042 
4043  ymin = ay * bx - sqrt(MAX(d, 0.0));
4044  ymin /= axy * ay;
4045 
4046  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4047  maxval = MAX(val, maxval);
4048  }
4049  }
4050  }
4051  else
4052  {
4053  maxval = infinity;
4054  }
4055 
4056  if( minval > -infinity )
4057  resultant->inf = minval - 1e-10 * REALABS(minval);
4058  else
4059  resultant->inf = -infinity;
4060  if( maxval < infinity )
4061  resultant->sup = maxval + 1e-10 * REALABS(maxval);
4062  else
4063  resultant->sup = infinity;
4064  SCIPintervalIntersect(resultant, *resultant, xbnds);
4065  }
4066 }
4067