Scippy

    SCIP

    Solving Constraint Integer Programs

    misc.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 misc.c
    26 * @ingroup OTHER_CFILES
    27 * @brief miscellaneous methods
    28 * @author Tobias Achterberg
    29 * @author Gerald Gamrath
    30 * @author Stefan Heinz
    31 * @author Michael Winkler
    32 * @author Kati Wolter
    33 * @author Gregor Hendel
    34 */
    35
    36/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    37
    38#define _USE_MATH_DEFINES /* to get M_SQRT2 on Windows */ /*lint !750 */
    39
    40#include <assert.h>
    41#include <string.h>
    42#include <stdarg.h>
    43#include <stdio.h>
    44#include <stdlib.h>
    45#include <errno.h>
    46#include <ctype.h>
    47#include <math.h>
    48#ifndef _MSC_VER
    49#include <strings.h>
    50#endif
    51
    52#include "scip/def.h"
    53#include "scip/pub_message.h"
    54#include "scip/misc.h"
    55#include "scip/intervalarith.h"
    56#include "scip/pub_misc.h"
    57#include "scip/rational.h"
    58
    59#ifndef NDEBUG
    60#include "scip/struct_misc.h"
    61#endif
    62
    63/*
    64 * methods for statistical tests
    65 */
    66
    67/**< contains all critical values for a one-sided two sample t-test up to 15 degrees of freedom
    68 * a critical value represents a threshold for rejecting the null-hypothesis in hypothesis testing at
    69 * a certain confidence level;
    70 *
    71 * access through method SCIPstudentTGetCriticalValue()
    72 *
    73 * source: German Wikipedia
    74 *
    75 * for confidence levels
    76 * c =
    77 * 0.75 0.875 0.90 0.95 0.975 (one-sided)
    78 * 0.50 0.750 0.80 0.90 0.950 (two-sided)
    79 *
    80 */
    81static const SCIP_Real studentt_quartiles[] = { /* df:*/
    82 1.000, 2.414, 3.078, 6.314, 12.706, /* 1 */
    83 0.816, 1.604, 1.886, 2.920, 4.303, /* 2 */
    84 0.765, 1.423, 1.638, 2.353, 3.182, /* 3 */
    85 0.741, 1.344, 1.533, 2.132, 2.776, /* 4 */
    86 0.727, 1.301, 1.476, 2.015, 2.571, /* 5 */
    87 0.718, 1.273, 1.440, 1.943, 2.447, /* 6 */
    88 0.711, 1.254, 1.415, 1.895, 2.365, /* 7 */
    89 0.706, 1.240, 1.397, 1.860, 2.306, /* 8 */
    90 0.703, 1.230, 1.383, 1.833, 2.262, /* 9 */
    91 0.700, 1.221, 1.372, 1.812, 2.228, /* 10 */
    92 0.697, 1.214, 1.363, 1.796, 2.201, /* 11 */
    93 0.695, 1.209, 1.356, 1.782, 2.179, /* 12 */
    94 0.694, 1.204, 1.350, 1.771, 2.160, /* 13 */
    95 0.692, 1.200, 1.345, 1.761, 2.145, /* 14 */
    96 0.691, 1.197, 1.341, 1.753, 2.131 /* 15 */
    97};
    98
    99/**< critical values for higher degrees of freedom of Student-T distribution for the same error probabilities; infact,
    100 * these are critical values of the standard normal distribution with mean 0 and variance 1
    101 */
    103 0.674, 1.150, 1.282, 1.645, 1.960
    104};
    105
    106/** the maximum degrees of freedom represented before switching to normal approximation */
    107static const int studentt_maxdf = sizeof(studentt_quartiles)/(5 * sizeof(SCIP_Real));
    108
    109/** get critical value of a Student-T distribution for a given number of degrees of freedom at a confidence level */
    111 SCIP_CONFIDENCELEVEL clevel, /**< (one-sided) confidence level */
    112 int df /**< degrees of freedom */
    113 )
    114{
    115 if( df > studentt_maxdf )
    116 return studentt_quartilesabove[(int)clevel];
    117 else
    118 return studentt_quartiles[(int)clevel + 5 * (df - 1)];
    119}
    120
    121/** compute a t-value for the hypothesis that x and y are from the same population; Assuming that
    122 * x and y represent normally distributed random samples with equal variance, the returned value
    123 * comes from a Student-T distribution with countx + county - 2 degrees of freedom; this
    124 * value can be compared with a critical value (see also SCIPstudentTGetCriticalValue()) at
    125 * a predefined confidence level for checking if x and y significantly differ in location
    126 */
    128 SCIP_Real meanx, /**< the mean of the first distribution */
    129 SCIP_Real meany, /**< the mean of the second distribution */
    130 SCIP_Real variancex, /**< the variance of the x-distribution */
    131 SCIP_Real variancey, /**< the variance of the y-distribution */
    132 SCIP_Real countx, /**< number of samples of x */
    133 SCIP_Real county /**< number of samples of y */
    134 )
    135{
    136 SCIP_Real pooledvariance;
    137 SCIP_Real tresult;
    138
    139 /* too few samples */
    140 if( countx < 1.9 || county < 1.9 )
    141 return SCIP_INVALID;
    142
    143 /* pooled variance is the weighted average of the two variances */
    144 pooledvariance = (countx - 1) * variancex + (county - 1) * variancey;
    145 pooledvariance /= (countx + county - 2);
    146
    147 /* a variance close to zero means the distributions are basically constant */
    148 pooledvariance = MAX(pooledvariance, 1e-9);
    149
    150 /* tresult can be understood as realization of a Student-T distributed variable with
    151 * countx + county - 2 degrees of freedom
    152 */
    153 tresult = (meanx - meany) / sqrt(pooledvariance);
    154 tresult *= sqrt(countx * county / (countx + county));
    155
    156 return tresult;
    157}
    158
    159/** returns the value of the Gauss error function evaluated at a given point */
    161 SCIP_Real x /**< value to evaluate */
    162 )
    163{
    164#ifdef _WIN32
    165 SCIP_Real a1, a2, a3, a4, a5, p, t, y;
    166 int sign;
    167
    168 a1 = 0.254829592;
    169 a2 = -0.284496736;
    170 a3 = 1.421413741;
    171 a4 = -1.453152027;
    172 a5 = 1.061405429;
    173 p = 0.3275911;
    174
    175 sign = (x >= 0) ? 1 : -1;
    176 x = REALABS(x);
    177
    178 t = 1.0/(1.0 + p*x);
    179 y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);
    180 return sign * y;
    181#else
    182 return erf(x);
    183#endif
    184}
    185
    186/** get critical value of a standard normal distribution at a given confidence level */
    188 SCIP_CONFIDENCELEVEL clevel /**< (one-sided) confidence level */
    189 )
    190{
    191 return studentt_quartilesabove[(int)clevel];
    192}
    193
    194/** calculates the cumulative distribution P(-infinity <= x <= value) that a normally distributed
    195 * random variable x takes a value between -infinity and parameter \p value.
    196 *
    197 * The distribution is given by the respective mean and deviation. This implementation
    198 * uses the error function SCIPerf().
    199 */
    201 SCIP_Real mean, /**< the mean value of the distribution */
    202 SCIP_Real variance, /**< the square of the deviation of the distribution */
    203 SCIP_Real value /**< the upper limit of the calculated distribution integral */
    204 )
    205{
    206 SCIP_Real normvalue;
    208
    209 /* we need to calculate the standard deviation from the variance */
    210 assert(variance >= -1e-9);
    211 if( variance < 1e-9 )
    212 std = 0.0;
    213 else
    214 std = sqrt(variance);
    215
    216 /* special treatment for zero variance */
    217 if( std < 1e-9 )
    218 {
    219 if( value < mean + 1e-9 )
    220 return 1.0;
    221 else
    222 return 0.0;
    223 }
    224 assert( std != 0.0 ); /* for lint */
    225
    226 /* scale and translate to standard normal distribution. Factor sqrt(2) is needed for SCIPerf() function */
    227 normvalue = (value - mean)/(std * M_SQRT2);
    228
    229 SCIPdebugMessage(" Normalized value %g = ( %g - %g ) / (%g * 1.4142136)\n", normvalue, value, mean, std);
    230
    231 /* calculate the cumulative distribution function for normvalue. For negative normvalues, we negate the normvalue and
    232 * use the oddness of the SCIPerf()-function; special treatment for values close to zero.
    233 */
    234 if( normvalue < 1e-9 && normvalue > -1e-9 )
    235 return .5;
    236 else if( normvalue > 0 )
    237 {
    238 SCIP_Real erfresult;
    239
    240 erfresult = SCIPerf(normvalue);
    241 return erfresult / 2.0 + 0.5;
    242 }
    243 else
    244 {
    245 SCIP_Real erfresult;
    246
    247 erfresult = SCIPerf(-normvalue);
    248
    249 return 0.5 - erfresult / 2.0;
    250 }
    251}
    252
    253/*
    254 * SCIP regression methods
    255 */
    256
    257/** returns the number of observations of this regression */
    259 SCIP_REGRESSION* regression /**< regression data structure */
    260 )
    261{
    262 assert(regression != NULL);
    263
    264 return regression->nobservations;
    265}
    266
    267/** return the current slope of the regression */
    269 SCIP_REGRESSION* regression /**< regression data structure */
    270 )
    271{
    272 assert(regression != NULL);
    273
    274 return regression->slope;
    275}
    276
    277/** get the current y-intercept of the regression */
    279 SCIP_REGRESSION* regression /**< regression data structure */
    280 )
    281{
    282 assert(regression != NULL);
    283
    284 return regression->intercept;
    285}
    286
    287/** recomputes regression coefficients from available observation data */
    288static
    290 SCIP_REGRESSION* regression /**< regression data structure */
    291 )
    292{
    293 /* regression coefficients require two or more observations and variance in x */
    294 if( regression->nobservations <= 1 || EPSZ(regression->variancesumx, 1e-9) )
    295 {
    296 regression->slope = SCIP_INVALID;
    297 regression->intercept = SCIP_INVALID;
    298 regression->corrcoef = SCIP_INVALID;
    299 }
    300 else if( EPSZ(regression->variancesumy, 1e-9) )
    301 {
    302 /* if there is no variance in the y's (but in the x's), the regression line is horizontal with y-intercept through the mean y */
    303 regression->slope = 0.0;
    304 regression->corrcoef = 0.0;
    305 regression->intercept = regression->meany;
    306 }
    307 else
    308 {
    309 /* we ruled this case out already, but to please some compilers... */
    310 assert(regression->variancesumx > 0.0);
    311 assert(regression->variancesumy > 0.0);
    312
    313 /* compute slope */
    314 regression->slope = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) / regression->variancesumx;
    315
    316 /* compute y-intercept */
    317 regression->intercept = regression->meany - regression->slope * regression->meanx;
    318
    319 /* compute empirical correlation coefficient */
    320 regression->corrcoef = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) /
    321 sqrt(regression->variancesumx * regression->variancesumy);
    322 }
    323}
    324
    325/* incremental update of statistics describing mean and variance */
    326static
    328 SCIP_Real value, /**< current value to be added to incremental statistics */
    329 SCIP_Real* meanptr, /**< pointer to value of current mean */
    330 SCIP_Real* sumvarptr, /**< pointer to the value of the current variance sum term */
    331 int nobservations, /**< total number of observations */
    332 SCIP_Bool add /**< TRUE if the value should be added, FALSE for removing it */
    333 )
    334{
    335 SCIP_Real oldmean;
    336 SCIP_Real addfactor;
    337 assert(meanptr != NULL);
    338 assert(sumvarptr != NULL);
    339 assert(nobservations > 0 || add);
    340
    341 addfactor = add ? 1.0 : -1.0;
    342
    343 oldmean = *meanptr;
    344 *meanptr = oldmean + addfactor * (value - oldmean)/(SCIP_Real)nobservations;
    345 *sumvarptr += addfactor * (value - oldmean) * (value - (*meanptr));
    346
    347 /* it may happen that *sumvarptr is slightly negative, especially after a series of add/removal operations */
    348 assert(*sumvarptr >= -1e-4);
    349 *sumvarptr = MAX(0.0, *sumvarptr);
    350}
    351
    352/** removes an observation (x,y) from the regression */
    354 SCIP_REGRESSION* regression, /**< regression data structure */
    355 SCIP_Real x, /**< X of observation */
    356 SCIP_Real y /**< Y of the observation */
    357 )
    358{
    359 assert(regression != NULL);
    360 assert(regression->nobservations > 0);
    361
    362 /* simply call the reset function in the case of a single remaining observation to avoid numerical troubles */
    363 if( regression->nobservations == 1 )
    364 {
    365 SCIPregressionReset(regression);
    366 }
    367 else
    368 {
    369 SCIP_Bool add = FALSE;
    370 --regression->nobservations;
    371
    372 /* decrement individual means and variances */
    373 incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
    374 incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
    375
    376 /* decrement product sum */
    377 regression->sumxy -= (x * y);
    378 }
    379
    380 /* recompute regression parameters */
    381 regressionRecompute(regression);
    382}
    383
    384/** update regression by a new observation (x,y) */
    386 SCIP_REGRESSION* regression, /**< regression data structure */
    387 SCIP_Real x, /**< X of observation */
    388 SCIP_Real y /**< Y of the observation */
    389 )
    390{
    391 SCIP_Bool add = TRUE;
    392 assert(regression != NULL);
    393
    394 ++(regression->nobservations);
    395 incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
    396 incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
    397
    398 regression->sumxy += x * y;
    399
    400 regressionRecompute(regression);
    401}
    402
    403/** reset regression data structure */
    405 SCIP_REGRESSION* regression /**< regression data structure */
    406 )
    407{
    408 regression->intercept = SCIP_INVALID;
    409 regression->slope = SCIP_INVALID;
    410 regression->corrcoef = SCIP_INVALID;
    411 regression->meanx = 0;
    412 regression->variancesumx = 0;
    413 regression->sumxy = 0;
    414 regression->meany = 0;
    415 regression->variancesumy = 0;
    416 regression->nobservations = 0;
    417}
    418
    419/** creates and resets a regression */
    421 SCIP_REGRESSION** regression /**< regression data structure */
    422 )
    423{
    424 assert(regression != NULL);
    425
    426 /* allocate necessary memory */
    427 SCIP_ALLOC (BMSallocMemory(regression) );
    428
    429 /* reset the regression */
    430 SCIPregressionReset(*regression);
    431
    432 return SCIP_OKAY;
    433}
    434
    435/** creates and resets a regression */
    437 SCIP_REGRESSION** regression /**< regression data structure */
    438 )
    439{
    440 BMSfreeMemory(regression);
    441}
    442
    443/** calculate memory size for dynamically allocated arrays (copied from scip/set.c) */
    444static
    446 int initsize, /**< initial size of array */
    447 SCIP_Real growfac, /**< growing factor of array */
    448 int num /**< minimum number of entries to store */
    449 )
    450{
    451 int size;
    452
    453 assert(initsize >= 0);
    454 assert(growfac >= 1.0);
    455 assert(num >= 0);
    456
    457 if( growfac == 1.0 )
    458 size = MAX(initsize, num);
    459 else
    460 {
    461 int oldsize;
    462
    463 /* calculate the size with this loop, such that the resulting numbers are always the same (-> block memory) */
    464 initsize = MAX(initsize, 4);
    465 size = initsize;
    466 oldsize = size - 1;
    467
    468 /* second condition checks against overflow */
    469 while( size < num && size > oldsize )
    470 {
    471 oldsize = size;
    472 size = (int)(growfac * size + initsize);
    473 }
    474
    475 /* if an overflow happened, set the correct value */
    476 if( size <= oldsize )
    477 size = num;
    478 }
    479
    480 assert(size >= initsize);
    481 assert(size >= num);
    482
    483 return size;
    484}
    485
    486/*
    487 * GML graphical printing methods
    488 * For a detailed format decription see http://docs.yworks.com/yfiles/doc/developers-guide/gml.html
    489 */
    490
    491#define GMLNODEWIDTH 120.0
    492#define GMLNODEHEIGTH 30.0
    493#define GMLFONTSIZE 13
    494#define GMLNODETYPE "rectangle"
    495#define GMLNODEFILLCOLOR "#ff0000"
    496#define GMLEDGECOLOR "black"
    497#define GMLNODEBORDERCOLOR "#000000"
    498
    499
    500/** writes a node section to the given graph file */
    502 FILE* file, /**< file to write to */
    503 unsigned int id, /**< id of the node */
    504 const char* label, /**< label of the node */
    505 const char* nodetype, /**< type of the node, or NULL */
    506 const char* fillcolor, /**< color of the node's interior, or NULL */
    507 const char* bordercolor /**< color of the node's border, or NULL */
    508 )
    509{
    510 assert(file != NULL);
    511 assert(label != NULL);
    512
    513 fprintf(file, " node\n");
    514 fprintf(file, " [\n");
    515 fprintf(file, " id %u\n", id);
    516 fprintf(file, " label \"%s\"\n", label);
    517 fprintf(file, " graphics\n");
    518 fprintf(file, " [\n");
    519 fprintf(file, " w %g\n", GMLNODEWIDTH);
    520 fprintf(file, " h %g\n", GMLNODEHEIGTH);
    521
    522 if( nodetype != NULL )
    523 fprintf(file, " type \"%s\"\n", nodetype);
    524 else
    525 fprintf(file, " type \"%s\"\n", GMLNODETYPE);
    526
    527 if( fillcolor != NULL )
    528 fprintf(file, " fill \"%s\"\n", fillcolor);
    529 else
    530 fprintf(file, " fill \"%s\"\n", GMLNODEFILLCOLOR);
    531
    532 if( bordercolor != NULL )
    533 fprintf(file, " outline \"%s\"\n", bordercolor);
    534 else
    535 fprintf(file, " outline \"%s\"\n", GMLNODEBORDERCOLOR);
    536
    537 fprintf(file, " ]\n");
    538 fprintf(file, " LabelGraphics\n");
    539 fprintf(file, " [\n");
    540 fprintf(file, " text \"%s\"\n", label);
    541 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
    542 fprintf(file, " fontName \"Dialog\"\n");
    543 fprintf(file, " anchor \"c\"\n");
    544 fprintf(file, " ]\n");
    545 fprintf(file, " ]\n");
    546}
    547
    548/** writes a node section including weight to the given graph file */
    550 FILE* file, /**< file to write to */
    551 unsigned int id, /**< id of the node */
    552 const char* label, /**< label of the node */
    553 const char* nodetype, /**< type of the node, or NULL */
    554 const char* fillcolor, /**< color of the node's interior, or NULL */
    555 const char* bordercolor, /**< color of the node's border, or NULL */
    556 SCIP_Real weight /**< weight of node */
    557 )
    558{
    559 assert(file != NULL);
    560 assert(label != NULL);
    561
    562 fprintf(file, " node\n");
    563 fprintf(file, " [\n");
    564 fprintf(file, " id %u\n", id);
    565 fprintf(file, " label \"%s\"\n", label);
    566 fprintf(file, " weight %g\n", weight);
    567 fprintf(file, " graphics\n");
    568 fprintf(file, " [\n");
    569 fprintf(file, " w %g\n", GMLNODEWIDTH);
    570 fprintf(file, " h %g\n", GMLNODEHEIGTH);
    571
    572 if( nodetype != NULL )
    573 fprintf(file, " type \"%s\"\n", nodetype);
    574 else
    575 fprintf(file, " type \"%s\"\n", GMLNODETYPE);
    576
    577 if( fillcolor != NULL )
    578 fprintf(file, " fill \"%s\"\n", fillcolor);
    579 else
    580 fprintf(file, " fill \"%s\"\n", GMLNODEFILLCOLOR);
    581
    582 if( bordercolor != NULL )
    583 fprintf(file, " outline \"%s\"\n", bordercolor);
    584 else
    585 fprintf(file, " outline \"%s\"\n", GMLNODEBORDERCOLOR);
    586
    587 fprintf(file, " ]\n");
    588 fprintf(file, " LabelGraphics\n");
    589 fprintf(file, " [\n");
    590 fprintf(file, " text \"%s\"\n", label);
    591 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
    592 fprintf(file, " fontName \"Dialog\"\n");
    593 fprintf(file, " anchor \"c\"\n");
    594 fprintf(file, " ]\n");
    595 fprintf(file, " ]\n");
    596}
    597
    598/** writes an edge section to the given graph file */
    600 FILE* file, /**< file to write to */
    601 unsigned int source, /**< source node id of the node */
    602 unsigned int target, /**< target node id of the edge */
    603 const char* label, /**< label of the edge, or NULL */
    604 const char* color /**< color of the edge, or NULL */
    605 )
    606{
    607 assert(file != NULL);
    608
    609 fprintf(file, " edge\n");
    610 fprintf(file, " [\n");
    611 fprintf(file, " source %u\n", source);
    612 fprintf(file, " target %u\n", target);
    613
    614 if( label != NULL)
    615 fprintf(file, " label \"%s\"\n", label);
    616
    617 fprintf(file, " graphics\n");
    618 fprintf(file, " [\n");
    619
    620 if( color != NULL )
    621 fprintf(file, " fill \"%s\"\n", color);
    622 else
    623 fprintf(file, " fill \"%s\"\n", GMLEDGECOLOR);
    624
    625 /* fprintf(file, " arrow \"both\"\n"); */
    626 fprintf(file, " ]\n");
    627
    628 if( label != NULL)
    629 {
    630 fprintf(file, " LabelGraphics\n");
    631 fprintf(file, " [\n");
    632 fprintf(file, " text \"%s\"\n", label);
    633 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
    634 fprintf(file, " fontName \"Dialog\"\n");
    635 fprintf(file, " anchor \"c\"\n");
    636 fprintf(file, " ]\n");
    637 }
    638
    639 fprintf(file, " ]\n");
    640}
    641
    642/** writes an arc section to the given graph file */
    644 FILE* file, /**< file to write to */
    645 unsigned int source, /**< source node id of the node */
    646 unsigned int target, /**< target node id of the edge */
    647 const char* label, /**< label of the edge, or NULL */
    648 const char* color /**< color of the edge, or NULL */
    649 )
    650{
    651 assert(file != NULL);
    652
    653 fprintf(file, " edge\n");
    654 fprintf(file, " [\n");
    655 fprintf(file, " source %u\n", source);
    656 fprintf(file, " target %u\n", target);
    657
    658 if( label != NULL)
    659 fprintf(file, " label \"%s\"\n", label);
    660
    661 fprintf(file, " graphics\n");
    662 fprintf(file, " [\n");
    663
    664 if( color != NULL )
    665 fprintf(file, " fill \"%s\"\n", color);
    666 else
    667 fprintf(file, " fill \"%s\"\n", GMLEDGECOLOR);
    668
    669 fprintf(file, " targetArrow \"standard\"\n");
    670 fprintf(file, " ]\n");
    671
    672 if( label != NULL)
    673 {
    674 fprintf(file, " LabelGraphics\n");
    675 fprintf(file, " [\n");
    676 fprintf(file, " text \"%s\"\n", label);
    677 fprintf(file, " fontSize %d\n", GMLFONTSIZE);
    678 fprintf(file, " fontName \"Dialog\"\n");
    679 fprintf(file, " anchor \"c\"\n");
    680 fprintf(file, " ]\n");
    681 }
    682
    683 fprintf(file, " ]\n");
    684}
    685
    686/** writes the starting line to a GML graph file, does not open a file */
    688 FILE* file, /**< file to write to */
    689 SCIP_Bool directed /**< is the graph directed */
    690 )
    691{
    692 assert(file != NULL);
    693
    694 fprintf(file, "graph\n");
    695 fprintf(file, "[\n");
    696 fprintf(file, " hierarchic 1\n");
    697
    698 if( directed )
    699 fprintf(file, " directed 1\n");
    700}
    701
    702/** writes the ending lines to a GML graph file, does not close a file */
    704 FILE* file /**< file to close */
    705 )
    706{
    707 assert(file != NULL);
    708
    709 fprintf(file, "]\n");
    710}
    711
    712/**
    713 * writes the opening line to a dot graph file, does not open a file
    714 */
    716 FILE* file /**< file to write to */
    717 )
    718{
    719 assert(file != NULL);
    720
    721 fprintf(file, "digraph G {\n");
    722}
    723
    724/** adds a node to the dot graph */
    726 FILE* file, /**< file to write to */
    727 int node, /**< node id */
    728 const char* label, /**< node label */
    729 const char* nodetype, /**< type of the node, or NULL */
    730 const char* fillcolor, /**< color of the node's interior, or NULL */
    731 const char* bordercolor /**< color of the node's border, or NULL */
    732 )
    733{
    734 assert(file != NULL);
    735
    736 fprintf(file, "\t%d [shape=\"%s\", label=\"%s\", style=\"filled\", fillcolor=\"%s\", color=\"%s\"];\n", node, nodetype, label, fillcolor, bordercolor);
    737}
    738
    739/** adds an arc (edge) between two nodes in the dot graph */
    741 FILE* file, /**< file to write to */
    742 int source, /**< source node id of the node */
    743 int target, /**< target node id of the edge */
    744 const char* color /**< color of the edge, or NULL */
    745 )
    746{
    747 assert(file != NULL);
    748
    749 fprintf(file, "\t%d -> %d [color=\"%s\"];\n", source, target, color);
    750}
    751
    752/** writes the closing line to a dot graph file, does not close a file */
    754 FILE* file /**< file to write to */
    755 )
    756{
    757 assert(file != NULL);
    758
    759 fprintf(file, "}\n");
    760}
    761
    762/*
    763 * Sparse solution
    764 */
    765
    766/** creates a sparse solution */
    768 SCIP_SPARSESOL** sparsesol, /**< pointer to store the created sparse solution */
    769 SCIP_VAR** vars, /**< variables in the sparse solution, must not contain continuous
    770 * variables
    771 */
    772 int nvars, /**< number of variables to store, size of the lower and upper bound
    773 * arrays
    774 */
    775 SCIP_Bool cleared /**< should the lower and upper bound arrays be cleared (entries set to 0) */
    776 )
    777{
    778 assert(sparsesol != NULL);
    779 assert(nvars == 0 || vars != NULL);
    780 assert(nvars >= 0);
    781
    782 SCIP_ALLOC( BMSallocMemory(sparsesol) );
    783
    784#ifndef NDEBUG
    785 {
    786 int v;
    787
    788 for( v = nvars - 1; v >= 0; --v )
    789 {
    790 assert(vars[v] != NULL);
    791 /* assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS); */
    792 }
    793 }
    794#endif
    795
    796 /* copy variables */
    797 SCIP_ALLOC( BMSduplicateMemoryArray(&((*sparsesol)->vars), vars, nvars) );
    798
    799 /* create bound arrays */
    800 if( cleared )
    801 {
    802 SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->lbvalues), nvars) );
    803 SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->ubvalues), nvars) );
    804 }
    805 else
    806 {
    807 SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->lbvalues), nvars) );
    808 SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->ubvalues), nvars) );
    809 }
    810
    811 (*sparsesol)->nvars = nvars;
    812
    813 return SCIP_OKAY;
    814}
    815
    816/** frees sparse solution */
    818 SCIP_SPARSESOL** sparsesol /**< pointer to a sparse solution */
    819 )
    820{
    821 assert(sparsesol != NULL);
    822 assert(*sparsesol != NULL);
    823
    824 BMSfreeMemoryArray(&((*sparsesol)->vars));
    825 BMSfreeMemoryArray(&((*sparsesol)->ubvalues));
    826 BMSfreeMemoryArray(&((*sparsesol)->lbvalues));
    827 BMSfreeMemory(sparsesol);
    828}
    829
    830/** returns the variables stored in the given sparse solution */
    832 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
    833 )
    834{
    835 assert(sparsesol != NULL);
    836
    837 return sparsesol->vars;
    838}
    839
    840/** returns the number of variables stored in the given sparse solution */
    842 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
    843 )
    844{
    845 assert(sparsesol != NULL);
    846
    847 return sparsesol->nvars;
    848}
    849
    850/** returns the lower bound array for all variables for a given sparse solution */
    852 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
    853 )
    854{
    855 assert(sparsesol != NULL);
    856
    857 return sparsesol->lbvalues;
    858}
    859
    860/** returns the upper bound array for all variables for a given sparse solution */
    862 SCIP_SPARSESOL* sparsesol /**< a sparse solution */
    863 )
    864{
    865 assert(sparsesol != NULL);
    866
    867 return sparsesol->ubvalues;
    868}
    869
    870/** constructs the first solution of sparse solution (all variables are set to their lower bound value */
    872 SCIP_SPARSESOL* sparsesol, /**< sparse solutions */
    873 SCIP_Longint* sol, /**< array to store the first solution */
    874 int nvars /**< number of variables */
    875 )
    876{
    877 SCIP_Longint* lbvalues;
    878 int v;
    879
    880 assert(sparsesol != NULL);
    881 assert(sol != NULL);
    882 assert(nvars == SCIPsparseSolGetNVars(sparsesol));
    883
    884 lbvalues = SCIPsparseSolGetLbs(sparsesol);
    885 assert(lbvalues != NULL);
    886
    887 /* copy the lower bounds */
    888 for( v = 0; v < nvars; ++v )
    889 sol[v] = lbvalues[v];
    890}
    891
    892
    893/** constructs the next solution of the sparse solution and return whether there was one more or not */
    895 SCIP_SPARSESOL* sparsesol, /**< sparse solutions */
    896 SCIP_Longint* sol, /**< current solution array which get changed to the next solution */
    897 int nvars /**< number of variables */
    898 )
    899{
    900 SCIP_Longint* lbvalues;
    901 SCIP_Longint* ubvalues;
    902 SCIP_Longint lbvalue;
    903 SCIP_Longint ubvalue;
    904 SCIP_Bool singular;
    905 SCIP_Bool carryflag;
    906 int v;
    907
    908 assert(sparsesol != NULL);
    909 assert(sol != NULL);
    910
    911 if( nvars == 0 )
    912 return FALSE;
    913
    914 assert(nvars > 0);
    915 assert(nvars == SCIPsparseSolGetNVars(sparsesol));
    916
    917 lbvalues = SCIPsparseSolGetLbs(sparsesol);
    918 ubvalues = SCIPsparseSolGetUbs(sparsesol);
    919 assert(lbvalues != NULL);
    920 assert(ubvalues != NULL);
    921
    922 singular = TRUE;
    923 carryflag = FALSE;
    924
    925 for( v = 0; v < nvars; ++v )
    926 {
    927 lbvalue = lbvalues[v];
    928 ubvalue = ubvalues[v];
    929
    930 if( lbvalue < ubvalue )
    931 {
    932 singular = FALSE;
    933
    934 if( carryflag == FALSE )
    935 {
    936 if( sol[v] < ubvalue )
    937 {
    938 sol[v]++;
    939 break;
    940 }
    941 else
    942 {
    943 /* in the last solution the variables v was set to its upper bound value */
    944 assert(sol[v] == ubvalue);
    945 sol[v] = lbvalue;
    946 carryflag = TRUE;
    947 }
    948 }
    949 else
    950 {
    951 if( sol[v] < ubvalue )
    952 {
    953 sol[v]++;
    954 carryflag = FALSE;
    955 break;
    956 }
    957 else
    958 {
    959 assert(sol[v] == ubvalue);
    960 sol[v] = lbvalue;
    961 }
    962 }
    963 }
    964 }
    965
    966 return (!carryflag && !singular);
    967}
    968
    969
    970/*
    971 * Queue
    972 */
    973
    974/** resizes element memory to hold at least the given number of elements */
    975static
    977 SCIP_QUEUE* queue, /**< pointer to a queue */
    978 int minsize /**< minimal number of storable elements */
    979 )
    980{
    981 assert(queue != NULL);
    982 assert(minsize > 0);
    983
    984 if( minsize <= queue->size )
    985 return SCIP_OKAY;
    986
    987 queue->size = MAX(minsize, (int)(queue->size * queue->sizefac));
    988 SCIP_ALLOC( BMSreallocMemoryArray(&queue->slots, queue->size) );
    989
    990 return SCIP_OKAY;
    991}
    992
    993
    994/** creates a (circular) queue, best used if the size will be fixed or will not be increased that much */
    996 SCIP_QUEUE** queue, /**< pointer to the new queue */
    997 int initsize, /**< initial number of available element slots */
    998 SCIP_Real sizefac /**< memory growing factor applied, if more element slots are needed */
    999 )
    1000{
    1001 assert(queue != NULL);
    1002
    1003 initsize = MAX(1, initsize);
    1004 sizefac = MAX(1.0, sizefac);
    1005
    1006 SCIP_ALLOC( BMSallocMemory(queue) );
    1007 (*queue)->firstfree = 0;
    1008 (*queue)->firstused = -1;
    1009 (*queue)->size = 0;
    1010 (*queue)->sizefac = sizefac;
    1011 (*queue)->slots = NULL;
    1012
    1013 SCIP_CALL( queueResize(*queue, initsize) );
    1014
    1015 return SCIP_OKAY;
    1016}
    1017
    1018/** frees queue, but not the data elements themselves */
    1020 SCIP_QUEUE** queue /**< pointer to a queue */
    1021 )
    1022{
    1023 assert(queue != NULL);
    1024
    1025 BMSfreeMemoryArray(&(*queue)->slots);
    1026 BMSfreeMemory(queue);
    1027}
    1028
    1029/** clears the queue, but doesn't free the data elements themselves */
    1031 SCIP_QUEUE* queue /**< queue */
    1032 )
    1033{
    1034 assert(queue != NULL);
    1035
    1036 queue->firstfree = 0;
    1037 queue->firstused = -1;
    1038}
    1039
    1040/** reallocates slots if queue is necessary */
    1041static
    1043 SCIP_QUEUE* queue /**< queue */
    1044 )
    1045{
    1046 if( queue->firstfree == queue->firstused )
    1047 {
    1048 int sizediff;
    1049 int oldsize = queue->size;
    1050
    1051 SCIP_CALL( queueResize(queue, queue->size+1) );
    1052 assert(oldsize < queue->size);
    1053
    1054 sizediff = queue->size - oldsize;
    1055
    1056 /* move the used memory at the slots to the end */
    1057 BMSmoveMemoryArray(&(queue->slots[queue->firstused + sizediff]), &(queue->slots[queue->firstused]), oldsize - queue->firstused); /*lint !e866*/
    1058 queue->firstused += sizediff;
    1059 }
    1060 assert(queue->firstfree != queue->firstused);
    1061
    1062 return SCIP_OKAY;
    1063}
    1064
    1065/** checks and adjusts marker of first free and first used slot */
    1066static
    1068 SCIP_QUEUE* queue /**< queue */
    1069 )
    1070{
    1071 /* if we saved the value at the last position we need to reset the firstfree position */
    1072 if( queue->firstfree == queue->size )
    1073 queue->firstfree = 0;
    1074
    1075 /* if a first element was added, we need to update the firstused counter */
    1076 if( queue->firstused == -1 )
    1077 queue->firstused = 0;
    1078}
    1079
    1080/** inserts pointer element at the end of the queue */
    1082 SCIP_QUEUE* queue, /**< queue */
    1083 void* elem /**< element to be inserted */
    1084 )
    1085{
    1086 assert(queue != NULL);
    1087 assert(queue->slots != NULL);
    1088 assert(queue->firstused >= -1 && queue->firstused < queue->size);
    1089 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
    1090 assert(queue->firstused > -1 || queue->firstfree == 0);
    1091 assert(elem != NULL);
    1092
    1093 /* check allocated memory */
    1094 SCIP_CALL( queueCheckSize(queue) );
    1095
    1096 /* insert element at the first free slot */
    1097 queue->slots[queue->firstfree].ptr = elem;
    1098 ++(queue->firstfree);
    1099
    1100 /* check and adjust marker */
    1101 queueCheckMarker(queue);
    1102
    1103 return SCIP_OKAY;
    1104}
    1105
    1106/** inserts unsigned integer element at the end of the queue */
    1108 SCIP_QUEUE* queue, /**< queue */
    1109 unsigned int elem /**< element to be inserted */
    1110 )
    1111{
    1112 assert(queue != NULL);
    1113 assert(queue->slots != NULL);
    1114 assert(queue->firstused >= -1 && queue->firstused < queue->size);
    1115 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
    1116 assert(queue->firstused > -1 || queue->firstfree == 0);
    1117
    1118 /* check allocated memory */
    1119 SCIP_CALL( queueCheckSize(queue) );
    1120
    1121 /* insert element at the first free slot */
    1122 queue->slots[queue->firstfree].uinteger = elem;
    1123 ++(queue->firstfree);
    1124
    1125 /* check and adjust marker */
    1126 queueCheckMarker(queue);
    1127
    1128 return SCIP_OKAY;
    1129}
    1130
    1131/** removes and returns the first pointer element of the queue, or NULL if no element exists */
    1133 SCIP_QUEUE* queue /**< queue */
    1134 )
    1135{
    1136 int pos;
    1137
    1138 assert(queue != NULL);
    1139 assert(queue->firstused >= -1 && queue->firstused < queue->size);
    1140 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
    1141 assert(queue->firstused > -1 || queue->firstfree == 0);
    1142
    1143 if( queue->firstused == -1 )
    1144 return NULL;
    1145
    1146 assert(queue->slots != NULL);
    1147
    1148 pos = queue->firstused;
    1149 ++(queue->firstused);
    1150
    1151 /* if we removed the value at the last position we need to reset the firstused position */
    1152 if( queue->firstused == queue->size )
    1153 queue->firstused = 0;
    1154
    1155 /* if we reached the first free position we can reset both, firstused and firstused, positions */
    1156 if( queue->firstused == queue->firstfree )
    1157 {
    1158 queue->firstused = -1;
    1159 queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
    1160 }
    1161
    1162 return (queue->slots[pos].ptr);
    1163}
    1164
    1165/** removes and returns the first unsigned integer element of the queue, or UINT_MAX if no element exists */
    1167 SCIP_QUEUE* queue /**< queue */
    1168 )
    1169{
    1170 int pos;
    1171
    1172 assert(queue != NULL);
    1173 assert(queue->firstused >= -1 && queue->firstused < queue->size);
    1174 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
    1175 assert(queue->firstused > -1 || queue->firstfree == 0);
    1176
    1177 if( queue->firstused == -1 )
    1178 return UINT_MAX;
    1179
    1180 assert(queue->slots != NULL);
    1181
    1182 pos = queue->firstused;
    1183 ++(queue->firstused);
    1184
    1185 /* if we removed the value at the last position we need to reset the firstused position */
    1186 if( queue->firstused == queue->size )
    1187 queue->firstused = 0;
    1188
    1189 /* if we reached the first free position we can reset both, firstused and firstused, positions */
    1190 if( queue->firstused == queue->firstfree )
    1191 {
    1192 queue->firstused = -1;
    1193 queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
    1194 }
    1195
    1196 return (queue->slots[pos].uinteger);
    1197}
    1198
    1199/** returns the first element of the queue without removing it, or NULL if no element exists */
    1201 SCIP_QUEUE* queue /**< queue */
    1202 )
    1203{
    1204 assert(queue != NULL);
    1205 assert(queue->firstused >= -1 && queue->firstused < queue->size);
    1206 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
    1207 assert(queue->firstused > -1 || queue->firstfree == 0);
    1208
    1209 if( queue->firstused == -1 )
    1210 return NULL;
    1211
    1212 assert(queue->slots != NULL);
    1213
    1214 return queue->slots[queue->firstused].ptr;
    1215}
    1216
    1217/** returns the first unsigned integer element of the queue without removing it, or UINT_MAX if no element exists */
    1219 SCIP_QUEUE* queue /**< queue */
    1220 )
    1221{
    1222 assert(queue != NULL);
    1223 assert(queue->firstused >= -1 && queue->firstused < queue->size);
    1224 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
    1225 assert(queue->firstused > -1 || queue->firstfree == 0);
    1226
    1227 if( queue->firstused == -1 )
    1228 return UINT_MAX;
    1229
    1230 assert(queue->slots != NULL);
    1231
    1232 return queue->slots[queue->firstused].uinteger;
    1233}
    1234
    1235/** returns whether the queue is empty */
    1237 SCIP_QUEUE* queue /**< queue */
    1238 )
    1239{
    1240 assert(queue != NULL);
    1241 assert(queue->firstused >= -1 && queue->firstused < queue->size);
    1242 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
    1243 assert(queue->firstused > -1 || queue->firstfree == 0);
    1244
    1245 return (queue->firstused == -1);
    1246}
    1247
    1248/** returns the number of elements in the queue */
    1250 SCIP_QUEUE* queue /**< queue */
    1251 )
    1252{
    1253 assert(queue != NULL);
    1254 assert(queue->firstused >= -1 && queue->firstused < queue->size);
    1255 assert(queue->firstfree >= 0 && queue->firstused < queue->size);
    1256 assert(queue->firstused > -1 || queue->firstfree == 0);
    1257
    1258 if( queue->firstused == -1 )
    1259 return 0;
    1260 else if( queue->firstused < queue->firstfree )
    1261 return queue->firstfree - queue->firstused;
    1262 else if( queue->firstused == queue->firstfree )
    1263 return queue->size;
    1264 else
    1265 return queue->firstfree + (queue->size - queue->firstused);
    1266}
    1267
    1268
    1269/*
    1270 * Priority Queue
    1271 */
    1272
    1273#define PQ_PARENT(q) (((q)+1)/2-1)
    1274#define PQ_LEFTCHILD(p) (2*(p)+1)
    1275#define PQ_RIGHTCHILD(p) (2*(p)+2)
    1276
    1277
    1278/** resizes element memory to hold at least the given number of elements */
    1279static
    1281 SCIP_PQUEUE* pqueue, /**< pointer to a priority queue */
    1282 int minsize /**< minimal number of storable elements */
    1283 )
    1284{
    1285 assert(pqueue != NULL);
    1286
    1287 if( minsize <= pqueue->size )
    1288 return SCIP_OKAY;
    1289
    1290 pqueue->size = MAX(minsize, (int)(pqueue->size * pqueue->sizefac));
    1291 SCIP_ALLOC( BMSreallocMemoryArray(&pqueue->slots, pqueue->size) );
    1292
    1293 return SCIP_OKAY;
    1294}
    1295
    1296/** creates priority queue */
    1298 SCIP_PQUEUE** pqueue, /**< pointer to a priority queue */
    1299 int initsize, /**< initial number of available element slots */
    1300 SCIP_Real sizefac, /**< memory growing factor applied, if more element slots are needed */
    1301 SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
    1302 SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)) /**< callback to act on position change of elem in priority queue, or NULL */
    1303 )
    1304{
    1305 assert(pqueue != NULL);
    1306 assert(ptrcomp != NULL);
    1307
    1308 initsize = MAX(1, initsize);
    1309 sizefac = MAX(1.0, sizefac);
    1310
    1311 SCIP_ALLOC( BMSallocMemory(pqueue) );
    1312 (*pqueue)->len = 0;
    1313 (*pqueue)->size = 0;
    1314 (*pqueue)->sizefac = sizefac;
    1315 (*pqueue)->slots = NULL;
    1316 (*pqueue)->ptrcomp = ptrcomp;
    1317 (*pqueue)->elemchgpos = elemchgpos;
    1318 SCIP_CALL( pqueueResize(*pqueue, initsize) );
    1319
    1320 return SCIP_OKAY;
    1321}
    1322
    1323/** frees priority queue, but not the data elements themselves */
    1325 SCIP_PQUEUE** pqueue /**< pointer to a priority queue */
    1326 )
    1327{
    1328 assert(pqueue != NULL);
    1329
    1330 BMSfreeMemoryArray(&(*pqueue)->slots);
    1331 BMSfreeMemory(pqueue);
    1332}
    1333
    1334/** clears the priority queue, but doesn't free the data elements themselves */
    1336 SCIP_PQUEUE* pqueue /**< priority queue */
    1337 )
    1338{
    1339 assert(pqueue != NULL);
    1340
    1341 pqueue->len = 0;
    1342}
    1343
    1344/** assign element to new slot in priority queue */
    1345static
    1347 SCIP_PQUEUE* pqueue, /**< priority queue */
    1348 void* elem, /**< element whose position changes */
    1349 int oldpos, /**< old position or -1 if elem is newly inserted */
    1350 int newpos /**< new position */
    1351 )
    1352{
    1353 pqueue->slots[newpos] = elem;
    1354
    1355 /* act on position change */
    1356 if( pqueue->elemchgpos != NULL )
    1357 {
    1358 pqueue->elemchgpos(elem, oldpos, newpos);
    1359 }
    1360}
    1361
    1362#ifdef SCIP_MORE_DEBUG
    1363/** ensure that the priority queue still has the heap property */
    1364static
    1365SCIP_Bool pqueueHasHeapProperty(
    1366 SCIP_PQUEUE* pqueue /**< priority queue */
    1367 )
    1368{
    1369 int i;
    1370
    1371 if( SCIPpqueueNElems(pqueue) == 0 )
    1372 return TRUE;
    1373
    1374 /* check local heap property between parents and children */
    1375 for( i = 0; i < SCIPpqueueNElems(pqueue); ++i )
    1376 {
    1377 if( i > 0 && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[PQ_PARENT(i)]) < 0 )
    1378 return FALSE;
    1379 if( i < PQ_PARENT(SCIPpqueueNElems(pqueue)) )
    1380 {
    1381 int leftchild = PQ_LEFTCHILD(i);
    1382 int rightchild = PQ_RIGHTCHILD(i);
    1383 assert(leftchild < SCIPpqueueNElems(pqueue));
    1384 assert(rightchild <= SCIPpqueueNElems(pqueue));
    1385 if( pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[leftchild]) > 0 )
    1386 return FALSE;
    1387 if( rightchild < SCIPpqueueNElems(pqueue) && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[rightchild]) > 0)
    1388 return FALSE;
    1389 }
    1390 }
    1391 return TRUE;
    1392}
    1393#endif
    1394
    1395/** inserts element into priority queue */
    1397 SCIP_PQUEUE* pqueue, /**< priority queue */
    1398 void* elem /**< element to be inserted */
    1399 )
    1400{
    1401 int pos;
    1402 int parentpos;
    1403
    1404 assert(pqueue != NULL);
    1405 assert(pqueue->len >= 0);
    1406 assert(elem != NULL);
    1407
    1408 SCIP_CALL( pqueueResize(pqueue, pqueue->len+1) );
    1409
    1410 /* insert element as leaf in the tree, move it towards the root as long it is better than its parent */
    1411 pos = pqueue->len;
    1412 pqueue->len++;
    1413 parentpos = PQ_PARENT(pos);
    1414 while( pos > 0 && (*pqueue->ptrcomp)(elem, pqueue->slots[parentpos]) < 0 )
    1415 {
    1416 assert((*pqueue->ptrcomp)(pqueue->slots[parentpos], elem) >= 0);
    1417 pqueueElemChgPos(pqueue, pqueue->slots[parentpos], parentpos, pos);
    1418
    1419 pos = parentpos;
    1420 parentpos = PQ_PARENT(pos);
    1421 }
    1422
    1423 /* insert element at the found position */
    1424 pqueueElemChgPos(pqueue, elem, -1, pos);
    1425
    1426#ifdef SCIP_MORE_DEBUG
    1427 assert(pqueueHasHeapProperty(pqueue));
    1428#endif
    1429
    1430 return SCIP_OKAY;
    1431}
    1432
    1433
    1434/** delete element at specified position, maintaining the heap property */
    1436 SCIP_PQUEUE* pqueue, /**< priority queue */
    1437 int pos /**< position of element that should be deleted */
    1438 )
    1439{
    1440 void* last;
    1441
    1442 assert(pqueue != NULL);
    1443 assert(pos >= 0);
    1444 assert(pos < SCIPpqueueNElems(pqueue));
    1445
    1446 /* remove element at specified position of the tree, move the better child to its parents position until the last element
    1447 * of the queue could be placed in the empty slot
    1448 */
    1449 pqueue->len--;
    1450
    1451 /* everything in place */
    1452 if( pos == pqueue->len )
    1453 return;
    1454
    1455 last = pqueue->slots[pqueue->len];
    1456
    1457 /* last element is brought to pos. it may now violate the heap property compared to its parent, or to its children.
    1458 * In the first case, move it up, otherwise, move it down.
    1459 */
    1460 while( pos > 0 && (*pqueue->ptrcomp)(last, pqueue->slots[PQ_PARENT(pos)]) < 0 )
    1461 {
    1462 pqueueElemChgPos(pqueue, pqueue->slots[PQ_PARENT(pos)], PQ_PARENT(pos), pos);
    1463 pos = PQ_PARENT(pos);
    1464 }
    1465
    1466 while( pos <= PQ_PARENT(pqueue->len-1) )
    1467 {
    1468 int childpos = PQ_LEFTCHILD(pos);
    1469 int brotherpos = PQ_RIGHTCHILD(pos);
    1470
    1471 /* determine better of the two children */
    1472 if( brotherpos < pqueue->len && (*pqueue->ptrcomp)(pqueue->slots[brotherpos], pqueue->slots[childpos]) < 0 )
    1473 childpos = brotherpos;
    1474
    1475 if( (*pqueue->ptrcomp)(last, pqueue->slots[childpos]) <= 0 )
    1476 break;
    1477
    1478 /* move better element from childpos to pos */
    1479 pqueueElemChgPos(pqueue, pqueue->slots[childpos], childpos, pos);
    1480
    1481 pos = childpos;
    1482 }
    1483
    1484 /* pos must point into a valid position */
    1485 assert(pos <= pqueue->len - 1);
    1486
    1487 pqueueElemChgPos(pqueue, last, pqueue->len, pos);
    1488
    1489#ifdef SCIP_MORE_DEBUG
    1490 assert(pqueueHasHeapProperty(pqueue));
    1491#endif
    1492}
    1493
    1494/** removes and returns best element from the priority queue */
    1496 SCIP_PQUEUE* pqueue /**< priority queue */
    1497 )
    1498{
    1499 void* root;
    1500
    1501 assert(pqueue != NULL);
    1502 assert(pqueue->len >= 0);
    1503
    1504 if( pqueue->len == 0 )
    1505 return NULL;
    1506
    1507 root = pqueue->slots[0];
    1508
    1509 SCIPpqueueDelPos(pqueue, 0);
    1510
    1511 return root;
    1512}
    1513
    1514/** returns the best element of the queue without removing it */
    1516 SCIP_PQUEUE* pqueue /**< priority queue */
    1517 )
    1518{
    1519 assert(pqueue != NULL);
    1520 assert(pqueue->len >= 0);
    1521
    1522 if( pqueue->len == 0 )
    1523 return NULL;
    1524
    1525 return pqueue->slots[0];
    1526}
    1527
    1528/** returns the number of elements in the queue */
    1530 SCIP_PQUEUE* pqueue /**< priority queue */
    1531 )
    1532{
    1533 assert(pqueue != NULL);
    1534 assert(pqueue->len >= 0);
    1535
    1536 return pqueue->len;
    1537}
    1538
    1539/** returns the elements of the queue; changing the returned array may destroy the queue's ordering! */
    1541 SCIP_PQUEUE* pqueue /**< priority queue */
    1542 )
    1543{
    1544 assert(pqueue != NULL);
    1545 assert(pqueue->len >= 0);
    1546
    1547 return pqueue->slots;
    1548}
    1549
    1550/** return the position of @p elem in the priority queue, or -1 if element is not found */
    1552 SCIP_PQUEUE* pqueue, /**< priority queue */
    1553 void* elem /**< element to be inserted */
    1554 )
    1555{
    1556 int pos = -1;
    1557
    1558 while( ++pos < SCIPpqueueNElems(pqueue) )
    1559 {
    1560 if( pqueue->slots[pos] == elem )
    1561 return pos;
    1562 }
    1563
    1564 return -1;
    1565}
    1566
    1567
    1568
    1569
    1570/*
    1571 * Hash Table
    1572 */
    1573
    1574/** table of some prime numbers */
    1575static int primetable[] = {
    1576 2,
    1577 7,
    1578 19,
    1579 31,
    1580 59,
    1581 227,
    1582 617,
    1583 1523,
    1584 3547,
    1585 8011,
    1586 17707,
    1587 38723,
    1588 83833,
    1589 180317,
    1590 385897,
    1591 821411,
    1592 1742369,
    1593 3680893,
    1594 5693959,
    1595 7753849,
    1596 9849703,
    1597 11973277,
    1598 14121853,
    1599 17643961,
    1600 24273817,
    1601 32452843,
    1602 49979687,
    1603 67867967,
    1604 86028121,
    1605 104395301,
    1606 122949823,
    1607 141650939,
    1608 160481183,
    1609 179424673,
    1610 198491317,
    1611 217645177,
    1612 256203161,
    1613 314606869,
    1614 373587883,
    1615 433024223,
    1616 492876847,
    1617 553105243,
    1618 613651349,
    1619 694847533,
    1620 756065159,
    1621 817504243,
    1622 879190747,
    1623 941083981,
    1624 982451653,
    1625 INT_MAX
    1626};
    1627static const int primetablesize = sizeof(primetable)/sizeof(int);
    1628
    1629/** simple and fast 2-universal hash function using multiply and shift */
    1630static
    1631uint32_t hashvalue(
    1632 uint64_t input /**< key value */
    1633 )
    1634{
    1635 return ( (uint32_t) ((UINT64_C(0x9e3779b97f4a7c15) * input)>>32) ) | 1u;
    1636}
    1637
    1638/** returns a reasonable hash table size (a prime number) that is at least as large as the specified value */
    1640 int minsize /**< minimal size of the hash table */
    1641 )
    1642{
    1643 int pos;
    1644
    1645 (void) SCIPsortedvecFindInt(primetable, minsize, primetablesize, &pos);
    1646 assert(0 <= pos && pos < primetablesize);
    1647
    1648 return primetable[pos];
    1649}
    1650
    1651/** appends element to the multihash list */
    1652static
    1654 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to hash list */
    1655 BMS_BLKMEM* blkmem, /**< block memory */
    1656 void* element /**< element to append to the list */
    1657 )
    1658{
    1659 SCIP_MULTIHASHLIST* newlist;
    1660
    1661 assert(multihashlist != NULL);
    1662 assert(blkmem != NULL);
    1663 assert(element != NULL);
    1664
    1665 SCIP_ALLOC( BMSallocBlockMemory(blkmem, &newlist) );
    1666 newlist->element = element;
    1667 newlist->next = *multihashlist;
    1668 *multihashlist = newlist;
    1669
    1670 return SCIP_OKAY;
    1671}
    1672
    1673/** frees a multihash list entry and all its successors */
    1674static
    1676 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to multihash list to free */
    1677 BMS_BLKMEM* blkmem /**< block memory */
    1678 )
    1679{
    1680 SCIP_MULTIHASHLIST* list;
    1681 SCIP_MULTIHASHLIST* nextlist;
    1682
    1683 assert(multihashlist != NULL);
    1684 assert(blkmem != NULL);
    1685
    1686 list = *multihashlist;
    1687 while( list != NULL )
    1688 {
    1689 nextlist = list->next;
    1690 BMSfreeBlockMemory(blkmem, &list);
    1691 list = nextlist;
    1692 }
    1693
    1694 *multihashlist = NULL;
    1695}
    1696
    1697/** finds multihash list entry pointing to element with given key in the multihash list, returns NULL if not found */
    1698static
    1700 SCIP_MULTIHASHLIST* multihashlist, /**< multihash list */
    1701 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
    1702 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
    1703 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
    1704 void* userptr, /**< user pointer */
    1705 uint64_t keyval, /**< hash value of key */
    1706 void* key /**< key to retrieve */
    1707 )
    1708{
    1709 uint64_t currentkeyval;
    1710 void* currentkey;
    1711
    1712 assert(hashkeyeq != NULL);
    1713 assert(key != NULL);
    1714
    1715 while( multihashlist != NULL )
    1716 {
    1717 currentkey = hashgetkey(userptr, multihashlist->element);
    1718 currentkeyval = hashkeyval(userptr, currentkey);
    1719 if( currentkeyval == keyval && hashkeyeq(userptr, currentkey, key) )
    1720 return multihashlist;
    1721
    1722 multihashlist = multihashlist->next;
    1723 }
    1724
    1725 return NULL;
    1726}
    1727
    1728/** retrieves element with given key from the multihash list, or NULL */
    1729static
    1731 SCIP_MULTIHASHLIST* multihashlist, /**< hash list */
    1732 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
    1733 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
    1734 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
    1735 void* userptr, /**< user pointer */
    1736 uint64_t keyval, /**< hash value of key */
    1737 void* key /**< key to retrieve */
    1738 )
    1739{
    1741
    1742 /* find hash list entry */
    1743 h = multihashlistFind(multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
    1744
    1745 /* return element */
    1746 if( h != NULL )
    1747 {
    1748#ifndef NDEBUG
    1750
    1751 h2 = multihashlistFind(h->next, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
    1752
    1753 if( h2 != NULL )
    1754 {
    1755 void* key1;
    1756 void* key2;
    1757
    1758 key1 = hashgetkey(userptr, h->element);
    1759 key2 = hashgetkey(userptr, h2->element);
    1760 assert(hashkeyval(userptr, key1) == hashkeyval(userptr, key2));
    1761
    1762 if( hashkeyeq(userptr, key1, key2) )
    1763 {
    1764 SCIPerrorMessage("WARNING: hashkey with same value exists multiple times (e.g. duplicate constraint/variable names), so the return value is maybe not correct\n");
    1765 }
    1766 }
    1767#endif
    1768
    1769 return h->element;
    1770 }
    1771 else
    1772 return NULL;
    1773}
    1774
    1775
    1776/** retrieves element with given key from the multihash list, or NULL
    1777 * returns pointer to multihash table list entry
    1778 */
    1779static
    1781 SCIP_MULTIHASHLIST** multihashlist, /**< on input: hash list to search; on exit: hash list entry corresponding
    1782 * to element after retrieved one, or NULL */
    1783 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
    1784 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
    1785 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
    1786 void* userptr, /**< user pointer */
    1787 uint64_t keyval, /**< hash value of key */
    1788 void* key /**< key to retrieve */
    1789 )
    1790{
    1792
    1793 assert(multihashlist != NULL);
    1794
    1795 /* find hash list entry */
    1796 h = multihashlistFind(*multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
    1797
    1798 /* return element */
    1799 if( h != NULL )
    1800 {
    1801 *multihashlist = h->next;
    1802
    1803 return h->element;
    1804 }
    1805
    1806 *multihashlist = NULL;
    1807
    1808 return NULL;
    1809}
    1810
    1811/** removes element from the multihash list */
    1812static
    1814 SCIP_MULTIHASHLIST** multihashlist, /**< pointer to hash list */
    1815 BMS_BLKMEM* blkmem, /**< block memory */
    1816 void* element /**< element to remove from the list */
    1817 )
    1818{
    1819 SCIP_MULTIHASHLIST* nextlist;
    1820
    1821 assert(multihashlist != NULL);
    1822 assert(blkmem != NULL);
    1823 assert(element != NULL);
    1824
    1825 while( *multihashlist != NULL && (*multihashlist)->element != element )
    1826 multihashlist = &(*multihashlist)->next;
    1827
    1828 if( *multihashlist != NULL )
    1829 {
    1830 nextlist = (*multihashlist)->next;
    1831 BMSfreeBlockMemory(blkmem, multihashlist);
    1832 *multihashlist = nextlist;
    1833
    1834 return TRUE;
    1835 }
    1836
    1837 return FALSE;
    1838}
    1839
    1840#define SCIP_MULTIHASH_MAXSIZE 33554431 /* 2^25 - 1*/
    1841#define SCIP_MULTIHASH_RESIZE_PERCENTAGE 65
    1842#define SCIP_MULTIHASH_GROW_FACTOR 1.31
    1843
    1844/** resizing(increasing) the given multihash */
    1845static
    1847 SCIP_MULTIHASH* multihash /**< hash table */
    1848 )
    1849{
    1850 SCIP_MULTIHASHLIST** newlists;
    1851 SCIP_MULTIHASHLIST* multihashlist;
    1852 SCIP_Longint nelements;
    1853 int nnewlists;
    1854 int l;
    1855
    1856 assert(multihash != NULL);
    1857 assert(multihash->lists != NULL);
    1858 assert(multihash->nlists > 0);
    1859 assert(multihash->hashgetkey != NULL);
    1860 assert(multihash->hashkeyeq != NULL);
    1861 assert(multihash->hashkeyval != NULL);
    1862
    1863 /* get new memeory for hash table lists */
    1864 nnewlists = (int) MIN((unsigned int)(multihash->nlists * SCIP_MULTIHASH_GROW_FACTOR), SCIP_MULTIHASH_MAXSIZE);
    1865 nnewlists = MAX(nnewlists, multihash->nlists);
    1866
    1867 SCIPdebugMessage("load = %g, nelements = %" SCIP_LONGINT_FORMAT ", nlists = %d, nnewlist = %d\n", SCIPmultihashGetLoad(multihash), multihash->nelements, multihash->nlists, nnewlists);
    1868
    1869 if( nnewlists > multihash->nlists )
    1870 {
    1871 SCIP_Bool onlyone;
    1872 void* key;
    1873 uint64_t keyval;
    1874 unsigned int hashval;
    1875
    1876 SCIP_ALLOC( BMSallocClearBlockMemoryArray(multihash->blkmem, &newlists, nnewlists) );
    1877
    1878 /* move all lists */
    1879 for( l = multihash->nlists - 1; l >= 0; --l )
    1880 {
    1881 multihashlist = multihash->lists[l];
    1882 onlyone = TRUE;
    1883
    1884 /* move all elements frmm the old lists into the new lists */
    1885 while( multihashlist != NULL )
    1886 {
    1887 /* get the hash key and its hash value */
    1888 key = multihash->hashgetkey(multihash->userptr, multihashlist->element);
    1889 keyval = multihash->hashkeyval(multihash->userptr, key);
    1890 hashval = (unsigned int) (keyval % (unsigned) nnewlists); /*lint !e573*/
    1891
    1892 /* if the old hash table list consists of only one entry, we still can use this old memory block instead
    1893 * of creating a new one
    1894 */
    1895 if( multihashlist->next == NULL && onlyone )
    1896 {
    1897 /* the new list is also empty, we can directly copy the entry */
    1898 if( newlists[hashval] == NULL )
    1899 newlists[hashval] = multihashlist;
    1900 /* the new list is not empty, so we need to find the first empty spot */
    1901 else
    1902 {
    1903 SCIP_MULTIHASHLIST* lastnext = newlists[hashval];
    1904 SCIP_MULTIHASHLIST* next = lastnext->next;
    1905
    1906 while( next != NULL )
    1907 {
    1908 lastnext = next;
    1909 next = next->next;
    1910 }
    1911
    1912 lastnext->next = multihashlist;
    1913 }
    1914
    1915 multihash->lists[l] = NULL;
    1916 }
    1917 else
    1918 {
    1919 /* append old element to the list at the hash position */
    1920 SCIP_CALL( multihashlistAppend(&(newlists[hashval]), multihash->blkmem, multihashlist->element) );
    1921 }
    1922
    1923 onlyone = FALSE;
    1924 multihashlist = multihashlist->next;
    1925 }
    1926 }
    1927
    1928 /* remember number of elements */
    1929 nelements = multihash->nelements;
    1930 /* clear old lists */
    1931 SCIPmultihashRemoveAll(multihash);
    1932 /* free old lists */
    1933 BMSfreeBlockMemoryArray(multihash->blkmem, &(multihash->lists), multihash->nlists);
    1934
    1935 /* set new data */
    1936 multihash->lists = newlists;
    1937 multihash->nlists = nnewlists;
    1938 multihash->nelements = nelements;
    1939
    1940#ifdef SCIP_MORE_DEBUG
    1941 {
    1942 SCIP_Longint sumslotsize = 0;
    1943
    1944 for( l = 0; l < multihash->nlists; ++l )
    1945 {
    1946 multihashlist = multihash->lists[l];
    1947 while( multihashlist != NULL )
    1948 {
    1949 sumslotsize++;
    1950 multihashlist = multihashlist->next;
    1951 }
    1952 }
    1953 assert(sumslotsize == multihash->nelements);
    1954 }
    1955#endif
    1956 }
    1957
    1958 return SCIP_OKAY;
    1959}
    1960
    1961/** creates a multihash table */
    1963 SCIP_MULTIHASH** multihash, /**< pointer to store the created multihash table */
    1964 BMS_BLKMEM* blkmem, /**< block memory used to store multihash table entries */
    1965 int tablesize, /**< size of the hash table */
    1966 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
    1967 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
    1968 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
    1969 void* userptr /**< user pointer */
    1970 )
    1971{
    1972 /* only assert non negative to catch overflow errors
    1973 * but not zeros due to integer divison
    1974 */
    1975 assert(tablesize >= 0);
    1976 assert(multihash != NULL);
    1977 assert(hashgetkey != NULL);
    1978 assert(hashkeyeq != NULL);
    1979 assert(hashkeyval != NULL);
    1980
    1981 SCIP_ALLOC( BMSallocBlockMemory(blkmem, multihash) );
    1982 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*multihash)->lists, tablesize) );
    1983 (*multihash)->blkmem = blkmem;
    1984 (*multihash)->nlists = tablesize;
    1985 (*multihash)->hashgetkey = hashgetkey;
    1986 (*multihash)->hashkeyeq = hashkeyeq;
    1987 (*multihash)->hashkeyval = hashkeyval;
    1988 (*multihash)->userptr = userptr;
    1989 (*multihash)->nelements = 0;
    1990
    1991 return SCIP_OKAY;
    1992}
    1993
    1994/** frees the multihash table */
    1996 SCIP_MULTIHASH** multihash /**< pointer to the multihash table */
    1997 )
    1998{
    1999 int i;
    2000 SCIP_MULTIHASH* table;
    2001 BMS_BLKMEM* blkmem;
    2002 SCIP_MULTIHASHLIST** lists;
    2003
    2004 assert(multihash != NULL);
    2005 assert(*multihash != NULL);
    2006
    2007 table = (*multihash);
    2008 blkmem = table->blkmem;
    2009 lists = table->lists;
    2010
    2011 /* free hash lists */
    2012 for( i = table->nlists - 1; i >= 0; --i )
    2013 multihashlistFree(&lists[i], blkmem);
    2014
    2015 /* free main hash table data structure */
    2016 BMSfreeBlockMemoryArray(blkmem, &table->lists, table->nlists);
    2017 BMSfreeBlockMemory(blkmem, multihash);
    2018}
    2019
    2020
    2021/** inserts element in multihash table (multiple inserts of same element possible)
    2022 *
    2023 * @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding an element
    2024 * to the hash table, due to dynamic resizing.
    2025 */
    2027 SCIP_MULTIHASH* multihash, /**< multihash table */
    2028 void* element /**< element to insert into the table */
    2029 )
    2030{
    2031 void* key;
    2032 uint64_t keyval;
    2033 unsigned int hashval;
    2034
    2035 assert(multihash != NULL);
    2036 assert(multihash->lists != NULL);
    2037 assert(multihash->nlists > 0);
    2038 assert(multihash->hashgetkey != NULL);
    2039 assert(multihash->hashkeyeq != NULL);
    2040 assert(multihash->hashkeyval != NULL);
    2041 assert(element != NULL);
    2042
    2043 /* dynamically resizing the hashtables */
    2045 {
    2046 SCIP_CALL( multihashResize(multihash) );
    2047 }
    2048
    2049 /* get the hash key and its hash value */
    2050 key = multihash->hashgetkey(multihash->userptr, element);
    2051 keyval = multihash->hashkeyval(multihash->userptr, key);
    2052 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
    2053
    2054 /* append element to the list at the hash position */
    2055 SCIP_CALL( multihashlistAppend(&multihash->lists[hashval], multihash->blkmem, element) );
    2056
    2057 ++(multihash->nelements);
    2058
    2059 return SCIP_OKAY;
    2060}
    2061
    2062/** inserts element in multihash table (multiple insertion of same element is checked and results in an error)
    2063 *
    2064 * @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding a new
    2065 * element to the multihash table, due to dynamic resizing.
    2066 */
    2068 SCIP_MULTIHASH* multihash, /**< multihash table */
    2069 void* element /**< element to insert into the table */
    2070 )
    2071{
    2072 assert(multihash != NULL);
    2073 assert(multihash->hashgetkey != NULL);
    2074
    2075 /* check, if key is already existing */
    2076 if( SCIPmultihashRetrieve(multihash, multihash->hashgetkey(multihash->userptr, element)) != NULL )
    2078
    2079 /* insert element in hash table */
    2080 SCIP_CALL( SCIPmultihashInsert(multihash, element) );
    2081
    2082 return SCIP_OKAY;
    2083}
    2084
    2085/** retrieve element with key from multihash table, returns NULL if not existing */
    2087 SCIP_MULTIHASH* multihash, /**< multihash table */
    2088 void* key /**< key to retrieve */
    2089 )
    2090{
    2091 uint64_t keyval;
    2092 unsigned int hashval;
    2093
    2094 assert(multihash != NULL);
    2095 assert(multihash->lists != NULL);
    2096 assert(multihash->nlists > 0);
    2097 assert(multihash->hashgetkey != NULL);
    2098 assert(multihash->hashkeyeq != NULL);
    2099 assert(multihash->hashkeyval != NULL);
    2100 assert(key != NULL);
    2101
    2102 /* get the hash value of the key */
    2103 keyval = multihash->hashkeyval(multihash->userptr, key);
    2104 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
    2105
    2106 return multihashlistRetrieve(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
    2107 multihash->hashkeyval, multihash->userptr, keyval, key);
    2108}
    2109
    2110/** retrieve element with key from multihash table, returns NULL if not existing
    2111 * can be used to retrieve all entries with the same key (one-by-one)
    2112 *
    2113 * @note The returned multimultihashlist pointer might get invalid when adding a new element to the multihash table.
    2114 */
    2116 SCIP_MULTIHASH* multihash, /**< multihash table */
    2117 SCIP_MULTIHASHLIST** multihashlist, /**< input: entry in hash table list from which to start searching, or NULL
    2118 * output: entry in hash table list corresponding to element after
    2119 * retrieved one, or NULL */
    2120 void* key /**< key to retrieve */
    2121 )
    2122{
    2123 uint64_t keyval;
    2124
    2125 assert(multihash != NULL);
    2126 assert(multihash->lists != NULL);
    2127 assert(multihash->nlists > 0);
    2128 assert(multihash->hashgetkey != NULL);
    2129 assert(multihash->hashkeyeq != NULL);
    2130 assert(multihash->hashkeyval != NULL);
    2131 assert(multihashlist != NULL);
    2132 assert(key != NULL);
    2133
    2134 keyval = multihash->hashkeyval(multihash->userptr, key);
    2135
    2136 if( *multihashlist == NULL )
    2137 {
    2138 unsigned int hashval;
    2139
    2140 /* get the hash value of the key */
    2141 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
    2142
    2143 *multihashlist = multihash->lists[hashval];
    2144 }
    2145
    2146 return multihashlistRetrieveNext(multihashlist, multihash->hashgetkey, multihash->hashkeyeq,
    2147 multihash->hashkeyval, multihash->userptr, keyval, key);
    2148}
    2149
    2150/** returns whether the given element exists in the multihash table */
    2152 SCIP_MULTIHASH* multihash, /**< multihash table */
    2153 void* element /**< element to search in the table */
    2154 )
    2155{
    2156 void* key;
    2157 uint64_t keyval;
    2158 unsigned int hashval;
    2159
    2160 assert(multihash != NULL);
    2161 assert(multihash->lists != NULL);
    2162 assert(multihash->nlists > 0);
    2163 assert(multihash->hashgetkey != NULL);
    2164 assert(multihash->hashkeyeq != NULL);
    2165 assert(multihash->hashkeyval != NULL);
    2166 assert(element != NULL);
    2167
    2168 /* get the hash key and its hash value */
    2169 key = multihash->hashgetkey(multihash->userptr, element);
    2170 keyval = multihash->hashkeyval(multihash->userptr, key);
    2171 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
    2172
    2173 return (multihashlistFind(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
    2174 multihash->hashkeyval, multihash->userptr, keyval, key) != NULL);
    2175}
    2176
    2177/** removes element from the multihash table, if it exists */
    2179 SCIP_MULTIHASH* multihash, /**< multihash table */
    2180 void* element /**< element to remove from the table */
    2181 )
    2182{
    2183 void* key;
    2184 uint64_t keyval;
    2185 unsigned int hashval;
    2186
    2187 assert(multihash != NULL);
    2188 assert(multihash->lists != NULL);
    2189 assert(multihash->nlists > 0);
    2190 assert(multihash->hashgetkey != NULL);
    2191 assert(multihash->hashkeyeq != NULL);
    2192 assert(multihash->hashkeyval != NULL);
    2193 assert(element != NULL);
    2194
    2195 /* get the hash key and its hash value */
    2196 key = multihash->hashgetkey(multihash->userptr, element);
    2197 keyval = multihash->hashkeyval(multihash->userptr, key);
    2198 hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
    2199
    2200 /* remove element from the list at the hash position */
    2201 if( multihashlistRemove(&multihash->lists[hashval], multihash->blkmem, element) )
    2202 --(multihash->nelements);
    2203
    2204 return SCIP_OKAY;
    2205}
    2206
    2207/** removes all elements of the multihash table
    2208 *
    2209 * @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
    2210 * be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
    2211 */
    2213 SCIP_MULTIHASH* multihash /**< multihash table */
    2214 )
    2215{
    2216 BMS_BLKMEM* blkmem;
    2217 SCIP_MULTIHASHLIST** lists;
    2218 int i;
    2219
    2220 assert(multihash != NULL);
    2221
    2222 blkmem = multihash->blkmem;
    2223 lists = multihash->lists;
    2224
    2225 /* free hash lists */
    2226 for( i = multihash->nlists - 1; i >= 0; --i )
    2227 multihashlistFree(&lists[i], blkmem);
    2228
    2229 multihash->nelements = 0;
    2230}
    2231
    2232/** returns number of multihash table elements */
    2234 SCIP_MULTIHASH* multihash /**< multihash table */
    2235 )
    2236{
    2237 assert(multihash != NULL);
    2238
    2239 return multihash->nelements;
    2240}
    2241
    2242/** returns the load of the given multihash table in percentage */
    2244 SCIP_MULTIHASH* multihash /**< multihash table */
    2245 )
    2246{
    2247 assert(multihash != NULL);
    2248
    2249 return ((SCIP_Real)(multihash->nelements) / (multihash->nlists) * 100.0);
    2250}
    2251
    2252/** prints statistics about multihash table usage */
    2254 SCIP_MULTIHASH* multihash, /**< multihash table */
    2255 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
    2256 )
    2257{
    2258 SCIP_MULTIHASHLIST* multihashlist;
    2259 int usedslots;
    2260 int maxslotsize;
    2261 int sumslotsize;
    2262 int slotsize;
    2263 int i;
    2264
    2265 assert(multihash != NULL);
    2266
    2267 usedslots = 0;
    2268 maxslotsize = 0;
    2269 sumslotsize = 0;
    2270 for( i = 0; i < multihash->nlists; ++i )
    2271 {
    2272 multihashlist = multihash->lists[i];
    2273 if( multihashlist != NULL )
    2274 {
    2275 usedslots++;
    2276 slotsize = 0;
    2277 while( multihashlist != NULL )
    2278 {
    2279 slotsize++;
    2280 multihashlist = multihashlist->next;
    2281 }
    2282 maxslotsize = MAX(maxslotsize, slotsize);
    2283 sumslotsize += slotsize;
    2284 }
    2285 }
    2286 assert(sumslotsize == multihash->nelements);
    2287 SCIP_UNUSED(sumslotsize);
    2288
    2289 SCIPmessagePrintInfo(messagehdlr, "%" SCIP_LONGINT_FORMAT " multihash entries, used %d/%d slots (%.1f%%)",
    2290 multihash->nelements, usedslots, multihash->nlists, 100.0*(SCIP_Real)usedslots/(SCIP_Real)(multihash->nlists));
    2291 if( usedslots > 0 )
    2292 SCIPmessagePrintInfo(messagehdlr, ", avg. %.1f entries/used slot, max. %d entries in slot",
    2293 (SCIP_Real)(multihash->nelements)/(SCIP_Real)usedslots, maxslotsize);
    2294 SCIPmessagePrintInfo(messagehdlr, "\n");
    2295}
    2296
    2297/** creates a hash table */
    2299 SCIP_HASHTABLE** hashtable, /**< pointer to store the created hash table */
    2300 BMS_BLKMEM* blkmem, /**< block memory used to store hash table entries */
    2301 int tablesize, /**< size of the hash table */
    2302 SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
    2303 SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
    2304 SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
    2305 void* userptr /**< user pointer */
    2306 )
    2307{
    2308 unsigned int nslots;
    2309
    2310 /* only assert non negative to catch overflow errors
    2311 * but not zeros due to integer divison
    2312 */
    2313 assert(tablesize >= 0);
    2314 assert(hashtable != NULL);
    2315 assert(hashgetkey != NULL);
    2316 assert(hashkeyeq != NULL);
    2317 assert(hashkeyval != NULL);
    2318 assert(blkmem != NULL);
    2319
    2320 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashtable) );
    2321
    2322 /* dont create too small hashtables, i.e. at least size 32, and increase
    2323 * the given size by divinding it by 0.9, since then no rebuilding will
    2324 * be necessary if the given number of elements are inserted. Finally round
    2325 * to the next power of two.
    2326 */
    2327 (*hashtable)->shift = 32;
    2328 (*hashtable)->shift -= (unsigned int)ceil(LOG2(MAX(32.0, tablesize / 0.9)));
    2329
    2330 /* compute size from shift */
    2331 nslots = 1u << (32 - (*hashtable)->shift);
    2332
    2333 /* compute mask to do a fast modulo by nslots using bitwise and */
    2334 (*hashtable)->mask = nslots - 1;
    2335 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*hashtable)->slots, nslots) );
    2336 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashtable)->hashes, nslots) );
    2337 (*hashtable)->blkmem = blkmem;
    2338 (*hashtable)->hashgetkey = hashgetkey;
    2339 (*hashtable)->hashkeyeq = hashkeyeq;
    2340 (*hashtable)->hashkeyval = hashkeyval;
    2341 (*hashtable)->userptr = userptr;
    2342 (*hashtable)->nelements = 0;
    2343
    2344 return SCIP_OKAY;
    2345}
    2346
    2347/** frees the hash table */
    2349 SCIP_HASHTABLE** hashtable /**< pointer to the hash table */
    2350 )
    2351{
    2352 uint32_t nslots;
    2353 SCIP_HASHTABLE* table;
    2354
    2355 assert(hashtable != NULL);
    2356 assert(*hashtable != NULL);
    2357 table = *hashtable;
    2358 nslots = (*hashtable)->mask + 1;
    2359#ifdef SCIP_DEBUG
    2360 {
    2361 uint32_t maxprobelen = 0;
    2362 uint64_t probelensum = 0;
    2363 uint32_t i;
    2364
    2365 assert(table != NULL);
    2366
    2367 for( i = 0; i < nslots; ++i )
    2368 {
    2369 if( table->hashes[i] != 0 )
    2370 {
    2371 uint32_t probelen = ((i + table->mask + 1 - (table->hashes[i]>>(table->shift))) & table->mask) + 1;
    2372 probelensum += probelen;
    2373 maxprobelen = MAX(probelen, maxprobelen);
    2374 }
    2375 }
    2376
    2377 SCIPdebugMessage("%u hash table entries, used %u/%u slots (%.1f%%)",
    2378 (unsigned int)table->nelements, (unsigned int)table->nelements, (unsigned int)nslots,
    2379 100.0*(SCIP_Real)table->nelements/(SCIP_Real)(nslots));
    2380 if( table->nelements > 0 )
    2381 SCIPdebugMessage(", avg. probe length is %.1f, max. probe length is %u",
    2382 (SCIP_Real)(probelensum)/(SCIP_Real)table->nelements, (unsigned int)maxprobelen);
    2383 SCIPdebugMessage("\n");
    2384 }
    2385#endif
    2386
    2387 /* free main hash table data structure */
    2388 BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->hashes, nslots);
    2389 BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->slots, nslots);
    2390 BMSfreeBlockMemory((*hashtable)->blkmem, hashtable);
    2391}
    2392
    2393/* computes the distance from it's desired position for the element stored at pos */
    2394#define ELEM_DISTANCE(pos) (((pos) + hashtable->mask + 1 - (hashtable->hashes[(pos)]>>(hashtable->shift))) & hashtable->mask)
    2395
    2396/** inserts element in hash table (multiple inserts of same element overrides previous one) */
    2397static
    2399 SCIP_HASHTABLE* hashtable, /**< hash table */
    2400 void* element, /**< element to insert into the table */
    2401 void* key, /**< key of element */
    2402 uint32_t hashval, /**< hash value of element */
    2403 SCIP_Bool override /**< should element be overridden or an error be returned if already existing */
    2404 )
    2405{
    2406 uint32_t elemdistance;
    2407 uint32_t pos;
    2408#ifndef NDEBUG
    2409 SCIP_Bool swapped = FALSE;
    2410#endif
    2411
    2412 assert(hashtable != NULL);
    2413 assert(hashtable->slots != NULL);
    2414 assert(hashtable->hashes != NULL);
    2415 assert(hashtable->mask > 0);
    2416 assert(hashtable->hashgetkey != NULL);
    2417 assert(hashtable->hashkeyeq != NULL);
    2418 assert(hashtable->hashkeyval != NULL);
    2419 assert(element != NULL);
    2420
    2421 pos = hashval>>(hashtable->shift);
    2422 elemdistance = 0;
    2423 while( TRUE ) /*lint !e716*/
    2424 {
    2425 uint32_t distance;
    2426
    2427 /* if position is empty or key equal insert element */
    2428 if( hashtable->hashes[pos] == 0 )
    2429 {
    2430 hashtable->slots[pos] = element;
    2431 hashtable->hashes[pos] = hashval;
    2432 ++hashtable->nelements;
    2433 return SCIP_OKAY;
    2434 }
    2435
    2436 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
    2437 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
    2438 {
    2439 if( override )
    2440 {
    2441#ifndef NDEBUG
    2442 assert(! swapped);
    2443#endif
    2444 hashtable->slots[pos] = element;
    2445 hashtable->hashes[pos] = hashval;
    2446 return SCIP_OKAY;
    2447 }
    2448 else
    2449 {
    2451 }
    2452 }
    2453
    2454 /* otherwise check if the current element at this position is closer to its hashvalue */
    2455 distance = ELEM_DISTANCE(pos);
    2456 if( distance < elemdistance )
    2457 {
    2458 uint32_t tmp;
    2459
    2460 /* if this is the case we insert the new element here and find a new position for the old one */
    2461 elemdistance = distance;
    2462 SCIPswapPointers(&hashtable->slots[pos], &element);
    2463 tmp = hashval;
    2464 hashval = hashtable->hashes[pos];
    2465 hashtable->hashes[pos] = tmp;
    2466 key = hashtable->hashgetkey(hashtable->userptr, element);
    2467
    2468 /* after doing a swap the case that other elements are replaced must not happen anymore */
    2469#ifndef NDEBUG
    2470 swapped = TRUE;
    2471#endif
    2472 }
    2473
    2474 /* continue until we have found an empty position */
    2475 pos = (pos + 1) & hashtable->mask;
    2476 ++elemdistance;
    2477 }
    2478}
    2479
    2480/** check if the load factor of the hashtable is too high and rebuild if necessary */
    2481static
    2483 SCIP_HASHTABLE* hashtable /**< hash table */
    2484 )
    2485{
    2486 assert(hashtable != NULL);
    2487 assert(hashtable->shift < 32);
    2488
    2489 /* use integer arithmetic to approximately check if load factor is above 90% */
    2490 if( ((((uint64_t)hashtable->nelements)<<10)>>(32-hashtable->shift) > 921) )
    2491 {
    2492 void** slots;
    2493 uint32_t* hashes;
    2494 uint32_t nslots;
    2495 uint32_t newnslots;
    2496 uint32_t i;
    2497
    2498 /* calculate new size (always power of two) */
    2499 nslots = hashtable->mask + 1;
    2500 newnslots = 2*nslots;
    2501 hashtable->mask = newnslots-1;
    2502 --hashtable->shift;
    2503
    2504 /* reallocate array */
    2505 SCIP_ALLOC( BMSallocBlockMemoryArray(hashtable->blkmem, &slots, newnslots) );
    2506 SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashtable->blkmem, &hashes, newnslots) );
    2507
    2508 SCIPswapPointers((void**) &slots, (void**) &hashtable->slots);
    2509 SCIPswapPointers((void**) &hashes, (void**) &hashtable->hashes);
    2510 hashtable->nelements = 0;
    2511
    2512 /* reinsert all elements */
    2513 for( i = 0; i < nslots; ++i )
    2514 {
    2515 /* using SCIP_CALL_ABORT since there are no allocations or duplicates
    2516 * and thus no bad return codes when inserting the elements
    2517 */
    2518 if( hashes[i] != 0 )
    2519 {
    2520 SCIP_CALL_ABORT( hashtableInsert(hashtable, slots[i], hashtable->hashgetkey(hashtable->userptr, slots[i]), hashes[i], FALSE) );
    2521 }
    2522 }
    2523 BMSfreeBlockMemoryArray(hashtable->blkmem, &hashes, nslots);
    2524 BMSfreeBlockMemoryArray(hashtable->blkmem, &slots, nslots);
    2525 }
    2526
    2527 return SCIP_OKAY;
    2528}
    2529
    2530
    2531/** inserts element in hash table
    2532 *
    2533 * @note multiple inserts of same element overrides previous one
    2534 */
    2536 SCIP_HASHTABLE* hashtable, /**< hash table */
    2537 void* element /**< element to insert into the table */
    2538 )
    2539{
    2540 void* key;
    2541 uint64_t keyval;
    2542 uint32_t hashval;
    2543
    2544 assert(hashtable != NULL);
    2545 assert(hashtable->slots != NULL);
    2546 assert(hashtable->hashes != NULL);
    2547 assert(hashtable->mask > 0);
    2548 assert(hashtable->hashgetkey != NULL);
    2549 assert(hashtable->hashkeyeq != NULL);
    2550 assert(hashtable->hashkeyval != NULL);
    2551 assert(element != NULL);
    2552
    2553 SCIP_CALL( hashtableCheckLoad(hashtable) );
    2554
    2555 /* get the hash key and its hash value */
    2556 key = hashtable->hashgetkey(hashtable->userptr, element);
    2557 keyval = hashtable->hashkeyval(hashtable->userptr, key);
    2558 hashval = hashvalue(keyval);
    2559
    2560 return hashtableInsert(hashtable, element, key, hashval, TRUE);
    2561}
    2562
    2563/** inserts element in hash table
    2564 *
    2565 * @note multiple insertion of same element is checked and results in an error
    2566 */
    2568 SCIP_HASHTABLE* hashtable, /**< hash table */
    2569 void* element /**< element to insert into the table */
    2570 )
    2571{
    2572 void* key;
    2573 uint64_t keyval;
    2574 uint32_t hashval;
    2575
    2576 assert(hashtable != NULL);
    2577 assert(hashtable->slots != NULL);
    2578 assert(hashtable->hashes != NULL);
    2579 assert(hashtable->mask > 0);
    2580 assert(hashtable->hashgetkey != NULL);
    2581 assert(hashtable->hashkeyeq != NULL);
    2582 assert(hashtable->hashkeyval != NULL);
    2583 assert(element != NULL);
    2584
    2585 SCIP_CALL( hashtableCheckLoad(hashtable) );
    2586
    2587 /* get the hash key and its hash value */
    2588 key = hashtable->hashgetkey(hashtable->userptr, element);
    2589 keyval = hashtable->hashkeyval(hashtable->userptr, key);
    2590 hashval = hashvalue(keyval);
    2591
    2592 return hashtableInsert(hashtable, element, key, hashval, FALSE);
    2593}
    2594
    2595/** retrieve element with key from hash table, returns NULL if not existing */
    2597 SCIP_HASHTABLE* hashtable, /**< hash table */
    2598 void* key /**< key to retrieve */
    2599 )
    2600{
    2601 uint64_t keyval;
    2602 uint32_t hashval;
    2603 uint32_t pos;
    2604 uint32_t elemdistance;
    2605
    2606 assert(hashtable != NULL);
    2607 assert(hashtable->slots != NULL);
    2608 assert(hashtable->hashes != NULL);
    2609 assert(hashtable->mask > 0);
    2610 assert(hashtable->hashgetkey != NULL);
    2611 assert(hashtable->hashkeyeq != NULL);
    2612 assert(hashtable->hashkeyval != NULL);
    2613 assert(key != NULL);
    2614
    2615 /* get the hash value of the key */
    2616 keyval = hashtable->hashkeyval(hashtable->userptr, key);
    2617 hashval = hashvalue(keyval);
    2618
    2619 pos = hashval>>(hashtable->shift);
    2620 elemdistance = 0;
    2621
    2622 while( TRUE ) /*lint !e716*/
    2623 {
    2624 uint32_t distance;
    2625
    2626 /* slots is empty so element cannot be contained */
    2627 if( hashtable->hashes[pos] == 0 )
    2628 return NULL;
    2629
    2630 distance = ELEM_DISTANCE(pos);
    2631
    2632 /* element cannot be contained since otherwise we would have swapped it with this one during insert */
    2633 if( elemdistance > distance )
    2634 return NULL;
    2635
    2636 /* found element */
    2637 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
    2638 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
    2639 return hashtable->slots[pos];
    2640
    2641 pos = (pos + 1) & hashtable->mask;
    2642 ++elemdistance;
    2643 }
    2644}
    2645
    2646/** returns whether the given element exists in the table */
    2648 SCIP_HASHTABLE* hashtable, /**< hash table */
    2649 void* element /**< element to search in the table */
    2650 )
    2651{
    2652 assert(hashtable != NULL);
    2653 assert(hashtable->slots != NULL);
    2654 assert(hashtable->hashes != NULL);
    2655 assert(hashtable->mask > 0);
    2656 assert(hashtable->hashgetkey != NULL);
    2657 assert(hashtable->hashkeyeq != NULL);
    2658 assert(hashtable->hashkeyval != NULL);
    2659 assert(element != NULL);
    2660
    2661 return (SCIPhashtableRetrieve(hashtable, hashtable->hashgetkey(hashtable->userptr, element)) != NULL);
    2662}
    2663
    2664/** removes element from the hash table, if it exists */
    2666 SCIP_HASHTABLE* hashtable, /**< hash table */
    2667 void* element /**< element to remove from the table */
    2668 )
    2669{
    2670 void* key;
    2671 uint64_t keyval;
    2672 uint32_t hashval;
    2673 uint32_t elemdistance;
    2674 uint32_t distance;
    2675 uint32_t pos;
    2676
    2677 assert(hashtable != NULL);
    2678 assert(hashtable->slots != NULL);
    2679 assert(hashtable->hashes != NULL);
    2680 assert(hashtable->mask > 0);
    2681 assert(hashtable->hashgetkey != NULL);
    2682 assert(hashtable->hashkeyeq != NULL);
    2683 assert(hashtable->hashkeyval != NULL);
    2684 assert(element != NULL);
    2685
    2686 /* get the hash key and its hash value */
    2687 key = hashtable->hashgetkey(hashtable->userptr, element);
    2688 keyval = hashtable->hashkeyval(hashtable->userptr, key);
    2689 hashval = hashvalue(keyval);
    2690
    2691 elemdistance = 0;
    2692 pos = hashval>>(hashtable->shift);
    2693 while( TRUE ) /*lint !e716*/
    2694 {
    2695 /* slots empty so element not contained */
    2696 if( hashtable->hashes[pos] == 0 )
    2697 return SCIP_OKAY;
    2698
    2699 distance = ELEM_DISTANCE(pos);
    2700
    2701 /* element can not be contained since otherwise we would have swapped it with this one */
    2702 if( elemdistance > distance )
    2703 return SCIP_OKAY;
    2704
    2705 if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
    2706 hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
    2707 {
    2708 /* element exists at pos so break out of loop */
    2709 break;
    2710 }
    2711
    2712 pos = (pos + 1) & hashtable->mask;
    2713 ++elemdistance;
    2714 }
    2715
    2716 /* remove element */
    2717 hashtable->hashes[pos] = 0;
    2718 --hashtable->nelements;
    2719 while( TRUE ) /*lint !e716*/
    2720 {
    2721 uint32_t nextpos = (pos + 1) & hashtable->mask;
    2722
    2723 /* nothing to do since there is no chain that needs to be moved */
    2724 if( hashtable->hashes[nextpos] == 0 )
    2725 break;
    2726
    2727 /* check if the element is the start of a new chain and return if that is the case */
    2728 if( (hashtable->hashes[nextpos]>>(hashtable->shift)) == nextpos )
    2729 break;
    2730
    2731 /* element should be moved to the left and next element needs to be checked */
    2732 hashtable->slots[pos] = hashtable->slots[nextpos];
    2733 hashtable->hashes[pos] = hashtable->hashes[nextpos];
    2734 hashtable->hashes[nextpos] = 0;
    2735
    2736 pos = nextpos;
    2737 }
    2738
    2739 return SCIP_OKAY;
    2740}
    2741
    2742/** removes all elements of the hash table */
    2744 SCIP_HASHTABLE* hashtable /**< hash table */
    2745 )
    2746{
    2747 assert(hashtable != NULL);
    2748
    2749 BMSclearMemoryArray(hashtable->hashes, hashtable->mask + 1);
    2750
    2751 hashtable->nelements = 0;
    2752}
    2753
    2754/** returns number of hash table elements */
    2756 SCIP_HASHTABLE* hashtable /**< hash table */
    2757 )
    2758{
    2759 assert(hashtable != NULL);
    2760
    2761 return hashtable->nelements;
    2762}
    2763
    2764/** gives the number of entries in the internal arrays of a hash table */
    2766 SCIP_HASHTABLE* hashtable /**< hash table */
    2767 )
    2768{
    2769 return (int) hashtable->mask + 1;
    2770}
    2771
    2772/** gives the element at the given index or NULL if entry at that index has no element */
    2774 SCIP_HASHTABLE* hashtable, /**< hash table */
    2775 int entryidx /**< index of hash table entry */
    2776 )
    2777{
    2778 return hashtable->hashes[entryidx] == 0 ? NULL : hashtable->slots[entryidx];
    2779}
    2780
    2781/** returns the load of the given hash table in percentage */
    2783 SCIP_HASHTABLE* hashtable /**< hash table */
    2784 )
    2785{
    2786 assert(hashtable != NULL);
    2787
    2788 return ((SCIP_Real)(hashtable->nelements) / (hashtable->mask + 1) * 100.0);
    2789}
    2790
    2791/** prints statistics about hash table usage */
    2793 SCIP_HASHTABLE* hashtable, /**< hash table */
    2794 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
    2795 )
    2796{
    2797 uint32_t maxprobelen = 0;
    2798 uint64_t probelensum = 0;
    2799 uint32_t nslots;
    2800 uint32_t i;
    2801
    2802 assert(hashtable != NULL);
    2803
    2804 nslots = hashtable->mask + 1;
    2805
    2806 /* compute the maximum and average probe length */
    2807 for( i = 0; i < nslots; ++i )
    2808 {
    2809 if( hashtable->hashes[i] != 0 )
    2810 {
    2811 uint32_t probelen = ELEM_DISTANCE(i) + 1;
    2812 probelensum += probelen;
    2813 maxprobelen = MAX(probelen, maxprobelen);
    2814 }
    2815 }
    2816
    2817 /* print general hash table statistics */
    2818 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
    2819 (unsigned int)hashtable->nelements, (unsigned int)hashtable->nelements,
    2820 (unsigned int)nslots, 100.0*(SCIP_Real)hashtable->nelements/(SCIP_Real)(nslots));
    2821
    2822 /* if not empty print average and maximum probe length */
    2823 if( hashtable->nelements > 0 )
    2824 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
    2825 (SCIP_Real)(probelensum)/(SCIP_Real)hashtable->nelements, (unsigned int)maxprobelen);
    2826 SCIPmessagePrintInfo(messagehdlr, "\n");
    2827}
    2828
    2829/** returns TRUE iff both keys (i.e. strings) are equal */
    2830SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
    2831{ /*lint --e{715}*/
    2832 const char* string1 = (const char*)key1;
    2833 const char* string2 = (const char*)key2;
    2834
    2835 return (strcmp(string1, string2) == 0);
    2836}
    2837
    2838/** returns the hash value of the key (i.e. string) */
    2839SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
    2840{ /*lint --e{715}*/
    2841 const char* str;
    2842 uint64_t hash;
    2843
    2844 str = (const char*)key;
    2845 hash = 37;
    2846 while( *str != '\0' )
    2847 {
    2848 hash *= 11;
    2849 hash += (unsigned int)(*str); /*lint !e571*/
    2850 str++;
    2851 }
    2852
    2853 return hash;
    2854}
    2855
    2856
    2857/** gets the element as the key */
    2858SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
    2859{ /*lint --e{715}*/
    2860 /* the key is the element itself */
    2861 return elem;
    2862}
    2863
    2864/** returns TRUE iff both keys(pointer) are equal */
    2865SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqPtr)
    2866{ /*lint --e{715}*/
    2867 return (key1 == key2);
    2868}
    2869
    2870/** returns the hash value of the key */
    2871SCIP_DECL_HASHKEYVAL(SCIPhashKeyValPtr)
    2872{ /*lint --e{715}*/
    2873 /* the key is used as the keyvalue too */
    2874 return (uint64_t) (uintptr_t) key;
    2875}
    2876
    2877
    2878
    2879/*
    2880 * Hash Map
    2881 */
    2882
    2883/* redefine ELEM_DISTANCE macro for hashmap */
    2884#undef ELEM_DISTANCE
    2885/* computes the distance from it's desired position for the element stored at pos */
    2886#define ELEM_DISTANCE(pos) (((pos) + hashmap->mask + 1 - (hashmap->hashes[(pos)]>>(hashmap->shift))) & hashmap->mask)
    2887
    2888/** inserts element in hash table */
    2889static
    2891 SCIP_HASHMAP* hashmap, /**< hash map */
    2892 void* origin, /**< element to insert into the table */
    2893 SCIP_HASHMAPIMAGE image, /**< key of element */
    2894 uint32_t hashval, /**< hash value of element */
    2895 SCIP_Bool override /**< should element be overridden or error be returned if already existing */
    2896 )
    2897{
    2898 uint32_t elemdistance;
    2899 uint32_t pos;
    2900
    2901 assert(hashmap != NULL);
    2902 assert(hashmap->slots != NULL);
    2903 assert(hashmap->hashes != NULL);
    2904 assert(hashmap->mask > 0);
    2905 assert(hashval != 0);
    2906
    2907 pos = hashval>>(hashmap->shift);
    2908 elemdistance = 0;
    2909 while( TRUE ) /*lint !e716*/
    2910 {
    2911 uint32_t distance;
    2912
    2913 /* if position is empty or key equal insert element */
    2914 if( hashmap->hashes[pos] == 0 )
    2915 {
    2916 hashmap->slots[pos].origin = origin;
    2917 hashmap->slots[pos].image = image;
    2918 hashmap->hashes[pos] = hashval;
    2919 ++hashmap->nelements;
    2920 return SCIP_OKAY;
    2921 }
    2922
    2923 if( hashval == hashmap->hashes[pos] && origin == hashmap->slots[pos].origin )
    2924 {
    2925 if( override )
    2926 {
    2927 hashmap->slots[pos].image = image;
    2928 hashmap->hashes[pos] = hashval;
    2929 return SCIP_OKAY;
    2930 }
    2931 else
    2932 {
    2934 }
    2935 }
    2936
    2937 /* otherwise check if the current element at this position is closer to its hashvalue */
    2938 distance = ELEM_DISTANCE(pos);
    2939 if( distance < elemdistance )
    2940 {
    2942 uint32_t tmphash;
    2943
    2944 /* if this is the case we insert the new element here and find a new position for the old one */
    2945 elemdistance = distance;
    2946 tmphash = hashval;
    2947 hashval = hashmap->hashes[pos];
    2948 hashmap->hashes[pos] = tmphash;
    2949 SCIPswapPointers(&hashmap->slots[pos].origin, &origin);
    2950 tmp = image;
    2951 image = hashmap->slots[pos].image;
    2952 hashmap->slots[pos].image = tmp;
    2953 }
    2954
    2955 /* continue until we have found an empty position */
    2956 pos = (pos + 1) & hashmap->mask;
    2957 ++elemdistance;
    2958 }
    2959}
    2960
    2961/** lookup origin in the hashmap. If element is found returns true and the position of the element,
    2962 * otherwise returns FALSE.
    2963 */
    2964static
    2966 SCIP_HASHMAP* hashmap, /**< hash table */
    2967 void* origin, /**< origin to lookup */
    2968 uint32_t* pos /**< pointer to store position of element, if exists */
    2969 )
    2970{
    2971 uint32_t hashval;
    2972 uint32_t elemdistance;
    2973
    2974 assert(hashmap != NULL);
    2975 assert(hashmap->slots != NULL);
    2976 assert(hashmap->hashes != NULL);
    2977 assert(hashmap->mask > 0);
    2978
    2979 /* get the hash value */
    2980 hashval = hashvalue((size_t)origin);
    2981 assert(hashval != 0);
    2982
    2983 *pos = hashval>>(hashmap->shift);
    2984 elemdistance = 0;
    2985
    2986 while( TRUE ) /*lint !e716*/
    2987 {
    2988 uint32_t distance;
    2989
    2990 /* slots is empty so element cannot be contained */
    2991 if( hashmap->hashes[*pos] == 0 )
    2992 return FALSE;
    2993
    2994 distance = ELEM_DISTANCE(*pos);
    2995 /* element can not be contained since otherwise we would have swapped it with this one during insert */
    2996 if( elemdistance > distance )
    2997 return FALSE;
    2998
    2999 /* found element */
    3000 if( hashmap->hashes[*pos] == hashval && hashmap->slots[*pos].origin == origin )
    3001 return TRUE;
    3002
    3003 *pos = (*pos + 1) & hashmap->mask;
    3004 ++elemdistance;
    3005 }
    3006}
    3007
    3008/** check if the load factor of the hashmap is too high and rebuild if necessary */
    3009static
    3011 SCIP_HASHMAP* hashmap /**< hash table */
    3012 )
    3013{
    3014 assert(hashmap != NULL);
    3015 assert(hashmap->shift < 32);
    3016
    3017 /* use integer arithmetic to approximately check if load factor is above 90% */
    3018 if( ((((uint64_t)hashmap->nelements)<<10)>>(32-hashmap->shift) > 921) )
    3019 {
    3020 SCIP_HASHMAPENTRY* slots;
    3021 uint32_t* hashes;
    3022 uint32_t nslots;
    3023 uint32_t newnslots;
    3024 uint32_t i;
    3025
    3026 /* calculate new size (always power of two) */
    3027 nslots = hashmap->mask + 1;
    3028 --hashmap->shift;
    3029 newnslots = 2*nslots;
    3030 hashmap->mask = newnslots-1;
    3031
    3032 /* reallocate array */
    3033 SCIP_ALLOC( BMSallocBlockMemoryArray(hashmap->blkmem, &slots, newnslots) );
    3034 SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashmap->blkmem, &hashes, newnslots) );
    3035
    3036 SCIPswapPointers((void**) &slots, (void**) &hashmap->slots);
    3037 SCIPswapPointers((void**) &hashes, (void**) &hashmap->hashes);
    3038 hashmap->nelements = 0;
    3039
    3040 /* reinsert all elements */
    3041 for( i = 0; i < nslots; ++i )
    3042 {
    3043 /* using SCIP_CALL_ABORT since there are no allocations or duplicates
    3044 * and thus no bad return codes when inserting the elements
    3045 */
    3046 if( hashes[i] != 0 )
    3047 {
    3048 SCIP_CALL_ABORT( hashmapInsert(hashmap, slots[i].origin, slots[i].image, hashes[i], FALSE) );
    3049 }
    3050 }
    3051
    3052 /* free old arrays */
    3053 BMSfreeBlockMemoryArray(hashmap->blkmem, &hashes, nslots);
    3054 BMSfreeBlockMemoryArray(hashmap->blkmem, &slots, nslots);
    3055 }
    3056
    3057 return SCIP_OKAY;
    3058}
    3059
    3060/** creates a hash map mapping pointers to pointers */
    3062 SCIP_HASHMAP** hashmap, /**< pointer to store the created hash map */
    3063 BMS_BLKMEM* blkmem, /**< block memory used to store hash map entries */
    3064 int mapsize /**< size of the hash map */
    3065 )
    3066{
    3067 uint32_t nslots;
    3068
    3069 assert(hashmap != NULL);
    3070 assert(mapsize >= 0);
    3071 assert(blkmem != NULL);
    3072
    3073 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashmap) );
    3074
    3075 /* dont create too small hashtables, i.e. at least size 32, and increase
    3076 * the given size by divinding it by 0.9, since then no rebuilding will
    3077 * be necessary if the given number of elements are inserted. Finally round
    3078 * to the next power of two.
    3079 */
    3080 (*hashmap)->shift = 32;
    3081 (*hashmap)->shift -= (unsigned int)ceil(log(MAX(32, mapsize / 0.9)) / log(2.0));
    3082 nslots = 1u << (32 - (*hashmap)->shift);
    3083 (*hashmap)->mask = nslots - 1;
    3084 (*hashmap)->blkmem = blkmem;
    3085 (*hashmap)->nelements = 0;
    3086 (*hashmap)->hashmaptype = SCIP_HASHMAPTYPE_UNKNOWN;
    3087
    3088 SCIP_ALLOC( BMSallocBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots) );
    3089 SCIP_ALLOC( BMSallocClearBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots) );
    3090
    3091 return SCIP_OKAY;
    3092}
    3093
    3094/** frees the hash map */
    3096 SCIP_HASHMAP** hashmap /**< pointer to the hash map */
    3097 )
    3098{
    3099 uint32_t nslots;
    3100
    3101 assert(hashmap != NULL);
    3102 assert(*hashmap != NULL);
    3103
    3104 nslots = (*hashmap)->mask + 1;
    3105#ifdef SCIP_DEBUG
    3106 {
    3107 uint32_t maxprobelen = 0;
    3108 uint64_t probelensum = 0;
    3109 uint32_t i;
    3110
    3111 assert(hashmap != NULL);
    3112
    3113 for( i = 0; i < nslots; ++i )
    3114 {
    3115 if( (*hashmap)->hashes[i] != 0 )
    3116 {
    3117 uint32_t probelen = ((i + (*hashmap)->mask + 1 - ((*hashmap)->hashes[i]>>((*hashmap)->shift))) & (*hashmap)->mask) + 1;
    3118 probelensum += probelen;
    3119 maxprobelen = MAX(probelen, maxprobelen);
    3120 }
    3121 }
    3122
    3123 SCIPdebugMessage("%u hash map entries, used %u/%u slots (%.1f%%)",
    3124 (unsigned int)(*hashmap)->nelements, (unsigned int)(*hashmap)->nelements, (unsigned int)nslots,
    3125 100.0*(SCIP_Real)(*hashmap)->nelements/(SCIP_Real)(nslots));
    3126 if( (*hashmap)->nelements > 0 )
    3127 SCIPdebugPrintf(", avg. probe length is %.1f, max. probe length is %u",
    3128 (SCIP_Real)(probelensum)/(SCIP_Real)(*hashmap)->nelements, (unsigned int)maxprobelen);
    3129 SCIPdebugPrintf("\n");
    3130 }
    3131#endif
    3132
    3133 /* free main hash map data structure */
    3134 BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots);
    3135 BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots);
    3136 BMSfreeBlockMemory((*hashmap)->blkmem, hashmap);
    3137}
    3138
    3139/** inserts new origin->image pair in hash map
    3140 *
    3141 * @note multiple insertion of same element is checked and results in an error
    3142 */
    3144 SCIP_HASHMAP* hashmap, /**< hash map */
    3145 void* origin, /**< origin to set image for */
    3146 void* image /**< new image for origin */
    3147 )
    3148{
    3149 uint32_t hashval;
    3151
    3152 assert(hashmap != NULL);
    3153 assert(hashmap->slots != NULL);
    3154 assert(hashmap->hashes != NULL);
    3155 assert(hashmap->mask > 0);
    3157
    3158#ifndef NDEBUG
    3159 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
    3161#endif
    3162
    3163 SCIP_CALL( hashmapCheckLoad(hashmap) );
    3164
    3165 /* get the hash value */
    3166 hashval = hashvalue((size_t)origin);
    3167
    3168 /* append origin->image pair to hash map */
    3169 img.ptr = image;
    3170 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
    3171
    3172 return SCIP_OKAY;
    3173}
    3174
    3175/** inserts new origin->image pair in hash map
    3176 *
    3177 * @note multiple insertion of same element is checked and results in an error
    3178 */
    3180 SCIP_HASHMAP* hashmap, /**< hash map */
    3181 void* origin, /**< origin to set image for */
    3182 int image /**< new image for origin */
    3183 )
    3184{
    3185 uint32_t hashval;
    3187
    3188 assert(hashmap != NULL);
    3189 assert(hashmap->slots != NULL);
    3190 assert(hashmap->hashes != NULL);
    3191 assert(hashmap->mask > 0);
    3192 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
    3193
    3194#ifndef NDEBUG
    3195 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
    3197#endif
    3198
    3199 SCIP_CALL( hashmapCheckLoad(hashmap) );
    3200
    3201 /* get the hash value */
    3202 hashval = hashvalue((size_t)origin);
    3203
    3204 /* append origin->image pair to hash map */
    3205 img.integer = image;
    3206 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
    3207
    3208 return SCIP_OKAY;
    3209}
    3210
    3211/** inserts new origin->image pair in hash map
    3212 *
    3213 * @note multiple insertion of same element is checked and results in an error
    3214 */
    3216 SCIP_HASHMAP* hashmap, /**< hash map */
    3217 void* origin, /**< origin to set image for */
    3218 SCIP_Longint image /**< new image for origin */
    3219 )
    3220{
    3221 uint32_t hashval;
    3223
    3224 assert(hashmap != NULL);
    3225 assert(hashmap->slots != NULL);
    3226 assert(hashmap->hashes != NULL);
    3227 assert(hashmap->mask > 0);
    3228 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_LONG);
    3229
    3230#ifndef NDEBUG
    3231 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
    3233#endif
    3234
    3235 SCIP_CALL( hashmapCheckLoad(hashmap) );
    3236
    3237 /* get the hash value */
    3238 hashval = hashvalue((size_t)origin);
    3239
    3240 /* append origin->image pair to hash map */
    3241 img.longint = image;
    3242 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
    3243
    3244 return SCIP_OKAY;
    3245}
    3246
    3247/** inserts new origin->image pair in hash map
    3248 *
    3249 * @note multiple insertion of same element is checked and results in an error
    3250 */
    3252 SCIP_HASHMAP* hashmap, /**< hash map */
    3253 void* origin, /**< origin to set image for */
    3254 SCIP_Real image /**< new image for origin */
    3255 )
    3256{
    3257 uint32_t hashval;
    3259
    3260 assert(hashmap != NULL);
    3261 assert(hashmap->slots != NULL);
    3262 assert(hashmap->hashes != NULL);
    3263 assert(hashmap->mask > 0);
    3264 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
    3265
    3266#ifndef NDEBUG
    3267 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
    3269#endif
    3270
    3271 SCIP_CALL( hashmapCheckLoad(hashmap) );
    3272
    3273 /* get the hash value */
    3274 hashval = hashvalue((size_t)origin);
    3275
    3276 /* append origin->image pair to hash map */
    3277 img.real = image;
    3278 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
    3279
    3280 return SCIP_OKAY;
    3281}
    3282
    3283/** retrieves image of given origin from the hash map, or NULL if no image exists */
    3285 SCIP_HASHMAP* hashmap, /**< hash map */
    3286 void* origin /**< origin to retrieve image for */
    3287 )
    3288{
    3289 uint32_t pos;
    3290
    3291 assert(hashmap != NULL);
    3292 assert(hashmap->slots != NULL);
    3293 assert(hashmap->hashes != NULL);
    3294 assert(hashmap->mask > 0);
    3296
    3297 if( hashmapLookup(hashmap, origin, &pos) )
    3298 return hashmap->slots[pos].image.ptr;
    3299
    3300 return NULL;
    3301}
    3302
    3303/** retrieves image of given origin from the hash map, or INT_MAX if no image exists */
    3305 SCIP_HASHMAP* hashmap, /**< hash map */
    3306 void* origin /**< origin to retrieve image for */
    3307 )
    3308{
    3309 uint32_t pos;
    3310
    3311 assert(hashmap != NULL);
    3312 assert(hashmap->slots != NULL);
    3313 assert(hashmap->hashes != NULL);
    3314 assert(hashmap->mask > 0);
    3315 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
    3316
    3317 if( hashmapLookup(hashmap, origin, &pos) )
    3318 return hashmap->slots[pos].image.integer;
    3319
    3320 return INT_MAX;
    3321}
    3322
    3323/** retrieves image of given origin from the hash map, or SCIP_LONGINT_MAX if no image exists */
    3325 SCIP_HASHMAP* hashmap, /**< hash map */
    3326 void* origin /**< origin to retrieve image for */
    3327 )
    3328{
    3329 uint32_t pos;
    3330
    3331 assert(hashmap != NULL);
    3332 assert(hashmap->slots != NULL);
    3333 assert(hashmap->hashes != NULL);
    3334 assert(hashmap->mask > 0);
    3335 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_LONG);
    3336
    3337 if( hashmapLookup(hashmap, origin, &pos) )
    3338 return hashmap->slots[pos].image.longint;
    3339
    3340 return SCIP_LONGINT_MAX;
    3341}
    3342
    3343/** retrieves image of given origin from the hash map, or SCIP_INVALID if no image exists */
    3345 SCIP_HASHMAP* hashmap, /**< hash map */
    3346 void* origin /**< origin to retrieve image for */
    3347 )
    3348{
    3349 uint32_t pos;
    3350
    3351 assert(hashmap != NULL);
    3352 assert(hashmap->slots != NULL);
    3353 assert(hashmap->hashes != NULL);
    3354 assert(hashmap->mask > 0);
    3355 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
    3356
    3357 if( hashmapLookup(hashmap, origin, &pos) )
    3358 return hashmap->slots[pos].image.real;
    3359
    3360 return SCIP_INVALID;
    3361}
    3362
    3363/** sets image for given origin in the hash map, either by modifying existing origin->image pair
    3364 * or by appending a new origin->image pair
    3365 */
    3367 SCIP_HASHMAP* hashmap, /**< hash map */
    3368 void* origin, /**< origin to set image for */
    3369 void* image /**< new image for origin */
    3370 )
    3371{
    3372 uint32_t hashval;
    3374
    3375 assert(hashmap != NULL);
    3376 assert(hashmap->slots != NULL);
    3377 assert(hashmap->mask > 0);
    3379
    3380#ifndef NDEBUG
    3381 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
    3383#endif
    3384
    3385 SCIP_CALL( hashmapCheckLoad(hashmap) );
    3386
    3387 /* get the hash value */
    3388 hashval = hashvalue((size_t)origin);
    3389
    3390 /* append origin->image pair to hash map */
    3391 img.ptr = image;
    3392 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
    3393
    3394 return SCIP_OKAY;
    3395}
    3396
    3397/** sets image for given origin in the hash map, either by modifying existing origin->image pair
    3398 * or by appending a new origin->image pair
    3399 */
    3401 SCIP_HASHMAP* hashmap, /**< hash map */
    3402 void* origin, /**< origin to set image for */
    3403 int image /**< new image for origin */
    3404 )
    3405{
    3406 uint32_t hashval;
    3408
    3409 assert(hashmap != NULL);
    3410 assert(hashmap->slots != NULL);
    3411 assert(hashmap->mask > 0);
    3412 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
    3413
    3414#ifndef NDEBUG
    3415 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
    3417#endif
    3418
    3419 SCIP_CALL( hashmapCheckLoad(hashmap) );
    3420
    3421 /* get the hash value */
    3422 hashval = hashvalue((size_t)origin);
    3423
    3424 /* append origin->image pair to hash map */
    3425 img.integer = image;
    3426 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
    3427
    3428 return SCIP_OKAY;
    3429}
    3430
    3431/** sets image for given origin in the hash map, either by modifying existing origin->image pair
    3432 * or by appending a new origin->image pair
    3433 */
    3435 SCIP_HASHMAP* hashmap, /**< hash map */
    3436 void* origin, /**< origin to set image for */
    3437 SCIP_Real image /**< new image for origin */
    3438 )
    3439{
    3440 uint32_t hashval;
    3442
    3443 assert(hashmap != NULL);
    3444 assert(hashmap->slots != NULL);
    3445 assert(hashmap->mask > 0);
    3446 assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
    3447
    3448#ifndef NDEBUG
    3449 if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
    3451#endif
    3452
    3453 SCIP_CALL( hashmapCheckLoad(hashmap) );
    3454
    3455 /* get the hash value */
    3456 hashval = hashvalue((size_t)origin);
    3457
    3458 /* append origin->image pair to hash map */
    3459 img.real = image;
    3460 SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
    3461
    3462 return SCIP_OKAY;
    3463}
    3464
    3465/** checks whether an image to the given origin exists in the hash map */
    3467 SCIP_HASHMAP* hashmap, /**< hash map */
    3468 void* origin /**< origin to search for */
    3469 )
    3470{
    3471 uint32_t pos;
    3472
    3473 assert(hashmap != NULL);
    3474 assert(hashmap->slots != NULL);
    3475 assert(hashmap->hashes != NULL);
    3476 assert(hashmap->mask > 0);
    3477
    3478 return hashmapLookup(hashmap, origin, &pos);
    3479}
    3480
    3481/** removes origin->image pair from the hash map, if it exists */
    3483 SCIP_HASHMAP* hashmap, /**< hash map */
    3484 void* origin /**< origin to remove from the list */
    3485 )
    3486{
    3487 uint32_t pos;
    3488
    3489 assert(hashmap != NULL);
    3490 assert(hashmap->slots != NULL);
    3491 assert(hashmap->mask > 0);
    3492
    3493 assert(origin != NULL);
    3494
    3495 if( hashmapLookup(hashmap, origin, &pos) )
    3496 {
    3497 /* remove element */
    3498 hashmap->hashes[pos] = 0;
    3499 --hashmap->nelements;
    3500
    3501 /* move other elements if necessary */
    3502 while( TRUE ) /*lint !e716*/
    3503 {
    3504 uint32_t nextpos = (pos + 1) & hashmap->mask;
    3505
    3506 /* nothing to do since there is no chain that needs to be moved */
    3507 if( hashmap->hashes[nextpos] == 0 )
    3508 return SCIP_OKAY;
    3509
    3510 /* check if the element is the start of a new chain and return if that is the case */
    3511 if( (hashmap->hashes[nextpos]>>(hashmap->shift)) == nextpos )
    3512 return SCIP_OKAY;
    3513
    3514 /* element should be moved to the left and next element needs to be checked */
    3515 hashmap->slots[pos].origin = hashmap->slots[nextpos].origin;
    3516 hashmap->slots[pos].image = hashmap->slots[nextpos].image;
    3517 hashmap->hashes[pos] = hashmap->hashes[nextpos];
    3518 hashmap->hashes[nextpos] = 0;
    3519
    3520 pos = nextpos;
    3521 }
    3522 }
    3523
    3524 return SCIP_OKAY;
    3525}
    3526
    3527/** prints statistics about hash map usage */
    3529 SCIP_HASHMAP* hashmap, /**< hash map */
    3530 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
    3531 )
    3532{
    3533 uint32_t maxprobelen = 0;
    3534 uint64_t probelensum = 0;
    3535 uint32_t nslots;
    3536 uint32_t i;
    3537
    3538 assert(hashmap != NULL);
    3539
    3540 nslots = hashmap->mask + 1;
    3541
    3542 /* compute the maximum and average probe length */
    3543 for( i = 0; i < nslots; ++i )
    3544 {
    3545 if( hashmap->hashes[i] != 0 )
    3546 {
    3547 uint32_t probelen = ELEM_DISTANCE(i) + 1;
    3548 probelensum += probelen;
    3549 maxprobelen = MAX(probelen, maxprobelen);
    3550 }
    3551 }
    3552
    3553 /* print general hash map statistics */
    3554 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
    3555 (unsigned int)hashmap->nelements, (unsigned int)hashmap->nelements,
    3556 (unsigned int)nslots, 100.0*(SCIP_Real)hashmap->nelements/(SCIP_Real)(nslots));
    3557
    3558 /* if not empty print average and maximum probe length */
    3559 if( hashmap->nelements > 0 )
    3560 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
    3561 (SCIP_Real)(probelensum)/(SCIP_Real)hashmap->nelements, (unsigned int)maxprobelen);
    3562 SCIPmessagePrintInfo(messagehdlr, "\n");
    3563}
    3564
    3565/** indicates whether a hash map has no entries */
    3567 SCIP_HASHMAP* hashmap /**< hash map */
    3568 )
    3569{
    3570 assert(hashmap != NULL);
    3571
    3572 return hashmap->nelements == 0;
    3573}
    3574
    3575/** gives the number of elements in a hash map */
    3577 SCIP_HASHMAP* hashmap /**< hash map */
    3578 )
    3579{
    3580 return (int) hashmap->nelements;
    3581}
    3582
    3583/** gives the number of entries in the internal arrays of a hash map */
    3585 SCIP_HASHMAP* hashmap /**< hash map */
    3586 )
    3587{
    3588 return (int) hashmap->mask + 1;
    3589}
    3590
    3591/** gives the hashmap entry at the given index or NULL if entry is empty */
    3593 SCIP_HASHMAP* hashmap, /**< hash map */
    3594 int entryidx /**< index of hash map entry */
    3595 )
    3596{
    3597 assert(hashmap != NULL);
    3598
    3599 return hashmap->hashes[entryidx] == 0 ? NULL : &hashmap->slots[entryidx];
    3600}
    3601
    3602/** gives the origin of the hashmap entry */
    3604 SCIP_HASHMAPENTRY* entry /**< hash map entry */
    3605 )
    3606{
    3607 assert(entry != NULL);
    3608
    3609 return entry->origin;
    3610}
    3611
    3612/** gives the image of the hashmap entry */
    3614 SCIP_HASHMAPENTRY* entry /**< hash map entry */
    3615 )
    3616{
    3617 assert(entry != NULL);
    3618
    3619 return entry->image.ptr;
    3620}
    3621
    3622/** gives the image of the hashmap entry */
    3624 SCIP_HASHMAPENTRY* entry /**< hash map entry */
    3625 )
    3626{
    3627 assert(entry != NULL);
    3628
    3629 return entry->image.integer;
    3630}
    3631
    3632/** gives the image of the hashmap entry */
    3634 SCIP_HASHMAPENTRY* entry /**< hash map entry */
    3635 )
    3636{
    3637 assert(entry != NULL);
    3638
    3639 return entry->image.real;
    3640}
    3641
    3642/** sets pointer image of a hashmap entry */
    3644 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
    3645 void* image /**< new image */
    3646 )
    3647{
    3648 assert(entry != NULL);
    3649
    3650 entry->image.ptr = image;
    3651}
    3652
    3653/** sets integer image of a hashmap entry */
    3655 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
    3656 int image /**< new image */
    3657 )
    3658{
    3659 assert(entry != NULL);
    3660
    3661 entry->image.integer = image;
    3662}
    3663
    3664/** sets real image of a hashmap entry */
    3666 SCIP_HASHMAPENTRY* entry, /**< hash map entry */
    3667 SCIP_Real image /**< new image */
    3668 )
    3669{
    3670 assert(entry != NULL);
    3671
    3672 entry->image.real = image;
    3673}
    3674
    3675/** removes all entries in a hash map. */
    3677 SCIP_HASHMAP* hashmap /**< hash map */
    3678 )
    3679{
    3680 assert(hashmap != NULL);
    3681
    3682 BMSclearMemoryArray(hashmap->hashes, hashmap->mask + 1);
    3683
    3684 hashmap->nelements = 0;
    3685
    3686 return SCIP_OKAY;
    3687}
    3688
    3689
    3690/*
    3691 * Hash Set
    3692 */
    3693
    3694/* redefine ELEM_DISTANCE macro for hashset */
    3695#undef ELEM_DISTANCE
    3696/* computes the distance from it's desired position for the element stored at pos */
    3697#define ELEM_DISTANCE(pos) (((pos) + nslots - hashSetDesiredPos(hashset, hashset->slots[(pos)])) & mask)
    3698
    3699/* calculate desired position of element in hash set */
    3700static
    3702 SCIP_HASHSET* hashset, /**< the hash set */
    3703 void* element /**< element to calculate position for */
    3704 )
    3705{
    3706 return (uint32_t)((UINT64_C(0x9e3779b97f4a7c15) * (uintptr_t)element)>>(hashset->shift));
    3707}
    3708
    3709static
    3711 SCIP_HASHSET* hashset, /**< hash set */
    3712 void* element /**< element to insert */
    3713 )
    3714{
    3715 uint32_t elemdistance;
    3716 uint32_t pos;
    3717 uint32_t nslots;
    3718 uint32_t mask;
    3719
    3720 assert(hashset != NULL);
    3721 assert(hashset->slots != NULL);
    3722 assert(element != NULL);
    3723
    3724 pos = hashSetDesiredPos(hashset, element);
    3725 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
    3726 mask = nslots - 1;
    3727
    3728 elemdistance = 0;
    3729 while( TRUE ) /*lint !e716*/
    3730 {
    3731 uint32_t distance;
    3732
    3733 /* if position is empty or key equal insert element */
    3734 if( hashset->slots[pos] == NULL )
    3735 {
    3736 hashset->slots[pos] = element;
    3737 ++hashset->nelements;
    3738 return;
    3739 }
    3740
    3741 if( hashset->slots[pos] == element )
    3742 return;
    3743
    3744 /* otherwise check if the current element at this position is closer to its hashvalue */
    3745 distance = ELEM_DISTANCE(pos);
    3746 if( distance < elemdistance )
    3747 {
    3748 /* if this is the case we insert the new element here and find a new position for the old one */
    3749 elemdistance = distance;
    3750 SCIPswapPointers(&hashset->slots[pos], &element);
    3751 }
    3752
    3753 /* continue until we have found an empty position */
    3754 pos = (pos + 1) & mask;
    3755 ++elemdistance;
    3756 }
    3757}
    3758
    3759/** check if the load factor of the hash set is too high and rebuild if necessary */
    3760static
    3762 SCIP_HASHSET* hashset, /**< hash set */
    3763 BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
    3764 )
    3765{
    3766 assert(hashset != NULL);
    3767 assert(hashset->shift < 64);
    3768
    3769 /* use integer arithmetic to approximately check if load factor is above 90% */
    3770 if( ((((uint64_t)hashset->nelements)<<10)>>(64-hashset->shift) > 921) )
    3771 {
    3772 void** slots;
    3773 uint32_t nslots;
    3774 uint32_t newnslots;
    3775 uint32_t i;
    3776
    3777 /* calculate new size (always power of two) */
    3778 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
    3779 newnslots = 2*nslots;
    3780 --hashset->shift;
    3781
    3782 /* reallocate array */
    3783 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &slots, newnslots) );
    3784
    3785 SCIPswapPointers((void**) &slots, (void**) &hashset->slots);
    3786 hashset->nelements = 0;
    3787
    3788 /* reinsert all elements */
    3789 for( i = 0; i < nslots; ++i )
    3790 {
    3791 if( slots[i] != NULL )
    3792 hashsetInsert(hashset, slots[i]);
    3793 }
    3794
    3795 BMSfreeBlockMemoryArray(blkmem, &slots, nslots);
    3796 }
    3797
    3798 return SCIP_OKAY;
    3799}
    3800
    3801/** creates a hash set of pointers */
    3803 SCIP_HASHSET** hashset, /**< pointer to store the created hash set */
    3804 BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
    3805 int size /**< initial size of the hash set; it is guaranteed that the set is not
    3806 * resized if at most that many elements are inserted */
    3807 )
    3808{
    3809 uint32_t nslots;
    3810
    3811 assert(hashset != NULL);
    3812 assert(size >= 0);
    3813 assert(blkmem != NULL);
    3814
    3815 SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashset) );
    3816
    3817 /* do not create too small hashtables, i.e. at least size 32, and increase
    3818 * the given size by dividing it by 0.9, since then no rebuilding will
    3819 * be necessary if the given number of elements are inserted. Finally round
    3820 * to the next power of two.
    3821 */
    3822 (*hashset)->shift = 64;
    3823 (*hashset)->shift -= (unsigned int)ceil(log(MAX(8.0, size / 0.9)) / log(2.0));
    3824 nslots = (uint32_t)SCIPhashsetGetNSlots(*hashset);
    3825 (*hashset)->nelements = 0;
    3826
    3827 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashset)->slots, nslots) );
    3828
    3829 return SCIP_OKAY;
    3830}
    3831
    3832/** frees the hash set */
    3834 SCIP_HASHSET** hashset, /**< pointer to the hash set */
    3835 BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
    3836 )
    3837{
    3838 BMSfreeBlockMemoryArray(blkmem, &(*hashset)->slots, SCIPhashsetGetNSlots(*hashset));
    3839 BMSfreeBlockMemory(blkmem, hashset);
    3840}
    3841
    3842/** inserts new element into the hash set */
    3844 SCIP_HASHSET* hashset, /**< hash set */
    3845 BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
    3846 void* element /**< element to insert */
    3847 )
    3848{
    3849 assert(hashset != NULL);
    3850 assert(hashset->slots != NULL);
    3851
    3852 SCIP_CALL( hashsetCheckLoad(hashset, blkmem) );
    3853
    3854 hashsetInsert(hashset, element);
    3855
    3856 return SCIP_OKAY;
    3857}
    3858
    3859/** checks whether an element exists in the hash set */
    3861 SCIP_HASHSET* hashset, /**< hash set */
    3862 void* element /**< element to search for */
    3863 )
    3864{
    3865 uint32_t pos;
    3866 uint32_t nslots;
    3867 uint32_t mask;
    3868 uint32_t elemdistance;
    3869
    3870 assert(hashset != NULL);
    3871 assert(hashset->slots != NULL);
    3872
    3873 pos = hashSetDesiredPos(hashset, element);
    3874 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
    3875 mask = nslots - 1;
    3876 elemdistance = 0;
    3877
    3878 while( TRUE ) /*lint !e716*/
    3879 {
    3880 uint32_t distance;
    3881
    3882 /* found element */
    3883 if( hashset->slots[pos] == element )
    3884 return TRUE;
    3885
    3886 /* slots is empty so element cannot be contained */
    3887 if( hashset->slots[pos] == NULL )
    3888 return FALSE;
    3889
    3890 distance = ELEM_DISTANCE(pos);
    3891 /* element can not be contained since otherwise we would have swapped it with this one during insert */
    3892 if( elemdistance > distance )
    3893 return FALSE;
    3894
    3895 pos = (pos + 1) & mask;
    3896 ++elemdistance;
    3897 }
    3898}
    3899
    3900/** removes an element from the hash set, if it exists */
    3902 SCIP_HASHSET* hashset, /**< hash set */
    3903 void* element /**< origin to remove from the list */
    3904 )
    3905{
    3906 uint32_t pos;
    3907 uint32_t nslots;
    3908 uint32_t mask;
    3909 uint32_t elemdistance;
    3910
    3911 assert(hashset != NULL);
    3912 assert(hashset->slots != NULL);
    3913 assert(element != NULL);
    3914
    3915 pos = hashSetDesiredPos(hashset, element);
    3916 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
    3917 mask = nslots - 1;
    3918 elemdistance = 0;
    3919
    3920 while( TRUE ) /*lint !e716*/
    3921 {
    3922 uint32_t distance;
    3923
    3924 /* found element */
    3925 if( hashset->slots[pos] == element )
    3926 break;
    3927
    3928 /* slots is empty so element cannot be contained */
    3929 if( hashset->slots[pos] == NULL )
    3930 return SCIP_OKAY;
    3931
    3932 distance = ELEM_DISTANCE(pos);
    3933 /* element can not be contained since otherwise we would have swapped it with this one during insert */
    3934 if( elemdistance > distance )
    3935 return SCIP_OKAY;
    3936
    3937 pos = (pos + 1) & mask;
    3938 ++elemdistance;
    3939 }
    3940
    3941 assert(hashset->slots[pos] == element);
    3942 assert(SCIPhashsetExists(hashset, element));
    3943
    3944 /* remove element */
    3945 --hashset->nelements;
    3946
    3947 /* move other elements if necessary */
    3948 while( TRUE ) /*lint !e716*/
    3949 {
    3950 uint32_t nextpos = (pos + 1) & mask;
    3951
    3952 /* nothing to do since there is no chain that needs to be moved */
    3953 if( hashset->slots[nextpos] == NULL )
    3954 {
    3955 hashset->slots[pos] = NULL;
    3956 assert(!SCIPhashsetExists(hashset, element));
    3957 return SCIP_OKAY;
    3958 }
    3959
    3960 /* check if the element is the start of a new chain and return if that is the case */
    3961 if( hashSetDesiredPos(hashset, hashset->slots[nextpos]) == nextpos )
    3962 {
    3963 hashset->slots[pos] = NULL;
    3964 assert(!SCIPhashsetExists(hashset, element));
    3965 return SCIP_OKAY;
    3966 }
    3967
    3968 /* element should be moved to the left and next element needs to be checked */
    3969 hashset->slots[pos] = hashset->slots[nextpos];
    3970
    3971 pos = nextpos;
    3972 }
    3973}
    3974
    3975/** prints statistics about hash set usage */
    3977 SCIP_HASHSET* hashset, /**< hash set */
    3978 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
    3979 )
    3980{
    3981 uint32_t maxprobelen = 0;
    3982 uint64_t probelensum = 0;
    3983 uint32_t nslots;
    3984 uint32_t mask;
    3985 uint32_t i;
    3986
    3987 assert(hashset != NULL);
    3988
    3989 nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
    3990 mask = nslots - 1;
    3991
    3992 /* compute the maximum and average probe length */
    3993 for( i = 0; i < nslots; ++i )
    3994 {
    3995 if( hashset->slots[i] != NULL )
    3996 {
    3997 uint32_t probelen = ((hashSetDesiredPos(hashset, hashset->slots[i]) + nslots - i) & mask) + 1;
    3998 probelensum += probelen;
    3999 maxprobelen = MAX(probelen, maxprobelen);
    4000 }
    4001 }
    4002
    4003 /* print general hash set statistics */
    4004 SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
    4005 (unsigned int)hashset->nelements, (unsigned int)hashset->nelements,
    4006 (unsigned int)nslots, 100.0*(SCIP_Real)hashset->nelements/(SCIP_Real)(nslots));
    4007
    4008 /* if not empty print average and maximum probe length */
    4009 if( hashset->nelements > 0 )
    4010 SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
    4011 (SCIP_Real)(probelensum)/(SCIP_Real)hashset->nelements, (unsigned int)maxprobelen);
    4012 SCIPmessagePrintInfo(messagehdlr, "\n");
    4013}
    4014
    4015/* In debug mode, the following methods are implemented as function calls to ensure
    4016 * type validity.
    4017 * In optimized mode, the methods are implemented as defines to improve performance.
    4018 * However, we want to have them in the library anyways, so we have to undef the defines.
    4019 */
    4020
    4021#undef SCIPhashsetIsEmpty
    4022#undef SCIPhashsetGetNElements
    4023#undef SCIPhashsetGetNSlots
    4024#undef SCIPhashsetGetSlots
    4025
    4026/** indicates whether a hash set has no entries */
    4028 SCIP_HASHSET* hashset /**< hash set */
    4029 )
    4030{
    4031 return hashset->nelements == 0;
    4032}
    4033
    4034/** gives the number of elements in a hash set */
    4036 SCIP_HASHSET* hashset /**< hash set */
    4037 )
    4038{
    4039 return (int)hashset->nelements;
    4040}
    4041
    4042/** gives the number of slots of a hash set */
    4044 SCIP_HASHSET* hashset /**< hash set */
    4045 )
    4046{
    4047 return (int) (1u << (64 - hashset->shift));
    4048}
    4049
    4050/** gives the array of hash set slots; contains all elements in indetermined order and may contain NULL values */
    4052 SCIP_HASHSET* hashset /**< hash set */
    4053 )
    4054{
    4055 return hashset->slots;
    4056}
    4057
    4058/** removes all entries in a hash set. */
    4060 SCIP_HASHSET* hashset /**< hash set */
    4061 )
    4062{
    4064
    4065 hashset->nelements = 0;
    4066}
    4067
    4068/*
    4069 * Dynamic Arrays
    4070 */
    4071
    4072/** creates a dynamic array of real values */
    4074 SCIP_REALARRAY** realarray, /**< pointer to store the real array */
    4075 BMS_BLKMEM* blkmem /**< block memory */
    4076 )
    4077{
    4078 assert(realarray != NULL);
    4079 assert(blkmem != NULL);
    4080
    4081 SCIP_ALLOC( BMSallocBlockMemory(blkmem, realarray) );
    4082 (*realarray)->blkmem = blkmem;
    4083 (*realarray)->vals = NULL;
    4084 (*realarray)->valssize = 0;
    4085 (*realarray)->firstidx = -1;
    4086 (*realarray)->minusedidx = INT_MAX;
    4087 (*realarray)->maxusedidx = INT_MIN;
    4088
    4089 return SCIP_OKAY;
    4090}
    4091
    4092/** creates a copy of a dynamic array of real values */
    4094 SCIP_REALARRAY** realarray, /**< pointer to store the copied real array */
    4095 BMS_BLKMEM* blkmem, /**< block memory */
    4096 SCIP_REALARRAY* sourcerealarray /**< dynamic real array to copy */
    4097 )
    4098{
    4099 assert(realarray != NULL);
    4100 assert(sourcerealarray != NULL);
    4101
    4102 SCIP_CALL( SCIPrealarrayCreate(realarray, blkmem) );
    4103 if( sourcerealarray->valssize > 0 )
    4104 {
    4105 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*realarray)->vals, sourcerealarray->vals, \
    4106 sourcerealarray->valssize) );
    4107 }
    4108 (*realarray)->valssize = sourcerealarray->valssize;
    4109 (*realarray)->firstidx = sourcerealarray->firstidx;
    4110 (*realarray)->minusedidx = sourcerealarray->minusedidx;
    4111 (*realarray)->maxusedidx = sourcerealarray->maxusedidx;
    4112
    4113 return SCIP_OKAY;
    4114}
    4115
    4116/** frees a dynamic array of real values */
    4118 SCIP_REALARRAY** realarray /**< pointer to the real array */
    4119 )
    4120{
    4121 assert(realarray != NULL);
    4122 assert(*realarray != NULL);
    4123
    4124 BMSfreeBlockMemoryArrayNull((*realarray)->blkmem, &(*realarray)->vals, (*realarray)->valssize);
    4125 BMSfreeBlockMemory((*realarray)->blkmem, realarray);
    4126
    4127 return SCIP_OKAY;
    4128}
    4129
    4130/** extends dynamic array to be able to store indices from minidx to maxidx */
    4132 SCIP_REALARRAY* realarray, /**< dynamic real array */
    4133 int arraygrowinit, /**< initial size of array */
    4134 SCIP_Real arraygrowfac, /**< growing factor of array */
    4135 int minidx, /**< smallest index to allocate storage for */
    4136 int maxidx /**< largest index to allocate storage for */
    4137 )
    4138{
    4139 int nused;
    4140 int nfree;
    4141 int newfirstidx;
    4142 int i;
    4143
    4144 assert(realarray != NULL);
    4145 assert(realarray->minusedidx == INT_MAX || realarray->firstidx >= 0);
    4146 assert(realarray->maxusedidx == INT_MIN || realarray->firstidx >= 0);
    4147 assert(realarray->minusedidx == INT_MAX || realarray->minusedidx >= realarray->firstidx);
    4148 assert(realarray->maxusedidx == INT_MIN || realarray->maxusedidx < realarray->firstidx + realarray->valssize);
    4149 assert(0 <= minidx);
    4150 assert(minidx <= maxidx);
    4151
    4152 minidx = MIN(minidx, realarray->minusedidx);
    4153 maxidx = MAX(maxidx, realarray->maxusedidx);
    4154 assert(0 <= minidx);
    4155 assert(minidx <= maxidx);
    4156
    4157 SCIPdebugMessage("extending realarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
    4158 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, minidx, maxidx);
    4159
    4160 /* check, whether we have to allocate additional memory, or shift the array */
    4161 nused = maxidx - minidx + 1;
    4162 if( nused > realarray->valssize )
    4163 {
    4164 SCIP_Real* newvals;
    4165 int newvalssize;
    4166
    4167 /* allocate new memory storage */
    4168 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
    4169 SCIP_ALLOC( BMSallocBlockMemoryArray(realarray->blkmem, &newvals, newvalssize) );
    4170 nfree = newvalssize - nused;
    4171 newfirstidx = minidx - nfree/2;
    4172 newfirstidx = MAX(newfirstidx, 0);
    4173 assert(newfirstidx <= minidx);
    4174 assert(maxidx < newfirstidx + newvalssize);
    4175
    4176 /* initialize memory array by copying old values and setting new values to zero */
    4177 if( realarray->firstidx != -1 )
    4178 {
    4179 for( i = 0; i < realarray->minusedidx - newfirstidx; ++i )
    4180 newvals[i] = 0.0;
    4181
    4182 /* check for possible overflow or negative value */
    4183 assert(realarray->maxusedidx - realarray->minusedidx + 1 > 0);
    4184
    4185 BMScopyMemoryArray(&newvals[realarray->minusedidx - newfirstidx],
    4186 &(realarray->vals[realarray->minusedidx - realarray->firstidx]),
    4187 realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866 !e776*/
    4188 for( i = realarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
    4189 newvals[i] = 0.0;
    4190 }
    4191 else
    4192 {
    4193 for( i = 0; i < newvalssize; ++i )
    4194 newvals[i] = 0.0;
    4195 }
    4196
    4197 /* free old memory storage, and set the new array parameters */
    4198 BMSfreeBlockMemoryArrayNull(realarray->blkmem, &realarray->vals, realarray->valssize);
    4199 realarray->vals = newvals;
    4200 realarray->valssize = newvalssize;
    4201 realarray->firstidx = newfirstidx;
    4202 }
    4203 else if( realarray->firstidx == -1 )
    4204 {
    4205 /* a sufficiently large memory storage exists, but it was cleared */
    4206 nfree = realarray->valssize - nused;
    4207 assert(nfree >= 0);
    4208 realarray->firstidx = minidx - nfree/2;
    4209 assert(realarray->firstidx <= minidx);
    4210 assert(maxidx < realarray->firstidx + realarray->valssize);
    4211#ifndef NDEBUG
    4212 for( i = 0; i < realarray->valssize; ++i )
    4213 assert(realarray->vals[i] == 0.0);
    4214#endif
    4215 }
    4216 else if( minidx < realarray->firstidx )
    4217 {
    4218 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
    4219 nfree = realarray->valssize - nused;
    4220 assert(nfree >= 0);
    4221 newfirstidx = minidx - nfree/2;
    4222 newfirstidx = MAX(newfirstidx, 0);
    4223 assert(newfirstidx <= minidx);
    4224 assert(maxidx < newfirstidx + realarray->valssize);
    4225
    4226 if( realarray->minusedidx <= realarray->maxusedidx )
    4227 {
    4228 int shift;
    4229
    4230 assert(realarray->firstidx <= realarray->minusedidx);
    4231 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
    4232
    4233 /* shift used part of array to the right */
    4234 shift = realarray->firstidx - newfirstidx;
    4235 assert(shift > 0);
    4236 for( i = realarray->maxusedidx - realarray->firstidx; i >= realarray->minusedidx - realarray->firstidx; --i )
    4237 {
    4238 assert(0 <= i + shift && i + shift < realarray->valssize);
    4239 realarray->vals[i + shift] = realarray->vals[i];
    4240 }
    4241 /* clear the formerly used head of the array */
    4242 for( i = 0; i < shift; ++i )
    4243 realarray->vals[realarray->minusedidx - realarray->firstidx + i] = 0.0;
    4244 }
    4245 realarray->firstidx = newfirstidx;
    4246 }
    4247 else if( maxidx >= realarray->firstidx + realarray->valssize )
    4248 {
    4249 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
    4250 nfree = realarray->valssize - nused;
    4251 assert(nfree >= 0);
    4252 newfirstidx = minidx - nfree/2;
    4253 newfirstidx = MAX(newfirstidx, 0);
    4254 assert(newfirstidx <= minidx);
    4255 assert(maxidx < newfirstidx + realarray->valssize);
    4256
    4257 if( realarray->minusedidx <= realarray->maxusedidx )
    4258 {
    4259 int shift;
    4260
    4261 assert(realarray->firstidx <= realarray->minusedidx);
    4262 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
    4263
    4264 /* shift used part of array to the left */
    4265 shift = newfirstidx - realarray->firstidx;
    4266 assert(shift > 0);
    4267 for( i = realarray->minusedidx - realarray->firstidx; i <= realarray->maxusedidx - realarray->firstidx; ++i )
    4268 {
    4269 assert(0 <= i - shift && i - shift < realarray->valssize);
    4270 realarray->vals[i - shift] = realarray->vals[i];
    4271 }
    4272 /* clear the formerly used tail of the array */
    4273 for( i = 0; i < shift; ++i )
    4274 realarray->vals[realarray->maxusedidx - realarray->firstidx - i] = 0.0;
    4275 }
    4276 realarray->firstidx = newfirstidx;
    4277 }
    4278
    4279 assert(minidx >= realarray->firstidx);
    4280 assert(maxidx < realarray->firstidx + realarray->valssize);
    4281
    4282 return SCIP_OKAY;
    4283}
    4284
    4285/** clears a dynamic real array */
    4287 SCIP_REALARRAY* realarray /**< dynamic real array */
    4288 )
    4289{
    4290 assert(realarray != NULL);
    4291
    4292 SCIPdebugMessage("clearing realarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
    4293 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx);
    4294
    4295 if( realarray->minusedidx <= realarray->maxusedidx )
    4296 {
    4297 assert(realarray->firstidx <= realarray->minusedidx);
    4298 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
    4299 assert(realarray->firstidx != -1);
    4300 assert(realarray->valssize > 0);
    4301
    4302 /* clear the used part of array */
    4303 BMSclearMemoryArray(&realarray->vals[realarray->minusedidx - realarray->firstidx],
    4304 realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866*/
    4305
    4306 /* mark the array cleared */
    4307 realarray->minusedidx = INT_MAX;
    4308 realarray->maxusedidx = INT_MIN;
    4309 }
    4310 assert(realarray->minusedidx == INT_MAX);
    4311 assert(realarray->maxusedidx == INT_MIN);
    4312
    4313 return SCIP_OKAY;
    4314}
    4315
    4316/** gets value of entry in dynamic array */
    4318 SCIP_REALARRAY* realarray, /**< dynamic real array */
    4319 int idx /**< array index to get value for */
    4320 )
    4321{
    4322 assert(realarray != NULL);
    4323 assert(idx >= 0);
    4324
    4325 if( idx < realarray->minusedidx || idx > realarray->maxusedidx )
    4326 return 0.0;
    4327 else
    4328 {
    4329 assert(realarray->vals != NULL);
    4330 assert(idx - realarray->firstidx >= 0);
    4331 assert(idx - realarray->firstidx < realarray->valssize);
    4332
    4333 return realarray->vals[idx - realarray->firstidx];
    4334 }
    4335}
    4336
    4337/** sets value of entry in dynamic array */
    4339 SCIP_REALARRAY* realarray, /**< dynamic real array */
    4340 int arraygrowinit, /**< initial size of array */
    4341 SCIP_Real arraygrowfac, /**< growing factor of array */
    4342 int idx, /**< array index to set value for */
    4343 SCIP_Real val /**< value to set array index to */
    4344 )
    4345{
    4346 assert(realarray != NULL);
    4347 assert(idx >= 0);
    4348
    4349 SCIPdebugMessage("setting realarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %g\n",
    4350 (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, idx, val);
    4351
    4352 if( val != 0.0 )
    4353 {
    4354 /* extend array to be able to store the index */
    4355 SCIP_CALL( SCIPrealarrayExtend(realarray, arraygrowinit, arraygrowfac, idx, idx) );
    4356 assert(idx >= realarray->firstidx);
    4357 assert(idx < realarray->firstidx + realarray->valssize);
    4358
    4359 /* set the array value of the index */
    4360 realarray->vals[idx - realarray->firstidx] = val;
    4361
    4362 /* update min/maxusedidx */
    4363 realarray->minusedidx = MIN(realarray->minusedidx, idx);
    4364 realarray->maxusedidx = MAX(realarray->maxusedidx, idx);
    4365 }
    4366 else if( idx >= realarray->firstidx && idx < realarray->firstidx + realarray->valssize )
    4367 {
    4368 /* set the array value of the index to zero */
    4369 realarray->vals[idx - realarray->firstidx] = 0.0;
    4370
    4371 /* check, if we can tighten the min/maxusedidx */
    4372 if( idx == realarray->minusedidx )
    4373 {
    4374 assert(realarray->maxusedidx >= 0);
    4375 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
    4376 do
    4377 {
    4378 realarray->minusedidx++;
    4379 }
    4380 while( realarray->minusedidx <= realarray->maxusedidx
    4381 && realarray->vals[realarray->minusedidx - realarray->firstidx] == 0.0 );
    4382
    4383 if( realarray->minusedidx > realarray->maxusedidx )
    4384 {
    4385 realarray->minusedidx = INT_MAX;
    4386 realarray->maxusedidx = INT_MIN;
    4387 }
    4388 }
    4389 else if( idx == realarray->maxusedidx )
    4390 {
    4391 assert(realarray->minusedidx >= 0);
    4392 assert(realarray->minusedidx < realarray->maxusedidx);
    4393 assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
    4394 do
    4395 {
    4396 realarray->maxusedidx--;
    4397 assert(realarray->minusedidx <= realarray->maxusedidx);
    4398 }
    4399 while( realarray->vals[realarray->maxusedidx - realarray->firstidx] == 0.0 );
    4400 }
    4401 }
    4402
    4403 return SCIP_OKAY;
    4404}
    4405
    4406/** increases value of entry in dynamic array */
    4408 SCIP_REALARRAY* realarray, /**< dynamic real array */
    4409 int arraygrowinit, /**< initial size of array */
    4410 SCIP_Real arraygrowfac, /**< growing factor of array */
    4411 int idx, /**< array index to increase value for */
    4412 SCIP_Real incval /**< value to increase array index */
    4413 )
    4414{
    4415 SCIP_Real oldval;
    4416
    4417 oldval = SCIPrealarrayGetVal(realarray, idx);
    4418 if( oldval != SCIP_INVALID ) /*lint !e777*/
    4419 return SCIPrealarraySetVal(realarray, arraygrowinit, arraygrowfac, idx, oldval + incval);
    4420 else
    4421 return SCIP_OKAY;
    4422}
    4423
    4424/** returns the minimal index of all stored non-zero elements */
    4426 SCIP_REALARRAY* realarray /**< dynamic real array */
    4427 )
    4428{
    4429 assert(realarray != NULL);
    4430
    4431 return realarray->minusedidx;
    4432}
    4433
    4434/** returns the maximal index of all stored non-zero elements */
    4436 SCIP_REALARRAY* realarray /**< dynamic real array */
    4437 )
    4438{
    4439 assert(realarray != NULL);
    4440
    4441 return realarray->maxusedidx;
    4442}
    4443
    4444/** creates a dynamic array of int values */
    4446 SCIP_INTARRAY** intarray, /**< pointer to store the int array */
    4447 BMS_BLKMEM* blkmem /**< block memory */
    4448 )
    4449{
    4450 assert(intarray != NULL);
    4451 assert(blkmem != NULL);
    4452
    4453 SCIP_ALLOC( BMSallocBlockMemory(blkmem, intarray) );
    4454 (*intarray)->blkmem = blkmem;
    4455 (*intarray)->vals = NULL;
    4456 (*intarray)->valssize = 0;
    4457 (*intarray)->firstidx = -1;
    4458 (*intarray)->minusedidx = INT_MAX;
    4459 (*intarray)->maxusedidx = INT_MIN;
    4460
    4461 return SCIP_OKAY;
    4462}
    4463
    4464/** creates a copy of a dynamic array of int values */
    4466 SCIP_INTARRAY** intarray, /**< pointer to store the copied int array */
    4467 BMS_BLKMEM* blkmem, /**< block memory */
    4468 SCIP_INTARRAY* sourceintarray /**< dynamic int array to copy */
    4469 )
    4470{
    4471 assert(intarray != NULL);
    4472 assert(sourceintarray != NULL);
    4473
    4474 SCIP_CALL( SCIPintarrayCreate(intarray, blkmem) );
    4475 if( sourceintarray->valssize > 0 )
    4476 {
    4477 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*intarray)->vals, sourceintarray->vals, sourceintarray->valssize) );
    4478 }
    4479 (*intarray)->valssize = sourceintarray->valssize;
    4480 (*intarray)->firstidx = sourceintarray->firstidx;
    4481 (*intarray)->minusedidx = sourceintarray->minusedidx;
    4482 (*intarray)->maxusedidx = sourceintarray->maxusedidx;
    4483
    4484 return SCIP_OKAY;
    4485}
    4486
    4487/** frees a dynamic array of int values */
    4489 SCIP_INTARRAY** intarray /**< pointer to the int array */
    4490 )
    4491{
    4492 assert(intarray != NULL);
    4493 assert(*intarray != NULL);
    4494
    4495 BMSfreeBlockMemoryArrayNull((*intarray)->blkmem, &(*intarray)->vals, (*intarray)->valssize);
    4496 BMSfreeBlockMemory((*intarray)->blkmem, intarray);
    4497
    4498 return SCIP_OKAY;
    4499}
    4500
    4501/** extends dynamic array to be able to store indices from minidx to maxidx */
    4503 SCIP_INTARRAY* intarray, /**< dynamic int array */
    4504 int arraygrowinit, /**< initial size of array */
    4505 SCIP_Real arraygrowfac, /**< growing factor of array */
    4506 int minidx, /**< smallest index to allocate storage for */
    4507 int maxidx /**< largest index to allocate storage for */
    4508 )
    4509{
    4510 int nused;
    4511 int nfree;
    4512 int newfirstidx;
    4513 int i;
    4514
    4515 assert(intarray != NULL);
    4516 assert(intarray->minusedidx == INT_MAX || intarray->firstidx >= 0);
    4517 assert(intarray->maxusedidx == INT_MIN || intarray->firstidx >= 0);
    4518 assert(intarray->minusedidx == INT_MAX || intarray->minusedidx >= intarray->firstidx);
    4519 assert(intarray->maxusedidx == INT_MIN || intarray->maxusedidx < intarray->firstidx + intarray->valssize);
    4520 assert(0 <= minidx);
    4521 assert(minidx <= maxidx);
    4522
    4523 minidx = MIN(minidx, intarray->minusedidx);
    4524 maxidx = MAX(maxidx, intarray->maxusedidx);
    4525 assert(0 <= minidx);
    4526 assert(minidx <= maxidx);
    4527
    4528 SCIPdebugMessage("extending intarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
    4529 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, minidx, maxidx);
    4530
    4531 /* check, whether we have to allocate additional memory, or shift the array */
    4532 nused = maxidx - minidx + 1;
    4533 if( nused > intarray->valssize )
    4534 {
    4535 int* newvals;
    4536 int newvalssize;
    4537
    4538 /* allocate new memory storage */
    4539 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
    4540 SCIP_ALLOC( BMSallocBlockMemoryArray(intarray->blkmem, &newvals, newvalssize) );
    4541 nfree = newvalssize - nused;
    4542 newfirstidx = minidx - nfree/2;
    4543 newfirstidx = MAX(newfirstidx, 0);
    4544 assert(newfirstidx <= minidx);
    4545 assert(maxidx < newfirstidx + newvalssize);
    4546
    4547 /* initialize memory array by copying old values and setting new values to zero */
    4548 if( intarray->firstidx != -1 )
    4549 {
    4550 for( i = 0; i < intarray->minusedidx - newfirstidx; ++i )
    4551 newvals[i] = 0;
    4552
    4553 /* check for possible overflow or negative value */
    4554 assert(intarray->maxusedidx - intarray->minusedidx + 1 > 0);
    4555
    4556 BMScopyMemoryArray(&newvals[intarray->minusedidx - newfirstidx],
    4557 &intarray->vals[intarray->minusedidx - intarray->firstidx],
    4558 intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866 !e776*/
    4559 for( i = intarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
    4560 newvals[i] = 0;
    4561 }
    4562 else
    4563 {
    4564 for( i = 0; i < newvalssize; ++i )
    4565 newvals[i] = 0;
    4566 }
    4567
    4568 /* free old memory storage, and set the new array parameters */
    4569 BMSfreeBlockMemoryArrayNull(intarray->blkmem, &intarray->vals, intarray->valssize);
    4570 intarray->vals = newvals;
    4571 intarray->valssize = newvalssize;
    4572 intarray->firstidx = newfirstidx;
    4573 }
    4574 else if( intarray->firstidx == -1 )
    4575 {
    4576 /* a sufficiently large memory storage exists, but it was cleared */
    4577 nfree = intarray->valssize - nused;
    4578 assert(nfree >= 0);
    4579 intarray->firstidx = minidx - nfree/2;
    4580 assert(intarray->firstidx <= minidx);
    4581 assert(maxidx < intarray->firstidx + intarray->valssize);
    4582#ifndef NDEBUG
    4583 for( i = 0; i < intarray->valssize; ++i )
    4584 assert(intarray->vals[i] == 0);
    4585#endif
    4586 }
    4587 else if( minidx < intarray->firstidx )
    4588 {
    4589 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
    4590 nfree = intarray->valssize - nused;
    4591 assert(nfree >= 0);
    4592 newfirstidx = minidx - nfree/2;
    4593 newfirstidx = MAX(newfirstidx, 0);
    4594 assert(newfirstidx <= minidx);
    4595 assert(maxidx < newfirstidx + intarray->valssize);
    4596
    4597 if( intarray->minusedidx <= intarray->maxusedidx )
    4598 {
    4599 int shift;
    4600
    4601 assert(intarray->firstidx <= intarray->minusedidx);
    4602 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
    4603
    4604 /* shift used part of array to the right */
    4605 shift = intarray->firstidx - newfirstidx;
    4606 assert(shift > 0);
    4607 for( i = intarray->maxusedidx - intarray->firstidx; i >= intarray->minusedidx - intarray->firstidx; --i )
    4608 {
    4609 assert(0 <= i + shift && i + shift < intarray->valssize);
    4610 intarray->vals[i + shift] = intarray->vals[i];
    4611 }
    4612 /* clear the formerly used head of the array */
    4613 for( i = 0; i < shift; ++i )
    4614 intarray->vals[intarray->minusedidx - intarray->firstidx + i] = 0;
    4615 }
    4616 intarray->firstidx = newfirstidx;
    4617 }
    4618 else if( maxidx >= intarray->firstidx + intarray->valssize )
    4619 {
    4620 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
    4621 nfree = intarray->valssize - nused;
    4622 assert(nfree >= 0);
    4623 newfirstidx = minidx - nfree/2;
    4624 newfirstidx = MAX(newfirstidx, 0);
    4625 assert(newfirstidx <= minidx);
    4626 assert(maxidx < newfirstidx + intarray->valssize);
    4627
    4628 if( intarray->minusedidx <= intarray->maxusedidx )
    4629 {
    4630 int shift;
    4631
    4632 assert(intarray->firstidx <= intarray->minusedidx);
    4633 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
    4634
    4635 /* shift used part of array to the left */
    4636 shift = newfirstidx - intarray->firstidx;
    4637 assert(shift > 0);
    4638 for( i = intarray->minusedidx - intarray->firstidx; i <= intarray->maxusedidx - intarray->firstidx; ++i )
    4639 {
    4640 assert(0 <= i - shift && i - shift < intarray->valssize);
    4641 intarray->vals[i - shift] = intarray->vals[i];
    4642 }
    4643 /* clear the formerly used tail of the array */
    4644 for( i = 0; i < shift; ++i )
    4645 intarray->vals[intarray->maxusedidx - intarray->firstidx - i] = 0;
    4646 }
    4647 intarray->firstidx = newfirstidx;
    4648 }
    4649
    4650 assert(minidx >= intarray->firstidx);
    4651 assert(maxidx < intarray->firstidx + intarray->valssize);
    4652
    4653 return SCIP_OKAY;
    4654}
    4655
    4656/** clears a dynamic int array */
    4658 SCIP_INTARRAY* intarray /**< dynamic int array */
    4659 )
    4660{
    4661 assert(intarray != NULL);
    4662
    4663 SCIPdebugMessage("clearing intarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
    4664 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx);
    4665
    4666 if( intarray->minusedidx <= intarray->maxusedidx )
    4667 {
    4668 assert(intarray->firstidx <= intarray->minusedidx);
    4669 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
    4670 assert(intarray->firstidx != -1);
    4671 assert(intarray->valssize > 0);
    4672
    4673 /* clear the used part of array */
    4674 BMSclearMemoryArray(&intarray->vals[intarray->minusedidx - intarray->firstidx],
    4675 intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866*/
    4676
    4677 /* mark the array cleared */
    4678 intarray->minusedidx = INT_MAX;
    4679 intarray->maxusedidx = INT_MIN;
    4680 }
    4681 assert(intarray->minusedidx == INT_MAX);
    4682 assert(intarray->maxusedidx == INT_MIN);
    4683
    4684 return SCIP_OKAY;
    4685}
    4686
    4687/** gets value of entry in dynamic array */
    4689 SCIP_INTARRAY* intarray, /**< dynamic int array */
    4690 int idx /**< array index to get value for */
    4691 )
    4692{
    4693 assert(intarray != NULL);
    4694 assert(idx >= 0);
    4695
    4696 if( idx < intarray->minusedidx || idx > intarray->maxusedidx )
    4697 return 0;
    4698 else
    4699 {
    4700 assert(intarray->vals != NULL);
    4701 assert(idx - intarray->firstidx >= 0);
    4702 assert(idx - intarray->firstidx < intarray->valssize);
    4703
    4704 return intarray->vals[idx - intarray->firstidx];
    4705 }
    4706}
    4707
    4708/** sets value of entry in dynamic array */
    4710 SCIP_INTARRAY* intarray, /**< dynamic int array */
    4711 int arraygrowinit, /**< initial size of array */
    4712 SCIP_Real arraygrowfac, /**< growing factor of array */
    4713 int idx, /**< array index to set value for */
    4714 int val /**< value to set array index to */
    4715 )
    4716{
    4717 assert(intarray != NULL);
    4718 assert(idx >= 0);
    4719
    4720 SCIPdebugMessage("setting intarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %d\n",
    4721 (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, idx, val);
    4722
    4723 if( val != 0 )
    4724 {
    4725 /* extend array to be able to store the index */
    4726 SCIP_CALL( SCIPintarrayExtend(intarray, arraygrowinit, arraygrowfac, idx, idx) );
    4727 assert(idx >= intarray->firstidx);
    4728 assert(idx < intarray->firstidx + intarray->valssize);
    4729
    4730 /* set the array value of the index */
    4731 intarray->vals[idx - intarray->firstidx] = val;
    4732
    4733 /* update min/maxusedidx */
    4734 intarray->minusedidx = MIN(intarray->minusedidx, idx);
    4735 intarray->maxusedidx = MAX(intarray->maxusedidx, idx);
    4736 }
    4737 else if( idx >= intarray->firstidx && idx < intarray->firstidx + intarray->valssize )
    4738 {
    4739 /* set the array value of the index to zero */
    4740 intarray->vals[idx - intarray->firstidx] = 0;
    4741
    4742 /* check, if we can tighten the min/maxusedidx */
    4743 if( idx == intarray->minusedidx )
    4744 {
    4745 assert(intarray->maxusedidx >= 0);
    4746 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
    4747 do
    4748 {
    4749 intarray->minusedidx++;
    4750 }
    4751 while( intarray->minusedidx <= intarray->maxusedidx
    4752 && intarray->vals[intarray->minusedidx - intarray->firstidx] == 0 );
    4753 if( intarray->minusedidx > intarray->maxusedidx )
    4754 {
    4755 intarray->minusedidx = INT_MAX;
    4756 intarray->maxusedidx = INT_MIN;
    4757 }
    4758 }
    4759 else if( idx == intarray->maxusedidx )
    4760 {
    4761 assert(intarray->minusedidx >= 0);
    4762 assert(intarray->minusedidx < intarray->maxusedidx);
    4763 assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
    4764 do
    4765 {
    4766 intarray->maxusedidx--;
    4767 assert(intarray->minusedidx <= intarray->maxusedidx);
    4768 }
    4769 while( intarray->vals[intarray->maxusedidx - intarray->firstidx] == 0 );
    4770 }
    4771 }
    4772
    4773 return SCIP_OKAY;
    4774}
    4775
    4776/** increases value of entry in dynamic array */
    4778 SCIP_INTARRAY* intarray, /**< dynamic int array */
    4779 int arraygrowinit, /**< initial size of array */
    4780 SCIP_Real arraygrowfac, /**< growing factor of array */
    4781 int idx, /**< array index to increase value for */
    4782 int incval /**< value to increase array index */
    4783 )
    4784{
    4785 return SCIPintarraySetVal(intarray, arraygrowinit, arraygrowfac, idx, SCIPintarrayGetVal(intarray, idx) + incval);
    4786}
    4787
    4788/** returns the minimal index of all stored non-zero elements */
    4790 SCIP_INTARRAY* intarray /**< dynamic int array */
    4791 )
    4792{
    4793 assert(intarray != NULL);
    4794
    4795 return intarray->minusedidx;
    4796}
    4797
    4798/** returns the maximal index of all stored non-zero elements */
    4800 SCIP_INTARRAY* intarray /**< dynamic int array */
    4801 )
    4802{
    4803 assert(intarray != NULL);
    4804
    4805 return intarray->maxusedidx;
    4806}
    4807
    4808
    4809/** creates a dynamic array of bool values */
    4811 SCIP_BOOLARRAY** boolarray, /**< pointer to store the bool array */
    4812 BMS_BLKMEM* blkmem /**< block memory */
    4813 )
    4814{
    4815 assert(boolarray != NULL);
    4816 assert(blkmem != NULL);
    4817
    4818 SCIP_ALLOC( BMSallocBlockMemory(blkmem, boolarray) );
    4819 (*boolarray)->blkmem = blkmem;
    4820 (*boolarray)->vals = NULL;
    4821 (*boolarray)->valssize = 0;
    4822 (*boolarray)->firstidx = -1;
    4823 (*boolarray)->minusedidx = INT_MAX;
    4824 (*boolarray)->maxusedidx = INT_MIN;
    4825
    4826 return SCIP_OKAY;
    4827}
    4828
    4829/** creates a copy of a dynamic array of bool values */
    4831 SCIP_BOOLARRAY** boolarray, /**< pointer to store the copied bool array */
    4832 BMS_BLKMEM* blkmem, /**< block memory */
    4833 SCIP_BOOLARRAY* sourceboolarray /**< dynamic bool array to copy */
    4834 )
    4835{
    4836 assert(boolarray != NULL);
    4837 assert(sourceboolarray != NULL);
    4838
    4839 SCIP_CALL( SCIPboolarrayCreate(boolarray, blkmem) );
    4840 if( sourceboolarray->valssize > 0 )
    4841 {
    4842 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*boolarray)->vals, sourceboolarray->vals,
    4843 sourceboolarray->valssize) );
    4844 }
    4845 (*boolarray)->valssize = sourceboolarray->valssize;
    4846 (*boolarray)->firstidx = sourceboolarray->firstidx;
    4847 (*boolarray)->minusedidx = sourceboolarray->minusedidx;
    4848 (*boolarray)->maxusedidx = sourceboolarray->maxusedidx;
    4849
    4850 return SCIP_OKAY;
    4851}
    4852
    4853/** frees a dynamic array of bool values */
    4855 SCIP_BOOLARRAY** boolarray /**< pointer to the bool array */
    4856 )
    4857{
    4858 assert(boolarray != NULL);
    4859 assert(*boolarray != NULL);
    4860
    4861 BMSfreeBlockMemoryArrayNull((*boolarray)->blkmem, &(*boolarray)->vals, (*boolarray)->valssize);
    4862 BMSfreeBlockMemory((*boolarray)->blkmem, boolarray);
    4863
    4864 return SCIP_OKAY;
    4865}
    4866
    4867/** extends dynamic array to be able to store indices from minidx to maxidx */
    4869 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
    4870 int arraygrowinit, /**< initial size of array */
    4871 SCIP_Real arraygrowfac, /**< growing factor of array */
    4872 int minidx, /**< smallest index to allocate storage for */
    4873 int maxidx /**< largest index to allocate storage for */
    4874 )
    4875{
    4876 int nused;
    4877 int nfree;
    4878 int newfirstidx;
    4879 int i;
    4880
    4881 assert(boolarray != NULL);
    4882 assert(boolarray->minusedidx == INT_MAX || boolarray->firstidx >= 0);
    4883 assert(boolarray->maxusedidx == INT_MIN || boolarray->firstidx >= 0);
    4884 assert(boolarray->minusedidx == INT_MAX || boolarray->minusedidx >= boolarray->firstidx);
    4885 assert(boolarray->maxusedidx == INT_MIN || boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
    4886 assert(0 <= minidx);
    4887 assert(minidx <= maxidx);
    4888
    4889 minidx = MIN(minidx, boolarray->minusedidx);
    4890 maxidx = MAX(maxidx, boolarray->maxusedidx);
    4891 assert(0 <= minidx);
    4892 assert(minidx <= maxidx);
    4893
    4894 SCIPdebugMessage("extending boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
    4895 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, minidx, maxidx);
    4896
    4897 /* check, whether we have to allocate additional memory, or shift the array */
    4898 nused = maxidx - minidx + 1;
    4899 if( nused > boolarray->valssize )
    4900 {
    4901 SCIP_Bool* newvals;
    4902 int newvalssize;
    4903
    4904 /* allocate new memory storage */
    4905 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
    4906 SCIP_ALLOC( BMSallocBlockMemoryArray(boolarray->blkmem, &newvals, newvalssize) );
    4907 nfree = newvalssize - nused;
    4908 newfirstidx = minidx - nfree/2;
    4909 newfirstidx = MAX(newfirstidx, 0);
    4910 assert(newfirstidx <= minidx);
    4911 assert(maxidx < newfirstidx + newvalssize);
    4912
    4913 /* initialize memory array by copying old values and setting new values to zero */
    4914 if( boolarray->firstidx != -1 )
    4915 {
    4916 for( i = 0; i < boolarray->minusedidx - newfirstidx; ++i )
    4917 newvals[i] = FALSE;
    4918
    4919 /* check for possible overflow or negative value */
    4920 assert(boolarray->maxusedidx - boolarray->minusedidx + 1 > 0);
    4921
    4922 BMScopyMemoryArray(&newvals[boolarray->minusedidx - newfirstidx],
    4923 &boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
    4924 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866 !e776*/
    4925 for( i = boolarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
    4926 newvals[i] = FALSE;
    4927 }
    4928 else
    4929 {
    4930 for( i = 0; i < newvalssize; ++i )
    4931 newvals[i] = FALSE;
    4932 }
    4933
    4934 /* free old memory storage, and set the new array parameters */
    4935 BMSfreeBlockMemoryArrayNull(boolarray->blkmem, &boolarray->vals, boolarray->valssize);
    4936 boolarray->vals = newvals;
    4937 boolarray->valssize = newvalssize;
    4938 boolarray->firstidx = newfirstidx;
    4939 }
    4940 else if( boolarray->firstidx == -1 )
    4941 {
    4942 /* a sufficiently large memory storage exists, but it was cleared */
    4943 nfree = boolarray->valssize - nused;
    4944 assert(nfree >= 0);
    4945 boolarray->firstidx = minidx - nfree/2;
    4946 assert(boolarray->firstidx <= minidx);
    4947 assert(maxidx < boolarray->firstidx + boolarray->valssize);
    4948#ifndef NDEBUG
    4949 for( i = 0; i < boolarray->valssize; ++i )
    4950 assert(boolarray->vals[i] == FALSE);
    4951#endif
    4952 }
    4953 else if( minidx < boolarray->firstidx )
    4954 {
    4955 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
    4956 nfree = boolarray->valssize - nused;
    4957 assert(nfree >= 0);
    4958 newfirstidx = minidx - nfree/2;
    4959 newfirstidx = MAX(newfirstidx, 0);
    4960 assert(newfirstidx <= minidx);
    4961 assert(maxidx < newfirstidx + boolarray->valssize);
    4962
    4963 if( boolarray->minusedidx <= boolarray->maxusedidx )
    4964 {
    4965 int shift;
    4966
    4967 assert(boolarray->firstidx <= boolarray->minusedidx);
    4968 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
    4969
    4970 /* shift used part of array to the right */
    4971 shift = boolarray->firstidx - newfirstidx;
    4972 assert(shift > 0);
    4973 for( i = boolarray->maxusedidx - boolarray->firstidx; i >= boolarray->minusedidx - boolarray->firstidx; --i )
    4974 {
    4975 assert(0 <= i + shift && i + shift < boolarray->valssize);
    4976 boolarray->vals[i + shift] = boolarray->vals[i];
    4977 }
    4978 /* clear the formerly used head of the array */
    4979 for( i = 0; i < shift; ++i )
    4980 boolarray->vals[boolarray->minusedidx - boolarray->firstidx + i] = FALSE;
    4981 }
    4982 boolarray->firstidx = newfirstidx;
    4983 }
    4984 else if( maxidx >= boolarray->firstidx + boolarray->valssize )
    4985 {
    4986 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
    4987 nfree = boolarray->valssize - nused;
    4988 assert(nfree >= 0);
    4989 newfirstidx = minidx - nfree/2;
    4990 newfirstidx = MAX(newfirstidx, 0);
    4991 assert(newfirstidx <= minidx);
    4992 assert(maxidx < newfirstidx + boolarray->valssize);
    4993
    4994 if( boolarray->minusedidx <= boolarray->maxusedidx )
    4995 {
    4996 int shift;
    4997
    4998 assert(boolarray->firstidx <= boolarray->minusedidx);
    4999 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
    5000
    5001 /* shift used part of array to the left */
    5002 shift = newfirstidx - boolarray->firstidx;
    5003 assert(shift > 0);
    5004
    5005 assert(0 <= boolarray->minusedidx - boolarray->firstidx - shift);
    5006 assert(boolarray->maxusedidx - boolarray->firstidx - shift < boolarray->valssize);
    5007 BMSmoveMemoryArray(&(boolarray->vals[boolarray->minusedidx - boolarray->firstidx - shift]),
    5008 &(boolarray->vals[boolarray->minusedidx - boolarray->firstidx]),
    5009 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
    5010
    5011 /* clear the formerly used tail of the array */
    5012 for( i = 0; i < shift; ++i )
    5013 boolarray->vals[boolarray->maxusedidx - boolarray->firstidx - i] = FALSE;
    5014 }
    5015 boolarray->firstidx = newfirstidx;
    5016 }
    5017
    5018 assert(minidx >= boolarray->firstidx);
    5019 assert(maxidx < boolarray->firstidx + boolarray->valssize);
    5020
    5021 return SCIP_OKAY;
    5022}
    5023
    5024/** clears a dynamic bool array */
    5026 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
    5027 )
    5028{
    5029 assert(boolarray != NULL);
    5030
    5031 SCIPdebugMessage("clearing boolarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
    5032 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx);
    5033
    5034 if( boolarray->minusedidx <= boolarray->maxusedidx )
    5035 {
    5036 assert(boolarray->firstidx <= boolarray->minusedidx);
    5037 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
    5038 assert(boolarray->firstidx != -1);
    5039 assert(boolarray->valssize > 0);
    5040
    5041 /* clear the used part of array */
    5042 BMSclearMemoryArray(&boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
    5043 boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
    5044
    5045 /* mark the array cleared */
    5046 boolarray->minusedidx = INT_MAX;
    5047 boolarray->maxusedidx = INT_MIN;
    5048 }
    5049 assert(boolarray->minusedidx == INT_MAX);
    5050 assert(boolarray->maxusedidx == INT_MIN);
    5051
    5052 return SCIP_OKAY;
    5053}
    5054
    5055/** gets value of entry in dynamic array */
    5057 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
    5058 int idx /**< array index to get value for */
    5059 )
    5060{
    5061 assert(boolarray != NULL);
    5062 assert(idx >= 0);
    5063
    5064 if( idx < boolarray->minusedidx || idx > boolarray->maxusedidx )
    5065 return FALSE;
    5066 else
    5067 {
    5068 assert(boolarray->vals != NULL);
    5069 assert(idx - boolarray->firstidx >= 0);
    5070 assert(idx - boolarray->firstidx < boolarray->valssize);
    5071
    5072 return boolarray->vals[idx - boolarray->firstidx];
    5073 }
    5074}
    5075
    5076/** sets value of entry in dynamic array */
    5078 SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
    5079 int arraygrowinit, /**< initial size of array */
    5080 SCIP_Real arraygrowfac, /**< growing factor of array */
    5081 int idx, /**< array index to set value for */
    5082 SCIP_Bool val /**< value to set array index to */
    5083 )
    5084{
    5085 assert(boolarray != NULL);
    5086 assert(idx >= 0);
    5087
    5088 SCIPdebugMessage("setting boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %u\n",
    5089 (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, idx, val);
    5090
    5091 if( val != FALSE )
    5092 {
    5093 /* extend array to be able to store the index */
    5094 SCIP_CALL( SCIPboolarrayExtend(boolarray, arraygrowinit, arraygrowfac, idx, idx) );
    5095 assert(idx >= boolarray->firstidx);
    5096 assert(idx < boolarray->firstidx + boolarray->valssize);
    5097
    5098 /* set the array value of the index */
    5099 boolarray->vals[idx - boolarray->firstidx] = val;
    5100
    5101 /* update min/maxusedidx */
    5102 boolarray->minusedidx = MIN(boolarray->minusedidx, idx);
    5103 boolarray->maxusedidx = MAX(boolarray->maxusedidx, idx);
    5104 }
    5105 else if( idx >= boolarray->firstidx && idx < boolarray->firstidx + boolarray->valssize )
    5106 {
    5107 /* set the array value of the index to zero */
    5108 boolarray->vals[idx - boolarray->firstidx] = FALSE;
    5109
    5110 /* check, if we can tighten the min/maxusedidx */
    5111 if( idx == boolarray->minusedidx )
    5112 {
    5113 assert(boolarray->maxusedidx >= 0);
    5114 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
    5115 do
    5116 {
    5117 boolarray->minusedidx++;
    5118 }
    5119 while( boolarray->minusedidx <= boolarray->maxusedidx
    5120 && boolarray->vals[boolarray->minusedidx - boolarray->firstidx] == FALSE );
    5121 if( boolarray->minusedidx > boolarray->maxusedidx )
    5122 {
    5123 boolarray->minusedidx = INT_MAX;
    5124 boolarray->maxusedidx = INT_MIN;
    5125 }
    5126 }
    5127 else if( idx == boolarray->maxusedidx )
    5128 {
    5129 assert(boolarray->minusedidx >= 0);
    5130 assert(boolarray->minusedidx < boolarray->maxusedidx);
    5131 assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
    5132 do
    5133 {
    5134 boolarray->maxusedidx--;
    5135 assert(boolarray->minusedidx <= boolarray->maxusedidx);
    5136 }
    5137 while( boolarray->vals[boolarray->maxusedidx - boolarray->firstidx] == FALSE );
    5138 }
    5139 }
    5140
    5141 return SCIP_OKAY;
    5142}
    5143
    5144/** returns the minimal index of all stored non-zero elements */
    5146 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
    5147 )
    5148{
    5149 assert(boolarray != NULL);
    5150
    5151 return boolarray->minusedidx;
    5152}
    5153
    5154/** returns the maximal index of all stored non-zero elements */
    5156 SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
    5157 )
    5158{
    5159 assert(boolarray != NULL);
    5160
    5161 return boolarray->maxusedidx;
    5162}
    5163
    5164
    5165/** creates a dynamic array of pointer values */
    5167 SCIP_PTRARRAY** ptrarray, /**< pointer to store the ptr array */
    5168 BMS_BLKMEM* blkmem /**< block memory */
    5169 )
    5170{
    5171 assert(ptrarray != NULL);
    5172 assert(blkmem != NULL);
    5173
    5174 SCIP_ALLOC( BMSallocBlockMemory(blkmem, ptrarray) );
    5175 (*ptrarray)->blkmem = blkmem;
    5176 (*ptrarray)->vals = NULL;
    5177 (*ptrarray)->valssize = 0;
    5178 (*ptrarray)->firstidx = -1;
    5179 (*ptrarray)->minusedidx = INT_MAX;
    5180 (*ptrarray)->maxusedidx = INT_MIN;
    5181
    5182 return SCIP_OKAY;
    5183}
    5184
    5185/** creates a copy of a dynamic array of pointer values */
    5187 SCIP_PTRARRAY** ptrarray, /**< pointer to store the copied ptr array */
    5188 BMS_BLKMEM* blkmem, /**< block memory */
    5189 SCIP_PTRARRAY* sourceptrarray /**< dynamic ptr array to copy */
    5190 )
    5191{
    5192 assert(ptrarray != NULL);
    5193 assert(sourceptrarray != NULL);
    5194
    5195 SCIP_CALL( SCIPptrarrayCreate(ptrarray, blkmem) );
    5196 if( sourceptrarray->valssize > 0 )
    5197 {
    5198 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*ptrarray)->vals, sourceptrarray->vals, sourceptrarray->valssize) );
    5199 }
    5200 (*ptrarray)->valssize = sourceptrarray->valssize;
    5201 (*ptrarray)->firstidx = sourceptrarray->firstidx;
    5202 (*ptrarray)->minusedidx = sourceptrarray->minusedidx;
    5203 (*ptrarray)->maxusedidx = sourceptrarray->maxusedidx;
    5204
    5205 return SCIP_OKAY;
    5206}
    5207
    5208/** frees a dynamic array of pointer values */
    5210 SCIP_PTRARRAY** ptrarray /**< pointer to the ptr array */
    5211 )
    5212{
    5213 assert(ptrarray != NULL);
    5214 assert(*ptrarray != NULL);
    5215
    5216 BMSfreeBlockMemoryArrayNull((*ptrarray)->blkmem, &(*ptrarray)->vals, (*ptrarray)->valssize);
    5217 BMSfreeBlockMemory((*ptrarray)->blkmem, ptrarray);
    5218
    5219 return SCIP_OKAY;
    5220}
    5221
    5222/** extends dynamic array to be able to store indices from minidx to maxidx */
    5224 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
    5225 int arraygrowinit, /**< initial size of array */
    5226 SCIP_Real arraygrowfac, /**< growing factor of array */
    5227 int minidx, /**< smallest index to allocate storage for */
    5228 int maxidx /**< largest index to allocate storage for */
    5229 )
    5230{
    5231 int nused;
    5232 int nfree;
    5233 int newfirstidx;
    5234 int i;
    5235
    5236 assert(ptrarray != NULL);
    5237 assert(ptrarray->minusedidx == INT_MAX || ptrarray->firstidx >= 0);
    5238 assert(ptrarray->maxusedidx == INT_MIN || ptrarray->firstidx >= 0);
    5239 assert(ptrarray->minusedidx == INT_MAX || ptrarray->minusedidx >= ptrarray->firstidx);
    5240 assert(ptrarray->maxusedidx == INT_MIN || ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
    5241 assert(0 <= minidx);
    5242 assert(minidx <= maxidx);
    5243
    5244 minidx = MIN(minidx, ptrarray->minusedidx);
    5245 maxidx = MAX(maxidx, ptrarray->maxusedidx);
    5246 assert(0 <= minidx);
    5247 assert(minidx <= maxidx);
    5248
    5249 SCIPdebugMessage("extending ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
    5250 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, minidx, maxidx);
    5251
    5252 /* check, whether we have to allocate additional memory, or shift the array */
    5253 nused = maxidx - minidx + 1;
    5254 if( nused > ptrarray->valssize )
    5255 {
    5256 void** newvals;
    5257 int newvalssize;
    5258
    5259 /* allocate new memory storage */
    5260 newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
    5261 SCIP_ALLOC( BMSallocBlockMemoryArray(ptrarray->blkmem, &newvals, newvalssize) );
    5262 nfree = newvalssize - nused;
    5263 newfirstidx = minidx - nfree/2;
    5264 newfirstidx = MAX(newfirstidx, 0);
    5265 assert(newfirstidx <= minidx);
    5266 assert(maxidx < newfirstidx + newvalssize);
    5267
    5268 /* initialize memory array by copying old values and setting new values to zero */
    5269 if( ptrarray->firstidx != -1 )
    5270 {
    5271 for( i = 0; i < ptrarray->minusedidx - newfirstidx; ++i )
    5272 newvals[i] = NULL;
    5273
    5274 /* check for possible overflow or negative value */
    5275 assert(ptrarray->maxusedidx - ptrarray->minusedidx + 1 > 0);
    5276
    5277 BMScopyMemoryArray(&newvals[ptrarray->minusedidx - newfirstidx],
    5278 &(ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx]),
    5279 ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866 !e776*/
    5280 for( i = ptrarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
    5281 newvals[i] = NULL;
    5282 }
    5283 else
    5284 {
    5285 for( i = 0; i < newvalssize; ++i )
    5286 newvals[i] = NULL;
    5287 }
    5288
    5289 /* free old memory storage, and set the new array parameters */
    5290 BMSfreeBlockMemoryArrayNull(ptrarray->blkmem, &ptrarray->vals, ptrarray->valssize);
    5291 ptrarray->vals = newvals;
    5292 ptrarray->valssize = newvalssize;
    5293 ptrarray->firstidx = newfirstidx;
    5294 }
    5295 else if( ptrarray->firstidx == -1 )
    5296 {
    5297 /* a sufficiently large memory storage exists, but it was cleared */
    5298 nfree = ptrarray->valssize - nused;
    5299 assert(nfree >= 0);
    5300 ptrarray->firstidx = minidx - nfree/2;
    5301 assert(ptrarray->firstidx <= minidx);
    5302 assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
    5303#ifndef NDEBUG
    5304 for( i = 0; i < ptrarray->valssize; ++i )
    5305 assert(ptrarray->vals[i] == NULL);
    5306#endif
    5307 }
    5308 else if( minidx < ptrarray->firstidx )
    5309 {
    5310 /* a sufficiently large memory storage exists, but it has to be shifted to the right */
    5311 nfree = ptrarray->valssize - nused;
    5312 assert(nfree >= 0);
    5313 newfirstidx = minidx - nfree/2;
    5314 newfirstidx = MAX(newfirstidx, 0);
    5315 assert(newfirstidx <= minidx);
    5316 assert(maxidx < newfirstidx + ptrarray->valssize);
    5317
    5318 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
    5319 {
    5320 int shift;
    5321
    5322 assert(ptrarray->firstidx <= ptrarray->minusedidx);
    5323 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
    5324
    5325 /* shift used part of array to the right */
    5326 shift = ptrarray->firstidx - newfirstidx;
    5327 assert(shift > 0);
    5328 for( i = ptrarray->maxusedidx - ptrarray->firstidx; i >= ptrarray->minusedidx - ptrarray->firstidx; --i )
    5329 {
    5330 assert(0 <= i + shift && i + shift < ptrarray->valssize);
    5331 ptrarray->vals[i + shift] = ptrarray->vals[i];
    5332 }
    5333 /* clear the formerly used head of the array */
    5334 for( i = 0; i < shift; ++i )
    5335 ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx + i] = NULL;
    5336 }
    5337 ptrarray->firstidx = newfirstidx;
    5338 }
    5339 else if( maxidx >= ptrarray->firstidx + ptrarray->valssize )
    5340 {
    5341 /* a sufficiently large memory storage exists, but it has to be shifted to the left */
    5342 nfree = ptrarray->valssize - nused;
    5343 assert(nfree >= 0);
    5344 newfirstidx = minidx - nfree/2;
    5345 newfirstidx = MAX(newfirstidx, 0);
    5346 assert(newfirstidx <= minidx);
    5347 assert(maxidx < newfirstidx + ptrarray->valssize);
    5348
    5349 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
    5350 {
    5351 int shift;
    5352
    5353 assert(ptrarray->firstidx <= ptrarray->minusedidx);
    5354 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
    5355
    5356 /* shift used part of array to the left */
    5357 shift = newfirstidx - ptrarray->firstidx;
    5358 assert(shift > 0);
    5359 for( i = ptrarray->minusedidx - ptrarray->firstidx; i <= ptrarray->maxusedidx - ptrarray->firstidx; ++i )
    5360 {
    5361 assert(0 <= i - shift && i - shift < ptrarray->valssize);
    5362 ptrarray->vals[i - shift] = ptrarray->vals[i];
    5363 }
    5364 /* clear the formerly used tail of the array */
    5365 for( i = 0; i < shift; ++i )
    5366 ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx - i] = NULL;
    5367 }
    5368 ptrarray->firstidx = newfirstidx;
    5369 }
    5370
    5371 assert(minidx >= ptrarray->firstidx);
    5372 assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
    5373
    5374 return SCIP_OKAY;
    5375}
    5376
    5377/** clears a dynamic pointer array */
    5379 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
    5380 )
    5381{
    5382 assert(ptrarray != NULL);
    5383
    5384 SCIPdebugMessage("clearing ptrarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
    5385 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx);
    5386
    5387 if( ptrarray->minusedidx <= ptrarray->maxusedidx )
    5388 {
    5389 assert(ptrarray->firstidx <= ptrarray->minusedidx);
    5390 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
    5391 assert(ptrarray->firstidx != -1);
    5392 assert(ptrarray->valssize > 0);
    5393
    5394 /* clear the used part of array */
    5395 BMSclearMemoryArray(&ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx],
    5396 ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866*/
    5397
    5398 /* mark the array cleared */
    5399 ptrarray->minusedidx = INT_MAX;
    5400 ptrarray->maxusedidx = INT_MIN;
    5401 }
    5402 assert(ptrarray->minusedidx == INT_MAX);
    5403 assert(ptrarray->maxusedidx == INT_MIN);
    5404
    5405 return SCIP_OKAY;
    5406}
    5407
    5408/** gets value of entry in dynamic array */
    5410 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
    5411 int idx /**< array index to get value for */
    5412 )
    5413{
    5414 assert(ptrarray != NULL);
    5415 assert(idx >= 0);
    5416
    5417 if( idx < ptrarray->minusedidx || idx > ptrarray->maxusedidx )
    5418 return NULL;
    5419 else
    5420 {
    5421 assert(ptrarray->vals != NULL);
    5422 assert(idx - ptrarray->firstidx >= 0);
    5423 assert(idx - ptrarray->firstidx < ptrarray->valssize);
    5424
    5425 return ptrarray->vals[idx - ptrarray->firstidx];
    5426 }
    5427}
    5428
    5429/** sets value of entry in dynamic array */
    5431 SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
    5432 int arraygrowinit, /**< initial size of array */
    5433 SCIP_Real arraygrowfac, /**< growing factor of array */
    5434 int idx, /**< array index to set value for */
    5435 void* val /**< value to set array index to */
    5436 )
    5437{
    5438 assert(ptrarray != NULL);
    5439 assert(idx >= 0);
    5440
    5441 SCIPdebugMessage("setting ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %p\n",
    5442 (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, idx, val);
    5443
    5444 if( val != NULL )
    5445 {
    5446 /* extend array to be able to store the index */
    5447 SCIP_CALL( SCIPptrarrayExtend(ptrarray, arraygrowinit, arraygrowfac, idx, idx) );
    5448 assert(idx >= ptrarray->firstidx);
    5449 assert(idx < ptrarray->firstidx + ptrarray->valssize);
    5450
    5451 /* set the array value of the index */
    5452 ptrarray->vals[idx - ptrarray->firstidx] = val;
    5453
    5454 /* update min/maxusedidx */
    5455 ptrarray->minusedidx = MIN(ptrarray->minusedidx, idx);
    5456 ptrarray->maxusedidx = MAX(ptrarray->maxusedidx, idx);
    5457 }
    5458 else if( idx >= ptrarray->firstidx && idx < ptrarray->firstidx + ptrarray->valssize )
    5459 {
    5460 /* set the array value of the index to zero */
    5461 ptrarray->vals[idx - ptrarray->firstidx] = NULL;
    5462
    5463 /* check, if we can tighten the min/maxusedidx */
    5464 if( idx == ptrarray->minusedidx )
    5465 {
    5466 assert(ptrarray->maxusedidx >= 0);
    5467 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
    5468 do
    5469 {
    5470 ptrarray->minusedidx++;
    5471 }
    5472 while( ptrarray->minusedidx <= ptrarray->maxusedidx
    5473 && ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx] == NULL );
    5474 if( ptrarray->minusedidx > ptrarray->maxusedidx )
    5475 {
    5476 ptrarray->minusedidx = INT_MAX;
    5477 ptrarray->maxusedidx = INT_MIN;
    5478 }
    5479 }
    5480 else if( idx == ptrarray->maxusedidx )
    5481 {
    5482 assert(ptrarray->minusedidx >= 0);
    5483 assert(ptrarray->minusedidx < ptrarray->maxusedidx);
    5484 assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
    5485 do
    5486 {
    5487 ptrarray->maxusedidx--;
    5488 assert(ptrarray->minusedidx <= ptrarray->maxusedidx);
    5489 }
    5490 while( ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx] == NULL );
    5491 }
    5492 }
    5493
    5494 return SCIP_OKAY;
    5495}
    5496
    5497/** returns the minimal index of all stored non-zero elements */
    5499 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
    5500 )
    5501{
    5502 assert(ptrarray != NULL);
    5503
    5504 return ptrarray->minusedidx;
    5505}
    5506
    5507/** returns the maximal index of all stored non-zero elements */
    5509 SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
    5510 )
    5511{
    5512 assert(ptrarray != NULL);
    5513
    5514 return ptrarray->maxusedidx;
    5515}
    5516
    5517
    5518/*
    5519 * Sorting algorithms
    5520 */
    5521
    5522/** default comparer for integers */
    5524{
    5525 int value1;
    5526 int value2;
    5527
    5528 value1 = (int)(size_t)elem1;
    5529 value2 = (int)(size_t)elem2;
    5530
    5531 if( value1 < value2 )
    5532 return -1;
    5533
    5534 if( value2 < value1 )
    5535 return 1;
    5536
    5537 return 0;
    5538}
    5539
    5540/** implements argsort
    5541 *
    5542 * The data pointer is a lookup array of integers.
    5543 */
    5544SCIP_DECL_SORTINDCOMP(SCIPsortArgsortInt)
    5545{
    5546 int* args;
    5547 args = (int*) dataptr;
    5548
    5549 if( args[ind1] < args[ind2] )
    5550 return -1;
    5551
    5552 if( args[ind1] > args[ind2] )
    5553 return 1;
    5554
    5555 return 0;
    5556}
    5557
    5558
    5559/** implements argsort
    5560 *
    5561 * The data pointer is a lookup array, which are pointer arrays.
    5562 */
    5563SCIP_DECL_SORTINDCOMP(SCIPsortArgsortPtr)
    5564{
    5565 void** args;
    5566 args = (void*) dataptr;
    5567
    5568 if( args[ind1] < args[ind2] )
    5569 return -1;
    5570
    5571 if( args[ind1] > args[ind2] )
    5572 return 1;
    5573
    5574 return 0;
    5575}
    5576
    5577
    5578/* first all upwards-sorting methods */
    5579
    5580/** sort an indexed element set in non-decreasing order, resulting in a permutation index array */
    5582 int* perm, /**< pointer to store the resulting permutation */
    5583 SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
    5584 void* dataptr, /**< pointer to data field that is given to the external compare method */
    5585 int len /**< number of elements to be sorted (valid index range) */
    5586 )
    5587{
    5588 int pos;
    5589
    5590 assert(indcomp != NULL);
    5591 assert(len == 0 || perm != NULL);
    5592
    5593 /* create identity permutation */
    5594 for( pos = 0; pos < len; ++pos )
    5595 perm[pos] = pos;
    5596
    5597 SCIPsortInd(perm, indcomp, dataptr, len);
    5598}
    5599
    5600/* SCIPsortInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5601#define SORTTPL_NAMEEXT Ind
    5602#define SORTTPL_KEYTYPE int
    5603#define SORTTPL_INDCOMP
    5604#include "scip/sorttpl.c" /*lint !e451*/
    5605
    5606
    5607/* SCIPsortPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5608#define SORTTPL_NAMEEXT Ptr
    5609#define SORTTPL_KEYTYPE void*
    5610#define SORTTPL_PTRCOMP
    5611#include "scip/sorttpl.c" /*lint !e451*/
    5612
    5613
    5614/* SCIPsortPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5615#define SORTTPL_NAMEEXT PtrPtr
    5616#define SORTTPL_KEYTYPE void*
    5617#define SORTTPL_FIELD1TYPE void*
    5618#define SORTTPL_PTRCOMP
    5619#include "scip/sorttpl.c" /*lint !e451*/
    5620
    5621
    5622/* SCIPsortPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5623#define SORTTPL_NAMEEXT PtrReal
    5624#define SORTTPL_KEYTYPE void*
    5625#define SORTTPL_FIELD1TYPE SCIP_Real
    5626#define SORTTPL_PTRCOMP
    5627#include "scip/sorttpl.c" /*lint !e451*/
    5628
    5629
    5630/* SCIPsortPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5631#define SORTTPL_NAMEEXT PtrInt
    5632#define SORTTPL_KEYTYPE void*
    5633#define SORTTPL_FIELD1TYPE int
    5634#define SORTTPL_PTRCOMP
    5635#include "scip/sorttpl.c" /*lint !e451*/
    5636
    5637
    5638/* SCIPsortPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5639#define SORTTPL_NAMEEXT PtrBool
    5640#define SORTTPL_KEYTYPE void*
    5641#define SORTTPL_FIELD1TYPE SCIP_Bool
    5642#define SORTTPL_PTRCOMP
    5643#include "scip/sorttpl.c" /*lint !e451*/
    5644
    5645
    5646/* SCIPsortPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5647#define SORTTPL_NAMEEXT PtrIntInt
    5648#define SORTTPL_KEYTYPE void*
    5649#define SORTTPL_FIELD1TYPE int
    5650#define SORTTPL_FIELD2TYPE int
    5651#define SORTTPL_PTRCOMP
    5652#include "scip/sorttpl.c" /*lint !e451*/
    5653
    5654
    5655/* SCIPsortPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5656#define SORTTPL_NAMEEXT PtrRealInt
    5657#define SORTTPL_KEYTYPE void*
    5658#define SORTTPL_FIELD1TYPE SCIP_Real
    5659#define SORTTPL_FIELD2TYPE int
    5660#define SORTTPL_PTRCOMP
    5661#include "scip/sorttpl.c" /*lint !e451*/
    5662
    5663/* SCIPsortPtrRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5664#define SORTTPL_NAMEEXT PtrRealRealInt
    5665#define SORTTPL_KEYTYPE void*
    5666#define SORTTPL_FIELD1TYPE SCIP_Real
    5667#define SORTTPL_FIELD2TYPE SCIP_Real
    5668#define SORTTPL_FIELD3TYPE int
    5669#define SORTTPL_PTRCOMP
    5670#include "scip/sorttpl.c" /*lint !e451*/
    5671
    5672/* SCIPsortPtrRealRealBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5673#define SORTTPL_NAMEEXT PtrRealRealBoolBool
    5674#define SORTTPL_KEYTYPE void*
    5675#define SORTTPL_FIELD1TYPE SCIP_Real
    5676#define SORTTPL_FIELD2TYPE SCIP_Real
    5677#define SORTTPL_FIELD3TYPE SCIP_Bool
    5678#define SORTTPL_FIELD4TYPE SCIP_Bool
    5679#define SORTTPL_PTRCOMP
    5680#include "scip/sorttpl.c" /*lint !e451*/
    5681
    5682/* SCIPsortPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5683#define SORTTPL_NAMEEXT PtrRealRealIntBool
    5684#define SORTTPL_KEYTYPE void*
    5685#define SORTTPL_FIELD1TYPE SCIP_Real
    5686#define SORTTPL_FIELD2TYPE SCIP_Real
    5687#define SORTTPL_FIELD3TYPE int
    5688#define SORTTPL_FIELD4TYPE SCIP_Bool
    5689#define SORTTPL_PTRCOMP
    5690#include "scip/sorttpl.c" /*lint !e451*/
    5691
    5692/* SCIPsortPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5693#define SORTTPL_NAMEEXT PtrRealBool
    5694#define SORTTPL_KEYTYPE void*
    5695#define SORTTPL_FIELD1TYPE SCIP_Real
    5696#define SORTTPL_FIELD2TYPE SCIP_Bool
    5697#define SORTTPL_PTRCOMP
    5698#include "scip/sorttpl.c" /*lint !e451*/
    5699
    5700
    5701/* SCIPsortPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5702#define SORTTPL_NAMEEXT PtrPtrInt
    5703#define SORTTPL_KEYTYPE void*
    5704#define SORTTPL_FIELD1TYPE void*
    5705#define SORTTPL_FIELD2TYPE int
    5706#define SORTTPL_PTRCOMP
    5707#include "scip/sorttpl.c" /*lint !e451*/
    5708
    5709
    5710/* SCIPsortPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5711#define SORTTPL_NAMEEXT PtrPtrReal
    5712#define SORTTPL_KEYTYPE void*
    5713#define SORTTPL_FIELD1TYPE void*
    5714#define SORTTPL_FIELD2TYPE SCIP_Real
    5715#define SORTTPL_PTRCOMP
    5716#include "scip/sorttpl.c" /*lint !e451*/
    5717
    5718
    5719/* SCIPsortPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5720#define SORTTPL_NAMEEXT PtrRealIntInt
    5721#define SORTTPL_KEYTYPE void*
    5722#define SORTTPL_FIELD1TYPE SCIP_Real
    5723#define SORTTPL_FIELD2TYPE int
    5724#define SORTTPL_FIELD3TYPE int
    5725#define SORTTPL_PTRCOMP
    5726#include "scip/sorttpl.c" /*lint !e451*/
    5727
    5728
    5729/* SCIPsortPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5730#define SORTTPL_NAMEEXT PtrPtrIntInt
    5731#define SORTTPL_KEYTYPE void*
    5732#define SORTTPL_FIELD1TYPE void*
    5733#define SORTTPL_FIELD2TYPE int
    5734#define SORTTPL_FIELD3TYPE int
    5735#define SORTTPL_PTRCOMP
    5736#include "scip/sorttpl.c" /*lint !e451*/
    5737
    5738
    5739/* SCIPsortPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5740#define SORTTPL_NAMEEXT PtrPtrRealInt
    5741#define SORTTPL_KEYTYPE void*
    5742#define SORTTPL_FIELD1TYPE void*
    5743#define SORTTPL_FIELD2TYPE SCIP_Real
    5744#define SORTTPL_FIELD3TYPE int
    5745#define SORTTPL_PTRCOMP
    5746#include "scip/sorttpl.c" /*lint !e451*/
    5747
    5748
    5749/* SCIPsortPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5750#define SORTTPL_NAMEEXT PtrPtrRealBool
    5751#define SORTTPL_KEYTYPE void*
    5752#define SORTTPL_FIELD1TYPE void*
    5753#define SORTTPL_FIELD2TYPE SCIP_Real
    5754#define SORTTPL_FIELD3TYPE SCIP_Bool
    5755#define SORTTPL_PTRCOMP
    5756#include "scip/sorttpl.c" /*lint !e451*/
    5757
    5758
    5759/* SCIPsortPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5760#define SORTTPL_NAMEEXT PtrPtrLongInt
    5761#define SORTTPL_KEYTYPE void*
    5762#define SORTTPL_FIELD1TYPE void*
    5763#define SORTTPL_FIELD2TYPE SCIP_Longint
    5764#define SORTTPL_FIELD3TYPE int
    5765#define SORTTPL_PTRCOMP
    5766#include "scip/sorttpl.c" /*lint !e451*/
    5767
    5768
    5769/* SCIPsortPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5770#define SORTTPL_NAMEEXT PtrPtrLongIntInt
    5771#define SORTTPL_KEYTYPE void*
    5772#define SORTTPL_FIELD1TYPE void*
    5773#define SORTTPL_FIELD2TYPE SCIP_Longint
    5774#define SORTTPL_FIELD3TYPE int
    5775#define SORTTPL_FIELD4TYPE int
    5776#define SORTTPL_PTRCOMP
    5777#include "scip/sorttpl.c" /*lint !e451*/
    5778
    5779
    5780/* SCIPsortReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5781#define SORTTPL_NAMEEXT Real
    5782#define SORTTPL_KEYTYPE SCIP_Real
    5783#include "scip/sorttpl.c" /*lint !e451*/
    5784
    5785
    5786/* SCIPsortRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5787#define SORTTPL_NAMEEXT RealBoolPtr
    5788#define SORTTPL_KEYTYPE SCIP_Real
    5789#define SORTTPL_FIELD1TYPE SCIP_Bool
    5790#define SORTTPL_FIELD2TYPE void*
    5791#include "scip/sorttpl.c" /*lint !e451*/
    5792
    5793
    5794/* SCIPsortRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5795#define SORTTPL_NAMEEXT RealPtr
    5796#define SORTTPL_KEYTYPE SCIP_Real
    5797#define SORTTPL_FIELD1TYPE void*
    5798#include "scip/sorttpl.c" /*lint !e451*/
    5799
    5800
    5801/* SCIPsortRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5802#define SORTTPL_NAMEEXT RealInt
    5803#define SORTTPL_KEYTYPE SCIP_Real
    5804#define SORTTPL_FIELD1TYPE int
    5805#include "scip/sorttpl.c" /*lint !e451*/
    5806
    5807
    5808/* SCIPsortRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5809#define SORTTPL_NAMEEXT RealIntInt
    5810#define SORTTPL_KEYTYPE SCIP_Real
    5811#define SORTTPL_FIELD1TYPE int
    5812#define SORTTPL_FIELD2TYPE int
    5813#include "scip/sorttpl.c" /*lint !e451*/
    5814
    5815
    5816/* SCIPsortRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5817#define SORTTPL_NAMEEXT RealIntLong
    5818#define SORTTPL_KEYTYPE SCIP_Real
    5819#define SORTTPL_FIELD1TYPE int
    5820#define SORTTPL_FIELD2TYPE SCIP_Longint
    5821#include "scip/sorttpl.c" /*lint !e451*/
    5822
    5823
    5824/* SCIPsortRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5825#define SORTTPL_NAMEEXT RealIntPtr
    5826#define SORTTPL_KEYTYPE SCIP_Real
    5827#define SORTTPL_FIELD1TYPE int
    5828#define SORTTPL_FIELD2TYPE void*
    5829#include "scip/sorttpl.c" /*lint !e451*/
    5830
    5831
    5832/* SCIPsortRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5833#define SORTTPL_NAMEEXT RealPtrPtr
    5834#define SORTTPL_KEYTYPE SCIP_Real
    5835#define SORTTPL_FIELD1TYPE void*
    5836#define SORTTPL_FIELD2TYPE void*
    5837#include "scip/sorttpl.c" /*lint !e451*/
    5838
    5839
    5840/* SCIPsortRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5841#define SORTTPL_NAMEEXT RealRealPtr
    5842#define SORTTPL_KEYTYPE SCIP_Real
    5843#define SORTTPL_FIELD1TYPE SCIP_Real
    5844#define SORTTPL_FIELD2TYPE void*
    5845#include "scip/sorttpl.c" /*lint !e451*/
    5846
    5847
    5848/* SCIPsortRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5849#define SORTTPL_NAMEEXT RealLongRealInt
    5850#define SORTTPL_KEYTYPE SCIP_Real
    5851#define SORTTPL_FIELD1TYPE SCIP_Longint
    5852#define SORTTPL_FIELD2TYPE SCIP_Real
    5853#define SORTTPL_FIELD3TYPE int
    5854#include "scip/sorttpl.c" /*lint !e451*/
    5855
    5856/* SCIPsortRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5857#define SORTTPL_NAMEEXT RealRealIntInt
    5858#define SORTTPL_KEYTYPE SCIP_Real
    5859#define SORTTPL_FIELD1TYPE SCIP_Real
    5860#define SORTTPL_FIELD2TYPE int
    5861#define SORTTPL_FIELD3TYPE int
    5862#include "scip/sorttpl.c" /*lint !e451*/
    5863
    5864
    5865/* SCIPsortRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5866#define SORTTPL_NAMEEXT RealRealRealInt
    5867#define SORTTPL_KEYTYPE SCIP_Real
    5868#define SORTTPL_FIELD1TYPE SCIP_Real
    5869#define SORTTPL_FIELD2TYPE SCIP_Real
    5870#define SORTTPL_FIELD3TYPE int
    5871#include "scip/sorttpl.c" /*lint !e451*/
    5872
    5873
    5874/* SCIPsortRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5875#define SORTTPL_NAMEEXT RealRealRealPtr
    5876#define SORTTPL_KEYTYPE SCIP_Real
    5877#define SORTTPL_FIELD1TYPE SCIP_Real
    5878#define SORTTPL_FIELD2TYPE SCIP_Real
    5879#define SORTTPL_FIELD3TYPE void*
    5880#include "scip/sorttpl.c" /*lint !e451*/
    5881
    5882
    5883/* SCIPsortRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5884#define SORTTPL_NAMEEXT RealPtrPtrInt
    5885#define SORTTPL_KEYTYPE SCIP_Real
    5886#define SORTTPL_FIELD1TYPE void*
    5887#define SORTTPL_FIELD2TYPE void*
    5888#define SORTTPL_FIELD3TYPE int
    5889#include "scip/sorttpl.c" /*lint !e451*/
    5890
    5891
    5892/* SCIPsortRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5893#define SORTTPL_NAMEEXT RealPtrPtrIntInt
    5894#define SORTTPL_KEYTYPE SCIP_Real
    5895#define SORTTPL_FIELD1TYPE void*
    5896#define SORTTPL_FIELD2TYPE void*
    5897#define SORTTPL_FIELD3TYPE int
    5898#define SORTTPL_FIELD4TYPE int
    5899#include "scip/sorttpl.c" /*lint !e451*/
    5900
    5901
    5902/* SCIPsortRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5903#define SORTTPL_NAMEEXT RealRealRealBoolPtr
    5904#define SORTTPL_KEYTYPE SCIP_Real
    5905#define SORTTPL_FIELD1TYPE SCIP_Real
    5906#define SORTTPL_FIELD2TYPE SCIP_Real
    5907#define SORTTPL_FIELD3TYPE SCIP_Bool
    5908#define SORTTPL_FIELD4TYPE void*
    5909#include "scip/sorttpl.c" /*lint !e451*/
    5910
    5911
    5912/* SCIPsortRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5913#define SORTTPL_NAMEEXT RealRealRealBoolBoolPtr
    5914#define SORTTPL_KEYTYPE SCIP_Real
    5915#define SORTTPL_FIELD1TYPE SCIP_Real
    5916#define SORTTPL_FIELD2TYPE SCIP_Real
    5917#define SORTTPL_FIELD3TYPE SCIP_Bool
    5918#define SORTTPL_FIELD4TYPE SCIP_Bool
    5919#define SORTTPL_FIELD5TYPE void*
    5920#include "scip/sorttpl.c" /*lint !e451*/
    5921
    5922
    5923/* SCIPsortInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5924#define SORTTPL_NAMEEXT Int
    5925#define SORTTPL_KEYTYPE int
    5926#include "scip/sorttpl.c" /*lint !e451*/
    5927
    5928
    5929/* SCIPsortIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5930#define SORTTPL_NAMEEXT IntInt
    5931#define SORTTPL_KEYTYPE int
    5932#define SORTTPL_FIELD1TYPE int
    5933#include "scip/sorttpl.c" /*lint !e451*/
    5934
    5935
    5936/* SCIPsortIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5937#define SORTTPL_NAMEEXT IntReal
    5938#define SORTTPL_KEYTYPE int
    5939#define SORTTPL_FIELD1TYPE SCIP_Real
    5940#include "scip/sorttpl.c" /*lint !e451*/
    5941
    5942
    5943/* SCIPsortIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5944#define SORTTPL_NAMEEXT IntPtr
    5945#define SORTTPL_KEYTYPE int
    5946#define SORTTPL_FIELD1TYPE void*
    5947#include "scip/sorttpl.c" /*lint !e451*/
    5948
    5949
    5950/* SCIPsortIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5951#define SORTTPL_NAMEEXT IntIntInt
    5952#define SORTTPL_KEYTYPE int
    5953#define SORTTPL_FIELD1TYPE int
    5954#define SORTTPL_FIELD2TYPE int
    5955#include "scip/sorttpl.c" /*lint !e451*/
    5956
    5957
    5958/* SCIPsortIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5959#define SORTTPL_NAMEEXT IntIntLong
    5960#define SORTTPL_KEYTYPE int
    5961#define SORTTPL_FIELD1TYPE int
    5962#define SORTTPL_FIELD2TYPE SCIP_Longint
    5963#include "scip/sorttpl.c" /*lint !e451*/
    5964
    5965/* SCIPsortIntRealLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5966#define SORTTPL_NAMEEXT IntRealLong
    5967#define SORTTPL_KEYTYPE int
    5968#define SORTTPL_FIELD1TYPE SCIP_Real
    5969#define SORTTPL_FIELD2TYPE SCIP_Longint
    5970#include "scip/sorttpl.c" /*lint !e451*/
    5971
    5972
    5973/* SCIPsortIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5974#define SORTTPL_NAMEEXT IntIntPtr
    5975#define SORTTPL_KEYTYPE int
    5976#define SORTTPL_FIELD1TYPE int
    5977#define SORTTPL_FIELD2TYPE void*
    5978#include "scip/sorttpl.c" /*lint !e451*/
    5979
    5980
    5981/* SCIPsortIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5982#define SORTTPL_NAMEEXT IntIntReal
    5983#define SORTTPL_KEYTYPE int
    5984#define SORTTPL_FIELD1TYPE int
    5985#define SORTTPL_FIELD2TYPE SCIP_Real
    5986#include "scip/sorttpl.c" /*lint !e451*/
    5987
    5988
    5989/* SCIPsortIntPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5990#define SORTTPL_NAMEEXT IntPtrReal
    5991#define SORTTPL_KEYTYPE int
    5992#define SORTTPL_FIELD1TYPE void*
    5993#define SORTTPL_FIELD2TYPE SCIP_Real
    5994#include "scip/sorttpl.c" /*lint !e451*/
    5995
    5996
    5997/* SCIPsortIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    5998#define SORTTPL_NAMEEXT IntIntIntPtr
    5999#define SORTTPL_KEYTYPE int
    6000#define SORTTPL_FIELD1TYPE int
    6001#define SORTTPL_FIELD2TYPE int
    6002#define SORTTPL_FIELD3TYPE void*
    6003#include "scip/sorttpl.c" /*lint !e451*/
    6004
    6005/* SCIPsortIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6006#define SORTTPL_NAMEEXT IntIntIntReal
    6007#define SORTTPL_KEYTYPE int
    6008#define SORTTPL_FIELD1TYPE int
    6009#define SORTTPL_FIELD2TYPE int
    6010#define SORTTPL_FIELD3TYPE SCIP_Real
    6011#include "scip/sorttpl.c" /*lint !e451*/
    6012
    6013/* SCIPsortIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6014#define SORTTPL_NAMEEXT IntPtrIntReal
    6015#define SORTTPL_KEYTYPE int
    6016#define SORTTPL_FIELD1TYPE void*
    6017#define SORTTPL_FIELD2TYPE int
    6018#define SORTTPL_FIELD3TYPE SCIP_Real
    6019#include "scip/sorttpl.c" /*lint !e451*/
    6020
    6021/* SCIPsortIntIntPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6022#define SORTTPL_NAMEEXT IntIntPtrPtr
    6023#define SORTTPL_KEYTYPE int
    6024#define SORTTPL_FIELD1TYPE int
    6025#define SORTTPL_FIELD2TYPE void*
    6026#define SORTTPL_FIELD3TYPE void*
    6027#include "scip/sorttpl.c" /*lint !e451*/
    6028
    6029/* SCIPsortIntIntPtrPtrInterval(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6030#define SORTTPL_NAMEEXT IntIntPtrPtrInterval
    6031#define SORTTPL_KEYTYPE int
    6032#define SORTTPL_FIELD1TYPE int
    6033#define SORTTPL_FIELD2TYPE void*
    6034#define SORTTPL_FIELD3TYPE void*
    6035#define SORTTPL_FIELD4TYPE SCIP_INTERVAL
    6036#include "scip/sorttpl.c" /*lint !e451*/
    6037
    6038/* SCIPsortLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6039#define SORTTPL_NAMEEXT Long
    6040#define SORTTPL_KEYTYPE SCIP_Longint
    6041#include "scip/sorttpl.c" /*lint !e451*/
    6042
    6043
    6044/* SCIPsortLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6045#define SORTTPL_NAMEEXT LongPtr
    6046#define SORTTPL_KEYTYPE SCIP_Longint
    6047#define SORTTPL_FIELD1TYPE void*
    6048#include "scip/sorttpl.c" /*lint !e451*/
    6049
    6050
    6051/* SCIPsortLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6052#define SORTTPL_NAMEEXT LongPtrInt
    6053#define SORTTPL_KEYTYPE SCIP_Longint
    6054#define SORTTPL_FIELD1TYPE void*
    6055#define SORTTPL_FIELD2TYPE int
    6056#include "scip/sorttpl.c" /*lint !e451*/
    6057
    6058
    6059/* SCIPsortLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6060#define SORTTPL_NAMEEXT LongPtrRealBool
    6061#define SORTTPL_KEYTYPE SCIP_Longint
    6062#define SORTTPL_FIELD1TYPE void*
    6063#define SORTTPL_FIELD2TYPE SCIP_Real
    6064#define SORTTPL_FIELD3TYPE SCIP_Bool
    6065#include "scip/sorttpl.c" /*lint !e451*/
    6066
    6067
    6068/* SCIPsortLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6069#define SORTTPL_NAMEEXT LongPtrRealRealBool
    6070#define SORTTPL_KEYTYPE SCIP_Longint
    6071#define SORTTPL_FIELD1TYPE void*
    6072#define SORTTPL_FIELD2TYPE SCIP_Real
    6073#define SORTTPL_FIELD3TYPE SCIP_Real
    6074#define SORTTPL_FIELD4TYPE SCIP_Bool
    6075#include "scip/sorttpl.c" /*lint !e451*/
    6076
    6077
    6078/* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6079#define SORTTPL_NAMEEXT LongPtrRealRealIntBool
    6080#define SORTTPL_KEYTYPE SCIP_Longint
    6081#define SORTTPL_FIELD1TYPE void*
    6082#define SORTTPL_FIELD2TYPE SCIP_Real
    6083#define SORTTPL_FIELD3TYPE SCIP_Real
    6084#define SORTTPL_FIELD4TYPE int
    6085#define SORTTPL_FIELD5TYPE SCIP_Bool
    6086#include "scip/sorttpl.c" /*lint !e451*/
    6087
    6088
    6089/* SCIPsortLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6090#define SORTTPL_NAMEEXT LongPtrPtrInt
    6091#define SORTTPL_KEYTYPE SCIP_Longint
    6092#define SORTTPL_FIELD1TYPE void*
    6093#define SORTTPL_FIELD2TYPE void*
    6094#define SORTTPL_FIELD3TYPE int
    6095#include "scip/sorttpl.c" /*lint !e451*/
    6096
    6097
    6098/* SCIPsortLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6099#define SORTTPL_NAMEEXT LongPtrPtrIntInt
    6100#define SORTTPL_KEYTYPE SCIP_Longint
    6101#define SORTTPL_FIELD1TYPE void*
    6102#define SORTTPL_FIELD2TYPE void*
    6103#define SORTTPL_FIELD3TYPE int
    6104#define SORTTPL_FIELD4TYPE int
    6105#include "scip/sorttpl.c" /*lint !e451*/
    6106
    6107
    6108/* SCIPsortLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6109#define SORTTPL_NAMEEXT LongPtrPtrBoolInt
    6110#define SORTTPL_KEYTYPE SCIP_Longint
    6111#define SORTTPL_FIELD1TYPE void*
    6112#define SORTTPL_FIELD2TYPE void*
    6113#define SORTTPL_FIELD3TYPE SCIP_Bool
    6114#define SORTTPL_FIELD4TYPE int
    6115#include "scip/sorttpl.c" /*lint !e451*/
    6116
    6117
    6118/* SCIPsortPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6119#define SORTTPL_NAMEEXT PtrIntIntBoolBool
    6120#define SORTTPL_KEYTYPE void*
    6121#define SORTTPL_FIELD1TYPE int
    6122#define SORTTPL_FIELD2TYPE int
    6123#define SORTTPL_FIELD3TYPE SCIP_Bool
    6124#define SORTTPL_FIELD4TYPE SCIP_Bool
    6125#define SORTTPL_PTRCOMP
    6126#include "scip/sorttpl.c" /*lint !e451*/
    6127
    6128
    6129/* SCIPsortIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6130#define SORTTPL_NAMEEXT IntPtrIntIntBoolBool
    6131#define SORTTPL_KEYTYPE int
    6132#define SORTTPL_FIELD1TYPE void*
    6133#define SORTTPL_FIELD2TYPE int
    6134#define SORTTPL_FIELD3TYPE int
    6135#define SORTTPL_FIELD4TYPE SCIP_Bool
    6136#define SORTTPL_FIELD5TYPE SCIP_Bool
    6137#include "scip/sorttpl.c" /*lint !e451*/
    6138
    6139
    6140/* now all downwards-sorting methods */
    6141
    6142
    6143/** sort an indexed element set in non-increasing order, resulting in a permutation index array */
    6145 int* perm, /**< pointer to store the resulting permutation */
    6146 SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
    6147 void* dataptr, /**< pointer to data field that is given to the external compare method */
    6148 int len /**< number of elements to be sorted (valid index range) */
    6149 )
    6150{
    6151 int pos;
    6152
    6153 assert(indcomp != NULL);
    6154 assert(len == 0 || perm != NULL);
    6155
    6156 /* create identity permutation */
    6157 for( pos = 0; pos < len; ++pos )
    6158 perm[pos] = pos;
    6159
    6160 SCIPsortDownInd(perm, indcomp, dataptr, len);
    6161}
    6162
    6163
    6164/* SCIPsortDownInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6165#define SORTTPL_NAMEEXT DownInd
    6166#define SORTTPL_KEYTYPE int
    6167#define SORTTPL_INDCOMP
    6168#define SORTTPL_BACKWARDS
    6169#include "scip/sorttpl.c" /*lint !e451*/
    6170
    6171
    6172/* SCIPsortDownPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6173#define SORTTPL_NAMEEXT DownPtr
    6174#define SORTTPL_KEYTYPE void*
    6175#define SORTTPL_PTRCOMP
    6176#define SORTTPL_BACKWARDS
    6177#include "scip/sorttpl.c" /*lint !e451*/
    6178
    6179
    6180/* SCIPsortDownPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6181#define SORTTPL_NAMEEXT DownPtrPtr
    6182#define SORTTPL_KEYTYPE void*
    6183#define SORTTPL_FIELD1TYPE void*
    6184#define SORTTPL_PTRCOMP
    6185#define SORTTPL_BACKWARDS
    6186#include "scip/sorttpl.c" /*lint !e451*/
    6187
    6188
    6189/* SCIPsortDownPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6190#define SORTTPL_NAMEEXT DownPtrReal
    6191#define SORTTPL_KEYTYPE void*
    6192#define SORTTPL_FIELD1TYPE SCIP_Real
    6193#define SORTTPL_PTRCOMP
    6194#define SORTTPL_BACKWARDS
    6195#include "scip/sorttpl.c" /*lint !e451*/
    6196
    6197
    6198/* SCIPsortDownPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6199#define SORTTPL_NAMEEXT DownPtrInt
    6200#define SORTTPL_KEYTYPE void*
    6201#define SORTTPL_FIELD1TYPE int
    6202#define SORTTPL_PTRCOMP
    6203#define SORTTPL_BACKWARDS
    6204#include "scip/sorttpl.c" /*lint !e451*/
    6205
    6206/* SCIPsortDownPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6207#define SORTTPL_NAMEEXT DownPtrBool
    6208#define SORTTPL_KEYTYPE void*
    6209#define SORTTPL_FIELD1TYPE SCIP_Bool
    6210#define SORTTPL_PTRCOMP
    6211#define SORTTPL_BACKWARDS
    6212#include "scip/sorttpl.c" /*lint !e451*/
    6213
    6214/* SCIPsortDownPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6215#define SORTTPL_NAMEEXT DownPtrIntInt
    6216#define SORTTPL_KEYTYPE void*
    6217#define SORTTPL_FIELD1TYPE int
    6218#define SORTTPL_FIELD2TYPE int
    6219#define SORTTPL_PTRCOMP
    6220#define SORTTPL_BACKWARDS
    6221#include "scip/sorttpl.c" /*lint !e451*/
    6222
    6223
    6224/* SCIPsortDownPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6225#define SORTTPL_NAMEEXT DownPtrRealInt
    6226#define SORTTPL_KEYTYPE void*
    6227#define SORTTPL_FIELD1TYPE SCIP_Real
    6228#define SORTTPL_FIELD2TYPE int
    6229#define SORTTPL_PTRCOMP
    6230#define SORTTPL_BACKWARDS
    6231#include "scip/sorttpl.c" /*lint !e451*/
    6232
    6233
    6234/* SCIPsortDownPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6235#define SORTTPL_NAMEEXT DownPtrRealBool
    6236#define SORTTPL_KEYTYPE void*
    6237#define SORTTPL_FIELD1TYPE SCIP_Real
    6238#define SORTTPL_FIELD2TYPE SCIP_Bool
    6239#define SORTTPL_PTRCOMP
    6240#define SORTTPL_BACKWARDS
    6241#include "scip/sorttpl.c" /*lint !e451*/
    6242
    6243
    6244/* SCIPsortDownPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6245#define SORTTPL_NAMEEXT DownPtrPtrInt
    6246#define SORTTPL_KEYTYPE void*
    6247#define SORTTPL_FIELD1TYPE void*
    6248#define SORTTPL_FIELD2TYPE int
    6249#define SORTTPL_PTRCOMP
    6250#define SORTTPL_BACKWARDS
    6251#include "scip/sorttpl.c" /*lint !e451*/
    6252
    6253
    6254/* SCIPsortDownPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6255#define SORTTPL_NAMEEXT DownPtrPtrReal
    6256#define SORTTPL_KEYTYPE void*
    6257#define SORTTPL_FIELD1TYPE void*
    6258#define SORTTPL_FIELD2TYPE SCIP_Real
    6259#define SORTTPL_PTRCOMP
    6260#define SORTTPL_BACKWARDS
    6261#include "scip/sorttpl.c" /*lint !e451*/
    6262
    6263
    6264/* SCIPsortDownPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6265#define SORTTPL_NAMEEXT DownPtrRealIntInt
    6266#define SORTTPL_KEYTYPE void*
    6267#define SORTTPL_FIELD1TYPE SCIP_Real
    6268#define SORTTPL_FIELD2TYPE int
    6269#define SORTTPL_FIELD3TYPE int
    6270#define SORTTPL_PTRCOMP
    6271#define SORTTPL_BACKWARDS
    6272#include "scip/sorttpl.c" /*lint !e451*/
    6273
    6274
    6275/* SCIPsortDownPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6276#define SORTTPL_NAMEEXT DownPtrPtrIntInt
    6277#define SORTTPL_KEYTYPE void*
    6278#define SORTTPL_FIELD1TYPE void*
    6279#define SORTTPL_FIELD2TYPE int
    6280#define SORTTPL_FIELD3TYPE int
    6281#define SORTTPL_PTRCOMP
    6282#define SORTTPL_BACKWARDS
    6283#include "scip/sorttpl.c" /*lint !e451*/
    6284
    6285
    6286/* SCIPsortDownPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6287#define SORTTPL_NAMEEXT DownPtrPtrRealInt
    6288#define SORTTPL_KEYTYPE void*
    6289#define SORTTPL_FIELD1TYPE void*
    6290#define SORTTPL_FIELD2TYPE SCIP_Real
    6291#define SORTTPL_FIELD3TYPE int
    6292#define SORTTPL_PTRCOMP
    6293#define SORTTPL_BACKWARDS
    6294#include "scip/sorttpl.c" /*lint !e451*/
    6295
    6296
    6297/* SCIPsortDownPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6298#define SORTTPL_NAMEEXT DownPtrPtrRealBool
    6299#define SORTTPL_KEYTYPE void*
    6300#define SORTTPL_FIELD1TYPE void*
    6301#define SORTTPL_FIELD2TYPE SCIP_Real
    6302#define SORTTPL_FIELD3TYPE SCIP_Bool
    6303#define SORTTPL_PTRCOMP
    6304#define SORTTPL_BACKWARDS
    6305#include "scip/sorttpl.c" /*lint !e451*/
    6306
    6307
    6308/* SCIPsortDownPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6309#define SORTTPL_NAMEEXT DownPtrPtrLongInt
    6310#define SORTTPL_KEYTYPE void*
    6311#define SORTTPL_FIELD1TYPE void*
    6312#define SORTTPL_FIELD2TYPE SCIP_Longint
    6313#define SORTTPL_FIELD3TYPE int
    6314#define SORTTPL_PTRCOMP
    6315#define SORTTPL_BACKWARDS
    6316#include "scip/sorttpl.c" /*lint !e451*/
    6317
    6318
    6319/* SCIPsortDownPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6320#define SORTTPL_NAMEEXT DownPtrPtrLongIntInt
    6321#define SORTTPL_KEYTYPE void*
    6322#define SORTTPL_FIELD1TYPE void*
    6323#define SORTTPL_FIELD2TYPE SCIP_Longint
    6324#define SORTTPL_FIELD3TYPE int
    6325#define SORTTPL_FIELD4TYPE int
    6326#define SORTTPL_PTRCOMP
    6327#define SORTTPL_BACKWARDS
    6328#include "scip/sorttpl.c" /*lint !e451*/
    6329
    6330
    6331/* SCIPsortDownReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6332#define SORTTPL_NAMEEXT DownReal
    6333#define SORTTPL_KEYTYPE SCIP_Real
    6334#define SORTTPL_BACKWARDS
    6335#include "scip/sorttpl.c" /*lint !e451*/
    6336
    6337
    6338/* SCIPsortDownRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6339#define SORTTPL_NAMEEXT DownRealBoolPtr
    6340#define SORTTPL_KEYTYPE SCIP_Real
    6341#define SORTTPL_FIELD1TYPE SCIP_Bool
    6342#define SORTTPL_FIELD2TYPE void*
    6343#define SORTTPL_BACKWARDS
    6344#include "scip/sorttpl.c" /*lint !e451*/
    6345
    6346
    6347/* SCIPsortDownRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6348#define SORTTPL_NAMEEXT DownRealPtr
    6349#define SORTTPL_KEYTYPE SCIP_Real
    6350#define SORTTPL_FIELD1TYPE void*
    6351#define SORTTPL_BACKWARDS
    6352#include "scip/sorttpl.c" /*lint !e451*/
    6353
    6354
    6355/* SCIPsortDownRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6356#define SORTTPL_NAMEEXT DownRealInt
    6357#define SORTTPL_KEYTYPE SCIP_Real
    6358#define SORTTPL_FIELD1TYPE int
    6359#define SORTTPL_BACKWARDS
    6360#include "scip/sorttpl.c" /*lint !e451*/
    6361
    6362/* SCIPsortDownRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6363#define SORTTPL_NAMEEXT DownRealIntInt
    6364#define SORTTPL_KEYTYPE SCIP_Real
    6365#define SORTTPL_FIELD1TYPE int
    6366#define SORTTPL_FIELD2TYPE int
    6367#define SORTTPL_BACKWARDS
    6368#include "scip/sorttpl.c" /*lint !e451*/
    6369
    6370/* SCIPsortDownRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6371#define SORTTPL_NAMEEXT DownRealIntLong
    6372#define SORTTPL_KEYTYPE SCIP_Real
    6373#define SORTTPL_FIELD1TYPE int
    6374#define SORTTPL_FIELD2TYPE SCIP_Longint
    6375#define SORTTPL_BACKWARDS
    6376#include "scip/sorttpl.c" /*lint !e451*/
    6377
    6378
    6379/* SCIPsortDownRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6380#define SORTTPL_NAMEEXT DownRealIntPtr
    6381#define SORTTPL_KEYTYPE SCIP_Real
    6382#define SORTTPL_FIELD1TYPE int
    6383#define SORTTPL_FIELD2TYPE void*
    6384#define SORTTPL_BACKWARDS
    6385#include "scip/sorttpl.c" /*lint !e451*/
    6386
    6387
    6388/* SCIPsortDownRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6389#define SORTTPL_NAMEEXT DownRealPtrPtr
    6390#define SORTTPL_KEYTYPE SCIP_Real
    6391#define SORTTPL_FIELD1TYPE void*
    6392#define SORTTPL_FIELD2TYPE void*
    6393#define SORTTPL_BACKWARDS
    6394#include "scip/sorttpl.c" /*lint !e451*/
    6395
    6396/* SCIPsortDownRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6397#define SORTTPL_NAMEEXT DownRealRealInt
    6398#define SORTTPL_KEYTYPE SCIP_Real
    6399#define SORTTPL_FIELD1TYPE SCIP_Real
    6400#define SORTTPL_FIELD2TYPE int
    6401#define SORTTPL_BACKWARDS
    6402#include "scip/sorttpl.c" /*lint !e451*/
    6403
    6404/* SCIPsortDownRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6405#define SORTTPL_NAMEEXT DownRealRealPtr
    6406#define SORTTPL_KEYTYPE SCIP_Real
    6407#define SORTTPL_FIELD1TYPE SCIP_Real
    6408#define SORTTPL_FIELD2TYPE void*
    6409#define SORTTPL_BACKWARDS
    6410#include "scip/sorttpl.c" /*lint !e451*/
    6411
    6412/* SCIPsortDownRealRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6413#define SORTTPL_NAMEEXT DownRealRealPtrPtr
    6414#define SORTTPL_KEYTYPE SCIP_Real
    6415#define SORTTPL_FIELD1TYPE SCIP_Real
    6416#define SORTTPL_FIELD2TYPE void*
    6417#define SORTTPL_FIELD3TYPE void*
    6418#define SORTTPL_BACKWARDS
    6419#include "scip/sorttpl.c" /*lint !e451*/
    6420
    6421
    6422/* SCIPsortDownRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6423#define SORTTPL_NAMEEXT DownRealLongRealInt
    6424#define SORTTPL_KEYTYPE SCIP_Real
    6425#define SORTTPL_FIELD1TYPE SCIP_Longint
    6426#define SORTTPL_FIELD2TYPE SCIP_Real
    6427#define SORTTPL_FIELD3TYPE int
    6428#define SORTTPL_BACKWARDS
    6429#include "scip/sorttpl.c" /*lint !e451*/
    6430
    6431
    6432/* SCIPsortDownRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6433#define SORTTPL_NAMEEXT DownRealRealIntInt
    6434#define SORTTPL_KEYTYPE SCIP_Real
    6435#define SORTTPL_FIELD1TYPE SCIP_Real
    6436#define SORTTPL_FIELD2TYPE int
    6437#define SORTTPL_FIELD3TYPE int
    6438#define SORTTPL_BACKWARDS
    6439#include "scip/sorttpl.c" /*lint !e451*/
    6440
    6441
    6442/* SCIPsortDownRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6443#define SORTTPL_NAMEEXT DownRealRealRealInt
    6444#define SORTTPL_KEYTYPE SCIP_Real
    6445#define SORTTPL_FIELD1TYPE SCIP_Real
    6446#define SORTTPL_FIELD2TYPE SCIP_Real
    6447#define SORTTPL_FIELD3TYPE int
    6448#define SORTTPL_BACKWARDS
    6449#include "scip/sorttpl.c" /*lint !e451*/
    6450
    6451
    6452/* SCIPsortDownRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6453#define SORTTPL_NAMEEXT DownRealRealRealPtr
    6454#define SORTTPL_KEYTYPE SCIP_Real
    6455#define SORTTPL_FIELD1TYPE SCIP_Real
    6456#define SORTTPL_FIELD2TYPE SCIP_Real
    6457#define SORTTPL_FIELD3TYPE void*
    6458#define SORTTPL_BACKWARDS
    6459#include "scip/sorttpl.c" /*lint !e451*/
    6460
    6461
    6462/* SCIPsortDownRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6463#define SORTTPL_NAMEEXT DownRealPtrPtrInt
    6464#define SORTTPL_KEYTYPE SCIP_Real
    6465#define SORTTPL_FIELD1TYPE void*
    6466#define SORTTPL_FIELD2TYPE void*
    6467#define SORTTPL_FIELD3TYPE int
    6468#define SORTTPL_BACKWARDS
    6469#include "scip/sorttpl.c" /*lint !e451*/
    6470
    6471/* SCIPsortDownRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6472#define SORTTPL_NAMEEXT DownRealPtrPtrIntInt
    6473#define SORTTPL_KEYTYPE SCIP_Real
    6474#define SORTTPL_FIELD1TYPE void*
    6475#define SORTTPL_FIELD2TYPE void*
    6476#define SORTTPL_FIELD3TYPE int
    6477#define SORTTPL_FIELD4TYPE int
    6478#define SORTTPL_BACKWARDS
    6479#include "scip/sorttpl.c" /*lint !e451*/
    6480
    6481
    6482/* SCIPsortDownRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6483#define SORTTPL_NAMEEXT DownRealRealRealBoolPtr
    6484#define SORTTPL_KEYTYPE SCIP_Real
    6485#define SORTTPL_FIELD1TYPE SCIP_Real
    6486#define SORTTPL_FIELD2TYPE SCIP_Real
    6487#define SORTTPL_FIELD3TYPE SCIP_Bool
    6488#define SORTTPL_FIELD4TYPE void*
    6489#define SORTTPL_BACKWARDS
    6490#include "scip/sorttpl.c" /*lint !e451*/
    6491
    6492
    6493/* SCIPsortDownRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6494#define SORTTPL_NAMEEXT DownRealRealRealBoolBoolPtr
    6495#define SORTTPL_KEYTYPE SCIP_Real
    6496#define SORTTPL_FIELD1TYPE SCIP_Real
    6497#define SORTTPL_FIELD2TYPE SCIP_Real
    6498#define SORTTPL_FIELD3TYPE SCIP_Bool
    6499#define SORTTPL_FIELD4TYPE SCIP_Bool
    6500#define SORTTPL_FIELD5TYPE void*
    6501#include "scip/sorttpl.c" /*lint !e451*/
    6502
    6503
    6504/* SCIPsortDownInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6505#define SORTTPL_NAMEEXT DownInt
    6506#define SORTTPL_KEYTYPE int
    6507#define SORTTPL_BACKWARDS
    6508#include "scip/sorttpl.c" /*lint !e451*/
    6509
    6510
    6511/* SCIPsortDownIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6512#define SORTTPL_NAMEEXT DownIntInt
    6513#define SORTTPL_KEYTYPE int
    6514#define SORTTPL_FIELD1TYPE int
    6515#define SORTTPL_BACKWARDS
    6516#include "scip/sorttpl.c" /*lint !e451*/
    6517
    6518
    6519/* SCIPsortDownIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6520#define SORTTPL_NAMEEXT DownIntIntReal
    6521#define SORTTPL_KEYTYPE int
    6522#define SORTTPL_FIELD1TYPE int
    6523#define SORTTPL_FIELD2TYPE SCIP_Real
    6524#define SORTTPL_BACKWARDS
    6525#include "scip/sorttpl.c" /*lint !e451*/
    6526
    6527
    6528/* SCIPsortDownIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6529#define SORTTPL_NAMEEXT DownIntReal
    6530#define SORTTPL_KEYTYPE int
    6531#define SORTTPL_FIELD1TYPE SCIP_Real
    6532#define SORTTPL_BACKWARDS
    6533#include "scip/sorttpl.c" /*lint !e451*/
    6534
    6535
    6536/* SCIPsortDownIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6537#define SORTTPL_NAMEEXT DownIntPtr
    6538#define SORTTPL_KEYTYPE int
    6539#define SORTTPL_FIELD1TYPE void*
    6540#define SORTTPL_BACKWARDS
    6541#include "scip/sorttpl.c" /*lint !e451*/
    6542
    6543
    6544/* SCIPsortDownIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6545#define SORTTPL_NAMEEXT DownIntIntInt
    6546#define SORTTPL_KEYTYPE int
    6547#define SORTTPL_FIELD1TYPE int
    6548#define SORTTPL_FIELD2TYPE int
    6549#define SORTTPL_BACKWARDS
    6550#include "scip/sorttpl.c" /*lint !e451*/
    6551
    6552
    6553/* SCIPsortDownIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6554#define SORTTPL_NAMEEXT DownIntIntLong
    6555#define SORTTPL_KEYTYPE int
    6556#define SORTTPL_FIELD1TYPE int
    6557#define SORTTPL_FIELD2TYPE SCIP_Longint
    6558#define SORTTPL_BACKWARDS
    6559#include "scip/sorttpl.c" /*lint !e451*/
    6560
    6561
    6562/* SCIPsortDownIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6563#define SORTTPL_NAMEEXT DownIntIntPtr
    6564#define SORTTPL_KEYTYPE int
    6565#define SORTTPL_FIELD1TYPE int
    6566#define SORTTPL_FIELD2TYPE void*
    6567#define SORTTPL_BACKWARDS
    6568#include "scip/sorttpl.c" /*lint !e451*/
    6569
    6570
    6571/* SCIPsortDownIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6572#define SORTTPL_NAMEEXT DownIntIntIntPtr
    6573#define SORTTPL_KEYTYPE int
    6574#define SORTTPL_FIELD1TYPE int
    6575#define SORTTPL_FIELD2TYPE int
    6576#define SORTTPL_FIELD3TYPE void*
    6577#define SORTTPL_BACKWARDS
    6578#include "scip/sorttpl.c" /*lint !e451*/
    6579
    6580
    6581/* SCIPsortDownIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6582#define SORTTPL_NAMEEXT DownIntIntIntReal
    6583#define SORTTPL_KEYTYPE int
    6584#define SORTTPL_FIELD1TYPE int
    6585#define SORTTPL_FIELD2TYPE int
    6586#define SORTTPL_FIELD3TYPE SCIP_Real
    6587#define SORTTPL_BACKWARDS
    6588#include "scip/sorttpl.c" /*lint !e451*/
    6589
    6590
    6591/* SCIPsortDownIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6592#define SORTTPL_NAMEEXT DownIntPtrIntReal
    6593#define SORTTPL_KEYTYPE int
    6594#define SORTTPL_FIELD1TYPE void*
    6595#define SORTTPL_FIELD2TYPE int
    6596#define SORTTPL_FIELD3TYPE SCIP_Real
    6597#define SORTTPL_BACKWARDS
    6598#include "scip/sorttpl.c" /*lint !e451*/
    6599
    6600
    6601/* SCIPsortDownLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6602#define SORTTPL_NAMEEXT DownLong
    6603#define SORTTPL_KEYTYPE SCIP_Longint
    6604#define SORTTPL_BACKWARDS
    6605#include "scip/sorttpl.c" /*lint !e451*/
    6606
    6607
    6608/* SCIPsortDownLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6609#define SORTTPL_NAMEEXT DownLongPtr
    6610#define SORTTPL_KEYTYPE SCIP_Longint
    6611#define SORTTPL_FIELD1TYPE void*
    6612#define SORTTPL_BACKWARDS
    6613#include "scip/sorttpl.c" /*lint !e451*/
    6614
    6615
    6616/* SCIPsortDownLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6617#define SORTTPL_NAMEEXT DownLongPtrInt
    6618#define SORTTPL_KEYTYPE SCIP_Longint
    6619#define SORTTPL_FIELD1TYPE void*
    6620#define SORTTPL_FIELD2TYPE int
    6621#define SORTTPL_BACKWARDS
    6622#include "scip/sorttpl.c" /*lint !e451*/
    6623
    6624
    6625/* SCIPsortDownLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6626#define SORTTPL_NAMEEXT DownLongPtrRealBool
    6627#define SORTTPL_KEYTYPE SCIP_Longint
    6628#define SORTTPL_FIELD1TYPE void*
    6629#define SORTTPL_FIELD2TYPE SCIP_Real
    6630#define SORTTPL_FIELD3TYPE SCIP_Bool
    6631#define SORTTPL_BACKWARDS
    6632#include "scip/sorttpl.c" /*lint !e451*/
    6633
    6634
    6635/* SCIPsortDownLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6636#define SORTTPL_NAMEEXT DownLongPtrRealRealBool
    6637#define SORTTPL_KEYTYPE SCIP_Longint
    6638#define SORTTPL_FIELD1TYPE void*
    6639#define SORTTPL_FIELD2TYPE SCIP_Real
    6640#define SORTTPL_FIELD3TYPE SCIP_Real
    6641#define SORTTPL_FIELD4TYPE SCIP_Bool
    6642#define SORTTPL_BACKWARDS
    6643#include "scip/sorttpl.c" /*lint !e451*/
    6644
    6645
    6646/* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6647#define SORTTPL_NAMEEXT DownLongPtrRealRealIntBool
    6648#define SORTTPL_KEYTYPE SCIP_Longint
    6649#define SORTTPL_FIELD1TYPE void*
    6650#define SORTTPL_FIELD2TYPE SCIP_Real
    6651#define SORTTPL_FIELD3TYPE SCIP_Real
    6652#define SORTTPL_FIELD4TYPE int
    6653#define SORTTPL_FIELD5TYPE SCIP_Bool
    6654#define SORTTPL_BACKWARDS
    6655#include "scip/sorttpl.c" /*lint !e451*/
    6656
    6657
    6658/* SCIPsortDownLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6659#define SORTTPL_NAMEEXT DownLongPtrPtrInt
    6660#define SORTTPL_KEYTYPE SCIP_Longint
    6661#define SORTTPL_FIELD1TYPE void*
    6662#define SORTTPL_FIELD2TYPE void*
    6663#define SORTTPL_FIELD3TYPE int
    6664#define SORTTPL_BACKWARDS
    6665#include "scip/sorttpl.c" /*lint !e451*/
    6666
    6667
    6668/* SCIPsortDownLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6669#define SORTTPL_NAMEEXT DownLongPtrPtrIntInt
    6670#define SORTTPL_KEYTYPE SCIP_Longint
    6671#define SORTTPL_FIELD1TYPE void*
    6672#define SORTTPL_FIELD2TYPE void*
    6673#define SORTTPL_FIELD3TYPE int
    6674#define SORTTPL_FIELD4TYPE int
    6675#define SORTTPL_BACKWARDS
    6676#include "scip/sorttpl.c" /*lint !e451*/
    6677
    6678
    6679/* SCIPsortDownLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6680#define SORTTPL_NAMEEXT DownLongPtrPtrBoolInt
    6681#define SORTTPL_KEYTYPE SCIP_Longint
    6682#define SORTTPL_FIELD1TYPE void*
    6683#define SORTTPL_FIELD2TYPE void*
    6684#define SORTTPL_FIELD3TYPE SCIP_Bool
    6685#define SORTTPL_FIELD4TYPE int
    6686#define SORTTPL_BACKWARDS
    6687#include "scip/sorttpl.c" /*lint !e451*/
    6688
    6689
    6690/* SCIPsortDownPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6691#define SORTTPL_NAMEEXT DownPtrIntIntBoolBool
    6692#define SORTTPL_KEYTYPE void*
    6693#define SORTTPL_FIELD1TYPE int
    6694#define SORTTPL_FIELD2TYPE int
    6695#define SORTTPL_FIELD3TYPE SCIP_Bool
    6696#define SORTTPL_FIELD4TYPE SCIP_Bool
    6697#define SORTTPL_PTRCOMP
    6698#define SORTTPL_BACKWARDS
    6699#include "scip/sorttpl.c" /*lint !e451*/
    6700
    6701
    6702/* SCIPsortDownIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
    6703#define SORTTPL_NAMEEXT DownIntPtrIntIntBoolBool
    6704#define SORTTPL_KEYTYPE int
    6705#define SORTTPL_FIELD1TYPE void*
    6706#define SORTTPL_FIELD2TYPE int
    6707#define SORTTPL_FIELD3TYPE int
    6708#define SORTTPL_FIELD4TYPE SCIP_Bool
    6709#define SORTTPL_FIELD5TYPE SCIP_Bool
    6710#define SORTTPL_BACKWARDS
    6711#include "scip/sorttpl.c" /*lint !e451*/
    6712
    6713/*
    6714 * Resulting activity
    6715 */
    6716
    6717/** create a resource activity */
    6719 SCIP_RESOURCEACTIVITY** activity, /**< pointer to store the resource activity */
    6720 SCIP_VAR* var, /**< start time variable of the activity */
    6721 int duration, /**< duration of the activity */
    6722 int demand /**< demand of the activity */
    6723 )
    6724{
    6725 assert(activity != NULL);
    6726
    6727 SCIP_ALLOC( BMSallocMemory(activity) );
    6728
    6729 (*activity)->var = var;
    6730 (*activity)->duration = duration;
    6731 (*activity)->demand = demand;
    6732
    6733 return SCIP_OKAY;
    6734}
    6735
    6736/** frees a resource activity */
    6738 SCIP_RESOURCEACTIVITY** activity /**< pointer to the resource activity */
    6739 )
    6740{
    6741 assert(activity != NULL);
    6742 assert(*activity != NULL);
    6743
    6744 BMSfreeMemory(activity);
    6745}
    6746
    6747/* some simple variable functions implemented as defines */
    6748
    6749#ifndef NDEBUG
    6750
    6751/* In debug mode, the following methods are implemented as function calls to ensure
    6752 * type validity.
    6753 * In optimized mode, the methods are implemented as defines to improve performance.
    6754 * However, we want to have them in the library anyways, so we have to undef the defines.
    6755 */
    6756
    6757#undef SCIPactivityGetVar
    6758#undef SCIPactivityGetDuration
    6759#undef SCIPactivityGetDemand
    6760#undef SCIPactivityGetEnergy
    6761
    6762/** returns the start time variable of the resource activity */
    6764 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
    6765 )
    6766{
    6767 assert(activity != NULL);
    6768
    6769 return activity->var;
    6770}
    6771
    6772/** returns the duration of the resource activity */
    6774 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
    6775 )
    6776{
    6777 assert(activity != NULL);
    6778
    6779 return activity->duration;
    6780}
    6781
    6782/** returns the demand of the resource activity */
    6784 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
    6785 )
    6786{
    6787 assert(activity != NULL);
    6788
    6789 return activity->demand;
    6790}
    6791
    6792/** returns the energy of the resource activity */
    6794 SCIP_RESOURCEACTIVITY* activity /**< resource activity */
    6795 )
    6796{
    6797 assert(activity != NULL);
    6798
    6799 return activity->duration * activity->demand ;
    6800}
    6801
    6802#endif
    6803
    6804/*
    6805 * Resource Profile
    6806 */
    6807
    6808/** helper method to create a profile */
    6809static
    6811 SCIP_PROFILE** profile, /**< pointer to store the resource profile */
    6812 int capacity /**< resource capacity */
    6813 )
    6814{
    6815 SCIP_ALLOC( BMSallocMemory(profile) );
    6816 BMSclearMemory(*profile);
    6817
    6818 (*profile)->arraysize = 10;
    6819 SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->timepoints, (*profile)->arraysize) );
    6820 SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->loads, (*profile)->arraysize) );
    6821
    6822 /* setup resource profile for use */
    6823 (*profile)->ntimepoints = 1;
    6824 (*profile)->timepoints[0] = 0;
    6825 (*profile)->loads[0] = 0;
    6826 (*profile)->capacity = capacity;
    6827
    6828 return SCIP_OKAY;
    6829}
    6830
    6831/** creates resource profile */
    6833 SCIP_PROFILE** profile, /**< pointer to store the resource profile */
    6834 int capacity /**< resource capacity */
    6835 )
    6836{
    6837 assert(profile != NULL);
    6838 assert(capacity > 0);
    6839
    6840 SCIP_CALL_FINALLY( doProfileCreate(profile, capacity), SCIPprofileFree(profile) );
    6841
    6842 return SCIP_OKAY;
    6843}
    6844
    6845/** frees given resource profile */
    6847 SCIP_PROFILE** profile /**< pointer to the resource profile */
    6848 )
    6849{
    6850 assert(profile != NULL);
    6851
    6852 /* free resource profile */
    6853 if( *profile != NULL )
    6854 {
    6855 BMSfreeMemoryArrayNull(&(*profile)->loads);
    6856 BMSfreeMemoryArrayNull(&(*profile)->timepoints);
    6857 BMSfreeMemory(profile);
    6858 }
    6859}
    6860
    6861/** output of the given resource profile */
    6863 SCIP_PROFILE* profile, /**< resource profile to output */
    6864 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    6865 FILE* file /**< output file (or NULL for standard output) */
    6866 )
    6867{
    6868 int t;
    6869
    6870 SCIPmessageFPrintInfo(messagehdlr, file, "Profile <%p> (capacity %d) --> ", (void*)profile, profile->capacity);
    6871
    6872 for( t = 0; t < profile->ntimepoints; ++t )
    6873 {
    6874 if( t == 0 )
    6875 SCIPmessageFPrintInfo(messagehdlr, file, "%d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
    6876 else
    6877 SCIPmessageFPrintInfo(messagehdlr, file, ", %d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
    6878 }
    6879
    6880 SCIPmessageFPrintInfo(messagehdlr, file,"\n");
    6881}
    6882
    6883/** returns the capacity of the resource profile */
    6885 SCIP_PROFILE* profile /**< resource profile to use */
    6886 )
    6887{
    6888 assert(profile != NULL);
    6889
    6890 return profile->capacity;
    6891}
    6892
    6893/** returns the number time points of the resource profile */
    6895 SCIP_PROFILE* profile /**< resource profile to use */
    6896 )
    6897{
    6898 assert(profile != NULL);
    6899
    6900 return profile->ntimepoints;
    6901}
    6902
    6903/** returns the time points of the resource profile */
    6905 SCIP_PROFILE* profile /**< resource profile to use */
    6906 )
    6907{
    6908 assert(profile != NULL);
    6909
    6910 return profile->timepoints;
    6911}
    6912
    6913/** returns the loads of the resource profile */
    6915 SCIP_PROFILE* profile /**< resource profile to use */
    6916 )
    6917{
    6918 assert(profile != NULL);
    6919
    6920 return profile->loads;
    6921}
    6922
    6923/** returns the time point for given position of the resource profile */
    6925 SCIP_PROFILE* profile, /**< resource profile to use */
    6926 int pos /**< position */
    6927 )
    6928{
    6929 assert(profile != NULL);
    6930 assert(pos >= 0 && pos < profile->ntimepoints);
    6931
    6932 return profile->timepoints[pos];
    6933}
    6934
    6935/** returns the loads of the resource profile at the given position */
    6937 SCIP_PROFILE* profile, /**< resource profile */
    6938 int pos /**< position */
    6939 )
    6940{
    6941 assert(profile != NULL);
    6942 assert(pos >= 0 && pos < profile->ntimepoints);
    6943
    6944 return profile->loads[pos];
    6945}
    6946
    6947/** returns if the given time point exists in the resource profile and stores the position of the given time point if it
    6948 * exists; otherwise the position of the next smaller existing time point is stored
    6949 */
    6951 SCIP_PROFILE* profile, /**< resource profile to search */
    6952 int timepoint, /**< time point to search for */
    6953 int* pos /**< pointer to store the position */
    6954 )
    6955{
    6956 assert(profile != NULL);
    6957 assert(timepoint >= 0);
    6958 assert(profile->ntimepoints > 0);
    6959 assert(profile->timepoints[0] == 0);
    6960
    6961 /* find the position of time point in the time points array via binary search */
    6962 if( SCIPsortedvecFindInt(profile->timepoints, timepoint, profile->ntimepoints, pos) )
    6963 return TRUE;
    6964
    6965 assert(*pos > 0);
    6966 (*pos)--;
    6967
    6968 return FALSE;
    6969}
    6970
    6971/* ensures that resource profile arrays is big enough */
    6972static
    6974 SCIP_PROFILE* profile, /**< resource profile to insert the time point */
    6975 int neededsize /**< needed size */
    6976 )
    6977{
    6978 assert(profile->arraysize > 0);
    6979
    6980 /* check whether the arrays are big enough */
    6981 if( neededsize <= profile->arraysize )
    6982 return SCIP_OKAY;
    6983
    6984 profile->arraysize *= 2;
    6985
    6986 SCIP_ALLOC( BMSreallocMemoryArray(&profile->timepoints, profile->arraysize) );
    6987 SCIP_ALLOC( BMSreallocMemoryArray(&profile->loads, profile->arraysize) );
    6988
    6989 return SCIP_OKAY;
    6990}
    6991
    6992/** inserts the given time point into the resource profile if it this time point does not exists yet; returns its
    6993 * position in the time point array
    6994 */
    6995static
    6997 SCIP_PROFILE* profile, /**< resource profile to insert the time point */
    6998 int timepoint, /**< time point to insert */
    6999 int* pos /**< pointer to store the insert position */
    7000 )
    7001{
    7002 assert(profile != NULL);
    7003 assert(timepoint >= 0);
    7004 assert(profile->arraysize >= profile->ntimepoints);
    7005
    7006 /* get the position of the given time point in the resource profile array if it exists; otherwise the position of the
    7007 * next smaller existing time point
    7008 */
    7009 if( !SCIPprofileFindLeft(profile, timepoint, pos) )
    7010 {
    7011 assert(*pos >= 0 && *pos < profile->ntimepoints);
    7012 assert(timepoint >= profile->timepoints[*pos]);
    7013
    7014 /* ensure that the arrays are big enough */
    7015 SCIP_CALL( ensureProfileSize(profile, profile->ntimepoints + 1) );
    7016 assert(profile->arraysize > profile->ntimepoints);
    7017
    7018 /* insert new time point into the (sorted) resource profile */
    7019 SCIPsortedvecInsertIntInt(profile->timepoints, profile->loads, timepoint, profile->loads[*pos],
    7020 &profile->ntimepoints, pos);
    7021 }
    7022
    7023#ifndef NDEBUG
    7024 /* check if the time points are sorted */
    7025 {
    7026 int i;
    7027 for( i = 1; i < profile->ntimepoints; ++i )
    7028 assert(profile->timepoints[i-1] < profile->timepoints[i]);
    7029 }
    7030#endif
    7031
    7032 return SCIP_OKAY;
    7033}
    7034
    7035/** updates the resource profile due to inserting of a core */
    7036static
    7038 SCIP_PROFILE* profile, /**< resource profile to update */
    7039 int left, /**< left side of core interval */
    7040 int right, /**< right side of core interval */
    7041 int demand, /**< demand of the core */
    7042 int* pos, /**< pointer to store the first position were it gets infeasible */
    7043 SCIP_Bool* infeasible /**< pointer to store if the update is infeasible */
    7044 )
    7045{
    7046 int startpos;
    7047 int endpos;
    7048 int i;
    7049
    7050 assert(profile != NULL);
    7051 assert(profile->arraysize >= profile->ntimepoints);
    7052 assert(left >= 0);
    7053 assert(left < right);
    7054 assert(infeasible != NULL);
    7055
    7056 (*infeasible) = FALSE;
    7057 (*pos) = -1;
    7058
    7059 /* get position of the starttime in profile */
    7060 SCIP_CALL( profileInsertTimepoint(profile, left, &startpos) );
    7061 assert(profile->timepoints[startpos] == left);
    7062
    7063 /* get position of the endtime in profile */
    7064 SCIP_CALL( profileInsertTimepoint(profile, right, &endpos) );
    7065 assert(profile->timepoints[endpos] == right);
    7066
    7067 assert(startpos < endpos);
    7068 assert(profile->arraysize >= profile->ntimepoints);
    7069
    7070 /* remove/add the given demand from the core */
    7071 for( i = startpos; i < endpos; ++i )
    7072 {
    7073 profile->loads[i] += demand;
    7074
    7075 /* check if the core fits */
    7076 if( profile->loads[i] > profile->capacity )
    7077 {
    7078 SCIPdebugMessage("core insertion detected infeasibility (pos %d)\n", i);
    7079
    7080 (*infeasible) = TRUE;
    7081 (*pos) = i;
    7082
    7083 /* remove the partly inserted core since it does fit completely */
    7084 for( ; i >= startpos; --i ) /*lint !e445*/
    7085 profile->loads[i] -= demand;
    7086
    7087 break;
    7088 }
    7089 }
    7090
    7091 return SCIP_OKAY;
    7092}
    7093
    7094/** insert a core into resource profile; if the core is non-empty the resource profile will be updated otherwise nothing
    7095 * happens
    7096 */
    7098 SCIP_PROFILE* profile, /**< resource profile */
    7099 int left, /**< left side of the core */
    7100 int right, /**< right side of the core */
    7101 int demand, /**< demand of the core */
    7102 int* pos, /**< pointer to store the first position were it gets infeasible */
    7103 SCIP_Bool* infeasible /**< pointer to store if the core does not fit due to capacity */
    7104 )
    7105{
    7106 assert(profile != NULL);
    7107 assert(left < right);
    7108 assert(demand >= 0);
    7109 assert(infeasible != NULL);
    7110
    7111 (*infeasible) = FALSE;
    7112 (*pos) = -1;
    7113
    7114 /* insert core into the resource profile */
    7115 SCIPdebugMessage("insert core [%d,%d] with demand %d\n", left, right, demand);
    7116
    7117 if( demand > 0 )
    7118 {
    7119 /* try to insert core into the resource profile */
    7120 SCIP_CALL( profileUpdate(profile, left, right, demand, pos, infeasible) );
    7121 }
    7122
    7123 return SCIP_OKAY;
    7124}
    7125
    7126/** subtracts the demand from the resource profile during core time */
    7128 SCIP_PROFILE* profile, /**< resource profile to use */
    7129 int left, /**< left side of the core */
    7130 int right, /**< right side of the core */
    7131 int demand /**< demand of the core */
    7132 )
    7133{
    7134 SCIP_Bool infeasible;
    7135 int pos;
    7136
    7137 assert(left < right);
    7138#ifndef NDEBUG
    7139 {
    7140 /* check if the left and right time points of the core correspond to a time point in the resource profile; this
    7141 * should be the case since we added the core before to the resource profile
    7142 */
    7143 assert(SCIPprofileFindLeft(profile, left, &pos));
    7144 assert(SCIPprofileFindLeft(profile, right, &pos));
    7145 }
    7146#endif
    7147
    7148 /* remove the core from the resource profile */
    7149 SCIPdebugMessage("delete core [%d,%d] with demand %d\n", left, right, demand);
    7150
    7151 SCIP_CALL( profileUpdate(profile, left, right, -demand, &pos, &infeasible) );
    7152 assert(!infeasible);
    7153
    7154 return SCIP_OKAY; /*lint !e438*/
    7155}
    7156
    7157/** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
    7158static
    7160 SCIP_PROFILE* profile, /**< resource profile to use */
    7161 int pos, /**< pointer to store the position in the profile to start the serch */
    7162 int lst, /**< latest start time */
    7163 int duration, /**< duration of the core */
    7164 int demand, /**< demand of the core */
    7165 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
    7166 )
    7167{
    7168 int remainingduration;
    7169 int startpos;
    7170
    7171 assert(profile != NULL);
    7172 assert(pos >= 0);
    7173 assert(pos < profile->ntimepoints);
    7174 assert(duration > 0);
    7175 assert(demand > 0);
    7176 assert(profile->loads[profile->ntimepoints-1] == 0);
    7177
    7178 remainingduration = duration;
    7179 startpos = pos;
    7180 (*infeasible) = FALSE;
    7181
    7182 if( profile->timepoints[startpos] > lst )
    7183 {
    7184 (*infeasible) = TRUE;
    7185 return pos;
    7186 }
    7187
    7188 while( pos < profile->ntimepoints - 1 )
    7189 {
    7190 if( profile->loads[pos] + demand > profile->capacity )
    7191 {
    7192 SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos], pos);
    7193 startpos = pos + 1;
    7194 remainingduration = duration;
    7195
    7196 if( profile->timepoints[startpos] > lst )
    7197 {
    7198 (*infeasible) = TRUE;
    7199 return pos;
    7200 }
    7201 }
    7202 else
    7203 remainingduration -= profile->timepoints[pos+1] - profile->timepoints[pos];
    7204
    7205 if( remainingduration <= 0 )
    7206 break;
    7207
    7208 pos++;
    7209 }
    7210
    7211 return startpos;
    7212}
    7213
    7214/** return the earliest possible starting point within the time interval [lb,ub] for a given core (given by its demand
    7215 * and duration)
    7216 */
    7218 SCIP_PROFILE* profile, /**< resource profile to use */
    7219 int est, /**< earliest starting time of the given core */
    7220 int lst, /**< latest starting time of the given core */
    7221 int duration, /**< duration of the core */
    7222 int demand, /**< demand of the core */
    7223 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
    7224 )
    7225{
    7226 SCIP_Bool found;
    7227 int pos;
    7228
    7229 assert(profile != NULL);
    7230 assert(est >= 0);
    7231 assert(est <= lst);
    7232 assert(duration >= 0);
    7233 assert(demand >= 0);
    7234 assert(infeasible != NULL);
    7235 assert(profile->ntimepoints > 0);
    7236 assert(profile->loads[profile->ntimepoints-1] == 0);
    7237
    7238 SCIPdebugMessage("profile <%p>: find earliest start time (demad %d, duration %d) [%d,%d]\n", (void*)profile, demand, duration, est, lst);
    7239
    7240 if( duration == 0 || demand == 0 )
    7241 {
    7242 *infeasible = FALSE;
    7243 return est;
    7244 }
    7245
    7246 found = SCIPprofileFindLeft(profile, est, &pos);
    7247 SCIPdebugMessage("profile <%p>: earliest start time does %s exist as time point (pos %d)\n", (void*)profile, found ? "" : "not", pos);
    7248
    7249 /* if the position is the last time point in the profile, the core can be inserted at its earliest start time */
    7250 if( pos == profile->ntimepoints - 1 )
    7251 {
    7252 (*infeasible) = FALSE;
    7253 return est;
    7254 }
    7255
    7256 if( found )
    7257 {
    7258 /* if the start time matches a time point in the profile we can just search */
    7259 assert(profile->timepoints[pos] == est);
    7260 pos = profileFindFeasibleStart(profile, pos, lst, duration, demand, infeasible);
    7261
    7262 assert(pos < profile->ntimepoints);
    7263 est = profile->timepoints[pos];
    7264 }
    7265 else if( profile->loads[pos] + demand > profile->capacity )
    7266 {
    7267 /* if the the time point left to the start time has not enough free capacity we can just search the profile
    7268 * starting from the next time point
    7269 */
    7270 assert(profile->timepoints[pos] <= est);
    7271 pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
    7272
    7273 assert(pos < profile->ntimepoints);
    7274 est = profile->timepoints[pos];
    7275 }
    7276 else
    7277 {
    7278 int remainingduration;
    7279
    7280 /* check if the core can be placed at its earliest start time */
    7281
    7282 assert(pos < profile->ntimepoints - 1);
    7283
    7284 remainingduration = duration - (profile->timepoints[pos+1] - est);
    7285 SCIPdebugMessage("remaining duration %d\n", remainingduration);
    7286
    7287 if( remainingduration <= 0 )
    7288 (*infeasible) = FALSE;
    7289 else
    7290 {
    7291 pos = profileFindFeasibleStart(profile, pos+1, profile->timepoints[pos+1], remainingduration, demand, infeasible);
    7292 SCIPdebugMessage("remaining duration can%s be processed\n", *infeasible ? "not" : "");
    7293
    7294 if( *infeasible )
    7295 {
    7296 pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
    7297
    7298 assert(pos < profile->ntimepoints);
    7299 est = profile->timepoints[pos];
    7300 }
    7301 }
    7302 }
    7303
    7304 return est;
    7305}
    7306
    7307/** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
    7308static
    7310 SCIP_PROFILE* profile, /**< resource profile to use */
    7311 int pos, /**< pointer to store the position in the profile to start the search */
    7312 int ect, /**< earliest completion time */
    7313 int duration, /**< duration of the core */
    7314 int demand, /**< demand of the core */
    7315 SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
    7316 )
    7317{
    7318 int remainingduration;
    7319 int endpos;
    7320
    7321 assert(profile != NULL);
    7322 assert(pos >= 0);
    7323 assert(pos < profile->ntimepoints);
    7324 assert(duration > 0);
    7325 assert(demand > 0);
    7326 assert(profile->ntimepoints > 0);
    7327 assert(profile->loads[profile->ntimepoints-1] == 0);
    7328
    7329 remainingduration = duration;
    7330 endpos = pos;
    7331 (*infeasible) = TRUE;
    7332
    7333 if( profile->timepoints[endpos] < ect - duration )
    7334 return pos;
    7335
    7336 while( pos > 0 )
    7337 {
    7338 if( profile->loads[pos-1] + demand > profile->capacity )
    7339 {
    7340 SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos-1], pos-1);
    7341
    7342 endpos = pos - 1;
    7343 remainingduration = duration;
    7344
    7345 if( profile->timepoints[endpos] < ect - duration )
    7346 return pos;
    7347 }
    7348 else
    7349 remainingduration -= profile->timepoints[pos] - profile->timepoints[pos-1];
    7350
    7351 if( remainingduration <= 0 )
    7352 {
    7353 *infeasible = FALSE;
    7354 break;
    7355 }
    7356
    7357 pos--;
    7358 }
    7359
    7360 return endpos;
    7361}
    7362
    7363/** return the latest possible starting point within the time interval [lb,ub] for a given core (given by its demand and
    7364 * duration)
    7365 */
    7367 SCIP_PROFILE* profile, /**< resource profile to use */
    7368 int est, /**< earliest possible start point */
    7369 int lst, /**< latest possible start point */
    7370 int duration, /**< duration of the core */
    7371 int demand, /**< demand of the core */
    7372 SCIP_Bool* infeasible /**< pointer store if the core cannot be inserted */
    7373 )
    7374{
    7375 SCIP_Bool found;
    7376 int ect;
    7377 int lct;
    7378 int pos;
    7379
    7380 assert(profile != NULL);
    7381 assert(est >= 0);
    7382 assert(est <= lst);
    7383 assert(duration >= 0);
    7384 assert(demand >= 0);
    7385 assert(infeasible != NULL);
    7386 assert(profile->ntimepoints > 0);
    7387 assert(profile->loads[profile->ntimepoints-1] == 0);
    7388
    7389 if( duration == 0 || demand == 0 )
    7390 {
    7391 *infeasible = FALSE;
    7392 return lst;
    7393 }
    7394
    7395 ect = est + duration;
    7396 lct = lst + duration;
    7397
    7398 found = SCIPprofileFindLeft(profile, lct, &pos);
    7399 SCIPdebugMessage("profile <%p>: latest completion time %d does %s exist as time point (pos %d)\n", (void*)profile, lct, found ? "" : "not", pos);
    7400
    7401 if( found )
    7402 {
    7403 /* if the start time matches a time point in the profile we can just search */
    7404 assert(profile->timepoints[pos] == lct);
    7405 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
    7406
    7407 assert(pos < profile->ntimepoints && pos >= 0);
    7408 lct = profile->timepoints[pos];
    7409 }
    7410 else if( profile->loads[pos] + demand > profile->capacity )
    7411 {
    7412 /* if the time point left to the start time has not enough free capacity we can just search the profile starting
    7413 * from the next time point
    7414 */
    7415 assert(profile->timepoints[pos] < lct);
    7416 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
    7417
    7418 assert(pos < profile->ntimepoints && pos >= 0);
    7419 lct = profile->timepoints[pos];
    7420 }
    7421 else
    7422 {
    7423 int remainingduration;
    7424
    7425 /* check if the core can be placed at its latest start time */
    7426 assert(profile->timepoints[pos] < lct);
    7427
    7428 remainingduration = duration - (lct - profile->timepoints[pos]);
    7429
    7430 if( remainingduration <= 0 )
    7431 (*infeasible) = FALSE;
    7432 else
    7433 {
    7434 pos = profileFindDownFeasibleStart(profile, pos, profile->timepoints[pos], remainingduration, demand, infeasible);
    7435
    7436 if( *infeasible )
    7437 {
    7438 pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
    7439
    7440 assert(pos < profile->ntimepoints && pos >= 0);
    7441 lct = profile->timepoints[pos];
    7442 }
    7443 }
    7444 }
    7445
    7446 return lct - duration;
    7447}
    7448
    7449/*
    7450 * Directed graph
    7451 */
    7452
    7453/** creates directed graph structure */
    7455 SCIP_DIGRAPH** digraph, /**< pointer to store the created directed graph */
    7456 BMS_BLKMEM* blkmem, /**< block memory to store the data */
    7457 int nnodes /**< number of nodes */
    7458 )
    7459{
    7460 assert(digraph != NULL);
    7461 assert(blkmem != NULL);
    7462 assert(nnodes > 0);
    7463
    7464 /* allocate memory for the graph and the arrays storing arcs and data */
    7465 SCIP_ALLOC( BMSallocBlockMemory(blkmem, digraph) );
    7466 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successors, nnodes) );
    7467 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->arcdata, nnodes) );
    7468 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successorssize, nnodes) );
    7469 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nsuccessors, nnodes) );
    7470 SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nodedata, nnodes) );
    7471
    7472 /* store number of nodes */
    7473 (*digraph)->nnodes = nnodes;
    7474
    7475 /* at the beginning, no components are stored */
    7476 (*digraph)->blkmem = blkmem;
    7477 (*digraph)->ncomponents = 0;
    7478 (*digraph)->componentstartsize = 0;
    7479 (*digraph)->components = NULL;
    7480 (*digraph)->componentstarts = NULL;
    7481
    7482 /* all nodes are initially considered as non-articulation points */
    7483 (*digraph)->narticulations = -1;
    7484 (*digraph)->articulations = NULL;
    7485 (*digraph)->articulationscheck = FALSE;
    7486
    7487 return SCIP_OKAY;
    7488}
    7489
    7490/** resize directed graph structure */
    7492 SCIP_DIGRAPH* digraph, /**< directed graph */
    7493 int nnodes /**< new number of nodes */
    7494 )
    7495{
    7496 int n;
    7497 assert(digraph != NULL);
    7498 assert(digraph->blkmem != NULL);
    7499
    7500 /* check if the digraph has already a proper size */
    7501 if( nnodes <= digraph->nnodes )
    7502 return SCIP_OKAY;
    7503
    7504 /* reallocate memory for increasing the arrays storing arcs and data */
    7505 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successors, digraph->nnodes, nnodes) );
    7506 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->arcdata, digraph->nnodes, nnodes) );
    7507 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successorssize, digraph->nnodes, nnodes) );
    7508 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nsuccessors, digraph->nnodes, nnodes) );
    7509 SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nodedata, digraph->nnodes, nnodes) );
    7510
    7511 /* initialize the new node data structures */
    7512 for( n = digraph->nnodes; n < nnodes; ++n )
    7513 {
    7514 digraph->nodedata[n] = NULL;
    7515 digraph->arcdata[n] = NULL;
    7516 digraph->successors[n] = NULL;
    7517 digraph->successorssize[n] = 0;
    7518 digraph->nsuccessors[n] = 0;
    7519 }
    7520
    7521 /* store the new number of nodes */
    7522 digraph->nnodes = nnodes;
    7523
    7524 return SCIP_OKAY;
    7525}
    7526
    7527/** copies directed graph structure
    7528 *
    7529 * @note The data in nodedata is copied verbatim. This possibly has to be adapted by the user.
    7530 */
    7532 SCIP_DIGRAPH** targetdigraph, /**< pointer to store the copied directed graph */
    7533 SCIP_DIGRAPH* sourcedigraph, /**< source directed graph */
    7534 BMS_BLKMEM* targetblkmem /**< block memory to store the target block memory, or NULL to use the same
    7535 * the same block memory as used for the \p sourcedigraph */
    7536 )
    7537{
    7538 int ncomponents;
    7539 int nnodes;
    7540 int i;
    7541 SCIP_Bool articulationscheck;
    7542
    7543 assert(sourcedigraph != NULL);
    7544 assert(targetdigraph != NULL);
    7545
    7546 /* use the source digraph block memory if not specified otherwise */
    7547 if( targetblkmem == NULL )
    7548 targetblkmem = sourcedigraph->blkmem;
    7549
    7550 assert(targetblkmem != NULL);
    7551
    7552 SCIP_ALLOC( BMSallocBlockMemory(targetblkmem, targetdigraph) );
    7553
    7554 nnodes = sourcedigraph->nnodes;
    7555 ncomponents = sourcedigraph->ncomponents;
    7556 articulationscheck = sourcedigraph->articulationscheck;
    7557 (*targetdigraph)->nnodes = nnodes;
    7558 (*targetdigraph)->ncomponents = ncomponents;
    7559 (*targetdigraph)->blkmem = targetblkmem;
    7560
    7561 /* copy arcs and data */
    7562 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->successors, nnodes) );
    7563 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->arcdata, nnodes) );
    7564 SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->nodedata, nnodes) );
    7565
    7566 /* copy lists of successors and arc data */
    7567 for( i = 0; i < nnodes; ++i )
    7568 {
    7569 if( sourcedigraph->nsuccessors[i] > 0 )
    7570 {
    7571 assert(sourcedigraph->successors[i] != NULL);
    7572 assert(sourcedigraph->arcdata[i] != NULL);
    7573
    7574 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->successors[i]),
    7575 sourcedigraph->successors[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
    7576 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->arcdata[i]),
    7577 sourcedigraph->arcdata[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
    7578 }
    7579 /* copy node data - careful if these are pointers to some information -> need to be copied by hand */
    7580 (*targetdigraph)->nodedata[i] = sourcedigraph->nodedata[i];
    7581 }
    7582
    7583 /* use nsuccessors as size to save memory */
    7584 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->successorssize, sourcedigraph->nsuccessors, nnodes) );
    7585 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->nsuccessors, sourcedigraph->nsuccessors, nnodes) );
    7586
    7587 /* copy component data */
    7588 if( ncomponents > 0 )
    7589 {
    7590 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->components, sourcedigraph->components,
    7591 sourcedigraph->componentstarts[ncomponents]) );
    7592 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->componentstarts,
    7593 sourcedigraph->componentstarts,ncomponents + 1) ); /*lint !e776*/
    7594 (*targetdigraph)->componentstartsize = ncomponents + 1;
    7595 }
    7596 else
    7597 {
    7598 (*targetdigraph)->components = NULL;
    7599 (*targetdigraph)->componentstarts = NULL;
    7600 (*targetdigraph)->componentstartsize = 0;
    7601 }
    7602
    7603 /* copy the articulation point information if it has been computed and is up-to-date */
    7604 if( articulationscheck )
    7605 {
    7606 SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->articulations, sourcedigraph->articulations, sourcedigraph->narticulations) );
    7607 (*targetdigraph)->narticulations = sourcedigraph->narticulations;
    7608 (*targetdigraph)->articulationscheck = TRUE;
    7609 }
    7610 else
    7611 {
    7612 (*targetdigraph)->narticulations = -1;
    7613 (*targetdigraph)->articulations = NULL;
    7614 (*targetdigraph)->articulationscheck = FALSE;
    7615 }
    7616
    7617 return SCIP_OKAY;
    7618}
    7619
    7620/** sets the sizes of the successor lists for the nodes in a directed graph and allocates memory for the lists */
    7622 SCIP_DIGRAPH* digraph, /**< directed graph */
    7623 int* sizes /**< sizes of the successor lists */
    7624 )
    7625{
    7626 int i;
    7627 BMS_BLKMEM* blkmem;
    7628
    7629 assert(digraph != NULL);
    7630 assert(digraph->nnodes > 0);
    7631 blkmem = digraph->blkmem;
    7632
    7633 for( i = 0; i < digraph->nnodes; ++i )
    7634 {
    7635 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[i], sizes[i]) ); /*lint !e866*/
    7636 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[i], sizes[i]) ); /*lint !e866*/
    7637 digraph->successorssize[i] = sizes[i];
    7638 digraph->nsuccessors[i] = 0;
    7639 }
    7640
    7641 return SCIP_OKAY;
    7642}
    7643
    7644/** frees given directed graph structure */
    7646 SCIP_DIGRAPH** digraph /**< pointer to the directed graph */
    7647 )
    7648{
    7649 int i;
    7650 BMS_BLKMEM* blkmem;
    7651 SCIP_DIGRAPH* digraphptr;
    7652
    7653 assert(digraph != NULL);
    7654 assert(*digraph != NULL);
    7655 assert((*digraph)->blkmem != NULL);
    7656
    7657 blkmem = (*digraph)->blkmem;
    7658 digraphptr = *digraph;
    7659
    7660 /* free arrays storing the successor nodes and arc data */
    7661 for( i = digraphptr->nnodes - 1; i >= 0; --i )
    7662 {
    7663 BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->successors[i], digraphptr->successorssize[i]);
    7664 BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->arcdata[i], digraphptr->successorssize[i]);
    7665 }
    7666
    7667 /* free components structure */
    7668 SCIPdigraphFreeComponents(digraphptr);
    7669 assert(digraphptr->ncomponents == 0);
    7670 assert(digraphptr->componentstartsize == 0);
    7671 assert(digraphptr->components == NULL);
    7672 assert(digraphptr->componentstarts == NULL);
    7673
    7674 /* free the articulation points structure if it has been computed*/
    7675 if( digraphptr->articulationscheck )
    7676 BMSfreeBlockMemoryArray(blkmem, &digraphptr->articulations, digraphptr->narticulations);
    7677
    7678 /* free directed graph data structure */
    7679 BMSfreeBlockMemoryArray(blkmem, &digraphptr->nodedata, digraphptr->nnodes);
    7680 BMSfreeBlockMemoryArray(blkmem, &digraphptr->successorssize, digraphptr->nnodes);
    7681 BMSfreeBlockMemoryArray(blkmem, &digraphptr->nsuccessors, digraphptr->nnodes);
    7682 BMSfreeBlockMemoryArray(blkmem, &digraphptr->successors, digraphptr->nnodes);
    7683 BMSfreeBlockMemoryArray(blkmem, &digraphptr->arcdata, digraphptr->nnodes);
    7684
    7685 BMSfreeBlockMemory(blkmem, digraph);
    7686}
    7687
    7688#define STARTSUCCESSORSSIZE 5
    7689
    7690/** ensures that successors array of one node in a directed graph is big enough */
    7691static
    7693 SCIP_DIGRAPH* digraph, /**< directed graph */
    7694 int idx, /**< index for which the size is ensured */
    7695 int newsize /**< needed size */
    7696 )
    7697{
    7698 BMS_BLKMEM* blkmem;
    7699
    7700 assert(digraph != NULL);
    7701 assert(digraph->blkmem != NULL);
    7702 assert(idx >= 0);
    7703 assert(idx < digraph->nnodes);
    7704 assert(newsize > 0);
    7705 assert(digraph->successorssize[idx] == 0 || digraph->successors[idx] != NULL);
    7706 assert(digraph->successorssize[idx] == 0 || digraph->arcdata[idx] != NULL);
    7707
    7708 blkmem = digraph->blkmem;
    7709
    7710 /* check whether array is big enough, and realloc, if needed */
    7711 if( newsize > digraph->successorssize[idx] )
    7712 {
    7713 if( digraph->successors[idx] == NULL )
    7714 {
    7715 assert(digraph->arcdata[idx] == NULL);
    7716 digraph->successorssize[idx] = STARTSUCCESSORSSIZE;
    7717 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx]) ); /*lint !e866*/
    7718 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx]) ); /*lint !e866*/
    7719 }
    7720 else
    7721 {
    7722 newsize = MAX(newsize, 2 * digraph->successorssize[idx]);
    7723 assert(digraph->arcdata[idx] != NULL);
    7724 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
    7725 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
    7726 digraph->successorssize[idx] = newsize;
    7727 }
    7728 }
    7729
    7730 assert(newsize <= digraph->successorssize[idx]);
    7731
    7732 return SCIP_OKAY;
    7733}
    7734
    7735/** add (directed) arc and a related data to the directed graph structure
    7736 *
    7737 * @note if the arc is already contained, it is added a second time
    7738 */
    7740 SCIP_DIGRAPH* digraph, /**< directed graph */
    7741 int startnode, /**< start node of the arc */
    7742 int endnode, /**< start node of the arc */
    7743 void* data /**< data that should be stored for the arc; or NULL */
    7744 )
    7745{
    7746 assert(digraph != NULL);
    7747 assert(startnode >= 0);
    7748 assert(endnode >= 0);
    7749 assert(startnode < digraph->nnodes);
    7750 assert(endnode < digraph->nnodes);
    7751
    7752 SCIP_CALL( ensureSuccessorsSize(digraph, startnode, digraph->nsuccessors[startnode] + 1) );
    7753
    7754 /* add arc */
    7755 digraph->successors[startnode][digraph->nsuccessors[startnode]] = endnode;
    7756 digraph->arcdata[startnode][digraph->nsuccessors[startnode]] = data;
    7757 digraph->nsuccessors[startnode]++;
    7758
    7759 /* the articulation points are not up-to-date */
    7760 digraph->articulationscheck = FALSE;
    7761
    7762 return SCIP_OKAY;
    7763}
    7764
    7765/** add (directed) arc to the directed graph structure, if it is not contained, yet
    7766 *
    7767 * @note if there already exists an arc from startnode to endnode, the new arc is not added,
    7768 * even if its data is different
    7769 */
    7771 SCIP_DIGRAPH* digraph, /**< directed graph */
    7772 int startnode, /**< start node of the arc */
    7773 int endnode, /**< start node of the arc */
    7774 void* data /**< data that should be stored for the arc; or NULL */
    7775 )
    7776{
    7777 int nsuccessors;
    7778 int i;
    7779
    7780 assert(digraph != NULL);
    7781 assert(startnode >= 0);
    7782 assert(endnode >= 0);
    7783 assert(startnode < digraph->nnodes);
    7784 assert(endnode < digraph->nnodes);
    7785
    7786 nsuccessors = digraph->nsuccessors[startnode];
    7787
    7788 /* search for the arc in existing arcs */
    7789 for( i = 0; i < nsuccessors; ++i )
    7790 if( digraph->successors[startnode][i] == endnode )
    7791 return SCIP_OKAY;
    7792
    7793 SCIP_CALL( ensureSuccessorsSize(digraph, startnode, nsuccessors + 1) );
    7794
    7795 /* add arc */
    7796 digraph->successors[startnode][nsuccessors] = endnode;
    7797 digraph->arcdata[startnode][nsuccessors] = data;
    7798 ++(digraph->nsuccessors[startnode]);
    7799
    7800 /* the articulation points are not up-to-date */
    7801 digraph->articulationscheck = FALSE;
    7802
    7803 return SCIP_OKAY;
    7804}
    7805
    7806/** sets the number of successors to a given value */
    7808 SCIP_DIGRAPH* digraph, /**< directed graph */
    7809 int node, /**< node for which the number of successors has to be changed */
    7810 int nsuccessors /**< new number of successors */
    7811 )
    7812{
    7813 assert(digraph != NULL);
    7814 assert(node >= 0);
    7815 assert(node < digraph->nnodes);
    7816
    7817 digraph->nsuccessors[node] = nsuccessors;
    7818
    7819 return SCIP_OKAY;
    7820}
    7821
    7822/** returns the number of nodes of the given digraph */
    7824 SCIP_DIGRAPH* digraph /**< directed graph */
    7825 )
    7826{
    7827 assert(digraph != NULL);
    7828
    7829 return digraph->nnodes;
    7830}
    7831
    7832/** returns the node data, or NULL if no data exist */
    7834 SCIP_DIGRAPH* digraph, /**< directed graph */
    7835 int node /**< node for which the node data is returned */
    7836 )
    7837{
    7838 assert(digraph != NULL);
    7839 assert(node >= 0);
    7840 assert(node < digraph->nnodes);
    7841
    7842 return digraph->nodedata[node];
    7843}
    7844
    7845/** sets the node data
    7846 *
    7847 * @note The old user pointer is not freed. This has to be done by the user
    7848 */
    7850 SCIP_DIGRAPH* digraph, /**< directed graph */
    7851 void* dataptr, /**< user node data pointer, or NULL */
    7852 int node /**< node for which the node data is returned */
    7853 )
    7854{
    7855 assert(digraph != NULL);
    7856 assert(node >= 0);
    7857 assert(node < digraph->nnodes);
    7858
    7859 digraph->nodedata[node] = dataptr;
    7860}
    7861
    7862/** returns the total number of arcs in the given digraph */
    7864 SCIP_DIGRAPH* digraph /**< directed graph */
    7865 )
    7866{
    7867 int i;
    7868 int narcs;
    7869
    7870 assert(digraph != NULL);
    7871
    7872 /* count number of arcs */
    7873 narcs = 0;
    7874 for( i = 0; i < digraph->nnodes; ++i )
    7875 narcs += digraph->nsuccessors[i];
    7876
    7877 return narcs;
    7878}
    7879
    7880/** returns the number of successor nodes of the given node */
    7882 SCIP_DIGRAPH* digraph, /**< directed graph */
    7883 int node /**< node for which the number of outgoing arcs is returned */
    7884 )
    7885{
    7886 assert(digraph != NULL);
    7887 assert(node >= 0);
    7888 assert(node < digraph->nnodes);
    7889 assert(digraph->nsuccessors[node] >= 0);
    7890 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
    7891
    7892 return digraph->nsuccessors[node];
    7893}
    7894
    7895/** returns the array of indices of the successor nodes; this array must not be changed from outside */
    7897 SCIP_DIGRAPH* digraph, /**< directed graph */
    7898 int node /**< node for which the array of outgoing arcs is returned */
    7899 )
    7900{
    7901 assert(digraph != NULL);
    7902 assert(node >= 0);
    7903 assert(node < digraph->nnodes);
    7904 assert(digraph->nsuccessors[node] >= 0);
    7905 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
    7906 assert((digraph->nsuccessors[node] == 0) || (digraph->successors[node] != NULL));
    7907
    7908 return digraph->successors[node];
    7909}
    7910
    7911/** returns the array of data corresponding to the arcs originating at the given node, or NULL if no data exist; this
    7912 * array must not be changed from outside
    7913 */
    7915 SCIP_DIGRAPH* digraph, /**< directed graph */
    7916 int node /**< node for which the data corresponding to the outgoing arcs is returned */
    7917 )
    7918{
    7919 assert(digraph != NULL);
    7920 assert(node >= 0);
    7921 assert(node < digraph->nnodes);
    7922 assert(digraph->nsuccessors[node] >= 0);
    7923 assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
    7924 assert(digraph->arcdata != NULL);
    7925
    7926 return digraph->arcdata[node];
    7927}
    7928
    7929/** performs depth-first-search in the given directed graph from the given start node */
    7930static
    7932 SCIP_DIGRAPH* digraph, /**< directed graph */
    7933 int startnode, /**< node to start the depth-first-search */
    7934 SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
    7935 int* dfsstack, /**< array of size number of nodes to store the stack;
    7936 * only needed for performance reasons */
    7937 int* stackadjvisited, /**< array of size number of nodes to store the number of adjacent nodes already visited
    7938 * for each node on the stack; only needed for performance reasons */
    7939 int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse dfs order */
    7940 int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at startnode */
    7941 )
    7942{
    7943 int stackidx;
    7944
    7945 assert(digraph != NULL);
    7946 assert(startnode >= 0);
    7947 assert(startnode < digraph->nnodes);
    7948 assert(visited != NULL);
    7949 assert(visited[startnode] == FALSE);
    7950 assert(dfsstack != NULL);
    7951 assert(dfsnodes != NULL);
    7952 assert(ndfsnodes != NULL);
    7953
    7954 /* put start node on the stack */
    7955 dfsstack[0] = startnode;
    7956 stackadjvisited[0] = 0;
    7957 stackidx = 0;
    7958
    7959 while( stackidx >= 0 )
    7960 {
    7961 int currnode;
    7962 int sadv;
    7963
    7964 /* get next node from stack */
    7965 currnode = dfsstack[stackidx];
    7966
    7967 sadv = stackadjvisited[stackidx];
    7968 assert( 0 <= sadv && sadv <= digraph->nsuccessors[currnode] );
    7969
    7970 /* mark current node as visited */
    7971 assert( visited[currnode] == (sadv > 0) );
    7972 visited[currnode] = TRUE;
    7973
    7974 /* iterate through the successor list until we reach unhandled node */
    7975 while( sadv < digraph->nsuccessors[currnode] && visited[digraph->successors[currnode][sadv]] )
    7976 ++sadv;
    7977
    7978 /* the current node was completely handled, remove it from stack */
    7979 if( sadv == digraph->nsuccessors[currnode] )
    7980 {
    7981 --stackidx;
    7982
    7983 /* store node in the sorted nodes array */
    7984 dfsnodes[(*ndfsnodes)++] = currnode;
    7985 }
    7986 /* handle next unhandled successor node */
    7987 else
    7988 {
    7989 assert( ! visited[digraph->successors[currnode][sadv]] );
    7990
    7991 /* store current stackadjvisted index */
    7992 stackadjvisited[stackidx] = sadv + 1;
    7993
    7994 /* put the successor node onto the stack */
    7995 ++stackidx;
    7996 dfsstack[stackidx] = digraph->successors[currnode][sadv];
    7997 stackadjvisited[stackidx] = 0;
    7998 assert( stackidx < digraph->nnodes );
    7999 }
    8000 }
    8001}
    8002
    8003/** checks for articulation points in a given directed graph through a recursive depth-first-search.
    8004 * starts from a given start node and keeps track of the nodes' discovery time in search for back edges.
    8005 *
    8006 * @note an articulation point is a node whose removal disconnects a connected graph or increases
    8007 * the number of connected components in a disconnected graph
    8008 */
    8009static
    8011 SCIP_DIGRAPH* digraph, /**< directed graph */
    8012 int startnode, /**< node to start the depth-first-search */
    8013 SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
    8014 int* tdisc, /**< array of size number of nodes to store each node's discovery time */
    8015 int* mindisc, /**< array of size number of nodes to store the discovery time of the earliest discovered vertex
    8016 * to which startnode (or any node in the subtree rooted at it) is having a back edge */
    8017 int* parent, /**< array to store the parent of each node in the DFS tree */
    8018 SCIP_Bool* articulationflag, /**< array to mark whether a node is identified as an articulation point */
    8019 int time /**< current discovery time in the DFS */
    8020 )
    8021{
    8022 int n;
    8023 int nchildren = 0;
    8024 int nsucc;
    8025 int* succnodes;
    8026
    8027 assert(digraph != NULL);
    8028 assert(startnode >= 0);
    8029 assert(startnode < digraph->nnodes);
    8030 assert(visited != NULL);
    8031 assert(visited[startnode] == FALSE);
    8032 assert(tdisc != NULL);
    8033 assert(mindisc != NULL);
    8034 assert(parent != NULL);
    8035 assert(articulationflag != NULL);
    8036 assert(time >= 0);
    8037
    8038 nsucc = (int) SCIPdigraphGetNSuccessors(digraph, startnode);
    8039 succnodes = (int*) SCIPdigraphGetSuccessors(digraph, startnode);
    8040 visited[startnode] = TRUE;
    8041 tdisc[startnode] = time + 1;
    8042 mindisc[startnode] = time + 1;
    8043
    8044 /* process all the adjacent nodes to startnode */
    8045 for( n = 0; n < nsucc; ++n)
    8046 {
    8047 if( !visited[succnodes[n]] )
    8048 {
    8049 parent[succnodes[n]] = startnode;
    8050 ++nchildren;
    8051 findArticulationPointsUtil(digraph, succnodes[n], visited, tdisc, mindisc, parent, articulationflag, time + 1);
    8052 /* updated the mindisc of startnode when the DFS concludes for node n*/
    8053 mindisc[startnode] = MIN(mindisc[startnode], mindisc[succnodes[n]]);
    8054
    8055 /* the root is an articulation point if it has more than 2 children*/
    8056 if( parent[startnode] == -1 && nchildren > 1 )
    8057 articulationflag[startnode] = TRUE;
    8058 /* a vertex startnode is an articulation point if it is not the root and
    8059 * there is no back edge from the subtree rooted at child n to any of the ancestors of startnode */
    8060 if( parent[startnode] > -1 && mindisc[succnodes[n]] >= tdisc[startnode] )
    8061 articulationflag[startnode] = TRUE;
    8062 }
    8063 else
    8064 {
    8065 if( parent[startnode] != succnodes[n] )
    8066 mindisc[startnode] = MIN(mindisc[startnode], tdisc[succnodes[n]]);
    8067 }
    8068 }
    8069
    8070 if( articulationflag[startnode] )
    8071 ++digraph->narticulations;
    8072}
    8073
    8074/** identifies the articulation points in a given directed graph
    8075 * uses the helper recursive function findArticulationPointsUtil
    8076 */
    8078 SCIP_DIGRAPH* digraph, /**< directed graph */
    8079 int** articulations, /**< array to store the sorted node indices of the computed articulation points, or NULL */
    8080 int* narticulations /**< number of the computed articulation points, or NULL */
    8081 )
    8082{
    8083 SCIP_RETCODE retcode = SCIP_OKAY;
    8084 BMS_BLKMEM* blkmem;
    8085 SCIP_Bool* visited = NULL;
    8086 SCIP_Bool* articulationflag = NULL;
    8087 int* tdisc = NULL;
    8088 int* mindisc = NULL;
    8089 int* parent = NULL;
    8090 int n;
    8091 int articulationidx = 0;
    8092 int time = 0;
    8093
    8094 assert(digraph != NULL);
    8095 assert(digraph->nnodes > 0);
    8096
    8097 /* Only perform the computation if the articulation points are NOT up-to-date */
    8098 if( !digraph->articulationscheck )
    8099 {
    8100 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&visited, digraph->nnodes), TERMINATE );
    8101 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&tdisc, digraph->nnodes), TERMINATE );
    8102 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&mindisc, digraph->nnodes), TERMINATE );
    8103 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&parent, digraph->nnodes), TERMINATE );
    8104 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&articulationflag, digraph->nnodes), TERMINATE );
    8105
    8106 assert(digraph->blkmem != NULL);
    8107 blkmem = digraph->blkmem;
    8108
    8109 if( digraph->narticulations >= 0 ) /* case: articulations have already been computed but not up-to-date */
    8110 BMSfreeBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations);
    8111
    8112 /* Initialize the no. of articulation points ahead of the recursive computation */
    8113 digraph->narticulations = 0;
    8114
    8115 for( n = 0; n < digraph->nnodes; ++n )
    8116 {
    8117 visited[n] = FALSE;
    8118 parent[n] = -1;
    8119 articulationflag[n] = FALSE;
    8120 }
    8121
    8122 /* the function is called on every unvisited node in the graph to cover the disconnected graph case */
    8123 for( n = 0; n < digraph->nnodes; ++n )
    8124 {
    8125 if( !visited[n] )
    8126 findArticulationPointsUtil(digraph, n, visited, tdisc, mindisc, parent, articulationflag, time);
    8127 }
    8128
    8129 /* allocation of the block memory for the node indices of the articulation points*/
    8130 SCIP_ALLOC_TERMINATE( retcode, BMSallocBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations), TERMINATE );
    8131
    8132 for( n = 0; n < digraph->nnodes; ++n )
    8133 {
    8134 if( articulationflag[n] )
    8135 {
    8136 digraph->articulations[articulationidx] = n;
    8137 ++articulationidx;
    8138 }
    8139 }
    8140 }
    8141
    8142 if( articulations != NULL )
    8143 (*articulations) = digraph->articulations;
    8144 if( narticulations != NULL )
    8145 (*narticulations) = digraph->narticulations;
    8146
    8147 /* the articulation points are now up-to-date */
    8148 digraph->articulationscheck = TRUE;
    8149
    8150TERMINATE:
    8151 BMSfreeMemoryArrayNull(&articulationflag);
    8152 BMSfreeMemoryArrayNull(&parent);
    8153 BMSfreeMemoryArrayNull(&mindisc);
    8154 BMSfreeMemoryArrayNull(&tdisc);
    8155 BMSfreeMemoryArrayNull(&visited);
    8156
    8157 return retcode;
    8158}
    8159
    8160/** Compute undirected connected components on the given graph.
    8161 *
    8162 * @note For each arc, its reverse is added, so the graph does not need to be the directed representation of an
    8163 * undirected graph.
    8164 */
    8166 SCIP_DIGRAPH* digraph, /**< directed graph */
    8167 int minsize, /**< all components with less nodes are ignored */
    8168 int* components, /**< array with as many slots as there are nodes in the directed graph
    8169 * to store for each node the component to which it belongs
    8170 * (components are numbered 0 to ncomponents - 1); or NULL, if components
    8171 * are accessed one-by-one using SCIPdigraphGetComponent() */
    8172 int* ncomponents /**< pointer to store the number of components; or NULL, if the
    8173 * number of components is accessed by SCIPdigraphGetNComponents() */
    8174 )
    8175{
    8176 BMS_BLKMEM* blkmem;
    8177 SCIP_Bool* visited;
    8178 int* ndirectedsuccessors;
    8179 int* stackadjvisited;
    8180 int* dfsstack;
    8181 int ndfsnodes;
    8182 int compstart;
    8183 int v;
    8184 int i;
    8185 int j;
    8186
    8187 SCIP_RETCODE retcode = SCIP_OKAY;
    8188
    8189 assert(digraph != NULL);
    8190 assert(digraph->nnodes > 0);
    8191 assert(digraph->blkmem != NULL);
    8192
    8193 blkmem = digraph->blkmem;
    8194
    8195 /* first free the old components */
    8196 if( digraph->ncomponents > 0 )
    8197 {
    8199 }
    8200
    8201 digraph->ncomponents = 0;
    8202 digraph->componentstartsize = 10;
    8203
    8204 /* storage to hold components is stored in block memory */
    8205 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes) );
    8207
    8208 /* allocate temporary arrays */
    8209 SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
    8210 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
    8211 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
    8212 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&ndirectedsuccessors, digraph->nnodes), TERMINATE );
    8213
    8214 digraph->componentstarts[0] = 0;
    8215
    8216 /* store the number of directed arcs per node */
    8217 BMScopyMemoryArray(ndirectedsuccessors, digraph->nsuccessors, digraph->nnodes);
    8218
    8219 /* add reverse arcs to the graph */
    8220 for( i = digraph->nnodes - 1; i >= 0; --i )
    8221 {
    8222 for( j = 0; j < ndirectedsuccessors[i]; ++j )
    8223 {
    8224 SCIP_CALL_TERMINATE( retcode, SCIPdigraphAddArc(digraph, digraph->successors[i][j], i, NULL), TERMINATE );
    8225 }
    8226 }
    8227
    8228 for( v = 0; v < digraph->nnodes; ++v )
    8229 {
    8230 if( visited[v] )
    8231 continue;
    8232
    8233 compstart = digraph->componentstarts[digraph->ncomponents];
    8234 ndfsnodes = 0;
    8235 depthFirstSearch(digraph, v, visited, dfsstack, stackadjvisited,
    8236 &digraph->components[compstart], &ndfsnodes);
    8237
    8238 /* forget about this component if it is too small */
    8239 if( ndfsnodes >= minsize )
    8240 {
    8241 digraph->ncomponents++;
    8242
    8243 /* enlarge componentstartsize array, if needed */
    8244 if( digraph->ncomponents >= digraph->componentstartsize )
    8245 {
    8246 int newsize;
    8247
    8248 newsize = 2 * digraph->componentstartsize;
    8249 assert(digraph->ncomponents < newsize);
    8250
    8251 SCIP_ALLOC_TERMINATE( retcode, BMSreallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize, newsize), TERMINATE );
    8252 digraph->componentstartsize = newsize;
    8253 }
    8254 digraph->componentstarts[digraph->ncomponents] = compstart + ndfsnodes;
    8255
    8256 /* store component number for contained nodes if array was given */
    8257 if( components != NULL )
    8258 {
    8259 for( i = digraph->componentstarts[digraph->ncomponents] - 1; i >= compstart; --i )
    8260 {
    8261 components[digraph->components[i]] = digraph->ncomponents - 1;
    8262 }
    8263 }
    8264 }
    8265 }
    8266
    8267 /* restore the number of directed arcs per node */
    8268 BMScopyMemoryArray(digraph->nsuccessors, ndirectedsuccessors, digraph->nnodes);
    8269 BMSclearMemoryArray(visited, digraph->nnodes);
    8270
    8271 /* return number of components, if the pointer was given */
    8272 if( ncomponents != NULL )
    8273 (*ncomponents) = digraph->ncomponents;
    8274
    8275TERMINATE:
    8276 if( retcode != SCIP_OKAY )
    8277 {
    8279 }
    8280 /* coverity[uninit_use_in_call] */
    8281 BMSfreeMemoryArrayNull(&ndirectedsuccessors);
    8282 BMSfreeMemoryArrayNull(&stackadjvisited);
    8283 BMSfreeMemoryArrayNull(&dfsstack);
    8284 BMSfreeMemoryArrayNull(&visited);
    8285
    8286 return retcode;
    8287}
    8288
    8289/** Performs an (almost) topological sort on the undirected components of the given directed graph. The undirected
    8290 * components should be computed before using SCIPdigraphComputeUndirectedComponents().
    8291 *
    8292 * @note In general a topological sort is not unique. Note, that there might be directed cycles, that are randomly
    8293 * broken, which is the reason for having only almost topologically sorted arrays.
    8294 */
    8296 SCIP_DIGRAPH* digraph /**< directed graph */
    8297 )
    8298{
    8299 SCIP_Bool* visited = NULL;
    8300 int* comps;
    8301 int* compstarts;
    8302 int* stackadjvisited = NULL;
    8303 int* dfsstack = NULL;
    8304 int* dfsnodes = NULL;
    8305 int ndfsnodes;
    8306 int ncomps;
    8307 int i;
    8308 int j;
    8309 int k;
    8310 int endidx;
    8311 SCIP_RETCODE retcode = SCIP_OKAY;
    8312
    8313 assert(digraph != NULL);
    8314
    8315 ncomps = digraph->ncomponents;
    8316 comps = digraph->components;
    8317 compstarts = digraph->componentstarts;
    8318
    8319 SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
    8320 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsnodes, digraph->nnodes), TERMINATE );
    8321 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
    8322 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
    8323
    8324 /* sort the components (almost) topologically */
    8325 for( i = 0; i < ncomps; ++i )
    8326 {
    8327 endidx = compstarts[i+1] - 1;
    8328 ndfsnodes = 0;
    8329 for( j = compstarts[i]; j < compstarts[i+1]; ++j )
    8330 {
    8331 if( visited[comps[j]] )
    8332 continue;
    8333
    8334 /* perform depth first search, nodes visited in this call are appended to the list dfsnodes in reverse
    8335 * dfs order, after the nodes already contained;
    8336 * so at every point in time, the nodes in dfsnode are in reverse (almost) topological order
    8337 */
    8338 depthFirstSearch(digraph, comps[j], visited, dfsstack, stackadjvisited, dfsnodes, &ndfsnodes);
    8339 }
    8340 assert(endidx - ndfsnodes == compstarts[i] - 1);
    8341
    8342 /* copy reverse (almost) topologically sorted array of nodes reached by the dfs searches;
    8343 * reverse their order to get an (almost) topologically sort
    8344 */
    8345 for( k = 0; k < ndfsnodes; ++k )
    8346 {
    8347 digraph->components[endidx - k] = dfsnodes[k];
    8348 }
    8349 }
    8350
    8351TERMINATE:
    8352 BMSfreeMemoryArrayNull(&stackadjvisited);
    8353 BMSfreeMemoryArrayNull(&dfsstack);
    8354 BMSfreeMemoryArrayNull(&dfsnodes);
    8355 BMSfreeMemoryArrayNull(&visited);
    8356
    8357 return retcode;
    8358}
    8359
    8360/** returns the number of previously computed undirected components for the given directed graph */
    8362 SCIP_DIGRAPH* digraph /**< directed graph */
    8363 )
    8364{
    8365 assert(digraph != NULL);
    8366 assert(digraph->componentstartsize > 0); /* components should have been computed */
    8367
    8368 return digraph->ncomponents;
    8369}
    8370
    8371/** Returns the previously computed undirected component of the given number for the given directed graph.
    8372 * If the components were sorted using SCIPdigraphTopoSortComponents(), the component is (almost) topologically sorted.
    8373 */
    8375 SCIP_DIGRAPH* digraph, /**< directed graph */
    8376 int compidx, /**< number of the component to return */
    8377 int** nodes, /**< pointer to store the nodes in the component; or NULL, if not needed */
    8378 int* nnodes /**< pointer to store the number of nodes in the component;
    8379 * or NULL, if not needed */
    8380 )
    8381{
    8382 assert(digraph != NULL);
    8383 assert(compidx >= 0);
    8384 assert(compidx < digraph->ncomponents);
    8385 assert(nodes != NULL || nnodes != NULL);
    8386
    8387 if( nodes != NULL )
    8388 (*nodes) = &(digraph->components[digraph->componentstarts[compidx]]);
    8389 if( nnodes != NULL )
    8390 (*nnodes) = digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx];
    8391}
    8392
    8393/* Performs Tarjan's algorithm for a given directed graph to obtain the strongly connected components
    8394 * which are reachable from a given node.
    8395 */
    8396static
    8398 SCIP_DIGRAPH* digraph, /**< directed graph */
    8399 int v, /**< node to start the algorithm */
    8400 int* lowlink, /**< array to store lowlink values */
    8401 int* dfsidx, /**< array to store dfs indices */
    8402 int* stack, /**< array to store a stack */
    8403 int* stacksize, /**< pointer to store the size of the stack */
    8404 SCIP_Bool* unprocessed, /**< array to store which node is unprocessed yet */
    8405 SCIP_Bool* nodeinstack, /**< array to store which nodes are in the stack */
    8406 int* maxdfs, /**< pointer to store index for DFS */
    8407 int* strongcomponents, /**< array to store for each node the strongly connected
    8408 * component to which it belongs (components are
    8409 * numbered 0 to nstrongcomponents - 1); */
    8410 int* nstrongcomponents, /**< pointer to store the number of computed components so far */
    8411 int* strongcompstartidx, /**< array to store the start index of the computed components */
    8412 int* nstorednodes /**< pointer to store the number of already stored nodes */
    8413 )
    8414{
    8415 int i;
    8416
    8417 assert(digraph != NULL);
    8418 assert(v >= 0);
    8419 assert(v < digraph->nnodes);
    8420 assert(lowlink != NULL);
    8421 assert(dfsidx != NULL);
    8422 assert(stack != NULL);
    8423 assert(stacksize != NULL);
    8424 assert(*stacksize >= 0);
    8425 assert(*stacksize < digraph->nnodes);
    8426 assert(unprocessed != NULL);
    8427 assert(nodeinstack != NULL);
    8428 assert(maxdfs != NULL);
    8429 assert(strongcomponents != NULL);
    8430 assert(nstrongcomponents != NULL);
    8431 assert(strongcompstartidx != NULL);
    8432 assert(nstorednodes != NULL);
    8433 assert(*nstorednodes >= 0 && *nstorednodes < digraph->nnodes);
    8434
    8435 dfsidx[v] = *maxdfs;
    8436 lowlink[v] = *maxdfs;
    8437 *maxdfs += 1;
    8438
    8439 /* add v to the stack */
    8440 stack[*stacksize] = v;
    8441 *stacksize += 1;
    8442 nodeinstack[v] = TRUE;
    8443
    8444 /* mark v as processed */
    8445 unprocessed[v] = FALSE;
    8446
    8447 for( i = 0; i < digraph->nsuccessors[v]; ++i )
    8448 {
    8449 int w;
    8450
    8451 /* edge (v,w) */
    8452 w = digraph->successors[v][i];
    8453
    8454 if( unprocessed[w] )
    8455 {
    8456 tarjan(digraph, w, lowlink, dfsidx, stack, stacksize, unprocessed, nodeinstack, maxdfs, strongcomponents,
    8457 nstrongcomponents, strongcompstartidx, nstorednodes);
    8458
    8459 assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
    8460 assert(lowlink[w] >= 0 && lowlink[w] < digraph->nnodes);
    8461
    8462 /* update lowlink */
    8463 lowlink[v] = MIN(lowlink[v], lowlink[w]);
    8464 }
    8465 else if( nodeinstack[w] )
    8466 {
    8467 assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
    8468 assert(dfsidx[w] >= 0 && dfsidx[w] < digraph->nnodes);
    8469
    8470 /* update lowlink */
    8471 lowlink[v] = MIN(lowlink[v], dfsidx[w]);
    8472 }
    8473 }
    8474
    8475 /* found a root of a strong component */
    8476 if( lowlink[v] == dfsidx[v] )
    8477 {
    8478 int w;
    8479
    8480 strongcompstartidx[*nstrongcomponents] = *nstorednodes;
    8481 *nstrongcomponents += 1;
    8482
    8483 do
    8484 {
    8485 assert(*stacksize > 0);
    8486
    8487 /* stack.pop() */
    8488 w = stack[*stacksize - 1];
    8489 *stacksize -= 1;
    8490 nodeinstack[w] = FALSE;
    8491
    8492 /* store the node in the corresponding component */
    8493 strongcomponents[*nstorednodes] = w;
    8494 *nstorednodes += 1;
    8495 }
    8496 while( v != w );
    8497 }
    8498}
    8499
    8500/** Computes all strongly connected components of an undirected connected component with Tarjan's Algorithm.
    8501 * The resulting strongly connected components are sorted topologically (starting from the end of the
    8502 * strongcomponents array).
    8503 *
    8504 * @note In general a topological sort of the strongly connected components is not unique.
    8505 */
    8507 SCIP_DIGRAPH* digraph, /**< directed graph */
    8508 int compidx, /**< number of the undirected connected component */
    8509 int* strongcomponents, /**< array to store the strongly connected components
    8510 * (length >= size of the component) */
    8511 int* strongcompstartidx, /**< array to store the start indices of the strongly connected
    8512 * components (length >= size of the component) */
    8513 int* nstrongcomponents /**< pointer to store the number of strongly connected
    8514 * components */
    8515 )
    8516{
    8517 int* lowlink = NULL;
    8518 int* dfsidx = NULL;
    8519 int* stack = NULL;
    8520 int stacksize;
    8521 SCIP_Bool* unprocessed = NULL;
    8522 SCIP_Bool* nodeinstack = NULL;
    8523 int maxdfs;
    8524 int nstorednodes;
    8525 int i;
    8526 SCIP_RETCODE retcode;
    8527
    8528 assert(digraph != NULL);
    8529 assert(compidx >= 0);
    8530 assert(compidx < digraph->ncomponents);
    8531 assert(strongcomponents != NULL);
    8532 assert(strongcompstartidx != NULL);
    8533 assert(nstrongcomponents != NULL);
    8534
    8535 retcode = SCIP_OKAY;
    8536
    8537 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&lowlink, digraph->nnodes), TERMINATE );
    8538 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsidx, digraph->nnodes), TERMINATE );
    8539 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stack, digraph->nnodes), TERMINATE );
    8540 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&unprocessed, digraph->nnodes), TERMINATE );
    8541 SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&nodeinstack, digraph->nnodes), TERMINATE );
    8542
    8543 for( i = 0; i < digraph->nnodes; ++i )
    8544 {
    8545 lowlink[i] = -1;
    8546 dfsidx[i] = -1;
    8547 stack[i] = -1;
    8548 unprocessed[i] = TRUE;
    8549 nodeinstack[i] = FALSE;
    8550 }
    8551
    8552 nstorednodes = 0;
    8553 stacksize = 0;
    8554 maxdfs = 0;
    8555 *nstrongcomponents = 0;
    8556
    8557 /* iterate over all nodes in the undirected connected component */
    8558 for( i = digraph->componentstarts[compidx]; i < digraph->componentstarts[compidx + 1]; ++i )
    8559 {
    8560 int v;
    8561
    8562 v = digraph->components[i];
    8563 assert(v >= 0 && v < digraph->nnodes);
    8564
    8565 /* call Tarjan's algorithm for unprocessed nodes */
    8566 if( unprocessed[v] )
    8567 {
    8568 SCIPdebugMessage("apply Tarjan's algorithm for node %d\n", v);
    8569 tarjan(digraph, v, lowlink, dfsidx, stack, &stacksize, unprocessed, nodeinstack, &maxdfs,
    8570 strongcomponents, nstrongcomponents, strongcompstartidx, &nstorednodes);
    8571 }
    8572 }
    8573
    8574 /* we should have stored as many nodes as in the undirected connected component */
    8575 assert(nstorednodes == digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx]);
    8576
    8577 /* to simplify the iteration over all strongly connected components */
    8578 assert(*nstrongcomponents < digraph->nnodes + 1);
    8579 strongcompstartidx[*nstrongcomponents] = nstorednodes;
    8580
    8581 assert(retcode == SCIP_OKAY);
    8582
    8583TERMINATE:
    8584 BMSfreeMemoryArrayNull(&lowlink);
    8585 BMSfreeMemoryArrayNull(&dfsidx);
    8586 BMSfreeMemoryArrayNull(&stack);
    8587 BMSfreeMemoryArrayNull(&unprocessed);
    8588 BMSfreeMemoryArrayNull(&nodeinstack);
    8589
    8590 return retcode;
    8591}
    8592
    8593/** frees the component information for the given directed graph */
    8595 SCIP_DIGRAPH* digraph /**< directed graph */
    8596 )
    8597{
    8598 BMS_BLKMEM* blkmem;
    8599
    8600 assert(digraph != NULL);
    8601 assert(digraph->blkmem != NULL);
    8602
    8603 blkmem = digraph->blkmem;
    8604
    8605 /* free components structure */
    8606 if( digraph->componentstartsize > 0 )
    8607 {
    8608 BMSfreeBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize);
    8609 BMSfreeBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes);
    8610 digraph->components = NULL;
    8611 digraph->componentstarts = NULL;
    8612 digraph->ncomponents = 0;
    8613 digraph->componentstartsize = 0;
    8614 }
    8615#ifndef NDEBUG
    8616 else
    8617 {
    8618 assert(digraph->components == NULL);
    8619 assert(digraph->componentstarts == NULL);
    8620 assert(digraph->ncomponents == 0);
    8621 }
    8622#endif
    8623}
    8624
    8625/** output of the given directed graph via the given message handler */
    8627 SCIP_DIGRAPH* digraph, /**< directed graph */
    8628 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    8629 FILE* file /**< output file (or NULL for standard output) */
    8630 )
    8631{
    8632 int n;
    8633
    8634 for( n = 0; n < digraph->nnodes; ++n )
    8635 {
    8636 int* successors;
    8637 int nsuccessors;
    8638 int m;
    8639
    8640 nsuccessors = digraph->nsuccessors[n];
    8641 successors = digraph->successors[n];
    8642
    8643 SCIPmessageFPrintInfo(messagehdlr, file, "node %d --> ", n);
    8644
    8645 for( m = 0; m < nsuccessors ; ++m )
    8646 {
    8647 if( m == 0 )
    8648 {
    8649 SCIPmessageFPrintInfo(messagehdlr, file, "%d", successors[m]);
    8650 }
    8651 else
    8652 {
    8653 SCIPmessageFPrintInfo(messagehdlr, file, ", %d", successors[m]);
    8654 }
    8655 }
    8656 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
    8657 }
    8658}
    8659
    8660/** prints the given directed graph structure in GML format into the given file */
    8662 SCIP_DIGRAPH* digraph, /**< directed graph */
    8663 FILE* file /**< file to write to */
    8664 )
    8665{
    8666 int n;
    8667
    8668 /* write GML format opening */
    8670
    8671 /* write all nodes of the graph */
    8672 for( n = 0; n < digraph->nnodes; ++n )
    8673 {
    8674 char label[SCIP_MAXSTRLEN];
    8675
    8676 (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", n);
    8677 SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", NULL, NULL);
    8678 }
    8679
    8680 /* write all edges */
    8681 for( n = 0; n < digraph->nnodes; ++n )
    8682 {
    8683 int* successors;
    8684 int nsuccessors;
    8685 int m;
    8686
    8687 nsuccessors = digraph->nsuccessors[n];
    8688 successors = digraph->successors[n];
    8689
    8690 for( m = 0; m < nsuccessors; ++m )
    8691 {
    8692 SCIPgmlWriteArc(file, (unsigned int)n, (unsigned int)successors[m], NULL, NULL);
    8693 }
    8694 }
    8695 /* write GML format closing */
    8696 SCIPgmlWriteClosing(file);
    8697}
    8698
    8699/** output of the given directed graph via the given message handler */
    8701 SCIP_DIGRAPH* digraph, /**< directed graph */
    8702 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
    8703 FILE* file /**< output file (or NULL for standard output) */
    8704 )
    8705{
    8706 int c;
    8707 int i;
    8708
    8709 for( c = 0; c < digraph->ncomponents; ++c )
    8710 {
    8711 int start = digraph->componentstarts[c];
    8712 int end = digraph->componentstarts[c+1];
    8713
    8714 SCIPmessageFPrintInfo(messagehdlr, file, "Components %d --> ", c);
    8715
    8716 for( i = start; i < end; ++i )
    8717 {
    8718 if( i == start )
    8719 {
    8720 SCIPmessageFPrintInfo(messagehdlr, file, "%d", digraph->components[i]);
    8721 }
    8722 else
    8723 {
    8724 SCIPmessageFPrintInfo(messagehdlr, file, ", %d", digraph->components[i]);
    8725 }
    8726 }
    8727 SCIPmessageFPrintInfo(messagehdlr, file, "\n");
    8728 }
    8729}
    8730
    8731/*
    8732 * Binary tree
    8733 */
    8734
    8735/** creates a node for a binary tree */
    8736static
    8738 SCIP_BT* tree, /**< binary tree */
    8739 SCIP_BTNODE** node /**< pointer to store the created node */
    8740 )
    8741{
    8742 SCIP_ALLOC( BMSallocBlockMemory(tree->blkmem, node) );
    8743
    8744 (*node)->parent = NULL;
    8745 (*node)->left = NULL;
    8746 (*node)->right = NULL;
    8747 (*node)->dataptr = NULL;
    8748
    8749 return SCIP_OKAY;
    8750}
    8751
    8752/** creates a tree node with (optinal) user data */
    8754 SCIP_BT* tree, /**< binary tree */
    8755 SCIP_BTNODE** node, /**< pointer to store the created node */
    8756 void* dataptr /**< user node data pointer, or NULL */
    8757 )
    8758{
    8759 assert(tree != NULL);
    8760 assert(node != NULL);
    8761
    8762 SCIP_CALL( btnodeCreateEmpty(tree, node) );
    8763
    8764 assert((*node)->parent == NULL);
    8765 assert((*node)->left == NULL);
    8766 assert((*node)->right == NULL);
    8767
    8768 /* initialize user data */
    8769 (*node)->dataptr = dataptr;
    8770
    8771 return SCIP_OKAY;
    8772}
    8773
    8774/** frees a tree leaf */
    8775static
    8777 SCIP_BT* tree, /**< binary tree */
    8778 SCIP_BTNODE** node /**< pointer to node which has to be freed */
    8779 )
    8780{
    8781 assert(tree != NULL);
    8782 assert(node != NULL);
    8783 assert(*node != NULL);
    8784
    8785 assert((*node)->left == NULL);
    8786 assert((*node)->right == NULL);
    8787
    8788#ifdef SCIP_DISABLED_CODE
    8789 /* remove reference from parent node */
    8790 if( (*node)->parent != NULL )
    8791 {
    8792 assert(*node != NULL);
    8793
    8794 assert((*node)->parent->left == *node || ((*node)->parent->right == *node));
    8795
    8796 if( (*node)->parent->left == *node )
    8797 {
    8798 (*node)->parent->left = NULL;
    8799 }
    8800 else
    8801 {
    8802 assert((*node)->parent->right == *node);
    8803 (*node)->parent->right = NULL;
    8804 }
    8805 }
    8806#endif
    8807
    8808 assert(*node != NULL);
    8809 BMSfreeBlockMemory(tree->blkmem, node);
    8810 assert(*node == NULL);
    8811}
    8812
    8813/** frees the node including the rooted subtree
    8814 *
    8815 * @note The user pointer (object) is not freed. If needed, it has to be done by the user.
    8816 */
    8818 SCIP_BT* tree, /**< binary tree */
    8819 SCIP_BTNODE** node /**< node to be freed */
    8820 )
    8821{
    8822 assert(tree != NULL);
    8823 assert(node != NULL);
    8824 assert(*node != NULL);
    8825
    8826 if( (*node)->left != NULL )
    8827 {
    8828 SCIPbtnodeFree(tree, &(*node)->left);
    8829 assert((*node)->left == NULL);
    8830 }
    8831
    8832 if( (*node)->right != NULL )
    8833 {
    8834 SCIPbtnodeFree(tree, &(*node)->right);
    8835 assert((*node)->right == NULL);
    8836 }
    8837
    8838 btnodeFreeLeaf(tree, node);
    8839 assert(*node == NULL);
    8840}
    8841
    8842/* some simple variable functions implemented as defines */
    8843
    8844/* In debug mode, the following methods are implemented as function calls to ensure
    8845 * type validity.
    8846 * In optimized mode, the methods are implemented as defines to improve performance.
    8847 * However, we want to have them in the library anyways, so we have to undef the defines.
    8848 */
    8849
    8850#undef SCIPbtnodeGetData
    8851#undef SCIPbtnodeGetKey
    8852#undef SCIPbtnodeGetParent
    8853#undef SCIPbtnodeGetLeftchild
    8854#undef SCIPbtnodeGetRightchild
    8855#undef SCIPbtnodeGetSibling
    8856#undef SCIPbtnodeIsRoot
    8857#undef SCIPbtnodeIsLeaf
    8858#undef SCIPbtnodeIsLeftchild
    8859#undef SCIPbtnodeIsRightchild
    8860
    8861/** returns the user data pointer stored in that node */
    8863 SCIP_BTNODE* node /**< node */
    8864 )
    8865{
    8866 assert(node != NULL);
    8867
    8868 return node->dataptr;
    8869}
    8870
    8871/** returns the parent which can be NULL if the given node is the root */
    8873 SCIP_BTNODE* node /**< node */
    8874 )
    8875{
    8876 assert(node != NULL);
    8877
    8878 return node->parent;
    8879}
    8880
    8881/** returns left child which can be NULL if the given node is a leaf */
    8883 SCIP_BTNODE* node /**< node */
    8884 )
    8885{
    8886 assert(node != NULL);
    8887
    8888 return node->left;
    8889}
    8890
    8891/** returns right child which can be NULL if the given node is a leaf */
    8893 SCIP_BTNODE* node /**< node */
    8894 )
    8895{
    8896 assert(node != NULL);
    8897
    8898 return node->right;
    8899}
    8900
    8901/** returns the sibling of the node or NULL if does not exist */
    8903 SCIP_BTNODE* node /**< node */
    8904 )
    8905{
    8906 SCIP_BTNODE* parent;
    8907
    8908 parent = SCIPbtnodeGetParent(node);
    8909
    8910 if( parent == NULL )
    8911 return NULL;
    8912
    8913 if( SCIPbtnodeGetLeftchild(parent) == node )
    8914 return SCIPbtnodeGetRightchild(parent);
    8915
    8916 assert(SCIPbtnodeGetRightchild(parent) == node);
    8917
    8918 return SCIPbtnodeGetLeftchild(parent);
    8919}
    8920
    8921/** returns whether the node is a root node */
    8923 SCIP_BTNODE* node /**< node */
    8924 )
    8925{
    8926 assert(node != NULL);
    8927
    8928 return (node->parent == NULL);
    8929}
    8930
    8931/** returns whether the node is a leaf */
    8933 SCIP_BTNODE* node /**< node */
    8934 )
    8935{
    8936 assert(node != NULL);
    8937
    8938 return (node->left == NULL && node->right == NULL);
    8939}
    8940
    8941/** returns TRUE if the given node is left child */
    8943 SCIP_BTNODE* node /**< node */
    8944 )
    8945{
    8946 SCIP_BTNODE* parent;
    8947
    8948 if( SCIPbtnodeIsRoot(node) )
    8949 return FALSE;
    8950
    8951 parent = SCIPbtnodeGetParent(node);
    8952
    8953 if( SCIPbtnodeGetLeftchild(parent) == node )
    8954 return TRUE;
    8955
    8956 return FALSE;
    8957}
    8958
    8959/** returns TRUE if the given node is right child */
    8961 SCIP_BTNODE* node /**< node */
    8962 )
    8963{
    8964 SCIP_BTNODE* parent;
    8965
    8966 if( SCIPbtnodeIsRoot(node) )
    8967 return FALSE;
    8968
    8969 parent = SCIPbtnodeGetParent(node);
    8970
    8971 if( SCIPbtnodeGetRightchild(parent) == node )
    8972 return TRUE;
    8973
    8974 return FALSE;
    8975}
    8976
    8977/** sets the give node data
    8978 *
    8979 * @note The old user pointer is not freed.
    8980 */
    8982 SCIP_BTNODE* node, /**< node */
    8983 void* dataptr /**< node user data pointer */
    8984 )
    8985{
    8986 assert(node != NULL);
    8987
    8988 node->dataptr = dataptr;
    8989}
    8990
    8991/** sets parent node
    8992 *
    8993 * @note The old parent including the rooted subtree is not delete.
    8994 */
    8996 SCIP_BTNODE* node, /**< node */
    8997 SCIP_BTNODE* parent /**< new parent node, or NULL */
    8998 )
    8999{
    9000 assert(node != NULL);
    9001
    9002 node->parent = parent;
    9003}
    9004
    9005/** sets left child
    9006 *
    9007 * @note The old left child including the rooted subtree is not delete.
    9008 */
    9010 SCIP_BTNODE* node, /**< node */
    9011 SCIP_BTNODE* left /**< new left child, or NULL */
    9012 )
    9013{
    9014 assert(node != NULL);
    9015
    9016 node->left = left;
    9017}
    9018
    9019/** sets right child
    9020 *
    9021 * @note The old right child including the rooted subtree is not delete.
    9022 */
    9024 SCIP_BTNODE* node, /**< node */
    9025 SCIP_BTNODE* right /**< new right child, or NULL */
    9026 )
    9027{
    9028 assert(node != NULL);
    9029
    9030 node->right = right;
    9031}
    9032
    9033/** creates an binary tree */
    9035 SCIP_BT** tree, /**< pointer to store the created binary tree */
    9036 BMS_BLKMEM* blkmem /**< block memory used to createnode */
    9037 )
    9038{
    9039 assert(tree != NULL);
    9040 assert(blkmem != NULL);
    9041
    9042 SCIP_ALLOC( BMSallocBlockMemory(blkmem, tree) );
    9043 (*tree)->blkmem = blkmem;
    9044 (*tree)->root = NULL;
    9045
    9046 return SCIP_OKAY;
    9047}
    9048
    9049/** frees binary tree
    9050 *
    9051 * @note The user pointers (object) of the nodes are not freed. If needed, it has to be done by the user.
    9052 */
    9054 SCIP_BT** tree /**< pointer to binary tree */
    9055 )
    9056{
    9057 assert(tree != NULL);
    9058
    9059 if( (*tree)->root != NULL )
    9060 {
    9061 SCIPbtnodeFree(*tree, &((*tree)->root));
    9062 }
    9063
    9064 BMSfreeBlockMemory((*tree)->blkmem, tree);
    9065}
    9066
    9067/** prints the rooted subtree of the given binary tree node in GML format into the given file */
    9068static
    9070 SCIP_BTNODE* node, /**< binary tree node */
    9071 FILE* file, /**< file to write to */
    9072 int* nnodes /**< pointer to count the number of nodes */
    9073 )
    9074{
    9075 SCIP_BTNODE* left;
    9076 SCIP_BTNODE* right;
    9077 char label[SCIP_MAXSTRLEN];
    9078
    9079 assert(node != NULL);
    9080
    9081 (*nnodes)++;
    9082 (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", *nnodes);
    9083
    9084 SCIPgmlWriteNode(file, (unsigned int)(size_t)node, label, "circle", NULL, NULL);
    9085
    9086 left = SCIPbtnodeGetLeftchild(node);
    9087 right = SCIPbtnodeGetRightchild(node);
    9088
    9089 if( left != NULL )
    9090 {
    9091 btPrintSubtree(left, file, nnodes);
    9092
    9093 SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)left, NULL, NULL);
    9094 }
    9095
    9096 if( right != NULL )
    9097 {
    9098 btPrintSubtree(right, file, nnodes);
    9099
    9100 SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)right, NULL, NULL);
    9101 }
    9102}
    9103
    9104/** prints the binary tree in GML format into the given file */
    9106 SCIP_BT* tree, /**< binary tree */
    9107 FILE* file /**< file to write to */
    9108 )
    9109{
    9110 /* write GML opening */
    9112
    9113 if( !SCIPbtIsEmpty(tree) )
    9114 {
    9115 SCIP_BTNODE* root;
    9116 int nnodes;
    9117
    9118 root = SCIPbtGetRoot(tree);
    9119 assert(root != NULL);
    9120
    9121 nnodes = 0;
    9122
    9123 btPrintSubtree(root, file, &nnodes);
    9124 }
    9125
    9126 /* write GML closing */
    9127 SCIPgmlWriteClosing(file);
    9128}
    9129
    9130/* some simple variable functions implemented as defines */
    9131#undef SCIPbtIsEmpty
    9132#undef SCIPbtGetRoot
    9133
    9134/** returns whether the binary tree is empty (has no nodes) */
    9136 SCIP_BT* tree /**< binary tree */
    9137 )
    9138{
    9139 assert(tree != NULL);
    9140
    9141 return (tree->root == NULL);
    9142}
    9143
    9144/** returns the the root node of the binary or NULL if the binary tree is empty */
    9146 SCIP_BT* tree /**< tree to be evaluated */
    9147 )
    9148{
    9149 assert(tree != NULL);
    9150
    9151 return tree->root;
    9152}
    9153
    9154/** sets root node
    9155 *
    9156 * @note The old root including the rooted subtree is not delete.
    9157 */
    9159 SCIP_BT* tree, /**< tree to be evaluated */
    9160 SCIP_BTNODE* root /**< new root, or NULL */
    9161 )
    9162{
    9163 assert(tree != NULL);
    9164
    9165 tree->root = root;
    9166}
    9167
    9168
    9169/*
    9170 * Numerical methods
    9171 */
    9172
    9173/** returns the machine epsilon: the smallest number eps > 0, for which 1.0 + eps > 1.0 */
    9175 void
    9176 )
    9177{
    9178 SCIP_Real eps;
    9179 SCIP_Real lasteps;
    9180 SCIP_Real one;
    9181 SCIP_Real onepluseps;
    9182
    9183 one = 1.0;
    9184 eps = 1.0;
    9185 do
    9186 {
    9187 lasteps = eps;
    9188 eps /= 2.0;
    9189 onepluseps = one + eps;
    9190 }
    9191 while( onepluseps > one );
    9192
    9193 return lasteps;
    9194}
    9195
    9196/** calculates the greatest common divisor of the two given values */
    9198 SCIP_Longint val1, /**< first value of greatest common devisor calculation */
    9199 SCIP_Longint val2 /**< second value of greatest common devisor calculation */
    9200 )
    9201{
    9202 int t;
    9203
    9204 assert(val1 > 0);
    9205 assert(val2 > 0);
    9206
    9207 t = 0;
    9208 /* if val1 is even, divide it by 2 */
    9209 while( !(val1 & 1) )
    9210 {
    9211 val1 >>= 1; /*lint !e704*/
    9212
    9213 /* if val2 is even too, divide it by 2 and increase t(=number of e) */
    9214 if( !(val2 & 1) )
    9215 {
    9216 val2 >>= 1; /*lint !e704*/
    9217 ++t;
    9218 }
    9219 /* only val1 can be odd */
    9220 else
    9221 {
    9222 /* while val1 is even, divide it by 2 */
    9223 while( !(val1 & 1) )
    9224 val1 >>= 1; /*lint !e704*/
    9225
    9226 break;
    9227 }
    9228 }
    9229
    9230 /* while val2 is even, divide it by 2 */
    9231 while( !(val2 & 1) )
    9232 val2 >>= 1; /*lint !e704*/
    9233
    9234 /* the following if/else condition is only to make sure that we do not overflow when adding up both values before
    9235 * dividing them by 4 in the following while loop
    9236 */
    9237 if( t == 0 )
    9238 {
    9239 if( val1 > val2 )
    9240 {
    9241 val1 -= val2;
    9242
    9243 /* divide val1 by 2 as long as possible */
    9244 while( !(val1 & 1) )
    9245 val1 >>= 1; /*lint !e704*/
    9246 }
    9247 else if( val1 < val2 )
    9248 {
    9249 val2 -= val1;
    9250
    9251 /* divide val2 by 2 as long as possible */
    9252 while( !(val2 & 1) )
    9253 val2 >>= 1; /*lint !e704*/
    9254 }
    9255 }
    9256
    9257 /* val1 and val2 are odd */
    9258 while( val1 != val2 )
    9259 {
    9260 if( val1 > val2 )
    9261 {
    9262 /* we can stop if one value reached one */
    9263 if( val2 == 1 )
    9264 return (val2 << t); /*lint !e647 !e703*/
    9265
    9266 /* if ((val1 xor val2) and 2) = 2, then gcd(val1, val2) = gcd((val1 + val2)/4, val2),
    9267 * and otherwise gcd(val1, val2) = gcd((val1 − val2)/4, val2)
    9268 */
    9269 if( ((val1 ^ val2) & 2) == 2 )
    9270 val1 += val2;
    9271 else
    9272 val1 -= val2;
    9273
    9274 assert((val1 & 3) == 0);
    9275 val1 >>= 2; /*lint !e704*/
    9276
    9277 /* if val1 is still even, divide it by 2 */
    9278 while( !(val1 & 1) )
    9279 val1 >>= 1; /*lint !e704*/
    9280 }
    9281 else
    9282 {
    9283 /* we can stop if one value reached one */
    9284 if( val1 == 1 )
    9285 return (val1 << t); /*lint !e647 !e703*/
    9286
    9287 /* if ((val2 xor val1) and 2) = 2, then gcd(val2, val1) = gcd((val2 + val1)/4, val1),
    9288 * and otherwise gcd(val2, val1) = gcd((val2 − val1)/4, val1)
    9289 */
    9290 if( ((val2 ^ val1) & 2) == 2 )
    9291 val2 += val1;
    9292 else
    9293 val2 -= val1;
    9294
    9295 assert((val2 & 3) == 0);
    9296 val2 >>= 2; /*lint !e704*/
    9297
    9298 /* if val2 is still even, divide it by 2 */
    9299 while( !(val2 & 1) )
    9300 val2 >>= 1; /*lint !e704*/
    9301 }
    9302 }
    9303
    9304 return (val1 << t); /*lint !e703*/
    9305}
    9306
    9307
    9308/* for the MS compiler, the function nextafter is named _nextafter */
    9309#if defined(_MSC_VER) && !defined(NO_NEXTAFTER)
    9310#define nextafter(x,y) _nextafter(x,y)
    9311#endif
    9312
    9313/* on systems where the function nextafter is not defined, we provide an implementation from Sun */
    9314#ifdef NO_NEXTAFTER
    9315/* The following implementation of the routine nextafter() comes with the following license:
    9316 *
    9317 * ====================================================
    9318 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
    9319 *
    9320 * Developed at SunSoft, a Sun Microsystems, Inc. business.
    9321 * Permission to use, copy, modify, and distribute this
    9322 * software is freely granted, provided that this notice
    9323 * is preserved.
    9324 * ====================================================
    9325 */
    9326
    9327#define __HI(x) *(1+(int*)&x)
    9328#define __LO(x) *(int*)&x
    9329#define __HIp(x) *(1+(int*)x)
    9330#define __LOp(x) *(int*)x
    9331
    9332static
    9333double nextafter(double x, double y)
    9334{
    9335 int hx;
    9336 int hy;
    9337 int ix;
    9338 int iy;
    9339 unsigned lx;
    9340 unsigned ly;
    9341
    9342 /* cppcheck-suppress invalidPointerCast */
    9343 hx = __HI(x); /* high word of x */
    9344 /* cppcheck-suppress invalidPointerCast */
    9345 lx = __LO(x); /* low word of x */
    9346 /* cppcheck-suppress invalidPointerCast */
    9347 hy = __HI(y); /* high word of y */
    9348 /* cppcheck-suppress invalidPointerCast */
    9349 ly = __LO(y); /* low word of y */
    9350 ix = hx&0x7fffffff; /* |x| */
    9351 iy = hy&0x7fffffff; /* |y| */
    9352
    9353 if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) || /* x is nan */
    9354 ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 )) /* y is nan */
    9355 return x + y;
    9356
    9357 /* x == y, return x */
    9358 if( x == y )
    9359 return x;
    9360
    9361 /* x == 0 */
    9362 if( (ix|lx) == 0 )
    9363 {
    9364 /* return +-minsubnormal */
    9365 /* cppcheck-suppress invalidPointerCast */
    9366 __HI(x) = hy&0x80000000;
    9367 /* cppcheck-suppress invalidPointerCast */
    9368 __LO(x) = 1;
    9369 y = x * x;
    9370 if ( y == x )
    9371 return y;
    9372 else
    9373 return x; /* raise underflow flag */
    9374 }
    9375 /* x > 0 */
    9376 if( hx >= 0 )
    9377 {
    9378 /* x > y, x -= ulp */
    9379 if( hx > hy || ((hx == hy) && (lx > ly)) )
    9380 {
    9381 if ( lx == 0 )
    9382 hx -= 1;
    9383 lx -= 1;
    9384 }
    9385 else
    9386 {
    9387 /* x < y, x += ulp */
    9388 lx += 1;
    9389 if ( lx == 0 )
    9390 hx += 1;
    9391 }
    9392 }
    9393 else
    9394 {
    9395 /* x < 0 */
    9396 if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
    9397 {
    9398 /* x < y, x -= ulp */
    9399 if ( lx == 0 )
    9400 hx -= 1;
    9401 lx -= 1;
    9402 }
    9403 else
    9404 {
    9405 /* x > y, x += ulp */
    9406 lx += 1;
    9407 if( lx == 0 )
    9408 hx += 1;
    9409 }
    9410 }
    9411 hy = hx&0x7ff00000;
    9412 /* overflow */
    9413 if( hy >= 0x7ff00000 )
    9414 return x + x;
    9415 if( hy < 0x00100000 )
    9416 {
    9417 /* underflow */
    9418 y = x*x;
    9419 if( y != x )
    9420 {
    9421 /* raise underflow flag */
    9422 /* cppcheck-suppress invalidPointerCast */
    9423 __HI(y) = hx;
    9424 /* cppcheck-suppress invalidPointerCast */
    9425 __LO(y) = lx;
    9426 return y;
    9427 }
    9428 }
    9429
    9430 /* cppcheck-suppress invalidPointerCast */
    9431 __HI(x) = hx;
    9432 /* cppcheck-suppress invalidPointerCast */
    9433 __LO(x) = lx;
    9434 return x;
    9435}
    9436#endif
    9437
    9438
    9439/** returns the next representable value of from in the direction of to */
    9441 SCIP_Real from, /**< value from which the next representable value should be returned */
    9442 SCIP_Real to /**< direction in which the next representable value should be returned */
    9443 )
    9444{
    9445 return nextafter(from, to);
    9446}
    9447
    9448/** calculates the smallest common multiple of the two given values */
    9450 SCIP_Longint val1, /**< first value of smallest common multiple calculation */
    9451 SCIP_Longint val2 /**< second value of smallest common multiple calculation */
    9452 )
    9453{
    9454 SCIP_Longint gcd;
    9455
    9456 assert(val1 > 0);
    9457 assert(val2 > 0);
    9458
    9459 gcd = SCIPcalcGreComDiv(val1, val2);
    9460
    9461 return val1/gcd * val2;
    9462}
    9463
    9464static const SCIP_Real simplednoms[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
    9465 17.0, 18.0, 19.0, 25.0, -1.0};
    9466
    9467/** converts a real number into a (approximate) rational representation, and returns TRUE iff the conversion was
    9468 * successful
    9469 */
    9471 SCIP_Real val, /**< real value r to convert into rational number */
    9472 SCIP_Real mindelta, /**< minimal allowed difference r - q of real r and rational q = n/d */
    9473 SCIP_Real maxdelta, /**< maximal allowed difference r - q of real r and rational q = n/d */
    9474 SCIP_Longint maxdnom, /**< maximal denominator allowed */
    9475 SCIP_Longint* numerator, /**< pointer to store the numerator n of the rational number */
    9476 SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
    9477 )
    9478{
    9479 SCIP_Real a;
    9480 SCIP_Real b;
    9481 SCIP_Real g0;
    9482 SCIP_Real g1;
    9483 SCIP_Real gx;
    9484 SCIP_Real h0;
    9485 SCIP_Real h1;
    9486 SCIP_Real hx;
    9487 SCIP_Real delta0;
    9488 SCIP_Real delta1;
    9489 SCIP_Real epsilon;
    9490 int i;
    9491
    9492 assert(mindelta <= 0.0);
    9493 assert(maxdelta >= 0.0);
    9494 assert(numerator != NULL);
    9495 assert(denominator != NULL);
    9496
    9497 if( REALABS(val) >= ((SCIP_Real)SCIP_LONGINT_MAX) / maxdnom )
    9498 return FALSE;
    9499
    9500 /* try the simple denominators first: each value of the simpledenoms table multiplied by powers of 10
    9501 * is tried as denominator
    9502 */
    9503 for( i = 0; simplednoms[i] > 0.0; ++i )
    9504 {
    9505 SCIP_Real nom;
    9506 SCIP_Real dnom;
    9507 SCIP_Real ratval0;
    9508 SCIP_Real ratval1;
    9509
    9510 /* try powers of 10 (including 10^0) */
    9511 dnom = simplednoms[i];
    9512 while( dnom <= maxdnom )
    9513 {
    9514 nom = floor(val * dnom);
    9515 ratval0 = nom/dnom;
    9516 ratval1 = (nom+1.0)/dnom;
    9517 if( mindelta <= val - ratval0 && val - ratval1 <= maxdelta )
    9518 {
    9519 if( val - ratval0 <= maxdelta )
    9520 {
    9521 *numerator = (SCIP_Longint)nom;
    9522 *denominator = (SCIP_Longint)dnom;
    9523 return TRUE;
    9524 }
    9525 if( mindelta <= val - ratval1 )
    9526 {
    9527 *numerator = (SCIP_Longint)(nom+1.0);
    9528 *denominator = (SCIP_Longint)dnom;
    9529 return TRUE;
    9530 }
    9531 }
    9532 dnom *= 10.0;
    9533 }
    9534 }
    9535
    9536 /* the simple denominators didn't work: calculate rational representation with arbitrary denominator */
    9537 epsilon = MIN(-mindelta, maxdelta)/2.0;
    9538
    9539 b = val;
    9540 a = EPSFLOOR(b, epsilon);
    9541 g0 = a;
    9542 h0 = 1.0;
    9543 g1 = 1.0;
    9544 h1 = 0.0;
    9545 delta0 = val - g0/h0;
    9546 delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
    9547
    9548 while( (delta0 < mindelta || delta0 > maxdelta) && (delta1 < mindelta || delta1 > maxdelta) )
    9549 {
    9550 assert(EPSGT(b, a, epsilon));
    9551 assert(h0 >= 0.0);
    9552 assert(h1 >= 0.0);
    9553
    9554 b = 1.0 / (b - a);
    9555 a = EPSFLOOR(b, epsilon);
    9556
    9557 assert(a >= 0.0);
    9558 gx = g0;
    9559 hx = h0;
    9560
    9561 g0 = a * g0 + g1;
    9562 h0 = a * h0 + h1;
    9563
    9564 g1 = gx;
    9565 h1 = hx;
    9566
    9567 if( h0 > maxdnom )
    9568 return FALSE;
    9569
    9570 delta0 = val - g0/h0;
    9571 delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
    9572 }
    9573
    9574 if( REALABS(g0) > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) || h0 > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) )
    9575 return FALSE;
    9576
    9577 assert(h0 > 0.5);
    9578
    9579 if( delta0 < mindelta )
    9580 {
    9581 assert(mindelta <= delta1 && delta1 <= maxdelta);
    9582 *numerator = (SCIP_Longint)(g0 - 1.0);
    9584 }
    9585 else if( delta0 > maxdelta )
    9586 {
    9587 assert(mindelta <= delta1 && delta1 <= maxdelta);
    9588 *numerator = (SCIP_Longint)(g0 + 1.0);
    9590 }
    9591 else
    9592 {
    9593 *numerator = (SCIP_Longint)g0;
    9595 }
    9596 assert(*denominator >= 1);
    9597 assert(val - (SCIP_Real)(*numerator)/(SCIP_Real)(*denominator) >= mindelta);
    9598 assert(val - (SCIP_Real)(*numerator)/(SCIP_Real)(*denominator) <= maxdelta);
    9599
    9600 return TRUE;
    9601}
    9602
    9603/** checks, if value is integral without any tolerances */
    9605 SCIP_Real val /**< value to process */
    9606 )
    9607{
    9608 return floor(val) == val; /*lint !e777*/
    9609}
    9610
    9611/** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
    9612static
    9614 SCIP_Real val, /**< value that should be scaled to an integral value */
    9615 SCIP_Real scalar, /**< scalar that should be tried */
    9616 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
    9617 SCIP_Real maxdelta /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
    9618 )
    9619{
    9620 SCIP_Real sval;
    9621 SCIP_Real downval;
    9622 SCIP_Real upval;
    9623
    9624 assert(mindelta <= 0.0);
    9625 assert(maxdelta >= 0.0);
    9626
    9627 sval = val * scalar;
    9628 downval = floor(sval);
    9629 upval = ceil(sval);
    9630
    9631 return (SCIPrelDiff(sval, downval) <= maxdelta || SCIPrelDiff(sval, upval) >= mindelta);
    9632}
    9633
    9634/** additional scalars that are tried in integrality scaling */
    9635static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
    9636static const int nscalars = 9;
    9637
    9638/** tries to find a value, such that all given values, if scaled with this value become integral in relative allowed
    9639 * difference in between mindelta and maxdelta
    9640 */
    9642 SCIP_Real* vals, /**< values to scale */
    9643 int nvals, /**< number of values to scale */
    9644 SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
    9645 SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
    9646 SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
    9647 SCIP_Real maxscale, /**< maximal allowed scalar */
    9648 SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
    9649 SCIP_Bool* success /**< stores whether returned value is valid */
    9650 )
    9651{
    9652 SCIP_Real bestscalar;
    9653 SCIP_Longint gcd;
    9654 SCIP_Longint scm;
    9657 SCIP_Real val;
    9658 SCIP_Real minval;
    9659 SCIP_Real absval;
    9660 SCIP_Real scaleval;
    9661 SCIP_Bool scalable;
    9662 SCIP_Bool rational;
    9663 int c;
    9664 int s;
    9665 int i;
    9666
    9667 assert(vals != NULL);
    9668 assert(nvals >= 0);
    9669 assert(maxdnom >= 1);
    9670 assert(mindelta < 0.0);
    9671 assert(maxdelta > 0.0);
    9672 assert(success != NULL);
    9673
    9674 SCIPdebugMessage("trying to find rational representation for given values\n");
    9675
    9676 if( intscalar != NULL )
    9677 *intscalar = SCIP_INVALID;
    9678 *success = FALSE;
    9679
    9680 /* get minimal absolute non-zero value */
    9681 minval = SCIP_REAL_MAX;
    9682 for( c = 0; c < nvals; ++c )
    9683 {
    9684 val = vals[c];
    9685 if( val < mindelta || val > maxdelta )
    9686 {
    9687 absval = REALABS(val);
    9688 minval = MIN(minval, absval);
    9689 }
    9690 }
    9691
    9692 if( minval == SCIP_REAL_MAX ) /*lint !e777*/
    9693 {
    9694 /* all coefficients are zero (inside tolerances) */
    9695 if( intscalar != NULL )
    9696 *intscalar = 1.0;
    9697 *success = TRUE;
    9698 SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
    9699
    9700 return SCIP_OKAY;
    9701 }
    9702 assert(minval > MIN(-mindelta, maxdelta));
    9703
    9704 bestscalar = SCIP_INVALID;
    9705
    9706 for( i = 0; i < 2; ++i )
    9707 {
    9708 scalable = TRUE;
    9709
    9710 /* try, if values can be made integral multiplying them with the reciprocal of the smallest value and a power of 2 */
    9711 if( i == 0 )
    9712 scaleval = 1.0/minval;
    9713 /* try, if values can be made integral by multiplying them by a power of 2 */
    9714 else
    9715 scaleval = 1.0;
    9716
    9717 for( c = 0; c < nvals && scalable; ++c )
    9718 {
    9719 /* check, if the value can be scaled with a simple scalar */
    9720 val = vals[c];
    9721 if( val == 0.0 ) /* zeros are allowed in the vals array */
    9722 continue;
    9723
    9724 absval = REALABS(val);
    9725 while( scaleval <= maxscale
    9726 && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta)) )
    9727 {
    9728 for( s = 0; s < nscalars; ++s )
    9729 {
    9730 if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta) )
    9731 {
    9732 scaleval *= scalars[s];
    9733 break;
    9734 }
    9735 }
    9736 if( s >= nscalars )
    9737 scaleval *= 2.0;
    9738 }
    9739 scalable = (scaleval <= maxscale);
    9740 SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
    9741 val, scaleval, val*scaleval, scalable);
    9742 }
    9743 if( scalable )
    9744 {
    9745 /* make values integral by dividing them by the smallest value (and multiplying them with a power of 2) */
    9746 assert(scaleval <= maxscale);
    9747
    9748 /* check if we found a better scaling value */
    9749 if( scaleval < bestscalar )
    9750 bestscalar = scaleval;
    9751
    9752 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g\n", scaleval);
    9753
    9754 /* if the scalar is still the reciprocal of the minimal value, all coeffcients are the same and we do not get a better scalar */
    9755 if( i == 0 && EPSEQ(scaleval, 1.0/minval, SCIP_DEFAULT_EPSILON) )
    9756 {
    9757 if( intscalar != NULL )
    9758 *intscalar = bestscalar;
    9759 *success = TRUE;
    9760
    9761 return SCIP_OKAY;
    9762 }
    9763 }
    9764 }
    9765
    9766 /* convert each value into a rational number, calculate the greatest common divisor of the numerators
    9767 * and the smallest common multiple of the denominators
    9768 */
    9769 gcd = 1;
    9770 scm = 1;
    9771 rational = TRUE;
    9772
    9773 /* first value (to initialize gcd) */
    9774 for( c = 0; c < nvals && rational; ++c )
    9775 {
    9776 val = vals[c];
    9777 if( val == 0.0 ) /* zeros are allowed in the vals array */
    9778 continue;
    9779
    9780 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
    9781 if( rational && numerator != 0 )
    9782 {
    9783 assert(denominator > 0);
    9784 gcd = ABS(numerator);
    9785 scm = denominator;
    9786 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
    9787 SCIPdebugMessage(" -> c=%d first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
    9788 c, val, numerator, denominator, gcd, scm, rational);
    9789 break;
    9790 }
    9791 }
    9792
    9793 /* remaining values */
    9794 for( ++c; c < nvals && rational; ++c )
    9795 {
    9796 val = vals[c];
    9797 if( val == 0.0 ) /* zeros are allowed in the vals array */
    9798 continue;
    9799
    9800 rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &numerator, &denominator);
    9801 if( rational && numerator != 0 )
    9802 {
    9803 assert(denominator > 0);
    9804 gcd = SCIPcalcGreComDiv(gcd, ABS(numerator));
    9806 rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
    9807 SCIPdebugMessage(" -> c=%d next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
    9808 c, val, numerator, denominator, gcd, scm, rational);
    9809 }
    9810 else
    9811 {
    9812 SCIPdebugMessage(" -> failed to convert %g into a rational representation\n", val);
    9813 }
    9814 }
    9815
    9816 if( rational )
    9817 {
    9818 /* make values integral by multiplying them with the smallest common multiple of the denominators */
    9819 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
    9820
    9821 /* check if we found a better scaling value */
    9822 if( (SCIP_Real)scm/(SCIP_Real)gcd < bestscalar )
    9823 bestscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
    9824
    9825 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
    9826 (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
    9827 }
    9828
    9829 if( bestscalar < SCIP_INVALID )
    9830 {
    9831 if( intscalar != NULL )
    9832 *intscalar = bestscalar;
    9833 *success = TRUE;
    9834
    9835 SCIPdebugMessage(" -> smallest value to achieve integrality is %g \n", bestscalar);
    9836 }
    9837
    9838 return SCIP_OKAY;
    9839}
    9840
    9841/** tries to find a value, such that all given values, if scaled with this value become integral */
    9843 BMS_BUFMEM* buffer,
    9844 SCIP_RATIONAL** vals, /**< values to scale */
    9845 int nvals, /**< number of values to scale */
    9846 SCIP_Real maxscale, /**< maximal allowed scalar */
    9847 SCIP_RATIONAL* intscalar, /**< pointer to store scalar that would make the coefficients integral */
    9848 SCIP_Bool* success /**< stores whether returned value is valid */
    9849 )
    9850{
    9851 SCIP_Longint gcd;
    9852 SCIP_Longint scm;
    9855 SCIP_Longint updatemultiplier;
    9856 SCIP_RATIONAL* ratupdate;
    9857 SCIP_RATIONAL* ratscm;
    9858 SCIP_Bool scalable;
    9859 int c;
    9860
    9861 assert(vals != NULL);
    9862 assert(nvals >= 0);
    9863 assert(success != NULL);
    9864
    9865 SCIPdebugMessage("trying to find rational representation for given rational values\n");
    9866
    9867 *success = FALSE;
    9868
    9869 /** @todo test whether it is faster to compute scm and gcd via mpz_scm() and mpz_gcd() in
    9870 * SCIPcalcIntegralScalarExact(); even if we stay with the SCIP_Longint conversion, we could use the other way
    9871 * to check the correctness of our result
    9872 */
    9873 /* calculate the greatest common divisor of the numerators and the smallest common multiple of the denominators */
    9874 gcd = 1;
    9875 scm = 1;
    9876 scalable = TRUE;
    9877
    9878 SCIP_CALL( SCIPrationalCreateBuffer(buffer, &ratupdate) );
    9879 SCIP_CALL( SCIPrationalCreateBuffer(buffer, &ratscm) );
    9880
    9881 /* first value (to initialize gcd) */
    9882 for( c = 0; c < nvals && scalable; ++c )
    9883 {
    9884 if( SCIPrationalIsZero(vals[c]) ) /* zeros are allowed in the vals array */
    9885 continue;
    9886
    9887 /* get numerator and check whether it fits into SCIP_Longint */
    9890 {
    9891 scalable = FALSE;
    9892 break;
    9893 }
    9894
    9895 /* get numerator and check whether it fits into SCIP_Longint */
    9898 {
    9899 scalable = FALSE;
    9900 break;
    9901 }
    9902
    9903 assert(denominator > 0);
    9904 gcd = ABS(numerator);
    9905 scm = denominator;
    9906
    9907 scalable = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale); /*lint !e838*/
    9908
    9909 break;
    9910 }
    9911
    9912 /* remaining values */
    9913 for( ++c; c < nvals && scalable; ++c )
    9914 {
    9915 if( SCIPrationalIsZero(vals[c]) ) /* zeros are allowed in the vals array */
    9916 continue;
    9917
    9918 /* get numerator and check whether it fits into SCIP_Longint */
    9921 {
    9922 scalable = FALSE;
    9923 break;
    9924 }
    9925
    9926 /* get denom and check whether it fits into SCIP_Longint */
    9929 {
    9930 scalable = FALSE;
    9931 break;
    9932 }
    9933
    9934 assert(denominator > 0);
    9935
    9936 gcd = SCIPcalcGreComDiv(gcd, ABS(numerator));
    9937
    9938 /* update scm via newscm = scm * denominator / gcd(scm, denominator) and check whether it fits into SCIP_Longint */
    9939 updatemultiplier = denominator / SCIPcalcGreComDiv(scm, denominator);
    9940 SCIPrationalSetFraction(ratupdate, updatemultiplier, 1LL);
    9941 SCIPrationalSetFraction(ratscm, scm, 1LL);
    9942 SCIPrationalMult(ratscm, ratscm, ratupdate);
    9944
    9945 scm = SCIPrationalNumerator(ratscm);
    9946
    9947 if( scm == SCIP_LONGINT_MAX )
    9948 {
    9949 scalable = FALSE;
    9950 break;
    9951 }
    9952
    9953 scalable = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale); /*lint !e838*/
    9954 }
    9955
    9956 if( scalable )
    9957 {
    9958 /* make values integral by multiplying them with the smallest common multiple of the denominators */
    9959 assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
    9960
    9961 SCIPrationalSetFraction(intscalar, scm, gcd);
    9962 SCIPrationalCanonicalize(intscalar);
    9963
    9964 *success = TRUE;
    9965
    9966 }
    9967
    9968 SCIPrationalFreeBuffer(buffer, &ratscm);
    9969 SCIPrationalFreeBuffer(buffer, &ratupdate);
    9970
    9971 return SCIP_OKAY;
    9972}
    9973
    9974/* Inform compiler that this code accesses the floating-point environment, so that
    9975 * certain optimizations should be omitted (http://www.cplusplus.com/reference/cfenv/FENV_ACCESS/).
    9976 * Not supported by Clang (gives warning) and GCC (silently), at the moment.
    9977 */
    9978#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
    9979#pragma fenv_access (on)
    9980#elif defined(__GNUC__) && !defined(__clang__)
    9981#pragma STDC FENV_ACCESS ON
    9982#endif
    9983#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
    9984#if defined(__clang__)
    9985__attribute__((optnone))
    9986#else
    9987__attribute__((optimize(0)))
    9988#endif
    9989#endif
    9990/** given a (usually very small) interval, tries to find a rational number with simple denominator (i.e. a small
    9991 * number, probably multiplied with powers of 10) out of this interval; returns TRUE iff a valid rational
    9992 * number inside the interval was found
    9993 */
    9995 SCIP_Real lb, /**< lower bound of the interval */
    9996 SCIP_Real ub, /**< upper bound of the interval */
    9997 SCIP_Longint maxdnom, /**< maximal denominator allowed for resulting rational number */
    9998 SCIP_Longint* numerator, /**< pointer to store the numerator n of the rational number */
    9999 SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
    10000 )
    10001{
    10002 SCIP_Real center;
    10003 SCIP_Real delta;
    10004
    10005 assert(lb <= ub);
    10006
    10007 center = 0.5*(lb+ub);
    10008
    10009 /* in order to compute a rational number that is exactly within the bounds (as the user expects),
    10010 * we computed the allowed delta with downward rounding, if available
    10011 */
    10013 {
    10014 SCIP_ROUNDMODE roundmode;
    10015
    10016 roundmode = SCIPintervalGetRoundingMode();
    10018
    10019 delta = 0.5*(ub-lb);
    10020
    10021 SCIPintervalSetRoundingMode(roundmode);
    10022 }
    10023 else
    10024 {
    10025 delta = 0.5*(ub-lb);
    10026 }
    10027
    10028 return SCIPrealToRational(center, -delta, +delta, maxdnom, numerator, denominator);
    10029}
    10030
    10031#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
    10032#pragma fenv_access (off)
    10033#elif defined(__GNUC__) && !defined(__clang__)
    10034#pragma STDC FENV_ACCESS OFF
    10035#endif
    10036
    10037/** given a (usually very small) interval, selects a value inside this interval; it is tried to select a rational number
    10038 * with simple denominator (i.e. a small number, probably multiplied with powers of 10);
    10039 * if no valid rational number inside the interval was found, selects the central value of the interval
    10040 */
    10042 SCIP_Real lb, /**< lower bound of the interval */
    10043 SCIP_Real ub, /**< upper bound of the interval */
    10044 SCIP_Longint maxdnom /**< maximal denominator allowed for resulting rational number */
    10045 )
    10046{
    10047 SCIP_Real val;
    10048
    10049 val = 0.5*(lb+ub);
    10050 if( lb < ub )
    10051 {
    10054 SCIP_Bool success;
    10055
    10056 /* try to find a "simple" rational number inside the interval */
    10057 SCIPdebugMessage("simple rational in [%.9f,%.9f]:", lb, ub);
    10058 success = SCIPfindSimpleRational(lb, ub, maxdnom, &numerator, &denominator);
    10059 if( success )
    10060 {
    10063
    10064 if( val - lb < 0.0 || val - ub > 0.0 )
    10065 {
    10066 SCIPdebugPrintf(" value is out of interval bounds by %g -> failed\n", MAX(lb-val, val-ub));
    10067 val = 0.5*(lb+ub);
    10068 }
    10069 }
    10070 else
    10071 {
    10072 SCIPdebugPrintf(" failed\n");
    10073 }
    10074 }
    10075
    10076 return val;
    10077}
    10078
    10079/** Performs the Newton Procedure from a given starting point to compute a root of the given function with
    10080 * specified precision and maximum number of iterations. If the procedure fails, SCIP_INVALID is returned.
    10081 */
    10083 SCIP_DECL_NEWTONEVAL((*function)), /**< pointer to function for which roots are computed */
    10084 SCIP_DECL_NEWTONEVAL((*derivative)), /**< pointer to derivative of above function */
    10085 SCIP_Real* params, /**< parameters needed for function (can be NULL) */
    10086 int nparams, /**< number of parameters (can be 0) */
    10087 SCIP_Real x, /**< starting point */
    10088 SCIP_Real eps, /**< tolerance */
    10089 int k /**< iteration limit */
    10090 )
    10091{
    10092 SCIP_Real result = x;
    10093 int iteration = 0;
    10094
    10095 assert(function != NULL);
    10096 assert(derivative != NULL);
    10097 assert(params != NULL || nparams == 0);
    10098 assert(eps > 0.0);
    10099 assert(k >= 0);
    10100 assert(x != SCIP_INVALID); /*lint !e777*/
    10101
    10102 while( iteration < k )
    10103 {
    10104 SCIP_Real deriv = derivative(result, params, nparams);
    10105
    10106 /* if we arrive at a stationary point, the procedure is aborted */
    10107 if( REALABS(deriv) <= eps || deriv == SCIP_INVALID ) /*lint !e777*/
    10108 return SCIP_INVALID;
    10109
    10110 result = result - function(result, params, nparams) / deriv;
    10111
    10112 /* if new point is within eps-range of 0, we are done */
    10113 if( REALABS(function(result, params, nparams)) <= eps )
    10114 break;
    10115
    10116 ++iteration;
    10117 }
    10118
    10119 if( k == iteration )
    10120 return SCIP_INVALID;
    10121 else
    10122 return result;
    10123}
    10124
    10125
    10126/*
    10127 * Random Numbers
    10128 */
    10129
    10130
    10131/* initial seeds for KISS random number generator */
    10132#define DEFAULT_SEED UINT32_C(123456789)
    10133#define DEFAULT_XOR UINT32_C(362436000)
    10134#define DEFAULT_MWC UINT32_C(521288629)
    10135#define DEFAULT_CST UINT32_C(7654321)
    10136
    10137
    10138/** initializes a random number generator with a given start seed */
    10140 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    10141 unsigned int initseed /**< initial random seed */
    10142 )
    10143{
    10144 assert(randnumgen != NULL);
    10145
    10146 /* use MAX() to avoid zero after over flowing */
    10147 randnumgen->seed = MAX(SCIPhashTwo(DEFAULT_SEED, initseed), 1u);
    10148 randnumgen->xor_seed = MAX(SCIPhashTwo(DEFAULT_XOR, initseed), 1u);
    10149 randnumgen->mwc_seed = MAX(SCIPhashTwo(DEFAULT_MWC, initseed), 1u);
    10150 randnumgen->cst_seed = SCIPhashTwo(DEFAULT_CST, initseed);
    10151
    10152 assert(randnumgen->seed > 0);
    10153 assert(randnumgen->xor_seed > 0);
    10154 assert(randnumgen->mwc_seed > 0);
    10155}
    10156
    10157/** returns a random number between 0 and UINT32_MAX
    10158 *
    10159 * implementation of KISS random number generator developed by George Marsaglia.
    10160 * KISS is combination of three different random number generators:
    10161 * - Linear congruential generator
    10162 * - Xorshift
    10163 * - Lag-1 Multiply-with-carry
    10164 *
    10165 * KISS has a period of 2^123 and passes all statistical test part of BigCrush-Test of TestU01 [1].
    10166 *
    10167 * [1] http://dl.acm.org/citation.cfm?doid=1268776.1268777
    10168 */
    10169static
    10171 SCIP_RANDNUMGEN* randnumgen /**< random number generator */
    10172 )
    10173{
    10174 uint64_t t;
    10175
    10176 /* linear congruential */
    10177 randnumgen->seed = (uint32_t) (randnumgen->seed * UINT64_C(1103515245) + UINT64_C(12345));
    10178
    10179 /* Xorshift */
    10180 randnumgen->xor_seed ^= (randnumgen->xor_seed << 13);
    10181 randnumgen->xor_seed ^= (randnumgen->xor_seed >> 17);
    10182 randnumgen->xor_seed ^= (randnumgen->xor_seed << 5);
    10183
    10184 /* Multiply-with-carry */
    10185 t = UINT64_C(698769069) * randnumgen->mwc_seed + randnumgen->cst_seed;
    10186 randnumgen->cst_seed = (uint32_t) (t >> 32);
    10187 randnumgen->mwc_seed = (uint32_t) t;
    10188
    10189 return randnumgen->seed + randnumgen->xor_seed + randnumgen->mwc_seed;
    10190}
    10191
    10192/** creates and initializes a random number generator */
    10194 SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
    10195 BMS_BLKMEM* blkmem, /**< block memory */
    10196 unsigned int initialseed /**< initial random seed */
    10197 )
    10198{
    10199 assert(randnumgen != NULL);
    10200
    10201 SCIP_ALLOC( BMSallocBlockMemory(blkmem, randnumgen) );
    10202
    10203 SCIPrandomSetSeed((*randnumgen), initialseed);
    10204
    10205 return SCIP_OKAY;
    10206}
    10207
    10208/** frees a random number generator */
    10210 SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
    10211 BMS_BLKMEM* blkmem /**< block memory */
    10212 )
    10213{
    10214 assert(randnumgen != NULL);
    10215 assert((*randnumgen) != NULL);
    10216
    10217 BMSfreeBlockMemory(blkmem, randnumgen);
    10218
    10219 return;
    10220}
    10221
    10222/** returns a random integer between minrandval and maxrandval */
    10224 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    10225 int minrandval, /**< minimal value to return */
    10226 int maxrandval /**< maximal value to return */
    10227 )
    10228{
    10229 SCIP_Real randnumber;
    10230 SCIP_Longint zeromax;
    10231
    10232 randnumber = (SCIP_Real)randomGetRand(randnumgen)/(UINT32_MAX+1.0);
    10233 assert(randnumber >= 0.0);
    10234 assert(randnumber < 1.0);
    10235
    10236 /* we need to shift the range to the non-negative integers to handle negative integer values correctly.
    10237 * we use a long integer to avoid overflows.
    10238 */
    10239 zeromax = (SCIP_Longint)maxrandval - (SCIP_Longint)minrandval + 1;
    10240
    10241 return (int) ((SCIP_Longint)(zeromax * randnumber) + (SCIP_Longint)minrandval);
    10242}
    10243
    10244/** returns a random real between minrandval and maxrandval */
    10246 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    10247 SCIP_Real minrandval, /**< minimal value to return */
    10248 SCIP_Real maxrandval /**< maximal value to return */
    10249 )
    10250{
    10251 SCIP_Real randnumber;
    10252
    10253 randnumber = (SCIP_Real)randomGetRand(randnumgen)/(SCIP_Real)UINT32_MAX;
    10254 assert(randnumber >= 0.0);
    10255 assert(randnumber <= 1.0);
    10256
    10257 /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
    10258 * SCIP_REAL_MAX apart
    10259 */
    10260 return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
    10261}
    10262
    10263/** randomly shuffles parts of an integer array using the Fisher-Yates algorithm */
    10265 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    10266 int* array, /**< array to be shuffled */
    10267 int begin, /**< first included index that should be subject to shuffling
    10268 * (0 for first array entry)
    10269 */
    10270 int end /**< first excluded index that should not be subject to shuffling
    10271 * (array size for last array entry)
    10272 */
    10273 )
    10274{
    10275 int tmp;
    10276 int i;
    10277
    10278 /* loop backwards through all elements and always swap the current last element to a random position */
    10279 while( end > begin+1 )
    10280 {
    10281 --end;
    10282
    10283 /* get a random position into which the last entry should be shuffled */
    10284 i = SCIPrandomGetInt(randnumgen, begin, end);
    10285
    10286 /* swap the last element and the random element */
    10287 tmp = array[i];
    10288 array[i] = array[end];
    10289 array[end] = tmp;
    10290 }
    10291}
    10292
    10293/** randomly shuffles parts of an array using the Fisher-Yates algorithm */
    10295 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    10296 void** array, /**< array to be shuffled */
    10297 int begin, /**< first included index that should be subject to shuffling
    10298 * (0 for first array entry)
    10299 */
    10300 int end /**< first excluded index that should not be subject to shuffling
    10301 * (array size for last array entry)
    10302 */
    10303 )
    10304{
    10305 void* tmp;
    10306 int i;
    10307
    10308 /* loop backwards through all elements and always swap the current last element to a random position */
    10309 while( end > begin+1 )
    10310 {
    10311 end--;
    10312
    10313 /* get a random position into which the last entry should be shuffled */
    10314 i = SCIPrandomGetInt(randnumgen, begin, end);
    10315
    10316 /* swap the last element and the random element */
    10317 tmp = array[i];
    10318 array[i] = array[end];
    10319 array[end] = tmp;
    10320 }
    10321}
    10322
    10323/** draws a random subset of disjoint elements from a given set of disjoint elements;
    10324 * this implementation is suited for the case that nsubelems is considerably smaller then nelems
    10325 */
    10327 SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
    10328 void** set, /**< original set, from which elements should be drawn */
    10329 int nelems, /**< number of elements in original set */
    10330 void** subset, /**< subset in which drawn elements should be stored */
    10331 int nsubelems /**< number of elements that should be drawn and stored */
    10332 )
    10333{
    10334 int i;
    10335 int j;
    10336
    10337 /* if both sets are of equal size, we just copy the array */
    10338 if( nelems == nsubelems)
    10339 {
    10340 BMScopyMemoryArray(subset,set,nelems);
    10341 return SCIP_OKAY;
    10342 }
    10343
    10344 /* abort, if size of subset is too big */
    10345 if( nsubelems > nelems )
    10346 {
    10347 SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
    10348 return SCIP_INVALIDDATA;
    10349 }
    10350#ifndef NDEBUG
    10351 for( i = 0; i < nsubelems; i++ )
    10352 for( j = 0; j < i; j++ )
    10353 assert(set[i] != set[j]);
    10354#endif
    10355
    10356 /* draw each element individually */
    10357 i = 0;
    10358 while( i < nsubelems )
    10359 {
    10360 int r;
    10361
    10362 r = SCIPrandomGetInt(randnumgen, 0, nelems-1);
    10363 subset[i] = set[r];
    10364
    10365 /* if we get an element that we already had, we will draw again */
    10366 for( j = 0; j < i; j++ )
    10367 {
    10368 if( subset[i] == subset[j] )
    10369 {
    10370 --i;
    10371 break;
    10372 }
    10373 }
    10374 ++i;
    10375 }
    10376 return SCIP_OKAY;
    10377}
    10378
    10379/*
    10380 * Additional math functions
    10381 */
    10382
    10383/** calculates a binomial coefficient n over m, choose m elements out of n, maximal value will be 33 over 16 (because
    10384 * the n=33 is the last line in the Pascal's triangle where each entry fits in a 4 byte value), an error occurs due to
    10385 * big numbers or an negative value m (and m < n) and -1 will be returned
    10386 */
    10388 int n, /**< number of different elements */
    10389 int m /**< number to choose out of the above */
    10390 )
    10391{
    10392 if( m == 0 || m >= n )
    10393 return 1;
    10394
    10395 if( m < 0 )
    10396 return -1;
    10397
    10398 /* symmetry of the binomial coefficient, choose smaller m */
    10399 if( m > n/2 )
    10400 m = n - m;
    10401
    10402 /* trivial case m == 1 */
    10403 if( m == 1 )
    10404 return n;
    10405
    10406 /* simple case m == 2 */
    10407 if( m == 2 )
    10408 {
    10409 if( ((SCIP_Real)SCIP_LONGINT_MAX) / n >= (n-1) * 2 ) /*lint !e790*/
    10410 return ((SCIP_Longint)n*(n-1)/2); /*lint !e647*/
    10411 else
    10412 return -1;
    10413 }
    10414
    10415 /* abort on to big numbers */
    10416 if( m > 16 || n > 33 )
    10417 return -1;
    10418
    10419 /* simple case m == 3 */
    10420 if( m == 3 )
    10421 return (n*(n-1)*(n-2)/6); /*lint !e647*/
    10422 else
    10423 {
    10424 /* first half of Pascal's triangle numbers(without the symmetric part) backwards from (33,16) over (32,16),
    10425 * (33,15), (32,15),(31,15, (30,15), (33,14) to (8,4) (rest is calculated directly)
    10426 *
    10427 * due to this order we can extract the right binomial coefficient by (16-m)^2+(16-m)+(33-n)
    10428 */
    10429 static const SCIP_Longint binoms[182] = {
    10430 1166803110, 601080390, 1037158320, 565722720, 300540195, 155117520, 818809200, 471435600, 265182525, 145422675,
    10431 77558760, 40116600, 573166440, 347373600, 206253075, 119759850, 67863915, 37442160, 20058300, 10400600,
    10432 354817320, 225792840, 141120525, 86493225, 51895935, 30421755, 17383860, 9657700, 5200300, 2704156, 193536720,
    10433 129024480, 84672315, 54627300, 34597290, 21474180, 13037895, 7726160, 4457400, 2496144, 1352078, 705432,
    10434 92561040, 64512240, 44352165, 30045015, 20030010, 13123110, 8436285, 5311735, 3268760, 1961256, 1144066,
    10435 646646, 352716, 184756, 38567100, 28048800, 20160075, 14307150, 10015005, 6906900, 4686825, 3124550, 2042975,
    10436 1307504, 817190, 497420, 293930, 167960, 92378, 48620, 13884156, 10518300, 7888725, 5852925, 4292145, 3108105,
    10437 2220075, 1562275, 1081575, 735471, 490314, 319770, 203490, 125970, 75582, 43758, 24310, 12870, 4272048, 3365856,
    10438 2629575, 2035800, 1560780, 1184040, 888030, 657800, 480700, 346104, 245157, 170544, 116280, 77520, 50388, 31824,
    10439 19448, 11440, 6435, 3432, 1107568, 906192, 736281, 593775, 475020, 376740, 296010, 230230, 177100, 134596,
    10440 100947, 74613, 54264, 38760, 27132, 18564, 12376, 8008, 5005, 3003, 1716, 924, 237336, 201376, 169911, 142506,
    10441 118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, 11628, 8568, 6188, 4368, 3003, 2002,
    10442 1287, 792, 462, 252, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985,
    10443 4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70};
    10444
    10445 /* m can at most be 16 */
    10446 const int t = 16-m;
    10447 assert(t >= 0);
    10448 assert(n <= 33);
    10449
    10450 /* binoms array hast exactly 182 elements */
    10451 assert(t*(t+1)+(33-n) < 182);
    10452
    10453 return binoms[t*(t+1)+(33-n)]; /*lint !e662 !e661*/
    10454 }
    10455}
    10456
    10457#ifndef NDEBUG
    10458/** calculates hash for floating-point number by using Fibonacci hashing */
    10459#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ * 10 >= 490 && !defined(__INTEL_COMPILER)
    10460__attribute__((no_sanitize_undefined))
    10461#endif
    10462unsigned int SCIPcalcFibHash(
    10463 SCIP_Real v /**< number to hash */
    10464 )
    10465{
    10466 if( v >= 0 )
    10467 return ((unsigned long long)(v * 2654435769)) % UINT_MAX;
    10468 return ((unsigned long long)(-v * 683565275)) % UINT_MAX;
    10469}
    10470#endif
    10471
    10472/** negates a number */
    10474 SCIP_Real x /**< value to negate */
    10475 )
    10476{
    10477 return -x;
    10478}
    10479
    10480/*
    10481 * Permutations / Shuffling
    10482 */
    10483
    10484/** swaps two ints */
    10486 int* value1, /**< pointer to first integer */
    10487 int* value2 /**< pointer to second integer */
    10488 )
    10489{
    10490 int tmp;
    10491
    10492 tmp = *value1;
    10493 *value1 = *value2;
    10494 *value2 = tmp;
    10495}
    10496
    10497/** swaps two real values */
    10499 SCIP_Real* value1, /**< pointer to first real value */
    10500 SCIP_Real* value2 /**< pointer to second real value */
    10501 )
    10502{
    10503 SCIP_Real tmp;
    10504
    10505 tmp = *value1;
    10506 *value1 = *value2;
    10507 *value2 = tmp;
    10508}
    10509
    10510/** swaps the addresses of two pointers */
    10512 void** pointer1, /**< first pointer */
    10513 void** pointer2 /**< second pointer */
    10514 )
    10515{
    10516 void* tmp;
    10517
    10518 tmp = *pointer1;
    10519 *pointer1 = *pointer2;
    10520 *pointer2 = tmp;
    10521}
    10522
    10523
    10524/*
    10525 * Arrays
    10526 */
    10527
    10528
    10529/** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly */
    10531 int* array1, /**< first array (in ascending order) */
    10532 int narray1, /**< number of entries of first array */
    10533 int* array2, /**< second array (in ascending order) */
    10534 int narray2, /**< number of entries of second array */
    10535 int* intersectarray, /**< intersection of array1 and array2
    10536 * (note: it is possible to use array1 for this input argument) */
    10537 int* nintersectarray /**< pointer to store number of entries of intersection array
    10538 * (note: it is possible to use narray1 for this input argument) */
    10539 )
    10540{
    10541 int cnt = 0;
    10542 int k = 0;
    10543 int v1;
    10544 int v2;
    10545
    10546 assert( array1 != NULL );
    10547 assert( array2 != NULL );
    10548 assert( intersectarray != NULL );
    10549 assert( nintersectarray != NULL );
    10550
    10551 /* determine intersection of array1 and array2 */
    10552 for (v1 = 0; v1 < narray1; ++v1)
    10553 {
    10554 assert( v1 == 0 || array1[v1] >= array1[v1-1] );
    10555
    10556 /* skip duplicate entries */
    10557 if ( v1+1 < narray1 && array1[v1] == array1[v1+1])
    10558 continue;
    10559
    10560 for (v2 = k; v2 < narray2; ++v2)
    10561 {
    10562 assert( v2 == 0 || array2[v2] >= array2[v2-1] );
    10563
    10564 if ( array2[v2] > array1[v1] )
    10565 {
    10566 k = v2;
    10567 break;
    10568 }
    10569 else if ( array2[v2] == array1[v1] )
    10570 {
    10571 intersectarray[cnt++] = array2[v2];
    10572 k = v2 + 1;
    10573 break;
    10574 }
    10575 }
    10576 }
    10577
    10578 /* store size of intersection array */
    10579 *nintersectarray = cnt;
    10580}
    10581
    10582/** computes set intersection (duplicates removed) of two void-pointer arrays that are ordered ascendingly */
    10584 void** array1, /**< pointer to first data array */
    10585 int narray1, /**< number of entries of first array */
    10586 void** array2, /**< pointer to second data array */
    10587 int narray2, /**< number of entries of second array */
    10588 SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
    10589 void** intersectarray, /**< intersection of array1 and array2
    10590 * (note: it is possible to use array1 for this input argument) */
    10591 int* nintersectarray /**< pointer to store number of entries of intersection array
    10592 * (note: it is possible to use narray1 for this input argument) */
    10593 )
    10594{
    10595 int cnt = 0;
    10596 int k = 0;
    10597 int v1;
    10598 int v2;
    10599
    10600 assert( array1 != NULL );
    10601 assert( array2 != NULL );
    10602 assert( ptrcomp != NULL );
    10603 assert( intersectarray != NULL );
    10604 assert( nintersectarray != NULL );
    10605
    10606 /* determine intersection of array1 and array2 */
    10607 for( v1 = 0; v1 < narray1; ++v1 )
    10608 {
    10609 assert( v1 == 0 || (*ptrcomp)(array1[v1], array1[v1-1]) >= 0 );
    10610
    10611 /* skip duplicate entries */
    10612 if( v1+1 < narray1 && array1[v1] == array1[v1+1] )
    10613 continue;
    10614
    10615 for( v2 = k; v2 < narray2; ++v2 )
    10616 {
    10617 assert( v2 == 0 || (*ptrcomp)(array2[v2], array2[v2-1]) > 0 || array2[v2] == array2[v2-1] );
    10618
    10619 if( (*ptrcomp)(array2[v2], array1[v1]) > 0 )
    10620 {
    10621 k = v2;
    10622 break;
    10623 }
    10624
    10625 if( array2[v2] == array1[v1] )
    10626 {
    10627 intersectarray[cnt++] = array2[v2];
    10628 k = v2 + 1;
    10629 break;
    10630 }
    10631 }
    10632 }
    10633
    10634 /* store size of intersection array */
    10635 *nintersectarray = cnt;
    10636}
    10637
    10638/** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly */
    10640 int* array1, /**< first array (in ascending order) */
    10641 int narray1, /**< number of entries of first array */
    10642 int* array2, /**< second array (in ascending order) */
    10643 int narray2, /**< number of entries of second array */
    10644 int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
    10645 * (note: it is possible to use array1 for this input argument) */
    10646 int* nsetminusarray /**< pointer to store number of entries of setminus array
    10647 * (note: it is possible to use narray1 for this input argument) */
    10648 )
    10649{
    10650 int cnt = 0;
    10651 int v1 = 0;
    10652 int v2 = 0;
    10653
    10654 assert( array1 != NULL );
    10655 assert( array2 != NULL );
    10656 assert( setminusarray != NULL );
    10657 assert( nsetminusarray != NULL );
    10658
    10659 while ( v1 < narray1 )
    10660 {
    10661 int entry1;
    10662
    10663 assert( v1 == 0 || array1[v1] >= array1[v1-1] );
    10664
    10665 /* skip duplicate entries */
    10666 while ( v1 + 1 < narray1 && array1[v1] == array1[v1 + 1] )
    10667 ++v1;
    10668
    10669 entry1 = array1[v1];
    10670
    10671 while ( v2 < narray2 && array2[v2] < entry1 )
    10672 ++v2;
    10673
    10674 if ( v2 >= narray2 || entry1 < array2[v2] )
    10675 setminusarray[cnt++] = entry1;
    10676 ++v1;
    10677 }
    10678
    10679 /* store size of setminus array */
    10680 *nsetminusarray = cnt;
    10681}
    10682
    10683
    10684/*
    10685 * Strings
    10686 */
    10687
    10688
    10689/** copies characters from 'src' to 'dest', copying is stopped when either the 'stop' character is reached or after
    10690 * 'cnt' characters have been copied, whichever comes first.
    10691 *
    10692 * @note undefined behavior on overlapping arrays
    10693 */
    10695 char* dest, /**< destination pointer to copy to */
    10696 const char* src, /**< source pointer to copy from */
    10697 char stop, /**< character when found stop copying */
    10698 unsigned int cnt /**< maximal number of characters to copy */
    10699 )
    10700{
    10701 if( dest == NULL || src == NULL || cnt == 0 )
    10702 return -1;
    10703 else
    10704 {
    10705 char* destination = dest;
    10706
    10707 while( cnt-- && (*destination++ = *src++) != stop ); /*lint !e722*/
    10708
    10709 return (int)(destination - dest);
    10710 }
    10711}
    10712
    10713/** prints an error message containing of the given string followed by a string describing the current system error
    10714 *
    10715 * Prefers to use the strerror_r method, which is threadsafe. On systems where this method does not exist,
    10716 * NO_STRERROR_R should be defined (see INSTALL). In this case, strerror is used which is not guaranteed to be
    10717 * threadsafe (on SUN-systems, it actually is).
    10718 */
    10720 const char* message /**< first part of the error message, e.g. the filename */
    10721 )
    10722{
    10723#ifdef NO_STRERROR_R
    10724 SCIPmessagePrintError("%s: %s\n", message, strerror(errno));
    10725#else
    10726 char buf[SCIP_MAXSTRLEN];
    10727
    10728#ifdef _WIN32
    10729 /* strerror_s returns 0 on success; the string is \0 terminated. */
    10730 if ( strerror_s(buf, SCIP_MAXSTRLEN, errno) != 0 )
    10731 SCIPmessagePrintError("Unknown error number %d or error message too long.\n", errno);
    10732 SCIPmessagePrintError("%s: %s\n", message, buf);
    10733#elif (_POSIX_C_SOURCE >= 200112L || __DARWIN_C_LEVEL > 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
    10734 /* We are in the POSIX/XSI case, where strerror_r returns 0 on success; \0 termination is unclear. */
    10735 if ( strerror_r(errno, buf, SCIP_MAXSTRLEN) != 0 )
    10736 SCIPmessagePrintError("Unknown error number %d.\n", errno);
    10737 buf[SCIP_MAXSTRLEN - 1] = '\0';
    10738 SCIPmessagePrintError("%s: %s\n", message, buf);
    10739#else
    10740 /* We are in the GNU case, where strerror_r returns a pointer to the error string. This string is possibly stored
    10741 * in buf and is always \0 terminated.
    10742 * However, if compiling on one system and executing on another system, we might actually call a different
    10743 * variant of the strerror_r function than we had at compile time.
    10744 */
    10745 char* errordescr;
    10746 *buf = '\0';
    10747 errordescr = strerror_r(errno, buf, SCIP_MAXSTRLEN);
    10748 if( *buf != '\0' )
    10749 {
    10750 /* strerror_r wrote into buf */
    10751 SCIPmessagePrintError("%s: %s\n", message, buf);
    10752 }
    10753 else if( errordescr != NULL )
    10754 {
    10755 /* strerror_r returned something non-NULL */
    10756 SCIPmessagePrintError("%s: %s\n", message, errordescr);
    10757 }
    10758 else
    10759 {
    10760 /* strerror_r did return NULL and did not write into buf */
    10761 SCIPmessagePrintError("Could not obtain description for error %d.\n", errno);
    10762 }
    10763#endif
    10764#endif
    10765}
    10766
    10767/** extracts tokens from strings - wrapper method for strtok_r() */
    10769 char* s, /**< string to parse */
    10770 const char* delim, /**< delimiters for parsing */
    10771 char** ptrptr /**< pointer to working char pointer - must stay the same while parsing */
    10772 )
    10773{
    10774#ifdef SCIP_NO_STRTOK_R
    10775 return strtok(s, delim);
    10776#else
    10777 return strtok_r(s, delim, ptrptr);
    10778#endif
    10779}
    10780
    10781/** translates the given string into a string where unescaped symbols ", ', and spaces are escaped with a \ prefix */
    10783 char* t, /**< target buffer to store escaped string */
    10784 int bufsize, /**< size of buffer t */
    10785 const char* s /**< string to transform into escaped string */
    10786 )
    10787{
    10788 int len;
    10789 int i;
    10790 int p;
    10791
    10792 assert(t != NULL);
    10793 assert(bufsize > 0);
    10794
    10795 len = (int)strlen(s);
    10796 for( p = 0, i = 0; i <= len && p < bufsize; ++i, ++p )
    10797 {
    10798 if( s[i] == '\\' )
    10799 {
    10800 t[p] = s[i];
    10801 ++p; /*lint !e850*/
    10802 ++i; /*lint !e850*/
    10803 }
    10804 else if( s[i] == ' ' || s[i] == '\"' || s[i] == '\'' )
    10805 {
    10806 t[p] = '\\';
    10807 ++p; /*lint !e850*/
    10808 }
    10809 if( i <= len && p < bufsize )
    10810 t[p] = s[i];
    10811 }
    10812 t[bufsize-1] = '\0';
    10813}
    10814
    10815/** increases string pointer as long as it refers to a space character or an explicit space control sequence */
    10817 char** s /**< pointer to string pointer */
    10818 )
    10819{
    10820 while( isspace((unsigned char)**s) || ( **s == '\\' && *(*s+1) != '\0' && strchr(SCIP_SPACECONTROL, *(*s+1)) ) )
    10821 *s += **s == '\\' ? 2 : 1;
    10822
    10823 return SCIP_OKAY;
    10824}
    10825
    10826/* safe version of snprintf */
    10828 char* t, /**< target string */
    10829 int len, /**< length of the string to copy */
    10830 const char* s, /**< source string */
    10831 ... /**< further parameters */
    10832 )
    10833{
    10834 va_list ap;
    10835 int n;
    10836
    10837 assert(t != NULL);
    10838 assert(len > 0);
    10839
    10840 va_start(ap, s); /*lint !e826*/
    10841
    10842#if defined(_MSC_VER) && _MSC_VER < 1900
    10843 n = _vsnprintf(t, (size_t) len, s, ap);
    10844#else
    10845 n = vsnprintf(t, (size_t) len, s, ap); /*lint !e571*/
    10846#endif
    10847 va_end(ap);
    10848
    10849 if( n < 0 || n >= len )
    10850 {
    10851#ifndef NDEBUG
    10852 if( n < 0 )
    10853 {
    10854 SCIPerrorMessage("vsnprintf returned %d\n",n);
    10855 }
    10856#endif
    10857 t[len-1] = '\0';
    10858 }
    10859 return n;
    10860}
    10861
    10862/** portable version of strcasecmp for case-insensitive comparison of two strings */
    10864 const char* s1, /**< first string */
    10865 const char* s2 /**< second string */
    10866 )
    10867{
    10868#ifdef _MSC_VER
    10869 return _stricmp(s1, s2);
    10870#else
    10871 return strcasecmp(s1, s2);
    10872#endif
    10873}
    10874
    10875/** portable version of strncasecmp for case-insensitive comparison of two strings up to a given number of characters */
    10877 const char* s1, /**< first string */
    10878 const char* s2, /**< second string */
    10879 int length /**< maximal length to compare */
    10880 )
    10881{
    10882 assert(length >= 0);
    10883#ifdef _MSC_VER
    10884 return _strnicmp(s1, s2, (size_t)length);
    10885#else
    10886 return strncasecmp(s1, s2, (size_t)length); /*lint !e571*/
    10887#endif
    10888}
    10889
    10890/** safe version of strncpy
    10891 *
    10892 * Copies string in s to t using at most @a size-1 nonzero characters (strncpy copies size characters). It always adds
    10893 * a terminating zero char. Does not pad the remaining string with zero characters (unlike strncpy). Returns the number
    10894 * of copied nonzero characters, if the length of s is at most size - 1, and returns size otherwise. Thus, the original
    10895 * string was truncated if the return value is size.
    10896 */
    10898 char* t, /**< target string */
    10899 const char* s, /**< source string */
    10900 int size /**< maximal size of t */
    10901 )
    10902{
    10903 int n;
    10904
    10905 if( size <= 0 )
    10906 return 0;
    10907
    10908 /* decrease size by 1 to create space for terminating zero char */
    10909 --size;
    10910 for( n = 0; n < size && *s != '\0'; n++ )
    10911 *(t++) = *(s++);
    10912 *t = '\0';
    10913
    10914 if( *s != '\0' )
    10915 ++n;
    10916
    10917 return n;
    10918}
    10919
    10920/** extract the next token as a integer value if it is one; in case no value is parsed the endptr is set to @p str
    10921 *
    10922 * @return Returns TRUE if a value could be extracted, otherwise FALSE
    10923 */
    10925 const char* str, /**< string to search */
    10926 int* value, /**< pointer to store the parsed value */
    10927 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
    10928 )
    10929{
    10930 assert(str != NULL);
    10931 assert(value != NULL);
    10932 assert(endptr != NULL);
    10933
    10934 /* init errno to detect possible errors */
    10935 errno = 0;
    10936
    10937 *value = (int) strtol(str, endptr, 10);
    10938
    10939 if( *endptr != str && *endptr != NULL )
    10940 {
    10941 SCIPdebugMessage("parsed integer value <%d>\n", *value);
    10942 return TRUE;
    10943 }
    10944 *endptr = (char*)str;
    10945
    10946 SCIPdebugMessage("failed parsing integer value <%s>\n", str);
    10947
    10948 return FALSE;
    10949}
    10950
    10951/** extract the next token as a double value if it is one; in case no value is parsed the endptr is set to @p str
    10952 *
    10953 * @return Returns TRUE if a value could be extracted, otherwise FALSE
    10954 */
    10956 const char* str, /**< string to search */
    10957 SCIP_Real* value, /**< pointer to store the parsed value */
    10958 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
    10959 )
    10960{
    10961 assert(str != NULL);
    10962 assert(value != NULL);
    10963 assert(endptr != NULL);
    10964
    10965 /* init errno to detect possible errors */
    10966 errno = 0;
    10967
    10968 *value = strtod(str, endptr);
    10969
    10970 if( *endptr != str && *endptr != NULL )
    10971 {
    10972 SCIPdebugMessage("parsed real value <%g>\n", *value);
    10973 return TRUE;
    10974 }
    10975 *endptr = (char*)str;
    10976
    10977 SCIPdebugMessage("failed parsing real value <%s>\n", str);
    10978
    10979 return FALSE;
    10980}
    10981
    10982/** copies the first size characters between a start and end character of str into token, if no error occurred endptr
    10983 * will point to the position after the read part, otherwise it will point to @p str
    10984 */
    10986 const char* str, /**< string to search */
    10987 char startchar, /**< character which defines the beginning */
    10988 char endchar, /**< character which defines the ending */
    10989 char* token, /**< string to store the copy */
    10990 int size, /**< size of the token char array */
    10991 char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
    10992 )
    10993{
    10994 const char* copystr;
    10995 int nchars;
    10996
    10997 assert(str != NULL);
    10998 assert(token != NULL);
    10999 assert(size > 0);
    11000 assert(endptr != NULL);
    11001
    11002 nchars = 0;
    11003
    11004 copystr = str;
    11005
    11006 /* find starting character */
    11007 while( *str != '\0' && *str != startchar )
    11008 ++str;
    11009
    11010 /* did not find start character */
    11011 if( *str == '\0' )
    11012 {
    11013 *endptr = (char*)copystr;
    11014 return;
    11015 }
    11016
    11017 /* skip start character */
    11018 ++str;
    11019
    11020 /* copy string */
    11021 while( *str != '\0' && *str != endchar && nchars < size-1 )
    11022 {
    11023 assert(nchars < SCIP_MAXSTRLEN);
    11024 token[nchars] = *str;
    11025 nchars++;
    11026 ++str;
    11027 }
    11028
    11029 /* add end to token */
    11030 token[nchars] = '\0';
    11031
    11032 /* if section was longer than size, we want to reach the end of the parsing section anyway */
    11033 if( nchars == (size-1) )
    11034 while( *str != '\0' && *str != endchar )
    11035 ++str;
    11036
    11037 /* did not find end character */
    11038 if( *str == '\0' )
    11039 {
    11040 *endptr = (char*)copystr;
    11041 return;
    11042 }
    11043
    11044 /* skip end character */
    11045 ++str;
    11046
    11047 SCIPdebugMessage("parsed section <%s>\n", token);
    11048
    11049 *endptr = (char*) str;
    11050}
    11051
    11052/*
    11053 * File methods
    11054 */
    11055
    11056/** returns whether the given file exists */
    11058 const char* filename /**< file name */
    11059 )
    11060{
    11061 FILE* f;
    11062
    11063 f = fopen(filename, "r");
    11064 if( f == NULL )
    11065 return FALSE;
    11066
    11067 fclose(f);
    11068
    11069 return TRUE;
    11070}
    11071
    11072/** splits filename into path, name, and extension */
    11074 char* filename, /**< filename to split; is destroyed (but not freed) during process */
    11075 char** path, /**< pointer to store path, or NULL if not needed */
    11076 char** name, /**< pointer to store name, or NULL if not needed */
    11077 char** extension, /**< pointer to store extension, or NULL if not needed */
    11078 char** compression /**< pointer to store compression extension, or NULL if not needed */
    11079 )
    11080{
    11081 char* lastslash;
    11082 char* lastbackslash;
    11083 char* lastdot;
    11084
    11085 assert(filename != NULL);
    11086
    11087 if( path != NULL )
    11088 *path = NULL;
    11089 if( name != NULL )
    11090 *name = NULL;
    11091 if( extension != NULL )
    11092 *extension = NULL;
    11093 if( compression != NULL )
    11094 *compression = NULL;
    11095
    11096 /* treat both slashes '/' and '\' as directory delimiters */
    11097 lastslash = strrchr(filename, '/');
    11098 lastbackslash = strrchr(filename, '\\');
    11099 lastslash = MAX(lastslash, lastbackslash); /*lint !e613*/
    11100 lastdot = strrchr(filename, '.');
    11101 if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
    11102 lastdot = NULL;
    11103
    11104 /* detect known compression extensions */
    11105#ifdef SCIP_WITH_ZLIB
    11106 if( lastdot != NULL )
    11107 {
    11108 char* compext;
    11109
    11110 compext = lastdot+1;
    11111 if( strcmp(compext, "gz") == 0
    11112 || strcmp(compext, "z") == 0
    11113 || strcmp(compext, "Z") == 0 )
    11114 {
    11115 if( compression != NULL )
    11116 *compression = compext;
    11117 *lastdot = '\0';
    11118 }
    11119
    11120 /* find again the last dot in the filename without compression extension */
    11121 lastdot = strrchr(filename, '.');
    11122 if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
    11123 lastdot = NULL;
    11124 }
    11125#endif
    11126
    11127 if( lastslash == NULL )
    11128 {
    11129 if( name != NULL )
    11130 *name = filename;
    11131 }
    11132 else
    11133 {
    11134 if( path != NULL )
    11135 *path = filename;
    11136 if( name != NULL )
    11137 *name = lastslash+1;
    11138 *lastslash = '\0';
    11139 }
    11140
    11141 if( lastdot != NULL )
    11142 {
    11143 if( extension != NULL )
    11144 *extension = lastdot+1;
    11145 *lastdot = '\0';
    11146 }
    11147}
    11148
    11149/*
    11150 * simple functions implemented as defines
    11151 */
    11152
    11153/* In debug mode, the following methods are implemented as function calls to ensure
    11154 * type validity.
    11155 * In optimized mode, the methods are implemented as defines to improve performance.
    11156 * However, we want to have them in the library anyways, so we have to undef the defines.
    11157 */
    11158
    11159#undef SCIPrelDiff
    11160
    11161/** returns the relative difference: (val1-val2)/max(|val1|,|val2|,1.0) */
    11163 SCIP_Real val1, /**< first value to be compared */
    11164 SCIP_Real val2 /**< second value to be compared */
    11165 )
    11166{
    11167 SCIP_Real absval1;
    11168 SCIP_Real absval2;
    11169 SCIP_Real quot;
    11170
    11171 absval1 = REALABS(val1);
    11172 absval2 = REALABS(val2);
    11173 quot = MAX3(1.0, absval1, absval2);
    11174
    11175 return (val1-val2)/quot;
    11176}
    11177
    11178
    11179/** computes the gap from the primal and the dual bound */
    11181 SCIP_Real eps, /**< the value treated as zero */
    11182 SCIP_Real inf, /**< the value treated as infinity */
    11183 SCIP_Real primalbound, /**< the primal bound */
    11184 SCIP_Real dualbound /**< the dual bound */
    11185 )
    11186{
    11187 if( EPSEQ(primalbound, dualbound, eps) )
    11188 return 0.0;
    11189 else
    11190 {
    11191 SCIP_Real absdual = REALABS(dualbound);
    11192 SCIP_Real absprimal = REALABS(primalbound);
    11193
    11194 if( EPSZ(dualbound, eps) || EPSZ(primalbound, eps) || absprimal >= inf || absdual >= inf ||
    11195 primalbound * dualbound < 0.0 )
    11196 return inf;
    11197 else
    11198 return REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
    11199 }
    11200}
    11201
    11202/*
    11203 * disjoint set (union-find) data structure
    11204 */
    11205
    11206/** creates a disjoint set (union find) structure \p djset for \p ncomponents many components (of size one) */
    11208 SCIP_DISJOINTSET** djset, /**< disjoint set (union find) data structure */
    11209 BMS_BLKMEM* blkmem, /**< block memory */
    11210 int ncomponents /**< number of components */
    11211 )
    11212{
    11213 assert(djset != NULL);
    11214 assert(blkmem != NULL);
    11215
    11216 /* allocate the necessary memory */
    11217 assert(ncomponents > 0);
    11218 SCIP_ALLOC( BMSallocBlockMemory(blkmem, djset) );
    11219 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->parents), ncomponents) );
    11220 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->sizes), ncomponents) );
    11221 (*djset)->size = ncomponents;
    11222
    11223 /* clear the data structure */
    11224 SCIPdisjointsetClear(*djset);
    11225
    11226 return SCIP_OKAY;
    11227}
    11228
    11229/** clears the disjoint set (union find) structure \p djset */
    11231 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
    11232 )
    11233{
    11234 int i;
    11235
    11236 djset->componentcount = djset->size;
    11237
    11238 /* reset all components to be unconnected */
    11239 for( i = 0; i < djset->componentcount; i++ )
    11240 {
    11241 djset->parents[i] = i;
    11242 djset->sizes[i] = 1;
    11243 }
    11244}
    11245
    11246/** finds and returns the component identifier of this \p element */
    11248 SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
    11249 int element /**< element to be found */
    11250 )
    11251{
    11252 int newelement;
    11253 int root = element;
    11254 int* parents = djset->parents;
    11255
    11256 /* find root of this element */
    11257 while( root != parents[root] )
    11258 {
    11259 root = parents[root];
    11260 }
    11261
    11262 /* compress the path to make future queries faster */
    11263 while( element != root )
    11264 {
    11265 newelement = parents[element];
    11266 parents[element] = root;
    11267 element = newelement;
    11268 }
    11269
    11270 return root;
    11271}
    11272
    11273/** merges the components containing the elements \p p and \p q */
    11275 SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
    11276 int p, /**< first element */
    11277 int q, /**< second element */
    11278 SCIP_Bool forcerepofp /**< force representative of p to be new representative */
    11279 )
    11280{
    11281 int idp;
    11282 int idq;
    11283 int* sizes;
    11284 int* parents;
    11285
    11286 assert(djset != NULL);
    11287 assert(0 <= p);
    11288 assert(0 <= q);
    11289 assert(djset->size > p);
    11290 assert(djset->size > q);
    11291
    11292 idp = SCIPdisjointsetFind(djset, p);
    11293 idq = SCIPdisjointsetFind(djset, q);
    11294
    11295 /* if p and q lie in the same component, there is nothing to be done */
    11296 if( idp == idq )
    11297 return;
    11298
    11299 sizes = djset->sizes;
    11300 parents = djset->parents;
    11301
    11302 if( forcerepofp )
    11303 {
    11304 parents[idq] = idp;
    11305 sizes[idp] += sizes[idq];
    11306 }
    11307 else
    11308 {
    11309 if( sizes[idp] < sizes[idq] )
    11310 {
    11311 parents[idp] = idq;
    11312 sizes[idq] += sizes[idp];
    11313 }
    11314 else
    11315 {
    11316 parents[idq] = idp;
    11317 sizes[idp] += sizes[idq];
    11318 }
    11319 }
    11320 /* one less component */
    11321 djset->componentcount--;
    11322}
    11323
    11324/** frees the disjoint set (union find) data structure */
    11326 SCIP_DISJOINTSET** djset, /**< pointer to disjoint set (union find) data structure */
    11327 BMS_BLKMEM* blkmem /**< block memory */
    11328 )
    11329{
    11330 SCIP_DISJOINTSET* dsptr;
    11331
    11332 assert(djset != NULL);
    11333 assert(*djset != NULL);
    11334
    11335 dsptr = *djset;
    11336
    11337 BMSfreeBlockMemoryArray(blkmem, &dsptr->sizes, dsptr->size);
    11338 BMSfreeBlockMemoryArray(blkmem, &dsptr->parents, dsptr->size);
    11339
    11340 BMSfreeBlockMemory(blkmem, djset);
    11341}
    11342
    11343/** returns the number of independent components in this disjoint set (union find) data structure */
    11345 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
    11346 )
    11347{
    11348 assert(djset != NULL);
    11349
    11350 return djset->componentcount;
    11351}
    11352
    11353/** returns the size (number of nodes) of this disjoint set (union find) data structure */
    11355 SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
    11356 )
    11357{
    11358 assert(djset != NULL);
    11359
    11360 return djset->size;
    11361}
    11362
    11363/** checks whether a given string t appears at the beginning of the string s (up to spaces at beginning) */
    11365 const char* s, /**< string to search in */
    11366 const char* t, /**< string to search for */
    11367 size_t tlen /**< length of t */
    11368 )
    11369{
    11370 int idxctr = 0;
    11371
    11372 assert(s != NULL);
    11373 assert(t != NULL);
    11374
    11375 /* skip whitespace at beginning */
    11376 while( idxctr < SCIP_MAXSTRLEN && isspace((unsigned char)s[idxctr]) )
    11377 ++idxctr;
    11378 if( strncmp(&s[idxctr], t, tlen) == 0 )
    11379 return TRUE;
    11380 return FALSE;
    11381}
    SCIP_VAR * h
    Definition: circlepacking.c:68
    SCIP_VAR * w
    Definition: circlepacking.c:67
    SCIP_VAR * a
    Definition: circlepacking.c:66
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    SCIP_VAR ** y
    Definition: circlepacking.c:64
    SCIP_Real * r
    Definition: circlepacking.c:59
    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 SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_UNUSED(x)
    Definition: def.h:409
    #define LOG2(x)
    Definition: def.h:211
    #define SCIP_SPACECONTROL
    Definition: def.h:270
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_DEFAULT_EPSILON
    Definition: def.h:164
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define MAX3(x, y, z)
    Definition: def.h:228
    #define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
    Definition: def.h:386
    #define SCIP_Real
    Definition: def.h:156
    #define ABS(x)
    Definition: def.h:216
    #define EPSEQ(x, y, eps)
    Definition: def.h:183
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_CALL_TERMINATE(retcode, x, TERM)
    Definition: def.h:376
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define EPSFLOOR(x, eps)
    Definition: def.h:191
    #define REALABS(x)
    Definition: def.h:182
    #define EPSGT(x, y, eps)
    Definition: def.h:186
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define EPSZ(x, eps)
    Definition: def.h:188
    #define SCIP_CALL(x)
    Definition: def.h:355
    #define SCIP_CALL_FINALLY(x, y)
    Definition: def.h:397
    #define nnodes
    Definition: gastrans.c:74
    #define narcs
    Definition: gastrans.c:77
    void SCIPcomputeArraysIntersectionPtr(void **array1, int narray1, void **array2, int narray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void **intersectarray, int *nintersectarray)
    Definition: misc.c:10583
    void SCIPcomputeArraysSetminusInt(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
    Definition: misc.c:10639
    void SCIPcomputeArraysIntersectionInt(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
    Definition: misc.c:10530
    void SCIPbtnodeSetRightchild(SCIP_BTNODE *node, SCIP_BTNODE *right)
    Definition: misc.c:9023
    SCIP_BTNODE * SCIPbtnodeGetRightchild(SCIP_BTNODE *node)
    Definition: misc.c:8892
    SCIP_Bool SCIPbtIsEmpty(SCIP_BT *tree)
    Definition: misc.c:9135
    SCIP_RETCODE SCIPbtCreate(SCIP_BT **tree, BMS_BLKMEM *blkmem)
    Definition: misc.c:9034
    void SCIPbtnodeFree(SCIP_BT *tree, SCIP_BTNODE **node)
    Definition: misc.c:8817
    SCIP_Bool SCIPbtnodeIsLeaf(SCIP_BTNODE *node)
    Definition: misc.c:8932
    void SCIPbtnodeSetData(SCIP_BTNODE *node, void *dataptr)
    Definition: misc.c:8981
    void * SCIPbtnodeGetData(SCIP_BTNODE *node)
    Definition: misc.c:8862
    SCIP_RETCODE SCIPbtnodeCreate(SCIP_BT *tree, SCIP_BTNODE **node, void *dataptr)
    Definition: misc.c:8753
    SCIP_Bool SCIPbtnodeIsRightchild(SCIP_BTNODE *node)
    Definition: misc.c:8960
    void SCIPbtnodeSetParent(SCIP_BTNODE *node, SCIP_BTNODE *parent)
    Definition: misc.c:8995
    SCIP_BTNODE * SCIPbtnodeGetSibling(SCIP_BTNODE *node)
    Definition: misc.c:8902
    SCIP_Bool SCIPbtnodeIsLeftchild(SCIP_BTNODE *node)
    Definition: misc.c:8942
    void SCIPbtnodeSetLeftchild(SCIP_BTNODE *node, SCIP_BTNODE *left)
    Definition: misc.c:9009
    SCIP_BTNODE * SCIPbtnodeGetParent(SCIP_BTNODE *node)
    Definition: misc.c:8872
    void SCIPbtFree(SCIP_BT **tree)
    Definition: misc.c:9053
    SCIP_BTNODE * SCIPbtnodeGetLeftchild(SCIP_BTNODE *node)
    Definition: misc.c:8882
    void SCIPbtSetRoot(SCIP_BT *tree, SCIP_BTNODE *root)
    Definition: misc.c:9158
    SCIP_Bool SCIPbtnodeIsRoot(SCIP_BTNODE *node)
    Definition: misc.c:8922
    SCIP_BTNODE * SCIPbtGetRoot(SCIP_BT *tree)
    Definition: misc.c:9145
    void SCIPbtPrintGml(SCIP_BT *tree, FILE *file)
    Definition: misc.c:9105
    void SCIPdigraphPrintComponents(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
    Definition: misc.c:8700
    void ** SCIPdigraphGetSuccessorsData(SCIP_DIGRAPH *digraph, int node)
    Definition: misc.c:7914
    void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
    Definition: misc.c:8594
    int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
    Definition: misc.c:7881
    SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
    Definition: misc.c:8165
    int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
    Definition: misc.c:7823
    void SCIPdigraphPrintGml(SCIP_DIGRAPH *digraph, FILE *file)
    Definition: misc.c:8661
    void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
    Definition: misc.c:8374
    SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
    Definition: misc.c:7739
    SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
    Definition: misc.c:8295
    SCIP_RETCODE SCIPdigraphSetSizes(SCIP_DIGRAPH *digraph, int *sizes)
    Definition: misc.c:7621
    SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
    Definition: misc.c:8506
    SCIP_RETCODE SCIPdigraphAddArcSafe(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
    Definition: misc.c:7770
    void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
    Definition: misc.c:7645
    int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
    Definition: misc.c:7863
    void SCIPdigraphPrint(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
    Definition: misc.c:8626
    void * SCIPdigraphGetNodeData(SCIP_DIGRAPH *digraph, int node)
    Definition: misc.c:7833
    void SCIPdigraphSetNodeData(SCIP_DIGRAPH *digraph, void *dataptr, int node)
    Definition: misc.c:7849
    SCIP_RETCODE SCIPdigraphSetNSuccessors(SCIP_DIGRAPH *digraph, int node, int nsuccessors)
    Definition: misc.c:7807
    int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
    Definition: misc.c:7896
    int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
    Definition: misc.c:8361
    SCIP_RETCODE SCIPdigraphResize(SCIP_DIGRAPH *digraph, int nnodes)
    Definition: misc.c:7491
    SCIP_RETCODE SCIPdigraphGetArticulationPoints(SCIP_DIGRAPH *digraph, int **articulations, int *narticulations)
    Definition: misc.c:8077
    int SCIPdisjointsetGetSize(SCIP_DISJOINTSET *djset)
    Definition: misc.c:11354
    void SCIPdisjointsetClear(SCIP_DISJOINTSET *djset)
    Definition: misc.c:11230
    int SCIPdisjointsetGetComponentCount(SCIP_DISJOINTSET *djset)
    Definition: misc.c:11344
    int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
    Definition: misc.c:11247
    void SCIPdisjointsetUnion(SCIP_DISJOINTSET *djset, int p, int q, SCIP_Bool forcerepofp)
    Definition: misc.c:11274
    SCIP_Bool SCIPfileExists(const char *filename)
    Definition: misc.c:11057
    void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
    Definition: misc.c:11073
    void SCIPdotWriteOpening(FILE *file)
    Definition: misc.c:715
    void SCIPdotWriteClosing(FILE *file)
    Definition: misc.c:753
    void SCIPdotWriteArc(FILE *file, int source, int target, const char *color)
    Definition: misc.c:740
    void SCIPgmlWriteNodeWeight(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor, SCIP_Real weight)
    Definition: misc.c:549
    void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
    Definition: misc.c:501
    void SCIPgmlWriteClosing(FILE *file)
    Definition: misc.c:703
    void SCIPdotWriteNode(FILE *file, int node, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
    Definition: misc.c:725
    void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
    Definition: misc.c:687
    void SCIPgmlWriteEdge(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
    Definition: misc.c:599
    void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
    Definition: misc.c:643
    void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
    Definition: misc.c:3095
    void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3613
    SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3344
    SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
    Definition: misc.c:3251
    void SCIPhashmapPrintStatistics(SCIP_HASHMAP *hashmap, SCIP_MESSAGEHDLR *messagehdlr)
    Definition: misc.c:3528
    int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3304
    void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3284
    SCIP_RETCODE SCIPhashmapSetImageReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
    Definition: misc.c:3434
    void SCIPhashmapEntrySetImageInt(SCIP_HASHMAPENTRY *entry, int image)
    Definition: misc.c:3654
    SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
    Definition: misc.c:3143
    SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
    Definition: misc.c:3366
    int SCIPhashmapGetNElements(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3576
    int SCIPhashmapEntryGetImageInt(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3623
    void SCIPhashmapEntrySetImageReal(SCIP_HASHMAPENTRY *entry, SCIP_Real image)
    Definition: misc.c:3665
    int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3584
    SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
    Definition: misc.c:3592
    void SCIPhashmapEntrySetImage(SCIP_HASHMAPENTRY *entry, void *image)
    Definition: misc.c:3643
    SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
    Definition: misc.c:3061
    void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3603
    SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3466
    SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
    Definition: misc.c:3179
    SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3566
    SCIP_RETCODE SCIPhashmapInsertLong(SCIP_HASHMAP *hashmap, void *origin, SCIP_Longint image)
    Definition: misc.c:3215
    SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3676
    SCIP_Real SCIPhashmapEntryGetImageReal(SCIP_HASHMAPENTRY *entry)
    Definition: misc.c:3633
    SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3482
    SCIP_Longint SCIPhashmapGetImageLong(SCIP_HASHMAP *hashmap, void *origin)
    Definition: misc.c:3324
    SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
    Definition: misc.c:3400
    void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
    Definition: misc.c:3833
    void SCIPhashsetPrintStatistics(SCIP_HASHSET *hashset, SCIP_MESSAGEHDLR *messagehdlr)
    Definition: misc.c:3976
    SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
    Definition: misc.c:3860
    void ** SCIPhashsetGetSlots(SCIP_HASHSET *hashset)
    Definition: misc.c:4051
    int SCIPhashsetGetNElements(SCIP_HASHSET *hashset)
    Definition: misc.c:4035
    int SCIPhashsetGetNSlots(SCIP_HASHSET *hashset)
    Definition: misc.c:4043
    void SCIPhashsetRemoveAll(SCIP_HASHSET *hashset)
    Definition: misc.c:4059
    SCIP_Bool SCIPhashsetIsEmpty(SCIP_HASHSET *hashset)
    Definition: misc.c:4027
    SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
    Definition: misc.c:3843
    SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
    Definition: misc.c:3802
    SCIP_RETCODE SCIPhashsetRemove(SCIP_HASHSET *hashset, void *element)
    Definition: misc.c:3901
    void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
    Definition: misc.c:2348
    SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2647
    #define SCIPhashTwo(a, b)
    Definition: pub_misc.h:568
    int SCIPhashtableGetNEntries(SCIP_HASHTABLE *hashtable)
    Definition: misc.c:2765
    SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2567
    void * SCIPhashtableGetEntry(SCIP_HASHTABLE *hashtable, int entryidx)
    Definition: misc.c:2773
    SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
    Definition: misc.c:2298
    void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
    Definition: misc.c:2596
    void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
    Definition: misc.c:2743
    SCIP_Real SCIPhashtableGetLoad(SCIP_HASHTABLE *hashtable)
    Definition: misc.c:2782
    void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
    Definition: misc.c:2792
    SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2665
    SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
    Definition: misc.c:2535
    SCIP_Longint SCIPhashtableGetNElements(SCIP_HASHTABLE *hashtable)
    Definition: misc.c:2755
    SCIP_Longint SCIPmultihashGetNElements(SCIP_MULTIHASH *multihash)
    Definition: misc.c:2233
    void SCIPmultihashFree(SCIP_MULTIHASH **multihash)
    Definition: misc.c:1995
    SCIP_RETCODE SCIPmultihashInsert(SCIP_MULTIHASH *multihash, void *element)
    Definition: misc.c:2026
    SCIP_RETCODE SCIPmultihashRemove(SCIP_MULTIHASH *multihash, void *element)
    Definition: misc.c:2178
    void SCIPmultihashRemoveAll(SCIP_MULTIHASH *multihash)
    Definition: misc.c:2212
    SCIP_RETCODE SCIPmultihashSafeInsert(SCIP_MULTIHASH *multihash, void *element)
    Definition: misc.c:2067
    SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
    Definition: misc.c:2830
    int SCIPcalcMultihashSize(int minsize)
    Definition: misc.c:1639
    SCIP_Real SCIPmultihashGetLoad(SCIP_MULTIHASH *multihash)
    Definition: misc.c:2243
    SCIP_RETCODE SCIPmultihashCreate(SCIP_MULTIHASH **multihash, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
    Definition: misc.c:1962
    SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
    Definition: misc.c:2839
    void * SCIPmultihashRetrieve(SCIP_MULTIHASH *multihash, void *key)
    Definition: misc.c:2086
    void * SCIPmultihashRetrieveNext(SCIP_MULTIHASH *multihash, SCIP_MULTIHASHLIST **multihashlist, void *key)
    Definition: misc.c:2115
    SCIP_Bool SCIPmultihashExists(SCIP_MULTIHASH *multihash, void *element)
    Definition: misc.c:2151
    void SCIPmultihashPrintStatistics(SCIP_MULTIHASH *multihash, SCIP_MESSAGEHDLR *messagehdlr)
    Definition: misc.c:2253
    SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
    Definition: misc.c:2858
    SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
    Definition: misc.c:9197
    SCIP_Longint SCIPcalcBinomCoef(int n, int m)
    Definition: misc.c:10387
    SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
    Definition: misc.c:9449
    SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
    Definition: misc.c:10041
    SCIP_Real SCIPcomputeGap(SCIP_Real eps, SCIP_Real inf, SCIP_Real primalbound, SCIP_Real dualbound)
    Definition: misc.c:11180
    SCIP_Bool SCIPfindSimpleRational(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
    Definition: misc.c:9994
    SCIP_Real SCIPcalcRootNewton(SCIP_DECL_NEWTONEVAL((*function)), SCIP_DECL_NEWTONEVAL((*derivative)), SCIP_Real *params, int nparams, SCIP_Real x, SCIP_Real eps, int k)
    Definition: misc.c:10082
    SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
    Definition: misc.c:9440
    SCIP_RETCODE SCIPcalcIntegralScalarExact(BMS_BUFMEM *buffer, SCIP_RATIONAL **vals, int nvals, SCIP_Real maxscale, SCIP_RATIONAL *intscalar, SCIP_Bool *success)
    Definition: misc.c:9842
    SCIP_Bool SCIPrealIsExactlyIntegral(SCIP_Real val)
    Definition: misc.c:9604
    SCIP_Real SCIPcalcMachineEpsilon(void)
    Definition: misc.c:9174
    unsigned int SCIPcalcFibHash(SCIP_Real v)
    Definition: misc.c:10462
    SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *numerator, SCIP_Longint *denominator)
    Definition: misc.c:9470
    SCIP_RETCODE SCIPcalcIntegralScalar(SCIP_Real *vals, int nvals, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Real *intscalar, SCIP_Bool *success)
    Definition: misc.c:9641
    SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
    Definition: misc.c:11162
    void SCIPswapInts(int *value1, int *value2)
    Definition: misc.c:10485
    void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
    Definition: misc.c:10264
    void SCIPswapPointers(void **pointer1, void **pointer2)
    Definition: misc.c:10511
    void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
    Definition: misc.c:10498
    void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
    Definition: misc.c:10294
    void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1540
    void SCIPpqueueDelPos(SCIP_PQUEUE *pqueue, int pos)
    Definition: misc.c:1435
    void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1335
    int SCIPpqueueFind(SCIP_PQUEUE *pqueue, void *elem)
    Definition: misc.c:1551
    void SCIPpqueueFree(SCIP_PQUEUE **pqueue)
    Definition: misc.c:1324
    SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
    Definition: misc.c:1396
    int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1529
    SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)))
    Definition: misc.c:1297
    void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1495
    void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
    Definition: misc.c:1515
    void SCIPintervalSetRoundingModeDownwards(void)
    SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
    void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
    int SCIP_ROUNDMODE
    Definition: intervalarith.h:65
    SCIP_Bool SCIPintervalHasRoundingControl(void)
    void SCIPrationalMult(SCIP_RATIONAL *res, SCIP_RATIONAL *op1, SCIP_RATIONAL *op2)
    Definition: rational.cpp:1066
    void SCIPrationalFreeBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:473
    SCIP_Longint SCIPrationalDenominator(SCIP_RATIONAL *rational)
    Definition: rational.cpp:2027
    SCIP_RETCODE SCIPrationalCreateBuffer(BMS_BUFMEM *bufmem, SCIP_RATIONAL **rational)
    Definition: rational.cpp:123
    SCIP_Bool SCIPrationalIsZero(SCIP_RATIONAL *rational)
    Definition: rational.cpp:1624
    void SCIPrationalCanonicalize(SCIP_RATIONAL *rational)
    Definition: rational.cpp:538
    void SCIPrationalSetFraction(SCIP_RATIONAL *res, SCIP_Longint nom, SCIP_Longint denom)
    Definition: rational.cpp:582
    SCIP_Longint SCIPrationalNumerator(SCIP_RATIONAL *rational)
    Definition: rational.cpp:2018
    int SCIPqueueNElems(SCIP_QUEUE *queue)
    Definition: misc.c:1249
    unsigned int SCIPqueueRemoveUInt(SCIP_QUEUE *queue)
    Definition: misc.c:1166
    void SCIPqueueFree(SCIP_QUEUE **queue)
    Definition: misc.c:1019
    SCIP_RETCODE SCIPqueueInsertUInt(SCIP_QUEUE *queue, unsigned int elem)
    Definition: misc.c:1107
    SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
    Definition: misc.c:995
    void SCIPqueueClear(SCIP_QUEUE *queue)
    Definition: misc.c:1030
    SCIP_RETCODE SCIPqueueInsert(SCIP_QUEUE *queue, void *elem)
    Definition: misc.c:1081
    SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
    Definition: misc.c:1236
    void * SCIPqueueRemove(SCIP_QUEUE *queue)
    Definition: misc.c:1132
    void * SCIPqueueFirst(SCIP_QUEUE *queue)
    Definition: misc.c:1200
    unsigned int SCIPqueueFirstUInt(SCIP_QUEUE *queue)
    Definition: misc.c:1218
    SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
    Definition: misc.c:10245
    SCIP_RETCODE SCIPrandomGetSubset(SCIP_RANDNUMGEN *randnumgen, void **set, int nelems, void **subset, int nsubelems)
    Definition: misc.c:10326
    int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
    Definition: misc.c:10223
    void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
    Definition: misc.c:353
    void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
    Definition: misc.c:385
    SCIP_Real SCIPregressionGetIntercept(SCIP_REGRESSION *regression)
    Definition: misc.c:278
    int SCIPregressionGetNObservations(SCIP_REGRESSION *regression)
    Definition: misc.c:258
    void SCIPregressionFree(SCIP_REGRESSION **regression)
    Definition: misc.c:436
    SCIP_RETCODE SCIPregressionCreate(SCIP_REGRESSION **regression)
    Definition: misc.c:420
    void SCIPregressionReset(SCIP_REGRESSION *regression)
    Definition: misc.c:404
    SCIP_Real SCIPregressionGetSlope(SCIP_REGRESSION *regression)
    Definition: misc.c:268
    SCIP_RETCODE SCIPactivityCreate(SCIP_RESOURCEACTIVITY **activity, SCIP_VAR *var, int duration, int demand)
    Definition: misc.c:6718
    int SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY *activity)
    Definition: misc.c:6773
    int SCIPactivityGetEnergy(SCIP_RESOURCEACTIVITY *activity)
    Definition: misc.c:6793
    SCIP_VAR * SCIPactivityGetVar(SCIP_RESOURCEACTIVITY *activity)
    Definition: misc.c:6763
    int SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY *activity)
    Definition: misc.c:6783
    void SCIPactivityFree(SCIP_RESOURCEACTIVITY **activity)
    Definition: misc.c:6737
    SCIP_RETCODE SCIPprofileInsertCore(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
    Definition: misc.c:7097
    int * SCIPprofileGetTimepoints(SCIP_PROFILE *profile)
    Definition: misc.c:6904
    int SCIPprofileGetLatestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
    Definition: misc.c:7366
    SCIP_Bool SCIPprofileFindLeft(SCIP_PROFILE *profile, int timepoint, int *pos)
    Definition: misc.c:6950
    int SCIPprofileGetEarliestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
    Definition: misc.c:7217
    int SCIPprofileGetNTimepoints(SCIP_PROFILE *profile)
    Definition: misc.c:6894
    void SCIPprofileFree(SCIP_PROFILE **profile)
    Definition: misc.c:6846
    int SCIPprofileGetLoad(SCIP_PROFILE *profile, int pos)
    Definition: misc.c:6936
    int * SCIPprofileGetLoads(SCIP_PROFILE *profile)
    Definition: misc.c:6914
    SCIP_RETCODE SCIPprofileCreate(SCIP_PROFILE **profile, int capacity)
    Definition: misc.c:6832
    int SCIPprofileGetTime(SCIP_PROFILE *profile, int pos)
    Definition: misc.c:6924
    int SCIPprofileGetCapacity(SCIP_PROFILE *profile)
    Definition: misc.c:6884
    SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
    Definition: misc.c:7127
    void SCIPprofilePrint(SCIP_PROFILE *profile, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
    Definition: misc.c:6862
    SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
    Definition: misc.c:200
    SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
    Definition: misc.c:127
    SCIP_Real SCIPnormalGetCriticalValue(SCIP_CONFIDENCELEVEL clevel)
    Definition: misc.c:187
    SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
    Definition: misc.c:110
    SCIP_Real SCIPerf(SCIP_Real x)
    Definition: misc.c:160
    void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
    void SCIPsortDown(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
    Definition: misc.c:6144
    SCIP_Bool SCIPsortedvecFindInt(int *intarray, int val, int len, int *pos)
    void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
    Definition: misc.c:5581
    SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
    Definition: misc.c:5523
    void SCIPsortedvecInsertIntInt(int *intarray1, int *intarray2, int keyval, int field1val, int *len, int *pos)
    void SCIPsortDownInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
    SCIP_DECL_SORTINDCOMP(SCIPsortArgsortInt)
    Definition: misc.c:5544
    int SCIPsparseSolGetNVars(SCIP_SPARSESOL *sparsesol)
    Definition: misc.c:841
    SCIP_Longint * SCIPsparseSolGetLbs(SCIP_SPARSESOL *sparsesol)
    Definition: misc.c:851
    void SCIPsparseSolGetFirstSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
    Definition: misc.c:871
    SCIP_RETCODE SCIPsparseSolCreate(SCIP_SPARSESOL **sparsesol, SCIP_VAR **vars, int nvars, SCIP_Bool cleared)
    Definition: misc.c:767
    SCIP_Longint * SCIPsparseSolGetUbs(SCIP_SPARSESOL *sparsesol)
    Definition: misc.c:861
    void SCIPsparseSolFree(SCIP_SPARSESOL **sparsesol)
    Definition: misc.c:817
    SCIP_Bool SCIPsparseSolGetNextSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
    Definition: misc.c:894
    SCIP_VAR ** SCIPsparseSolGetVars(SCIP_SPARSESOL *sparsesol)
    Definition: misc.c:831
    SCIP_Bool SCIPstrToIntValue(const char *str, int *value, char **endptr)
    Definition: misc.c:10924
    int SCIPstrcasecmp(const char *s1, const char *s2)
    Definition: misc.c:10863
    int SCIPsnprintf(char *t, int len, const char *s,...)
    Definition: misc.c:10827
    SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
    Definition: misc.c:10955
    void SCIPescapeString(char *t, int bufsize, const char *s)
    Definition: misc.c:10782
    void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
    Definition: misc.c:10985
    void SCIPprintSysError(const char *message)
    Definition: misc.c:10719
    SCIP_Bool SCIPstrAtStart(const char *s, const char *t, size_t tlen)
    Definition: misc.c:11364
    SCIP_RETCODE SCIPskipSpace(char **s)
    Definition: misc.c:10816
    int SCIPstrncpy(char *t, const char *s, int size)
    Definition: misc.c:10897
    int SCIPstrncasecmp(const char *s1, const char *s2, int length)
    Definition: misc.c:10876
    char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
    Definition: misc.c:10768
    int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
    Definition: misc.c:10694
    static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
    Definition: heur_twoopt.c:967
    interval arithmetics for provable bounds
    #define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
    Definition: memory.h:462
    #define BMSfreeMemory(ptr)
    Definition: memory.h:145
    #define BMSfreeBlockMemory(mem, ptr)
    Definition: memory.h:465
    #define BMSallocBlockMemory(mem, ptr)
    Definition: memory.h:451
    #define BMSreallocMemoryArray(ptr, num)
    Definition: memory.h:127
    #define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
    Definition: memory.h:468
    #define BMSduplicateMemoryArray(ptr, source, num)
    Definition: memory.h:143
    #define BMSclearMemory(ptr)
    Definition: memory.h:129
    #define BMSallocMemoryArray(ptr, num)
    Definition: memory.h:123
    #define BMSfreeMemoryArray(ptr)
    Definition: memory.h:147
    #define BMSallocBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:454
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSfreeBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:467
    #define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
    Definition: memory.h:458
    #define BMSmoveMemoryArray(ptr, source, num)
    Definition: memory.h:138
    #define BMSallocClearBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:455
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    #define BMSallocClearMemoryArray(ptr, num)
    Definition: memory.h:125
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    #define BMSfreeMemoryArrayNull(ptr)
    Definition: memory.h:148
    #define BMSallocMemory(ptr)
    Definition: memory.h:118
    void SCIPmessagePrintError(const char *formatstr,...)
    Definition: message.c:791
    void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
    Definition: message.c:618
    void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
    Definition: message.c:594
    SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
    Definition: misc.c:4131
    #define GMLNODEHEIGTH
    Definition: misc.c:492
    #define ELEM_DISTANCE(pos)
    Definition: misc.c:3697
    SCIP_Bool SCIPboolarrayGetVal(SCIP_BOOLARRAY *boolarray, int idx)
    Definition: misc.c:5056
    static void incrementalStatsUpdate(SCIP_Real value, SCIP_Real *meanptr, SCIP_Real *sumvarptr, int nobservations, SCIP_Bool add)
    Definition: misc.c:327
    static SCIP_RETCODE doProfileCreate(SCIP_PROFILE **profile, int capacity)
    Definition: misc.c:6810
    static int primetable[]
    Definition: misc.c:1575
    SCIP_RETCODE SCIPboolarrayFree(SCIP_BOOLARRAY **boolarray)
    Definition: misc.c:4854
    SCIP_RETCODE SCIPboolarrayCopy(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem, SCIP_BOOLARRAY *sourceboolarray)
    Definition: misc.c:4830
    static void pqueueElemChgPos(SCIP_PQUEUE *pqueue, void *elem, int oldpos, int newpos)
    Definition: misc.c:1346
    #define GMLNODEBORDERCOLOR
    Definition: misc.c:497
    static void multihashlistFree(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem)
    Definition: misc.c:1675
    static SCIP_RETCODE multihashlistAppend(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
    Definition: misc.c:1653
    static SCIP_RETCODE hashtableCheckLoad(SCIP_HASHTABLE *hashtable)
    Definition: misc.c:2482
    int SCIPptrarrayGetMaxIdx(SCIP_PTRARRAY *ptrarray)
    Definition: misc.c:5508
    #define DEFAULT_SEED
    Definition: misc.c:10132
    SCIP_RETCODE SCIPrealarraySetVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real val)
    Definition: misc.c:4338
    SCIP_RETCODE SCIPintarraySetVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int val)
    Definition: misc.c:4709
    static SCIP_Bool multihashlistRemove(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
    Definition: misc.c:1813
    static const int primetablesize
    Definition: misc.c:1627
    #define SCIP_MULTIHASH_MAXSIZE
    Definition: misc.c:1840
    SCIP_RETCODE SCIPintarrayFree(SCIP_INTARRAY **intarray)
    Definition: misc.c:4488
    #define DEFAULT_MWC
    Definition: misc.c:10134
    #define PQ_RIGHTCHILD(p)
    Definition: misc.c:1275
    static SCIP_RETCODE queueResize(SCIP_QUEUE *queue, int minsize)
    Definition: misc.c:976
    static SCIP_RETCODE queueCheckSize(SCIP_QUEUE *queue)
    Definition: misc.c:1042
    static int profileFindFeasibleStart(SCIP_PROFILE *profile, int pos, int lst, int duration, int demand, SCIP_Bool *infeasible)
    Definition: misc.c:7159
    static void tarjan(SCIP_DIGRAPH *digraph, int v, int *lowlink, int *dfsidx, int *stack, int *stacksize, SCIP_Bool *unprocessed, SCIP_Bool *nodeinstack, int *maxdfs, int *strongcomponents, int *nstrongcomponents, int *strongcompstartidx, int *nstorednodes)
    Definition: misc.c:8397
    #define DEFAULT_XOR
    Definition: misc.c:10133
    void SCIPdisjointsetFree(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem)
    Definition: misc.c:11325
    static void btnodeFreeLeaf(SCIP_BT *tree, SCIP_BTNODE **node)
    Definition: misc.c:8776
    static void depthFirstSearch(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *dfsstack, int *stackadjvisited, int *dfsnodes, int *ndfsnodes)
    Definition: misc.c:7931
    int SCIPptrarrayGetMinIdx(SCIP_PTRARRAY *ptrarray)
    Definition: misc.c:5498
    static SCIP_RETCODE profileUpdate(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
    Definition: misc.c:7037
    static SCIP_RETCODE ensureSuccessorsSize(SCIP_DIGRAPH *digraph, int idx, int newsize)
    Definition: misc.c:7692
    static SCIP_RETCODE profileInsertTimepoint(SCIP_PROFILE *profile, int timepoint, int *pos)
    Definition: misc.c:6996
    SCIP_RETCODE SCIPptrarrayExtend(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
    Definition: misc.c:5223
    SCIP_RETCODE SCIPboolarrayExtend(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
    Definition: misc.c:4868
    SCIP_RETCODE SCIPptrarrayCopy(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem, SCIP_PTRARRAY *sourceptrarray)
    Definition: misc.c:5186
    static void * multihashlistRetrieve(SCIP_MULTIHASHLIST *multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
    Definition: misc.c:1730
    static SCIP_RETCODE hashtableInsert(SCIP_HASHTABLE *hashtable, void *element, void *key, uint32_t hashval, SCIP_Bool override)
    Definition: misc.c:2398
    static void btPrintSubtree(SCIP_BTNODE *node, FILE *file, int *nnodes)
    Definition: misc.c:9069
    int SCIPboolarrayGetMaxIdx(SCIP_BOOLARRAY *boolarray)
    Definition: misc.c:5155
    static const SCIP_Real studentt_quartilesabove[]
    Definition: misc.c:102
    void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
    Definition: misc.c:10209
    SCIP_RETCODE SCIPdisjointsetCreate(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem, int ncomponents)
    Definition: misc.c:11207
    SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
    Definition: misc.c:10193
    SCIP_RETCODE SCIPintarrayCopy(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem, SCIP_INTARRAY *sourceintarray)
    Definition: misc.c:4465
    SCIP_RETCODE SCIPptrarrayClear(SCIP_PTRARRAY *ptrarray)
    Definition: misc.c:5378
    static SCIP_RETCODE hashmapInsert(SCIP_HASHMAP *hashmap, void *origin, SCIP_HASHMAPIMAGE image, uint32_t hashval, SCIP_Bool override)
    Definition: misc.c:2890
    int SCIPrealarrayGetMaxIdx(SCIP_REALARRAY *realarray)
    Definition: misc.c:4435
    SCIP_RETCODE SCIPdigraphCreate(SCIP_DIGRAPH **digraph, BMS_BLKMEM *blkmem, int nnodes)
    Definition: misc.c:7454
    static uint32_t hashSetDesiredPos(SCIP_HASHSET *hashset, void *element)
    Definition: misc.c:3701
    int SCIPintarrayGetMaxIdx(SCIP_INTARRAY *intarray)
    Definition: misc.c:4799
    SCIP_RETCODE SCIPintarrayCreate(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem)
    Definition: misc.c:4445
    static SCIP_RETCODE hashsetCheckLoad(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem)
    Definition: misc.c:3761
    static void regressionRecompute(SCIP_REGRESSION *regression)
    Definition: misc.c:289
    #define STARTSUCCESSORSSIZE
    Definition: misc.c:7688
    SCIP_Real SCIPrealarrayGetVal(SCIP_REALARRAY *realarray, int idx)
    Definition: misc.c:4317
    SCIP_RETCODE SCIPptrarrayFree(SCIP_PTRARRAY **ptrarray)
    Definition: misc.c:5209
    SCIP_RETCODE SCIPintarrayClear(SCIP_INTARRAY *intarray)
    Definition: misc.c:4657
    #define GMLNODEWIDTH
    Definition: misc.c:491
    #define SCIP_MULTIHASH_RESIZE_PERCENTAGE
    Definition: misc.c:1841
    SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
    Definition: misc.c:4407
    int SCIPrealarrayGetMinIdx(SCIP_REALARRAY *realarray)
    Definition: misc.c:4425
    SCIP_RETCODE SCIPrealarrayCreate(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem)
    Definition: misc.c:4073
    #define GMLFONTSIZE
    Definition: misc.c:493
    static const int nscalars
    Definition: misc.c:9636
    SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
    Definition: misc.c:4286
    int SCIPboolarrayGetMinIdx(SCIP_BOOLARRAY *boolarray)
    Definition: misc.c:5145
    static int calcGrowSize(int initsize, SCIP_Real growfac, int num)
    Definition: misc.c:445
    #define GMLNODETYPE
    Definition: misc.c:494
    static const SCIP_Real studentt_quartiles[]
    Definition: misc.c:81
    static const int studentt_maxdf
    Definition: misc.c:107
    #define PQ_PARENT(q)
    Definition: misc.c:1273
    static uint32_t randomGetRand(SCIP_RANDNUMGEN *randnumgen)
    Definition: misc.c:10170
    static uint32_t hashvalue(uint64_t input)
    Definition: misc.c:1631
    static void findArticulationPointsUtil(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *tdisc, int *mindisc, int *parent, SCIP_Bool *articulationflag, int time)
    Definition: misc.c:8010
    static void queueCheckMarker(SCIP_QUEUE *queue)
    Definition: misc.c:1067
    static int profileFindDownFeasibleStart(SCIP_PROFILE *profile, int pos, int ect, int duration, int demand, SCIP_Bool *infeasible)
    Definition: misc.c:7309
    int SCIPintarrayGetMinIdx(SCIP_INTARRAY *intarray)
    Definition: misc.c:4789
    static SCIP_RETCODE pqueueResize(SCIP_PQUEUE *pqueue, int minsize)
    Definition: misc.c:1280
    SCIP_RETCODE SCIPrealarrayCopy(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem, SCIP_REALARRAY *sourcerealarray)
    Definition: misc.c:4093
    static SCIP_RETCODE hashmapCheckLoad(SCIP_HASHMAP *hashmap)
    Definition: misc.c:3010
    void * SCIPptrarrayGetVal(SCIP_PTRARRAY *ptrarray, int idx)
    Definition: misc.c:5409
    void SCIPrandomSetSeed(SCIP_RANDNUMGEN *randnumgen, unsigned int initseed)
    Definition: misc.c:10139
    #define PQ_LEFTCHILD(p)
    Definition: misc.c:1274
    SCIP_RETCODE SCIPintarrayExtend(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
    Definition: misc.c:4502
    #define SCIP_MULTIHASH_GROW_FACTOR
    Definition: misc.c:1842
    static SCIP_RETCODE multihashResize(SCIP_MULTIHASH *multihash)
    Definition: misc.c:1846
    SCIP_RETCODE SCIPboolarrayCreate(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem)
    Definition: misc.c:4810
    static SCIP_RETCODE ensureProfileSize(SCIP_PROFILE *profile, int neededsize)
    Definition: misc.c:6973
    static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta)
    Definition: misc.c:9613
    #define GMLEDGECOLOR
    Definition: misc.c:496
    SCIP_Real SCIPnegateReal(SCIP_Real x)
    Definition: misc.c:10473
    static SCIP_RETCODE btnodeCreateEmpty(SCIP_BT *tree, SCIP_BTNODE **node)
    Definition: misc.c:8737
    #define DEFAULT_CST
    Definition: misc.c:10135
    SCIP_RETCODE SCIPboolarrayClear(SCIP_BOOLARRAY *boolarray)
    Definition: misc.c:5025
    static void * multihashlistRetrieveNext(SCIP_MULTIHASHLIST **multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
    Definition: misc.c:1780
    SCIP_RETCODE SCIPintarrayIncVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int incval)
    Definition: misc.c:4777
    int SCIPintarrayGetVal(SCIP_INTARRAY *intarray, int idx)
    Definition: misc.c:4688
    static SCIP_Bool hashmapLookup(SCIP_HASHMAP *hashmap, void *origin, uint32_t *pos)
    Definition: misc.c:2965
    static const SCIP_Real scalars[]
    Definition: misc.c:9635
    SCIP_RETCODE SCIPdigraphCopy(SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph, BMS_BLKMEM *targetblkmem)
    Definition: misc.c:7531
    #define GMLNODEFILLCOLOR
    Definition: misc.c:495
    SCIP_RETCODE SCIPptrarrayCreate(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem)
    Definition: misc.c:5166
    SCIP_RETCODE SCIPptrarraySetVal(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, void *val)
    Definition: misc.c:5430
    static const SCIP_Real simplednoms[]
    Definition: misc.c:9464
    static SCIP_MULTIHASHLIST * multihashlistFind(SCIP_MULTIHASHLIST *multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
    Definition: misc.c:1699
    SCIP_RETCODE SCIPrealarrayFree(SCIP_REALARRAY **realarray)
    Definition: misc.c:4117
    static void hashsetInsert(SCIP_HASHSET *hashset, void *element)
    Definition: misc.c:3710
    SCIP_RETCODE SCIPboolarraySetVal(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Bool val)
    Definition: misc.c:5077
    internal miscellaneous methods
    #define M_SQRT2
    Definition: misc_rowprep.c:59
    SCIP_Longint denominator(Rational &r)
    SCIP_Longint numerator(Rational &r)
    Definition: pqueue.h:38
    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
    public data structures and miscellaneous methods
    wrapper for rational number arithmetic
    template functions for sorting
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:182
    SCIP_Bool * vals
    Definition: struct_misc.h:183
    SCIP_BTNODE * parent
    Definition: struct_misc.h:241
    void * dataptr
    Definition: struct_misc.h:244
    SCIP_BTNODE * left
    Definition: struct_misc.h:242
    SCIP_BTNODE * right
    Definition: struct_misc.h:243
    SCIP_BTNODE * root
    Definition: struct_misc.h:250
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:251
    SCIP_Bool articulationscheck
    Definition: struct_misc.h:235
    int ** successors
    Definition: struct_misc.h:223
    void ** nodedata
    Definition: struct_misc.h:225
    int * successorssize
    Definition: struct_misc.h:226
    void *** arcdata
    Definition: struct_misc.h:224
    int componentstartsize
    Definition: struct_misc.h:232
    int * articulations
    Definition: struct_misc.h:230
    int * componentstarts
    Definition: struct_misc.h:229
    int narticulations
    Definition: struct_misc.h:234
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:222
    int * components
    Definition: struct_misc.h:228
    int * nsuccessors
    Definition: struct_misc.h:227
    SCIP_HASHMAPIMAGE image
    Definition: struct_misc.h:134
    uint32_t nelements
    Definition: struct_misc.h:145
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:140
    SCIP_HASHMAPTYPE hashmaptype
    Definition: struct_misc.h:146
    uint32_t mask
    Definition: struct_misc.h:144
    uint32_t shift
    Definition: struct_misc.h:143
    SCIP_HASHMAPENTRY * slots
    Definition: struct_misc.h:141
    uint32_t * hashes
    Definition: struct_misc.h:142
    uint32_t nelements
    Definition: struct_misc.h:154
    void ** slots
    Definition: struct_misc.h:152
    uint32_t shift
    Definition: struct_misc.h:153
    void * userptr
    Definition: struct_misc.h:95
    uint32_t nelements
    Definition: struct_misc.h:100
    uint32_t shift
    Definition: struct_misc.h:98
    uint32_t mask
    Definition: struct_misc.h:99
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:94
    void ** slots
    Definition: struct_misc.h:96
    uint32_t * hashes
    Definition: struct_misc.h:97
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:171
    SCIP_MULTIHASHLIST * next
    Definition: struct_misc.h:107
    SCIP_MULTIHASHLIST ** lists
    Definition: struct_misc.h:117
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:116
    SCIP_Longint nelements
    Definition: struct_misc.h:120
    void ** slots
    Definition: struct_misc.h:83
    SCIP_Real sizefac
    Definition: struct_misc.h:80
    int * timepoints
    Definition: struct_misc.h:212
    void ** vals
    Definition: struct_misc.h:194
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:193
    SCIP_Real sizefac
    Definition: struct_misc.h:62
    int firstused
    Definition: struct_misc.h:65
    SCIP_QUEUEELEMENT * slots
    Definition: struct_misc.h:63
    int firstfree
    Definition: struct_misc.h:64
    uint32_t xor_seed
    Definition: struct_misc.h:272
    uint32_t cst_seed
    Definition: struct_misc.h:274
    uint32_t mwc_seed
    Definition: struct_misc.h:273
    SCIP_Real * vals
    Definition: struct_misc.h:161
    BMS_BLKMEM * blkmem
    Definition: struct_misc.h:160
    SCIP_Real slope
    Definition: struct_misc.h:258
    SCIP_Real meany
    Definition: struct_misc.h:260
    SCIP_Real meanx
    Definition: struct_misc.h:259
    SCIP_Real variancesumx
    Definition: struct_misc.h:262
    SCIP_Real corrcoef
    Definition: struct_misc.h:264
    SCIP_Real sumxy
    Definition: struct_misc.h:261
    SCIP_Real intercept
    Definition: struct_misc.h:257
    SCIP_Real variancesumy
    Definition: struct_misc.h:263
    SCIP_Longint * lbvalues
    Definition: struct_misc.h:49
    SCIP_VAR ** vars
    Definition: struct_misc.h:48
    SCIP_Longint * ubvalues
    Definition: struct_misc.h:50
    miscellaneous datastructures
    Definition: heur_padm.c:135
    @ SCIP_HASHMAPTYPE_REAL
    Definition: type_misc.h:60
    @ SCIP_HASHMAPTYPE_POINTER
    Definition: type_misc.h:59
    @ SCIP_HASHMAPTYPE_UNKNOWN
    Definition: type_misc.h:58
    @ SCIP_HASHMAPTYPE_INT
    Definition: type_misc.h:61
    @ SCIP_HASHMAPTYPE_LONG
    Definition: type_misc.h:62
    #define SCIP_DECL_PQUEUEELEMCHGPOS(x)
    Definition: type_misc.h:209
    #define SCIP_DECL_NEWTONEVAL(x)
    Definition: type_misc.h:206
    enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
    Definition: type_misc.h:53
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_KEYALREADYEXISTING
    Definition: type_retcode.h:58
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    SCIP_Longint longint
    Definition: struct_misc.h:127
    unsigned int uinteger
    Definition: struct_misc.h:56