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