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