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