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