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-2018 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 ROUNDING_FE
37 #define ROUNDING
38 /*
39  * Linux rounding operations
40  */
41 
42 #include <fenv.h>
43 
44 /** Linux rounding mode settings */
45 #define SCIP_ROUND_DOWNWARDS FE_DOWNWARD /**< round always down */
46 #define SCIP_ROUND_UPWARDS FE_UPWARD /**< round always up */
47 #define SCIP_ROUND_NEAREST FE_TONEAREST /**< round always to nearest */
48 #define SCIP_ROUND_ZERO FE_TOWARDZERO /**< round always towards 0.0 */
49 
50 /** returns whether rounding mode control is available */
52  void
53  )
54 {
55  return TRUE;
56 }
57 
58 /** sets rounding mode of floating point operations */
60  SCIP_ROUNDMODE roundmode /**< rounding mode to activate */
61  )
62 {
63  if( fesetround(roundmode) != 0 )
64  {
65  SCIPerrorMessage("error setting rounding mode to %d\n", roundmode);
66  abort();
67  }
68 }
69 
70 /** gets current rounding mode of floating point operations */
72  void
73  )
74 {
75  return (SCIP_ROUNDMODE)fegetround();
76 }
77 
78 #endif
79 
80 
81 
82 #ifdef ROUNDING_FP
83 #define ROUNDING
84 /*
85  * OSF rounding operations
86  */
87 
88 #include <float.h>
89 
90 /** OSF rounding mode settings */
91 #define SCIP_ROUND_DOWNWARDS FP_RND_RM /**< round always down */
92 #define SCIP_ROUND_UPWARDS FP_RND_RP /**< round always up */
93 #define SCIP_ROUND_NEAREST FP_RND_RN /**< round always to nearest */
94 #define SCIP_ROUND_ZERO FP_RND_RZ /**< round always towards 0.0 */
95 
96 /** returns whether rounding mode control is available */
98  void
99  )
100 {
101  return TRUE;
102 }
103 
104 /** sets rounding mode of floating point operations */
106  SCIP_ROUNDMODE roundmode /**< rounding mode to activate */
107  )
108 {
109  if( write_rnd(roundmode) != 0 )
110  {
111  SCIPerrorMessage("error setting rounding mode to %d\n", roundmode);
112  abort();
113  }
114 }
115 
116 /** gets current rounding mode of floating point operations */
118  void
119  )
120 {
121  return read_rnd();
122 }
123 
124 #endif
125 
126 
127 
128 #ifdef ROUNDING_MS
129 #define ROUNDING
130 /*
131  * Microsoft compiler rounding operations
132  */
133 
134 #include <float.h>
135 
136 /** Microsoft rounding mode settings */
137 #define SCIP_ROUND_DOWNWARDS RC_DOWN /**< round always down */
138 #define SCIP_ROUND_UPWARDS RC_UP /**< round always up */
139 #define SCIP_ROUND_NEAREST RC_NEAR /**< round always to nearest */
140 #define SCIP_ROUND_ZERO RC_CHOP /**< round always towards zero */
141 
142 /** returns whether rounding mode control is available */
144  void
145  )
146 {
147  return TRUE;
148 }
149 
150 /** sets rounding mode of floating point operations */
152  SCIP_ROUNDMODE roundmode /**< rounding mode to activate */
153  )
154 {
155  if( (_controlfp(roundmode, _MCW_RC) & _MCW_RC) != roundmode )
156  {
157  SCIPerrorMessage("error setting rounding mode to %x\n", roundmode);
158  abort();
159  }
160 }
161 
162 /** gets current rounding mode of floating point operations */
164  void
165  )
166 {
167  return _controlfp(0, 0) & _MCW_RC;
168 }
169 #endif
170 
171 
172 
173 #ifndef ROUNDING
174 /*
175  * rouding operations not available
176  */
177 #define SCIP_ROUND_DOWNWARDS 0 /**< round always down */
178 #define SCIP_ROUND_UPWARDS 1 /**< round always up */
179 #define SCIP_ROUND_NEAREST 2 /**< round always to nearest */
180 #define SCIP_ROUND_ZERO 3 /**< round always towards zero */
181 
182 /** returns whether rounding mode control is available */
184  void
185  )
186 {
187  return FALSE;
188 }
189 
190 /** sets rounding mode of floating point operations */
192  SCIP_ROUNDMODE roundmode /**< rounding mode to activate */
193  )
194 { /*lint --e{715}*/
195  SCIPerrorMessage("setting rounding mode not available - interval arithmetic is invalid!\n");
196 }
197 
198 /** gets current rounding mode of floating point operations */
200  void
201  )
202 {
203  return SCIP_ROUND_NEAREST;
204 }
205 #else
206 #undef ROUNDING
207 #endif
208 
209 
210 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) /* gcc or icc compiler on x86 32bit or 64bit */
211 
212 /** gets the negation of a double
213  * Do this in a way that the compiler does not "optimize" it away, which usually does not considers rounding modes.
214  * However, compiling with -frounding-math would allow to return -x here.
215  */
216 static
217 double negate(
218  /* we explicitely use double here, since I'm not sure the assembler code would work as it for other float's */
219  double x /**< number that should be negated */
220  )
221 {
222  /* The following line of code is taken from GAOL, http://sourceforge.net/projects/gaol. */
223  __asm volatile ("fldl %1; fchs; fstpl %0" : "=m" (x) : "m" (x));
224  return x;
225 }
226 
227 /* cl or icl compiler on 32bit windows or icl compiler on 64bit windows
228  * cl on 64bit windows does not seem to support inline assembler
229  */
230 #elif defined(_MSC_VER) && (defined(__INTEL_COMPILER) || !defined(_M_X64))
231 
232 /** gets the negation of a double
233  * Do this in a way that the compiler does not "optimize" it away, which usually does not considers rounding modes.
234  */
235 static
236 double negate(
237  /* we explicitely use double here, since I'm not sure the assembler code would work as it for other float's */
238  double x /**< number that should be negated */
239  )
240 {
241  /* The following lines of code are taken from GAOL, http://sourceforge.net/projects/gaol. */
242  __asm {
243  fld x
244  fchs
245  fstp x
246  }
247  return x;
248 }
249 
250 #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  SCIPintervalSolveUnivariateQuadExpressionPositiveAllScalar(infinity, &res2, sqrcoeff.sup, lincoeff.sup, rhs.inf, xbnds);
2888  SCIPdebugMessage("solve %g*x^2 + %g*x >= %g gives [%.20f, %.20f]\n", sqrcoeff.sup, lincoeff.sup, rhs.inf, res2.inf, res2.sup);
2889  SCIPdebugMessage("intersection of [%.20f, %.20f] and [%.20f, %.20f]", resultant->inf, resultant->sup, res2.inf, res2.sup);
2890  /* intersect both results */
2891  SCIPintervalIntersect(resultant, *resultant, res2);
2892  SCIPdebugPrintf(" gives [%.20f, %.20f]\n", resultant->inf, resultant->sup);
2893  }
2894  /* else res2 = [0, infty] */
2895 
2896  if( resultant->inf >= infinity || resultant->sup <= -infinity )
2897  {
2898  SCIPintervalSetEmpty(resultant);
2899  }
2900 }
2901 
2902 /** computes interval with negative solutions of a quadratic equation with interval coefficients
2903  *
2904  * 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.
2905  */
2907  SCIP_Real infinity, /**< value for infinity */
2908  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2909  SCIP_INTERVAL sqrcoeff, /**< coefficient of x^2 */
2910  SCIP_INTERVAL lincoeff, /**< coefficient of x */
2911  SCIP_INTERVAL rhs, /**< right hand side of equation */
2912  SCIP_INTERVAL xbnds /**< bounds on x */
2913  )
2914 {
2915  SCIP_Real tmp;
2916 
2917  /* change in variables y = -x, thus get all positive solutions of
2918  * a * y^2 + (-b) * y in c with -xbnds as bounds on y
2919  */
2920 
2921  tmp = lincoeff.inf;
2922  lincoeff.inf = -lincoeff.sup;
2923  lincoeff.sup = -tmp;
2924 
2925  tmp = xbnds.inf;
2926  xbnds.inf = -xbnds.sup;
2927  xbnds.sup = -tmp;
2928 
2929  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, resultant, sqrcoeff, lincoeff, rhs, xbnds);
2930 
2931  tmp = resultant->inf;
2932  resultant->inf = -resultant->sup;
2933  resultant->sup = -tmp;
2934 }
2935 
2936 
2937 /** computes positive solutions of a quadratic equation with scalar coefficients
2938  *
2939  * 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.
2940  * Implements Algorithm 3.2 from Domes and Neumaier: Constraint propagation on quadratic constraints (2008).
2941  */
2943  SCIP_Real infinity, /**< value for infinity */
2944  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2945  SCIP_Real sqrcoeff, /**< coefficient of x^2 */
2946  SCIP_Real lincoeff, /**< coefficient of x */
2947  SCIP_Real rhs, /**< right hand side of equation */
2948  SCIP_INTERVAL xbnds /**< bounds on x */
2949  )
2950 {
2951  SCIP_ROUNDMODE roundmode;
2952  SCIP_Real b;
2953  SCIP_Real delta;
2954  SCIP_Real z;
2955 
2956  assert(resultant != NULL);
2957  assert(sqrcoeff < infinity);
2958  assert(sqrcoeff > -infinity);
2959 
2960  if( sqrcoeff == 0.0 )
2961  {
2962  /* special handling for linear b * x >= c
2963  *
2964  * The non-negative solutions here are:
2965  * b < 0, c <= 0 : [0, c/b]
2966  * b <= 0, c > 0 : empty
2967  * b > 0, c > 0 : [c/b, infty]
2968  * b >= 0, c <= 0 : [0, infty]
2969  *
2970  * The same should have been computed below, but without the sqrcoeff, terms simplify (thus, also less rounding).
2971  */
2972 
2973  if( lincoeff <= 0.0 && rhs > 0.0 )
2974  {
2975  SCIPintervalSetEmpty(resultant);
2976  return;
2977  }
2978 
2979  if( lincoeff >= 0.0 && rhs <= 0.0 )
2980  {
2981  /* [0,infty] cap xbnds */
2982  resultant->inf = MAX(0.0, xbnds.inf);
2983  resultant->sup = xbnds.sup;
2984  return;
2985  }
2986 
2987  roundmode = SCIPintervalGetRoundingMode();
2988 
2989  if( lincoeff < 0.0 && rhs <= 0.0 )
2990  {
2991  /* [0,c/b] cap xbnds */
2992  resultant->inf = MAX(0.0, xbnds.inf);
2993 
2995  resultant->sup = rhs / lincoeff;
2996  if( xbnds.sup < resultant->sup )
2997  resultant->sup = xbnds.sup;
2998  }
2999  else
3000  {
3001  assert(lincoeff > 0.0);
3002  assert(rhs > 0.0);
3003 
3004  /* [c/b, infty] cap xbnds */
3005 
3007  resultant->inf = rhs / lincoeff;
3008  if( resultant->inf < xbnds.inf )
3009  resultant->inf = xbnds.inf;
3010 
3011  resultant->sup = xbnds.sup;
3012  }
3013 
3014  SCIPintervalSetRoundingMode(roundmode);
3015 
3016  return;
3017  }
3018 
3019  resultant->inf = 0.0;
3020  resultant->sup = infinity;
3021 
3022  roundmode = SCIPintervalGetRoundingMode();
3023 
3024  /* this should actually be round_upwards, but unless lincoeff is min_double,
3025  * there shouldn't be any rounding happening when dividing by 2, i.e., shifting exponent,
3026  * so it is ok to not change the rounding mode here
3027  */
3028  b = lincoeff / 2.0;
3029 
3030  if( lincoeff >= 0.0 )
3031  { /* b >= 0.0 */
3032  if( rhs > 0.0 )
3033  { /* b >= 0.0 and c > 0.0 */
3035  delta = b*b + sqrcoeff*rhs;
3036  if( delta < 0.0 )
3037  {
3038  SCIPintervalSetEmpty(resultant);
3039  }
3040  else
3041  {
3043  z = SCIPnextafter(sqrt(delta), SCIP_REAL_MAX);
3045  z += b;
3046  resultant->inf = negate(negate(rhs)/z);
3047  if( sqrcoeff < 0.0 )
3048  resultant->sup = z / negate(sqrcoeff);
3049  }
3050  }
3051  else
3052  { /* b >= 0.0 and c <= 0.0 */
3053  if( sqrcoeff < 0.0 )
3054  {
3056  delta = b*b + sqrcoeff*rhs;
3058  z = SCIPnextafter(sqrt(delta), SCIP_REAL_MAX);
3060  z += b;
3061  resultant->sup = z / negate(sqrcoeff);
3062  }
3063  }
3064  }
3065  else
3066  { /* b < 0.0 */
3067  if( rhs > 0.0 )
3068  { /* b < 0.0 and c > 0.0 */
3069  if( sqrcoeff > 0.0 )
3070  {
3072  delta = b*b + sqrcoeff*rhs;
3074  z = SCIPnextafter(sqrt(delta), SCIP_REAL_MIN);
3076  z += negate(b);
3077  resultant->inf = z / sqrcoeff;
3078  }
3079  else
3080  {
3081  SCIPintervalSetEmpty(resultant);
3082  }
3083  }
3084  else
3085  { /* b < 0.0 and c <= 0.0 */
3087  delta = b*b + sqrcoeff * rhs;
3088  if( delta >= 0.0 )
3089  {
3090  /* let resultant = [0,-c/z] for now */
3092  z = SCIPnextafter(sqrt(delta), SCIP_REAL_MIN);
3093  /* continue with downward rounding, because we want z (>= 0) to be small,
3094  * because -rhs/z needs to be large (-rhs >= 0)
3095  */
3097  z += negate(b);
3098  /* also now compute rhs/z with downward rounding, so that -(rhs/z) becomes large */
3099  resultant->sup = negate(rhs/z);
3100 
3101  if( sqrcoeff > 0.0 )
3102  {
3103  /* for a > 0, the result is [0,-c/z] \vee [z/a,infinity]
3104  * currently, resultant = [0,-c/z]
3105  */
3106  SCIP_Real zdiva;
3107 
3108  zdiva = z/sqrcoeff;
3109 
3110  if( xbnds.sup < zdiva )
3111  {
3112  /* after intersecting with xbnds, result is [0,-c/z], so we are done */
3113  }
3114  else if( xbnds.inf > resultant->sup )
3115  {
3116  /* after intersecting with xbnds, result is [z/a,infinity] */
3117  resultant->inf = zdiva;
3118  resultant->sup = infinity;
3119  }
3120  else
3121  {
3122  /* after intersecting with xbnds we can neither exclude [0,-c/z] nor [z/a,infinity],
3123  * so put resultant = [0,infinity] (intersection with xbnds happens below)
3124  * @todo we could create a hole here
3125  */
3126  resultant->sup = infinity;
3127  }
3128  }
3129  else
3130  {
3131  /* for a < 0, the result is [0,-c/z], so we are done */
3132  }
3133  }
3134  }
3135  }
3136 
3137  SCIPintervalIntersect(resultant, *resultant, xbnds);
3138 
3139  SCIPintervalSetRoundingMode(roundmode);
3140 }
3141 
3142 /** solves a quadratic equation with interval coefficients
3143  *
3144  * 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
3145  */
3147  SCIP_Real infinity, /**< value for infinity */
3148  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
3149  SCIP_INTERVAL sqrcoeff, /**< coefficient of x^2 */
3150  SCIP_INTERVAL lincoeff, /**< coefficient of x */
3151  SCIP_INTERVAL rhs, /**< right hand side of equation */
3152  SCIP_INTERVAL xbnds /**< bounds on x */
3153  )
3154 {
3155  SCIP_INTERVAL xpos;
3156  SCIP_INTERVAL xneg;
3157 
3158  assert(resultant != NULL);
3159  assert(!SCIPintervalIsEmpty(infinity, sqrcoeff));
3160  assert(!SCIPintervalIsEmpty(infinity, lincoeff));
3161  assert(!SCIPintervalIsEmpty(infinity, rhs));
3162 
3163  /* special handling for lincoeff * x = rhs without 0 in lincoeff
3164  * rhs/lincoeff gives a good interval that we just have to intersect with xbnds
3165  * 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)
3166  */
3167  if( sqrcoeff.inf == 0.0 && sqrcoeff.sup == 0.0 && (lincoeff.inf > 0.0 || lincoeff.sup < 0.0) )
3168  {
3169  SCIPintervalDiv(infinity, resultant, rhs, lincoeff);
3170  SCIPintervalIntersect(resultant, *resultant, xbnds);
3171  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);
3172  return;
3173  }
3174 
3175  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);
3176 
3177  /* find all x>=0 such that a*x^2+b*x = c */
3178  if( xbnds.sup >= 0 )
3179  {
3180  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &xpos, sqrcoeff, lincoeff, rhs, xbnds);
3181  SCIPdebugMessage(" solutions of [%g,%g]*x^2 + [%g,%g]*x in [%g,%g] for x in [%g,%g] are [%.20g,%.20g]\n",
3182  sqrcoeff.inf, sqrcoeff.sup, lincoeff.inf, lincoeff.sup, rhs.inf, rhs.sup, MAX(xbnds.inf, 0.0), xbnds.sup, xpos.inf, xpos.sup);
3183  }
3184  else
3185  {
3186  SCIPintervalSetEmpty(&xpos);
3187  }
3188 
3189  /* find all x<=0 such that a*x^2-b*x = c */
3190  if( xbnds.inf <= 0.0 )
3191  {
3192  SCIPintervalSolveUnivariateQuadExpressionNegative(infinity, &xneg, sqrcoeff, lincoeff, rhs, xbnds);
3193  SCIPdebugMessage(" solutions of [%g,%g]*x^2 + [%g,%g]*x in [%g,%g] for x in [%g,%g] are [%g,%g]\n",
3194  sqrcoeff.inf, sqrcoeff.sup, lincoeff.inf, lincoeff.sup, rhs.inf, rhs.sup, xbnds.inf, MIN(xbnds.sup, 0.0), xneg.inf, xneg.sup);
3195  }
3196  else
3197  {
3198  SCIPintervalSetEmpty(&xneg);
3199  }
3200 
3201  SCIPintervalUnify(resultant, xpos, xneg);
3202  SCIPdebugMessage(" unify gives [%g,%g]\n", SCIPintervalGetInf(*resultant), SCIPintervalGetSup(*resultant));
3203 }
3204 
3205 /** stores range of bivariate quadratic term in resultant
3206  * 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$
3207  * NOTE: the operations are not applied rounding-safe here
3208  */
3210  SCIP_Real infinity, /**< value for infinity in interval arithmetics */
3211  SCIP_INTERVAL* resultant, /**< buffer where to store result of operation */
3212  SCIP_Real ax, /**< square coefficient of x */
3213  SCIP_Real ay, /**< square coefficient of y */
3214  SCIP_Real axy, /**< bilinear coefficients */
3215  SCIP_Real bx, /**< linear coefficient of x */
3216  SCIP_Real by, /**< linear coefficient of y */
3217  SCIP_INTERVAL xbnds, /**< bounds on x */
3218  SCIP_INTERVAL ybnds /**< bounds on y */
3219  )
3220 {
3221  /* we use double double precision and finally widen the computed range by 1e-8% to compensate for not computing rounding-safe here */
3222  SCIP_Real minval;
3223  SCIP_Real maxval;
3224  SCIP_Real val;
3225  SCIP_Real x;
3226  SCIP_Real y;
3227  SCIP_Real denom;
3228 
3229  assert(resultant != NULL);
3230  assert(xbnds.inf <= xbnds.sup);
3231  assert(ybnds.inf <= ybnds.sup);
3232 
3233  /* if we are separable, then fall back to use SCIPintervalQuad two times and add */
3234  if( axy == 0.0 )
3235  {
3236  SCIP_INTERVAL tmp;
3237 
3238  SCIPintervalSet(&tmp, bx);
3239  SCIPintervalQuad(infinity, resultant, ax, tmp, xbnds);
3240 
3241  SCIPintervalSet(&tmp, by);
3242  SCIPintervalQuad(infinity, &tmp, ay, tmp, ybnds);
3243 
3244  SCIPintervalAdd(infinity, resultant, *resultant, tmp);
3245 
3246  return;
3247  }
3248 
3249  SCIPintervalSet(resultant, 0.0);
3250 
3251  minval = infinity;
3252  maxval = -infinity;
3253 
3254  /* check minima/maxima of expression */
3255  denom = 4.0 * ax * ay - axy * axy;
3256  if( REALABS(denom) > 1e-9 )
3257  {
3258  x = (axy * by - 2.0 * ay * bx) / denom;
3259  y = (axy * bx - 2.0 * ax * by) / denom;
3260  if( xbnds.inf <= x && x <= xbnds.sup && ybnds.inf <= y && y <= ybnds.sup )
3261  {
3262  val = (axy * bx * by - ay * bx * bx - ax * by * by) / denom;
3263  minval = MIN(val, minval);
3264  maxval = MAX(val, maxval);
3265  }
3266  }
3267  else if( REALABS(2.0 * ay * bx - axy * by) <= 1e-9 )
3268  {
3269  /* The whole line (x, -bx/axy - (axy/2ay) x) defines an extreme point with value -ay bx^2 / axy^2
3270  * If x is unbounded, then there is an (x,y) with y in ybnds where the extreme value is assumed.
3271  * 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.
3272  */
3273  if( xbnds.inf <= -infinity && xbnds.sup >= infinity )
3274  {
3275  val = -ay * bx * bx / (axy * axy);
3276  minval = MIN(val, minval);
3277  maxval = MAX(val, maxval);
3278  }
3279  }
3280 
3281  /* check boundary of box xbnds x ybnds */
3282 
3283  if( xbnds.inf <= -infinity )
3284  {
3285  /* check value for x -> -infinity */
3286  if( ax > 0.0 )
3287  maxval = infinity;
3288  else if( ax < 0.0 )
3289  minval = -infinity;
3290  else if( ax == 0.0 )
3291  {
3292  /* bivar(x,y) tends to -(bx+axy y) * infinity */
3293 
3294  if( ybnds.inf <= -infinity )
3295  val = (axy < 0.0 ? -infinity : infinity);
3296  else if( bx + axy * ybnds.inf < 0.0 )
3297  val = infinity;
3298  else
3299  val = -infinity;
3300  minval = MIN(val, minval);
3301  maxval = MAX(val, maxval);
3302 
3303  if( ybnds.sup >= infinity )
3304  val = (axy < 0.0 ? infinity : -infinity);
3305  else if( bx + axy * ybnds.sup < 0.0 )
3306  val = infinity;
3307  else
3308  val = -infinity;
3309  minval = MIN(val, minval);
3310  maxval = MAX(val, maxval);
3311  }
3312  }
3313  else
3314  {
3315  /* get range of bivar(xbnds.inf, y) for y in ybnds */
3316  SCIP_INTERVAL tmp;
3317  SCIP_INTERVAL ycoef;
3318 
3319  SCIPintervalSet(&ycoef, axy * xbnds.inf + by);
3320  SCIPintervalQuad(infinity, &tmp, ay, ycoef, ybnds);
3321  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ax * xbnds.inf * xbnds.inf + bx * xbnds.inf));
3322  minval = MIN(tmp.inf, minval);
3323  maxval = MAX(tmp.sup, maxval);
3324  }
3325 
3326  if( xbnds.sup >= infinity )
3327  {
3328  /* check value for x -> infinity */
3329  if( ax > 0.0 )
3330  maxval = infinity;
3331  else if( ax < 0.0 )
3332  minval = -infinity;
3333  else if( ax == 0.0 )
3334  {
3335  /* bivar(x,y) tends to (bx+axy y) * infinity */
3336 
3337  if( ybnds.inf <= -infinity )
3338  val = (axy > 0.0 ? -infinity : infinity);
3339  else if( bx + axy * ybnds.inf > 0.0 )
3340  val = infinity;
3341  else
3342  val = -infinity;
3343  minval = MIN(val, minval);
3344  maxval = MAX(val, maxval);
3345 
3346  if( ybnds.sup >= infinity )
3347  val = (axy > 0.0 ? infinity : -infinity);
3348  else if( bx + axy * ybnds.sup > 0.0 )
3349  val = infinity;
3350  else
3351  val = -infinity;
3352  minval = MIN(val, minval);
3353  maxval = MAX(val, maxval);
3354  }
3355  }
3356  else
3357  {
3358  /* get range of bivar(xbnds.sup, y) for y in ybnds */
3359  SCIP_INTERVAL tmp;
3360  SCIP_INTERVAL ycoef;
3361 
3362  SCIPintervalSet(&ycoef, axy * xbnds.sup + by);
3363  SCIPintervalQuad(infinity, &tmp, ay, ycoef, ybnds);
3364  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ax * xbnds.sup * xbnds.sup + bx * xbnds.sup));
3365  minval = MIN(tmp.inf, minval);
3366  maxval = MAX(tmp.sup, maxval);
3367  }
3368 
3369  if( ybnds.inf <= -infinity )
3370  {
3371  /* check value for y -> -infinity */
3372  if( ay > 0.0 )
3373  maxval = infinity;
3374  else if( ay < 0.0 )
3375  minval = -infinity;
3376  else if( ay == 0.0 )
3377  {
3378  /* bivar(x,y) tends to -(by+axy x) * infinity */
3379 
3380  if( xbnds.inf <= -infinity )
3381  val = (axy < 0.0 ? -infinity : infinity);
3382  else if( by + axy * xbnds.inf < 0.0 )
3383  val = infinity;
3384  else
3385  val = -infinity;
3386  minval = MIN(val, minval);
3387  maxval = MAX(val, maxval);
3388 
3389  if( xbnds.sup >= infinity )
3390  val = (axy < 0.0 ? infinity : -infinity);
3391  else if( by + axy * xbnds.sup < 0.0 )
3392  val = infinity;
3393  else
3394  val = -infinity;
3395  minval = MIN(val, minval);
3396  maxval = MAX(val, maxval);
3397  }
3398  }
3399  else
3400  {
3401  /* get range of bivar(x, ybnds.inf) for x in xbnds */
3402  SCIP_INTERVAL tmp;
3403  SCIP_INTERVAL xcoef;
3404 
3405  SCIPintervalSet(&xcoef, axy * ybnds.inf + bx);
3406  SCIPintervalQuad(infinity, &tmp, ax, xcoef, xbnds);
3407  SCIPintervalAddScalar(infinity, &tmp, tmp, ay * ybnds.inf * ybnds.inf + by * ybnds.inf);
3408  minval = MIN(tmp.inf, minval);
3409  maxval = MAX(tmp.sup, maxval);
3410  }
3411 
3412  if( ybnds.sup >= infinity )
3413  {
3414  /* check value for y -> infinity */
3415  if( ay > 0.0 )
3416  maxval = infinity;
3417  else if( ay < 0.0 )
3418  minval = -infinity;
3419  else if( ay == 0.0 )
3420  {
3421  /* bivar(x,y) tends to (by+axy x) * infinity */
3422 
3423  if( xbnds.inf <= -infinity )
3424  val = (axy > 0.0 ? -infinity : infinity);
3425  else if( by + axy * xbnds.inf > 0.0 )
3426  val = infinity;
3427  else
3428  val = -infinity;
3429  minval = MIN(val, minval);
3430  maxval = MAX(val, maxval);
3431 
3432  if( xbnds.sup >= infinity )
3433  val = (axy > 0.0 ? infinity : -infinity);
3434  else if( by + axy * xbnds.sup > 0.0 )
3435  val = infinity;
3436  else
3437  val = -infinity;
3438  minval = MIN(val, minval);
3439  maxval = MAX(val, maxval);
3440  }
3441  }
3442  else
3443  {
3444  /* get range of bivar(x, ybnds.sup) for x in xbnds */
3445  SCIP_INTERVAL tmp;
3446  SCIP_INTERVAL xcoef;
3447 
3448  SCIPintervalSet(&xcoef, axy * ybnds.sup + bx);
3449  SCIPintervalQuad(infinity, &tmp, ax, xcoef, xbnds);
3450  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ay * ybnds.sup * ybnds.sup + by * ybnds.sup));
3451  minval = MIN(tmp.inf, minval);
3452  maxval = MAX(tmp.sup, maxval);
3453  }
3454 
3455  minval -= 1e-10 * REALABS(minval);
3456  maxval += 1e-10 * REALABS(maxval);
3457  SCIPintervalSetBounds(resultant, (SCIP_Real)minval, (SCIP_Real)maxval);
3458 
3459  SCIPdebugMessage("range for %gx^2 + %gy^2 + %gxy + %gx + %gy = [%g, %g] for x = [%g, %g], y=[%g, %g]\n",
3460  ax, ay, axy, bx, by, minval, maxval, xbnds.inf, xbnds.sup, ybnds.inf, ybnds.sup);
3461 }
3462 
3463 /** solves a bivariate quadratic equation for the first variable
3464  * given scalars ax, ay, axy, bx and by, and intervals for x, y, and rhs,
3465  * 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$
3466  * NOTE: the operations are not applied rounding-safe here
3467  */
3469  SCIP_Real infinity, /**< value for infinity in interval arithmetics */
3470  SCIP_INTERVAL* resultant, /**< buffer where to store result of operation */
3471  SCIP_Real ax, /**< square coefficient of x */
3472  SCIP_Real ay, /**< square coefficient of y */
3473  SCIP_Real axy, /**< bilinear coefficients */
3474  SCIP_Real bx, /**< linear coefficient of x */
3475  SCIP_Real by, /**< linear coefficient of y */
3476  SCIP_INTERVAL rhs, /**< right-hand-side of equation */
3477  SCIP_INTERVAL xbnds, /**< bounds on x */
3478  SCIP_INTERVAL ybnds /**< bounds on y */
3479  )
3480 {
3481  /* we use double double precision and finally widen the computed range by 1e-8% to compensate for not computing rounding-safe here */
3482  SCIP_Real val;
3483 
3484  assert(resultant != NULL);
3485 
3486  if( axy == 0.0 )
3487  {
3488  /* if axy == 0, fall back to SCIPintervalSolveUnivariateQuadExpression */
3489  SCIP_INTERVAL ytermrng;
3490  SCIP_INTERVAL sqrcoef;
3491  SCIP_INTERVAL lincoef;
3492  SCIP_INTERVAL pos;
3493  SCIP_INTERVAL neg;
3494 
3495  SCIPintervalSet(&lincoef, by);
3496  SCIPintervalQuad(infinity, &ytermrng, ay, lincoef, ybnds);
3497  SCIPintervalSub(infinity, &rhs, rhs, ytermrng);
3498 
3499  SCIPintervalSet(&sqrcoef, ax);
3500 
3501  /* get positive solutions, if of interest */
3502  if( xbnds.sup >= 0.0 )
3503  {
3504  SCIPintervalSet(&lincoef, bx);
3505  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &pos, sqrcoef, lincoef, rhs, xbnds);
3506  }
3507  else
3508  SCIPintervalSetEmpty(&pos);
3509 
3510  /* get negative solutions, if of interest */
3511  if( xbnds.inf < 0.0 )
3512  {
3513  SCIP_INTERVAL xbndsneg;
3514  SCIPintervalSet(&lincoef, -bx);
3515  SCIPintervalSetBounds(&xbndsneg, -xbnds.sup, -xbnds.inf);
3516  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &neg, sqrcoef, lincoef, rhs, xbndsneg);
3517  if( !SCIPintervalIsEmpty(infinity, neg) )
3518  SCIPintervalSetBounds(&neg, -neg.sup, -neg.inf);
3519  }
3520  else
3521  SCIPintervalSetEmpty(&neg);
3522 
3523  SCIPintervalUnify(resultant, pos, neg);
3524 
3525  return;
3526  }
3527 
3528  if( ybnds.inf <= -infinity || ybnds.sup >= infinity )
3529  {
3530  /* the code below is buggy if y is unbounded, see #2250
3531  * 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
3532  */
3533  SCIP_INTERVAL ax_;
3534  SCIP_INTERVAL bx_;
3535  SCIP_INTERVAL ycoef;
3536  SCIP_INTERVAL ytermbounds;
3537 
3538  *resultant = xbnds;
3539 
3540  /* nothing we can do here if x is unbounded (we have a_xy != 0 here) */
3541  if( xbnds.inf <= -infinity && xbnds.sup >= infinity )
3542  return;
3543 
3544  /* ycoef = axy xbnds + by */
3545  SCIPintervalMulScalar(infinity, &ycoef, xbnds, axy);
3546  SCIPintervalAddScalar(infinity, &ycoef, ycoef, by);
3547 
3548  /* get bounds on ay y^2 + (axy xbnds + by) y */
3549  SCIPintervalQuad(infinity, &ytermbounds, ay, ycoef, ybnds);
3550 
3551  /* now solve ax x^2 + bx x in rhs - ytermbounds */
3552  SCIPintervalSet(&ax_, ax);
3553  SCIPintervalSet(&bx_, bx);
3554  SCIPintervalSub(infinity, &rhs, rhs, ytermbounds);
3555  SCIPintervalSolveUnivariateQuadExpression(infinity, resultant, ax_, bx_, rhs, xbnds);
3556 
3557  return;
3558  }
3559 
3560  if( ax < 0.0 )
3561  {
3562  SCIP_Real tmp;
3563  tmp = rhs.inf;
3564  rhs.inf = -rhs.sup;
3565  rhs.sup = -tmp;
3566 
3567  SCIPintervalSolveBivariateQuadExpressionAllScalar(infinity, resultant, -ax, -ay, -axy, -bx, -by, rhs, xbnds, ybnds);
3568  return;
3569  }
3570  assert(ax >= 0.0);
3571 
3572  *resultant = xbnds;
3573 
3574  if( ax > 0.0 )
3575  {
3576  SCIP_Real sqrtax;
3577  SCIP_Real minvalleft;
3578  SCIP_Real maxvalleft;
3579  SCIP_Real minvalright;
3580  SCIP_Real maxvalright;
3581  SCIP_Real ymin;
3582  SCIP_Real rcoef_y;
3583  SCIP_Real rcoef_yy;
3584  SCIP_Real rcoef_const;
3585 
3586  sqrtax = sqrt(ax);
3587 
3588  /* rewrite equation as (sqrt(ax)x + b(y))^2 \in r(rhs,y), where
3589  * b(y) = (bx + axy y)/(2sqrt(ax)), r(rhs,y) = rhs - ay y^2 - by y + b(y)^2
3590  *
3591  * -> r(rhs,y) = bx^2/(4ax) + rhs + (axy bx/(2ax) - by)*y + (axy^2/(4ax) - ay)*y^2
3592  */
3593  rcoef_y = axy * bx / (2.0*ax) - by;
3594  rcoef_yy = axy * axy / (4.0*ax) - ay;
3595  rcoef_const = bx * bx / (4.0*ax);
3596 
3597 #define CALCB(y) ((bx + axy * (y)) / (2.0 * sqrtax))
3598 #define CALCR(c,y) (rcoef_const + (c) + (rcoef_y + rcoef_yy * (y)) * (y))
3599 
3600  /* check whether r(rhs,y) is always negative */
3601  if( rhs.sup < infinity )
3602  {
3603  SCIP_INTERVAL ycoef;
3604  SCIP_Real ub;
3605 
3606  SCIPintervalSet(&ycoef, (SCIP_Real)rcoef_y);
3607  ub = (SCIP_Real)(SCIPintervalQuadUpperBound(infinity, (SCIP_Real)rcoef_yy, ycoef, ybnds) + rhs.sup + rcoef_const);
3608 
3609  if( EPSN(ub, 1e-9) )
3610  {
3611  SCIPintervalSetEmpty(resultant);
3612  return;
3613  }
3614  else if( ub < 0.0 )
3615  {
3616  /* 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
3617  * thus, we relax rhs a be feasible a bit (-ub would be sufficient, but that would put us exactly onto the boundary)
3618  * see also #1861
3619  */
3620  rhs.sup += -2.0*ub;
3621  }
3622  }
3623 
3624  /* we have sqrt(ax)x \in (-sqrt(r(rhs,y))-b(y)) \cup (sqrt(r(rhs,y))-b(y))
3625  * compute minima and maxima of both functions such that
3626  *
3627  * [minvalleft, maxvalleft ] = -sqrt(r(rhs,y))-b(y)
3628  * [minvalright, maxvalright] = sqrt(r(rhs,y))-b(y)
3629  */
3630 
3631  minvalleft = infinity;
3632  maxvalleft = -infinity;
3633  minvalright = infinity;
3634  maxvalright = -infinity;
3635 
3636  if( rhs.sup >= infinity )
3637  {
3638  /* we can't do much if rhs.sup is infinite
3639  * but we may do a bit of xbnds isn't too huge and rhs.inf > -infinity
3640  */
3641  minvalleft = -infinity;
3642  maxvalright = infinity;
3643  }
3644 
3645  /* evaluate at lower bound of y, as long as r(rhs,ylb) > 0 */
3646  if( ybnds.inf <= -infinity )
3647  {
3648  /* check limit of +/-sqrt(r(rhs,y))-b(y) for y -> -infty */
3649  if( !EPSZ(ay, 1e-9) && axy * axy >= 4.0 * ax * ay )
3650  {
3651  if( axy < 0.0 )
3652  {
3653  minvalleft = -infinity;
3654 
3655  if( ay > 0.0 )
3656  minvalright = -infinity;
3657  else
3658  maxvalright = infinity;
3659  }
3660  else
3661  {
3662  maxvalright = infinity;
3663 
3664  if( ay > 0.0 )
3665  maxvalleft = infinity;
3666  else
3667  minvalleft = -infinity;
3668  }
3669  }
3670  else if( !EPSZ(ay, 1e-9) )
3671  {
3672  /* here axy * axy < 4 * ax * ay, so need to check for zeros of r(rhs,y), which is done below */
3673  }
3674  else
3675  {
3676  /* here ay = 0.0, which gives a limit of -by/2 for -sqrt(r(rhs,y))-b(y) */
3677  minvalleft = -by / 2.0;
3678  maxvalleft = -by / 2.0;
3679  /* here ay = 0.0, which gives a limit of +infinity for sqrt(r(rhs,y))-b(y) */
3680  maxvalright = infinity;
3681  }
3682  }
3683  else
3684  {
3685  SCIP_Real b;
3686  SCIP_Real c;
3687 
3688  b = CALCB(ybnds.inf);
3689 
3690  if( rhs.sup < infinity )
3691  {
3692  c = CALCR(rhs.sup, ybnds.inf);
3693 
3694  if( c > 0.0 )
3695  {
3696  SCIP_Real sqrtc;
3697 
3698  sqrtc = sqrt(c);
3699  minvalleft = MIN(-sqrtc - b, minvalleft);
3700  maxvalright = MAX( sqrtc - b, maxvalright);
3701  }
3702  }
3703 
3704  if( rhs.inf > -infinity )
3705  {
3706  c = CALCR(rhs.inf, ybnds.inf);
3707 
3708  if( c > 0.0 )
3709  {
3710  SCIP_Real sqrtc;
3711 
3712  sqrtc = sqrt(c);
3713  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3714  minvalright = MIN( sqrtc - b, minvalright);
3715  }
3716  }
3717  }
3718 
3719  /* evaluate at upper bound of y, as long as r(rhs, yub) > 0 */
3720  if( ybnds.sup >= infinity )
3721  {
3722  /* check limit of +/-sqrt(r(rhs,y))-b(y) for y -> +infty */
3723  if( !EPSZ(ay, 1e-9) && axy * axy >= 4.0 * ax * ay )
3724  {
3725  if( axy > 0.0 )
3726  {
3727  minvalleft = -infinity;
3728 
3729  if( ay > 0.0 )
3730  minvalright = -infinity;
3731  else
3732  maxvalright = infinity;
3733  }
3734  else
3735  {
3736  maxvalright = infinity;
3737 
3738  if( ay > 0.0 )
3739  maxvalleft = infinity;
3740  else
3741  minvalleft = -infinity;
3742  }
3743  }
3744  else if( !EPSZ(ay, 1e-9) )
3745  {
3746  /* here axy * axy < 4 * ax * ay, so need to check for zeros of r(rhs,y), which will happen below */
3747  }
3748  else
3749  {
3750  /* here ay = 0.0, which gives a limit of -infinity for -sqrt(r(rhs,y))-b(y) */
3751  minvalleft = -infinity;
3752  /* here ay = 0.0, which gives a limit of -by/2 for sqrt(r(rhs,y))-b(y) */
3753  minvalright = MIN(minvalright, -by / 2.0);
3754  maxvalright = MAX(maxvalright, -by / 2.0);
3755  }
3756  }
3757  else
3758  {
3759  SCIP_Real b;
3760  SCIP_Real c;
3761 
3762  b = CALCB(ybnds.sup);
3763 
3764  if( rhs.sup < infinity )
3765  {
3766  c = CALCR(rhs.sup, ybnds.sup);
3767 
3768  if( c > 0.0 )
3769  {
3770  SCIP_Real sqrtc;
3771 
3772  sqrtc = sqrt(c);
3773  minvalleft = MIN(-sqrtc - b, minvalleft);
3774  maxvalright = MAX( sqrtc - b, maxvalright);
3775  }
3776  }
3777 
3778  if( rhs.inf > -infinity )
3779  {
3780  c = CALCR(rhs.inf, ybnds.sup);
3781 
3782  if( c > 0.0 )
3783  {
3784  SCIP_Real sqrtc;
3785 
3786  sqrtc = sqrt(c);
3787  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3788  minvalright = MIN( sqrtc - b, minvalright);
3789  }
3790  }
3791  }
3792 
3793  /* evaluate at ymin = y_{_,+}, if inside ybnds
3794  * if ay = 0 or 2ay*bx == axy*by, then there is no ymin */
3795  if( !EPSZ(ay, 1e-9) )
3796  {
3797  if( REALABS(axy*axy - 4.0*ax*ay) > 1e-9 )
3798  {
3799  SCIP_Real sqrtterm;
3800 
3801  if( rhs.sup < infinity )
3802  {
3803  sqrtterm = axy * axy * ay * (ay * bx * bx - axy * bx * by + ax * by * by - axy * axy * rhs.sup + 4.0 * ax * ay * rhs.sup);
3804  if( !EPSN(sqrtterm, 1e-9) )
3805  {
3806  sqrtterm = sqrt(MAX(sqrtterm, 0.0));
3807  /* check first candidate for extreme points of +/-sqrt(rhs(r,y))-b(y) */
3808  ymin = axy * ay * bx - 2.0 * ax * ay * by - sqrtterm;
3809  ymin /= ay;
3810  ymin /= 4.0 * ax * ay - axy * axy;
3811 
3812  if( ymin > ybnds.inf && ymin < ybnds.sup )
3813  {
3814  SCIP_Real b;
3815  SCIP_Real c;
3816 
3817  b = CALCB(ymin);
3818  c = CALCR(rhs.sup, ymin);
3819 
3820  if( c > 0.0 )
3821  {
3822  SCIP_Real sqrtc;
3823 
3824  sqrtc = sqrt(c);
3825  minvalleft = MIN(-sqrtc - b, minvalleft);
3826  maxvalright = MAX( sqrtc - b, maxvalright);
3827  }
3828  }
3829 
3830  /* check second candidate for extreme points of +/-sqrt(rhs(r,y))-b(y) */
3831  ymin = axy * ay * bx - 2.0 * ax * ay * by + sqrtterm;
3832  ymin /= ay;
3833  ymin /= 4.0 * ax * ay - axy * axy;
3834 
3835  if( ymin > ybnds.inf && ymin < ybnds.sup )
3836  {
3837  SCIP_Real b;
3838  SCIP_Real c;
3839 
3840  b = CALCB(ymin);
3841  c = CALCR(rhs.sup, ymin);
3842 
3843  if( c > 0.0 )
3844  {
3845  SCIP_Real sqrtc;
3846 
3847  sqrtc = sqrt(c);
3848  minvalleft = MIN(-sqrtc - b, minvalleft);
3849  maxvalright = MAX( sqrtc - b, maxvalright);
3850  }
3851  }
3852  }
3853  }
3854 
3855  if( rhs.inf > -infinity )
3856  {
3857  sqrtterm = axy * axy * ay * (ay * bx * bx - axy * bx * by + ax * by * by - axy * axy * rhs.inf + 4.0 * ax * ay * rhs.inf);
3858  if( !EPSN(sqrtterm, 1e-9) )
3859  {
3860  sqrtterm = sqrt(MAX(sqrtterm, 0.0));
3861  /* check first candidate for extreme points of +/-sqrt(r(rhs,y))-b(y) */
3862  ymin = axy * ay * bx - 2.0 * ax * ay * by - sqrtterm;
3863  ymin /= ay;
3864  ymin /= 4.0 * ax * ay - axy * axy;
3865 
3866  if( ymin > ybnds.inf && ymin < ybnds.sup )
3867  {
3868  SCIP_Real b;
3869  SCIP_Real c;
3870 
3871  b = CALCB(ymin);
3872  c = CALCR(rhs.inf, ymin);
3873 
3874  if( c > 0.0 )
3875  {
3876  SCIP_Real sqrtc;
3877 
3878  sqrtc = sqrt(c);
3879  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3880  minvalright = MIN( sqrtc - b, minvalright);
3881  }
3882  }
3883 
3884  /* check second candidate for extreme points of +/-sqrt(c(y))-b(y) */
3885  ymin = axy * ay * bx - 2.0 * ax * ay * by + sqrtterm;
3886  ymin /= ay;
3887  ymin /= 4.0 * ax * ay - axy * axy;
3888 
3889  if( ymin > ybnds.inf && ymin < ybnds.sup )
3890  {
3891  SCIP_Real b;
3892  SCIP_Real c;
3893 
3894  b = CALCB(ymin);
3895  c = CALCR(rhs.inf, ymin);
3896 
3897  if( c > 0.0 )
3898  {
3899  SCIP_Real sqrtc;
3900 
3901  sqrtc = sqrt(c);
3902  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3903  minvalright = MIN( sqrtc - b, minvalright);
3904  }
3905  }
3906  }
3907  }
3908  }
3909  else if( REALABS(2.0 * ay * bx - axy * by) > 1e-9 )
3910  {
3911  if( rhs.sup < infinity )
3912  {
3913  ymin = - (4.0 * ay * bx * by - axy * by * by + 4.0 * axy * ay * rhs.sup);
3914  ymin /= 4.0 * ay;
3915  ymin /= 2.0 * ay * bx - axy * by;
3916 
3917  if( ymin > ybnds.inf && ymin < ybnds.sup )
3918  {
3919  SCIP_Real b;
3920  SCIP_Real c;
3921 
3922  b = CALCB(ymin);
3923  c = CALCR(rhs.sup, ymin);
3924 
3925  if( c > 0.0 )
3926  {
3927  SCIP_Real sqrtc;
3928 
3929  sqrtc = sqrt(c);
3930  minvalleft = MIN(-sqrtc - b, minvalleft);
3931  maxvalright = MAX( sqrtc - b, maxvalright);
3932  }
3933  }
3934  }
3935 
3936  if( rhs.inf > -infinity )
3937  {
3938  ymin = - (4.0 * ay * bx * by - axy * by * by + 4.0 * axy * ay * rhs.inf);
3939  ymin /= 4.0 * ay;
3940  ymin /= 2.0 * ay * bx - axy * by;
3941 
3942  if( ymin > ybnds.inf && ymin < ybnds.sup )
3943  {
3944  SCIP_Real b;
3945  SCIP_Real c;
3946 
3947  b = CALCB(ymin);
3948  c = CALCR(rhs.inf, ymin);
3949 
3950  if( c > 0.0 )
3951  {
3952  SCIP_Real sqrtc;
3953 
3954  sqrtc = sqrt(c);
3955  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3956  minvalright = MIN( sqrtc - b, minvalright);
3957  }
3958  }
3959  }
3960  }
3961  }
3962 
3963  /* evaluate the case r(rhs,y) = 0, which is to min/max -b(y) w.r.t. r(rhs,y) = 0, y in ybnds
3964  * with the above assignments
3965  * rcoef_y = axy * bx / (2.0*ax) - by;
3966  * rcoef_yy = axy * axy / (4.0*ax) - ay;
3967  * rcoef_const = bx * bx / (4.0*ax);
3968  * we have r(rhs,y) = rhs + rcoef_const + rcoef_y * y + rcoef_yy * y^2
3969  *
3970  * thus, r(rhs,y) = 0 <-> rcoef_y * y + rcoef_yy * y^2 in -rhs - rcoef_const
3971  *
3972  */
3973  {
3974  SCIP_INTERVAL rcoef_yy_int;
3975  SCIP_INTERVAL rcoef_y_int;
3976  SCIP_INTERVAL rhs2;
3977  SCIP_Real b;
3978 
3979  /* setup rcoef_yy, rcoef_y and -rhs-rcoef_const as intervals */
3980  SCIPintervalSet(&rcoef_yy_int, (SCIP_Real)rcoef_yy);
3981  SCIPintervalSet(&rcoef_y_int, (SCIP_Real)rcoef_y);
3982  SCIPintervalSetBounds(&rhs2, (SCIP_Real)(-rhs.sup - rcoef_const), (SCIP_Real)(-rhs.inf - rcoef_const));
3983 
3984  /* first find all y >= 0 such that rcoef_y * y + rcoef_yy * y^2 in -rhs2, if ybnds.sup >= 0.0
3985  * and evaluate -b(y) w.r.t. these values
3986  */
3987  if( ybnds.sup >= 0.0 )
3988  {
3989  SCIP_INTERVAL ypos;
3990 
3991  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &ypos, rcoef_yy_int, rcoef_y_int, rhs2, ybnds);
3992  if( !SCIPintervalIsEmpty(infinity, ypos) )
3993  {
3994  assert(ypos.inf >= 0.0); /* we computed only positive solutions above */
3995  b = CALCB(ypos.inf);
3996  minvalleft = MIN(minvalleft, -b);
3997  maxvalleft = MAX(maxvalleft, -b);
3998  minvalright = MIN(minvalright, -b);
3999  maxvalright = MAX(maxvalright, -b);
4000 
4001  if( ypos.sup < infinity )
4002  {
4003  b = CALCB(ypos.sup);
4004  minvalleft = MIN(minvalleft, -b);
4005  maxvalleft = MAX(maxvalleft, -b);
4006  minvalright = MIN(minvalright, -b);
4007  maxvalright = MAX(maxvalright, -b);
4008  }
4009  else
4010  {
4011  /* -b(y) = - (bx + axy * y) / (2.0 * sqrt(ax)) -> -sign(axy)*infinity for y -> infinity */
4012  if( axy > 0.0 )
4013  {
4014  minvalleft = -infinity;
4015  minvalright = -infinity;
4016  }
4017  else
4018  {
4019  maxvalleft = infinity;
4020  maxvalright = infinity;
4021  }
4022  }
4023  }
4024  }
4025 
4026  /* next find all y <= 0 such that rcoef_y * y + rcoef_yy * y^2 in -rhs2, if ybnds.inf < 0.0
4027  * and evaluate -b(y) w.r.t. these values
4028  * (the case y fixed to 0 has been handled in the ybnds.sup >= 0 case above)
4029  */
4030  if( ybnds.inf < 0.0 )
4031  {
4032  SCIP_INTERVAL yneg;
4033 
4034  SCIPintervalSolveUnivariateQuadExpressionNegative(infinity, &yneg, rcoef_yy_int, rcoef_y_int, rhs2, ybnds);
4035  if( !SCIPintervalIsEmpty(infinity, yneg) )
4036  {
4037  if( yneg.inf > -infinity )
4038  {
4039  b = CALCB(yneg.inf);
4040  minvalleft = MIN(minvalleft, -b);
4041  maxvalleft = MAX(maxvalleft, -b);
4042  minvalright = MIN(minvalright, -b);
4043  maxvalright = MAX(maxvalright, -b);
4044  }
4045  else
4046  {
4047  /* -b(y) = - (bx + axy * y) / (2.0 * sqrt(ax)) -> sign(axy)*infinity for y -> -infinity */
4048  if( axy > 0.0 )
4049  {
4050  maxvalleft = infinity;
4051  maxvalright = infinity;
4052  }
4053  else
4054  {
4055  minvalleft = -infinity;
4056  minvalright = -infinity;
4057  }
4058  }
4059 
4060  assert(yneg.sup <= 0.0); /* we computed only negative solutions above */
4061  b = CALCB(yneg.sup);
4062  minvalleft = MIN(minvalleft, -b);
4063  maxvalleft = MAX(maxvalleft, -b);
4064  minvalright = MIN(minvalright, -b);
4065  maxvalright = MAX(maxvalright, -b);
4066  }
4067  }
4068  }
4069 
4070  if( rhs.inf > -infinity && xbnds.inf > -infinity && EPSGT(xbnds.inf, maxvalleft / sqrtax, 1e-9) )
4071  {
4072  /* 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)
4073  * 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) */
4074  assert(EPSGE(minvalright, minvalleft, 1e-9)); /* right interval should not be above lower bound of left interval */
4075  if( minvalright > -infinity )
4076  {
4077  assert(minvalright < infinity);
4078  resultant->inf = (SCIP_Real)(minvalright / sqrtax);
4079  }
4080  }
4081  else
4082  {
4083  /* otherwise, tighten lower bound of sqrt(ax)*x to lower bound of -sqrt(r(rhs,y))-b(y) */
4084  if( minvalleft > -infinity )
4085  {
4086  assert(minvalleft < infinity);
4087  resultant->inf = (SCIP_Real)(minvalleft / sqrtax);
4088  }
4089  }
4090 
4091  if( rhs.inf > -infinity && xbnds.sup < infinity && EPSLT(xbnds.sup, minvalright / sqrtax, 1e-9) )
4092  {
4093  /* 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)
4094  * 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) */
4095  assert(EPSLE(maxvalleft, maxvalright, 1e-9)); /* left interval should not be above upper bound of right interval */
4096  if( maxvalleft < infinity )
4097  {
4098  assert(maxvalleft > -infinity);
4099  resultant->sup = (SCIP_Real)(maxvalleft / sqrtax);
4100  }
4101  }
4102  else
4103  {
4104  /* otherwise, tighten upper bound of sqrt(ax)*x to upper bound of sqrt(r(rhs,y))-b(y) */
4105  if( maxvalright < infinity )
4106  {
4107  assert(maxvalright > -infinity);
4108  resultant->sup = (SCIP_Real)(maxvalright / sqrtax);
4109  }
4110  }
4111 
4112  resultant->inf -= 1e-10 * REALABS(resultant->inf);
4113  resultant->sup += 1e-10 * REALABS(resultant->sup);
4114 
4115 #undef CALCB
4116 #undef CALCR
4117  }
4118  else
4119  {
4120  /* case ax == 0 */
4121 
4122  SCIP_Real c;
4123  SCIP_Real d;
4124  SCIP_Real ymin;
4125  SCIP_Real minval;
4126  SCIP_Real maxval;
4127 
4128  /* consider -bx / axy in ybnds, i.e., bx + axy y can be 0 */
4129  if( EPSGE(-bx / axy, ybnds.inf, 1e-9) && EPSLE(-bx / axy, ybnds.sup, 1e-9) )
4130  {
4131  /* write as (bx + axy y) * x \in (c - ay y^2 - by y)
4132  * and estimate bx + axy y and c - ay y^2 - by y by intervals independently
4133  * @todo can we do better, as in the case where bx + axy y is bounded away from 0?
4134  */
4135  SCIP_INTERVAL lincoef;
4136  SCIP_INTERVAL myrhs;
4137  SCIP_INTERVAL tmp;
4138 
4139  if( xbnds.inf < 0.0 && xbnds.sup > 0.0 )
4140  {
4141  /* if (bx + axy y) can be arbitrary small and x be both positive and negative,
4142  * then nothing we can tighten here
4143  */
4144  SCIPintervalSetBounds(resultant, xbnds.inf, xbnds.sup);
4145  return;
4146  }
4147 
4148  /* store interval for (bx + axy y) in lincoef */
4149  SCIPintervalMulScalar(infinity, &lincoef, ybnds, axy);
4150  SCIPintervalAddScalar(infinity, &lincoef, lincoef, bx);
4151 
4152  /* store interval for (c - ay y^2 - by y) in myrhs */
4153  SCIPintervalSet(&tmp, by);
4154  SCIPintervalQuad(infinity, &tmp, ay, tmp, ybnds);
4155  SCIPintervalSub(infinity, &myrhs, rhs, tmp);
4156 
4157  if( lincoef.inf == 0.0 && lincoef.sup == 0.0 )
4158  {
4159  /* equation became 0.0 \in myrhs */
4160  if( myrhs.inf <= 0.0 && myrhs.sup >= 0.0 )
4161  *resultant = xbnds;
4162  else
4163  SCIPintervalSetEmpty(resultant);
4164  }
4165  else if( xbnds.inf >= 0.0 )
4166  {
4167  SCIP_INTERVAL a_;
4168 
4169  /* need only positive solutions */
4170  SCIPintervalSet(&a_, 0.0);
4171  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, resultant, a_, lincoef, myrhs, xbnds);
4172  }
4173  else
4174  {
4175  SCIP_INTERVAL a_;
4176  SCIP_INTERVAL xbndsneg;
4177 
4178  assert(xbnds.sup <= 0.0);
4179 
4180  /* need only negative solutions */
4181  SCIPintervalSet(&a_, 0.0);
4182  SCIPintervalSetBounds(&lincoef, -lincoef.sup, -lincoef.inf);
4183  SCIPintervalSetBounds(&xbndsneg, -xbnds.sup, -xbnds.inf);
4184  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, resultant, a_, lincoef, myrhs, xbndsneg);
4185  if( !SCIPintervalIsEmpty(infinity, *resultant) )
4186  SCIPintervalSetBounds(resultant, -resultant->sup, -resultant->inf);
4187  }
4188 
4189  return;
4190  }
4191 
4192  minval = infinity;
4193  maxval = -infinity;
4194 
4195  /* compute a lower bound on x */
4196  if( bx + axy * (axy > 0.0 ? ybnds.inf : ybnds.sup) > 0.0 )
4197  c = rhs.inf;
4198  else
4199  c = rhs.sup;
4200 
4201  if( c > -infinity && c < infinity )
4202  {
4203  if( ybnds.inf <= -infinity )
4204  {
4205  /* limit is ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4206  if( EPSZ(ay, 1e-9) )
4207  minval = -by / axy;
4208  else if( ay * axy < 0.0 )
4209  minval = -infinity;
4210  }
4211  else
4212  {
4213  val = (c - ay * ybnds.inf * ybnds.inf - by * ybnds.inf) / (bx + axy * ybnds.inf);
4214  minval = MIN(val, minval);
4215  }
4216 
4217  if( ybnds.sup >= infinity )
4218  {
4219  /* limit is -ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4220  if( EPSZ(ay, 1e-9) )
4221  minval = MIN(minval, -by / axy);
4222  else if( ay * axy > 0.0 )
4223  minval = -infinity;
4224  }
4225  else
4226  {
4227  val = (c - ay * ybnds.sup * ybnds.sup - by * ybnds.sup) / (bx + axy * ybnds.sup);
4228  minval = MIN(val, minval);
4229  }
4230 
4231  if( !EPSZ(ay, 1e-9) )
4232  {
4233  d = ay * (ay * bx * bx - axy * (bx * by + axy * c));
4234  if( !EPSN(d, 1e-9) )
4235  {
4236  ymin = -ay * bx + sqrt(MAX(d, 0.0));
4237  ymin /= axy * ay;
4238 
4239  if( ymin > ybnds.inf && ymin < ybnds.sup )
4240  {
4241  assert(bx + axy * ymin != 0.0);
4242 
4243  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4244  minval = MIN(val, minval);
4245  }
4246 
4247  ymin = -ay * bx - sqrt(MAX(d, 0.0));
4248  ymin /= axy * ay;
4249 
4250  if(ymin > ybnds.inf && ymin < ybnds.sup )
4251  {
4252  assert(bx + axy * ymin != 0.0);
4253 
4254  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4255  minval = MIN(val, minval);
4256  }
4257  }
4258  }
4259  }
4260  else
4261  {
4262  minval = -infinity;
4263  }
4264 
4265  /* compute an upper bound on x */
4266  if( bx + axy * (axy > 0.0 ? ybnds.inf : ybnds.sup) > 0.0 )
4267  c = rhs.sup;
4268  else
4269  c = rhs.inf;
4270 
4271  if( c > -infinity && c < infinity )
4272  {
4273  if( ybnds.inf <= -infinity )
4274  {
4275  /* limit is ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4276  if( EPSZ(ay, 1e-9) )
4277  maxval = -by / axy;
4278  else if( ay * axy > 0.0 )
4279  maxval = infinity;
4280  }
4281  else
4282  {
4283  val = (c - ay * ybnds.inf * ybnds.inf - by * ybnds.inf) / (bx + axy * ybnds.inf);
4284  maxval = MAX(val, maxval);
4285  }
4286 
4287  if( ybnds.sup >= infinity )
4288  {
4289  /* limit is -ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4290  if( EPSZ(ay, 1e-9) )
4291  maxval = MAX(maxval, -by / axy);
4292  else if( ay * axy < 0.0 )
4293  maxval = infinity;
4294  }
4295  else
4296  {
4297  val = (c - ay * ybnds.sup * ybnds.sup - by * ybnds.sup) / (bx + axy * ybnds.sup);
4298  maxval = MAX(val, maxval);
4299  }
4300 
4301  if( !EPSZ(ay, 1e-9) )
4302  {
4303  d = ay * (ay * bx * bx - axy * (bx * by + axy * c));
4304  if( !EPSN(d, 1e-9) )
4305  {
4306  ymin = ay * bx + sqrt(MAX(d, 0.0));
4307  ymin /= axy * ay;
4308 
4309  if( ymin > ybnds.inf && ymin < ybnds.sup )
4310  {
4311  assert(bx + axy * ymin != 0.0); /* the case -bx/axy in ybnds was handled aboved */
4312  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4313  maxval = MAX(val, maxval);
4314  }
4315 
4316  ymin = ay * bx - sqrt(MAX(d, 0.0));
4317  ymin /= axy * ay;
4318 
4319  if( ymin > ybnds.inf && ymin < ybnds.sup )
4320  {
4321  assert(bx + axy * ymin != 0.0); /* the case -bx/axy in ybnds was handled aboved */
4322  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4323  maxval = MAX(val, maxval);
4324  }
4325  }
4326  }
4327  }
4328  else
4329  {
4330  maxval = infinity;
4331  }
4332 
4333  if( minval > -infinity )
4334  resultant->inf = minval - 1e-10 * REALABS(minval);
4335  else
4336  resultant->inf = -infinity;
4337  if( maxval < infinity )
4338  resultant->sup = maxval + 1e-10 * REALABS(maxval);
4339  else
4340  resultant->sup = infinity;
4341  SCIPintervalIntersect(resultant, *resultant, xbnds);
4342  }
4343 }
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:239
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:65
void SCIPintervalMul(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
#define EPSISINT(x, eps)
Definition: def.h:187
#define TRUE
Definition: def.h:64
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:179
#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:9607
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:182
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:174
#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:62
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:209
void SCIPintervalSquare(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
Definition: misc.c:8697
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:177
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:151
#define EPSLT(x, y, eps)
Definition: def.h:176
#define SCIP_REAL_MIN
Definition: def.h:152
#define EPSGT(x, y, eps)
Definition: def.h:178
SCIP_VAR ** b
Definition: circlepacking.c:56
#define MAX(x, y)
Definition: def.h:208
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:150
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:180
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)