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-2017 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 = SCIPnextafter(tmp, SCIP_REAL_MIN);
2356  resultant->sup = SCIPnextafter(tmp, SCIP_REAL_MAX);
2357 
2358  return;
2359  }
2360  }
2361 
2362  if( operand.inf <= -infinity )
2363  {
2364  resultant->inf = 0.0;
2365  }
2366  else if( operand.inf == 0.0 )
2367  {
2368  resultant->inf = 1.0;
2369  }
2370  else
2371  {
2373  resultant->inf = SCIPnextafter(exp(operand.inf), SCIP_REAL_MIN);
2374  /* make sure we do not exceed value for infinity, so interval is not declared as empty if inf and sup are both > infinity */
2375  if( resultant->inf >= infinity )
2376  resultant->inf = infinity;
2377  }
2378 
2379  if( operand.sup >= infinity )
2380  {
2381  resultant->sup = infinity;
2382  }
2383  else if( operand.sup == 0.0 )
2384  {
2385  resultant->sup = 1.0;
2386  }
2387  else
2388  {
2390  resultant->sup = SCIPnextafter(exp(operand.sup), SCIP_REAL_MAX);
2391  if( resultant->sup < -infinity )
2392  resultant->sup = -infinity;
2393  }
2394 }
2395 
2396 /** stores natural logarithm of operand in resultant
2397  * @attention we assume a correctly rounded log(double) function when rounding is to nearest
2398  */
2400  SCIP_Real infinity, /**< value for infinity */
2401  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2402  SCIP_INTERVAL operand /**< operand of operation */
2403  )
2404 {
2405  assert(resultant != NULL);
2406  assert(!SCIPintervalIsEmpty(infinity, operand));
2407 
2408  /* if operand.sup == 0.0, we could return -inf in resultant->sup, but that
2409  * seems of little use and just creates problems somewhere else, e.g., #1230
2410  */
2411  if( operand.sup <= 0.0 )
2412  {
2413  SCIPintervalSetEmpty(resultant);
2414  return;
2415  }
2416 
2417  if( operand.inf == operand.sup ) /*lint !e777 */
2418  {
2419  if( operand.sup == 1.0 )
2420  {
2421  resultant->inf = 0.0;
2422  resultant->sup = 0.0;
2423  }
2424  else
2425  {
2426  SCIP_Real tmp;
2427 
2429  tmp = log(operand.inf);
2430  resultant->inf = SCIPnextafter(tmp, SCIP_REAL_MIN);
2431  resultant->sup = SCIPnextafter(tmp, SCIP_REAL_MAX);
2432  }
2433 
2434  return;
2435  }
2436 
2437  if( operand.inf <= 0.0 )
2438  {
2439  resultant->inf = -infinity;
2440  }
2441  else if( operand.inf == 1.0 )
2442  {
2443  resultant->inf = 0.0;
2444  }
2445  else
2446  {
2448  resultant->inf = SCIPnextafter(log(operand.inf), SCIP_REAL_MIN);
2449  }
2450 
2451  if( operand.sup >= infinity )
2452  {
2453  resultant->sup = infinity;
2454  }
2455  else if( operand.sup == 1.0 )
2456  {
2457  resultant->sup = 0.0;
2458  }
2459  else
2460  {
2462  resultant->sup = SCIPnextafter(log(operand.sup), SCIP_REAL_MAX);
2463  }
2464 }
2465 
2466 /** stores minimum of operands in resultant */
2468  SCIP_Real infinity, /**< value for infinity */
2469  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2470  SCIP_INTERVAL operand1, /**< first operand of operation */
2471  SCIP_INTERVAL operand2 /**< second operand of operation */
2472  )
2473 {
2474  assert(resultant != NULL);
2475  assert(!SCIPintervalIsEmpty(infinity, operand1));
2476  assert(!SCIPintervalIsEmpty(infinity, operand2));
2477 
2478  resultant->inf = MIN(operand1.inf, operand2.inf);
2479  resultant->sup = MIN(operand1.sup, operand2.sup);
2480 }
2481 
2482 /** stores maximum of operands in resultant */
2484  SCIP_Real infinity, /**< value for infinity */
2485  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2486  SCIP_INTERVAL operand1, /**< first operand of operation */
2487  SCIP_INTERVAL operand2 /**< second operand of operation */
2488  )
2489 {
2490  assert(resultant != NULL);
2491  assert(!SCIPintervalIsEmpty(infinity, operand1));
2492  assert(!SCIPintervalIsEmpty(infinity, operand2));
2493 
2494  resultant->inf = MAX(operand1.inf, operand2.inf);
2495  resultant->sup = MAX(operand1.sup, operand2.sup);
2496 }
2497 
2498 /** stores absolute value of operand in resultant */
2500  SCIP_Real infinity, /**< value for infinity */
2501  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2502  SCIP_INTERVAL operand /**< operand of operation */
2503  )
2504 {
2505  assert(resultant != NULL);
2506  assert(!SCIPintervalIsEmpty(infinity, operand));
2507 
2508  if( operand.inf <= 0.0 && operand.sup >= 0.0)
2509  {
2510  resultant->inf = 0.0;
2511  resultant->sup = MAX(-operand.inf, operand.sup);
2512  }
2513  else if( operand.inf > 0.0 )
2514  {
2515  *resultant = operand;
2516  }
2517  else
2518  {
2519  resultant->inf = -operand.sup;
2520  resultant->sup = -operand.inf;
2521  }
2522 }
2523 
2524 /** stores sine value of operand in resultant
2525  * NOTE: the operations are not applied rounding-safe here
2526  */
2528  SCIP_Real infinity, /**< value for infinity */
2529  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2530  SCIP_INTERVAL operand /**< operand of operation */
2531  )
2532 {
2533  SCIP_Real intervallen;
2534  SCIP_Real modinf;
2535  SCIP_Real modsup;
2536  SCIP_Real finf;
2537  SCIP_Real fsup;
2538  int a;
2539  int b;
2540  int nbetween;
2541  /* first one is 1 so even indices are the maximum points */
2542  static SCIP_Real extremepoints[] = {0.5*M_PI, 1.5*M_PI, 2.5*M_PI, 3.5*M_PI};
2543 
2544  assert(resultant != NULL);
2545  assert(!SCIPintervalIsEmpty(infinity, operand));
2546 
2547  intervallen = operand.sup - operand.inf;
2548  if( intervallen >= 2*M_PI )
2549  {
2550  SCIPintervalSetBounds(resultant, -1.0, 1.0);
2551  return;
2552  }
2553 
2554  modinf = fmod(operand.inf, 2*M_PI);
2555  if( modinf < 0.0 )
2556  modinf += 2*M_PI;
2557  modsup = modinf + intervallen;
2558 
2559  for( b = 0; ; ++b )
2560  {
2561  if( modinf <= extremepoints[b] )
2562  {
2563  a = b;
2564  break;
2565  }
2566  }
2567  for( ; b < 4; ++b )
2568  {
2569  if( modsup <= extremepoints[b] )
2570  break;
2571  }
2572 
2573  nbetween = b-a;
2574 
2575  if( nbetween > 1 )
2576  {
2577  SCIPintervalSetBounds(resultant, -1.0, 1.0);
2578  return;
2579  }
2580 
2581  finf = sin(operand.inf);
2582  fsup = sin(operand.sup);
2583 
2584  if( nbetween == 0 )
2585  {
2586  if( a & 1 ) /* next extremepoint is minimum -> decreasing -> finf < fsup */
2587  SCIPintervalSetBounds(resultant, fsup, finf);
2588  else
2589  SCIPintervalSetBounds(resultant, finf, fsup);
2590  }
2591  else /* 1 extremepoint in between */
2592  {
2593  if( a & 1 ) /* extremepoint is minimum */
2594  SCIPintervalSetBounds(resultant, -1.0, MAX(finf,fsup));
2595  else
2596  SCIPintervalSetBounds(resultant, MIN(finf,fsup), 1.0);
2597  }
2598 
2599  /* above operations did not take outward rounding into account,
2600  * so extend the computed interval slightly to increase the chance that it will contain the complete sin(operand)
2601  */
2602  if( resultant->inf > -1.0 )
2603  resultant->inf = MAX(-1.0, resultant->inf - 1e-10 * REALABS(resultant->inf)); /*lint !e666*/
2604  if( resultant->sup < 1.0 )
2605  resultant->sup = MIN( 1.0, resultant->sup + 1e-10 * REALABS(resultant->sup)); /*lint !e666*/
2606 
2607  assert(resultant->inf <= resultant->sup);
2608 }
2609 
2610 /** stores cosine value of operand in resultant
2611  * NOTE: the operations are not applied rounding-safe here
2612  */
2614  SCIP_Real infinity, /**< value for infinity */
2615  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2616  SCIP_INTERVAL operand /**< operand of operation */
2617  )
2618 {
2619  SCIP_Real intervallen;
2620  SCIP_Real modinf;
2621  SCIP_Real modsup;
2622  SCIP_Real finf;
2623  SCIP_Real fsup;
2624  int a;
2625  int b;
2626  int nbetween;
2627  /* first one is -1 so even indices are the minimum points */
2628  static SCIP_Real extremepoints[] = {M_PI, 2*M_PI, 3*M_PI};
2629 
2630  assert(resultant != NULL);
2631  assert(!SCIPintervalIsEmpty(infinity, operand));
2632 
2633  intervallen = operand.sup - operand.inf;
2634  if( intervallen >= 2*M_PI )
2635  {
2636  SCIPintervalSetBounds(resultant, -1.0, 1.0);
2637  return;
2638  }
2639 
2640  modinf = fmod(operand.inf, 2*M_PI);
2641  if( modinf < 0.0 )
2642  modinf += 2*M_PI;
2643  modsup = modinf + intervallen;
2644 
2645  for( b = 0; ; ++b )
2646  {
2647  if( modinf <= extremepoints[b] )
2648  {
2649  a = b;
2650  break;
2651  }
2652  }
2653  for( ; b < 3; ++b )
2654  {
2655  if( modsup <= extremepoints[b] )
2656  break;
2657  }
2658 
2659  nbetween = b-a;
2660 
2661  if( nbetween > 1 )
2662  {
2663  SCIPintervalSetBounds(resultant, -1.0, 1.0);
2664  return;
2665  }
2666 
2667  finf = cos(operand.inf);
2668  fsup = cos(operand.sup);
2669 
2670  if( nbetween == 0 )
2671  {
2672  if( a & 1 ) /* next extremepoint is maximum -> increasing -> finf < fsup */
2673  SCIPintervalSetBounds(resultant, finf, fsup);
2674  else
2675  SCIPintervalSetBounds(resultant, fsup, finf);
2676  }
2677  else /* 1 extremepoint in between */
2678  {
2679  if( a & 1 ) /* extremepoint is maximum */
2680  SCIPintervalSetBounds(resultant, MIN(finf,fsup), 1.0);
2681  else
2682  SCIPintervalSetBounds(resultant, -1.0, MAX(finf,fsup));
2683  }
2684 
2685  /* above operations did not take outward rounding into account,
2686  * so extend the computed interval slightly to increase the chance that it will contain the complete cos(operand)
2687  */
2688  if( resultant->inf > -1.0 )
2689  resultant->inf = MAX(-1.0, resultant->inf - 1e-10 * REALABS(resultant->inf)); /*lint !e666*/
2690  if( resultant->sup < 1.0 )
2691  resultant->sup = MIN( 1.0, resultant->sup + 1e-10 * REALABS(resultant->sup)); /*lint !e666*/
2692 
2693  assert(resultant->inf <= resultant->sup);
2694 }
2695 
2696 /** stores sign of operand in resultant */
2698  SCIP_Real infinity, /**< value for infinity */
2699  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2700  SCIP_INTERVAL operand /**< operand of operation */
2701  )
2702 {
2703  assert(resultant != NULL);
2704  assert(!SCIPintervalIsEmpty(infinity, operand));
2705 
2706  if( operand.sup < 0.0 )
2707  {
2708  resultant->inf = -1.0;
2709  resultant->sup = -1.0;
2710  }
2711  else if( operand.inf >= 0.0 )
2712  {
2713  resultant->inf = 1.0;
2714  resultant->sup = 1.0;
2715  }
2716  else
2717  {
2718  resultant->inf = -1.0;
2719  resultant->sup = 1.0;
2720  }
2721 }
2722 
2723 /** computes exact upper bound on \f$ a x^2 + b x \f$ for x in [xlb, xub], b an interval, and a scalar
2724  *
2725  * Uses Algorithm 2.2 from Domes and Neumaier: Constraint propagation on quadratic constraints (2008) */
2727  SCIP_Real infinity, /**< value for infinity */
2728  SCIP_Real a, /**< coefficient of x^2 */
2729  SCIP_INTERVAL b_, /**< coefficient of x */
2730  SCIP_INTERVAL x /**< range of x */
2731  )
2732 {
2733  SCIP_Real b;
2734  SCIP_Real u;
2735 
2736  assert(!SCIPintervalIsEmpty(infinity, x));
2737  assert(b_.inf < infinity);
2738  assert(b_.sup > -infinity);
2739  assert( x.inf < infinity);
2740  assert( x.sup > -infinity);
2741 
2742  /* handle b*x separately */
2743  if( a == 0.0 )
2744  {
2745  if( (b_.inf <= -infinity && x.inf < 0.0 ) ||
2746  ( b_.inf < 0.0 && x.inf <= -infinity) ||
2747  ( b_.sup > 0.0 && x.sup >= infinity) ||
2748  ( b_.sup >= infinity && x.sup > 0.0 ) )
2749  {
2750  u = infinity;
2751  }
2752  else
2753  {
2754  SCIP_ROUNDMODE roundmode;
2755  SCIP_Real cand1, cand2, cand3, cand4;
2756 
2757  roundmode = SCIPintervalGetRoundingMode();
2759  cand1 = b_.inf * x.inf;
2760  cand2 = b_.inf * x.sup;
2761  cand3 = b_.sup * x.inf;
2762  cand4 = b_.sup * x.sup;
2763  u = MAX(MAX(cand1, cand2), MAX(cand3, cand4));
2764 
2765  SCIPintervalSetRoundingMode(roundmode);
2766  }
2767 
2768  return u;
2769  }
2770 
2771  if( x.sup <= 0.0 )
2772  { /* change sign of x: enclose a*x^2 + [-bub, -blb]*(-x) for (-x) in [-xub, -xlb] */
2773  u = x.sup;
2774  x.sup = -x.inf;
2775  x.inf = -u;
2776  b = -b_.inf;
2777  }
2778  else
2779  {
2780  b = b_.sup;
2781  }
2782 
2783  if( x.inf >= 0.0 )
2784  { /* upper bound for a*x^2 + b*x */
2785  SCIP_ROUNDMODE roundmode;
2786  SCIP_Real s,t;
2787 
2788  if( b >= infinity )
2789  return infinity;
2790 
2791  roundmode = SCIPintervalGetRoundingMode();
2793 
2794  u = MAX(x.inf * (a*x.inf + b), x.sup * (a*x.sup + b));
2795  s = b/2;
2796  t = s/negate(a);
2797  if( t > x.inf && negate(2*a)*x.sup > b && s*t > u )
2798  u = s*t;
2799 
2800  SCIPintervalSetRoundingMode(roundmode);
2801  return u;
2802  }
2803  else
2804  {
2805  SCIP_INTERVAL xlow = x;
2806  SCIP_Real cand1;
2807  SCIP_Real cand2;
2808  assert(x.inf < 0.0 && x.sup > 0);
2809 
2810  xlow.sup = 0; /* so xlow is lower part of interval */
2811  x.inf = 0; /* so x is upper part of interval now */
2812  cand1 = SCIPintervalQuadUpperBound(infinity, a, b_, xlow);
2813  cand2 = SCIPintervalQuadUpperBound(infinity, a, b_, x);
2814  return MAX(cand1, cand2);
2815  }
2816 }
2817 
2818 /** stores range of quadratic term in resultant
2819  *
2820  * given scalar a and intervals b and x, computes interval for \f$ a x^2 + b x \f$ */
2822  SCIP_Real infinity, /**< value for infinity */
2823  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2824  SCIP_Real sqrcoeff, /**< coefficient of x^2 */
2825  SCIP_INTERVAL lincoeff, /**< coefficient of x */
2826  SCIP_INTERVAL xrng /**< range of x */
2827  )
2828 {
2829  SCIP_Real tmp;
2830 
2831  if( SCIPintervalIsEmpty(infinity, xrng) )
2832  {
2833  SCIPintervalSetEmpty(resultant);
2834  return;
2835  }
2836  if( sqrcoeff == 0.0 )
2837  {
2838  SCIPintervalMul(infinity, resultant, lincoeff, xrng);
2839  return;
2840  }
2841 
2842  resultant->sup = SCIPintervalQuadUpperBound(infinity, sqrcoeff, lincoeff, xrng);
2843 
2844  tmp = lincoeff.inf;
2845  lincoeff.inf = -lincoeff.sup;
2846  lincoeff.sup = -tmp;
2847  resultant->inf = -SCIPintervalQuadUpperBound(infinity, -sqrcoeff, lincoeff, xrng);
2848 
2849  assert(resultant->sup >= resultant->inf);
2850 }
2851 
2852 /** computes interval with positive solutions of a quadratic equation with interval coefficients
2853  *
2854  * 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$.
2855  */
2857  SCIP_Real infinity, /**< value for infinity */
2858  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2859  SCIP_INTERVAL sqrcoeff, /**< coefficient of x^2 */
2860  SCIP_INTERVAL lincoeff, /**< coefficient of x */
2861  SCIP_INTERVAL rhs /**< right hand side of equation */
2862  )
2863 {
2864  assert(resultant != NULL);
2865 
2866  /* find x>=0 s.t. a.inf x^2 + b.inf x <= c.sup -> -a.inf x^2 - b.inf x >= -c.sup */
2867  if( lincoeff.inf <= -infinity || rhs.sup >= infinity || sqrcoeff.inf <= -infinity )
2868  {
2869  resultant->inf = 0.0;
2870  resultant->sup = infinity;
2871  }
2872  else
2873  {
2874  SCIPintervalSolveUnivariateQuadExpressionPositiveAllScalar(infinity, resultant, -sqrcoeff.inf, -lincoeff.inf, -rhs.sup);
2875  SCIPdebugMessage("solve %g*x^2 + %g*x >= %g gives [%.20f, %.20f]\n", -sqrcoeff.inf, -lincoeff.inf, -rhs.sup, resultant->inf, resultant->sup);
2876  }
2877 
2878  /* find x>=0 s.t. a.sup x^2 + b.sup x >= c.inf */
2879  if( lincoeff.sup < infinity && rhs.inf > -infinity && sqrcoeff.sup < infinity )
2880  {
2881  SCIP_INTERVAL res2;
2882  SCIPintervalSolveUnivariateQuadExpressionPositiveAllScalar(infinity, &res2, sqrcoeff.sup, lincoeff.sup, rhs.inf);
2883  SCIPdebugMessage("solve %g*x^2 + %g*x >= %g gives [%.20f, %.20f]\n", sqrcoeff.sup, lincoeff.sup, rhs.inf, res2.inf, res2.sup);
2884  SCIPdebugMessage("intersection of [%.20f, %.20f] and [%.20f, %.20f]", resultant->inf, resultant->sup, res2.inf, res2.sup);
2885  /* intersect both results */
2886  SCIPintervalIntersect(resultant, *resultant, res2);
2887  SCIPdebugPrintf(" gives [%.20f, %.20f]\n", resultant->inf, resultant->sup);
2888  }
2889  /* else res2 = [0, infty] */
2890 
2891  if( resultant->inf >= infinity || resultant->sup <= -infinity )
2892  {
2893  SCIPintervalSetEmpty(resultant);
2894  }
2895 }
2896 
2897 /** computes positive solutions of a quadratic equation with scalar coefficients
2898  *
2899  * 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$.
2900  * Implements Algorithm 3.2 from Domes and Neumaier: Constraint propagation on quadratic constraints (2008).
2901  */
2903  SCIP_Real infinity, /**< value for infinity */
2904  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
2905  SCIP_Real sqrcoeff, /**< coefficient of x^2 */
2906  SCIP_Real lincoeff, /**< coefficient of x */
2907  SCIP_Real rhs /**< right hand side of equation */
2908  )
2909 {
2910  SCIP_ROUNDMODE roundmode;
2911  SCIP_Real b;
2912  SCIP_Real delta;
2913  SCIP_Real z;
2914 
2915  assert(resultant != NULL);
2916  assert(sqrcoeff < infinity);
2917  assert(sqrcoeff > -infinity);
2918 
2919  resultant->inf = 0.0;
2920  resultant->sup = infinity;
2921 
2922  roundmode = SCIPintervalGetRoundingMode();
2923 
2925  b = lincoeff / 2.0;
2926 
2927  if( lincoeff >= 0.0 )
2928  { /* b >= 0.0 */
2929  /*SCIPintervalSetRoundingMode(SCIP_ROUND_UPWARDS); */
2930  if( rhs > 0.0 )
2931  { /* b >= 0.0 and c > 0.0 */
2932  delta = b*b + sqrcoeff*rhs;
2933  if( delta < 0.0 || (sqrcoeff == 0.0 && lincoeff == 0.0) )
2934  {
2935  SCIPintervalSetEmpty(resultant);
2936  }
2937  else
2938  {
2940  z = SCIPnextafter(sqrt(delta), SCIP_REAL_MAX);
2942  z += b;
2943  resultant->inf = negate(negate(rhs)/z);
2944  if( sqrcoeff < 0.0 )
2945  resultant->sup = z / negate(sqrcoeff);
2946  }
2947  }
2948  else
2949  { /* b >= 0.0 and c <= 0.0 */
2950  if( sqrcoeff < 0.0 )
2951  {
2952  delta = b*b + sqrcoeff*rhs;
2954  z = SCIPnextafter(sqrt(delta), SCIP_REAL_MAX);
2956  z += b;
2957  resultant->sup = z / negate(sqrcoeff);
2958  }
2959  }
2960  }
2961  else
2962  { /* b < 0.0 */
2963  if( rhs > 0.0 )
2964  { /* b < 0.0 and c > 0.0 */
2965  if( sqrcoeff > 0.0 )
2966  {
2968  delta = b*b + sqrcoeff*rhs;
2970  z = SCIPnextafter(sqrt(delta), SCIP_REAL_MAX);
2972  z += negate(b);
2973  resultant->inf = z / sqrcoeff;
2974  }
2975  else
2976  {
2977  SCIPintervalSetEmpty(resultant);
2978  }
2979  }
2980  else
2981  { /* b < 0.0 and c <= 0.0 */
2982  /* SCIPintervalSetRoundingMode(SCIP_ROUND_DOWNWARDS); */
2983  delta = b*b + sqrcoeff * rhs;
2984  if( delta >= 0.0 && sqrcoeff <= 0.0 )
2985  {
2987  z = SCIPnextafter(sqrt(delta), SCIP_REAL_MAX);
2989  z += negate(b);
2990  resultant->sup = negate(rhs/z);
2991  }
2992  /* @todo actually we could generate a hole here */
2993  }
2994  }
2995 
2996  SCIPintervalSetRoundingMode(roundmode);
2997 }
2998 
2999 /** solves a quadratic equation with interval coefficients
3000  *
3001  * 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$
3002  */
3004  SCIP_Real infinity, /**< value for infinity */
3005  SCIP_INTERVAL* resultant, /**< resultant interval of operation */
3006  SCIP_INTERVAL sqrcoeff, /**< coefficient of x^2 */
3007  SCIP_INTERVAL lincoeff, /**< coefficient of x */
3008  SCIP_INTERVAL rhs /**< right hand side of equation */
3009  )
3010 {
3011  SCIP_Real tmp;
3012  SCIP_INTERVAL xpos;
3013  SCIP_INTERVAL xneg;
3014 
3015  assert(resultant != NULL);
3016 
3017  if( sqrcoeff.inf == 0.0 && sqrcoeff.sup == 0.0 )
3018  { /* relatively easy case: x \in rhs / lincoeff */
3019  if( lincoeff.inf == 0.0 && lincoeff.sup == 0.0 )
3020  { /* equation became 0.0 \in rhs */
3021  if( rhs.inf <= 0.0 && rhs.sup >= 0.0 )
3022  SCIPintervalSetEntire(infinity, resultant);
3023  else
3024  SCIPintervalSetEmpty(resultant);
3025  }
3026  else
3027  SCIPintervalDiv(infinity, resultant, rhs, lincoeff);
3028  SCIPdebugMessage(" solving [%g,%g]*x in [%g,%g] gives [%g,%g]\n", SCIPintervalGetInf(lincoeff), SCIPintervalGetSup(lincoeff), SCIPintervalGetInf(rhs), SCIPintervalGetSup(rhs), SCIPintervalGetInf(*resultant), SCIPintervalGetSup(*resultant));
3029  return;
3030  }
3031 
3032  if( lincoeff.inf == 0.0 && lincoeff.sup == 0.0 )
3033  { /* easy case: x \in +/- sqrt(rhs/a) */
3034  SCIPintervalDiv(infinity, resultant, rhs, sqrcoeff);
3035  SCIPintervalSquareRoot(infinity, resultant, *resultant);
3036  resultant->inf = -resultant->sup;
3037  return;
3038  }
3039 
3040  /* find all x>=0 such that a*x^2+b*x = c */
3041  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &xpos, sqrcoeff, lincoeff, rhs);
3042  SCIPdebugMessage(" positive solutions of [%g,%g]*x^2 + [%g,%g]*x in [%g,%g] are [%g,%g]\n",
3043  sqrcoeff.inf, sqrcoeff.sup, lincoeff.inf, lincoeff.sup, rhs.inf, rhs.sup, xpos.inf, xpos.sup);
3044 
3045  tmp = lincoeff.inf;
3046  lincoeff.inf = -lincoeff.sup;
3047  lincoeff.sup = -tmp;
3048 
3049  /* find all x>=0 such that a*x^2-b*x = c */
3050  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &xneg, sqrcoeff, lincoeff, rhs);
3051  tmp = xneg.inf;
3052  xneg.inf = -xneg.sup;
3053  xneg.sup = -tmp;
3054  SCIPdebugMessage(" negative solutions of [%g,%g]*x^2 + [%g,%g]*x in [%g,%g] are [%g,%g]\n",
3055  sqrcoeff.inf, sqrcoeff.sup, lincoeff.inf, lincoeff.sup, rhs.inf, rhs.sup, xneg.inf, xneg.sup);
3056 
3057  SCIPintervalUnify(resultant, xpos, xneg);
3058  SCIPdebugMessage(" unify gives [%g,%g]\n", SCIPintervalGetInf(*resultant), SCIPintervalGetSup(*resultant));
3059 }
3060 
3061 /** stores range of bivariate quadratic term in resultant
3062  * 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$
3063  * NOTE: the operations are not applied rounding-safe here
3064  */
3066  SCIP_Real infinity, /**< value for infinity in interval arithmetics */
3067  SCIP_INTERVAL* resultant, /**< buffer where to store result of operation */
3068  SCIP_Real ax, /**< square coefficient of x */
3069  SCIP_Real ay, /**< square coefficient of y */
3070  SCIP_Real axy, /**< bilinear coefficients */
3071  SCIP_Real bx, /**< linear coefficient of x */
3072  SCIP_Real by, /**< linear coefficient of y */
3073  SCIP_INTERVAL xbnds, /**< bounds on x */
3074  SCIP_INTERVAL ybnds /**< bounds on y */
3075  )
3076 {
3077  /* we use double double precision and finally widen the computed range by 1e-8% to compensate for not computing rounding-safe here */
3078  SCIP_Real minval;
3079  SCIP_Real maxval;
3080  SCIP_Real val;
3081  SCIP_Real x;
3082  SCIP_Real y;
3083  SCIP_Real denom;
3084 
3085  assert(resultant != NULL);
3086  assert(xbnds.inf <= xbnds.sup);
3087  assert(ybnds.inf <= ybnds.sup);
3088 
3089  /* if we are separable, then fall back to use SCIPintervalQuad two times and add */
3090  if( axy == 0.0 )
3091  {
3092  SCIP_INTERVAL tmp;
3093 
3094  SCIPintervalSet(&tmp, bx);
3095  SCIPintervalQuad(infinity, resultant, ax, tmp, xbnds);
3096 
3097  SCIPintervalSet(&tmp, by);
3098  SCIPintervalQuad(infinity, &tmp, ay, tmp, ybnds);
3099 
3100  SCIPintervalAdd(infinity, resultant, *resultant, tmp);
3101 
3102  return;
3103  }
3104 
3105  SCIPintervalSet(resultant, 0.0);
3106 
3107  minval = infinity;
3108  maxval = -infinity;
3109 
3110  /* check minima/maxima of expression */
3111  denom = 4.0 * ax * ay - axy * axy;
3112  if( REALABS(denom) > 1e-9 )
3113  {
3114  x = (axy * by - 2.0 * ay * bx) / denom;
3115  y = (axy * bx - 2.0 * ax * by) / denom;
3116  if( xbnds.inf <= x && x <= xbnds.sup && ybnds.inf <= y && y <= ybnds.sup )
3117  {
3118  val = (axy * bx * by - ay * bx * bx - ax * by * by) / denom;
3119  minval = MIN(val, minval);
3120  maxval = MAX(val, maxval);
3121  }
3122  }
3123  else if( REALABS(2.0 * ay * bx - axy * by) <= 1e-9 )
3124  {
3125  /* The whole line (x, -bx/axy - (axy/2ay) x) defines an extreme point with value -ay bx^2 / axy^2
3126  * If x is unbounded, then there is an (x,y) with y in ybnds where the extreme value is assumed.
3127  * 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.
3128  */
3129  if( xbnds.inf <= -infinity && xbnds.sup >= infinity )
3130  {
3131  val = -ay * bx * bx / (axy * axy);
3132  minval = MIN(val, minval);
3133  maxval = MAX(val, maxval);
3134  }
3135  }
3136 
3137  /* check boundary of box xbnds x ybnds */
3138 
3139  if( xbnds.inf <= -infinity )
3140  {
3141  /* check value for x -> -infinity */
3142  if( ax > 0.0 )
3143  maxval = infinity;
3144  else if( ax < 0.0 )
3145  minval = -infinity;
3146  else if( ax == 0.0 )
3147  {
3148  /* bivar(x,y) tends to -(bx+axy y) * infinity */
3149 
3150  if( ybnds.inf <= -infinity )
3151  val = (axy < 0.0 ? -infinity : infinity);
3152  else if( bx + axy * ybnds.inf < 0.0 )
3153  val = infinity;
3154  else
3155  val = -infinity;
3156  minval = MIN(val, minval);
3157  maxval = MAX(val, maxval);
3158 
3159  if( ybnds.sup >= infinity )
3160  val = (axy < 0.0 ? infinity : -infinity);
3161  else if( bx + axy * ybnds.sup < 0.0 )
3162  val = infinity;
3163  else
3164  val = -infinity;
3165  minval = MIN(val, minval);
3166  maxval = MAX(val, maxval);
3167  }
3168  }
3169  else
3170  {
3171  /* get range of bivar(xbnds.inf, y) for y in ybnds */
3172  SCIP_INTERVAL tmp;
3173  SCIP_INTERVAL ycoef;
3174 
3175  SCIPintervalSet(&ycoef, axy * xbnds.inf + by);
3176  SCIPintervalQuad(infinity, &tmp, ay, ycoef, ybnds);
3177  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ax * xbnds.inf * xbnds.inf + bx * xbnds.inf));
3178  minval = MIN(tmp.inf, minval);
3179  maxval = MAX(tmp.sup, maxval);
3180  }
3181 
3182  if( xbnds.sup >= infinity )
3183  {
3184  /* check value for x -> infinity */
3185  if( ax > 0.0 )
3186  maxval = infinity;
3187  else if( ax < 0.0 )
3188  minval = -infinity;
3189  else if( ax == 0.0 )
3190  {
3191  /* bivar(x,y) tends to (bx+axy y) * infinity */
3192 
3193  if( ybnds.inf <= -infinity )
3194  val = (axy > 0.0 ? -infinity : infinity);
3195  else if( bx + axy * ybnds.inf > 0.0 )
3196  val = infinity;
3197  else
3198  val = -infinity;
3199  minval = MIN(val, minval);
3200  maxval = MAX(val, maxval);
3201 
3202  if( ybnds.sup >= infinity )
3203  val = (axy > 0.0 ? infinity : -infinity);
3204  else if( bx + axy * ybnds.sup > 0.0 )
3205  val = infinity;
3206  else
3207  val = -infinity;
3208  minval = MIN(val, minval);
3209  maxval = MAX(val, maxval);
3210  }
3211  }
3212  else
3213  {
3214  /* get range of bivar(xbnds.sup, y) for y in ybnds */
3215  SCIP_INTERVAL tmp;
3216  SCIP_INTERVAL ycoef;
3217 
3218  SCIPintervalSet(&ycoef, axy * xbnds.sup + by);
3219  SCIPintervalQuad(infinity, &tmp, ay, ycoef, ybnds);
3220  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ax * xbnds.sup * xbnds.sup + bx * xbnds.sup));
3221  minval = MIN(tmp.inf, minval);
3222  maxval = MAX(tmp.sup, maxval);
3223  }
3224 
3225  if( ybnds.inf <= -infinity )
3226  {
3227  /* check value for y -> -infinity */
3228  if( ay > 0.0 )
3229  maxval = infinity;
3230  else if( ay < 0.0 )
3231  minval = -infinity;
3232  else if( ay == 0.0 )
3233  {
3234  /* bivar(x,y) tends to -(by+axy x) * infinity */
3235 
3236  if( xbnds.inf <= -infinity )
3237  val = (axy < 0.0 ? -infinity : infinity);
3238  else if( by + axy * xbnds.inf < 0.0 )
3239  val = infinity;
3240  else
3241  val = -infinity;
3242  minval = MIN(val, minval);
3243  maxval = MAX(val, maxval);
3244 
3245  if( xbnds.sup >= infinity )
3246  val = (axy < 0.0 ? infinity : -infinity);
3247  else if( by + axy * xbnds.sup < 0.0 )
3248  val = infinity;
3249  else
3250  val = -infinity;
3251  minval = MIN(val, minval);
3252  maxval = MAX(val, maxval);
3253  }
3254  }
3255  else
3256  {
3257  /* get range of bivar(x, ybnds.inf) for x in xbnds */
3258  SCIP_INTERVAL tmp;
3259  SCIP_INTERVAL xcoef;
3260 
3261  SCIPintervalSet(&xcoef, axy * ybnds.inf + bx);
3262  SCIPintervalQuad(infinity, &tmp, ax, xcoef, xbnds);
3263  SCIPintervalAddScalar(infinity, &tmp, tmp, ay * ybnds.inf * ybnds.inf + by * ybnds.inf);
3264  minval = MIN(tmp.inf, minval);
3265  maxval = MAX(tmp.sup, maxval);
3266  }
3267 
3268  if( ybnds.sup >= infinity )
3269  {
3270  /* check value for y -> infinity */
3271  if( ay > 0.0 )
3272  maxval = infinity;
3273  else if( ay < 0.0 )
3274  minval = -infinity;
3275  else if( ay == 0.0 )
3276  {
3277  /* bivar(x,y) tends to (by+axy x) * infinity */
3278 
3279  if( xbnds.inf <= -infinity )
3280  val = (axy > 0.0 ? -infinity : infinity);
3281  else if( by + axy * xbnds.inf > 0.0 )
3282  val = infinity;
3283  else
3284  val = -infinity;
3285  minval = MIN(val, minval);
3286  maxval = MAX(val, maxval);
3287 
3288  if( xbnds.sup >= infinity )
3289  val = (axy > 0.0 ? infinity : -infinity);
3290  else if( by + axy * xbnds.sup > 0.0 )
3291  val = infinity;
3292  else
3293  val = -infinity;
3294  minval = MIN(val, minval);
3295  maxval = MAX(val, maxval);
3296  }
3297  }
3298  else
3299  {
3300  /* get range of bivar(x, ybnds.sup) for x in xbnds */
3301  SCIP_INTERVAL tmp;
3302  SCIP_INTERVAL xcoef;
3303 
3304  SCIPintervalSet(&xcoef, axy * ybnds.sup + bx);
3305  SCIPintervalQuad(infinity, &tmp, ax, xcoef, xbnds);
3306  SCIPintervalAddScalar(infinity, &tmp, tmp, (SCIP_Real)(ay * ybnds.sup * ybnds.sup + by * ybnds.sup));
3307  minval = MIN(tmp.inf, minval);
3308  maxval = MAX(tmp.sup, maxval);
3309  }
3310 
3311  minval -= 1e-10 * REALABS(minval);
3312  maxval += 1e-10 * REALABS(maxval);
3313  SCIPintervalSetBounds(resultant, (SCIP_Real)minval, (SCIP_Real)maxval);
3314 
3315  SCIPdebugMessage("range for %gx^2 + %gy^2 + %gxy + %gx + %gy = [%g, %g] for x = [%g, %g], y=[%g, %g]\n",
3316  ax, ay, axy, bx, by, minval, maxval, xbnds.inf, xbnds.sup, ybnds.inf, ybnds.sup);
3317 }
3318 
3319 /** solves a bivariate quadratic equation for the first variable
3320  * given scalars ax, ay, axy, bx and by, and intervals for x, y, and rhs,
3321  * 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$
3322  * NOTE: the operations are not applied rounding-safe here
3323  */
3325  SCIP_Real infinity, /**< value for infinity in interval arithmetics */
3326  SCIP_INTERVAL* resultant, /**< buffer where to store result of operation */
3327  SCIP_Real ax, /**< square coefficient of x */
3328  SCIP_Real ay, /**< square coefficient of y */
3329  SCIP_Real axy, /**< bilinear coefficients */
3330  SCIP_Real bx, /**< linear coefficient of x */
3331  SCIP_Real by, /**< linear coefficient of y */
3332  SCIP_INTERVAL rhs, /**< right-hand-side of equation */
3333  SCIP_INTERVAL xbnds, /**< bounds on x */
3334  SCIP_INTERVAL ybnds /**< bounds on y */
3335  )
3336 {
3337  /* we use double double precision and finally widen the computed range by 1e-8% to compensate for not computing rounding-safe here */
3338  SCIP_Real val;
3339 
3340  assert(resultant != NULL);
3341 
3342  if( axy == 0.0 )
3343  {
3344  /* if axy == 0, fall back to SCIPintervalSolveUnivariateQuadExpression */
3345  SCIP_INTERVAL ytermrng;
3346  SCIP_INTERVAL sqrcoef;
3347  SCIP_INTERVAL lincoef;
3348  SCIP_INTERVAL pos;
3349  SCIP_INTERVAL neg;
3350 
3351  SCIPintervalSet(&lincoef, by);
3352  SCIPintervalQuad(infinity, &ytermrng, ay, lincoef, ybnds);
3353  SCIPintervalSub(infinity, &rhs, rhs, ytermrng);
3354 
3355  SCIPintervalSet(&sqrcoef, ax);
3356 
3357  /* get positive solutions, if of interest */
3358  if( xbnds.sup >= 0.0 )
3359  {
3360  SCIPintervalSet(&lincoef, bx);
3361  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &pos, sqrcoef, lincoef, rhs);
3362  SCIPintervalIntersect(&pos, pos, xbnds);
3363  }
3364  else
3365  SCIPintervalSetEmpty(&pos);
3366 
3367  /* get negative solutions, if of interest */
3368  if( xbnds.inf < 0.0 )
3369  {
3370  SCIPintervalSet(&lincoef, -bx);
3371  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &neg, sqrcoef, lincoef, rhs);
3372  if( !SCIPintervalIsEmpty(infinity, neg) )
3373  {
3374  SCIPintervalSetBounds(&neg, -neg.sup, -neg.inf);
3375  SCIPintervalIntersect(&neg, neg, xbnds);
3376  }
3377  }
3378  else
3379  SCIPintervalSetEmpty(&neg);
3380 
3381  SCIPintervalUnify(resultant, pos, neg);
3382 
3383  return;
3384  }
3385 
3386  if( ax < 0.0 )
3387  {
3388  SCIP_Real tmp;
3389  tmp = rhs.inf;
3390  rhs.inf = -rhs.sup;
3391  rhs.sup = -tmp;
3392 
3393  SCIPintervalSolveBivariateQuadExpressionAllScalar(infinity, resultant, -ax, -ay, -axy, -bx, -by, rhs, xbnds, ybnds);
3394  return;
3395  }
3396  assert(ax >= 0.0);
3397 
3398  *resultant = xbnds;
3399 
3400  if( ax > 0.0 )
3401  {
3402  SCIP_Real sqrtax;
3403  SCIP_Real minvalleft;
3404  SCIP_Real maxvalleft;
3405  SCIP_Real minvalright;
3406  SCIP_Real maxvalright;
3407  SCIP_Real ymin;
3408  SCIP_Real rcoef_y;
3409  SCIP_Real rcoef_yy;
3410  SCIP_Real rcoef_const;
3411 
3412  sqrtax = sqrt(ax);
3413 
3414  /* rewrite equation as (sqrt(ax)x + b(y))^2 \in r(rhs,y), where
3415  * b(y) = (bx + axy y)/(2sqrt(ax)), r(rhs,y) = rhs - ay y^2 - by y + b(y)^2
3416  *
3417  * -> r(rhs,y) = bx^2/(4ax) + rhs + (axy bx/(2ax) - by)*y + (axy^2/(4ax) - ay)*y^2
3418  */
3419  rcoef_y = axy * bx / (2.0*ax) - by;
3420  rcoef_yy = axy * axy / (4.0*ax) - ay;
3421  rcoef_const = bx * bx / (4.0*ax);
3422 
3423 #define CALCB(y) ((bx + axy * (y)) / (2.0 * sqrtax))
3424 #define CALCR(c,y) (rcoef_const + (c) + (rcoef_y + rcoef_yy * (y)) * (y))
3425 
3426  /* check whether r(rhs,y) is always negative */
3427  if( rhs.sup < infinity )
3428  {
3429  SCIP_INTERVAL ycoef;
3430  SCIP_Real ub;
3431 
3432  SCIPintervalSet(&ycoef, (SCIP_Real)rcoef_y);
3433  ub = (SCIP_Real)(SCIPintervalQuadUpperBound(infinity, (SCIP_Real)rcoef_yy, ycoef, ybnds) + rhs.sup + rcoef_const);
3434 
3435  if( EPSN(ub, 1e-9) )
3436  {
3437  SCIPintervalSetEmpty(resultant);
3438  return;
3439  }
3440  else if( ub < 0.0 )
3441  {
3442  /* 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
3443  * thus, we relax rhs a be feasible a bit (-ub would be sufficient, but that would put us exactly onto the boundary)
3444  * see also #1861
3445  */
3446  rhs.sup += -2.0*ub;
3447  }
3448  }
3449 
3450  /* we have sqrt(ax)x \in (-sqrt(r(rhs,y))-b(y)) \cup (sqrt(r(rhs,y))-b(y))
3451  * compute minima and maxima of both functions such that
3452  *
3453  * [minvalleft, maxvalleft ] = -sqrt(r(rhs,y))-b(y)
3454  * [minvalright, maxvalright] = sqrt(r(rhs,y))-b(y)
3455  */
3456 
3457  minvalleft = infinity;
3458  maxvalleft = -infinity;
3459  minvalright = infinity;
3460  maxvalright = -infinity;
3461 
3462  if( rhs.sup >= infinity )
3463  {
3464  /* we can't do much if rhs.sup is infinite
3465  * but we may do a bit of xbnds isn't too huge and rhs.inf > -infinity
3466  */
3467  minvalleft = -infinity;
3468  maxvalright = infinity;
3469  }
3470 
3471  /* evaluate at lower bound of y, as long as r(rhs,ylb) > 0 */
3472  if( ybnds.inf <= -infinity )
3473  {
3474  /* check limit of +/-sqrt(r(rhs,y))-b(y) for y -> -infty */
3475  if( !EPSZ(ay, 1e-9) && axy * axy >= 4.0 * ax * ay )
3476  {
3477  if( axy < 0.0 )
3478  {
3479  minvalleft = -infinity;
3480 
3481  if( ay > 0.0 )
3482  minvalright = -infinity;
3483  else
3484  maxvalright = infinity;
3485  }
3486  else
3487  {
3488  maxvalright = infinity;
3489 
3490  if( ay > 0.0 )
3491  maxvalleft = infinity;
3492  else
3493  minvalleft = -infinity;
3494  }
3495  }
3496  else if( !EPSZ(ay, 1e-9) )
3497  {
3498  /* here axy * axy < 4 * ax * ay, so need to check for zeros of r(rhs,y), which is done below */
3499  }
3500  else
3501  {
3502  /* here ay = 0.0, which gives a limit of -by/2 for -sqrt(r(rhs,y))-b(y) */
3503  minvalleft = -by / 2.0;
3504  maxvalleft = -by / 2.0;
3505  /* here ay = 0.0, which gives a limit of +infinity for sqrt(r(rhs,y))-b(y) */
3506  maxvalright = infinity;
3507  }
3508  }
3509  else
3510  {
3511  SCIP_Real b;
3512  SCIP_Real c;
3513 
3514  b = CALCB(ybnds.inf);
3515 
3516  if( rhs.sup < infinity )
3517  {
3518  c = CALCR(rhs.sup, ybnds.inf);
3519 
3520  if( c > 0.0 )
3521  {
3522  SCIP_Real sqrtc;
3523 
3524  sqrtc = sqrt(c);
3525  minvalleft = MIN(-sqrtc - b, minvalleft);
3526  maxvalright = MAX( sqrtc - b, maxvalright);
3527  }
3528  }
3529 
3530  if( rhs.inf > -infinity )
3531  {
3532  c = CALCR(rhs.inf, ybnds.inf);
3533 
3534  if( c > 0.0 )
3535  {
3536  SCIP_Real sqrtc;
3537 
3538  sqrtc = sqrt(c);
3539  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3540  minvalright = MIN( sqrtc - b, minvalright);
3541  }
3542  }
3543  }
3544 
3545  /* evaluate at upper bound of y, as long as r(rhs, yub) > 0 */
3546  if( ybnds.sup >= infinity )
3547  {
3548  /* check limit of +/-sqrt(r(rhs,y))-b(y) for y -> +infty */
3549  if( !EPSZ(ay, 1e-9) && axy * axy >= 4.0 * ax * ay )
3550  {
3551  if( axy > 0.0 )
3552  {
3553  minvalleft = -infinity;
3554 
3555  if( ay > 0.0 )
3556  minvalright = -infinity;
3557  else
3558  maxvalright = infinity;
3559  }
3560  else
3561  {
3562  maxvalright = infinity;
3563 
3564  if( ay > 0.0 )
3565  maxvalleft = infinity;
3566  else
3567  minvalleft = -infinity;
3568  }
3569  }
3570  else if( !EPSZ(ay, 1e-9) )
3571  {
3572  /* here axy * axy < 4 * ax * ay, so need to check for zeros of r(rhs,y), which will happen below */
3573  }
3574  else
3575  {
3576  /* here ay = 0.0, which gives a limit of -infinity for -sqrt(r(rhs,y))-b(y) */
3577  minvalleft = -infinity;
3578  /* here ay = 0.0, which gives a limit of -by/2 for sqrt(r(rhs,y))-b(y) */
3579  minvalright = MIN(minvalright, -by / 2.0);
3580  maxvalright = MAX(maxvalright, -by / 2.0);
3581  }
3582  }
3583  else
3584  {
3585  SCIP_Real b;
3586  SCIP_Real c;
3587 
3588  b = CALCB(ybnds.sup);
3589 
3590  if( rhs.sup < infinity )
3591  {
3592  c = CALCR(rhs.sup, ybnds.sup);
3593 
3594  if( c > 0.0 )
3595  {
3596  SCIP_Real sqrtc;
3597 
3598  sqrtc = sqrt(c);
3599  minvalleft = MIN(-sqrtc - b, minvalleft);
3600  maxvalright = MAX( sqrtc - b, maxvalright);
3601  }
3602  }
3603 
3604  if( rhs.inf > -infinity )
3605  {
3606  c = CALCR(rhs.inf, ybnds.sup);
3607 
3608  if( c > 0.0 )
3609  {
3610  SCIP_Real sqrtc;
3611 
3612  sqrtc = sqrt(c);
3613  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3614  minvalright = MIN( sqrtc - b, minvalright);
3615  }
3616  }
3617  }
3618 
3619  /* evaluate at ymin = y_{_,+}, if inside ybnds
3620  * if ay = 0 or 2ay*bx == axy*by, then there is no ymin */
3621  if( !EPSZ(ay, 1e-9) )
3622  {
3623  if( REALABS(axy*axy - 4.0*ax*ay) > 1e-9 )
3624  {
3625  SCIP_Real sqrtterm;
3626 
3627  if( rhs.sup < infinity )
3628  {
3629  sqrtterm = axy * axy * ay * (ay * bx * bx - axy * bx * by + ax * by * by - axy * axy * rhs.sup + 4.0 * ax * ay * rhs.sup);
3630  if( !EPSN(sqrtterm, 1e-9) )
3631  {
3632  sqrtterm = sqrt(MAX(sqrtterm, 0.0));
3633  /* check first candidate for extreme points of +/-sqrt(rhs(r,y))-b(y) */
3634  ymin = axy * ay * bx - 2.0 * ax * ay * by - sqrtterm;
3635  ymin /= ay;
3636  ymin /= 4.0 * ax * ay - axy * axy;
3637 
3638  if( ymin > ybnds.inf && ymin < ybnds.sup )
3639  {
3640  SCIP_Real b;
3641  SCIP_Real c;
3642 
3643  b = CALCB(ymin);
3644  c = CALCR(rhs.sup, ymin);
3645 
3646  if( c > 0.0 )
3647  {
3648  SCIP_Real sqrtc;
3649 
3650  sqrtc = sqrt(c);
3651  minvalleft = MIN(-sqrtc - b, minvalleft);
3652  maxvalright = MAX( sqrtc - b, maxvalright);
3653  }
3654  }
3655 
3656  /* check second candidate for extreme points of +/-sqrt(rhs(r,y))-b(y) */
3657  ymin = axy * ay * bx - 2.0 * ax * ay * by + sqrtterm;
3658  ymin /= ay;
3659  ymin /= 4.0 * ax * ay - axy * axy;
3660 
3661  if( ymin > ybnds.inf && ymin < ybnds.sup )
3662  {
3663  SCIP_Real b;
3664  SCIP_Real c;
3665 
3666  b = CALCB(ymin);
3667  c = CALCR(rhs.sup, ymin);
3668 
3669  if( c > 0.0 )
3670  {
3671  SCIP_Real sqrtc;
3672 
3673  sqrtc = sqrt(c);
3674  minvalleft = MIN(-sqrtc - b, minvalleft);
3675  maxvalright = MAX( sqrtc - b, maxvalright);
3676  }
3677  }
3678  }
3679  }
3680 
3681  if( rhs.inf > -infinity )
3682  {
3683  sqrtterm = axy * axy * ay * (ay * bx * bx - axy * bx * by + ax * by * by - axy * axy * rhs.inf + 4.0 * ax * ay * rhs.inf);
3684  if( !EPSN(sqrtterm, 1e-9) )
3685  {
3686  sqrtterm = sqrt(MAX(sqrtterm, 0.0));
3687  /* check first candidate for extreme points of +/-sqrt(r(rhs,y))-b(y) */
3688  ymin = axy * ay * bx - 2.0 * ax * ay * by - sqrtterm;
3689  ymin /= ay;
3690  ymin /= 4.0 * ax * ay - axy * axy;
3691 
3692  if( ymin > ybnds.inf && ymin < ybnds.sup )
3693  {
3694  SCIP_Real b;
3695  SCIP_Real c;
3696 
3697  b = CALCB(ymin);
3698  c = CALCR(rhs.inf, ymin);
3699 
3700  if( c > 0.0 )
3701  {
3702  SCIP_Real sqrtc;
3703 
3704  sqrtc = sqrt(c);
3705  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3706  minvalright = MIN( sqrtc - b, minvalright);
3707  }
3708  }
3709 
3710  /* check second candidate for extreme points of +/-sqrt(c(y))-b(y) */
3711  ymin = axy * ay * bx - 2.0 * ax * ay * by + sqrtterm;
3712  ymin /= ay;
3713  ymin /= 4.0 * ax * ay - axy * axy;
3714 
3715  if( ymin > ybnds.inf && ymin < ybnds.sup )
3716  {
3717  SCIP_Real b;
3718  SCIP_Real c;
3719 
3720  b = CALCB(ymin);
3721  c = CALCR(rhs.inf, ymin);
3722 
3723  if( c > 0.0 )
3724  {
3725  SCIP_Real sqrtc;
3726 
3727  sqrtc = sqrt(c);
3728  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3729  minvalright = MIN( sqrtc - b, minvalright);
3730  }
3731  }
3732  }
3733  }
3734 
3735  }
3736  else if( REALABS(2.0 * ay * bx - axy * by) > 1e-9 )
3737  {
3738  if( rhs.sup < infinity )
3739  {
3740  ymin = - (4.0 * ay * bx * by - axy * by * by + 4.0 * axy * ay * rhs.sup);
3741  ymin /= 4.0 * ay;
3742  ymin /= 2.0 * ay * bx - axy * by;
3743 
3744  if( ymin > ybnds.inf && ymin < ybnds.sup )
3745  {
3746  SCIP_Real b;
3747  SCIP_Real c;
3748 
3749  b = CALCB(ymin);
3750  c = CALCR(rhs.sup, ymin);
3751 
3752  if( c > 0.0 )
3753  {
3754  SCIP_Real sqrtc;
3755 
3756  sqrtc = sqrt(c);
3757  minvalleft = MIN(-sqrtc - b, minvalleft);
3758  maxvalright = MAX( sqrtc - b, maxvalright);
3759  }
3760  }
3761  }
3762 
3763  if( rhs.inf > -infinity )
3764  {
3765  ymin = - (4.0 * ay * bx * by - axy * by * by + 4.0 * axy * ay * rhs.inf);
3766  ymin /= 4.0 * ay;
3767  ymin /= 2.0 * ay * bx - axy * by;
3768 
3769  if( ymin > ybnds.inf && ymin < ybnds.sup )
3770  {
3771  SCIP_Real b;
3772  SCIP_Real c;
3773 
3774  b = CALCB(ymin);
3775  c = CALCR(rhs.inf, ymin);
3776 
3777  if( c > 0.0 )
3778  {
3779  SCIP_Real sqrtc;
3780 
3781  sqrtc = sqrt(c);
3782  maxvalleft = MAX(-sqrtc - b, maxvalleft);
3783  minvalright = MIN( sqrtc - b, minvalright);
3784  }
3785  }
3786  }
3787  }
3788  }
3789 
3790  /* evaluate the case r(rhs,y) = 0, which is to min/max -b(y) w.r.t. r(rhs,y) = 0, y in ybnds
3791  * with the above assignments
3792  * rcoef_y = axy * bx / (2.0*ax) - by;
3793  * rcoef_yy = axy * axy / (4.0*ax) - ay;
3794  * rcoef_const = bx * bx / (4.0*ax);
3795  * we have r(rhs,y) = rhs + rcoef_const + rcoef_y * y + rcoef_yy * y^2
3796  *
3797  * thus, r(rhs,y) = 0 <-> rcoef_y * y + rcoef_yy * y^2 in -rhs - rcoef_const
3798  *
3799  */
3800  {
3801  SCIP_INTERVAL rcoef_yy_int;
3802  SCIP_INTERVAL rcoef_y_int;
3803  SCIP_INTERVAL rhs2;
3804  SCIP_Real b;
3805 
3806  /* setup rcoef_yy, rcoef_y and -rhs-rcoef_const as intervals */
3807  SCIPintervalSet(&rcoef_yy_int, (SCIP_Real)rcoef_yy);
3808  SCIPintervalSet(&rcoef_y_int, (SCIP_Real)rcoef_y);
3809  SCIPintervalSetBounds(&rhs2, (SCIP_Real)(-rhs.sup - rcoef_const), (SCIP_Real)(-rhs.inf - rcoef_const));
3810 
3811  /* first find all y >= 0 such that rcoef_y * y + rcoef_yy * y^2 in -rhs2, if ybnds.sup >= 0.0
3812  * and evaluate -b(y) w.r.t. these values
3813  */
3814  if( ybnds.sup >= 0.0 )
3815  {
3816  SCIP_INTERVAL ypos;
3817 
3818  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &ypos, rcoef_yy_int, rcoef_y_int, rhs2);
3819  SCIPintervalIntersect(&ypos, ypos, ybnds);
3820  if( !SCIPintervalIsEmpty(infinity, ypos) )
3821  {
3822  assert(ypos.inf >= 0.0); /* we computed only positive solutions above */
3823  b = CALCB(ypos.inf);
3824  minvalleft = MIN(minvalleft, -b);
3825  maxvalleft = MAX(maxvalleft, -b);
3826  minvalright = MIN(minvalright, -b);
3827  maxvalright = MAX(maxvalright, -b);
3828 
3829  if( ypos.sup < infinity )
3830  {
3831  b = CALCB(ypos.sup);
3832  minvalleft = MIN(minvalleft, -b);
3833  maxvalleft = MAX(maxvalleft, -b);
3834  minvalright = MIN(minvalright, -b);
3835  maxvalright = MAX(maxvalright, -b);
3836  }
3837  else
3838  {
3839  /* -b(y) = - (bx + axy * y) / (2.0 * sqrt(ax)) -> -sign(axy)*infinity for y -> infinity */
3840  if( axy > 0.0 )
3841  {
3842  minvalleft = -infinity;
3843  minvalright = -infinity;
3844  }
3845  else
3846  {
3847  maxvalleft = infinity;
3848  maxvalright = infinity;
3849  }
3850  }
3851  }
3852  }
3853 
3854  /* next find all y <= 0 such that rcoef_y * y + rcoef_yy * y^2 in -rhs2, if ybnds.inf < 0.0
3855  * and evaluate -b(y) w.r.t. these values
3856  * (the case y fixed to 0 has been handled in the ybnds.sup >= 0 case above)
3857  */
3858  if( ybnds.inf < 0.0 )
3859  {
3860  SCIP_INTERVAL yneg;
3861 
3862  /* find all y >= 0 such that -rcoef_y * y + rcoef_yy * y^2 in -rhs2 and then negate y */
3863  SCIPintervalSet(&rcoef_y_int, -(SCIP_Real)rcoef_y);
3864  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, &yneg, rcoef_yy_int, rcoef_y_int, rhs2);
3865  if( !SCIPintervalIsEmpty(infinity, yneg) )
3866  {
3867  SCIPintervalSetBounds(&yneg, -yneg.sup, -yneg.inf);
3868  SCIPintervalIntersect(&yneg, yneg, ybnds);
3869  }
3870  if( !SCIPintervalIsEmpty(infinity, yneg) )
3871  {
3872  if( yneg.inf > -infinity )
3873  {
3874  b = CALCB(yneg.inf);
3875  minvalleft = MIN(minvalleft, -b);
3876  maxvalleft = MAX(maxvalleft, -b);
3877  minvalright = MIN(minvalright, -b);
3878  maxvalright = MAX(maxvalright, -b);
3879  }
3880  else
3881  {
3882  /* -b(y) = - (bx + axy * y) / (2.0 * sqrt(ax)) -> sign(axy)*infinity for y -> -infinity */
3883  if( axy > 0.0 )
3884  {
3885  maxvalleft = infinity;
3886  maxvalright = infinity;
3887  }
3888  else
3889  {
3890  minvalleft = -infinity;
3891  minvalright = -infinity;
3892  }
3893  }
3894 
3895  assert(yneg.sup <= 0.0); /* we computed only negative solutions above */
3896  b = CALCB(yneg.sup);
3897  minvalleft = MIN(minvalleft, -b);
3898  maxvalleft = MAX(maxvalleft, -b);
3899  minvalright = MIN(minvalright, -b);
3900  maxvalright = MAX(maxvalright, -b);
3901  }
3902  }
3903  }
3904 
3905  if( rhs.inf > -infinity && xbnds.inf > -infinity && EPSGT(xbnds.inf, maxvalleft / sqrtax, 1e-9) )
3906  {
3907  /* 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)
3908  * 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) */
3909  assert(EPSGE(minvalright, minvalleft, 1e-9)); /* right interval should not be above lower bound of left interval */
3910  if( minvalright > -infinity )
3911  {
3912  assert(minvalright < infinity);
3913  resultant->inf = (SCIP_Real)(minvalright / sqrtax);
3914  }
3915  }
3916  else
3917  {
3918  /* otherwise, tighten lower bound of sqrt(ax)*x to lower bound of -sqrt(r(rhs,y))-b(y) */
3919  if( minvalleft > -infinity )
3920  {
3921  assert(minvalleft < infinity);
3922  resultant->inf = (SCIP_Real)(minvalleft / sqrtax);
3923  }
3924  }
3925 
3926  if( rhs.inf > -infinity && xbnds.sup < infinity && EPSLT(xbnds.sup, minvalright / sqrtax, 1e-9) )
3927  {
3928  /* 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)
3929  * 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) */
3930  assert(EPSLE(maxvalleft, maxvalright, 1e-9)); /* left interval should not be above upper bound of right interval */
3931  if( maxvalleft < infinity )
3932  {
3933  assert(maxvalleft > -infinity);
3934  resultant->sup = (SCIP_Real)(maxvalleft / sqrtax);
3935  }
3936  }
3937  else
3938  {
3939  /* otherwise, tighten upper bound of sqrt(ax)*x to upper bound of sqrt(r(rhs,y))-b(y) */
3940  if( maxvalright < infinity )
3941  {
3942  assert(maxvalright > -infinity);
3943  resultant->sup = (SCIP_Real)(maxvalright / sqrtax);
3944  }
3945  }
3946 
3947  resultant->inf -= 1e-10 * REALABS(resultant->inf);
3948  resultant->sup += 1e-10 * REALABS(resultant->sup);
3949 
3950 #undef CALCB
3951 #undef CALCR
3952  }
3953  else
3954  {
3955  /* case ax == 0 */
3956 
3957  SCIP_Real c;
3958  SCIP_Real d;
3959  SCIP_Real ymin;
3960  SCIP_Real minval;
3961  SCIP_Real maxval;
3962 
3963  /* consider -bx / axy in ybnds, i.e., bx + axy y can be 0 */
3964  if( EPSGE(-bx / axy, ybnds.inf, 1e-9) && EPSLE(-bx / axy, ybnds.sup, 1e-9) )
3965  {
3966  /* write as (bx + axy y) * x \in (c - ay y^2 - by y)
3967  * and estimate bx + axy y and c - ay y^2 - by y by intervals independently
3968  * @todo can we do better, as in the case where bx + axy y is bounded away from 0?
3969  */
3970  SCIP_INTERVAL lincoef;
3971  SCIP_INTERVAL myrhs;
3972  SCIP_INTERVAL tmp;
3973 
3974  if( xbnds.inf < 0.0 && xbnds.sup > 0.0 )
3975  {
3976  /* if (bx + axy y) can be arbitrary small and x be both positive and negative,
3977  * then nothing we can tighten here
3978  */
3979  SCIPintervalSetBounds(resultant, xbnds.inf, xbnds.sup);
3980  return;
3981  }
3982 
3983  /* store interval for (bx + axy y) in lincoef */
3984  SCIPintervalMulScalar(infinity, &lincoef, ybnds, axy);
3985  SCIPintervalAddScalar(infinity, &lincoef, lincoef, bx);
3986 
3987  /* store interval for (c - ay y^2 - by y) in myrhs */
3988  SCIPintervalSet(&tmp, by);
3989  SCIPintervalQuad(infinity, &tmp, ay, tmp, ybnds);
3990  SCIPintervalSub(infinity, &myrhs, rhs, tmp);
3991 
3992  if( lincoef.inf == 0.0 && lincoef.sup == 0.0 )
3993  {
3994  /* equation became 0.0 \in myrhs */
3995  if( myrhs.inf <= 0.0 && myrhs.sup >= 0.0 )
3996  SCIPintervalSetEntire(infinity, resultant);
3997  else
3998  SCIPintervalSetEmpty(resultant);
3999  }
4000  else if( xbnds.inf >= 0.0 )
4001  {
4002  SCIP_INTERVAL a_;
4003 
4004  /* need only positive solutions */
4005  SCIPintervalSet(&a_, 0.0);
4006  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, resultant, a_, lincoef, myrhs);
4007  }
4008  else
4009  {
4010  SCIP_INTERVAL a_;
4011 
4012  assert(xbnds.sup <= 0.0);
4013 
4014  /* need only negative solutions */
4015  SCIPintervalSet(&a_, 0.0);
4016  SCIPintervalSetBounds(&lincoef, -lincoef.sup, -lincoef.inf);
4017  SCIPintervalSolveUnivariateQuadExpressionPositive(infinity, resultant, a_, lincoef, myrhs);
4018  if( !SCIPintervalIsEmpty(infinity, *resultant) )
4019  SCIPintervalSetBounds(resultant, -resultant->sup, -resultant->inf);
4020  }
4021 
4022  SCIPintervalIntersect(resultant, xbnds, *resultant);
4023 
4024  return;
4025  }
4026 
4027  minval = infinity;
4028  maxval = -infinity;
4029 
4030  /* compute a lower bound on x */
4031  if( bx + axy * (axy > 0.0 ? ybnds.inf : ybnds.sup) > 0.0 )
4032  c = rhs.inf;
4033  else
4034  c = rhs.sup;
4035 
4036  if( c > -infinity && c < infinity )
4037  {
4038  if( ybnds.inf <= -infinity )
4039  {
4040  /* limit is ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4041  if( EPSZ(ay, 1e-9) )
4042  minval = -by / axy;
4043  else if( ay * axy < 0.0 )
4044  minval = -infinity;
4045  }
4046  else
4047  {
4048  val = (c - ay * ybnds.inf * ybnds.inf - by * ybnds.inf) / (bx + axy * ybnds.inf);
4049  minval = MIN(val, minval);
4050  }
4051 
4052  if( ybnds.sup >= infinity )
4053  {
4054  /* limit is -ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4055  if( EPSZ(ay, 1e-9) )
4056  minval = MIN(minval, -by / axy);
4057  else if( ay * axy > 0.0 )
4058  minval = -infinity;
4059  }
4060  else
4061  {
4062  val = (c - ay * ybnds.sup * ybnds.sup - by * ybnds.sup) / (bx + axy * ybnds.sup);
4063  minval = MIN(val, minval);
4064  }
4065 
4066  if( !EPSZ(ay, 1e-9) )
4067  {
4068  d = ay * (ay * bx * bx - axy * (bx * by + axy * c));
4069  if( !EPSN(d, 1e-9) )
4070  {
4071  ymin = -ay * bx + sqrt(MAX(d, 0.0));
4072  ymin /= axy * ay;
4073 
4074  if( ymin > ybnds.inf && ymin < ybnds.sup )
4075  {
4076  assert(bx + axy * ymin != 0.0);
4077 
4078  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4079  minval = MIN(val, minval);
4080  }
4081 
4082  ymin = -ay * bx - sqrt(MAX(d, 0.0));
4083  ymin /= axy * ay;
4084 
4085  if(ymin > ybnds.inf && ymin < ybnds.sup )
4086  {
4087  assert(bx + axy * ymin != 0.0);
4088 
4089  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4090  minval = MIN(val, minval);
4091  }
4092  }
4093  }
4094  }
4095  else
4096  {
4097  minval = -infinity;
4098  }
4099 
4100  /* compute an upper bound on x */
4101  if( bx + axy * (axy > 0.0 ? ybnds.inf : ybnds.sup) > 0.0 )
4102  c = rhs.sup;
4103  else
4104  c = rhs.inf;
4105 
4106  if( c > -infinity && c < infinity )
4107  {
4108  if( ybnds.inf <= -infinity )
4109  {
4110  /* limit is ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4111  if( EPSZ(ay, 1e-9) )
4112  maxval = -by / axy;
4113  else if( ay * axy > 0.0 )
4114  maxval = infinity;
4115  }
4116  else
4117  {
4118  val = (c - ay * ybnds.inf * ybnds.inf - by * ybnds.inf) / (bx + axy * ybnds.inf);
4119  maxval = MAX(val, maxval);
4120  }
4121 
4122  if( ybnds.sup >= infinity )
4123  {
4124  /* limit is -ay/axy * infinity if ay != 0.0 and -by/axy otherwise */
4125  if( EPSZ(ay, 1e-9) )
4126  maxval = MAX(maxval, -by / axy);
4127  else if( ay * axy < 0.0 )
4128  maxval = infinity;
4129  }
4130  else
4131  {
4132  val = (c - ay * ybnds.sup * ybnds.sup - by * ybnds.sup) / (bx + axy * ybnds.sup);
4133  maxval = MAX(val, maxval);
4134  }
4135 
4136  if( !EPSZ(ay, 1e-9) )
4137  {
4138  d = ay * (ay * bx * bx - axy * (bx * by + axy * c));
4139  if( !EPSN(d, 1e-9) )
4140  {
4141  ymin = ay * bx + sqrt(MAX(d, 0.0));
4142  ymin /= axy * ay;
4143 
4144  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4145  maxval = MAX(val, maxval);
4146 
4147  ymin = ay * bx - sqrt(MAX(d, 0.0));
4148  ymin /= axy * ay;
4149 
4150  val = (c - ay * ymin * ymin - by * ymin) / (bx + axy * ymin);
4151  maxval = MAX(val, maxval);
4152  }
4153  }
4154  }
4155  else
4156  {
4157  maxval = infinity;
4158  }
4159 
4160  if( minval > -infinity )
4161  resultant->inf = minval - 1e-10 * REALABS(minval);
4162  else
4163  resultant->inf = -infinity;
4164  if( maxval < infinity )
4165  resultant->sup = maxval + 1e-10 * REALABS(maxval);
4166  else
4167  resultant->sup = infinity;
4168  SCIPintervalIntersect(resultant, *resultant, xbnds);
4169  }
4170 }
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)