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