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