1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /*                                                                           */
3 /*                  This file is part of the program and library             */
4 /*         SCIP --- Solving Constraint Integer Programs                      */
5 /*                                                                           */
6 /*    Copyright (C) 2002-2021 Konrad-Zuse-Zentrum                            */
7 /*                            fuer Informationstechnik Berlin                */
8 /*                                                                           */
9 /*  SCIP is distributed under the terms of the ZIB Academic License.         */
10 /*                                                                           */
11 /*  You should have received a copy of the ZIB Academic License              */
12 /*  along with SCIP; see the file COPYING. If not visit scipopt.org.         */
13 /*                                                                           */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file   misc.c
17  * @ingroup OTHER_CFILES
18  * @brief  miscellaneous methods
19  * @author Tobias Achterberg
20  * @author Gerald Gamrath
21  * @author Stefan Heinz
22  * @author Michael Winkler
23  * @author Kati Wolter
24  * @author Gregor Hendel
25  */
26 
27 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
28 
29 #include <assert.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <ctype.h>
36 
37 #include "scip/def.h"
38 #include "scip/pub_message.h"
39 #include "scip/misc.h"
40 #include "scip/intervalarith.h"
41 #include "scip/pub_misc.h"
42 
43 #ifndef NDEBUG
44 #include "scip/struct_misc.h"
45 #endif
46 
47 /*
48  * methods for statistical tests
49  */
50 
51 #define SQRTOFTWO                  1.4142136 /**< the square root of 2 with sufficient precision */
52 
53 /**< contains all critical values for a one-sided two sample t-test up to 15 degrees of freedom
54  *   a critical value represents a threshold for rejecting the null-hypothesis in hypothesis testing at
55  *   a certain confidence level;
56  *
57  *   access through method SCIPstudentTGetCriticalValue()
58  *
59  *  source: German Wikipedia
60  *
61  *  for confidence levels
62  *  c =
63  *  0.75    0.875     0.90      0.95      0.975 (one-sided)
64  *  0.50    0.750     0.80      0.90      0.950 (two-sided)
65  *
66  */
67 static const SCIP_Real studentt_quartiles[] = {      /* df:*/
68    1.000,    2.414,    3.078,    6.314,    12.706,   /*  1 */
69    0.816,    1.604,    1.886,    2.920,    4.303,    /*  2 */
70    0.765,    1.423,    1.638,    2.353,    3.182,    /*  3 */
71    0.741,    1.344,    1.533,    2.132,    2.776,    /*  4 */
72    0.727,    1.301,    1.476,    2.015,    2.571,    /*  5 */
73    0.718,    1.273,    1.440,    1.943,    2.447,    /*  6 */
74    0.711,    1.254,    1.415,    1.895,    2.365,    /*  7 */
75    0.706,    1.240,    1.397,    1.860,    2.306,    /*  8 */
76    0.703,    1.230,    1.383,    1.833,    2.262,    /*  9 */
77    0.700,    1.221,    1.372,    1.812,    2.228,    /* 10 */
78    0.697,    1.214,    1.363,    1.796,    2.201,    /* 11 */
79    0.695,    1.209,    1.356,    1.782,    2.179,    /* 12 */
80    0.694,    1.204,    1.350,    1.771,    2.160,    /* 13 */
81    0.692,    1.200,    1.345,    1.761,    2.145,    /* 14 */
82    0.691,    1.197,    1.341,    1.753,    2.131     /* 15 */
83 };
84 
85 /**< critical values for higher degrees of freedom of Student-T distribution for the same error probabilities; infact,
86  *   these are critical values of the standard normal distribution with mean 0 and variance 1
87  */
88 static const SCIP_Real studentt_quartilesabove[] = {
89    0.674,    1.150,    1.282,    1.645,    1.960
90 };
91 
92 /** the maximum degrees of freedom represented before switching to normal approximation */
93 static const int studentt_maxdf = sizeof(studentt_quartiles)/(5 * sizeof(SCIP_Real));
94 
95 /** get critical value of a Student-T distribution for a given number of degrees of freedom at a confidence level */
SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel,int df)96 SCIP_Real SCIPstudentTGetCriticalValue(
97    SCIP_CONFIDENCELEVEL  clevel,             /**< (one-sided) confidence level */
98    int                   df                  /**< degrees of freedom */
99    )
100 {
101    if( df > studentt_maxdf )
102       return studentt_quartilesabove[(int)clevel];
103    else
104       return studentt_quartiles[(int)clevel + 5 * (df - 1)];
105 }
106 
107 /** compute a t-value for the hypothesis that x and y are from the same population; Assuming that
108  *  x and y represent normally distributed random samples with equal variance, the returned value
109  *  comes from a Student-T distribution with countx + county - 2 degrees of freedom; this
110  *  value can be compared with a critical value (see also SCIPstudentTGetCriticalValue()) at
111  *  a predefined confidence level for checking if x and y significantly differ in location
112  */
SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx,SCIP_Real meany,SCIP_Real variancex,SCIP_Real variancey,SCIP_Real countx,SCIP_Real county)113 SCIP_Real SCIPcomputeTwoSampleTTestValue(
114    SCIP_Real             meanx,              /**< the mean of the first distribution */
115    SCIP_Real             meany,              /**< the mean of the second distribution */
116    SCIP_Real             variancex,          /**< the variance of the x-distribution */
117    SCIP_Real             variancey,          /**< the variance of the y-distribution */
118    SCIP_Real             countx,             /**< number of samples of x */
119    SCIP_Real             county              /**< number of samples of y */
120    )
121 {
122    SCIP_Real pooledvariance;
123    SCIP_Real tresult;
124 
125    /* too few samples */
126    if( countx < 1.9 || county < 1.9 )
127       return SCIP_INVALID;
128 
129    /* pooled variance is the weighted average of the two variances */
130    pooledvariance = (countx - 1) * variancex + (county - 1) * variancey;
131    pooledvariance /= (countx + county - 2);
132 
133    /* a variance close to zero means the distributions are basically constant */
134    pooledvariance = MAX(pooledvariance, 1e-9);
135 
136    /* tresult can be understood as realization of a Student-T distributed variable with
137     * countx + county - 2 degrees of freedom
138     */
139    tresult = (meanx - meany) / pooledvariance;
140    tresult *= SQRT(countx * county / (countx + county));
141 
142    return tresult;
143 }
144 
145 /** returns the value of the Gauss error function evaluated at a given point */
SCIPerf(SCIP_Real x)146 SCIP_Real SCIPerf(
147    SCIP_Real             x                   /**< value to evaluate */
148    )
149 {
150 #if defined(_WIN32) || defined(_WIN64)
151    SCIP_Real a1, a2, a3, a4, a5, p, t, y;
152    int sign;
153 
154    a1 =  0.254829592;
155    a2 = -0.284496736;
156    a3 =  1.421413741;
157    a4 = -1.453152027;
158    a5 =  1.061405429;
159    p  =  0.3275911;
160 
161    sign = (x >= 0) ? 1 : -1;
162    x = REALABS(x);
163 
164    t = 1.0/(1.0 + p*x);
165    y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);
166    return sign * y;
167 #else
168    return erf(x);
169 #endif
170 }
171 
172 /** get critical value of a standard normal distribution  at a given confidence level */
SCIPnormalGetCriticalValue(SCIP_CONFIDENCELEVEL clevel)173 SCIP_Real SCIPnormalGetCriticalValue(
174    SCIP_CONFIDENCELEVEL  clevel              /**< (one-sided) confidence level */
175    )
176 {
177    return studentt_quartilesabove[(int)clevel];
178 }
179 
180 /** calculates the cumulative distribution P(-infinity <= x <= value) that a normally distributed
181  *  random variable x takes a value between -infinity and parameter \p value.
182  *
183  *  The distribution is given by the respective mean and deviation. This implementation
184  *  uses the error function SCIPerf().
185  */
SCIPnormalCDF(SCIP_Real mean,SCIP_Real variance,SCIP_Real value)186 SCIP_Real SCIPnormalCDF(
187    SCIP_Real             mean,               /**< the mean value of the distribution */
188    SCIP_Real             variance,           /**< the square of the deviation of the distribution */
189    SCIP_Real             value               /**< the upper limit of the calculated distribution integral */
190    )
191 {
192    SCIP_Real normvalue;
193    SCIP_Real std;
194 
195    /* we need to calculate the standard deviation from the variance */
196    assert(variance >= -1e-9);
197    if( variance < 1e-9 )
198       std = 0.0;
199    else
200       std = sqrt(variance);
201 
202    /* special treatment for zero variance */
203    if( std < 1e-9 )
204    {
205       if( value < mean + 1e-9 )
206          return 1.0;
207       else
208          return 0.0;
209    }
210    assert( std != 0.0 ); /* for lint */
211 
212    /* scale and translate to standard normal distribution. Factor sqrt(2) is needed for SCIPerf() function */
213    normvalue = (value - mean)/(std * SQRTOFTWO);
214 
215    SCIPdebugMessage(" Normalized value %g = ( %g - %g ) / (%g * 1.4142136)\n", normvalue, value, mean, std);
216 
217    /* calculate the cumulative distribution function for normvalue. For negative normvalues, we negate the normvalue and
218     * use the oddness of the SCIPerf()-function; special treatment for values close to zero.
219     */
220    if( normvalue < 1e-9 && normvalue > -1e-9 )
221       return .5;
222    else if( normvalue > 0 )
223    {
224       SCIP_Real erfresult;
225 
226       erfresult = SCIPerf(normvalue);
227       return  erfresult / 2.0 + 0.5;
228    }
229    else
230    {
231       SCIP_Real erfresult;
232 
233       erfresult = SCIPerf(-normvalue);
234 
235       return 0.5 - erfresult / 2.0;
236    }
237 }
238 
239 /*
240  * SCIP regression methods
241  */
242 
243 /** returns the number of observations of this regression */
SCIPregressionGetNObservations(SCIP_REGRESSION * regression)244 int SCIPregressionGetNObservations(
245    SCIP_REGRESSION*      regression          /**< regression data structure */
246    )
247 {
248    assert(regression != NULL);
249 
250    return regression->nobservations;
251 }
252 
253 /** return the current slope of the regression */
SCIPregressionGetSlope(SCIP_REGRESSION * regression)254 SCIP_Real SCIPregressionGetSlope(
255    SCIP_REGRESSION*      regression          /**< regression data structure */
256    )
257 {
258    assert(regression != NULL);
259 
260    return regression->slope;
261 }
262 
263 /** get the current y-intercept of the regression */
SCIPregressionGetIntercept(SCIP_REGRESSION * regression)264 SCIP_Real SCIPregressionGetIntercept(
265    SCIP_REGRESSION*      regression          /**< regression data structure */
266    )
267 {
268    assert(regression != NULL);
269 
270    return regression->intercept;
271 }
272 
273 /** recomputes regression coefficients from available observation data */
274 static
regressionRecompute(SCIP_REGRESSION * regression)275 void regressionRecompute(
276    SCIP_REGRESSION*      regression          /**< regression data structure */
277    )
278 {
279    /* regression coefficients require two or more observations and variance in x */
280    if( regression->nobservations <= 1 || EPSZ(regression->variancesumx, 1e-9) )
281    {
282       regression->slope = SCIP_INVALID;
283       regression->intercept = SCIP_INVALID;
284       regression->corrcoef = SCIP_INVALID;
285    }
286    else if( EPSZ(regression->variancesumy, 1e-9) )
287    {
288       /* 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 */
289       regression->slope = 0.0;
290       regression->corrcoef = 0.0;
291       regression->intercept = regression->meany;
292    }
293    else
294    {
295       /* we ruled this case out already, but to please some compilers... */
296       assert(regression->variancesumx > 0.0);
297       assert(regression->variancesumy > 0.0);
298 
299       /* compute slope */
300       regression->slope = (regression->sumxy  - regression->nobservations * regression->meanx * regression->meany) / regression->variancesumx;
301 
302       /* compute y-intercept */
303       regression->intercept = regression->meany - regression->slope * regression->meanx;
304 
305       /* compute empirical correlation coefficient */
306       regression->corrcoef = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) /
307          sqrt(regression->variancesumx * regression->variancesumy);
308    }
309 }
310 
311 /* incremental update of statistics describing mean and variance */
312 static
incrementalStatsUpdate(SCIP_Real value,SCIP_Real * meanptr,SCIP_Real * sumvarptr,int nobservations,SCIP_Bool add)313 void incrementalStatsUpdate(
314    SCIP_Real             value,              /**< current value to be added to incremental statistics */
315    SCIP_Real*            meanptr,            /**< pointer to value of current mean */
316    SCIP_Real*            sumvarptr,          /**< pointer to the value of the current variance sum term */
317    int                   nobservations,      /**< total number of observations */
318    SCIP_Bool             add                 /**< TRUE if the value should be added, FALSE for removing it */
319    )
320 {
321    SCIP_Real oldmean;
322    SCIP_Real addfactor;
323    assert(meanptr != NULL);
324    assert(sumvarptr != NULL);
325    assert(nobservations > 0 || add);
326 
327    addfactor = add ? 1.0 : -1.0;
328 
329    oldmean = *meanptr;
330    *meanptr = oldmean + addfactor * (value - oldmean)/(SCIP_Real)nobservations;
331    *sumvarptr += addfactor * (value - oldmean) * (value - (*meanptr));
332 
333    /* it may happen that *sumvarptr is slightly negative, especially after a series of add/removal operations */
334    assert(*sumvarptr >= -1e-4);
335    *sumvarptr = MAX(0.0, *sumvarptr);
336 }
337 
338 /** removes an observation (x,y) from the regression */
SCIPregressionRemoveObservation(SCIP_REGRESSION * regression,SCIP_Real x,SCIP_Real y)339 void SCIPregressionRemoveObservation(
340    SCIP_REGRESSION*      regression,         /**< regression data structure */
341    SCIP_Real             x,                  /**< X of observation */
342    SCIP_Real             y                   /**< Y of the observation */
343    )
344 {
345    assert(regression != NULL);
346    assert(regression->nobservations > 0);
347 
348    /* simply call the reset function in the case of a single remaining observation to avoid numerical troubles */
349    if( regression->nobservations == 1 )
350    {
351       SCIPregressionReset(regression);
352    }
353    else
354    {
355       SCIP_Bool add = FALSE;
356       --regression->nobservations;
357 
358       /* decrement individual means and variances */
359       incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
360       incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
361 
362       /* decrement product sum */
363       regression->sumxy -= (x * y);
364    }
365 
366    /* recompute regression parameters */
367    regressionRecompute(regression);
368 }
369 
370 /** update regression by a new observation (x,y) */
SCIPregressionAddObservation(SCIP_REGRESSION * regression,SCIP_Real x,SCIP_Real y)371 void SCIPregressionAddObservation(
372    SCIP_REGRESSION*      regression,         /**< regression data structure */
373    SCIP_Real             x,                  /**< X of observation */
374    SCIP_Real             y                   /**< Y of the observation */
375    )
376 {
377    SCIP_Bool add = TRUE;
378    assert(regression != NULL);
379 
380    ++(regression->nobservations);
381    incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
382    incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
383 
384    regression->sumxy += x * y;
385 
386    regressionRecompute(regression);
387 }
388 
389 /** reset regression data structure */
SCIPregressionReset(SCIP_REGRESSION * regression)390 void SCIPregressionReset(
391    SCIP_REGRESSION*      regression          /**< regression data structure */
392    )
393 {
394    regression->intercept = SCIP_INVALID;
395    regression->slope = SCIP_INVALID;
396    regression->corrcoef = SCIP_INVALID;
397    regression->meanx = 0;
398    regression->variancesumx = 0;
399    regression->sumxy = 0;
400    regression->meany = 0;
401    regression->variancesumy = 0;
402    regression->nobservations = 0;
403 }
404 
405 /** creates and resets a regression */
SCIPregressionCreate(SCIP_REGRESSION ** regression)406 SCIP_RETCODE SCIPregressionCreate(
407    SCIP_REGRESSION**     regression          /**< regression data structure */
408    )
409 {
410    assert(regression != NULL);
411 
412    /* allocate necessary memory */
413    SCIP_ALLOC (BMSallocMemory(regression) );
414 
415    /* reset the regression */
416    SCIPregressionReset(*regression);
417 
418    return SCIP_OKAY;
419 }
420 
421 /** creates and resets a regression */
SCIPregressionFree(SCIP_REGRESSION ** regression)422 void SCIPregressionFree(
423    SCIP_REGRESSION**     regression          /**< regression data structure */
424    )
425 {
426    BMSfreeMemory(regression);
427 }
428 
429 /** calculate memory size for dynamically allocated arrays (copied from scip/set.c) */
430 static
calcGrowSize(int initsize,SCIP_Real growfac,int num)431 int calcGrowSize(
432    int                   initsize,           /**< initial size of array */
433    SCIP_Real             growfac,            /**< growing factor of array */
434    int                   num                 /**< minimum number of entries to store */
435    )
436 {
437    int size;
438 
439    assert(initsize >= 0);
440    assert(growfac >= 1.0);
441    assert(num >= 0);
442 
443    if( growfac == 1.0 )
444       size = MAX(initsize, num);
445    else
446    {
447       int oldsize;
448 
449       /* calculate the size with this loop, such that the resulting numbers are always the same (-> block memory) */
450       initsize = MAX(initsize, 4);
451       size = initsize;
452       oldsize = size - 1;
453 
454       /* second condition checks against overflow */
455       while( size < num && size > oldsize )
456       {
457          oldsize = size;
458          size = (int)(growfac * size + initsize);
459       }
460 
461       /* if an overflow happened, set the correct value */
462       if( size <= oldsize )
463          size = num;
464    }
465 
466    assert(size >= initsize);
467    assert(size >= num);
468 
469    return size;
470 }
471 
472 /*
473  * GML graphical printing methods
474  * For a detailed format decription see http://docs.yworks.com/yfiles/doc/developers-guide/gml.html
475  */
476 
477 #define GMLNODEWIDTH 120.0
478 #define GMLNODEHEIGTH 30.0
479 #define GMLFONTSIZE 13
480 #define GMLNODETYPE "rectangle"
481 #define GMLNODEFILLCOLOR "#ff0000"
482 #define GMLEDGECOLOR "black"
483 #define GMLNODEBORDERCOLOR "#000000"
484 
485 
486 /** writes a node section to the given graph file */
SCIPgmlWriteNode(FILE * file,unsigned int id,const char * label,const char * nodetype,const char * fillcolor,const char * bordercolor)487 void SCIPgmlWriteNode(
488    FILE*                 file,               /**< file to write to */
489    unsigned int          id,                 /**< id of the node */
490    const char*           label,              /**< label of the node */
491    const char*           nodetype,           /**< type of the node, or NULL */
492    const char*           fillcolor,          /**< color of the node's interior, or NULL */
493    const char*           bordercolor         /**< color of the node's border, or NULL */
494    )
495 {
496    assert(file != NULL);
497    assert(label != NULL);
498 
499    fprintf(file, "  node\n");
500    fprintf(file, "  [\n");
501    fprintf(file, "    id      %u\n", id);
502    fprintf(file, "    label   \"%s\"\n", label);
503    fprintf(file, "    graphics\n");
504    fprintf(file, "    [\n");
505    fprintf(file, "      w       %g\n", GMLNODEWIDTH);
506    fprintf(file, "      h       %g\n", GMLNODEHEIGTH);
507 
508    if( nodetype != NULL )
509       fprintf(file, "      type    \"%s\"\n", nodetype);
510    else
511       fprintf(file, "      type    \"%s\"\n", GMLNODETYPE);
512 
513    if( fillcolor != NULL )
514       fprintf(file, "      fill    \"%s\"\n", fillcolor);
515    else
516       fprintf(file, "      fill    \"%s\"\n", GMLNODEFILLCOLOR);
517 
518    if( bordercolor != NULL )
519       fprintf(file, "      outline \"%s\"\n", bordercolor);
520    else
521       fprintf(file, "      outline \"%s\"\n", GMLNODEBORDERCOLOR);
522 
523    fprintf(file, "    ]\n");
524    fprintf(file, "    LabelGraphics\n");
525    fprintf(file, "    [\n");
526    fprintf(file, "      text      \"%s\"\n", label);
527    fprintf(file, "      fontSize  %d\n", GMLFONTSIZE);
528    fprintf(file, "      fontName  \"Dialog\"\n");
529    fprintf(file, "      anchor    \"c\"\n");
530    fprintf(file, "    ]\n");
531    fprintf(file, "  ]\n");
532 }
533 
534 /** writes a node section including weight to the given graph file */
SCIPgmlWriteNodeWeight(FILE * file,unsigned int id,const char * label,const char * nodetype,const char * fillcolor,const char * bordercolor,SCIP_Real weight)535 void SCIPgmlWriteNodeWeight(
536    FILE*                 file,               /**< file to write to */
537    unsigned int          id,                 /**< id of the node */
538    const char*           label,              /**< label of the node */
539    const char*           nodetype,           /**< type of the node, or NULL */
540    const char*           fillcolor,          /**< color of the node's interior, or NULL */
541    const char*           bordercolor,        /**< color of the node's border, or NULL */
542    SCIP_Real             weight              /**< weight of node */
543    )
544 {
545    assert(file != NULL);
546    assert(label != NULL);
547 
548    fprintf(file, "  node\n");
549    fprintf(file, "  [\n");
550    fprintf(file, "    id      %u\n", id);
551    fprintf(file, "    label   \"%s\"\n", label);
552    fprintf(file, "    weight  %g\n", weight);
553    fprintf(file, "    graphics\n");
554    fprintf(file, "    [\n");
555    fprintf(file, "      w       %g\n", GMLNODEWIDTH);
556    fprintf(file, "      h       %g\n", GMLNODEHEIGTH);
557 
558    if( nodetype != NULL )
559       fprintf(file, "      type    \"%s\"\n", nodetype);
560    else
561       fprintf(file, "      type    \"%s\"\n", GMLNODETYPE);
562 
563    if( fillcolor != NULL )
564       fprintf(file, "      fill    \"%s\"\n", fillcolor);
565    else
566       fprintf(file, "      fill    \"%s\"\n", GMLNODEFILLCOLOR);
567 
568    if( bordercolor != NULL )
569       fprintf(file, "      outline \"%s\"\n", bordercolor);
570    else
571       fprintf(file, "      outline \"%s\"\n", GMLNODEBORDERCOLOR);
572 
573    fprintf(file, "    ]\n");
574    fprintf(file, "    LabelGraphics\n");
575    fprintf(file, "    [\n");
576    fprintf(file, "      text      \"%s\"\n", label);
577    fprintf(file, "      fontSize  %d\n", GMLFONTSIZE);
578    fprintf(file, "      fontName  \"Dialog\"\n");
579    fprintf(file, "      anchor    \"c\"\n");
580    fprintf(file, "    ]\n");
581    fprintf(file, "  ]\n");
582 }
583 
584 /** writes an edge section to the given graph file */
SCIPgmlWriteEdge(FILE * file,unsigned int source,unsigned int target,const char * label,const char * color)585 void SCIPgmlWriteEdge(
586    FILE*                 file,               /**< file to write to */
587    unsigned int          source,             /**< source node id of the node */
588    unsigned int          target,             /**< target node id of the edge */
589    const char*           label,              /**< label of the edge, or NULL */
590    const char*           color               /**< color of the edge, or NULL */
591    )
592 {
593    assert(file != NULL);
594 
595    fprintf(file, "  edge\n");
596    fprintf(file, "  [\n");
597    fprintf(file, "    source  %u\n", source);
598    fprintf(file, "    target  %u\n", target);
599 
600    if( label != NULL)
601       fprintf(file, "    label   \"%s\"\n", label);
602 
603    fprintf(file, "    graphics\n");
604    fprintf(file, "    [\n");
605 
606    if( color != NULL )
607       fprintf(file, "      fill    \"%s\"\n", color);
608    else
609       fprintf(file, "      fill    \"%s\"\n", GMLEDGECOLOR);
610 
611    /* fprintf(file, "      arrow     \"both\"\n"); */
612    fprintf(file, "    ]\n");
613 
614    if( label != NULL)
615    {
616       fprintf(file, "    LabelGraphics\n");
617       fprintf(file, "    [\n");
618       fprintf(file, "      text      \"%s\"\n", label);
619       fprintf(file, "      fontSize  %d\n", GMLFONTSIZE);
620       fprintf(file, "      fontName  \"Dialog\"\n");
621       fprintf(file, "      anchor    \"c\"\n");
622       fprintf(file, "    ]\n");
623    }
624 
625    fprintf(file, "  ]\n");
626 }
627 
628 /** writes an arc section to the given graph file */
SCIPgmlWriteArc(FILE * file,unsigned int source,unsigned int target,const char * label,const char * color)629 void SCIPgmlWriteArc(
630    FILE*                 file,               /**< file to write to */
631    unsigned int          source,             /**< source node id of the node */
632    unsigned int          target,             /**< target node id of the edge */
633    const char*           label,              /**< label of the edge, or NULL */
634    const char*           color               /**< color of the edge, or NULL */
635    )
636 {
637    assert(file != NULL);
638 
639    fprintf(file, "  edge\n");
640    fprintf(file, "  [\n");
641    fprintf(file, "    source  %u\n", source);
642    fprintf(file, "    target  %u\n", target);
643 
644    if( label != NULL)
645       fprintf(file, "    label   \"%s\"\n", label);
646 
647    fprintf(file, "    graphics\n");
648    fprintf(file, "    [\n");
649 
650    if( color != NULL )
651       fprintf(file, "      fill    \"%s\"\n", color);
652    else
653       fprintf(file, "      fill    \"%s\"\n", GMLEDGECOLOR);
654 
655    fprintf(file, "      targetArrow     \"standard\"\n");
656    fprintf(file, "    ]\n");
657 
658    if( label != NULL)
659    {
660       fprintf(file, "    LabelGraphics\n");
661       fprintf(file, "    [\n");
662       fprintf(file, "      text      \"%s\"\n", label);
663       fprintf(file, "      fontSize  %d\n", GMLFONTSIZE);
664       fprintf(file, "      fontName  \"Dialog\"\n");
665       fprintf(file, "      anchor    \"c\"\n");
666       fprintf(file, "    ]\n");
667    }
668 
669    fprintf(file, "  ]\n");
670 }
671 
672 /** writes the starting line to a GML graph file, does not open a file */
SCIPgmlWriteOpening(FILE * file,SCIP_Bool directed)673 void SCIPgmlWriteOpening(
674    FILE*                 file,               /**< file to write to */
675    SCIP_Bool             directed            /**< is the graph directed */
676    )
677 {
678    assert(file != NULL);
679 
680    fprintf(file, "graph\n");
681    fprintf(file, "[\n");
682    fprintf(file, "  hierarchic      1\n");
683 
684    if( directed )
685       fprintf(file, "  directed        1\n");
686 }
687 
688 /** writes the ending lines to a GML graph file, does not close a file */
SCIPgmlWriteClosing(FILE * file)689 void SCIPgmlWriteClosing(
690    FILE*                 file                /**< file to close */
691    )
692 {
693    assert(file != NULL);
694 
695    fprintf(file, "]\n");
696 }
697 
698 
699 /*
700  * Sparse solution
701  */
702 
703 /** creates a sparse solution */
SCIPsparseSolCreate(SCIP_SPARSESOL ** sparsesol,SCIP_VAR ** vars,int nvars,SCIP_Bool cleared)704 SCIP_RETCODE SCIPsparseSolCreate(
705    SCIP_SPARSESOL**      sparsesol,          /**< pointer to store the created sparse solution */
706    SCIP_VAR**            vars,               /**< variables in the sparse solution, must not contain continuous
707 					      *   variables
708 					      */
709    int                   nvars,              /**< number of variables to store, size of the lower and upper bound
710 					      *   arrays
711 					      */
712    SCIP_Bool             cleared             /**< should the lower and upper bound arrays be cleared (entries set to
713 					      *	  0)
714 					      */
715    )
716 {
717    assert(sparsesol != NULL);
718    assert(vars != NULL);
719    assert(nvars >= 0);
720 
721    SCIP_ALLOC( BMSallocMemory(sparsesol) );
722 
723 #ifndef NDEBUG
724    {
725       int v;
726 
727       for( v = nvars - 1; v >= 0; --v )
728       {
729 	 assert(vars[v] != NULL);
730 	 /* assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS); */
731       }
732    }
733 #endif
734 
735    /* copy variables */
736    SCIP_ALLOC( BMSduplicateMemoryArray(&((*sparsesol)->vars), vars, nvars) );
737 
738    /* create bound arrays */
739    if( cleared )
740    {
741       SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->lbvalues), nvars) );
742       SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->ubvalues), nvars) );
743    }
744    else
745    {
746       SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->lbvalues), nvars) );
747       SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->ubvalues), nvars) );
748    }
749 
750    (*sparsesol)->nvars = nvars;
751 
752    return SCIP_OKAY;
753 }
754 
755 /** frees sparse solution */
SCIPsparseSolFree(SCIP_SPARSESOL ** sparsesol)756 void SCIPsparseSolFree(
757    SCIP_SPARSESOL**      sparsesol           /**< pointer to a sparse solution */
758    )
759 {
760    assert(sparsesol != NULL);
761    assert(*sparsesol != NULL);
762 
763    BMSfreeMemoryArray(&((*sparsesol)->vars));
764    BMSfreeMemoryArray(&((*sparsesol)->ubvalues));
765    BMSfreeMemoryArray(&((*sparsesol)->lbvalues));
766    BMSfreeMemory(sparsesol);
767 }
768 
769 /** returns the variables stored in the given sparse solution */
SCIPsparseSolGetVars(SCIP_SPARSESOL * sparsesol)770 SCIP_VAR** SCIPsparseSolGetVars(
771    SCIP_SPARSESOL*       sparsesol           /**< a sparse solution */
772    )
773 {
774    assert(sparsesol != NULL);
775 
776    return sparsesol->vars;
777 }
778 
779 /** returns the number of variables stored in the given sparse solution */
SCIPsparseSolGetNVars(SCIP_SPARSESOL * sparsesol)780 int SCIPsparseSolGetNVars(
781    SCIP_SPARSESOL*       sparsesol           /**< a sparse solution */
782    )
783 {
784    assert(sparsesol != NULL);
785 
786    return sparsesol->nvars;
787 }
788 
789 /** returns the lower bound array for all variables for a given sparse solution */
SCIPsparseSolGetLbs(SCIP_SPARSESOL * sparsesol)790 SCIP_Longint* SCIPsparseSolGetLbs(
791    SCIP_SPARSESOL*       sparsesol           /**< a sparse solution */
792    )
793 {
794    assert(sparsesol != NULL);
795 
796    return sparsesol->lbvalues;
797 }
798 
799 /** returns the upper bound array for all variables for a given sparse solution */
SCIPsparseSolGetUbs(SCIP_SPARSESOL * sparsesol)800 SCIP_Longint* SCIPsparseSolGetUbs(
801    SCIP_SPARSESOL*       sparsesol           /**< a sparse solution */
802    )
803 {
804    assert(sparsesol != NULL);
805 
806    return sparsesol->ubvalues;
807 }
808 
809 /** constructs the first solution of sparse solution (all variables are set to their lower bound value */
SCIPsparseSolGetFirstSol(SCIP_SPARSESOL * sparsesol,SCIP_Longint * sol,int nvars)810 void SCIPsparseSolGetFirstSol(
811    SCIP_SPARSESOL*       sparsesol,          /**< sparse solutions */
812    SCIP_Longint*         sol,                /**< array to store the first solution */
813    int                   nvars               /**< number of variables */
814    )
815 {
816    SCIP_Longint* lbvalues;
817    int v;
818 
819    assert(sparsesol != NULL);
820    assert(sol != NULL);
821    assert(nvars == SCIPsparseSolGetNVars(sparsesol));
822 
823    lbvalues = SCIPsparseSolGetLbs(sparsesol);
824    assert(lbvalues != NULL);
825 
826    /* copy the lower bounds */
827    for( v = 0; v < nvars; ++v )
828       sol[v] = lbvalues[v];
829 }
830 
831 
832 /** constructs the next solution of the sparse solution and return whether there was one more or not */
SCIPsparseSolGetNextSol(SCIP_SPARSESOL * sparsesol,SCIP_Longint * sol,int nvars)833 SCIP_Bool SCIPsparseSolGetNextSol(
834    SCIP_SPARSESOL*       sparsesol,          /**< sparse solutions */
835    SCIP_Longint*         sol,                /**< current solution array which get changed to the next solution */
836    int                   nvars               /**< number of variables */
837    )
838 {
839    SCIP_Longint* lbvalues;
840    SCIP_Longint* ubvalues;
841    SCIP_Longint lbvalue;
842    SCIP_Longint ubvalue;
843    SCIP_Bool singular;
844    SCIP_Bool carryflag;
845    int v;
846 
847    assert(sparsesol != NULL);
848    assert(sol != NULL);
849 
850    if( nvars == 0 )
851       return FALSE;
852 
853    assert(nvars > 0);
854    assert(nvars == SCIPsparseSolGetNVars(sparsesol));
855 
856    lbvalues = SCIPsparseSolGetLbs(sparsesol);
857    ubvalues = SCIPsparseSolGetUbs(sparsesol);
858    assert(lbvalues != NULL);
859    assert(ubvalues != NULL);
860 
861    singular = TRUE;
862    carryflag = FALSE;
863 
864    for( v = 0; v < nvars; ++v )
865    {
866       lbvalue = lbvalues[v];
867       ubvalue = ubvalues[v];
868 
869       if( lbvalue < ubvalue )
870       {
871          singular = FALSE;
872 
873          if( carryflag == FALSE )
874          {
875             if( sol[v] < ubvalue )
876             {
877                sol[v]++;
878                break;
879             }
880             else
881             {
882                /* in the last solution the variables v was set to its upper bound value */
883                assert(sol[v] == ubvalue);
884                sol[v] = lbvalue;
885                carryflag = TRUE;
886             }
887          }
888          else
889          {
890             if( sol[v] < ubvalue )
891             {
892                sol[v]++;
893                carryflag = FALSE;
894                break;
895             }
896             else
897             {
898                assert(sol[v] == ubvalue);
899                sol[v] = lbvalue;
900             }
901          }
902       }
903    }
904 
905    return (!carryflag && !singular);
906 }
907 
908 
909 /*
910  * Queue
911  */
912 
913 /** resizes element memory to hold at least the given number of elements */
914 static
queueResize(SCIP_QUEUE * queue,int minsize)915 SCIP_RETCODE queueResize(
916    SCIP_QUEUE*           queue,              /**< pointer to a queue */
917    int                   minsize             /**< minimal number of storable elements */
918    )
919 {
920    assert(queue != NULL);
921    assert(minsize > 0);
922 
923    if( minsize <= queue->size )
924       return SCIP_OKAY;
925 
926    queue->size = MAX(minsize, (int)(queue->size * queue->sizefac));
927    SCIP_ALLOC( BMSreallocMemoryArray(&queue->slots, queue->size) );
928 
929    return SCIP_OKAY;
930 }
931 
932 
933 /** creates a (circular) queue, best used if the size will be fixed or will not be increased that much */
SCIPqueueCreate(SCIP_QUEUE ** queue,int initsize,SCIP_Real sizefac)934 SCIP_RETCODE SCIPqueueCreate(
935    SCIP_QUEUE**          queue,              /**< pointer to the new queue */
936    int                   initsize,           /**< initial number of available element slots */
937    SCIP_Real             sizefac             /**< memory growing factor applied, if more element slots are needed */
938    )
939 {
940    assert(queue != NULL);
941 
942    initsize = MAX(1, initsize);
943    sizefac = MAX(1.0, sizefac);
944 
945    SCIP_ALLOC( BMSallocMemory(queue) );
946    (*queue)->firstfree = 0;
947    (*queue)->firstused = -1;
948    (*queue)->size = 0;
949    (*queue)->sizefac = sizefac;
950    (*queue)->slots = NULL;
951 
952    SCIP_CALL( queueResize(*queue, initsize) );
953 
954    return SCIP_OKAY;
955 }
956 
957 /** frees queue, but not the data elements themselves */
SCIPqueueFree(SCIP_QUEUE ** queue)958 void SCIPqueueFree(
959    SCIP_QUEUE**          queue               /**< pointer to a queue */
960    )
961 {
962    assert(queue != NULL);
963 
964    BMSfreeMemoryArray(&(*queue)->slots);
965    BMSfreeMemory(queue);
966 }
967 
968 /** clears the queue, but doesn't free the data elements themselves */
SCIPqueueClear(SCIP_QUEUE * queue)969 void SCIPqueueClear(
970    SCIP_QUEUE*           queue               /**< queue */
971    )
972 {
973    assert(queue != NULL);
974 
975    queue->firstfree = 0;
976    queue->firstused = -1;
977 }
978 
979 /** reallocates slots if queue is necessary */
980 static
queueCheckSize(SCIP_QUEUE * queue)981 SCIP_RETCODE queueCheckSize(
982    SCIP_QUEUE*           queue               /**< queue */
983    )
984 {
985    if( queue->firstfree == queue->firstused )
986    {
987       int sizediff;
988       int oldsize = queue->size;
989 
990       SCIP_CALL( queueResize(queue, queue->size+1) );
991       assert(oldsize < queue->size);
992 
993       sizediff = queue->size - oldsize;
994 
995       /* move the used memory at the slots to the end */
996       BMSmoveMemoryArray(&(queue->slots[queue->firstused + sizediff]), &(queue->slots[queue->firstused]), oldsize - queue->firstused); /*lint !e866*/
997       queue->firstused += sizediff;
998    }
999    assert(queue->firstfree != queue->firstused);
1000 
1001    return SCIP_OKAY;
1002 }
1003 
1004 /** checks and adjusts marker of first free and first used slot */
1005 static
queueCheckMarker(SCIP_QUEUE * queue)1006 void queueCheckMarker(
1007    SCIP_QUEUE*           queue               /**< queue */
1008    )
1009 {
1010    /* if we saved the value at the last position we need to reset the firstfree position */
1011    if( queue->firstfree == queue->size )
1012       queue->firstfree = 0;
1013 
1014    /* if a first element was added, we need to update the firstused counter */
1015    if( queue->firstused == -1 )
1016       queue->firstused = 0;
1017 }
1018 
1019 /** inserts pointer element at the end of the queue */
SCIPqueueInsert(SCIP_QUEUE * queue,void * elem)1020 SCIP_RETCODE SCIPqueueInsert(
1021    SCIP_QUEUE*           queue,              /**< queue */
1022    void*                 elem                /**< element to be inserted */
1023    )
1024 {
1025    assert(queue != NULL);
1026    assert(queue->slots != NULL);
1027    assert(queue->firstused >= -1 && queue->firstused < queue->size);
1028    assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1029    assert(queue->firstused > -1 || queue->firstfree == 0);
1030    assert(elem != NULL);
1031 
1032    /* check allocated memory */
1033    SCIP_CALL( queueCheckSize(queue) );
1034 
1035    /* insert element at the first free slot */
1036    queue->slots[queue->firstfree].ptr = elem;
1037    ++(queue->firstfree);
1038 
1039    /* check and adjust marker */
1040    queueCheckMarker(queue);
1041 
1042    return SCIP_OKAY;
1043 }
1044 
1045 /** inserts unsigned integer element at the end of the queue */
SCIPqueueInsertUInt(SCIP_QUEUE * queue,unsigned int elem)1046 SCIP_RETCODE SCIPqueueInsertUInt(
1047    SCIP_QUEUE*           queue,              /**< queue */
1048    unsigned int          elem                /**< element to be inserted */
1049    )
1050 {
1051    assert(queue != NULL);
1052    assert(queue->slots != NULL);
1053    assert(queue->firstused >= -1 && queue->firstused < queue->size);
1054    assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1055    assert(queue->firstused > -1 || queue->firstfree == 0);
1056 
1057    /* check allocated memory */
1058    SCIP_CALL( queueCheckSize(queue) );
1059 
1060    /* insert element at the first free slot */
1061    queue->slots[queue->firstfree].uinteger = elem;
1062    ++(queue->firstfree);
1063 
1064    /* check and adjust marker */
1065    queueCheckMarker(queue);
1066 
1067    return SCIP_OKAY;
1068 }
1069 
1070 /** removes and returns the first pointer element of the queue, or NULL if no element exists */
SCIPqueueRemove(SCIP_QUEUE * queue)1071 void* SCIPqueueRemove(
1072    SCIP_QUEUE*           queue               /**< queue */
1073    )
1074 {
1075    int pos;
1076 
1077    assert(queue != NULL);
1078    assert(queue->firstused >= -1 && queue->firstused < queue->size);
1079    assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1080    assert(queue->firstused > -1 || queue->firstfree == 0);
1081 
1082    if( queue->firstused == -1 )
1083       return NULL;
1084 
1085    assert(queue->slots != NULL);
1086 
1087    pos = queue->firstused;
1088    ++(queue->firstused);
1089 
1090    /* if we removed the value at the last position we need to reset the firstused position */
1091    if( queue->firstused == queue->size )
1092       queue->firstused = 0;
1093 
1094    /* if we reached the first free position we can reset both, firstused and firstused, positions */
1095    if( queue->firstused == queue->firstfree )
1096    {
1097       queue->firstused = -1;
1098       queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
1099    }
1100 
1101    return (queue->slots[pos].ptr);
1102 }
1103 
1104 /** removes and returns the first unsigned integer element of the queue, or UINT_MAX if no element exists */
SCIPqueueRemoveUInt(SCIP_QUEUE * queue)1105 unsigned int SCIPqueueRemoveUInt(
1106    SCIP_QUEUE*           queue               /**< queue */
1107    )
1108 {
1109    int pos;
1110 
1111    assert(queue != NULL);
1112    assert(queue->firstused >= -1 && queue->firstused < queue->size);
1113    assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1114    assert(queue->firstused > -1 || queue->firstfree == 0);
1115 
1116    if( queue->firstused == -1 )
1117       return UINT_MAX;
1118 
1119    assert(queue->slots != NULL);
1120 
1121    pos = queue->firstused;
1122    ++(queue->firstused);
1123 
1124    /* if we removed the value at the last position we need to reset the firstused position */
1125    if( queue->firstused == queue->size )
1126       queue->firstused = 0;
1127 
1128    /* if we reached the first free position we can reset both, firstused and firstused, positions */
1129    if( queue->firstused == queue->firstfree )
1130    {
1131       queue->firstused = -1;
1132       queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
1133    }
1134 
1135    return (queue->slots[pos].uinteger);
1136 }
1137 
1138 /** returns the first element of the queue without removing it, or NULL if no element exists */
SCIPqueueFirst(SCIP_QUEUE * queue)1139 void* SCIPqueueFirst(
1140    SCIP_QUEUE*           queue               /**< queue */
1141    )
1142 {
1143    assert(queue != NULL);
1144    assert(queue->firstused >= -1 && queue->firstused < queue->size);
1145    assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1146    assert(queue->firstused > -1 || queue->firstfree == 0);
1147 
1148    if( queue->firstused == -1 )
1149       return NULL;
1150 
1151    assert(queue->slots != NULL);
1152 
1153    return queue->slots[queue->firstused].ptr;
1154 }
1155 
1156 /** returns the first unsigned integer element of the queue without removing it, or UINT_MAX if no element exists */
SCIPqueueFirstUInt(SCIP_QUEUE * queue)1157 unsigned int SCIPqueueFirstUInt(
1158    SCIP_QUEUE*           queue               /**< queue */
1159    )
1160 {
1161    assert(queue != NULL);
1162    assert(queue->firstused >= -1 && queue->firstused < queue->size);
1163    assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1164    assert(queue->firstused > -1 || queue->firstfree == 0);
1165 
1166    if( queue->firstused == -1 )
1167       return UINT_MAX;
1168 
1169    assert(queue->slots != NULL);
1170 
1171    return queue->slots[queue->firstused].uinteger;
1172 }
1173 
1174 /** returns whether the queue is empty */
SCIPqueueIsEmpty(SCIP_QUEUE * queue)1175 SCIP_Bool SCIPqueueIsEmpty(
1176    SCIP_QUEUE*           queue               /**< queue */
1177    )
1178 {
1179    assert(queue != NULL);
1180    assert(queue->firstused >= -1 && queue->firstused < queue->size);
1181    assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1182    assert(queue->firstused > -1 || queue->firstfree == 0);
1183 
1184    return (queue->firstused == -1);
1185 }
1186 
1187 /** returns the number of elements in the queue */
SCIPqueueNElems(SCIP_QUEUE * queue)1188 int SCIPqueueNElems(
1189    SCIP_QUEUE*           queue               /**< queue */
1190    )
1191 {
1192    assert(queue != NULL);
1193    assert(queue->firstused >= -1 && queue->firstused < queue->size);
1194    assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1195    assert(queue->firstused > -1 || queue->firstfree == 0);
1196 
1197    if( queue->firstused == -1 )
1198       return 0;
1199    else if( queue->firstused < queue->firstfree )
1200       return queue->firstfree - queue->firstused;
1201    else if( queue->firstused == queue->firstfree )
1202       return queue->size;
1203    else
1204       return queue->firstfree + (queue->size - queue->firstused);
1205 }
1206 
1207 
1208 /*
1209  * Priority Queue
1210  */
1211 
1212 #define PQ_PARENT(q) (((q)+1)/2-1)
1213 #define PQ_LEFTCHILD(p) (2*(p)+1)
1214 #define PQ_RIGHTCHILD(p) (2*(p)+2)
1215 
1216 
1217 /** resizes element memory to hold at least the given number of elements */
1218 static
pqueueResize(SCIP_PQUEUE * pqueue,int minsize)1219 SCIP_RETCODE pqueueResize(
1220    SCIP_PQUEUE*          pqueue,             /**< pointer to a priority queue */
1221    int                   minsize             /**< minimal number of storable elements */
1222    )
1223 {
1224    assert(pqueue != NULL);
1225 
1226    if( minsize <= pqueue->size )
1227       return SCIP_OKAY;
1228 
1229    pqueue->size = MAX(minsize, (int)(pqueue->size * pqueue->sizefac));
1230    SCIP_ALLOC( BMSreallocMemoryArray(&pqueue->slots, pqueue->size) );
1231 
1232    return SCIP_OKAY;
1233 }
1234 
1235 /** creates priority queue */
SCIPpqueueCreate(SCIP_PQUEUE ** pqueue,int initsize,SCIP_Real sizefac,SCIP_DECL_SORTPTRCOMP ((* ptrcomp)),SCIP_DECL_PQUEUEELEMCHGPOS ((* elemchgpos)))1236 SCIP_RETCODE SCIPpqueueCreate(
1237    SCIP_PQUEUE**         pqueue,             /**< pointer to a priority queue */
1238    int                   initsize,           /**< initial number of available element slots */
1239    SCIP_Real             sizefac,            /**< memory growing factor applied, if more element slots are needed */
1240    SCIP_DECL_SORTPTRCOMP((*ptrcomp)),        /**< data element comparator */
1241    SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)) /**< callback to act on position change of elem in priority queue, or NULL */
1242    )
1243 {
1244    assert(pqueue != NULL);
1245    assert(ptrcomp != NULL);
1246 
1247    initsize = MAX(1, initsize);
1248    sizefac = MAX(1.0, sizefac);
1249 
1250    SCIP_ALLOC( BMSallocMemory(pqueue) );
1251    (*pqueue)->len = 0;
1252    (*pqueue)->size = 0;
1253    (*pqueue)->sizefac = sizefac;
1254    (*pqueue)->slots = NULL;
1255    (*pqueue)->ptrcomp = ptrcomp;
1256    (*pqueue)->elemchgpos = elemchgpos;
1257    SCIP_CALL( pqueueResize(*pqueue, initsize) );
1258 
1259    return SCIP_OKAY;
1260 }
1261 
1262 /** frees priority queue, but not the data elements themselves */
SCIPpqueueFree(SCIP_PQUEUE ** pqueue)1263 void SCIPpqueueFree(
1264    SCIP_PQUEUE**         pqueue              /**< pointer to a priority queue */
1265    )
1266 {
1267    assert(pqueue != NULL);
1268 
1269    BMSfreeMemoryArray(&(*pqueue)->slots);
1270    BMSfreeMemory(pqueue);
1271 }
1272 
1273 /** clears the priority queue, but doesn't free the data elements themselves */
SCIPpqueueClear(SCIP_PQUEUE * pqueue)1274 void SCIPpqueueClear(
1275    SCIP_PQUEUE*          pqueue              /**< priority queue */
1276    )
1277 {
1278    assert(pqueue != NULL);
1279 
1280    pqueue->len = 0;
1281 }
1282 
1283 /** assign element to new slot in priority queue */
1284 static
pqueueElemChgPos(SCIP_PQUEUE * pqueue,void * elem,int oldpos,int newpos)1285 void pqueueElemChgPos(
1286    SCIP_PQUEUE*          pqueue,             /**< priority queue */
1287    void*                 elem,               /**< element whose position changes */
1288    int                   oldpos,             /**< old position or -1 if elem is newly inserted */
1289    int                   newpos              /**< new position */
1290    )
1291 {
1292    pqueue->slots[newpos] = elem;
1293 
1294    /* act on position change */
1295    if( pqueue->elemchgpos != NULL )
1296    {
1297       pqueue->elemchgpos(elem, oldpos, newpos);
1298    }
1299 }
1300 
1301 #ifdef SCIP_MORE_DEBUG
1302 /** ensure that the priority queue still has the heap property */
1303 static
pqueueHasHeapProperty(SCIP_PQUEUE * pqueue)1304 SCIP_Bool pqueueHasHeapProperty(
1305    SCIP_PQUEUE*          pqueue              /**< priority queue */
1306    )
1307 {
1308    int i;
1309 
1310    if( SCIPpqueueNElems(pqueue) == 0 )
1311       return TRUE;
1312 
1313    /* check local heap property between parents and children */
1314    for( i = 0; i < SCIPpqueueNElems(pqueue); ++i )
1315    {
1316       if( i > 0 && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[PQ_PARENT(i)]) < 0 )
1317          return FALSE;
1318       if( i < PQ_PARENT(SCIPpqueueNElems(pqueue)) )
1319       {
1320          int leftchild = PQ_LEFTCHILD(i);
1321          int rightchild = PQ_RIGHTCHILD(i);
1322          assert(leftchild < SCIPpqueueNElems(pqueue));
1323          assert(rightchild <= SCIPpqueueNElems(pqueue));
1324          if( pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[leftchild]) > 0 )
1325             return FALSE;
1326          if( rightchild < SCIPpqueueNElems(pqueue) && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[rightchild]) > 0)
1327             return FALSE;
1328       }
1329    }
1330    return TRUE;
1331 }
1332 #endif
1333 
1334 /** inserts element into priority queue */
SCIPpqueueInsert(SCIP_PQUEUE * pqueue,void * elem)1335 SCIP_RETCODE SCIPpqueueInsert(
1336    SCIP_PQUEUE*          pqueue,             /**< priority queue */
1337    void*                 elem                /**< element to be inserted */
1338    )
1339 {
1340    int pos;
1341    int parentpos;
1342 
1343    assert(pqueue != NULL);
1344    assert(pqueue->len >= 0);
1345    assert(elem != NULL);
1346 
1347    SCIP_CALL( pqueueResize(pqueue, pqueue->len+1) );
1348 
1349    /* insert element as leaf in the tree, move it towards the root as long it is better than its parent */
1350    pos = pqueue->len;
1351    pqueue->len++;
1352    parentpos = PQ_PARENT(pos);
1353    while( pos > 0 && (*pqueue->ptrcomp)(elem, pqueue->slots[parentpos]) < 0 )
1354    {
1355       assert((*pqueue->ptrcomp)(pqueue->slots[parentpos], elem) >= 0);
1356       pqueueElemChgPos(pqueue, pqueue->slots[parentpos], parentpos, pos);
1357 
1358       pos = parentpos;
1359       parentpos = PQ_PARENT(pos);
1360    }
1361 
1362    /* insert element at the found position */
1363    pqueueElemChgPos(pqueue, elem, -1, pos);
1364 
1365 #ifdef SCIP_MORE_DEBUG
1366    assert(pqueueHasHeapProperty(pqueue));
1367 #endif
1368 
1369    return SCIP_OKAY;
1370 }
1371 
1372 
1373 /** delete element at specified position, maintaining the heap property */
SCIPpqueueDelPos(SCIP_PQUEUE * pqueue,int pos)1374 void SCIPpqueueDelPos(
1375    SCIP_PQUEUE*          pqueue,             /**< priority queue */
1376    int                   pos                 /**< position of element that should be deleted */
1377    )
1378 {
1379    void* last;
1380 
1381    assert(pqueue != NULL);
1382    assert(pos >= 0);
1383    assert(pos < SCIPpqueueNElems(pqueue));
1384 
1385    /* remove element at specified position of the tree, move the better child to its parents position until the last element
1386     * of the queue could be placed in the empty slot
1387     */
1388    pqueue->len--;
1389 
1390    /* everything in place */
1391    if( pos == pqueue->len )
1392       return;
1393 
1394    last = pqueue->slots[pqueue->len];
1395 
1396    /* last element is brought to pos. it may now violate the heap property compared to its parent, or to its children.
1397     * In the first case, move it up, otherwise, move it down.
1398     */
1399    while( pos > 0 && (*pqueue->ptrcomp)(last, pqueue->slots[PQ_PARENT(pos)]) < 0 )
1400    {
1401       pqueueElemChgPos(pqueue, pqueue->slots[PQ_PARENT(pos)], PQ_PARENT(pos), pos);
1402       pos = PQ_PARENT(pos);
1403    }
1404 
1405    while( pos <= PQ_PARENT(pqueue->len-1) )
1406    {
1407       int childpos = PQ_LEFTCHILD(pos);
1408       int brotherpos = PQ_RIGHTCHILD(pos);
1409 
1410       /* determine better of the two children */
1411       if( brotherpos < pqueue->len && (*pqueue->ptrcomp)(pqueue->slots[brotherpos], pqueue->slots[childpos]) < 0 )
1412          childpos = brotherpos;
1413 
1414       if( (*pqueue->ptrcomp)(last, pqueue->slots[childpos]) <= 0 )
1415          break;
1416 
1417       /* move better element from childpos to pos */
1418       pqueueElemChgPos(pqueue, pqueue->slots[childpos], childpos, pos);
1419 
1420       pos = childpos;
1421    }
1422 
1423    /* pos must point into a valid position */
1424    assert(pos <= pqueue->len - 1);
1425 
1426    pqueueElemChgPos(pqueue, last, pqueue->len, pos);
1427 
1428 #ifdef SCIP_MORE_DEBUG
1429    assert(pqueueHasHeapProperty(pqueue));
1430 #endif
1431 }
1432 
1433 /** removes and returns best element from the priority queue */
SCIPpqueueRemove(SCIP_PQUEUE * pqueue)1434 void* SCIPpqueueRemove(
1435    SCIP_PQUEUE*          pqueue              /**< priority queue */
1436    )
1437 {
1438    void* root;
1439 
1440    assert(pqueue != NULL);
1441    assert(pqueue->len >= 0);
1442 
1443    if( pqueue->len == 0 )
1444       return NULL;
1445 
1446    root = pqueue->slots[0];
1447 
1448    SCIPpqueueDelPos(pqueue, 0);
1449 
1450    return root;
1451 }
1452 
1453 /** returns the best element of the queue without removing it */
SCIPpqueueFirst(SCIP_PQUEUE * pqueue)1454 void* SCIPpqueueFirst(
1455    SCIP_PQUEUE*          pqueue              /**< priority queue */
1456    )
1457 {
1458    assert(pqueue != NULL);
1459    assert(pqueue->len >= 0);
1460 
1461    if( pqueue->len == 0 )
1462       return NULL;
1463 
1464    return pqueue->slots[0];
1465 }
1466 
1467 /** returns the number of elements in the queue */
SCIPpqueueNElems(SCIP_PQUEUE * pqueue)1468 int SCIPpqueueNElems(
1469    SCIP_PQUEUE*          pqueue              /**< priority queue */
1470    )
1471 {
1472    assert(pqueue != NULL);
1473    assert(pqueue->len >= 0);
1474 
1475    return pqueue->len;
1476 }
1477 
1478 /** returns the elements of the queue; changing the returned array may destroy the queue's ordering! */
SCIPpqueueElems(SCIP_PQUEUE * pqueue)1479 void** SCIPpqueueElems(
1480    SCIP_PQUEUE*          pqueue              /**< priority queue */
1481    )
1482 {
1483    assert(pqueue != NULL);
1484    assert(pqueue->len >= 0);
1485 
1486    return pqueue->slots;
1487 }
1488 
1489 /** return the position of @p elem in the priority queue, or -1 if element is not found */
SCIPpqueueFind(SCIP_PQUEUE * pqueue,void * elem)1490 int SCIPpqueueFind(
1491    SCIP_PQUEUE*          pqueue,             /**< priority queue */
1492    void*                 elem                /**< element to be inserted */
1493    )
1494 {
1495    int pos = -1;
1496 
1497    while( ++pos < SCIPpqueueNElems(pqueue) )
1498    {
1499       if( pqueue->slots[pos] == elem )
1500          return pos;
1501    }
1502 
1503    return -1;
1504 }
1505 
1506 
1507 
1508 
1509 /*
1510  * Hash Table
1511  */
1512 
1513 /** table of some prime numbers */
1514 static int primetable[] = {
1515    2,
1516    7,
1517    19,
1518    31,
1519    59,
1520    227,
1521    617,
1522    1523,
1523    3547,
1524    8011,
1525    17707,
1526    38723,
1527    83833,
1528    180317,
1529    385897,
1530    821411,
1531    1742369,
1532    3680893,
1533    5693959,
1534    7753849,
1535    9849703,
1536    11973277,
1537    14121853,
1538    17643961,
1539    24273817,
1540    32452843,
1541    49979687,
1542    67867967,
1543    86028121,
1544    104395301,
1545    122949823,
1546    141650939,
1547    160481183,
1548    179424673,
1549    198491317,
1550    217645177,
1551    256203161,
1552    314606869,
1553    373587883,
1554    433024223,
1555    492876847,
1556    553105243,
1557    613651349,
1558    694847533,
1559    756065159,
1560    817504243,
1561    879190747,
1562    941083981,
1563    982451653,
1564    INT_MAX
1565 };
1566 static const int primetablesize = sizeof(primetable)/sizeof(int);
1567 
1568 /** simple and fast 2-universal hash function using multiply and shift */
1569 static
hashvalue(uint64_t input)1570 uint32_t hashvalue(
1571    uint64_t              input               /**< key value */
1572    )
1573 {
1574    return ( (uint32_t) ((UINT64_C(0x9e3779b97f4a7c15) * input)>>32) ) | 1u;
1575 }
1576 
1577 /** returns a reasonable hash table size (a prime number) that is at least as large as the specified value */
SCIPcalcMultihashSize(int minsize)1578 int SCIPcalcMultihashSize(
1579    int                   minsize             /**< minimal size of the hash table */
1580    )
1581 {
1582    int pos;
1583 
1584    (void) SCIPsortedvecFindInt(primetable, minsize, primetablesize, &pos);
1585    assert(0 <= pos && pos < primetablesize);
1586 
1587    return primetable[pos];
1588 }
1589 
1590 /** appends element to the multihash list */
1591 static
multihashlistAppend(SCIP_MULTIHASHLIST ** multihashlist,BMS_BLKMEM * blkmem,void * element)1592 SCIP_RETCODE multihashlistAppend(
1593    SCIP_MULTIHASHLIST**  multihashlist,      /**< pointer to hash list */
1594    BMS_BLKMEM*           blkmem,             /**< block memory */
1595    void*                 element             /**< element to append to the list */
1596    )
1597 {
1598    SCIP_MULTIHASHLIST* newlist;
1599 
1600    assert(multihashlist != NULL);
1601    assert(blkmem != NULL);
1602    assert(element != NULL);
1603 
1604    SCIP_ALLOC( BMSallocBlockMemory(blkmem, &newlist) );
1605    newlist->element = element;
1606    newlist->next = *multihashlist;
1607    *multihashlist = newlist;
1608 
1609    return SCIP_OKAY;
1610 }
1611 
1612 /** frees a multihash list entry and all its successors */
1613 static
multihashlistFree(SCIP_MULTIHASHLIST ** multihashlist,BMS_BLKMEM * blkmem)1614 void multihashlistFree(
1615    SCIP_MULTIHASHLIST**  multihashlist,      /**< pointer to multihash list to free */
1616    BMS_BLKMEM*           blkmem              /**< block memory */
1617    )
1618 {
1619    SCIP_MULTIHASHLIST* list;
1620    SCIP_MULTIHASHLIST* nextlist;
1621 
1622    assert(multihashlist != NULL);
1623    assert(blkmem != NULL);
1624 
1625    list = *multihashlist;
1626    while( list != NULL )
1627    {
1628       nextlist = list->next;
1629       BMSfreeBlockMemory(blkmem, &list);
1630       list = nextlist;
1631    }
1632 
1633    *multihashlist = NULL;
1634 }
1635 
1636 /** finds multihash list entry pointing to element with given key in the multihash list, returns NULL if not found */
1637 static
multihashlistFind(SCIP_MULTIHASHLIST * multihashlist,SCIP_DECL_HASHGETKEY ((* hashgetkey)),SCIP_DECL_HASHKEYEQ ((* hashkeyeq)),SCIP_DECL_HASHKEYVAL ((* hashkeyval)),void * userptr,uint64_t keyval,void * key)1638 SCIP_MULTIHASHLIST* multihashlistFind(
1639    SCIP_MULTIHASHLIST*   multihashlist,      /**< multihash list */
1640    SCIP_DECL_HASHGETKEY((*hashgetkey)),      /**< gets the key of the given element */
1641    SCIP_DECL_HASHKEYEQ ((*hashkeyeq)),       /**< returns TRUE iff both keys are equal */
1642    SCIP_DECL_HASHKEYVAL((*hashkeyval)),      /**< returns the hash value of the key */
1643    void*                 userptr,            /**< user pointer */
1644    uint64_t              keyval,             /**< hash value of key */
1645    void*                 key                 /**< key to retrieve */
1646    )
1647 {
1648    uint64_t currentkeyval;
1649    void* currentkey;
1650 
1651    assert(hashkeyeq != NULL);
1652    assert(key != NULL);
1653 
1654    while( multihashlist != NULL )
1655    {
1656       currentkey = hashgetkey(userptr, multihashlist->element);
1657       currentkeyval = hashkeyval(userptr, currentkey);
1658       if( currentkeyval == keyval && hashkeyeq(userptr, currentkey, key) )
1659          return multihashlist;
1660 
1661       multihashlist = multihashlist->next;
1662    }
1663 
1664    return NULL;
1665 }
1666 
1667 /** retrieves element with given key from the multihash list, or NULL */
1668 static
multihashlistRetrieve(SCIP_MULTIHASHLIST * multihashlist,SCIP_DECL_HASHGETKEY ((* hashgetkey)),SCIP_DECL_HASHKEYEQ ((* hashkeyeq)),SCIP_DECL_HASHKEYVAL ((* hashkeyval)),void * userptr,uint64_t keyval,void * key)1669 void* multihashlistRetrieve(
1670    SCIP_MULTIHASHLIST*   multihashlist,      /**< hash list */
1671    SCIP_DECL_HASHGETKEY((*hashgetkey)),      /**< gets the key of the given element */
1672    SCIP_DECL_HASHKEYEQ ((*hashkeyeq)),       /**< returns TRUE iff both keys are equal */
1673    SCIP_DECL_HASHKEYVAL((*hashkeyval)),      /**< returns the hash value of the key */
1674    void*                 userptr,            /**< user pointer */
1675    uint64_t              keyval,             /**< hash value of key */
1676    void*                 key                 /**< key to retrieve */
1677    )
1678 {
1679    SCIP_MULTIHASHLIST* h;
1680 
1681    /* find hash list entry */
1682    h = multihashlistFind(multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1683 
1684    /* return element */
1685    if( h != NULL )
1686    {
1687 #ifndef NDEBUG
1688       SCIP_MULTIHASHLIST* h2;
1689 
1690       h2 = multihashlistFind(h->next, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1691 
1692       if( h2 != NULL )
1693       {
1694          void* key1;
1695          void* key2;
1696 
1697          key1 = hashgetkey(userptr, h->element);
1698          key2 = hashgetkey(userptr, h2->element);
1699          assert(hashkeyval(userptr, key1) == hashkeyval(userptr, key2));
1700 
1701          if( hashkeyeq(userptr, key1, key2) )
1702          {
1703             SCIPerrorMessage("WARNING: hashkey with same value exists multiple times (e.g. duplicate constraint/variable names), so the return value is maybe not correct\n");
1704          }
1705       }
1706 #endif
1707 
1708       return h->element;
1709    }
1710    else
1711       return NULL;
1712 }
1713 
1714 
1715 /** retrieves element with given key from the multihash list, or NULL
1716  *  returns pointer to multihash table list entry
1717  */
1718 static
multihashlistRetrieveNext(SCIP_MULTIHASHLIST ** multihashlist,SCIP_DECL_HASHGETKEY ((* hashgetkey)),SCIP_DECL_HASHKEYEQ ((* hashkeyeq)),SCIP_DECL_HASHKEYVAL ((* hashkeyval)),void * userptr,uint64_t keyval,void * key)1719 void* multihashlistRetrieveNext(
1720    SCIP_MULTIHASHLIST**  multihashlist,      /**< on input: hash list to search; on exit: hash list entry corresponding
1721                                               *   to element after retrieved one, or NULL */
1722    SCIP_DECL_HASHGETKEY((*hashgetkey)),      /**< gets the key of the given element */
1723    SCIP_DECL_HASHKEYEQ ((*hashkeyeq)),       /**< returns TRUE iff both keys are equal */
1724    SCIP_DECL_HASHKEYVAL((*hashkeyval)),      /**< returns the hash value of the key */
1725    void*                 userptr,            /**< user pointer */
1726    uint64_t              keyval,             /**< hash value of key */
1727    void*                 key                 /**< key to retrieve */
1728    )
1729 {
1730    SCIP_MULTIHASHLIST* h;
1731 
1732    assert(multihashlist != NULL);
1733 
1734    /* find hash list entry */
1735    h = multihashlistFind(*multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1736 
1737    /* return element */
1738    if( h != NULL )
1739    {
1740       *multihashlist = h->next;
1741 
1742       return h->element;
1743    }
1744 
1745    *multihashlist = NULL;
1746 
1747    return NULL;
1748 }
1749 
1750 /** removes element from the multihash list */
1751 static
multihashlistRemove(SCIP_MULTIHASHLIST ** multihashlist,BMS_BLKMEM * blkmem,void * element)1752 SCIP_Bool multihashlistRemove(
1753    SCIP_MULTIHASHLIST**  multihashlist,      /**< pointer to hash list */
1754    BMS_BLKMEM*           blkmem,             /**< block memory */
1755    void*                 element             /**< element to remove from the list */
1756    )
1757 {
1758    SCIP_MULTIHASHLIST* nextlist;
1759 
1760    assert(multihashlist != NULL);
1761    assert(blkmem != NULL);
1762    assert(element != NULL);
1763 
1764    while( *multihashlist != NULL && (*multihashlist)->element != element )
1765       multihashlist = &(*multihashlist)->next;
1766 
1767    if( *multihashlist != NULL )
1768    {
1769       nextlist = (*multihashlist)->next;
1770       BMSfreeBlockMemory(blkmem, multihashlist);
1771       *multihashlist = nextlist;
1772 
1773       return TRUE;
1774    }
1775 
1776    return FALSE;
1777 }
1778 
1779 #define SCIP_MULTIHASH_MAXSIZE 33554431 /* 2^25 - 1*/
1780 #define SCIP_MULTIHASH_RESIZE_PERCENTAGE 65
1781 #define SCIP_MULTIHASH_GROW_FACTOR 1.31
1782 
1783 /** resizing(increasing) the given multihash */
1784 static
multihashResize(SCIP_MULTIHASH * multihash)1785 SCIP_RETCODE multihashResize(
1786    SCIP_MULTIHASH*       multihash           /**< hash table */
1787    )
1788 {
1789    SCIP_MULTIHASHLIST** newlists;
1790    SCIP_MULTIHASHLIST* multihashlist;
1791    SCIP_Longint nelements;
1792    int nnewlists;
1793    int l;
1794 
1795    assert(multihash != NULL);
1796    assert(multihash->lists != NULL);
1797    assert(multihash->nlists > 0);
1798    assert(multihash->hashgetkey != NULL);
1799    assert(multihash->hashkeyeq != NULL);
1800    assert(multihash->hashkeyval != NULL);
1801 
1802    /* get new memeory for hash table lists */
1803    nnewlists = (int) MIN((unsigned int)(multihash->nlists * SCIP_MULTIHASH_GROW_FACTOR), SCIP_MULTIHASH_MAXSIZE);
1804    nnewlists = MAX(nnewlists, multihash->nlists);
1805 
1806    SCIPdebugMessage("load = %g, nelements = %" SCIP_LONGINT_FORMAT ", nlists = %d, nnewlist = %d\n", SCIPmultihashGetLoad(multihash), multihash->nelements, multihash->nlists, nnewlists);
1807 
1808    if( nnewlists > multihash->nlists )
1809    {
1810       SCIP_Bool onlyone;
1811       void* key;
1812       uint64_t keyval;
1813       unsigned int hashval;
1814 
1815       SCIP_ALLOC( BMSallocClearBlockMemoryArray(multihash->blkmem, &newlists, nnewlists) );
1816 
1817       /* move all lists */
1818       for( l = multihash->nlists - 1; l >= 0; --l )
1819       {
1820          multihashlist = multihash->lists[l];
1821          onlyone = TRUE;
1822 
1823          /* move all elements frmm the old lists into the new lists */
1824          while( multihashlist != NULL )
1825          {
1826             /* get the hash key and its hash value */
1827             key = multihash->hashgetkey(multihash->userptr, multihashlist->element);
1828             keyval = multihash->hashkeyval(multihash->userptr, key);
1829             hashval = (unsigned int) (keyval % (unsigned) nnewlists); /*lint !e573*/
1830 
1831             /* if the old hash table list consists of only one entry, we still can use this old memory block instead
1832              * of creating a new one
1833              */
1834             if( multihashlist->next == NULL && onlyone )
1835             {
1836                /* the new list is also empty, we can directly copy the entry */
1837                if( newlists[hashval] == NULL )
1838                   newlists[hashval] = multihashlist;
1839                /* the new list is not empty, so we need to find the first empty spot */
1840                else
1841                {
1842                   SCIP_MULTIHASHLIST* lastnext = newlists[hashval];
1843                   SCIP_MULTIHASHLIST* next = lastnext->next;
1844 
1845                   while( next != NULL )
1846                   {
1847                      lastnext = next;
1848                      next = next->next;
1849                   }
1850 
1851                   lastnext->next = multihashlist;
1852                }
1853 
1854                multihash->lists[l] = NULL;
1855             }
1856             else
1857             {
1858                /* append old element to the list at the hash position */
1859                SCIP_CALL( multihashlistAppend(&(newlists[hashval]), multihash->blkmem, multihashlist->element) );
1860             }
1861 
1862             onlyone = FALSE;
1863             multihashlist = multihashlist->next;
1864          }
1865       }
1866 
1867       /* remember number of elements */
1868       nelements = multihash->nelements;
1869       /* clear old lists */
1870       SCIPmultihashRemoveAll(multihash);
1871       /* free old lists */
1872       BMSfreeBlockMemoryArray(multihash->blkmem, &(multihash->lists), multihash->nlists);
1873 
1874       /* set new data */
1875       multihash->lists = newlists;
1876       multihash->nlists = nnewlists;
1877       multihash->nelements = nelements;
1878 
1879 #ifdef SCIP_MORE_DEBUG
1880       {
1881          SCIP_Longint sumslotsize = 0;
1882 
1883          for( l = 0; l < multihash->nlists; ++l )
1884          {
1885             multihashlist = multihash->lists[l];
1886             while( multihashlist != NULL )
1887             {
1888                sumslotsize++;
1889                multihashlist = multihashlist->next;
1890             }
1891          }
1892          assert(sumslotsize == multihash->nelements);
1893       }
1894 #endif
1895    }
1896 
1897    return SCIP_OKAY;
1898 }
1899 
1900 /** creates a multihash table */
SCIPmultihashCreate(SCIP_MULTIHASH ** multihash,BMS_BLKMEM * blkmem,int tablesize,SCIP_DECL_HASHGETKEY ((* hashgetkey)),SCIP_DECL_HASHKEYEQ ((* hashkeyeq)),SCIP_DECL_HASHKEYVAL ((* hashkeyval)),void * userptr)1901 SCIP_RETCODE SCIPmultihashCreate(
1902    SCIP_MULTIHASH**      multihash,          /**< pointer to store the created multihash table */
1903    BMS_BLKMEM*           blkmem,             /**< block memory used to store multihash table entries */
1904    int                   tablesize,          /**< size of the hash table */
1905    SCIP_DECL_HASHGETKEY((*hashgetkey)),      /**< gets the key of the given element */
1906    SCIP_DECL_HASHKEYEQ ((*hashkeyeq)),       /**< returns TRUE iff both keys are equal */
1907    SCIP_DECL_HASHKEYVAL((*hashkeyval)),      /**< returns the hash value of the key */
1908    void*                 userptr             /**< user pointer */
1909    )
1910 {
1911    /* only assert non negative to catch overflow errors
1912     * but not zeros due to integer divison
1913     */
1914    assert(tablesize >= 0);
1915    assert(multihash != NULL);
1916    assert(hashgetkey != NULL);
1917    assert(hashkeyeq != NULL);
1918    assert(hashkeyval != NULL);
1919 
1920    SCIP_ALLOC( BMSallocBlockMemory(blkmem, multihash) );
1921    SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*multihash)->lists, tablesize) );
1922    (*multihash)->blkmem = blkmem;
1923    (*multihash)->nlists = tablesize;
1924    (*multihash)->hashgetkey = hashgetkey;
1925    (*multihash)->hashkeyeq = hashkeyeq;
1926    (*multihash)->hashkeyval = hashkeyval;
1927    (*multihash)->userptr = userptr;
1928    (*multihash)->nelements = 0;
1929 
1930    return SCIP_OKAY;
1931 }
1932 
1933 /** frees the multihash table */
SCIPmultihashFree(SCIP_MULTIHASH ** multihash)1934 void SCIPmultihashFree(
1935    SCIP_MULTIHASH**      multihash           /**< pointer to the multihash table */
1936    )
1937 {
1938    int i;
1939    SCIP_MULTIHASH* table;
1940    BMS_BLKMEM* blkmem;
1941    SCIP_MULTIHASHLIST** lists;
1942 
1943    assert(multihash != NULL);
1944    assert(*multihash != NULL);
1945 
1946    table = (*multihash);
1947    blkmem = table->blkmem;
1948    lists = table->lists;
1949 
1950    /* free hash lists */
1951    for( i = table->nlists - 1; i >= 0; --i )
1952       multihashlistFree(&lists[i], blkmem);
1953 
1954    /* free main hash table data structure */
1955    BMSfreeBlockMemoryArray(blkmem, &table->lists, table->nlists);
1956    BMSfreeBlockMemory(blkmem, multihash);
1957 }
1958 
1959 
1960 /** inserts element in multihash table (multiple inserts of same element possible)
1961  *
1962  *  @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding an element
1963  *        to the hash table, due to dynamic resizing.
1964  */
SCIPmultihashInsert(SCIP_MULTIHASH * multihash,void * element)1965 SCIP_RETCODE SCIPmultihashInsert(
1966    SCIP_MULTIHASH*       multihash,          /**< multihash table */
1967    void*                 element             /**< element to insert into the table */
1968    )
1969 {
1970    void* key;
1971    uint64_t keyval;
1972    unsigned int hashval;
1973 
1974    assert(multihash != NULL);
1975    assert(multihash->lists != NULL);
1976    assert(multihash->nlists > 0);
1977    assert(multihash->hashgetkey != NULL);
1978    assert(multihash->hashkeyeq != NULL);
1979    assert(multihash->hashkeyval != NULL);
1980    assert(element != NULL);
1981 
1982    /* dynamically resizing the hashtables */
1983    if( SCIPmultihashGetLoad(multihash) > SCIP_MULTIHASH_RESIZE_PERCENTAGE )
1984    {
1985       SCIP_CALL( multihashResize(multihash) );
1986    }
1987 
1988    /* get the hash key and its hash value */
1989    key = multihash->hashgetkey(multihash->userptr, element);
1990    keyval = multihash->hashkeyval(multihash->userptr, key);
1991    hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
1992 
1993    /* append element to the list at the hash position */
1994    SCIP_CALL( multihashlistAppend(&multihash->lists[hashval], multihash->blkmem, element) );
1995 
1996    ++(multihash->nelements);
1997 
1998    return SCIP_OKAY;
1999 }
2000 
2001 /** inserts element in multihash table (multiple insertion of same element is checked and results in an error)
2002  *
2003  *  @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding a new
2004  *        element to the multihash table, due to dynamic resizing.
2005  */
SCIPmultihashSafeInsert(SCIP_MULTIHASH * multihash,void * element)2006 SCIP_RETCODE SCIPmultihashSafeInsert(
2007    SCIP_MULTIHASH*       multihash,          /**< multihash table */
2008    void*                 element             /**< element to insert into the table */
2009    )
2010 {
2011    assert(multihash != NULL);
2012    assert(multihash->hashgetkey != NULL);
2013 
2014    /* check, if key is already existing */
2015    if( SCIPmultihashRetrieve(multihash, multihash->hashgetkey(multihash->userptr, element)) != NULL )
2016       return SCIP_KEYALREADYEXISTING;
2017 
2018    /* insert element in hash table */
2019    SCIP_CALL( SCIPmultihashInsert(multihash, element) );
2020 
2021    return SCIP_OKAY;
2022 }
2023 
2024 /** retrieve element with key from multihash table, returns NULL if not existing */
SCIPmultihashRetrieve(SCIP_MULTIHASH * multihash,void * key)2025 void* SCIPmultihashRetrieve(
2026    SCIP_MULTIHASH*       multihash,          /**< multihash table */
2027    void*                 key                 /**< key to retrieve */
2028    )
2029 {
2030    uint64_t keyval;
2031    unsigned int hashval;
2032 
2033    assert(multihash != NULL);
2034    assert(multihash->lists != NULL);
2035    assert(multihash->nlists > 0);
2036    assert(multihash->hashgetkey != NULL);
2037    assert(multihash->hashkeyeq != NULL);
2038    assert(multihash->hashkeyval != NULL);
2039    assert(key != NULL);
2040 
2041    /* get the hash value of the key */
2042    keyval = multihash->hashkeyval(multihash->userptr, key);
2043    hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2044 
2045    return multihashlistRetrieve(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
2046       multihash->hashkeyval, multihash->userptr, keyval, key);
2047 }
2048 
2049 /** retrieve element with key from multihash table, returns NULL if not existing
2050  *  can be used to retrieve all entries with the same key (one-by-one)
2051  *
2052  *  @note The returned multimultihashlist pointer might get invalid when adding a new element to the multihash table.
2053  */
SCIPmultihashRetrieveNext(SCIP_MULTIHASH * multihash,SCIP_MULTIHASHLIST ** multihashlist,void * key)2054 void* SCIPmultihashRetrieveNext(
2055    SCIP_MULTIHASH*       multihash,          /**< multihash table */
2056    SCIP_MULTIHASHLIST**  multihashlist,      /**< input: entry in hash table list from which to start searching, or NULL
2057                                               *   output: entry in hash table list corresponding to element after
2058                                               *           retrieved one, or NULL */
2059    void*                 key                 /**< key to retrieve */
2060    )
2061 {
2062    uint64_t keyval;
2063 
2064    assert(multihash != NULL);
2065    assert(multihash->lists != NULL);
2066    assert(multihash->nlists > 0);
2067    assert(multihash->hashgetkey != NULL);
2068    assert(multihash->hashkeyeq != NULL);
2069    assert(multihash->hashkeyval != NULL);
2070    assert(multihashlist != NULL);
2071    assert(key != NULL);
2072 
2073    keyval = multihash->hashkeyval(multihash->userptr, key);
2074 
2075    if( *multihashlist == NULL )
2076    {
2077       unsigned int hashval;
2078 
2079       /* get the hash value of the key */
2080       hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2081 
2082       *multihashlist = multihash->lists[hashval];
2083    }
2084 
2085    return multihashlistRetrieveNext(multihashlist, multihash->hashgetkey, multihash->hashkeyeq,
2086       multihash->hashkeyval, multihash->userptr, keyval, key);
2087 }
2088 
2089 /** returns whether the given element exists in the multihash table */
SCIPmultihashExists(SCIP_MULTIHASH * multihash,void * element)2090 SCIP_Bool SCIPmultihashExists(
2091    SCIP_MULTIHASH*       multihash,          /**< multihash table */
2092    void*                 element             /**< element to search in the table */
2093    )
2094 {
2095    void* key;
2096    uint64_t keyval;
2097    unsigned int hashval;
2098 
2099    assert(multihash != NULL);
2100    assert(multihash->lists != NULL);
2101    assert(multihash->nlists > 0);
2102    assert(multihash->hashgetkey != NULL);
2103    assert(multihash->hashkeyeq != NULL);
2104    assert(multihash->hashkeyval != NULL);
2105    assert(element != NULL);
2106 
2107    /* get the hash key and its hash value */
2108    key = multihash->hashgetkey(multihash->userptr, element);
2109    keyval = multihash->hashkeyval(multihash->userptr, key);
2110    hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2111 
2112    return (multihashlistFind(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
2113          multihash->hashkeyval, multihash->userptr, keyval, key) != NULL);
2114 }
2115 
2116 /** removes element from the multihash table, if it exists */
SCIPmultihashRemove(SCIP_MULTIHASH * multihash,void * element)2117 SCIP_RETCODE SCIPmultihashRemove(
2118    SCIP_MULTIHASH*       multihash,          /**< multihash table */
2119    void*                 element             /**< element to remove from the table */
2120    )
2121 {
2122    void* key;
2123    uint64_t keyval;
2124    unsigned int hashval;
2125 
2126    assert(multihash != NULL);
2127    assert(multihash->lists != NULL);
2128    assert(multihash->nlists > 0);
2129    assert(multihash->hashgetkey != NULL);
2130    assert(multihash->hashkeyeq != NULL);
2131    assert(multihash->hashkeyval != NULL);
2132    assert(element != NULL);
2133 
2134    /* get the hash key and its hash value */
2135    key = multihash->hashgetkey(multihash->userptr, element);
2136    keyval = multihash->hashkeyval(multihash->userptr, key);
2137    hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2138 
2139    /* remove element from the list at the hash position */
2140    if( multihashlistRemove(&multihash->lists[hashval], multihash->blkmem, element) )
2141       --(multihash->nelements);
2142 
2143    return SCIP_OKAY;
2144 }
2145 
2146 /** removes all elements of the multihash table
2147  *
2148  *  @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
2149  *        be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
2150  */
SCIPmultihashRemoveAll(SCIP_MULTIHASH * multihash)2151 void SCIPmultihashRemoveAll(
2152    SCIP_MULTIHASH*       multihash           /**< multihash table */
2153    )
2154 {
2155    BMS_BLKMEM* blkmem;
2156    SCIP_MULTIHASHLIST** lists;
2157    int i;
2158 
2159    assert(multihash != NULL);
2160 
2161    blkmem = multihash->blkmem;
2162    lists = multihash->lists;
2163 
2164    /* free hash lists */
2165    for( i = multihash->nlists - 1; i >= 0; --i )
2166       multihashlistFree(&lists[i], blkmem);
2167 
2168    multihash->nelements = 0;
2169 }
2170 
2171 /** returns number of multihash table elements */
SCIPmultihashGetNElements(SCIP_MULTIHASH * multihash)2172 SCIP_Longint SCIPmultihashGetNElements(
2173    SCIP_MULTIHASH*       multihash           /**< multihash table */
2174    )
2175 {
2176    assert(multihash != NULL);
2177 
2178    return multihash->nelements;
2179 }
2180 
2181 /** returns the load of the given multihash table in percentage */
SCIPmultihashGetLoad(SCIP_MULTIHASH * multihash)2182 SCIP_Real SCIPmultihashGetLoad(
2183    SCIP_MULTIHASH*       multihash           /**< multihash table */
2184    )
2185 {
2186    assert(multihash != NULL);
2187 
2188    return ((SCIP_Real)(multihash->nelements) / (multihash->nlists) * 100.0);
2189 }
2190 
2191 /** prints statistics about multihash table usage */
SCIPmultihashPrintStatistics(SCIP_MULTIHASH * multihash,SCIP_MESSAGEHDLR * messagehdlr)2192 void SCIPmultihashPrintStatistics(
2193    SCIP_MULTIHASH*       multihash,          /**< multihash table */
2194    SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
2195    )
2196 {
2197    SCIP_MULTIHASHLIST* multihashlist;
2198    int usedslots;
2199    int maxslotsize;
2200    int sumslotsize;
2201    int slotsize;
2202    int i;
2203 
2204    assert(multihash != NULL);
2205 
2206    usedslots = 0;
2207    maxslotsize = 0;
2208    sumslotsize = 0;
2209    for( i = 0; i < multihash->nlists; ++i )
2210    {
2211       multihashlist = multihash->lists[i];
2212       if( multihashlist != NULL )
2213       {
2214          usedslots++;
2215          slotsize = 0;
2216          while( multihashlist != NULL )
2217          {
2218             slotsize++;
2219             multihashlist = multihashlist->next;
2220          }
2221          maxslotsize = MAX(maxslotsize, slotsize);
2222          sumslotsize += slotsize;
2223       }
2224    }
2225    assert(sumslotsize == multihash->nelements);
2226 
2227    SCIPmessagePrintInfo(messagehdlr, "%" SCIP_LONGINT_FORMAT " multihash entries, used %d/%d slots (%.1f%%)",
2228       multihash->nelements, usedslots, multihash->nlists, 100.0*(SCIP_Real)usedslots/(SCIP_Real)(multihash->nlists));
2229    if( usedslots > 0 )
2230       SCIPmessagePrintInfo(messagehdlr, ", avg. %.1f entries/used slot, max. %d entries in slot",
2231          (SCIP_Real)(multihash->nelements)/(SCIP_Real)usedslots, maxslotsize);
2232    SCIPmessagePrintInfo(messagehdlr, "\n");
2233 }
2234 
2235 /** creates a hash table */
SCIPhashtableCreate(SCIP_HASHTABLE ** hashtable,BMS_BLKMEM * blkmem,int tablesize,SCIP_DECL_HASHGETKEY ((* hashgetkey)),SCIP_DECL_HASHKEYEQ ((* hashkeyeq)),SCIP_DECL_HASHKEYVAL ((* hashkeyval)),void * userptr)2236 SCIP_RETCODE SCIPhashtableCreate(
2237    SCIP_HASHTABLE**      hashtable,          /**< pointer to store the created hash table */
2238    BMS_BLKMEM*           blkmem,             /**< block memory used to store hash table entries */
2239    int                   tablesize,          /**< size of the hash table */
2240    SCIP_DECL_HASHGETKEY((*hashgetkey)),      /**< gets the key of the given element */
2241    SCIP_DECL_HASHKEYEQ ((*hashkeyeq)),       /**< returns TRUE iff both keys are equal */
2242    SCIP_DECL_HASHKEYVAL((*hashkeyval)),      /**< returns the hash value of the key */
2243    void*                 userptr             /**< user pointer */
2244    )
2245 {
2246    unsigned int nslots;
2247 
2248    /* only assert non negative to catch overflow errors
2249     * but not zeros due to integer divison
2250     */
2251    assert(tablesize >= 0);
2252    assert(hashtable != NULL);
2253    assert(hashgetkey != NULL);
2254    assert(hashkeyeq != NULL);
2255    assert(hashkeyval != NULL);
2256    assert(blkmem != NULL);
2257 
2258    SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashtable) );
2259 
2260    /* dont create too small hashtables, i.e. at least size 32, and increase
2261     * the given size by divinding it by 0.9, since then no rebuilding will
2262     * be necessary if the given number of elements are inserted. Finally round
2263     * to the next power of two.
2264     */
2265    (*hashtable)->shift = 32;
2266    (*hashtable)->shift -= (unsigned int)ceil(LOG2(MAX(32.0, tablesize / 0.9)));
2267 
2268    /* compute size from shift */
2269    nslots = 1u << (32 - (*hashtable)->shift);
2270 
2271    /* compute mask to do a fast modulo by nslots using bitwise and */
2272    (*hashtable)->mask = nslots - 1;
2273    SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*hashtable)->slots, nslots) );
2274    SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashtable)->hashes, nslots) );
2275    (*hashtable)->blkmem = blkmem;
2276    (*hashtable)->hashgetkey = hashgetkey;
2277    (*hashtable)->hashkeyeq = hashkeyeq;
2278    (*hashtable)->hashkeyval = hashkeyval;
2279    (*hashtable)->userptr = userptr;
2280    (*hashtable)->nelements = 0;
2281 
2282    return SCIP_OKAY;
2283 }
2284 
2285 /** frees the hash table */
SCIPhashtableFree(SCIP_HASHTABLE ** hashtable)2286 void SCIPhashtableFree(
2287    SCIP_HASHTABLE**      hashtable           /**< pointer to the hash table */
2288    )
2289 {
2290    uint32_t nslots;
2291    SCIP_HASHTABLE* table;
2292 
2293    assert(hashtable != NULL);
2294    assert(*hashtable != NULL);
2295    table = *hashtable;
2296    nslots = (*hashtable)->mask + 1;
2297 #ifdef SCIP_DEBUG
2298    {
2299       uint32_t maxprobelen = 0;
2300       uint64_t probelensum = 0;
2301       uint32_t i;
2302 
2303       assert(table != NULL);
2304 
2305       for( i = 0; i < nslots; ++i )
2306       {
2307          if( table->hashes[i] != 0 )
2308          {
2309             uint32_t probelen = ((i + table->mask + 1 - (table->hashes[i]>>(table->shift))) & table->mask) + 1;
2310             probelensum += probelen;
2311             maxprobelen = MAX(probelen, maxprobelen);
2312          }
2313       }
2314 
2315       SCIPdebugMessage("%u hash table entries, used %u/%u slots (%.1f%%)",
2316                        (unsigned int)table->nelements, (unsigned int)table->nelements, (unsigned int)nslots,
2317                        100.0*(SCIP_Real)table->nelements/(SCIP_Real)(nslots));
2318       if( table->nelements > 0 )
2319          SCIPdebugMessage(", avg. probe length is %.1f, max. probe length is %u",
2320                               (SCIP_Real)(probelensum)/(SCIP_Real)table->nelements, (unsigned int)maxprobelen);
2321       SCIPdebugMessage("\n");
2322    }
2323 #endif
2324 
2325    /* free main hash table data structure */
2326    BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->hashes, nslots);
2327    BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->slots, nslots);
2328    BMSfreeBlockMemory((*hashtable)->blkmem, hashtable);
2329 }
2330 
2331 /** removes all elements of the hash table
2332  *
2333  *  @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
2334  *        be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
2335  *
2336  *  @deprecated Please use SCIPhashtableRemoveAll()
2337  */
SCIPhashtableClear(SCIP_HASHTABLE * hashtable)2338 void SCIPhashtableClear(
2339    SCIP_HASHTABLE*       hashtable           /**< hash table */
2340    )
2341 {
2342    SCIPhashtableRemoveAll(hashtable);
2343 }
2344 
2345 /* computes the distance from it's desired position for the element stored at pos */
2346 #define ELEM_DISTANCE(pos) (((pos) + hashtable->mask + 1 - (hashtable->hashes[(pos)]>>(hashtable->shift))) & hashtable->mask)
2347 
2348 /** inserts element in hash table (multiple inserts of same element overrides previous one) */
2349 static
hashtableInsert(SCIP_HASHTABLE * hashtable,void * element,void * key,uint32_t hashval,SCIP_Bool override)2350 SCIP_RETCODE hashtableInsert(
2351    SCIP_HASHTABLE*       hashtable,          /**< hash table */
2352    void*                 element,            /**< element to insert into the table */
2353    void*                 key,                /**< key of element */
2354    uint32_t              hashval,            /**< hash value of element */
2355    SCIP_Bool             override            /**< should element be overridden or an error be returned if already existing */
2356    )
2357 {
2358    uint32_t elemdistance;
2359    uint32_t pos;
2360 #ifndef NDEBUG
2361    SCIP_Bool swapped = FALSE;
2362 #endif
2363 
2364    assert(hashtable != NULL);
2365    assert(hashtable->slots != NULL);
2366    assert(hashtable->hashes != NULL);
2367    assert(hashtable->mask > 0);
2368    assert(hashtable->hashgetkey != NULL);
2369    assert(hashtable->hashkeyeq != NULL);
2370    assert(hashtable->hashkeyval != NULL);
2371    assert(element != NULL);
2372 
2373    pos = hashval>>(hashtable->shift);
2374    elemdistance = 0;
2375    while( TRUE ) /*lint !e716*/
2376    {
2377       uint32_t distance;
2378 
2379       /* if position is empty or key equal insert element */
2380       if( hashtable->hashes[pos] == 0 )
2381       {
2382          hashtable->slots[pos] = element;
2383          hashtable->hashes[pos] = hashval;
2384          ++hashtable->nelements;
2385          return SCIP_OKAY;
2386       }
2387 
2388       if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2389              hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2390       {
2391          if( override )
2392          {
2393 #ifndef NDEBUG
2394             assert(! swapped);
2395 #endif
2396             hashtable->slots[pos] = element;
2397             hashtable->hashes[pos] = hashval;
2398             return SCIP_OKAY;
2399          }
2400          else
2401          {
2402             return SCIP_KEYALREADYEXISTING;
2403          }
2404       }
2405 
2406       /* otherwise check if the current element at this position is closer to its hashvalue */
2407       distance = ELEM_DISTANCE(pos);
2408       if( distance < elemdistance )
2409       {
2410          uint32_t tmp;
2411 
2412          /* if this is the case we insert the new element here and find a new position for the old one */
2413          elemdistance = distance;
2414          SCIPswapPointers(&hashtable->slots[pos], &element);
2415          tmp = hashval;
2416          hashval = hashtable->hashes[pos];
2417          hashtable->hashes[pos] = tmp;
2418          key = hashtable->hashgetkey(hashtable->userptr, element);
2419 
2420          /* after doing a swap the case that other elements are replaced must not happen anymore */
2421 #ifndef NDEBUG
2422          swapped = TRUE;
2423 #endif
2424       }
2425 
2426       /* continue until we have found an empty position */
2427       pos = (pos + 1) & hashtable->mask;
2428       ++elemdistance;
2429    }
2430 }
2431 
2432 /** check if the load factor of the hashtable is too high and rebuild if necessary */
2433 static
hashtableCheckLoad(SCIP_HASHTABLE * hashtable)2434 SCIP_RETCODE hashtableCheckLoad(
2435    SCIP_HASHTABLE*       hashtable           /**< hash table */
2436    )
2437 {
2438    assert(hashtable != NULL);
2439    assert(hashtable->shift < 32);
2440 
2441    /* use integer arithmetic to approximately check if load factor is above 90% */
2442    if( ((((uint64_t)hashtable->nelements)<<10)>>(32-hashtable->shift) > 921) )
2443    {
2444       void** slots;
2445       uint32_t* hashes;
2446       uint32_t nslots;
2447       uint32_t newnslots;
2448       uint32_t i;
2449 
2450       /* calculate new size (always power of two) */
2451       nslots = hashtable->mask + 1;
2452       newnslots = 2*nslots;
2453       hashtable->mask = newnslots-1;
2454       --hashtable->shift;
2455 
2456       /* reallocate array */
2457       SCIP_ALLOC( BMSallocBlockMemoryArray(hashtable->blkmem, &slots, newnslots) );
2458       SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashtable->blkmem, &hashes, newnslots) );
2459 
2460       SCIPswapPointers((void**) &slots, (void**) &hashtable->slots);
2461       SCIPswapPointers((void**) &hashes, (void**) &hashtable->hashes);
2462       hashtable->nelements = 0;
2463 
2464       /* reinsert all elements */
2465       for( i = 0; i < nslots; ++i )
2466       {
2467          /* using SCIP_CALL_ABORT since there are no allocations or duplicates
2468           * and thus no bad return codes when inserting the elements
2469           */
2470          if( hashes[i] != 0 )
2471          {
2472             SCIP_CALL_ABORT( hashtableInsert(hashtable, slots[i], hashtable->hashgetkey(hashtable->userptr, slots[i]), hashes[i], FALSE) );
2473          }
2474       }
2475       BMSfreeBlockMemoryArray(hashtable->blkmem, &hashes, nslots);
2476       BMSfreeBlockMemoryArray(hashtable->blkmem, &slots, nslots);
2477    }
2478 
2479    return SCIP_OKAY;
2480 }
2481 
2482 
2483 /** inserts element in hash table
2484  *
2485  *  @note multiple inserts of same element overrides previous one
2486  */
SCIPhashtableInsert(SCIP_HASHTABLE * hashtable,void * element)2487 SCIP_RETCODE SCIPhashtableInsert(
2488    SCIP_HASHTABLE*       hashtable,          /**< hash table */
2489    void*                 element             /**< element to insert into the table */
2490    )
2491 {
2492    void* key;
2493    uint64_t keyval;
2494    uint32_t hashval;
2495 
2496    assert(hashtable != NULL);
2497    assert(hashtable->slots != NULL);
2498    assert(hashtable->hashes != NULL);
2499    assert(hashtable->mask > 0);
2500    assert(hashtable->hashgetkey != NULL);
2501    assert(hashtable->hashkeyeq != NULL);
2502    assert(hashtable->hashkeyval != NULL);
2503    assert(element != NULL);
2504 
2505    SCIP_CALL( hashtableCheckLoad(hashtable) );
2506 
2507    /* get the hash key and its hash value */
2508    key = hashtable->hashgetkey(hashtable->userptr, element);
2509    keyval = hashtable->hashkeyval(hashtable->userptr, key);
2510    hashval = hashvalue(keyval);
2511 
2512    return hashtableInsert(hashtable, element, key, hashval, TRUE);
2513 }
2514 
2515 /** inserts element in hash table
2516  *
2517  *  @note multiple insertion of same element is checked and results in an error
2518  */
SCIPhashtableSafeInsert(SCIP_HASHTABLE * hashtable,void * element)2519 SCIP_RETCODE SCIPhashtableSafeInsert(
2520    SCIP_HASHTABLE*       hashtable,          /**< hash table */
2521    void*                 element             /**< element to insert into the table */
2522    )
2523 {
2524    void* key;
2525    uint64_t keyval;
2526    uint32_t hashval;
2527 
2528    assert(hashtable != NULL);
2529    assert(hashtable->slots != NULL);
2530    assert(hashtable->hashes != NULL);
2531    assert(hashtable->mask > 0);
2532    assert(hashtable->hashgetkey != NULL);
2533    assert(hashtable->hashkeyeq != NULL);
2534    assert(hashtable->hashkeyval != NULL);
2535    assert(element != NULL);
2536 
2537    SCIP_CALL( hashtableCheckLoad(hashtable) );
2538 
2539    /* get the hash key and its hash value */
2540    key = hashtable->hashgetkey(hashtable->userptr, element);
2541    keyval = hashtable->hashkeyval(hashtable->userptr, key);
2542    hashval = hashvalue(keyval);
2543 
2544    return hashtableInsert(hashtable, element, key, hashval, FALSE);
2545 }
2546 
2547 /** retrieve element with key from hash table, returns NULL if not existing */
SCIPhashtableRetrieve(SCIP_HASHTABLE * hashtable,void * key)2548 void* SCIPhashtableRetrieve(
2549    SCIP_HASHTABLE*       hashtable,          /**< hash table */
2550    void*                 key                 /**< key to retrieve */
2551    )
2552 {
2553    uint64_t keyval;
2554    uint32_t hashval;
2555    uint32_t pos;
2556    uint32_t elemdistance;
2557 
2558    assert(hashtable != NULL);
2559    assert(hashtable->slots != NULL);
2560    assert(hashtable->hashes != NULL);
2561    assert(hashtable->mask > 0);
2562    assert(hashtable->hashgetkey != NULL);
2563    assert(hashtable->hashkeyeq != NULL);
2564    assert(hashtable->hashkeyval != NULL);
2565    assert(key != NULL);
2566 
2567    /* get the hash value of the key */
2568    keyval = hashtable->hashkeyval(hashtable->userptr, key);
2569    hashval = hashvalue(keyval);
2570 
2571    pos = hashval>>(hashtable->shift);
2572    elemdistance = 0;
2573 
2574    while( TRUE ) /*lint !e716*/
2575    {
2576       uint32_t distance;
2577 
2578       /* slots is empty so element cannot be contained */
2579       if( hashtable->hashes[pos] == 0 )
2580          return NULL;
2581 
2582       distance = ELEM_DISTANCE(pos);
2583 
2584       /* element cannot be contained since otherwise we would have swapped it with this one during insert */
2585       if( elemdistance > distance )
2586          return NULL;
2587 
2588       /* found element */
2589       if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2590              hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2591          return hashtable->slots[pos];
2592 
2593       pos = (pos + 1) & hashtable->mask;
2594       ++elemdistance;
2595    }
2596 }
2597 
2598 /** returns whether the given element exists in the table */
SCIPhashtableExists(SCIP_HASHTABLE * hashtable,void * element)2599 SCIP_Bool SCIPhashtableExists(
2600    SCIP_HASHTABLE*       hashtable,          /**< hash table */
2601    void*                 element             /**< element to search in the table */
2602    )
2603 {
2604    assert(hashtable != NULL);
2605    assert(hashtable->slots != NULL);
2606    assert(hashtable->hashes != NULL);
2607    assert(hashtable->mask > 0);
2608    assert(hashtable->hashgetkey != NULL);
2609    assert(hashtable->hashkeyeq != NULL);
2610    assert(hashtable->hashkeyval != NULL);
2611    assert(element != NULL);
2612 
2613    return (SCIPhashtableRetrieve(hashtable, hashtable->hashgetkey(hashtable->userptr, element)) != NULL);
2614 }
2615 
2616 /** removes element from the hash table, if it exists */
SCIPhashtableRemove(SCIP_HASHTABLE * hashtable,void * element)2617 SCIP_RETCODE SCIPhashtableRemove(
2618    SCIP_HASHTABLE*       hashtable,          /**< hash table */
2619    void*                 element             /**< element to remove from the table */
2620    )
2621 {
2622    void* key;
2623    uint64_t keyval;
2624    uint32_t hashval;
2625    uint32_t elemdistance;
2626    uint32_t distance;
2627    uint32_t pos;
2628 
2629    assert(hashtable != NULL);
2630    assert(hashtable->slots != NULL);
2631    assert(hashtable->hashes != NULL);
2632    assert(hashtable->mask > 0);
2633    assert(hashtable->hashgetkey != NULL);
2634    assert(hashtable->hashkeyeq != NULL);
2635    assert(hashtable->hashkeyval != NULL);
2636    assert(element != NULL);
2637 
2638    /* get the hash key and its hash value */
2639    key = hashtable->hashgetkey(hashtable->userptr, element);
2640    keyval = hashtable->hashkeyval(hashtable->userptr, key);
2641    hashval = hashvalue(keyval);
2642 
2643    elemdistance = 0;
2644    pos = hashval>>(hashtable->shift);
2645    while( TRUE ) /*lint !e716*/
2646    {
2647       /* slots empty so element not contained */
2648       if( hashtable->hashes[pos] == 0 )
2649          return SCIP_OKAY;
2650 
2651       distance = ELEM_DISTANCE(pos);
2652 
2653       /* element can not be contained since otherwise we would have swapped it with this one */
2654       if( elemdistance > distance )
2655          return SCIP_OKAY;
2656 
2657       if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2658              hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2659       {
2660          /* element exists at pos so break out of loop */
2661          break;
2662       }
2663 
2664       pos = (pos + 1) & hashtable->mask;
2665       ++elemdistance;
2666    }
2667 
2668    /* remove element */
2669    hashtable->hashes[pos] = 0;
2670    --hashtable->nelements;
2671    while( TRUE ) /*lint !e716*/
2672    {
2673       uint32_t nextpos = (pos + 1) & hashtable->mask;
2674 
2675       /* nothing to do since there is no chain that needs to be moved */
2676       if( hashtable->hashes[nextpos] == 0 )
2677          break;
2678 
2679       /* check if the element is the start of a new chain and return if that is the case */
2680       if( (hashtable->hashes[nextpos]>>(hashtable->shift)) == nextpos )
2681          break;
2682 
2683       /* element should be moved to the left and next element needs to be checked */
2684       hashtable->slots[pos] = hashtable->slots[nextpos];
2685       hashtable->hashes[pos] = hashtable->hashes[nextpos];
2686       hashtable->hashes[nextpos] = 0;
2687 
2688       pos = nextpos;
2689    }
2690 
2691    return SCIP_OKAY;
2692 }
2693 
2694 /** removes all elements of the hash table */
SCIPhashtableRemoveAll(SCIP_HASHTABLE * hashtable)2695 void SCIPhashtableRemoveAll(
2696    SCIP_HASHTABLE*       hashtable           /**< hash table */
2697    )
2698 {
2699    assert(hashtable != NULL);
2700 
2701    BMSclearMemoryArray(hashtable->hashes, hashtable->mask + 1);
2702 
2703    hashtable->nelements = 0;
2704 }
2705 
2706 /** returns number of hash table elements */
SCIPhashtableGetNElements(SCIP_HASHTABLE * hashtable)2707 SCIP_Longint SCIPhashtableGetNElements(
2708    SCIP_HASHTABLE*       hashtable           /**< hash table */
2709    )
2710 {
2711    assert(hashtable != NULL);
2712 
2713    return hashtable->nelements;
2714 }
2715 
2716 /** gives the number of entries in the internal arrays of a hash table */
SCIPhashtableGetNEntries(SCIP_HASHTABLE * hashtable)2717 int SCIPhashtableGetNEntries(
2718    SCIP_HASHTABLE*       hashtable           /**< hash table */
2719    )
2720 {
2721    return (int) hashtable->mask + 1;
2722 }
2723 
2724 /** gives the element at the given index or NULL if entry at that index has no element */
SCIPhashtableGetEntry(SCIP_HASHTABLE * hashtable,int entryidx)2725 void* SCIPhashtableGetEntry(
2726    SCIP_HASHTABLE*       hashtable,          /**< hash table */
2727    int                   entryidx            /**< index of hash table entry */
2728    )
2729 {
2730    return hashtable->hashes[entryidx] == 0 ? NULL : hashtable->slots[entryidx];
2731 }
2732 
2733 /** returns the load of the given hash table in percentage */
SCIPhashtableGetLoad(SCIP_HASHTABLE * hashtable)2734 SCIP_Real SCIPhashtableGetLoad(
2735    SCIP_HASHTABLE*       hashtable           /**< hash table */
2736    )
2737 {
2738    assert(hashtable != NULL);
2739 
2740    return ((SCIP_Real)(hashtable->nelements) / (hashtable->mask + 1) * 100.0);
2741 }
2742 
2743 /** prints statistics about hash table usage */
SCIPhashtablePrintStatistics(SCIP_HASHTABLE * hashtable,SCIP_MESSAGEHDLR * messagehdlr)2744 void SCIPhashtablePrintStatistics(
2745    SCIP_HASHTABLE*       hashtable,          /**< hash table */
2746    SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
2747    )
2748 {
2749    uint32_t maxprobelen = 0;
2750    uint64_t probelensum = 0;
2751    uint32_t nslots;
2752    uint32_t i;
2753 
2754    assert(hashtable != NULL);
2755 
2756    nslots = hashtable->mask + 1;
2757 
2758    /* compute the maximum and average probe length */
2759    for( i = 0; i < nslots; ++i )
2760    {
2761       if( hashtable->hashes[i] != 0 )
2762       {
2763          uint32_t probelen = ELEM_DISTANCE(i) + 1;
2764          probelensum += probelen;
2765          maxprobelen = MAX(probelen, maxprobelen);
2766       }
2767    }
2768 
2769    /* print general hash table statistics */
2770    SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
2771                         (unsigned int)hashtable->nelements, (unsigned int)hashtable->nelements,
2772                         (unsigned int)nslots, 100.0*(SCIP_Real)hashtable->nelements/(SCIP_Real)(nslots));
2773 
2774    /* if not empty print average and maximum probe length */
2775    if( hashtable->nelements > 0 )
2776       SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
2777          (SCIP_Real)(probelensum)/(SCIP_Real)hashtable->nelements, (unsigned int)maxprobelen);
2778    SCIPmessagePrintInfo(messagehdlr, "\n");
2779 }
2780 
2781 /** returns TRUE iff both keys (i.e. strings) are equal */
SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)2782 SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
2783 {  /*lint --e{715}*/
2784    const char* string1 = (const char*)key1;
2785    const char* string2 = (const char*)key2;
2786 
2787    return (strcmp(string1, string2) == 0);
2788 }
2789 
2790 /** returns the hash value of the key (i.e. string) */
SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)2791 SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
2792 {  /*lint --e{715}*/
2793    const char* str;
2794    uint64_t hash;
2795 
2796    str = (const char*)key;
2797    hash = 37;
2798    while( *str != '\0' )
2799    {
2800       hash *= 11;
2801       hash += (unsigned int)(*str); /*lint !e571*/
2802       str++;
2803    }
2804 
2805    return hash;
2806 }
2807 
2808 
2809 /** gets the element as the key */
SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)2810 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
2811 {  /*lint --e{715}*/
2812    /* the key is the element itself */
2813    return elem;
2814 }
2815 
2816 /** returns TRUE iff both keys(pointer) are equal */
SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqPtr)2817 SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqPtr)
2818 {  /*lint --e{715}*/
2819    return (key1 == key2);
2820 }
2821 
2822 /** returns the hash value of the key */
SCIP_DECL_HASHKEYVAL(SCIPhashKeyValPtr)2823 SCIP_DECL_HASHKEYVAL(SCIPhashKeyValPtr)
2824 {  /*lint --e{715}*/
2825    /* the key is used as the keyvalue too */
2826    return (uint64_t) (uintptr_t) key;
2827 }
2828 
2829 
2830 
2831 /*
2832  * Hash Map
2833  */
2834 
2835 /* redefine ELEM_DISTANCE macro for hashmap */
2836 #undef ELEM_DISTANCE
2837 /* computes the distance from it's desired position for the element stored at pos */
2838 #define ELEM_DISTANCE(pos) (((pos) + hashmap->mask + 1 - (hashmap->hashes[(pos)]>>(hashmap->shift))) & hashmap->mask)
2839 
2840 /** inserts element in hash table */
2841 static
hashmapInsert(SCIP_HASHMAP * hashmap,void * origin,SCIP_HASHMAPIMAGE image,uint32_t hashval,SCIP_Bool override)2842 SCIP_RETCODE hashmapInsert(
2843    SCIP_HASHMAP*         hashmap,            /**< hash map */
2844    void*                 origin,             /**< element to insert into the table */
2845    SCIP_HASHMAPIMAGE     image,              /**< key of element */
2846    uint32_t              hashval,            /**< hash value of element */
2847    SCIP_Bool             override            /**< should element be overridden or error be returned if already existing */
2848    )
2849 {
2850    uint32_t elemdistance;
2851    uint32_t pos;
2852 
2853    assert(hashmap != NULL);
2854    assert(hashmap->slots != NULL);
2855    assert(hashmap->hashes != NULL);
2856    assert(hashmap->mask > 0);
2857    assert(hashval != 0);
2858 
2859    pos = hashval>>(hashmap->shift);
2860    elemdistance = 0;
2861    while( TRUE ) /*lint !e716*/
2862    {
2863       uint32_t distance;
2864 
2865       /* if position is empty or key equal insert element */
2866       if( hashmap->hashes[pos] == 0 )
2867       {
2868          hashmap->slots[pos].origin = origin;
2869          hashmap->slots[pos].image = image;
2870          hashmap->hashes[pos] = hashval;
2871          ++hashmap->nelements;
2872          return SCIP_OKAY;
2873       }
2874 
2875       if( hashval == hashmap->hashes[pos] && origin == hashmap->slots[pos].origin )
2876       {
2877          if( override )
2878          {
2879             hashmap->slots[pos].origin = origin;
2880             hashmap->slots[pos].image = image;
2881             hashmap->hashes[pos] = hashval;
2882             return SCIP_OKAY;
2883          }
2884          else
2885          {
2886             return SCIP_KEYALREADYEXISTING;
2887          }
2888       }
2889 
2890       /* otherwise check if the current element at this position is closer to its hashvalue */
2891       distance = ELEM_DISTANCE(pos);
2892       if( distance < elemdistance )
2893       {
2894          SCIP_HASHMAPIMAGE tmp;
2895          uint32_t tmphash;
2896 
2897          /* if this is the case we insert the new element here and find a new position for the old one */
2898          elemdistance = distance;
2899          tmphash = hashval;
2900          hashval = hashmap->hashes[pos];
2901          hashmap->hashes[pos] = tmphash;
2902          SCIPswapPointers(&hashmap->slots[pos].origin, &origin);
2903          tmp = image;
2904          image = hashmap->slots[pos].image;
2905          hashmap->slots[pos].image = tmp;
2906       }
2907 
2908       /* continue until we have found an empty position */
2909       pos = (pos + 1) & hashmap->mask;
2910       ++elemdistance;
2911    }
2912 }
2913 
2914 /** lookup origin in the hashmap. If element is found returns true and the position of the element,
2915  *  otherwise returns FALSE.
2916  */
2917 static
hashmapLookup(SCIP_HASHMAP * hashmap,void * origin,uint32_t * pos)2918 SCIP_Bool hashmapLookup(
2919    SCIP_HASHMAP*         hashmap,            /**< hash table */
2920    void*                 origin,             /**< origin to lookup */
2921    uint32_t*             pos                 /**< pointer to store position of element, if exists */
2922    )
2923 {
2924    uint32_t hashval;
2925    uint32_t elemdistance;
2926 
2927    assert(hashmap != NULL);
2928    assert(hashmap->slots != NULL);
2929    assert(hashmap->hashes != NULL);
2930    assert(hashmap->mask > 0);
2931 
2932    /* get the hash value */
2933    hashval = hashvalue((size_t)origin);
2934    assert(hashval != 0);
2935 
2936    *pos = hashval>>(hashmap->shift);
2937    elemdistance = 0;
2938 
2939    while( TRUE ) /*lint !e716*/
2940    {
2941       uint32_t distance;
2942 
2943       /* slots is empty so element cannot be contained */
2944       if( hashmap->hashes[*pos] == 0 )
2945          return FALSE;
2946 
2947       distance = ELEM_DISTANCE(*pos);
2948       /* element can not be contained since otherwise we would have swapped it with this one during insert */
2949       if( elemdistance > distance )
2950          return FALSE;
2951 
2952       /* found element */
2953       if( hashmap->hashes[*pos] == hashval && hashmap->slots[*pos].origin == origin )
2954          return TRUE;
2955 
2956       *pos = (*pos + 1) & hashmap->mask;
2957       ++elemdistance;
2958    }
2959 }
2960 
2961 /** check if the load factor of the hashmap is too high and rebuild if necessary */
2962 static
hashmapCheckLoad(SCIP_HASHMAP * hashmap)2963 SCIP_RETCODE hashmapCheckLoad(
2964    SCIP_HASHMAP*         hashmap             /**< hash table */
2965    )
2966 {
2967    assert(hashmap != NULL);
2968    assert(hashmap->shift < 32);
2969 
2970    /* use integer arithmetic to approximately check if load factor is above 90% */
2971    if( ((((uint64_t)hashmap->nelements)<<10)>>(32-hashmap->shift) > 921) )
2972    {
2973       SCIP_HASHMAPENTRY* slots;
2974       uint32_t* hashes;
2975       uint32_t nslots;
2976       uint32_t newnslots;
2977       uint32_t i;
2978 
2979       /* calculate new size (always power of two) */
2980       nslots = hashmap->mask + 1;
2981       --hashmap->shift;
2982       newnslots = 2*nslots;
2983       hashmap->mask = newnslots-1;
2984 
2985       /* reallocate array */
2986       SCIP_ALLOC( BMSallocBlockMemoryArray(hashmap->blkmem, &slots, newnslots) );
2987       SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashmap->blkmem, &hashes, newnslots) );
2988 
2989       SCIPswapPointers((void**) &slots, (void**) &hashmap->slots);
2990       SCIPswapPointers((void**) &hashes, (void**) &hashmap->hashes);
2991       hashmap->nelements = 0;
2992 
2993       /* reinsert all elements */
2994       for( i = 0; i < nslots; ++i )
2995       {
2996          /* using SCIP_CALL_ABORT since there are no allocations or duplicates
2997           * and thus no bad return codes when inserting the elements
2998           */
2999          if( hashes[i] != 0 )
3000          {
3001             SCIP_CALL_ABORT( hashmapInsert(hashmap, slots[i].origin, slots[i].image, hashes[i], FALSE) );
3002          }
3003       }
3004 
3005       /* free old arrays */
3006       BMSfreeBlockMemoryArray(hashmap->blkmem, &hashes, nslots);
3007       BMSfreeBlockMemoryArray(hashmap->blkmem, &slots, nslots);
3008    }
3009 
3010    return SCIP_OKAY;
3011 }
3012 
3013 /** creates a hash map mapping pointers to pointers */
SCIPhashmapCreate(SCIP_HASHMAP ** hashmap,BMS_BLKMEM * blkmem,int mapsize)3014 SCIP_RETCODE SCIPhashmapCreate(
3015    SCIP_HASHMAP**        hashmap,            /**< pointer to store the created hash map */
3016    BMS_BLKMEM*           blkmem,             /**< block memory used to store hash map entries */
3017    int                   mapsize             /**< size of the hash map */
3018    )
3019 {
3020    uint32_t nslots;
3021 
3022    assert(hashmap != NULL);
3023    assert(mapsize >= 0);
3024    assert(blkmem != NULL);
3025 
3026    SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashmap) );
3027 
3028    /* dont create too small hashtables, i.e. at least size 32, and increase
3029     * the given size by divinding it by 0.9, since then no rebuilding will
3030     * be necessary if the given number of elements are inserted. Finally round
3031     * to the next power of two.
3032     */
3033    (*hashmap)->shift = 32;
3034    (*hashmap)->shift -= (unsigned int)ceil(log(MAX(32, mapsize / 0.9)) / log(2.0));
3035    nslots = 1u << (32 - (*hashmap)->shift);
3036    (*hashmap)->mask = nslots - 1;
3037    (*hashmap)->blkmem = blkmem;
3038    (*hashmap)->nelements = 0;
3039    (*hashmap)->hashmaptype = SCIP_HASHMAPTYPE_UNKNOWN;
3040 
3041    SCIP_ALLOC( BMSallocBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots) );
3042    SCIP_ALLOC( BMSallocClearBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots) );
3043 
3044    return SCIP_OKAY;
3045 }
3046 
3047 /** frees the hash map */
SCIPhashmapFree(SCIP_HASHMAP ** hashmap)3048 void SCIPhashmapFree(
3049    SCIP_HASHMAP**        hashmap             /**< pointer to the hash map */
3050    )
3051 {
3052    uint32_t nslots;
3053 
3054    assert(hashmap != NULL);
3055    assert(*hashmap != NULL);
3056 
3057    nslots = (*hashmap)->mask + 1;
3058 #ifdef SCIP_DEBUG
3059    {
3060       uint32_t maxprobelen = 0;
3061       uint64_t probelensum = 0;
3062       uint32_t i;
3063 
3064       assert(hashmap != NULL);
3065 
3066       for( i = 0; i < nslots; ++i )
3067       {
3068          if( (*hashmap)->hashes[i] != 0 )
3069          {
3070             uint32_t probelen = ((i + (*hashmap)->mask + 1 - ((*hashmap)->hashes[i]>>((*hashmap)->shift))) & (*hashmap)->mask) + 1;
3071             probelensum += probelen;
3072             maxprobelen = MAX(probelen, maxprobelen);
3073          }
3074       }
3075 
3076       SCIPdebugMessage("%u hash map entries, used %u/%u slots (%.1f%%)",
3077                        (unsigned int)(*hashmap)->nelements, (unsigned int)(*hashmap)->nelements, (unsigned int)nslots,
3078                        100.0*(SCIP_Real)(*hashmap)->nelements/(SCIP_Real)(nslots));
3079       if( (*hashmap)->nelements > 0 )
3080          SCIPdebugPrintf(", avg. probe length is %.1f, max. probe length is %u",
3081                           (SCIP_Real)(probelensum)/(SCIP_Real)(*hashmap)->nelements, (unsigned int)maxprobelen);
3082       SCIPdebugPrintf("\n");
3083    }
3084 #endif
3085 
3086    /* free main hash map data structure */
3087    BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots);
3088    BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots);
3089    BMSfreeBlockMemory((*hashmap)->blkmem, hashmap);
3090 }
3091 
3092 /** inserts new origin->image pair in hash map
3093  *
3094  *  @note multiple insertion of same element is checked and results in an error
3095  */
SCIPhashmapInsert(SCIP_HASHMAP * hashmap,void * origin,void * image)3096 SCIP_RETCODE SCIPhashmapInsert(
3097    SCIP_HASHMAP*         hashmap,            /**< hash map */
3098    void*                 origin,             /**< origin to set image for */
3099    void*                 image               /**< new image for origin */
3100    )
3101 {
3102    uint32_t hashval;
3103    SCIP_HASHMAPIMAGE img;
3104 
3105    assert(hashmap != NULL);
3106    assert(hashmap->slots != NULL);
3107    assert(hashmap->hashes != NULL);
3108    assert(hashmap->mask > 0);
3109    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3110 
3111 #ifndef NDEBUG
3112    if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3113       hashmap->hashmaptype = SCIP_HASHMAPTYPE_POINTER;
3114 #endif
3115 
3116    SCIP_CALL( hashmapCheckLoad(hashmap) );
3117 
3118    /* get the hash value */
3119    hashval = hashvalue((size_t)origin);
3120 
3121    /* append origin->image pair to hash map */
3122    img.ptr = image;
3123    SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3124 
3125    return SCIP_OKAY;
3126 }
3127 
3128 /** inserts new origin->image pair in hash map
3129  *
3130  *  @note multiple insertion of same element is checked and results in an error
3131  */
SCIPhashmapInsertInt(SCIP_HASHMAP * hashmap,void * origin,int image)3132 SCIP_RETCODE SCIPhashmapInsertInt(
3133    SCIP_HASHMAP*         hashmap,            /**< hash map */
3134    void*                 origin,             /**< origin to set image for */
3135    int                   image               /**< new image for origin */
3136    )
3137 {
3138    uint32_t hashval;
3139    SCIP_HASHMAPIMAGE img;
3140 
3141    assert(hashmap != NULL);
3142    assert(hashmap->slots != NULL);
3143    assert(hashmap->hashes != NULL);
3144    assert(hashmap->mask > 0);
3145    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3146 
3147 #ifndef NDEBUG
3148    if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3149       hashmap->hashmaptype = SCIP_HASHMAPTYPE_INT;
3150 #endif
3151 
3152    SCIP_CALL( hashmapCheckLoad(hashmap) );
3153 
3154    /* get the hash value */
3155    hashval = hashvalue((size_t)origin);
3156 
3157    /* append origin->image pair to hash map */
3158    img.integer = image;
3159    SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3160 
3161    return SCIP_OKAY;
3162 }
3163 
3164 /** inserts new origin->image pair in hash map
3165  *
3166  *  @note multiple insertion of same element is checked and results in an error
3167  */
SCIPhashmapInsertReal(SCIP_HASHMAP * hashmap,void * origin,SCIP_Real image)3168 SCIP_RETCODE SCIPhashmapInsertReal(
3169    SCIP_HASHMAP*         hashmap,            /**< hash map */
3170    void*                 origin,             /**< origin to set image for */
3171    SCIP_Real             image               /**< new image for origin */
3172    )
3173 {
3174    uint32_t hashval;
3175    SCIP_HASHMAPIMAGE img;
3176 
3177    assert(hashmap != NULL);
3178    assert(hashmap->slots != NULL);
3179    assert(hashmap->hashes != NULL);
3180    assert(hashmap->mask > 0);
3181    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3182 
3183 #ifndef NDEBUG
3184    if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3185       hashmap->hashmaptype = SCIP_HASHMAPTYPE_REAL;
3186 #endif
3187 
3188    SCIP_CALL( hashmapCheckLoad(hashmap) );
3189 
3190    /* get the hash value */
3191    hashval = hashvalue((size_t)origin);
3192 
3193    /* append origin->image pair to hash map */
3194    img.real = image;
3195    SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3196 
3197    return SCIP_OKAY;
3198 }
3199 
3200 /** retrieves image of given origin from the hash map, or NULL if no image exists */
SCIPhashmapGetImage(SCIP_HASHMAP * hashmap,void * origin)3201 void* SCIPhashmapGetImage(
3202    SCIP_HASHMAP*         hashmap,            /**< hash map */
3203    void*                 origin              /**< origin to retrieve image for */
3204    )
3205 {
3206    uint32_t pos;
3207 
3208    assert(hashmap != NULL);
3209    assert(hashmap->slots != NULL);
3210    assert(hashmap->hashes != NULL);
3211    assert(hashmap->mask > 0);
3212    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3213 
3214    if( hashmapLookup(hashmap, origin, &pos) )
3215       return hashmap->slots[pos].image.ptr;
3216 
3217    return NULL;
3218 }
3219 
3220 /** retrieves image of given origin from the hash map, or INT_MAX if no image exists */
SCIPhashmapGetImageInt(SCIP_HASHMAP * hashmap,void * origin)3221 int SCIPhashmapGetImageInt(
3222    SCIP_HASHMAP*         hashmap,            /**< hash map */
3223    void*                 origin              /**< origin to retrieve image for */
3224    )
3225 {
3226    uint32_t pos;
3227 
3228    assert(hashmap != NULL);
3229    assert(hashmap->slots != NULL);
3230    assert(hashmap->hashes != NULL);
3231    assert(hashmap->mask > 0);
3232    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3233 
3234    if( hashmapLookup(hashmap, origin, &pos) )
3235       return hashmap->slots[pos].image.integer;
3236 
3237    return INT_MAX;
3238 }
3239 
3240 /** retrieves image of given origin from the hash map, or SCIP_INVALID if no image exists */
SCIPhashmapGetImageReal(SCIP_HASHMAP * hashmap,void * origin)3241 SCIP_Real SCIPhashmapGetImageReal(
3242    SCIP_HASHMAP*         hashmap,            /**< hash map */
3243    void*                 origin              /**< origin to retrieve image for */
3244    )
3245 {
3246    uint32_t pos;
3247 
3248    assert(hashmap != NULL);
3249    assert(hashmap->slots != NULL);
3250    assert(hashmap->hashes != NULL);
3251    assert(hashmap->mask > 0);
3252    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3253 
3254    if( hashmapLookup(hashmap, origin, &pos) )
3255       return hashmap->slots[pos].image.real;
3256 
3257    return SCIP_INVALID;
3258 }
3259 
3260 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3261  *  or by appending a new origin->image pair
3262  */
SCIPhashmapSetImage(SCIP_HASHMAP * hashmap,void * origin,void * image)3263 SCIP_RETCODE SCIPhashmapSetImage(
3264    SCIP_HASHMAP*         hashmap,            /**< hash map */
3265    void*                 origin,             /**< origin to set image for */
3266    void*                 image               /**< new image for origin */
3267    )
3268 {
3269    uint32_t hashval;
3270    SCIP_HASHMAPIMAGE img;
3271 
3272    assert(hashmap != NULL);
3273    assert(hashmap->slots != NULL);
3274    assert(hashmap->mask > 0);
3275    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3276 
3277 #ifndef NDEBUG
3278    if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3279       hashmap->hashmaptype = SCIP_HASHMAPTYPE_POINTER;
3280 #endif
3281 
3282    SCIP_CALL( hashmapCheckLoad(hashmap) );
3283 
3284    /* get the hash value */
3285    hashval = hashvalue((size_t)origin);
3286 
3287    /* append origin->image pair to hash map */
3288    img.ptr = image;
3289    SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3290 
3291    return SCIP_OKAY;
3292 }
3293 
3294 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3295  *  or by appending a new origin->image pair
3296  */
SCIPhashmapSetImageInt(SCIP_HASHMAP * hashmap,void * origin,int image)3297 SCIP_RETCODE SCIPhashmapSetImageInt(
3298    SCIP_HASHMAP*         hashmap,            /**< hash map */
3299    void*                 origin,             /**< origin to set image for */
3300    int                   image               /**< new image for origin */
3301    )
3302 {
3303    uint32_t hashval;
3304    SCIP_HASHMAPIMAGE img;
3305 
3306    assert(hashmap != NULL);
3307    assert(hashmap->slots != NULL);
3308    assert(hashmap->mask > 0);
3309    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3310 
3311 #ifndef NDEBUG
3312    if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3313       hashmap->hashmaptype = SCIP_HASHMAPTYPE_INT;
3314 #endif
3315 
3316    SCIP_CALL( hashmapCheckLoad(hashmap) );
3317 
3318    /* get the hash value */
3319    hashval = hashvalue((size_t)origin);
3320 
3321    /* append origin->image pair to hash map */
3322    img.integer = image;
3323    SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3324 
3325    return SCIP_OKAY;
3326 }
3327 
3328 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3329  *  or by appending a new origin->image pair
3330  */
SCIPhashmapSetImageReal(SCIP_HASHMAP * hashmap,void * origin,SCIP_Real image)3331 SCIP_RETCODE SCIPhashmapSetImageReal(
3332    SCIP_HASHMAP*         hashmap,            /**< hash map */
3333    void*                 origin,             /**< origin to set image for */
3334    SCIP_Real             image               /**< new image for origin */
3335    )
3336 {
3337    uint32_t hashval;
3338    SCIP_HASHMAPIMAGE img;
3339 
3340    assert(hashmap != NULL);
3341    assert(hashmap->slots != NULL);
3342    assert(hashmap->mask > 0);
3343    assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3344 
3345 #ifndef NDEBUG
3346    if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3347       hashmap->hashmaptype = SCIP_HASHMAPTYPE_REAL;
3348 #endif
3349 
3350    SCIP_CALL( hashmapCheckLoad(hashmap) );
3351 
3352    /* get the hash value */
3353    hashval = hashvalue((size_t)origin);
3354 
3355    /* append origin->image pair to hash map */
3356    img.real = image;
3357    SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3358 
3359    return SCIP_OKAY;
3360 }
3361 
3362 /** checks whether an image to the given origin exists in the hash map */
SCIPhashmapExists(SCIP_HASHMAP * hashmap,void * origin)3363 SCIP_Bool SCIPhashmapExists(
3364    SCIP_HASHMAP*         hashmap,            /**< hash map */
3365    void*                 origin              /**< origin to search for */
3366    )
3367 {
3368    uint32_t pos;
3369 
3370    assert(hashmap != NULL);
3371    assert(hashmap->slots != NULL);
3372    assert(hashmap->hashes != NULL);
3373    assert(hashmap->mask > 0);
3374 
3375    return hashmapLookup(hashmap, origin, &pos);
3376 }
3377 
3378 /** removes origin->image pair from the hash map, if it exists */
SCIPhashmapRemove(SCIP_HASHMAP * hashmap,void * origin)3379 SCIP_RETCODE SCIPhashmapRemove(
3380    SCIP_HASHMAP*         hashmap,            /**< hash map */
3381    void*                 origin              /**< origin to remove from the list */
3382    )
3383 {
3384    uint32_t pos;
3385 
3386    assert(hashmap != NULL);
3387    assert(hashmap->slots != NULL);
3388    assert(hashmap->mask > 0);
3389 
3390    assert(origin != NULL);
3391 
3392    if( hashmapLookup(hashmap, origin, &pos) )
3393    {
3394       /* remove element */
3395       hashmap->hashes[pos] = 0;
3396       --hashmap->nelements;
3397 
3398       /* move other elements if necessary */
3399       while( TRUE ) /*lint !e716*/
3400       {
3401          uint32_t nextpos = (pos + 1) & hashmap->mask;
3402 
3403          /* nothing to do since there is no chain that needs to be moved */
3404          if( hashmap->hashes[nextpos] == 0 )
3405             return SCIP_OKAY;
3406 
3407          /* check if the element is the start of a new chain and return if that is the case */
3408          if( (hashmap->hashes[nextpos]>>(hashmap->shift)) == nextpos )
3409             return SCIP_OKAY;
3410 
3411          /* element should be moved to the left and next element needs to be checked */
3412          hashmap->slots[pos].origin = hashmap->slots[nextpos].origin;
3413          hashmap->slots[pos].image = hashmap->slots[nextpos].image;
3414          hashmap->hashes[pos] = hashmap->hashes[nextpos];
3415          hashmap->hashes[nextpos] = 0;
3416 
3417          pos = nextpos;
3418       }
3419    }
3420 
3421    return SCIP_OKAY;
3422 }
3423 
3424 /** prints statistics about hash map usage */
SCIPhashmapPrintStatistics(SCIP_HASHMAP * hashmap,SCIP_MESSAGEHDLR * messagehdlr)3425 void SCIPhashmapPrintStatistics(
3426    SCIP_HASHMAP*         hashmap,            /**< hash map */
3427    SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
3428    )
3429 {
3430    uint32_t maxprobelen = 0;
3431    uint64_t probelensum = 0;
3432    uint32_t nslots;
3433    uint32_t i;
3434 
3435    assert(hashmap != NULL);
3436 
3437    nslots = hashmap->mask + 1;
3438 
3439    /* compute the maximum and average probe length */
3440    for( i = 0; i < nslots; ++i )
3441    {
3442       if( hashmap->hashes[i] != 0 )
3443       {
3444          uint32_t probelen = ELEM_DISTANCE(i) + 1;
3445          probelensum += probelen;
3446          maxprobelen = MAX(probelen, maxprobelen);
3447       }
3448    }
3449 
3450    /* print general hash map statistics */
3451    SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3452                         (unsigned int)hashmap->nelements, (unsigned int)hashmap->nelements,
3453                         (unsigned int)nslots, 100.0*(SCIP_Real)hashmap->nelements/(SCIP_Real)(nslots));
3454 
3455    /* if not empty print average and maximum probe length */
3456    if( hashmap->nelements > 0 )
3457       SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3458          (SCIP_Real)(probelensum)/(SCIP_Real)hashmap->nelements, (unsigned int)maxprobelen);
3459    SCIPmessagePrintInfo(messagehdlr, "\n");
3460 }
3461 
3462 /** indicates whether a hash map has no entries */
SCIPhashmapIsEmpty(SCIP_HASHMAP * hashmap)3463 SCIP_Bool SCIPhashmapIsEmpty(
3464    SCIP_HASHMAP*         hashmap             /**< hash map */
3465    )
3466 {
3467    assert(hashmap != NULL);
3468 
3469    return hashmap->nelements == 0;
3470 }
3471 
3472 /** gives the number of elements in a hash map */
SCIPhashmapGetNElements(SCIP_HASHMAP * hashmap)3473 int SCIPhashmapGetNElements(
3474    SCIP_HASHMAP*         hashmap             /**< hash map */
3475    )
3476 {
3477    return (int) hashmap->nelements;
3478 }
3479 
3480 /** gives the number of entries in the internal arrays of a hash map */
SCIPhashmapGetNEntries(SCIP_HASHMAP * hashmap)3481 int SCIPhashmapGetNEntries(
3482    SCIP_HASHMAP*         hashmap             /**< hash map */
3483    )
3484 {
3485    return (int) hashmap->mask + 1;
3486 }
3487 
3488 /** gives the hashmap entry at the given index or NULL if entry is empty */
SCIPhashmapGetEntry(SCIP_HASHMAP * hashmap,int entryidx)3489 SCIP_HASHMAPENTRY* SCIPhashmapGetEntry(
3490    SCIP_HASHMAP*         hashmap,            /**< hash map */
3491    int                   entryidx            /**< index of hash map entry */
3492    )
3493 {
3494    assert(hashmap != NULL);
3495 
3496    return hashmap->hashes[entryidx] == 0 ? NULL : &hashmap->slots[entryidx];
3497 }
3498 
3499 /** gives the origin of the hashmap entry */
SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY * entry)3500 void* SCIPhashmapEntryGetOrigin(
3501    SCIP_HASHMAPENTRY*    entry               /**< hash map entry */
3502    )
3503 {
3504    assert(entry != NULL);
3505 
3506    return entry->origin;
3507 }
3508 
3509 /** gives the image of the hashmap entry */
SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY * entry)3510 void* SCIPhashmapEntryGetImage(
3511    SCIP_HASHMAPENTRY*    entry               /**< hash map entry */
3512    )
3513 {
3514    assert(entry != NULL);
3515 
3516    return entry->image.ptr;
3517 }
3518 
3519 /** gives the image of the hashmap entry */
SCIPhashmapEntryGetImageInt(SCIP_HASHMAPENTRY * entry)3520 int SCIPhashmapEntryGetImageInt(
3521    SCIP_HASHMAPENTRY*    entry               /**< hash map entry */
3522    )
3523 {
3524    assert(entry != NULL);
3525 
3526    return entry->image.integer;
3527 }
3528 
3529 /** gives the image of the hashmap entry */
SCIPhashmapEntryGetImageReal(SCIP_HASHMAPENTRY * entry)3530 SCIP_Real SCIPhashmapEntryGetImageReal(
3531    SCIP_HASHMAPENTRY*    entry               /**< hash map entry */
3532    )
3533 {
3534    assert(entry != NULL);
3535 
3536    return entry->image.real;
3537 }
3538 
3539 /** sets pointer image of a hashmap entry */
SCIPhashmapEntrySetImage(SCIP_HASHMAPENTRY * entry,void * image)3540 void SCIPhashmapEntrySetImage(
3541    SCIP_HASHMAPENTRY*    entry,              /**< hash map entry */
3542    void*                 image               /**< new image */
3543    )
3544 {
3545    assert(entry != NULL);
3546 
3547    entry->image.ptr = image;
3548 }
3549 
3550 /** sets integer image of a hashmap entry */
SCIPhashmapEntrySetImageInt(SCIP_HASHMAPENTRY * entry,int image)3551 void SCIPhashmapEntrySetImageInt(
3552    SCIP_HASHMAPENTRY*    entry,              /**< hash map entry */
3553    int                   image               /**< new image */
3554    )
3555 {
3556    assert(entry != NULL);
3557 
3558    entry->image.integer = image;
3559 }
3560 
3561 /** sets real image of a hashmap entry */
SCIPhashmapEntrySetImageReal(SCIP_HASHMAPENTRY * entry,SCIP_Real image)3562 void SCIPhashmapEntrySetImageReal(
3563    SCIP_HASHMAPENTRY*    entry,              /**< hash map entry */
3564    SCIP_Real             image               /**< new image */
3565    )
3566 {
3567    assert(entry != NULL);
3568 
3569    entry->image.real = image;
3570 }
3571 
3572 /** removes all entries in a hash map. */
SCIPhashmapRemoveAll(SCIP_HASHMAP * hashmap)3573 SCIP_RETCODE SCIPhashmapRemoveAll(
3574    SCIP_HASHMAP*         hashmap             /**< hash map */
3575    )
3576 {
3577    assert(hashmap != NULL);
3578 
3579    BMSclearMemoryArray(hashmap->hashes, hashmap->mask + 1);
3580 
3581    hashmap->nelements = 0;
3582 
3583    return SCIP_OKAY;
3584 }
3585 
3586 
3587 /*
3588  * Hash Set
3589  */
3590 
3591 /* redefine ELEM_DISTANCE macro for hashset */
3592 #undef ELEM_DISTANCE
3593 /* computes the distance from it's desired position for the element stored at pos */
3594 #define ELEM_DISTANCE(pos) (((pos) + nslots - hashSetDesiredPos(hashset, hashset->slots[(pos)])) & mask)
3595 
3596 /* calculate desired position of element in hash set */
3597 static
hashSetDesiredPos(SCIP_HASHSET * hashset,void * element)3598 uint32_t hashSetDesiredPos(
3599    SCIP_HASHSET*         hashset,            /**< the hash set */
3600    void*                 element             /**< element to calculate position for */
3601    )
3602 {
3603    return (uint32_t)((UINT64_C(0x9e3779b97f4a7c15) * (uintptr_t)element)>>(hashset->shift));
3604 }
3605 
3606 static
hashsetInsert(SCIP_HASHSET * hashset,void * element)3607 void hashsetInsert(
3608    SCIP_HASHSET*         hashset,            /**< hash set */
3609    void*                 element             /**< element to insert */
3610    )
3611 {
3612    uint32_t elemdistance;
3613    uint32_t pos;
3614    uint32_t nslots;
3615    uint32_t mask;
3616 
3617    assert(hashset != NULL);
3618    assert(hashset->slots != NULL);
3619    assert(element != NULL);
3620 
3621    pos = hashSetDesiredPos(hashset, element);
3622    nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3623    mask = nslots - 1;
3624 
3625    elemdistance = 0;
3626    while( TRUE ) /*lint !e716*/
3627    {
3628       uint32_t distance;
3629 
3630       /* if position is empty or key equal insert element */
3631       if( hashset->slots[pos] == NULL )
3632       {
3633          hashset->slots[pos] = element;
3634          ++hashset->nelements;
3635          return;
3636       }
3637 
3638       if( hashset->slots[pos] == element )
3639          return;
3640 
3641       /* otherwise check if the current element at this position is closer to its hashvalue */
3642       distance = ELEM_DISTANCE(pos);
3643       if( distance < elemdistance )
3644       {
3645          /* if this is the case we insert the new element here and find a new position for the old one */
3646          elemdistance = distance;
3647          SCIPswapPointers(&hashset->slots[pos], &element);
3648       }
3649 
3650       /* continue until we have found an empty position */
3651       pos = (pos + 1) & mask;
3652       ++elemdistance;
3653    }
3654 }
3655 
3656 /** check if the load factor of the hash set is too high and rebuild if necessary */
3657 static
hashsetCheckLoad(SCIP_HASHSET * hashset,BMS_BLKMEM * blkmem)3658 SCIP_RETCODE hashsetCheckLoad(
3659    SCIP_HASHSET*         hashset,            /**< hash set */
3660    BMS_BLKMEM*           blkmem              /**< block memory used to store hash set entries */
3661    )
3662 {
3663    assert(hashset != NULL);
3664    assert(hashset->shift < 64);
3665 
3666    /* use integer arithmetic to approximately check if load factor is above 90% */
3667    if( ((((uint64_t)hashset->nelements)<<10)>>(64-hashset->shift) > 921) )
3668    {
3669       void** slots;
3670       uint32_t nslots;
3671       uint32_t newnslots;
3672       uint32_t i;
3673 
3674       /* calculate new size (always power of two) */
3675       nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3676       newnslots = 2*nslots;
3677       --hashset->shift;
3678 
3679       /* reallocate array */
3680       SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &slots, newnslots) );
3681 
3682       SCIPswapPointers((void**) &slots, (void**) &hashset->slots);
3683       hashset->nelements = 0;
3684 
3685       /* reinsert all elements */
3686       for( i = 0; i < nslots; ++i )
3687       {
3688          if( slots[i] != NULL )
3689             hashsetInsert(hashset, slots[i]);
3690       }
3691 
3692       BMSfreeBlockMemoryArray(blkmem, &slots, nslots);
3693    }
3694 
3695    return SCIP_OKAY;
3696 }
3697 
3698 /** creates a hash set of pointers */
SCIPhashsetCreate(SCIP_HASHSET ** hashset,BMS_BLKMEM * blkmem,int size)3699 SCIP_RETCODE SCIPhashsetCreate(
3700    SCIP_HASHSET**        hashset,            /**< pointer to store the created hash set */
3701    BMS_BLKMEM*           blkmem,             /**< block memory used to store hash set entries */
3702    int                   size                /**< initial size of the hash set; it is guaranteed that the set is not
3703                                               *   resized if at most that many elements are inserted */
3704    )
3705 {
3706    uint32_t nslots;
3707 
3708    assert(hashset != NULL);
3709    assert(size >= 0);
3710    assert(blkmem != NULL);
3711 
3712    SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashset) );
3713 
3714    /* do not create too small hashtables, i.e. at least size 32, and increase
3715     * the given size by dividing it by 0.9, since then no rebuilding will
3716     * be necessary if the given number of elements are inserted. Finally round
3717     * to the next power of two.
3718     */
3719    (*hashset)->shift = 64;
3720    (*hashset)->shift -= (unsigned int)ceil(log(MAX(8.0, size / 0.9)) / log(2.0));
3721    nslots = (uint32_t)SCIPhashsetGetNSlots(*hashset);
3722    (*hashset)->nelements = 0;
3723 
3724    SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashset)->slots, nslots) );
3725 
3726    return SCIP_OKAY;
3727 }
3728 
3729 /** frees the hash set */
SCIPhashsetFree(SCIP_HASHSET ** hashset,BMS_BLKMEM * blkmem)3730 void SCIPhashsetFree(
3731    SCIP_HASHSET**        hashset,            /**< pointer to the hash set */
3732    BMS_BLKMEM*           blkmem              /**< block memory used to store hash set entries */
3733    )
3734 {
3735    BMSfreeBlockMemoryArray(blkmem, &(*hashset)->slots, SCIPhashsetGetNSlots(*hashset));
3736    BMSfreeBlockMemory(blkmem, hashset);
3737 }
3738 
3739 /** inserts new element into the hash set */
SCIPhashsetInsert(SCIP_HASHSET * hashset,BMS_BLKMEM * blkmem,void * element)3740 SCIP_RETCODE SCIPhashsetInsert(
3741    SCIP_HASHSET*         hashset,            /**< hash set */
3742    BMS_BLKMEM*           blkmem,             /**< block memory used to store hash set entries */
3743    void*                 element             /**< element to insert */
3744    )
3745 {
3746    assert(hashset != NULL);
3747    assert(hashset->slots != NULL);
3748 
3749    SCIP_CALL( hashsetCheckLoad(hashset, blkmem) );
3750 
3751    hashsetInsert(hashset, element);
3752 
3753    return SCIP_OKAY;
3754 }
3755 
3756 /** checks whether an element exists in the hash set */
SCIPhashsetExists(SCIP_HASHSET * hashset,void * element)3757 SCIP_Bool SCIPhashsetExists(
3758    SCIP_HASHSET*         hashset,            /**< hash set */
3759    void*                 element             /**< element to search for */
3760    )
3761 {
3762    uint32_t pos;
3763    uint32_t nslots;
3764    uint32_t mask;
3765    uint32_t elemdistance;
3766 
3767    assert(hashset != NULL);
3768    assert(hashset->slots != NULL);
3769 
3770    pos = hashSetDesiredPos(hashset, element);
3771    nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3772    mask = nslots - 1;
3773    elemdistance = 0;
3774 
3775    while( TRUE ) /*lint !e716*/
3776    {
3777       uint32_t distance;
3778 
3779       /* found element */
3780       if( hashset->slots[pos] == element )
3781          return TRUE;
3782 
3783       /* slots is empty so element cannot be contained */
3784       if( hashset->slots[pos] == NULL )
3785          return FALSE;
3786 
3787       distance = ELEM_DISTANCE(pos);
3788       /* element can not be contained since otherwise we would have swapped it with this one during insert */
3789       if( elemdistance > distance )
3790          return FALSE;
3791 
3792       pos = (pos + 1) & mask;
3793       ++elemdistance;
3794    }
3795 }
3796 
3797 /** removes an element from the hash set, if it exists */
SCIPhashsetRemove(SCIP_HASHSET * hashset,void * element)3798 SCIP_RETCODE SCIPhashsetRemove(
3799    SCIP_HASHSET*         hashset,            /**< hash set */
3800    void*                 element             /**< origin to remove from the list */
3801    )
3802 {
3803    uint32_t pos;
3804    uint32_t nslots;
3805    uint32_t mask;
3806    uint32_t elemdistance;
3807 
3808    assert(hashset != NULL);
3809    assert(hashset->slots != NULL);
3810    assert(element != NULL);
3811 
3812    pos = hashSetDesiredPos(hashset, element);
3813    nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3814    mask = nslots - 1;
3815    elemdistance = 0;
3816 
3817    while( TRUE ) /*lint !e716*/
3818    {
3819       uint32_t distance;
3820 
3821       /* found element */
3822       if( hashset->slots[pos] == element )
3823          break;
3824 
3825       /* slots is empty so element cannot be contained */
3826       if( hashset->slots[pos] == NULL )
3827          return SCIP_OKAY;
3828 
3829       distance = ELEM_DISTANCE(pos);
3830       /* element can not be contained since otherwise we would have swapped it with this one during insert */
3831       if( elemdistance > distance )
3832          return SCIP_OKAY;
3833 
3834       pos = (pos + 1) & mask;
3835       ++elemdistance;
3836    }
3837 
3838    assert(hashset->slots[pos] == element);
3839    assert(SCIPhashsetExists(hashset, element));
3840 
3841    /* remove element */
3842    --hashset->nelements;
3843 
3844    /* move other elements if necessary */
3845    while( TRUE ) /*lint !e716*/
3846    {
3847       uint32_t nextpos = (pos + 1) & mask;
3848 
3849       /* nothing to do since there is no chain that needs to be moved */
3850       if( hashset->slots[nextpos] == NULL )
3851       {
3852          hashset->slots[pos] = NULL;
3853          assert(!SCIPhashsetExists(hashset, element));
3854          return SCIP_OKAY;
3855       }
3856 
3857       /* check if the element is the start of a new chain and return if that is the case */
3858       if( hashSetDesiredPos(hashset, hashset->slots[nextpos]) == nextpos )
3859       {
3860          hashset->slots[pos] = NULL;
3861          assert(!SCIPhashsetExists(hashset, element));
3862          return SCIP_OKAY;
3863       }
3864 
3865       /* element should be moved to the left and next element needs to be checked */
3866       hashset->slots[pos] = hashset->slots[nextpos];
3867 
3868       pos = nextpos;
3869    }
3870 }
3871 
3872 /** prints statistics about hash set usage */
SCIPhashsetPrintStatistics(SCIP_HASHSET * hashset,SCIP_MESSAGEHDLR * messagehdlr)3873 void SCIPhashsetPrintStatistics(
3874    SCIP_HASHSET*         hashset,            /**< hash set */
3875    SCIP_MESSAGEHDLR*     messagehdlr         /**< message handler */
3876    )
3877 {
3878    uint32_t maxprobelen = 0;
3879    uint64_t probelensum = 0;
3880    uint32_t nslots;
3881    uint32_t mask;
3882    uint32_t i;
3883 
3884    assert(hashset != NULL);
3885 
3886    nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3887    mask = nslots - 1;
3888 
3889    /* compute the maximum and average probe length */
3890    for( i = 0; i < nslots; ++i )
3891    {
3892       if( hashset->slots[i] != NULL )
3893       {
3894          uint32_t probelen = ((hashSetDesiredPos(hashset, hashset->slots[i]) + nslots - i) & mask) + 1;
3895          probelensum += probelen;
3896          maxprobelen = MAX(probelen, maxprobelen);
3897       }
3898    }
3899 
3900    /* print general hash set statistics */
3901    SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3902                         (unsigned int)hashset->nelements, (unsigned int)hashset->nelements,
3903                         (unsigned int)nslots, 100.0*(SCIP_Real)hashset->nelements/(SCIP_Real)(nslots));
3904 
3905    /* if not empty print average and maximum probe length */
3906    if( hashset->nelements > 0 )
3907       SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3908          (SCIP_Real)(probelensum)/(SCIP_Real)hashset->nelements, (unsigned int)maxprobelen);
3909    SCIPmessagePrintInfo(messagehdlr, "\n");
3910 }
3911 
3912 /* In debug mode, the following methods are implemented as function calls to ensure
3913  * type validity.
3914  * In optimized mode, the methods are implemented as defines to improve performance.
3915  * However, we want to have them in the library anyways, so we have to undef the defines.
3916  */
3917 
3918 #undef SCIPhashsetIsEmpty
3919 #undef SCIPhashsetGetNElements
3920 #undef SCIPhashsetGetNSlots
3921 #undef SCIPhashsetGetSlots
3922 
3923 /** indicates whether a hash set has no entries */
SCIPhashsetIsEmpty(SCIP_HASHSET * hashset)3924 SCIP_Bool SCIPhashsetIsEmpty(
3925    SCIP_HASHSET*         hashset             /**< hash set */
3926    )
3927 {
3928    return hashset->nelements == 0;
3929 }
3930 
3931 /** gives the number of elements in a hash set */
SCIPhashsetGetNElements(SCIP_HASHSET * hashset)3932 int SCIPhashsetGetNElements(
3933    SCIP_HASHSET*         hashset             /**< hash set */
3934    )
3935 {
3936    return (int)hashset->nelements;
3937 }
3938 
3939 /** gives the number of slots of a hash set */
SCIPhashsetGetNSlots(SCIP_HASHSET * hashset)3940 int SCIPhashsetGetNSlots(
3941    SCIP_HASHSET*         hashset             /**< hash set */
3942    )
3943 {
3944    return (int) (1u << (64 - hashset->shift));
3945 }
3946 
3947 /** gives the array of hash set slots; contains all elements in indetermined order and may contain NULL values */
SCIPhashsetGetSlots(SCIP_HASHSET * hashset)3948 void** SCIPhashsetGetSlots(
3949    SCIP_HASHSET*         hashset             /**< hash set */
3950    )
3951 {
3952    return hashset->slots;
3953 }
3954 
3955 /** removes all entries in a hash set. */
SCIPhashsetRemoveAll(SCIP_HASHSET * hashset)3956 void SCIPhashsetRemoveAll(
3957    SCIP_HASHSET*         hashset             /**< hash set */
3958    )
3959 {
3960    BMSclearMemoryArray(hashset->slots, SCIPhashsetGetNSlots(hashset));
3961 
3962    hashset->nelements = 0;
3963 }
3964 
3965 /*
3966  * Dynamic Arrays
3967  */
3968 
3969 /** creates a dynamic array of real values */
SCIPrealarrayCreate(SCIP_REALARRAY ** realarray,BMS_BLKMEM * blkmem)3970 SCIP_RETCODE SCIPrealarrayCreate(
3971    SCIP_REALARRAY**      realarray,          /**< pointer to store the real array */
3972    BMS_BLKMEM*           blkmem              /**< block memory */
3973    )
3974 {
3975    assert(realarray != NULL);
3976    assert(blkmem != NULL);
3977 
3978    SCIP_ALLOC( BMSallocBlockMemory(blkmem, realarray) );
3979    (*realarray)->blkmem = blkmem;
3980    (*realarray)->vals = NULL;
3981    (*realarray)->valssize = 0;
3982    (*realarray)->firstidx = -1;
3983    (*realarray)->minusedidx = INT_MAX;
3984    (*realarray)->maxusedidx = INT_MIN;
3985 
3986    return SCIP_OKAY;
3987 }
3988 
3989 /** creates a copy of a dynamic array of real values */
SCIPrealarrayCopy(SCIP_REALARRAY ** realarray,BMS_BLKMEM * blkmem,SCIP_REALARRAY * sourcerealarray)3990 SCIP_RETCODE SCIPrealarrayCopy(
3991    SCIP_REALARRAY**      realarray,          /**< pointer to store the copied real array */
3992    BMS_BLKMEM*           blkmem,             /**< block memory */
3993    SCIP_REALARRAY*       sourcerealarray     /**< dynamic real array to copy */
3994    )
3995 {
3996    assert(realarray != NULL);
3997    assert(sourcerealarray != NULL);
3998 
3999    SCIP_CALL( SCIPrealarrayCreate(realarray, blkmem) );
4000    if( sourcerealarray->valssize > 0 )
4001    {
4002       SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*realarray)->vals, sourcerealarray->vals, \
4003                      sourcerealarray->valssize) );
4004    }
4005    (*realarray)->valssize = sourcerealarray->valssize;
4006    (*realarray)->firstidx = sourcerealarray->firstidx;
4007    (*realarray)->minusedidx = sourcerealarray->minusedidx;
4008    (*realarray)->maxusedidx = sourcerealarray->maxusedidx;
4009 
4010    return SCIP_OKAY;
4011 }
4012 
4013 /** frees a dynamic array of real values */
SCIPrealarrayFree(SCIP_REALARRAY ** realarray)4014 SCIP_RETCODE SCIPrealarrayFree(
4015    SCIP_REALARRAY**      realarray           /**< pointer to the real array */
4016    )
4017 {
4018    assert(realarray != NULL);
4019    assert(*realarray != NULL);
4020 
4021    BMSfreeBlockMemoryArrayNull((*realarray)->blkmem, &(*realarray)->vals, (*realarray)->valssize);
4022    BMSfreeBlockMemory((*realarray)->blkmem, realarray);
4023 
4024    return SCIP_OKAY;
4025 }
4026 
4027 /** extends dynamic array to be able to store indices from minidx to maxidx */
SCIPrealarrayExtend(SCIP_REALARRAY * realarray,int arraygrowinit,SCIP_Real arraygrowfac,int minidx,int maxidx)4028 SCIP_RETCODE SCIPrealarrayExtend(
4029    SCIP_REALARRAY*       realarray,          /**< dynamic real array */
4030    int                   arraygrowinit,      /**< initial size of array */
4031    SCIP_Real             arraygrowfac,       /**< growing factor of array */
4032    int                   minidx,             /**< smallest index to allocate storage for */
4033    int                   maxidx              /**< largest index to allocate storage for */
4034    )
4035 {
4036    int nused;
4037    int nfree;
4038    int newfirstidx;
4039    int i;
4040 
4041    assert(realarray != NULL);
4042    assert(realarray->minusedidx == INT_MAX || realarray->firstidx >= 0);
4043    assert(realarray->maxusedidx == INT_MIN || realarray->firstidx >= 0);
4044    assert(realarray->minusedidx == INT_MAX || realarray->minusedidx >= realarray->firstidx);
4045    assert(realarray->maxusedidx == INT_MIN || realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4046    assert(0 <= minidx);
4047    assert(minidx <= maxidx);
4048 
4049    minidx = MIN(minidx, realarray->minusedidx);
4050    maxidx = MAX(maxidx, realarray->maxusedidx);
4051    assert(0 <= minidx);
4052    assert(minidx <= maxidx);
4053 
4054    SCIPdebugMessage("extending realarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4055       (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, minidx, maxidx);
4056 
4057    /* check, whether we have to allocate additional memory, or shift the array */
4058    nused = maxidx - minidx + 1;
4059    if( nused > realarray->valssize )
4060    {
4061       SCIP_Real* newvals;
4062       int newvalssize;
4063 
4064       /* allocate new memory storage */
4065       newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4066       SCIP_ALLOC( BMSallocBlockMemoryArray(realarray->blkmem, &newvals, newvalssize) );
4067       nfree = newvalssize - nused;
4068       newfirstidx = minidx - nfree/2;
4069       newfirstidx = MAX(newfirstidx, 0);
4070       assert(newfirstidx <= minidx);
4071       assert(maxidx < newfirstidx + newvalssize);
4072 
4073       /* initialize memory array by copying old values and setting new values to zero */
4074       if( realarray->firstidx != -1 )
4075       {
4076          for( i = 0; i < realarray->minusedidx - newfirstidx; ++i )
4077             newvals[i] = 0.0;
4078 
4079          /* check for possible overflow or negative value */
4080          assert(realarray->maxusedidx - realarray->minusedidx + 1 > 0);
4081 
4082          BMScopyMemoryArray(&newvals[realarray->minusedidx - newfirstidx],
4083             &(realarray->vals[realarray->minusedidx - realarray->firstidx]),
4084             realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866 !e776*/
4085          for( i = realarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4086             newvals[i] = 0.0;
4087       }
4088       else
4089       {
4090          for( i = 0; i < newvalssize; ++i )
4091             newvals[i] = 0.0;
4092       }
4093 
4094       /* free old memory storage, and set the new array parameters */
4095       BMSfreeBlockMemoryArrayNull(realarray->blkmem, &realarray->vals, realarray->valssize);
4096       realarray->vals = newvals;
4097       realarray->valssize = newvalssize;
4098       realarray->firstidx = newfirstidx;
4099    }
4100    else if( realarray->firstidx == -1 )
4101    {
4102       /* a sufficiently large memory storage exists, but it was cleared */
4103       nfree = realarray->valssize - nused;
4104       assert(nfree >= 0);
4105       realarray->firstidx = minidx - nfree/2;
4106       assert(realarray->firstidx <= minidx);
4107       assert(maxidx < realarray->firstidx + realarray->valssize);
4108 #ifndef NDEBUG
4109       for( i = 0; i < realarray->valssize; ++i )
4110          assert(realarray->vals[i] == 0.0);
4111 #endif
4112    }
4113    else if( minidx < realarray->firstidx )
4114    {
4115       /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4116       nfree = realarray->valssize - nused;
4117       assert(nfree >= 0);
4118       newfirstidx = minidx - nfree/2;
4119       newfirstidx = MAX(newfirstidx, 0);
4120       assert(newfirstidx <= minidx);
4121       assert(maxidx < newfirstidx + realarray->valssize);
4122 
4123       if( realarray->minusedidx <= realarray->maxusedidx )
4124       {
4125          int shift;
4126 
4127          assert(realarray->firstidx <= realarray->minusedidx);
4128          assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4129 
4130          /* shift used part of array to the right */
4131          shift = realarray->firstidx - newfirstidx;
4132          assert(shift > 0);
4133          for( i = realarray->maxusedidx - realarray->firstidx; i >= realarray->minusedidx - realarray->firstidx; --i )
4134          {
4135             assert(0 <= i + shift && i + shift < realarray->valssize);
4136             realarray->vals[i + shift] = realarray->vals[i];
4137          }
4138          /* clear the formerly used head of the array */
4139          for( i = 0; i < shift; ++i )
4140             realarray->vals[realarray->minusedidx - realarray->firstidx + i] = 0.0;
4141       }
4142       realarray->firstidx = newfirstidx;
4143    }
4144    else if( maxidx >= realarray->firstidx + realarray->valssize )
4145    {
4146       /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4147       nfree = realarray->valssize - nused;
4148       assert(nfree >= 0);
4149       newfirstidx = minidx - nfree/2;
4150       newfirstidx = MAX(newfirstidx, 0);
4151       assert(newfirstidx <= minidx);
4152       assert(maxidx < newfirstidx + realarray->valssize);
4153 
4154       if( realarray->minusedidx <= realarray->maxusedidx )
4155       {
4156          int shift;
4157 
4158          assert(realarray->firstidx <= realarray->minusedidx);
4159          assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4160 
4161          /* shift used part of array to the left */
4162          shift = newfirstidx - realarray->firstidx;
4163          assert(shift > 0);
4164          for( i = realarray->minusedidx - realarray->firstidx; i <= realarray->maxusedidx - realarray->firstidx; ++i )
4165          {
4166             assert(0 <= i - shift && i - shift < realarray->valssize);
4167             realarray->vals[i - shift] = realarray->vals[i];
4168          }
4169          /* clear the formerly used tail of the array */
4170          for( i = 0; i < shift; ++i )
4171             realarray->vals[realarray->maxusedidx - realarray->firstidx - i] = 0.0;
4172       }
4173       realarray->firstidx = newfirstidx;
4174    }
4175 
4176    assert(minidx >= realarray->firstidx);
4177    assert(maxidx < realarray->firstidx + realarray->valssize);
4178 
4179    return SCIP_OKAY;
4180 }
4181 
4182 /** clears a dynamic real array */
SCIPrealarrayClear(SCIP_REALARRAY * realarray)4183 SCIP_RETCODE SCIPrealarrayClear(
4184    SCIP_REALARRAY*       realarray           /**< dynamic real array */
4185    )
4186 {
4187    assert(realarray != NULL);
4188 
4189    SCIPdebugMessage("clearing realarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4190       (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx);
4191 
4192    if( realarray->minusedidx <= realarray->maxusedidx )
4193    {
4194       assert(realarray->firstidx <= realarray->minusedidx);
4195       assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4196       assert(realarray->firstidx != -1);
4197       assert(realarray->valssize > 0);
4198 
4199       /* clear the used part of array */
4200       BMSclearMemoryArray(&realarray->vals[realarray->minusedidx - realarray->firstidx],
4201          realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866*/
4202 
4203       /* mark the array cleared */
4204       realarray->minusedidx = INT_MAX;
4205       realarray->maxusedidx = INT_MIN;
4206    }
4207    assert(realarray->minusedidx == INT_MAX);
4208    assert(realarray->maxusedidx == INT_MIN);
4209 
4210    return SCIP_OKAY;
4211 }
4212 
4213 /** gets value of entry in dynamic array */
SCIPrealarrayGetVal(SCIP_REALARRAY * realarray,int idx)4214 SCIP_Real SCIPrealarrayGetVal(
4215    SCIP_REALARRAY*       realarray,          /**< dynamic real array */
4216    int                   idx                 /**< array index to get value for */
4217    )
4218 {
4219    assert(realarray != NULL);
4220    assert(idx >= 0);
4221 
4222    if( idx < realarray->minusedidx || idx > realarray->maxusedidx )
4223       return 0.0;
4224    else
4225    {
4226       assert(realarray->vals != NULL);
4227       assert(idx - realarray->firstidx >= 0);
4228       assert(idx - realarray->firstidx < realarray->valssize);
4229 
4230       return realarray->vals[idx - realarray->firstidx];
4231    }
4232 }
4233 
4234 /** sets value of entry in dynamic array */
SCIPrealarraySetVal(SCIP_REALARRAY * realarray,int arraygrowinit,SCIP_Real arraygrowfac,int idx,SCIP_Real val)4235 SCIP_RETCODE SCIPrealarraySetVal(
4236    SCIP_REALARRAY*       realarray,          /**< dynamic real array */
4237    int                   arraygrowinit,      /**< initial size of array */
4238    SCIP_Real             arraygrowfac,       /**< growing factor of array */
4239    int                   idx,                /**< array index to set value for */
4240    SCIP_Real             val                 /**< value to set array index to */
4241    )
4242 {
4243    assert(realarray != NULL);
4244    assert(idx >= 0);
4245 
4246    SCIPdebugMessage("setting realarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %g\n",
4247       (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, idx, val);
4248 
4249    if( val != 0.0 )
4250    {
4251       /* extend array to be able to store the index */
4252       SCIP_CALL( SCIPrealarrayExtend(realarray, arraygrowinit, arraygrowfac, idx, idx) );
4253       assert(idx >= realarray->firstidx);
4254       assert(idx < realarray->firstidx + realarray->valssize);
4255 
4256       /* set the array value of the index */
4257       realarray->vals[idx - realarray->firstidx] = val;
4258 
4259       /* update min/maxusedidx */
4260       realarray->minusedidx = MIN(realarray->minusedidx, idx);
4261       realarray->maxusedidx = MAX(realarray->maxusedidx, idx);
4262    }
4263    else if( idx >= realarray->firstidx && idx < realarray->firstidx + realarray->valssize )
4264    {
4265       /* set the array value of the index to zero */
4266       realarray->vals[idx - realarray->firstidx] = 0.0;
4267 
4268       /* check, if we can tighten the min/maxusedidx */
4269       if( idx == realarray->minusedidx )
4270       {
4271          assert(realarray->maxusedidx >= 0);
4272          assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4273          do
4274          {
4275             realarray->minusedidx++;
4276          }
4277          while( realarray->minusedidx <= realarray->maxusedidx
4278             && realarray->vals[realarray->minusedidx - realarray->firstidx] == 0.0 );
4279 
4280          if( realarray->minusedidx > realarray->maxusedidx )
4281          {
4282             realarray->minusedidx = INT_MAX;
4283             realarray->maxusedidx = INT_MIN;
4284          }
4285       }
4286       else if( idx == realarray->maxusedidx )
4287       {
4288          assert(realarray->minusedidx >= 0);
4289          assert(realarray->minusedidx < realarray->maxusedidx);
4290          assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4291          do
4292          {
4293             realarray->maxusedidx--;
4294             assert(realarray->minusedidx <= realarray->maxusedidx);
4295          }
4296          while( realarray->vals[realarray->maxusedidx - realarray->firstidx] == 0.0 );
4297       }
4298    }
4299 
4300    return SCIP_OKAY;
4301 }
4302 
4303 /** increases value of entry in dynamic array */
SCIPrealarrayIncVal(SCIP_REALARRAY * realarray,int arraygrowinit,SCIP_Real arraygrowfac,int idx,SCIP_Real incval)4304 SCIP_RETCODE SCIPrealarrayIncVal(
4305    SCIP_REALARRAY*       realarray,          /**< dynamic real array */
4306    int                   arraygrowinit,      /**< initial size of array */
4307    SCIP_Real             arraygrowfac,       /**< growing factor of array */
4308    int                   idx,                /**< array index to increase value for */
4309    SCIP_Real             incval              /**< value to increase array index */
4310    )
4311 {
4312    SCIP_Real oldval;
4313 
4314    oldval = SCIPrealarrayGetVal(realarray, idx);
4315    if( oldval != SCIP_INVALID ) /*lint !e777*/
4316       return SCIPrealarraySetVal(realarray, arraygrowinit, arraygrowfac, idx, oldval + incval);
4317    else
4318       return SCIP_OKAY;
4319 }
4320 
4321 /** returns the minimal index of all stored non-zero elements */
SCIPrealarrayGetMinIdx(SCIP_REALARRAY * realarray)4322 int SCIPrealarrayGetMinIdx(
4323    SCIP_REALARRAY*       realarray           /**< dynamic real array */
4324    )
4325 {
4326    assert(realarray != NULL);
4327 
4328    return realarray->minusedidx;
4329 }
4330 
4331 /** returns the maximal index of all stored non-zero elements */
SCIPrealarrayGetMaxIdx(SCIP_REALARRAY * realarray)4332 int SCIPrealarrayGetMaxIdx(
4333    SCIP_REALARRAY*       realarray           /**< dynamic real array */
4334    )
4335 {
4336    assert(realarray != NULL);
4337 
4338    return realarray->maxusedidx;
4339 }
4340 
4341 /** creates a dynamic array of int values */
SCIPintarrayCreate(SCIP_INTARRAY ** intarray,BMS_BLKMEM * blkmem)4342 SCIP_RETCODE SCIPintarrayCreate(
4343    SCIP_INTARRAY**       intarray,           /**< pointer to store the int array */
4344    BMS_BLKMEM*           blkmem              /**< block memory */
4345    )
4346 {
4347    assert(intarray != NULL);
4348    assert(blkmem != NULL);
4349 
4350    SCIP_ALLOC( BMSallocBlockMemory(blkmem, intarray) );
4351    (*intarray)->blkmem = blkmem;
4352    (*intarray)->vals = NULL;
4353    (*intarray)->valssize = 0;
4354    (*intarray)->firstidx = -1;
4355    (*intarray)->minusedidx = INT_MAX;
4356    (*intarray)->maxusedidx = INT_MIN;
4357 
4358    return SCIP_OKAY;
4359 }
4360 
4361 /** creates a copy of a dynamic array of int values */
SCIPintarrayCopy(SCIP_INTARRAY ** intarray,BMS_BLKMEM * blkmem,SCIP_INTARRAY * sourceintarray)4362 SCIP_RETCODE SCIPintarrayCopy(
4363    SCIP_INTARRAY**       intarray,           /**< pointer to store the copied int array */
4364    BMS_BLKMEM*           blkmem,             /**< block memory */
4365    SCIP_INTARRAY*        sourceintarray      /**< dynamic int array to copy */
4366    )
4367 {
4368    assert(intarray != NULL);
4369    assert(sourceintarray != NULL);
4370 
4371    SCIP_CALL( SCIPintarrayCreate(intarray, blkmem) );
4372    if( sourceintarray->valssize > 0 )
4373    {
4374       SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*intarray)->vals, sourceintarray->vals, sourceintarray->valssize) );
4375    }
4376    (*intarray)->valssize = sourceintarray->valssize;
4377    (*intarray)->firstidx = sourceintarray->firstidx;
4378    (*intarray)->minusedidx = sourceintarray->minusedidx;
4379    (*intarray)->maxusedidx = sourceintarray->maxusedidx;
4380 
4381    return SCIP_OKAY;
4382 }
4383 
4384 /** frees a dynamic array of int values */
SCIPintarrayFree(SCIP_INTARRAY ** intarray)4385 SCIP_RETCODE SCIPintarrayFree(
4386    SCIP_INTARRAY**       intarray            /**< pointer to the int array */
4387    )
4388 {
4389    assert(intarray != NULL);
4390    assert(*intarray != NULL);
4391 
4392    BMSfreeBlockMemoryArrayNull((*intarray)->blkmem, &(*intarray)->vals, (*intarray)->valssize);
4393    BMSfreeBlockMemory((*intarray)->blkmem, intarray);
4394 
4395    return SCIP_OKAY;
4396 }
4397 
4398 /** extends dynamic array to be able to store indices from minidx to maxidx */
SCIPintarrayExtend(SCIP_INTARRAY * intarray,int arraygrowinit,SCIP_Real arraygrowfac,int minidx,int maxidx)4399 SCIP_RETCODE SCIPintarrayExtend(
4400    SCIP_INTARRAY*        intarray,           /**< dynamic int array */
4401    int                   arraygrowinit,      /**< initial size of array */
4402    SCIP_Real             arraygrowfac,       /**< growing factor of array */
4403    int                   minidx,             /**< smallest index to allocate storage for */
4404    int                   maxidx              /**< largest index to allocate storage for */
4405    )
4406 {
4407    int nused;
4408    int nfree;
4409    int newfirstidx;
4410    int i;
4411 
4412    assert(intarray != NULL);
4413    assert(intarray->minusedidx == INT_MAX || intarray->firstidx >= 0);
4414    assert(intarray->maxusedidx == INT_MIN || intarray->firstidx >= 0);
4415    assert(intarray->minusedidx == INT_MAX || intarray->minusedidx >= intarray->firstidx);
4416    assert(intarray->maxusedidx == INT_MIN || intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4417    assert(0 <= minidx);
4418    assert(minidx <= maxidx);
4419 
4420    minidx = MIN(minidx, intarray->minusedidx);
4421    maxidx = MAX(maxidx, intarray->maxusedidx);
4422    assert(0 <= minidx);
4423    assert(minidx <= maxidx);
4424 
4425    SCIPdebugMessage("extending intarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4426       (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, minidx, maxidx);
4427 
4428    /* check, whether we have to allocate additional memory, or shift the array */
4429    nused = maxidx - minidx + 1;
4430    if( nused > intarray->valssize )
4431    {
4432       int* newvals;
4433       int newvalssize;
4434 
4435       /* allocate new memory storage */
4436       newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4437       SCIP_ALLOC( BMSallocBlockMemoryArray(intarray->blkmem, &newvals, newvalssize) );
4438       nfree = newvalssize - nused;
4439       newfirstidx = minidx - nfree/2;
4440       newfirstidx = MAX(newfirstidx, 0);
4441       assert(newfirstidx <= minidx);
4442       assert(maxidx < newfirstidx + newvalssize);
4443 
4444       /* initialize memory array by copying old values and setting new values to zero */
4445       if( intarray->firstidx != -1 )
4446       {
4447          for( i = 0; i < intarray->minusedidx - newfirstidx; ++i )
4448             newvals[i] = 0;
4449 
4450          /* check for possible overflow or negative value */
4451          assert(intarray->maxusedidx - intarray->minusedidx + 1 > 0);
4452 
4453          BMScopyMemoryArray(&newvals[intarray->minusedidx - newfirstidx],
4454             &intarray->vals[intarray->minusedidx - intarray->firstidx],
4455             intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866 !e776*/
4456          for( i = intarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4457             newvals[i] = 0;
4458       }
4459       else
4460       {
4461          for( i = 0; i < newvalssize; ++i )
4462             newvals[i] = 0;
4463       }
4464 
4465       /* free old memory storage, and set the new array parameters */
4466       BMSfreeBlockMemoryArrayNull(intarray->blkmem, &intarray->vals, intarray->valssize);
4467       intarray->vals = newvals;
4468       intarray->valssize = newvalssize;
4469       intarray->firstidx = newfirstidx;
4470    }
4471    else if( intarray->firstidx == -1 )
4472    {
4473       /* a sufficiently large memory storage exists, but it was cleared */
4474       nfree = intarray->valssize - nused;
4475       assert(nfree >= 0);
4476       intarray->firstidx = minidx - nfree/2;
4477       assert(intarray->firstidx <= minidx);
4478       assert(maxidx < intarray->firstidx + intarray->valssize);
4479 #ifndef NDEBUG
4480       for( i = 0; i < intarray->valssize; ++i )
4481          assert(intarray->vals[i] == 0);
4482 #endif
4483    }
4484    else if( minidx < intarray->firstidx )
4485    {
4486       /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4487       nfree = intarray->valssize - nused;
4488       assert(nfree >= 0);
4489       newfirstidx = minidx - nfree/2;
4490       newfirstidx = MAX(newfirstidx, 0);
4491       assert(newfirstidx <= minidx);
4492       assert(maxidx < newfirstidx + intarray->valssize);
4493 
4494       if( intarray->minusedidx <= intarray->maxusedidx )
4495       {
4496          int shift;
4497 
4498          assert(intarray->firstidx <= intarray->minusedidx);
4499          assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4500 
4501          /* shift used part of array to the right */
4502          shift = intarray->firstidx - newfirstidx;
4503          assert(shift > 0);
4504          for( i = intarray->maxusedidx - intarray->firstidx; i >= intarray->minusedidx - intarray->firstidx; --i )
4505          {
4506             assert(0 <= i + shift && i + shift < intarray->valssize);
4507             intarray->vals[i + shift] = intarray->vals[i];
4508          }
4509          /* clear the formerly used head of the array */
4510          for( i = 0; i < shift; ++i )
4511             intarray->vals[intarray->minusedidx - intarray->firstidx + i] = 0;
4512       }
4513       intarray->firstidx = newfirstidx;
4514    }
4515    else if( maxidx >= intarray->firstidx + intarray->valssize )
4516    {
4517       /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4518       nfree = intarray->valssize - nused;
4519       assert(nfree >= 0);
4520       newfirstidx = minidx - nfree/2;
4521       newfirstidx = MAX(newfirstidx, 0);
4522       assert(newfirstidx <= minidx);
4523       assert(maxidx < newfirstidx + intarray->valssize);
4524 
4525       if( intarray->minusedidx <= intarray->maxusedidx )
4526       {
4527          int shift;
4528 
4529          assert(intarray->firstidx <= intarray->minusedidx);
4530          assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4531 
4532          /* shift used part of array to the left */
4533          shift = newfirstidx - intarray->firstidx;
4534          assert(shift > 0);
4535          for( i = intarray->minusedidx - intarray->firstidx; i <= intarray->maxusedidx - intarray->firstidx; ++i )
4536          {
4537             assert(0 <= i - shift && i - shift < intarray->valssize);
4538             intarray->vals[i - shift] = intarray->vals[i];
4539          }
4540          /* clear the formerly used tail of the array */
4541          for( i = 0; i < shift; ++i )
4542             intarray->vals[intarray->maxusedidx - intarray->firstidx - i] = 0;
4543       }
4544       intarray->firstidx = newfirstidx;
4545    }
4546 
4547    assert(minidx >= intarray->firstidx);
4548    assert(maxidx < intarray->firstidx + intarray->valssize);
4549 
4550    return SCIP_OKAY;
4551 }
4552 
4553 /** clears a dynamic int array */
SCIPintarrayClear(SCIP_INTARRAY * intarray)4554 SCIP_RETCODE SCIPintarrayClear(
4555    SCIP_INTARRAY*        intarray            /**< dynamic int array */
4556    )
4557 {
4558    assert(intarray != NULL);
4559 
4560    SCIPdebugMessage("clearing intarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4561       (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx);
4562 
4563    if( intarray->minusedidx <= intarray->maxusedidx )
4564    {
4565       assert(intarray->firstidx <= intarray->minusedidx);
4566       assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4567       assert(intarray->firstidx != -1);
4568       assert(intarray->valssize > 0);
4569 
4570       /* clear the used part of array */
4571       BMSclearMemoryArray(&intarray->vals[intarray->minusedidx - intarray->firstidx],
4572          intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866*/
4573 
4574       /* mark the array cleared */
4575       intarray->minusedidx = INT_MAX;
4576       intarray->maxusedidx = INT_MIN;
4577    }
4578    assert(intarray->minusedidx == INT_MAX);
4579    assert(intarray->maxusedidx == INT_MIN);
4580 
4581    return SCIP_OKAY;
4582 }
4583 
4584 /** gets value of entry in dynamic array */
SCIPintarrayGetVal(SCIP_INTARRAY * intarray,int idx)4585 int SCIPintarrayGetVal(
4586    SCIP_INTARRAY*        intarray,           /**< dynamic int array */
4587    int                   idx                 /**< array index to get value for */
4588    )
4589 {
4590    assert(intarray != NULL);
4591    assert(idx >= 0);
4592 
4593    if( idx < intarray->minusedidx || idx > intarray->maxusedidx )
4594       return 0;
4595    else
4596    {
4597       assert(intarray->vals != NULL);
4598       assert(idx - intarray->firstidx >= 0);
4599       assert(idx - intarray->firstidx < intarray->valssize);
4600 
4601       return intarray->vals[idx - intarray->firstidx];
4602    }
4603 }
4604 
4605 /** sets value of entry in dynamic array */
SCIPintarraySetVal(SCIP_INTARRAY * intarray,int arraygrowinit,SCIP_Real arraygrowfac,int idx,int val)4606 SCIP_RETCODE SCIPintarraySetVal(
4607    SCIP_INTARRAY*        intarray,           /**< dynamic int array */
4608    int                   arraygrowinit,      /**< initial size of array */
4609    SCIP_Real             arraygrowfac,       /**< growing factor of array */
4610    int                   idx,                /**< array index to set value for */
4611    int                   val                 /**< value to set array index to */
4612    )
4613 {
4614    assert(intarray != NULL);
4615    assert(idx >= 0);
4616 
4617    SCIPdebugMessage("setting intarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %d\n",
4618       (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, idx, val);
4619 
4620    if( val != 0 )
4621    {
4622       /* extend array to be able to store the index */
4623       SCIP_CALL( SCIPintarrayExtend(intarray, arraygrowinit, arraygrowfac, idx, idx) );
4624       assert(idx >= intarray->firstidx);
4625       assert(idx < intarray->firstidx + intarray->valssize);
4626 
4627       /* set the array value of the index */
4628       intarray->vals[idx - intarray->firstidx] = val;
4629 
4630       /* update min/maxusedidx */
4631       intarray->minusedidx = MIN(intarray->minusedidx, idx);
4632       intarray->maxusedidx = MAX(intarray->maxusedidx, idx);
4633    }
4634    else if( idx >= intarray->firstidx && idx < intarray->firstidx + intarray->valssize )
4635    {
4636       /* set the array value of the index to zero */
4637       intarray->vals[idx - intarray->firstidx] = 0;
4638 
4639       /* check, if we can tighten the min/maxusedidx */
4640       if( idx == intarray->minusedidx )
4641       {
4642          assert(intarray->maxusedidx >= 0);
4643          assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4644          do
4645          {
4646             intarray->minusedidx++;
4647          }
4648          while( intarray->minusedidx <= intarray->maxusedidx
4649             && intarray->vals[intarray->minusedidx - intarray->firstidx] == 0 );
4650          if( intarray->minusedidx > intarray->maxusedidx )
4651          {
4652             intarray->minusedidx = INT_MAX;
4653             intarray->maxusedidx = INT_MIN;
4654          }
4655       }
4656       else if( idx == intarray->maxusedidx )
4657       {
4658          assert(intarray->minusedidx >= 0);
4659          assert(intarray->minusedidx < intarray->maxusedidx);
4660          assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4661          do
4662          {
4663             intarray->maxusedidx--;
4664             assert(intarray->minusedidx <= intarray->maxusedidx);
4665          }
4666          while( intarray->vals[intarray->maxusedidx - intarray->firstidx] == 0 );
4667       }
4668    }
4669 
4670    return SCIP_OKAY;
4671 }
4672 
4673 /** increases value of entry in dynamic array */
SCIPintarrayIncVal(SCIP_INTARRAY * intarray,int arraygrowinit,SCIP_Real arraygrowfac,int idx,int incval)4674 SCIP_RETCODE SCIPintarrayIncVal(
4675    SCIP_INTARRAY*        intarray,           /**< dynamic int array */
4676    int                   arraygrowinit,      /**< initial size of array */
4677    SCIP_Real             arraygrowfac,       /**< growing factor of array */
4678    int                   idx,                /**< array index to increase value for */
4679    int                   incval              /**< value to increase array index */
4680    )
4681 {
4682    return SCIPintarraySetVal(intarray, arraygrowinit, arraygrowfac, idx, SCIPintarrayGetVal(intarray, idx) + incval);
4683 }
4684 
4685 /** returns the minimal index of all stored non-zero elements */
SCIPintarrayGetMinIdx(SCIP_INTARRAY * intarray)4686 int SCIPintarrayGetMinIdx(
4687    SCIP_INTARRAY*        intarray            /**< dynamic int array */
4688    )
4689 {
4690    assert(intarray != NULL);
4691 
4692    return intarray->minusedidx;
4693 }
4694 
4695 /** returns the maximal index of all stored non-zero elements */
SCIPintarrayGetMaxIdx(SCIP_INTARRAY * intarray)4696 int SCIPintarrayGetMaxIdx(
4697    SCIP_INTARRAY*        intarray            /**< dynamic int array */
4698    )
4699 {
4700    assert(intarray != NULL);
4701 
4702    return intarray->maxusedidx;
4703 }
4704 
4705 
4706 /** creates a dynamic array of bool values */
SCIPboolarrayCreate(SCIP_BOOLARRAY ** boolarray,BMS_BLKMEM * blkmem)4707 SCIP_RETCODE SCIPboolarrayCreate(
4708    SCIP_BOOLARRAY**      boolarray,          /**< pointer to store the bool array */
4709    BMS_BLKMEM*           blkmem              /**< block memory */
4710    )
4711 {
4712    assert(boolarray != NULL);
4713    assert(blkmem != NULL);
4714 
4715    SCIP_ALLOC( BMSallocBlockMemory(blkmem, boolarray) );
4716    (*boolarray)->blkmem = blkmem;
4717    (*boolarray)->vals = NULL;
4718    (*boolarray)->valssize = 0;
4719    (*boolarray)->firstidx = -1;
4720    (*boolarray)->minusedidx = INT_MAX;
4721    (*boolarray)->maxusedidx = INT_MIN;
4722 
4723    return SCIP_OKAY;
4724 }
4725 
4726 /** creates a copy of a dynamic array of bool values */
SCIPboolarrayCopy(SCIP_BOOLARRAY ** boolarray,BMS_BLKMEM * blkmem,SCIP_BOOLARRAY * sourceboolarray)4727 SCIP_RETCODE SCIPboolarrayCopy(
4728    SCIP_BOOLARRAY**      boolarray,          /**< pointer to store the copied bool array */
4729    BMS_BLKMEM*           blkmem,             /**< block memory */
4730    SCIP_BOOLARRAY*       sourceboolarray     /**< dynamic bool array to copy */
4731    )
4732 {
4733    assert(boolarray != NULL);
4734    assert(sourceboolarray != NULL);
4735 
4736    SCIP_CALL( SCIPboolarrayCreate(boolarray, blkmem) );
4737    if( sourceboolarray->valssize > 0 )
4738    {
4739       SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*boolarray)->vals, sourceboolarray->vals, \
4740                      sourceboolarray->valssize) );
4741    }
4742    (*boolarray)->valssize = sourceboolarray->valssize;
4743    (*boolarray)->firstidx = sourceboolarray->firstidx;
4744    (*boolarray)->minusedidx = sourceboolarray->minusedidx;
4745    (*boolarray)->maxusedidx = sourceboolarray->maxusedidx;
4746 
4747    return SCIP_OKAY;
4748 }
4749 
4750 /** frees a dynamic array of bool values */
SCIPboolarrayFree(SCIP_BOOLARRAY ** boolarray)4751 SCIP_RETCODE SCIPboolarrayFree(
4752    SCIP_BOOLARRAY**      boolarray           /**< pointer to the bool array */
4753    )
4754 {
4755    assert(boolarray != NULL);
4756    assert(*boolarray != NULL);
4757 
4758    BMSfreeBlockMemoryArrayNull((*boolarray)->blkmem, &(*boolarray)->vals, (*boolarray)->valssize);
4759    BMSfreeBlockMemory((*boolarray)->blkmem, boolarray);
4760 
4761    return SCIP_OKAY;
4762 }
4763 
4764 /** extends dynamic array to be able to store indices from minidx to maxidx */
SCIPboolarrayExtend(SCIP_BOOLARRAY * boolarray,int arraygrowinit,SCIP_Real arraygrowfac,int minidx,int maxidx)4765 SCIP_RETCODE SCIPboolarrayExtend(
4766    SCIP_BOOLARRAY*       boolarray,          /**< dynamic bool array */
4767    int                   arraygrowinit,      /**< initial size of array */
4768    SCIP_Real             arraygrowfac,       /**< growing factor of array */
4769    int                   minidx,             /**< smallest index to allocate storage for */
4770    int                   maxidx              /**< largest index to allocate storage for */
4771    )
4772 {
4773    int nused;
4774    int nfree;
4775    int newfirstidx;
4776    int i;
4777 
4778    assert(boolarray != NULL);
4779    assert(boolarray->minusedidx == INT_MAX || boolarray->firstidx >= 0);
4780    assert(boolarray->maxusedidx == INT_MIN || boolarray->firstidx >= 0);
4781    assert(boolarray->minusedidx == INT_MAX || boolarray->minusedidx >= boolarray->firstidx);
4782    assert(boolarray->maxusedidx == INT_MIN || boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4783    assert(0 <= minidx);
4784    assert(minidx <= maxidx);
4785 
4786    minidx = MIN(minidx, boolarray->minusedidx);
4787    maxidx = MAX(maxidx, boolarray->maxusedidx);
4788    assert(0 <= minidx);
4789    assert(minidx <= maxidx);
4790 
4791    SCIPdebugMessage("extending boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4792       (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, minidx, maxidx);
4793 
4794    /* check, whether we have to allocate additional memory, or shift the array */
4795    nused = maxidx - minidx + 1;
4796    if( nused > boolarray->valssize )
4797    {
4798       SCIP_Bool* newvals;
4799       int newvalssize;
4800 
4801       /* allocate new memory storage */
4802       newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4803       SCIP_ALLOC( BMSallocBlockMemoryArray(boolarray->blkmem, &newvals, newvalssize) );
4804       nfree = newvalssize - nused;
4805       newfirstidx = minidx - nfree/2;
4806       newfirstidx = MAX(newfirstidx, 0);
4807       assert(newfirstidx <= minidx);
4808       assert(maxidx < newfirstidx + newvalssize);
4809 
4810       /* initialize memory array by copying old values and setting new values to zero */
4811       if( boolarray->firstidx != -1 )
4812       {
4813          for( i = 0; i < boolarray->minusedidx - newfirstidx; ++i )
4814             newvals[i] = FALSE;
4815 
4816          /* check for possible overflow or negative value */
4817          assert(boolarray->maxusedidx - boolarray->minusedidx + 1 > 0);
4818 
4819          BMScopyMemoryArray(&newvals[boolarray->minusedidx - newfirstidx],
4820             &boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4821             boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866 !e776*/
4822          for( i = boolarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4823             newvals[i] = FALSE;
4824       }
4825       else
4826       {
4827          for( i = 0; i < newvalssize; ++i )
4828             newvals[i] = FALSE;
4829       }
4830 
4831       /* free old memory storage, and set the new array parameters */
4832       BMSfreeBlockMemoryArrayNull(boolarray->blkmem, &boolarray->vals, boolarray->valssize);
4833       boolarray->vals = newvals;
4834       boolarray->valssize = newvalssize;
4835       boolarray->firstidx = newfirstidx;
4836    }
4837    else if( boolarray->firstidx == -1 )
4838    {
4839       /* a sufficiently large memory storage exists, but it was cleared */
4840       nfree = boolarray->valssize - nused;
4841       assert(nfree >= 0);
4842       boolarray->firstidx = minidx - nfree/2;
4843       assert(boolarray->firstidx <= minidx);
4844       assert(maxidx < boolarray->firstidx + boolarray->valssize);
4845 #ifndef NDEBUG
4846       for( i = 0; i < boolarray->valssize; ++i )
4847          assert(boolarray->vals[i] == FALSE);
4848 #endif
4849    }
4850    else if( minidx < boolarray->firstidx )
4851    {
4852       /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4853       nfree = boolarray->valssize - nused;
4854       assert(nfree >= 0);
4855       newfirstidx = minidx - nfree/2;
4856       newfirstidx = MAX(newfirstidx, 0);
4857       assert(newfirstidx <= minidx);
4858       assert(maxidx < newfirstidx + boolarray->valssize);
4859 
4860       if( boolarray->minusedidx <= boolarray->maxusedidx )
4861       {
4862          int shift;
4863 
4864          assert(boolarray->firstidx <= boolarray->minusedidx);
4865          assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4866 
4867          /* shift used part of array to the right */
4868          shift = boolarray->firstidx - newfirstidx;
4869          assert(shift > 0);
4870          for( i = boolarray->maxusedidx - boolarray->firstidx; i >= boolarray->minusedidx - boolarray->firstidx; --i )
4871          {
4872             assert(0 <= i + shift && i + shift < boolarray->valssize);
4873             boolarray->vals[i + shift] = boolarray->vals[i];
4874          }
4875          /* clear the formerly used head of the array */
4876          for( i = 0; i < shift; ++i )
4877             boolarray->vals[boolarray->minusedidx - boolarray->firstidx + i] = FALSE;
4878       }
4879       boolarray->firstidx = newfirstidx;
4880    }
4881    else if( maxidx >= boolarray->firstidx + boolarray->valssize )
4882    {
4883       /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4884       nfree = boolarray->valssize - nused;
4885       assert(nfree >= 0);
4886       newfirstidx = minidx - nfree/2;
4887       newfirstidx = MAX(newfirstidx, 0);
4888       assert(newfirstidx <= minidx);
4889       assert(maxidx < newfirstidx + boolarray->valssize);
4890 
4891       if( boolarray->minusedidx <= boolarray->maxusedidx )
4892       {
4893          int shift;
4894 
4895          assert(boolarray->firstidx <= boolarray->minusedidx);
4896          assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4897 
4898          /* shift used part of array to the left */
4899          shift = newfirstidx - boolarray->firstidx;
4900          assert(shift > 0);
4901 
4902 	 assert(0 <= boolarray->minusedidx - boolarray->firstidx - shift);
4903          assert(boolarray->maxusedidx - boolarray->firstidx - shift < boolarray->valssize);
4904 	 BMSmoveMemoryArray(&(boolarray->vals[boolarray->minusedidx - boolarray->firstidx - shift]),
4905             &(boolarray->vals[boolarray->minusedidx - boolarray->firstidx]),
4906             boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
4907 
4908          /* clear the formerly used tail of the array */
4909          for( i = 0; i < shift; ++i )
4910             boolarray->vals[boolarray->maxusedidx - boolarray->firstidx - i] = FALSE;
4911       }
4912       boolarray->firstidx = newfirstidx;
4913    }
4914 
4915    assert(minidx >= boolarray->firstidx);
4916    assert(maxidx < boolarray->firstidx + boolarray->valssize);
4917 
4918    return SCIP_OKAY;
4919 }
4920 
4921 /** clears a dynamic bool array */
SCIPboolarrayClear(SCIP_BOOLARRAY * boolarray)4922 SCIP_RETCODE SCIPboolarrayClear(
4923    SCIP_BOOLARRAY*       boolarray           /**< dynamic bool array */
4924    )
4925 {
4926    assert(boolarray != NULL);
4927 
4928    SCIPdebugMessage("clearing boolarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4929       (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx);
4930 
4931    if( boolarray->minusedidx <= boolarray->maxusedidx )
4932    {
4933       assert(boolarray->firstidx <= boolarray->minusedidx);
4934       assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4935       assert(boolarray->firstidx != -1);
4936       assert(boolarray->valssize > 0);
4937 
4938       /* clear the used part of array */
4939       BMSclearMemoryArray(&boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4940          boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
4941 
4942       /* mark the array cleared */
4943       boolarray->minusedidx = INT_MAX;
4944       boolarray->maxusedidx = INT_MIN;
4945    }
4946    assert(boolarray->minusedidx == INT_MAX);
4947    assert(boolarray->maxusedidx == INT_MIN);
4948 
4949    return SCIP_OKAY;
4950 }
4951 
4952 /** gets value of entry in dynamic array */
SCIPboolarrayGetVal(SCIP_BOOLARRAY * boolarray,int idx)4953 SCIP_Bool SCIPboolarrayGetVal(
4954    SCIP_BOOLARRAY*       boolarray,          /**< dynamic bool array */
4955    int                   idx                 /**< array index to get value for */
4956    )
4957 {
4958    assert(boolarray != NULL);
4959    assert(idx >= 0);
4960 
4961    if( idx < boolarray->minusedidx || idx > boolarray->maxusedidx )
4962       return FALSE;
4963    else
4964    {
4965       assert(boolarray->vals != NULL);
4966       assert(idx - boolarray->firstidx >= 0);
4967       assert(idx - boolarray->firstidx < boolarray->valssize);
4968 
4969       return boolarray->vals[idx - boolarray->firstidx];
4970    }
4971 }
4972 
4973 /** sets value of entry in dynamic array */
SCIPboolarraySetVal(SCIP_BOOLARRAY * boolarray,int arraygrowinit,SCIP_Real arraygrowfac,int idx,SCIP_Bool val)4974 SCIP_RETCODE SCIPboolarraySetVal(
4975    SCIP_BOOLARRAY*       boolarray,          /**< dynamic bool array */
4976    int                   arraygrowinit,      /**< initial size of array */
4977    SCIP_Real             arraygrowfac,       /**< growing factor of array */
4978    int                   idx,                /**< array index to set value for */
4979    SCIP_Bool             val                 /**< value to set array index to */
4980    )
4981 {
4982    assert(boolarray != NULL);
4983    assert(idx >= 0);
4984 
4985    SCIPdebugMessage("setting boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %u\n",
4986       (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, idx, val);
4987 
4988    if( val != FALSE )
4989    {
4990       /* extend array to be able to store the index */
4991       SCIP_CALL( SCIPboolarrayExtend(boolarray, arraygrowinit, arraygrowfac, idx, idx) );
4992       assert(idx >= boolarray->firstidx);
4993       assert(idx < boolarray->firstidx + boolarray->valssize);
4994 
4995       /* set the array value of the index */
4996       boolarray->vals[idx - boolarray->firstidx] = val;
4997 
4998       /* update min/maxusedidx */
4999       boolarray->minusedidx = MIN(boolarray->minusedidx, idx);
5000       boolarray->maxusedidx = MAX(boolarray->maxusedidx, idx);
5001    }
5002    else if( idx >= boolarray->firstidx && idx < boolarray->firstidx + boolarray->valssize )
5003    {
5004       /* set the array value of the index to zero */
5005       boolarray->vals[idx - boolarray->firstidx] = FALSE;
5006 
5007       /* check, if we can tighten the min/maxusedidx */
5008       if( idx == boolarray->minusedidx )
5009       {
5010          assert(boolarray->maxusedidx >= 0);
5011          assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5012          do
5013          {
5014             boolarray->minusedidx++;
5015          }
5016          while( boolarray->minusedidx <= boolarray->maxusedidx
5017             && boolarray->vals[boolarray->minusedidx - boolarray->firstidx] == FALSE );
5018          if( boolarray->minusedidx > boolarray->maxusedidx )
5019          {
5020             boolarray->minusedidx = INT_MAX;
5021             boolarray->maxusedidx = INT_MIN;
5022          }
5023       }
5024       else if( idx == boolarray->maxusedidx )
5025       {
5026          assert(boolarray->minusedidx >= 0);
5027          assert(boolarray->minusedidx < boolarray->maxusedidx);
5028          assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5029          do
5030          {
5031             boolarray->maxusedidx--;
5032             assert(boolarray->minusedidx <= boolarray->maxusedidx);
5033          }
5034          while( boolarray->vals[boolarray->maxusedidx - boolarray->firstidx] == FALSE );
5035       }
5036    }
5037 
5038    return SCIP_OKAY;
5039 }
5040 
5041 /** returns the minimal index of all stored non-zero elements */
SCIPboolarrayGetMinIdx(SCIP_BOOLARRAY * boolarray)5042 int SCIPboolarrayGetMinIdx(
5043    SCIP_BOOLARRAY*       boolarray           /**< dynamic bool array */
5044    )
5045 {
5046    assert(boolarray != NULL);
5047 
5048    return boolarray->minusedidx;
5049 }
5050 
5051 /** returns the maximal index of all stored non-zero elements */
SCIPboolarrayGetMaxIdx(SCIP_BOOLARRAY * boolarray)5052 int SCIPboolarrayGetMaxIdx(
5053    SCIP_BOOLARRAY*       boolarray           /**< dynamic bool array */
5054    )
5055 {
5056    assert(boolarray != NULL);
5057 
5058    return boolarray->maxusedidx;
5059 }
5060 
5061 
5062 /** creates a dynamic array of pointer values */
SCIPptrarrayCreate(SCIP_PTRARRAY ** ptrarray,BMS_BLKMEM * blkmem)5063 SCIP_RETCODE SCIPptrarrayCreate(
5064    SCIP_PTRARRAY**       ptrarray,           /**< pointer to store the ptr array */
5065    BMS_BLKMEM*           blkmem              /**< block memory */
5066    )
5067 {
5068    assert(ptrarray != NULL);
5069    assert(blkmem != NULL);
5070 
5071    SCIP_ALLOC( BMSallocBlockMemory(blkmem, ptrarray) );
5072    (*ptrarray)->blkmem = blkmem;
5073    (*ptrarray)->vals = NULL;
5074    (*ptrarray)->valssize = 0;
5075    (*ptrarray)->firstidx = -1;
5076    (*ptrarray)->minusedidx = INT_MAX;
5077    (*ptrarray)->maxusedidx = INT_MIN;
5078 
5079    return SCIP_OKAY;
5080 }
5081 
5082 /** creates a copy of a dynamic array of pointer values */
SCIPptrarrayCopy(SCIP_PTRARRAY ** ptrarray,BMS_BLKMEM * blkmem,SCIP_PTRARRAY * sourceptrarray)5083 SCIP_RETCODE SCIPptrarrayCopy(
5084    SCIP_PTRARRAY**       ptrarray,           /**< pointer to store the copied ptr array */
5085    BMS_BLKMEM*           blkmem,             /**< block memory */
5086    SCIP_PTRARRAY*        sourceptrarray      /**< dynamic ptr array to copy */
5087    )
5088 {
5089    assert(ptrarray != NULL);
5090    assert(sourceptrarray != NULL);
5091 
5092    SCIP_CALL( SCIPptrarrayCreate(ptrarray, blkmem) );
5093    if( sourceptrarray->valssize > 0 )
5094    {
5095       SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*ptrarray)->vals, sourceptrarray->vals, sourceptrarray->valssize) );
5096    }
5097    (*ptrarray)->valssize = sourceptrarray->valssize;
5098    (*ptrarray)->firstidx = sourceptrarray->firstidx;
5099    (*ptrarray)->minusedidx = sourceptrarray->minusedidx;
5100    (*ptrarray)->maxusedidx = sourceptrarray->maxusedidx;
5101 
5102    return SCIP_OKAY;
5103 }
5104 
5105 /** frees a dynamic array of pointer values */
SCIPptrarrayFree(SCIP_PTRARRAY ** ptrarray)5106 SCIP_RETCODE SCIPptrarrayFree(
5107    SCIP_PTRARRAY**       ptrarray            /**< pointer to the ptr array */
5108    )
5109 {
5110    assert(ptrarray != NULL);
5111    assert(*ptrarray != NULL);
5112 
5113    BMSfreeBlockMemoryArrayNull((*ptrarray)->blkmem, &(*ptrarray)->vals, (*ptrarray)->valssize);
5114    BMSfreeBlockMemory((*ptrarray)->blkmem, ptrarray);
5115 
5116    return SCIP_OKAY;
5117 }
5118 
5119 /** extends dynamic array to be able to store indices from minidx to maxidx */
SCIPptrarrayExtend(SCIP_PTRARRAY * ptrarray,int arraygrowinit,SCIP_Real arraygrowfac,int minidx,int maxidx)5120 SCIP_RETCODE SCIPptrarrayExtend(
5121    SCIP_PTRARRAY*        ptrarray,           /**< dynamic ptr array */
5122    int                   arraygrowinit,      /**< initial size of array */
5123    SCIP_Real             arraygrowfac,       /**< growing factor of array */
5124    int                   minidx,             /**< smallest index to allocate storage for */
5125    int                   maxidx              /**< largest index to allocate storage for */
5126    )
5127 {
5128    int nused;
5129    int nfree;
5130    int newfirstidx;
5131    int i;
5132 
5133    assert(ptrarray != NULL);
5134    assert(ptrarray->minusedidx == INT_MAX || ptrarray->firstidx >= 0);
5135    assert(ptrarray->maxusedidx == INT_MIN || ptrarray->firstidx >= 0);
5136    assert(ptrarray->minusedidx == INT_MAX || ptrarray->minusedidx >= ptrarray->firstidx);
5137    assert(ptrarray->maxusedidx == INT_MIN || ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5138    assert(0 <= minidx);
5139    assert(minidx <= maxidx);
5140 
5141    minidx = MIN(minidx, ptrarray->minusedidx);
5142    maxidx = MAX(maxidx, ptrarray->maxusedidx);
5143    assert(0 <= minidx);
5144    assert(minidx <= maxidx);
5145 
5146    SCIPdebugMessage("extending ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
5147       (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, minidx, maxidx);
5148 
5149    /* check, whether we have to allocate additional memory, or shift the array */
5150    nused = maxidx - minidx + 1;
5151    if( nused > ptrarray->valssize )
5152    {
5153       void** newvals;
5154       int newvalssize;
5155 
5156       /* allocate new memory storage */
5157       newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
5158       SCIP_ALLOC( BMSallocBlockMemoryArray(ptrarray->blkmem, &newvals, newvalssize) );
5159       nfree = newvalssize - nused;
5160       newfirstidx = minidx - nfree/2;
5161       newfirstidx = MAX(newfirstidx, 0);
5162       assert(newfirstidx <= minidx);
5163       assert(maxidx < newfirstidx + newvalssize);
5164 
5165       /* initialize memory array by copying old values and setting new values to zero */
5166       if( ptrarray->firstidx != -1 )
5167       {
5168          for( i = 0; i < ptrarray->minusedidx - newfirstidx; ++i )
5169             newvals[i] = NULL;
5170 
5171          /* check for possible overflow or negative value */
5172          assert(ptrarray->maxusedidx - ptrarray->minusedidx + 1 > 0);
5173 
5174          BMScopyMemoryArray(&newvals[ptrarray->minusedidx - newfirstidx],
5175             &(ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx]),
5176             ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866 !e776*/
5177          for( i = ptrarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
5178             newvals[i] = NULL;
5179       }
5180       else
5181       {
5182          for( i = 0; i < newvalssize; ++i )
5183             newvals[i] = NULL;
5184       }
5185 
5186       /* free old memory storage, and set the new array parameters */
5187       BMSfreeBlockMemoryArrayNull(ptrarray->blkmem, &ptrarray->vals, ptrarray->valssize);
5188       ptrarray->vals = newvals;
5189       ptrarray->valssize = newvalssize;
5190       ptrarray->firstidx = newfirstidx;
5191    }
5192    else if( ptrarray->firstidx == -1 )
5193    {
5194       /* a sufficiently large memory storage exists, but it was cleared */
5195       nfree = ptrarray->valssize - nused;
5196       assert(nfree >= 0);
5197       ptrarray->firstidx = minidx - nfree/2;
5198       assert(ptrarray->firstidx <= minidx);
5199       assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5200 #ifndef NDEBUG
5201       for( i = 0; i < ptrarray->valssize; ++i )
5202          assert(ptrarray->vals[i] == NULL);
5203 #endif
5204    }
5205    else if( minidx < ptrarray->firstidx )
5206    {
5207       /* a sufficiently large memory storage exists, but it has to be shifted to the right */
5208       nfree = ptrarray->valssize - nused;
5209       assert(nfree >= 0);
5210       newfirstidx = minidx - nfree/2;
5211       newfirstidx = MAX(newfirstidx, 0);
5212       assert(newfirstidx <= minidx);
5213       assert(maxidx < newfirstidx + ptrarray->valssize);
5214 
5215       if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5216       {
5217          int shift;
5218 
5219          assert(ptrarray->firstidx <= ptrarray->minusedidx);
5220          assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5221 
5222          /* shift used part of array to the right */
5223          shift = ptrarray->firstidx - newfirstidx;
5224          assert(shift > 0);
5225          for( i = ptrarray->maxusedidx - ptrarray->firstidx; i >= ptrarray->minusedidx - ptrarray->firstidx; --i )
5226          {
5227             assert(0 <= i + shift && i + shift < ptrarray->valssize);
5228             ptrarray->vals[i + shift] = ptrarray->vals[i];
5229          }
5230          /* clear the formerly used head of the array */
5231          for( i = 0; i < shift; ++i )
5232             ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx + i] = NULL;
5233       }
5234       ptrarray->firstidx = newfirstidx;
5235    }
5236    else if( maxidx >= ptrarray->firstidx + ptrarray->valssize )
5237    {
5238       /* a sufficiently large memory storage exists, but it has to be shifted to the left */
5239       nfree = ptrarray->valssize - nused;
5240       assert(nfree >= 0);
5241       newfirstidx = minidx - nfree/2;
5242       newfirstidx = MAX(newfirstidx, 0);
5243       assert(newfirstidx <= minidx);
5244       assert(maxidx < newfirstidx + ptrarray->valssize);
5245 
5246       if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5247       {
5248          int shift;
5249 
5250          assert(ptrarray->firstidx <= ptrarray->minusedidx);
5251          assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5252 
5253          /* shift used part of array to the left */
5254          shift = newfirstidx - ptrarray->firstidx;
5255          assert(shift > 0);
5256          for( i = ptrarray->minusedidx - ptrarray->firstidx; i <= ptrarray->maxusedidx - ptrarray->firstidx; ++i )
5257          {
5258             assert(0 <= i - shift && i - shift < ptrarray->valssize);
5259             ptrarray->vals[i - shift] = ptrarray->vals[i];
5260          }
5261          /* clear the formerly used tail of the array */
5262          for( i = 0; i < shift; ++i )
5263             ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx - i] = NULL;
5264       }
5265       ptrarray->firstidx = newfirstidx;
5266    }
5267 
5268    assert(minidx >= ptrarray->firstidx);
5269    assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5270 
5271    return SCIP_OKAY;
5272 }
5273 
5274 /** clears a dynamic pointer array */
SCIPptrarrayClear(SCIP_PTRARRAY * ptrarray)5275 SCIP_RETCODE SCIPptrarrayClear(
5276    SCIP_PTRARRAY*        ptrarray            /**< dynamic ptr array */
5277    )
5278 {
5279    assert(ptrarray != NULL);
5280 
5281    SCIPdebugMessage("clearing ptrarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
5282       (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx);
5283 
5284    if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5285    {
5286       assert(ptrarray->firstidx <= ptrarray->minusedidx);
5287       assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5288       assert(ptrarray->firstidx != -1);
5289       assert(ptrarray->valssize > 0);
5290 
5291       /* clear the used part of array */
5292       BMSclearMemoryArray(&ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx],
5293          ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866*/
5294 
5295       /* mark the array cleared */
5296       ptrarray->minusedidx = INT_MAX;
5297       ptrarray->maxusedidx = INT_MIN;
5298    }
5299    assert(ptrarray->minusedidx == INT_MAX);
5300    assert(ptrarray->maxusedidx == INT_MIN);
5301 
5302    return SCIP_OKAY;
5303 }
5304 
5305 /** gets value of entry in dynamic array */
SCIPptrarrayGetVal(SCIP_PTRARRAY * ptrarray,int idx)5306 void* SCIPptrarrayGetVal(
5307    SCIP_PTRARRAY*        ptrarray,           /**< dynamic ptr array */
5308    int                   idx                 /**< array index to get value for */
5309    )
5310 {
5311    assert(ptrarray != NULL);
5312    assert(idx >= 0);
5313 
5314    if( idx < ptrarray->minusedidx || idx > ptrarray->maxusedidx )
5315       return NULL;
5316    else
5317    {
5318       assert(ptrarray->vals != NULL);
5319       assert(idx - ptrarray->firstidx >= 0);
5320       assert(idx - ptrarray->firstidx < ptrarray->valssize);
5321 
5322       return ptrarray->vals[idx - ptrarray->firstidx];
5323    }
5324 }
5325 
5326 /** sets value of entry in dynamic array */
SCIPptrarraySetVal(SCIP_PTRARRAY * ptrarray,int arraygrowinit,SCIP_Real arraygrowfac,int idx,void * val)5327 SCIP_RETCODE SCIPptrarraySetVal(
5328    SCIP_PTRARRAY*        ptrarray,           /**< dynamic ptr array */
5329    int                   arraygrowinit,      /**< initial size of array */
5330    SCIP_Real             arraygrowfac,       /**< growing factor of array */
5331    int                   idx,                /**< array index to set value for */
5332    void*                 val                 /**< value to set array index to */
5333    )
5334 {
5335    assert(ptrarray != NULL);
5336    assert(idx >= 0);
5337 
5338    SCIPdebugMessage("setting ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %p\n",
5339       (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, idx, val);
5340 
5341    if( val != NULL )
5342    {
5343       /* extend array to be able to store the index */
5344       SCIP_CALL( SCIPptrarrayExtend(ptrarray, arraygrowinit, arraygrowfac, idx, idx) );
5345       assert(idx >= ptrarray->firstidx);
5346       assert(idx < ptrarray->firstidx + ptrarray->valssize);
5347 
5348       /* set the array value of the index */
5349       ptrarray->vals[idx - ptrarray->firstidx] = val;
5350 
5351       /* update min/maxusedidx */
5352       ptrarray->minusedidx = MIN(ptrarray->minusedidx, idx);
5353       ptrarray->maxusedidx = MAX(ptrarray->maxusedidx, idx);
5354    }
5355    else if( idx >= ptrarray->firstidx && idx < ptrarray->firstidx + ptrarray->valssize )
5356    {
5357       /* set the array value of the index to zero */
5358       ptrarray->vals[idx - ptrarray->firstidx] = NULL;
5359 
5360       /* check, if we can tighten the min/maxusedidx */
5361       if( idx == ptrarray->minusedidx )
5362       {
5363          assert(ptrarray->maxusedidx >= 0);
5364          assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5365          do
5366          {
5367             ptrarray->minusedidx++;
5368          }
5369          while( ptrarray->minusedidx <= ptrarray->maxusedidx
5370             && ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx] == NULL );
5371          if( ptrarray->minusedidx > ptrarray->maxusedidx )
5372          {
5373             ptrarray->minusedidx = INT_MAX;
5374             ptrarray->maxusedidx = INT_MIN;
5375          }
5376       }
5377       else if( idx == ptrarray->maxusedidx )
5378       {
5379          assert(ptrarray->minusedidx >= 0);
5380          assert(ptrarray->minusedidx < ptrarray->maxusedidx);
5381          assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5382          do
5383          {
5384             ptrarray->maxusedidx--;
5385             assert(ptrarray->minusedidx <= ptrarray->maxusedidx);
5386          }
5387          while( ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx] == NULL );
5388       }
5389    }
5390 
5391    return SCIP_OKAY;
5392 }
5393 
5394 /** returns the minimal index of all stored non-zero elements */
SCIPptrarrayGetMinIdx(SCIP_PTRARRAY * ptrarray)5395 int SCIPptrarrayGetMinIdx(
5396    SCIP_PTRARRAY*        ptrarray            /**< dynamic ptr array */
5397    )
5398 {
5399    assert(ptrarray != NULL);
5400 
5401    return ptrarray->minusedidx;
5402 }
5403 
5404 /** returns the maximal index of all stored non-zero elements */
SCIPptrarrayGetMaxIdx(SCIP_PTRARRAY * ptrarray)5405 int SCIPptrarrayGetMaxIdx(
5406    SCIP_PTRARRAY*        ptrarray            /**< dynamic ptr array */
5407    )
5408 {
5409    assert(ptrarray != NULL);
5410 
5411    return ptrarray->maxusedidx;
5412 }
5413 
5414 
5415 /*
5416  * Sorting algorithms
5417  */
5418 
5419 /** default comparer for integers */
SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)5420 SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
5421 {
5422    int value1;
5423    int value2;
5424 
5425    value1 = (int)(size_t)elem1;
5426    value2 = (int)(size_t)elem2;
5427 
5428    if( value1 < value2 )
5429       return -1;
5430 
5431    if( value2 < value1 )
5432       return 1;
5433 
5434    return 0;
5435 }
5436 
5437 /* first all upwards-sorting methods */
5438 
5439 /** sort an indexed element set in non-decreasing order, resulting in a permutation index array */
SCIPsort(int * perm,SCIP_DECL_SORTINDCOMP ((* indcomp)),void * dataptr,int len)5440 void SCIPsort(
5441    int*                  perm,               /**< pointer to store the resulting permutation */
5442    SCIP_DECL_SORTINDCOMP((*indcomp)),        /**< data element comparator */
5443    void*                 dataptr,            /**< pointer to data field that is given to the external compare method */
5444    int                   len                 /**< number of elements to be sorted (valid index range) */
5445    )
5446 {
5447    int pos;
5448 
5449    assert(indcomp != NULL);
5450    assert(len == 0 || perm != NULL);
5451 
5452    /* create identity permutation */
5453    for( pos = 0; pos < len; ++pos )
5454       perm[pos] = pos;
5455 
5456    SCIPsortInd(perm, indcomp, dataptr, len);
5457 }
5458 
5459 /* SCIPsortInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5460 #define SORTTPL_NAMEEXT     Ind
5461 #define SORTTPL_KEYTYPE     int
5462 #define SORTTPL_INDCOMP
5463 #include "scip/sorttpl.c" /*lint !e451*/
5464 
5465 
5466 /* SCIPsortPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5467 #define SORTTPL_NAMEEXT     Ptr
5468 #define SORTTPL_KEYTYPE     void*
5469 #define SORTTPL_PTRCOMP
5470 #include "scip/sorttpl.c" /*lint !e451*/
5471 
5472 
5473 /* SCIPsortPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5474 #define SORTTPL_NAMEEXT     PtrPtr
5475 #define SORTTPL_KEYTYPE     void*
5476 #define SORTTPL_FIELD1TYPE  void*
5477 #define SORTTPL_PTRCOMP
5478 #include "scip/sorttpl.c" /*lint !e451*/
5479 
5480 
5481 /* SCIPsortPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5482 #define SORTTPL_NAMEEXT     PtrReal
5483 #define SORTTPL_KEYTYPE     void*
5484 #define SORTTPL_FIELD1TYPE  SCIP_Real
5485 #define SORTTPL_PTRCOMP
5486 #include "scip/sorttpl.c" /*lint !e451*/
5487 
5488 
5489 /* SCIPsortPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5490 #define SORTTPL_NAMEEXT     PtrInt
5491 #define SORTTPL_KEYTYPE     void*
5492 #define SORTTPL_FIELD1TYPE  int
5493 #define SORTTPL_PTRCOMP
5494 #include "scip/sorttpl.c" /*lint !e451*/
5495 
5496 
5497 /* SCIPsortPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5498 #define SORTTPL_NAMEEXT     PtrBool
5499 #define SORTTPL_KEYTYPE     void*
5500 #define SORTTPL_FIELD1TYPE  SCIP_Bool
5501 #define SORTTPL_PTRCOMP
5502 #include "scip/sorttpl.c" /*lint !e451*/
5503 
5504 
5505 /* SCIPsortPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5506 #define SORTTPL_NAMEEXT     PtrIntInt
5507 #define SORTTPL_KEYTYPE     void*
5508 #define SORTTPL_FIELD1TYPE  int
5509 #define SORTTPL_FIELD2TYPE  int
5510 #define SORTTPL_PTRCOMP
5511 #include "scip/sorttpl.c" /*lint !e451*/
5512 
5513 
5514 /* SCIPsortPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5515 #define SORTTPL_NAMEEXT     PtrRealInt
5516 #define SORTTPL_KEYTYPE     void*
5517 #define SORTTPL_FIELD1TYPE  SCIP_Real
5518 #define SORTTPL_FIELD2TYPE  int
5519 #define SORTTPL_PTRCOMP
5520 #include "scip/sorttpl.c" /*lint !e451*/
5521 
5522 /* SCIPsortPtrRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5523 #define SORTTPL_NAMEEXT     PtrRealRealInt
5524 #define SORTTPL_KEYTYPE     void*
5525 #define SORTTPL_FIELD1TYPE  SCIP_Real
5526 #define SORTTPL_FIELD2TYPE  SCIP_Real
5527 #define SORTTPL_FIELD3TYPE  int
5528 #define SORTTPL_PTRCOMP
5529 #include "scip/sorttpl.c" /*lint !e451*/
5530 
5531 /* SCIPsortPtrRealRealBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5532 #define SORTTPL_NAMEEXT     PtrRealRealBoolBool
5533 #define SORTTPL_KEYTYPE     void*
5534 #define SORTTPL_FIELD1TYPE  SCIP_Real
5535 #define SORTTPL_FIELD2TYPE  SCIP_Real
5536 #define SORTTPL_FIELD3TYPE  SCIP_Bool
5537 #define SORTTPL_FIELD4TYPE  SCIP_Bool
5538 #define SORTTPL_PTRCOMP
5539 #include "scip/sorttpl.c" /*lint !e451*/
5540 
5541 /* SCIPsortPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5542 #define SORTTPL_NAMEEXT     PtrRealRealIntBool
5543 #define SORTTPL_KEYTYPE     void*
5544 #define SORTTPL_FIELD1TYPE  SCIP_Real
5545 #define SORTTPL_FIELD2TYPE  SCIP_Real
5546 #define SORTTPL_FIELD3TYPE  int
5547 #define SORTTPL_FIELD4TYPE  SCIP_Bool
5548 #define SORTTPL_PTRCOMP
5549 #include "scip/sorttpl.c" /*lint !e451*/
5550 
5551 /* SCIPsortPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5552 #define SORTTPL_NAMEEXT     PtrRealBool
5553 #define SORTTPL_KEYTYPE     void*
5554 #define SORTTPL_FIELD1TYPE  SCIP_Real
5555 #define SORTTPL_FIELD2TYPE  SCIP_Bool
5556 #define SORTTPL_PTRCOMP
5557 #include "scip/sorttpl.c" /*lint !e451*/
5558 
5559 
5560 /* SCIPsortPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5561 #define SORTTPL_NAMEEXT     PtrPtrInt
5562 #define SORTTPL_KEYTYPE     void*
5563 #define SORTTPL_FIELD1TYPE  void*
5564 #define SORTTPL_FIELD2TYPE  int
5565 #define SORTTPL_PTRCOMP
5566 #include "scip/sorttpl.c" /*lint !e451*/
5567 
5568 
5569 /* SCIPsortPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5570 #define SORTTPL_NAMEEXT     PtrPtrReal
5571 #define SORTTPL_KEYTYPE     void*
5572 #define SORTTPL_FIELD1TYPE  void*
5573 #define SORTTPL_FIELD2TYPE  SCIP_Real
5574 #define SORTTPL_PTRCOMP
5575 #include "scip/sorttpl.c" /*lint !e451*/
5576 
5577 
5578 /* SCIPsortPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5579 #define SORTTPL_NAMEEXT     PtrRealIntInt
5580 #define SORTTPL_KEYTYPE     void*
5581 #define SORTTPL_FIELD1TYPE  SCIP_Real
5582 #define SORTTPL_FIELD2TYPE  int
5583 #define SORTTPL_FIELD3TYPE  int
5584 #define SORTTPL_PTRCOMP
5585 #include "scip/sorttpl.c" /*lint !e451*/
5586 
5587 
5588 /* SCIPsortPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5589 #define SORTTPL_NAMEEXT     PtrPtrIntInt
5590 #define SORTTPL_KEYTYPE     void*
5591 #define SORTTPL_FIELD1TYPE  void*
5592 #define SORTTPL_FIELD2TYPE  int
5593 #define SORTTPL_FIELD3TYPE  int
5594 #define SORTTPL_PTRCOMP
5595 #include "scip/sorttpl.c" /*lint !e451*/
5596 
5597 
5598 /* SCIPsortPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5599 #define SORTTPL_NAMEEXT     PtrPtrRealInt
5600 #define SORTTPL_KEYTYPE     void*
5601 #define SORTTPL_FIELD1TYPE  void*
5602 #define SORTTPL_FIELD2TYPE  SCIP_Real
5603 #define SORTTPL_FIELD3TYPE  int
5604 #define SORTTPL_PTRCOMP
5605 #include "scip/sorttpl.c" /*lint !e451*/
5606 
5607 
5608 /* SCIPsortPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5609 #define SORTTPL_NAMEEXT     PtrPtrRealBool
5610 #define SORTTPL_KEYTYPE     void*
5611 #define SORTTPL_FIELD1TYPE  void*
5612 #define SORTTPL_FIELD2TYPE  SCIP_Real
5613 #define SORTTPL_FIELD3TYPE  SCIP_Bool
5614 #define SORTTPL_PTRCOMP
5615 #include "scip/sorttpl.c" /*lint !e451*/
5616 
5617 
5618 /* SCIPsortPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5619 #define SORTTPL_NAMEEXT     PtrPtrLongInt
5620 #define SORTTPL_KEYTYPE     void*
5621 #define SORTTPL_FIELD1TYPE  void*
5622 #define SORTTPL_FIELD2TYPE  SCIP_Longint
5623 #define SORTTPL_FIELD3TYPE  int
5624 #define SORTTPL_PTRCOMP
5625 #include "scip/sorttpl.c" /*lint !e451*/
5626 
5627 
5628 /* SCIPsortPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5629 #define SORTTPL_NAMEEXT     PtrPtrLongIntInt
5630 #define SORTTPL_KEYTYPE     void*
5631 #define SORTTPL_FIELD1TYPE  void*
5632 #define SORTTPL_FIELD2TYPE  SCIP_Longint
5633 #define SORTTPL_FIELD3TYPE  int
5634 #define SORTTPL_FIELD4TYPE  int
5635 #define SORTTPL_PTRCOMP
5636 #include "scip/sorttpl.c" /*lint !e451*/
5637 
5638 
5639 /* SCIPsortReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5640 #define SORTTPL_NAMEEXT     Real
5641 #define SORTTPL_KEYTYPE     SCIP_Real
5642 #include "scip/sorttpl.c" /*lint !e451*/
5643 
5644 
5645 /* SCIPsortRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5646 #define SORTTPL_NAMEEXT     RealBoolPtr
5647 #define SORTTPL_KEYTYPE     SCIP_Real
5648 #define SORTTPL_FIELD1TYPE  SCIP_Bool
5649 #define SORTTPL_FIELD2TYPE  void*
5650 #include "scip/sorttpl.c" /*lint !e451*/
5651 
5652 
5653 /* SCIPsortRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5654 #define SORTTPL_NAMEEXT     RealPtr
5655 #define SORTTPL_KEYTYPE     SCIP_Real
5656 #define SORTTPL_FIELD1TYPE  void*
5657 #include "scip/sorttpl.c" /*lint !e451*/
5658 
5659 
5660 /* SCIPsortRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5661 #define SORTTPL_NAMEEXT     RealInt
5662 #define SORTTPL_KEYTYPE     SCIP_Real
5663 #define SORTTPL_FIELD1TYPE  int
5664 #include "scip/sorttpl.c" /*lint !e451*/
5665 
5666 
5667 /* SCIPsortRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5668 #define SORTTPL_NAMEEXT     RealIntInt
5669 #define SORTTPL_KEYTYPE     SCIP_Real
5670 #define SORTTPL_FIELD1TYPE  int
5671 #define SORTTPL_FIELD2TYPE  int
5672 #include "scip/sorttpl.c" /*lint !e451*/
5673 
5674 
5675 /* SCIPsortRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5676 #define SORTTPL_NAMEEXT     RealIntLong
5677 #define SORTTPL_KEYTYPE     SCIP_Real
5678 #define SORTTPL_FIELD1TYPE  int
5679 #define SORTTPL_FIELD2TYPE  SCIP_Longint
5680 #include "scip/sorttpl.c" /*lint !e451*/
5681 
5682 
5683 /* SCIPsortRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5684 #define SORTTPL_NAMEEXT     RealIntPtr
5685 #define SORTTPL_KEYTYPE     SCIP_Real
5686 #define SORTTPL_FIELD1TYPE  int
5687 #define SORTTPL_FIELD2TYPE  void*
5688 #include "scip/sorttpl.c" /*lint !e451*/
5689 
5690 
5691 /* SCIPsortRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5692 #define SORTTPL_NAMEEXT     RealRealPtr
5693 #define SORTTPL_KEYTYPE     SCIP_Real
5694 #define SORTTPL_FIELD1TYPE  SCIP_Real
5695 #define SORTTPL_FIELD2TYPE  void*
5696 #include "scip/sorttpl.c" /*lint !e451*/
5697 
5698 
5699 /* SCIPsortRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5700 #define SORTTPL_NAMEEXT     RealLongRealInt
5701 #define SORTTPL_KEYTYPE     SCIP_Real
5702 #define SORTTPL_FIELD1TYPE  SCIP_Longint
5703 #define SORTTPL_FIELD2TYPE  SCIP_Real
5704 #define SORTTPL_FIELD3TYPE  int
5705 #include "scip/sorttpl.c" /*lint !e451*/
5706 
5707 /* SCIPsortRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5708 #define SORTTPL_NAMEEXT     RealRealIntInt
5709 #define SORTTPL_KEYTYPE     SCIP_Real
5710 #define SORTTPL_FIELD1TYPE  SCIP_Real
5711 #define SORTTPL_FIELD2TYPE  int
5712 #define SORTTPL_FIELD3TYPE  int
5713 #include "scip/sorttpl.c" /*lint !e451*/
5714 
5715 
5716 /* SCIPsortRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5717 #define SORTTPL_NAMEEXT     RealRealRealInt
5718 #define SORTTPL_KEYTYPE     SCIP_Real
5719 #define SORTTPL_FIELD1TYPE  SCIP_Real
5720 #define SORTTPL_FIELD2TYPE  SCIP_Real
5721 #define SORTTPL_FIELD3TYPE  int
5722 #include "scip/sorttpl.c" /*lint !e451*/
5723 
5724 
5725 /* SCIPsortRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5726 #define SORTTPL_NAMEEXT     RealRealRealPtr
5727 #define SORTTPL_KEYTYPE     SCIP_Real
5728 #define SORTTPL_FIELD1TYPE  SCIP_Real
5729 #define SORTTPL_FIELD2TYPE  SCIP_Real
5730 #define SORTTPL_FIELD3TYPE  void*
5731 #include "scip/sorttpl.c" /*lint !e451*/
5732 
5733 
5734 /* SCIPsortRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5735 #define SORTTPL_NAMEEXT     RealPtrPtrInt
5736 #define SORTTPL_KEYTYPE     SCIP_Real
5737 #define SORTTPL_FIELD1TYPE  void*
5738 #define SORTTPL_FIELD2TYPE  void*
5739 #define SORTTPL_FIELD3TYPE  int
5740 #include "scip/sorttpl.c" /*lint !e451*/
5741 
5742 
5743 /* SCIPsortRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5744 #define SORTTPL_NAMEEXT     RealPtrPtrIntInt
5745 #define SORTTPL_KEYTYPE     SCIP_Real
5746 #define SORTTPL_FIELD1TYPE  void*
5747 #define SORTTPL_FIELD2TYPE  void*
5748 #define SORTTPL_FIELD3TYPE  int
5749 #define SORTTPL_FIELD4TYPE  int
5750 #include "scip/sorttpl.c" /*lint !e451*/
5751 
5752 
5753 /* SCIPsortRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5754 #define SORTTPL_NAMEEXT     RealRealRealBoolPtr
5755 #define SORTTPL_KEYTYPE     SCIP_Real
5756 #define SORTTPL_FIELD1TYPE  SCIP_Real
5757 #define SORTTPL_FIELD2TYPE  SCIP_Real
5758 #define SORTTPL_FIELD3TYPE  SCIP_Bool
5759 #define SORTTPL_FIELD4TYPE  void*
5760 #include "scip/sorttpl.c" /*lint !e451*/
5761 
5762 
5763 /* SCIPsortRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5764 #define SORTTPL_NAMEEXT     RealRealRealBoolBoolPtr
5765 #define SORTTPL_KEYTYPE     SCIP_Real
5766 #define SORTTPL_FIELD1TYPE  SCIP_Real
5767 #define SORTTPL_FIELD2TYPE  SCIP_Real
5768 #define SORTTPL_FIELD3TYPE  SCIP_Bool
5769 #define SORTTPL_FIELD4TYPE  SCIP_Bool
5770 #define SORTTPL_FIELD5TYPE  void*
5771 #include "scip/sorttpl.c" /*lint !e451*/
5772 
5773 
5774 /* SCIPsortInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5775 #define SORTTPL_NAMEEXT     Int
5776 #define SORTTPL_KEYTYPE     int
5777 #include "scip/sorttpl.c" /*lint !e451*/
5778 
5779 
5780 /* SCIPsortIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5781 #define SORTTPL_NAMEEXT     IntInt
5782 #define SORTTPL_KEYTYPE     int
5783 #define SORTTPL_FIELD1TYPE  int
5784 #include "scip/sorttpl.c" /*lint !e451*/
5785 
5786 
5787 /* SCIPsortIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5788 #define SORTTPL_NAMEEXT     IntReal
5789 #define SORTTPL_KEYTYPE     int
5790 #define SORTTPL_FIELD1TYPE  SCIP_Real
5791 #include "scip/sorttpl.c" /*lint !e451*/
5792 
5793 
5794 /* SCIPsortIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5795 #define SORTTPL_NAMEEXT     IntPtr
5796 #define SORTTPL_KEYTYPE     int
5797 #define SORTTPL_FIELD1TYPE  void*
5798 #include "scip/sorttpl.c" /*lint !e451*/
5799 
5800 
5801 /* SCIPsortIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5802 #define SORTTPL_NAMEEXT     IntIntInt
5803 #define SORTTPL_KEYTYPE     int
5804 #define SORTTPL_FIELD1TYPE  int
5805 #define SORTTPL_FIELD2TYPE  int
5806 #include "scip/sorttpl.c" /*lint !e451*/
5807 
5808 
5809 /* SCIPsortIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5810 #define SORTTPL_NAMEEXT     IntIntLong
5811 #define SORTTPL_KEYTYPE     int
5812 #define SORTTPL_FIELD1TYPE  int
5813 #define SORTTPL_FIELD2TYPE  SCIP_Longint
5814 #include "scip/sorttpl.c" /*lint !e451*/
5815 
5816 /* SCIPsortIntRealLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5817 #define SORTTPL_NAMEEXT     IntRealLong
5818 #define SORTTPL_KEYTYPE     int
5819 #define SORTTPL_FIELD1TYPE  SCIP_Real
5820 #define SORTTPL_FIELD2TYPE  SCIP_Longint
5821 #include "scip/sorttpl.c" /*lint !e451*/
5822 
5823 
5824 /* SCIPsortIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5825 #define SORTTPL_NAMEEXT     IntIntPtr
5826 #define SORTTPL_KEYTYPE     int
5827 #define SORTTPL_FIELD1TYPE  int
5828 #define SORTTPL_FIELD2TYPE  void*
5829 #include "scip/sorttpl.c" /*lint !e451*/
5830 
5831 
5832 /* SCIPsortIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5833 #define SORTTPL_NAMEEXT     IntIntReal
5834 #define SORTTPL_KEYTYPE     int
5835 #define SORTTPL_FIELD1TYPE  int
5836 #define SORTTPL_FIELD2TYPE  SCIP_Real
5837 #include "scip/sorttpl.c" /*lint !e451*/
5838 
5839 
5840 /* SCIPsortIntPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5841 #define SORTTPL_NAMEEXT     IntPtrReal
5842 #define SORTTPL_KEYTYPE     int
5843 #define SORTTPL_FIELD1TYPE  void*
5844 #define SORTTPL_FIELD2TYPE  SCIP_Real
5845 #include "scip/sorttpl.c" /*lint !e451*/
5846 
5847 
5848 /* SCIPsortIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5849 #define SORTTPL_NAMEEXT     IntIntIntPtr
5850 #define SORTTPL_KEYTYPE     int
5851 #define SORTTPL_FIELD1TYPE  int
5852 #define SORTTPL_FIELD2TYPE  int
5853 #define SORTTPL_FIELD3TYPE  void*
5854 #include "scip/sorttpl.c" /*lint !e451*/
5855 
5856 /* SCIPsortIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5857 #define SORTTPL_NAMEEXT     IntIntIntReal
5858 #define SORTTPL_KEYTYPE     int
5859 #define SORTTPL_FIELD1TYPE  int
5860 #define SORTTPL_FIELD2TYPE  int
5861 #define SORTTPL_FIELD3TYPE  SCIP_Real
5862 #include "scip/sorttpl.c" /*lint !e451*/
5863 
5864 /* SCIPsortIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5865 #define SORTTPL_NAMEEXT     IntPtrIntReal
5866 #define SORTTPL_KEYTYPE     int
5867 #define SORTTPL_FIELD1TYPE  void*
5868 #define SORTTPL_FIELD2TYPE  int
5869 #define SORTTPL_FIELD3TYPE  SCIP_Real
5870 #include "scip/sorttpl.c" /*lint !e451*/
5871 
5872 
5873 /* SCIPsortLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5874 #define SORTTPL_NAMEEXT     Long
5875 #define SORTTPL_KEYTYPE     SCIP_Longint
5876 #include "scip/sorttpl.c" /*lint !e451*/
5877 
5878 
5879 /* SCIPsortLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5880 #define SORTTPL_NAMEEXT     LongPtr
5881 #define SORTTPL_KEYTYPE     SCIP_Longint
5882 #define SORTTPL_FIELD1TYPE  void*
5883 #include "scip/sorttpl.c" /*lint !e451*/
5884 
5885 
5886 /* SCIPsortLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5887 #define SORTTPL_NAMEEXT     LongPtrInt
5888 #define SORTTPL_KEYTYPE     SCIP_Longint
5889 #define SORTTPL_FIELD1TYPE  void*
5890 #define SORTTPL_FIELD2TYPE  int
5891 #include "scip/sorttpl.c" /*lint !e451*/
5892 
5893 
5894 /* SCIPsortLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5895 #define SORTTPL_NAMEEXT     LongPtrRealBool
5896 #define SORTTPL_KEYTYPE     SCIP_Longint
5897 #define SORTTPL_FIELD1TYPE  void*
5898 #define SORTTPL_FIELD2TYPE  SCIP_Real
5899 #define SORTTPL_FIELD3TYPE  SCIP_Bool
5900 #include "scip/sorttpl.c" /*lint !e451*/
5901 
5902 
5903 /* SCIPsortLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5904 #define SORTTPL_NAMEEXT     LongPtrRealRealBool
5905 #define SORTTPL_KEYTYPE     SCIP_Longint
5906 #define SORTTPL_FIELD1TYPE  void*
5907 #define SORTTPL_FIELD2TYPE  SCIP_Real
5908 #define SORTTPL_FIELD3TYPE  SCIP_Real
5909 #define SORTTPL_FIELD4TYPE  SCIP_Bool
5910 #include "scip/sorttpl.c" /*lint !e451*/
5911 
5912 
5913 /* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5914 #define SORTTPL_NAMEEXT     LongPtrRealRealIntBool
5915 #define SORTTPL_KEYTYPE     SCIP_Longint
5916 #define SORTTPL_FIELD1TYPE  void*
5917 #define SORTTPL_FIELD2TYPE  SCIP_Real
5918 #define SORTTPL_FIELD3TYPE  SCIP_Real
5919 #define SORTTPL_FIELD4TYPE  int
5920 #define SORTTPL_FIELD5TYPE  SCIP_Bool
5921 #include "scip/sorttpl.c" /*lint !e451*/
5922 
5923 
5924 /* SCIPsortLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5925 #define SORTTPL_NAMEEXT     LongPtrPtrInt
5926 #define SORTTPL_KEYTYPE     SCIP_Longint
5927 #define SORTTPL_FIELD1TYPE  void*
5928 #define SORTTPL_FIELD2TYPE  void*
5929 #define SORTTPL_FIELD3TYPE  int
5930 #include "scip/sorttpl.c" /*lint !e451*/
5931 
5932 
5933 /* SCIPsortLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5934 #define SORTTPL_NAMEEXT     LongPtrPtrIntInt
5935 #define SORTTPL_KEYTYPE     SCIP_Longint
5936 #define SORTTPL_FIELD1TYPE  void*
5937 #define SORTTPL_FIELD2TYPE  void*
5938 #define SORTTPL_FIELD3TYPE  int
5939 #define SORTTPL_FIELD4TYPE  int
5940 #include "scip/sorttpl.c" /*lint !e451*/
5941 
5942 
5943 /* SCIPsortLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5944 #define SORTTPL_NAMEEXT     LongPtrPtrBoolInt
5945 #define SORTTPL_KEYTYPE     SCIP_Longint
5946 #define SORTTPL_FIELD1TYPE  void*
5947 #define SORTTPL_FIELD2TYPE  void*
5948 #define SORTTPL_FIELD3TYPE  SCIP_Bool
5949 #define SORTTPL_FIELD4TYPE  int
5950 #include "scip/sorttpl.c" /*lint !e451*/
5951 
5952 
5953 /* SCIPsortPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5954 #define SORTTPL_NAMEEXT     PtrIntIntBoolBool
5955 #define SORTTPL_KEYTYPE     void*
5956 #define SORTTPL_FIELD1TYPE  int
5957 #define SORTTPL_FIELD2TYPE  int
5958 #define SORTTPL_FIELD3TYPE  SCIP_Bool
5959 #define SORTTPL_FIELD4TYPE  SCIP_Bool
5960 #define SORTTPL_PTRCOMP
5961 #include "scip/sorttpl.c" /*lint !e451*/
5962 
5963 
5964 /* SCIPsortIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5965 #define SORTTPL_NAMEEXT     IntPtrIntIntBoolBool
5966 #define SORTTPL_KEYTYPE     int
5967 #define SORTTPL_FIELD1TYPE  void*
5968 #define SORTTPL_FIELD2TYPE  int
5969 #define SORTTPL_FIELD3TYPE  int
5970 #define SORTTPL_FIELD4TYPE  SCIP_Bool
5971 #define SORTTPL_FIELD5TYPE  SCIP_Bool
5972 #include "scip/sorttpl.c" /*lint !e451*/
5973 
5974 
5975 /* now all downwards-sorting methods */
5976 
5977 
5978 /** sort an indexed element set in non-increasing order, resulting in a permutation index array */
SCIPsortDown(int * perm,SCIP_DECL_SORTINDCOMP ((* indcomp)),void * dataptr,int len)5979 void SCIPsortDown(
5980    int*                  perm,               /**< pointer to store the resulting permutation */
5981    SCIP_DECL_SORTINDCOMP((*indcomp)),        /**< data element comparator */
5982    void*                 dataptr,            /**< pointer to data field that is given to the external compare method */
5983    int                   len                 /**< number of elements to be sorted (valid index range) */
5984    )
5985 {
5986    int pos;
5987 
5988    assert(indcomp != NULL);
5989    assert(len == 0 || perm != NULL);
5990 
5991    /* create identity permutation */
5992    for( pos = 0; pos < len; ++pos )
5993       perm[pos] = pos;
5994 
5995    SCIPsortDownInd(perm, indcomp, dataptr, len);
5996 }
5997 
5998 
5999 /* SCIPsortDownInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6000 #define SORTTPL_NAMEEXT     DownInd
6001 #define SORTTPL_KEYTYPE     int
6002 #define SORTTPL_INDCOMP
6003 #define SORTTPL_BACKWARDS
6004 #include "scip/sorttpl.c" /*lint !e451*/
6005 
6006 
6007 /* SCIPsortDownPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6008 #define SORTTPL_NAMEEXT     DownPtr
6009 #define SORTTPL_KEYTYPE     void*
6010 #define SORTTPL_PTRCOMP
6011 #define SORTTPL_BACKWARDS
6012 #include "scip/sorttpl.c" /*lint !e451*/
6013 
6014 
6015 /* SCIPsortDownPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6016 #define SORTTPL_NAMEEXT     DownPtrPtr
6017 #define SORTTPL_KEYTYPE     void*
6018 #define SORTTPL_FIELD1TYPE  void*
6019 #define SORTTPL_PTRCOMP
6020 #define SORTTPL_BACKWARDS
6021 #include "scip/sorttpl.c" /*lint !e451*/
6022 
6023 
6024 /* SCIPsortDownPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6025 #define SORTTPL_NAMEEXT     DownPtrReal
6026 #define SORTTPL_KEYTYPE     void*
6027 #define SORTTPL_FIELD1TYPE  SCIP_Real
6028 #define SORTTPL_PTRCOMP
6029 #define SORTTPL_BACKWARDS
6030 #include "scip/sorttpl.c" /*lint !e451*/
6031 
6032 
6033 /* SCIPsortDownPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6034 #define SORTTPL_NAMEEXT     DownPtrInt
6035 #define SORTTPL_KEYTYPE     void*
6036 #define SORTTPL_FIELD1TYPE  int
6037 #define SORTTPL_PTRCOMP
6038 #define SORTTPL_BACKWARDS
6039 #include "scip/sorttpl.c" /*lint !e451*/
6040 
6041 /* SCIPsortDownPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6042 #define SORTTPL_NAMEEXT     DownPtrBool
6043 #define SORTTPL_KEYTYPE     void*
6044 #define SORTTPL_FIELD1TYPE  SCIP_Bool
6045 #define SORTTPL_PTRCOMP
6046 #define SORTTPL_BACKWARDS
6047 #include "scip/sorttpl.c" /*lint !e451*/
6048 
6049 /* SCIPsortDownPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6050 #define SORTTPL_NAMEEXT     DownPtrIntInt
6051 #define SORTTPL_KEYTYPE     void*
6052 #define SORTTPL_FIELD1TYPE  int
6053 #define SORTTPL_FIELD2TYPE  int
6054 #define SORTTPL_PTRCOMP
6055 #define SORTTPL_BACKWARDS
6056 #include "scip/sorttpl.c" /*lint !e451*/
6057 
6058 
6059 /* SCIPsortDownPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6060 #define SORTTPL_NAMEEXT     DownPtrRealInt
6061 #define SORTTPL_KEYTYPE     void*
6062 #define SORTTPL_FIELD1TYPE  SCIP_Real
6063 #define SORTTPL_FIELD2TYPE  int
6064 #define SORTTPL_PTRCOMP
6065 #define SORTTPL_BACKWARDS
6066 #include "scip/sorttpl.c" /*lint !e451*/
6067 
6068 
6069 /* SCIPsortDownPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6070 #define SORTTPL_NAMEEXT     DownPtrRealBool
6071 #define SORTTPL_KEYTYPE     void*
6072 #define SORTTPL_FIELD1TYPE  SCIP_Real
6073 #define SORTTPL_FIELD2TYPE  SCIP_Bool
6074 #define SORTTPL_PTRCOMP
6075 #define SORTTPL_BACKWARDS
6076 #include "scip/sorttpl.c" /*lint !e451*/
6077 
6078 
6079 /* SCIPsortDownPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6080 #define SORTTPL_NAMEEXT     DownPtrPtrInt
6081 #define SORTTPL_KEYTYPE     void*
6082 #define SORTTPL_FIELD1TYPE  void*
6083 #define SORTTPL_FIELD2TYPE  int
6084 #define SORTTPL_PTRCOMP
6085 #define SORTTPL_BACKWARDS
6086 #include "scip/sorttpl.c" /*lint !e451*/
6087 
6088 
6089 /* SCIPsortDownPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6090 #define SORTTPL_NAMEEXT     DownPtrPtrReal
6091 #define SORTTPL_KEYTYPE     void*
6092 #define SORTTPL_FIELD1TYPE  void*
6093 #define SORTTPL_FIELD2TYPE  SCIP_Real
6094 #define SORTTPL_PTRCOMP
6095 #define SORTTPL_BACKWARDS
6096 #include "scip/sorttpl.c" /*lint !e451*/
6097 
6098 
6099 /* SCIPsortDownPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6100 #define SORTTPL_NAMEEXT     DownPtrRealIntInt
6101 #define SORTTPL_KEYTYPE     void*
6102 #define SORTTPL_FIELD1TYPE  SCIP_Real
6103 #define SORTTPL_FIELD2TYPE  int
6104 #define SORTTPL_FIELD3TYPE  int
6105 #define SORTTPL_PTRCOMP
6106 #define SORTTPL_BACKWARDS
6107 #include "scip/sorttpl.c" /*lint !e451*/
6108 
6109 
6110 /* SCIPsortDownPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6111 #define SORTTPL_NAMEEXT     DownPtrPtrIntInt
6112 #define SORTTPL_KEYTYPE     void*
6113 #define SORTTPL_FIELD1TYPE  void*
6114 #define SORTTPL_FIELD2TYPE  int
6115 #define SORTTPL_FIELD3TYPE  int
6116 #define SORTTPL_PTRCOMP
6117 #define SORTTPL_BACKWARDS
6118 #include "scip/sorttpl.c" /*lint !e451*/
6119 
6120 
6121 /* SCIPsortDownPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6122 #define SORTTPL_NAMEEXT     DownPtrPtrRealInt
6123 #define SORTTPL_KEYTYPE     void*
6124 #define SORTTPL_FIELD1TYPE  void*
6125 #define SORTTPL_FIELD2TYPE  SCIP_Real
6126 #define SORTTPL_FIELD3TYPE  int
6127 #define SORTTPL_PTRCOMP
6128 #define SORTTPL_BACKWARDS
6129 #include "scip/sorttpl.c" /*lint !e451*/
6130 
6131 
6132 /* SCIPsortDownPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6133 #define SORTTPL_NAMEEXT     DownPtrPtrRealBool
6134 #define SORTTPL_KEYTYPE     void*
6135 #define SORTTPL_FIELD1TYPE  void*
6136 #define SORTTPL_FIELD2TYPE  SCIP_Real
6137 #define SORTTPL_FIELD3TYPE  SCIP_Bool
6138 #define SORTTPL_PTRCOMP
6139 #define SORTTPL_BACKWARDS
6140 #include "scip/sorttpl.c" /*lint !e451*/
6141 
6142 
6143 /* SCIPsortDownPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6144 #define SORTTPL_NAMEEXT     DownPtrPtrLongInt
6145 #define SORTTPL_KEYTYPE     void*
6146 #define SORTTPL_FIELD1TYPE  void*
6147 #define SORTTPL_FIELD2TYPE  SCIP_Longint
6148 #define SORTTPL_FIELD3TYPE  int
6149 #define SORTTPL_PTRCOMP
6150 #define SORTTPL_BACKWARDS
6151 #include "scip/sorttpl.c" /*lint !e451*/
6152 
6153 
6154 /* SCIPsortDownPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6155 #define SORTTPL_NAMEEXT     DownPtrPtrLongIntInt
6156 #define SORTTPL_KEYTYPE     void*
6157 #define SORTTPL_FIELD1TYPE  void*
6158 #define SORTTPL_FIELD2TYPE  SCIP_Longint
6159 #define SORTTPL_FIELD3TYPE  int
6160 #define SORTTPL_FIELD4TYPE  int
6161 #define SORTTPL_PTRCOMP
6162 #define SORTTPL_BACKWARDS
6163 #include "scip/sorttpl.c" /*lint !e451*/
6164 
6165 
6166 /* SCIPsortDownReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6167 #define SORTTPL_NAMEEXT     DownReal
6168 #define SORTTPL_KEYTYPE     SCIP_Real
6169 #define SORTTPL_BACKWARDS
6170 #include "scip/sorttpl.c" /*lint !e451*/
6171 
6172 
6173 /* SCIPsortDownRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6174 #define SORTTPL_NAMEEXT     DownRealBoolPtr
6175 #define SORTTPL_KEYTYPE     SCIP_Real
6176 #define SORTTPL_FIELD1TYPE  SCIP_Bool
6177 #define SORTTPL_FIELD2TYPE  void*
6178 #define SORTTPL_BACKWARDS
6179 #include "scip/sorttpl.c" /*lint !e451*/
6180 
6181 
6182 /* SCIPsortDownRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6183 #define SORTTPL_NAMEEXT     DownRealPtr
6184 #define SORTTPL_KEYTYPE     SCIP_Real
6185 #define SORTTPL_FIELD1TYPE  void*
6186 #define SORTTPL_BACKWARDS
6187 #include "scip/sorttpl.c" /*lint !e451*/
6188 
6189 
6190 /* SCIPsortDownRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6191 #define SORTTPL_NAMEEXT     DownRealInt
6192 #define SORTTPL_KEYTYPE     SCIP_Real
6193 #define SORTTPL_FIELD1TYPE  int
6194 #define SORTTPL_BACKWARDS
6195 #include "scip/sorttpl.c" /*lint !e451*/
6196 
6197 /* SCIPsortDownRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6198 #define SORTTPL_NAMEEXT     DownRealIntInt
6199 #define SORTTPL_KEYTYPE     SCIP_Real
6200 #define SORTTPL_FIELD1TYPE  int
6201 #define SORTTPL_FIELD2TYPE  int
6202 #define SORTTPL_BACKWARDS
6203 #include "scip/sorttpl.c" /*lint !e451*/
6204 
6205 /* SCIPsortDownRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6206 #define SORTTPL_NAMEEXT     DownRealIntLong
6207 #define SORTTPL_KEYTYPE     SCIP_Real
6208 #define SORTTPL_FIELD1TYPE  int
6209 #define SORTTPL_FIELD2TYPE  SCIP_Longint
6210 #define SORTTPL_BACKWARDS
6211 #include "scip/sorttpl.c" /*lint !e451*/
6212 
6213 
6214 /* SCIPsortDownRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6215 #define SORTTPL_NAMEEXT     DownRealIntPtr
6216 #define SORTTPL_KEYTYPE     SCIP_Real
6217 #define SORTTPL_FIELD1TYPE  int
6218 #define SORTTPL_FIELD2TYPE  void*
6219 #define SORTTPL_BACKWARDS
6220 #include "scip/sorttpl.c" /*lint !e451*/
6221 
6222 
6223 /* SCIPsortDownRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6224 #define SORTTPL_NAMEEXT     DownRealPtrPtr
6225 #define SORTTPL_KEYTYPE     SCIP_Real
6226 #define SORTTPL_FIELD1TYPE  void*
6227 #define SORTTPL_FIELD2TYPE  void*
6228 #define SORTTPL_BACKWARDS
6229 #include "scip/sorttpl.c" /*lint !e451*/
6230 
6231 /* SCIPsortDownRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6232 #define SORTTPL_NAMEEXT     DownRealRealInt
6233 #define SORTTPL_KEYTYPE     SCIP_Real
6234 #define SORTTPL_FIELD1TYPE  SCIP_Real
6235 #define SORTTPL_FIELD2TYPE  int
6236 #define SORTTPL_BACKWARDS
6237 #include "scip/sorttpl.c" /*lint !e451*/
6238 
6239 /* SCIPsortDownRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6240 #define SORTTPL_NAMEEXT     DownRealRealPtr
6241 #define SORTTPL_KEYTYPE     SCIP_Real
6242 #define SORTTPL_FIELD1TYPE  SCIP_Real
6243 #define SORTTPL_FIELD2TYPE  void*
6244 #define SORTTPL_BACKWARDS
6245 #include "scip/sorttpl.c" /*lint !e451*/
6246 
6247 /* SCIPsortDownRealRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6248 #define SORTTPL_NAMEEXT     DownRealRealPtrPtr
6249 #define SORTTPL_KEYTYPE     SCIP_Real
6250 #define SORTTPL_FIELD1TYPE  SCIP_Real
6251 #define SORTTPL_FIELD2TYPE  void*
6252 #define SORTTPL_FIELD3TYPE  void*
6253 #define SORTTPL_BACKWARDS
6254 #include "scip/sorttpl.c" /*lint !e451*/
6255 
6256 
6257 /* SCIPsortDownRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6258 #define SORTTPL_NAMEEXT     DownRealLongRealInt
6259 #define SORTTPL_KEYTYPE     SCIP_Real
6260 #define SORTTPL_FIELD1TYPE  SCIP_Longint
6261 #define SORTTPL_FIELD2TYPE  SCIP_Real
6262 #define SORTTPL_FIELD3TYPE  int
6263 #define SORTTPL_BACKWARDS
6264 #include "scip/sorttpl.c" /*lint !e451*/
6265 
6266 
6267 /* SCIPsortDownRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6268 #define SORTTPL_NAMEEXT     DownRealRealIntInt
6269 #define SORTTPL_KEYTYPE     SCIP_Real
6270 #define SORTTPL_FIELD1TYPE  SCIP_Real
6271 #define SORTTPL_FIELD2TYPE  int
6272 #define SORTTPL_FIELD3TYPE  int
6273 #define SORTTPL_BACKWARDS
6274 #include "scip/sorttpl.c" /*lint !e451*/
6275 
6276 
6277 /* SCIPsortDownRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6278 #define SORTTPL_NAMEEXT     DownRealRealRealInt
6279 #define SORTTPL_KEYTYPE     SCIP_Real
6280 #define SORTTPL_FIELD1TYPE  SCIP_Real
6281 #define SORTTPL_FIELD2TYPE  SCIP_Real
6282 #define SORTTPL_FIELD3TYPE  int
6283 #define SORTTPL_BACKWARDS
6284 #include "scip/sorttpl.c" /*lint !e451*/
6285 
6286 
6287 /* SCIPsortDownRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6288 #define SORTTPL_NAMEEXT     DownRealRealRealPtr
6289 #define SORTTPL_KEYTYPE     SCIP_Real
6290 #define SORTTPL_FIELD1TYPE  SCIP_Real
6291 #define SORTTPL_FIELD2TYPE  SCIP_Real
6292 #define SORTTPL_FIELD3TYPE  void*
6293 #define SORTTPL_BACKWARDS
6294 #include "scip/sorttpl.c" /*lint !e451*/
6295 
6296 
6297 /* SCIPsortDownRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6298 #define SORTTPL_NAMEEXT     DownRealPtrPtrInt
6299 #define SORTTPL_KEYTYPE     SCIP_Real
6300 #define SORTTPL_FIELD1TYPE  void*
6301 #define SORTTPL_FIELD2TYPE  void*
6302 #define SORTTPL_FIELD3TYPE  int
6303 #define SORTTPL_BACKWARDS
6304 #include "scip/sorttpl.c" /*lint !e451*/
6305 
6306 /* SCIPsortDownRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6307 #define SORTTPL_NAMEEXT     DownRealPtrPtrIntInt
6308 #define SORTTPL_KEYTYPE     SCIP_Real
6309 #define SORTTPL_FIELD1TYPE  void*
6310 #define SORTTPL_FIELD2TYPE  void*
6311 #define SORTTPL_FIELD3TYPE  int
6312 #define SORTTPL_FIELD4TYPE  int
6313 #define SORTTPL_BACKWARDS
6314 #include "scip/sorttpl.c" /*lint !e451*/
6315 
6316 
6317 /* SCIPsortDownRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6318 #define SORTTPL_NAMEEXT     DownRealRealRealBoolPtr
6319 #define SORTTPL_KEYTYPE     SCIP_Real
6320 #define SORTTPL_FIELD1TYPE  SCIP_Real
6321 #define SORTTPL_FIELD2TYPE  SCIP_Real
6322 #define SORTTPL_FIELD3TYPE  SCIP_Bool
6323 #define SORTTPL_FIELD4TYPE  void*
6324 #define SORTTPL_BACKWARDS
6325 #include "scip/sorttpl.c" /*lint !e451*/
6326 
6327 
6328 /* SCIPsortDownRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6329 #define SORTTPL_NAMEEXT     DownRealRealRealBoolBoolPtr
6330 #define SORTTPL_KEYTYPE     SCIP_Real
6331 #define SORTTPL_FIELD1TYPE  SCIP_Real
6332 #define SORTTPL_FIELD2TYPE  SCIP_Real
6333 #define SORTTPL_FIELD3TYPE  SCIP_Bool
6334 #define SORTTPL_FIELD4TYPE  SCIP_Bool
6335 #define SORTTPL_FIELD5TYPE  void*
6336 #include "scip/sorttpl.c" /*lint !e451*/
6337 
6338 
6339 /* SCIPsortDownInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6340 #define SORTTPL_NAMEEXT     DownInt
6341 #define SORTTPL_KEYTYPE     int
6342 #define SORTTPL_BACKWARDS
6343 #include "scip/sorttpl.c" /*lint !e451*/
6344 
6345 
6346 /* SCIPsortDownIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6347 #define SORTTPL_NAMEEXT     DownIntInt
6348 #define SORTTPL_KEYTYPE     int
6349 #define SORTTPL_FIELD1TYPE  int
6350 #define SORTTPL_BACKWARDS
6351 #include "scip/sorttpl.c" /*lint !e451*/
6352 
6353 
6354 /* SCIPsortDownIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6355 #define SORTTPL_NAMEEXT     DownIntIntReal
6356 #define SORTTPL_KEYTYPE     int
6357 #define SORTTPL_FIELD1TYPE  int
6358 #define SORTTPL_FIELD2TYPE  SCIP_Real
6359 #define SORTTPL_BACKWARDS
6360 #include "scip/sorttpl.c" /*lint !e451*/
6361 
6362 
6363 /* SCIPsortDownIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6364 #define SORTTPL_NAMEEXT     DownIntReal
6365 #define SORTTPL_KEYTYPE     int
6366 #define SORTTPL_FIELD1TYPE  SCIP_Real
6367 #define SORTTPL_BACKWARDS
6368 #include "scip/sorttpl.c" /*lint !e451*/
6369 
6370 
6371 /* SCIPsortDownIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6372 #define SORTTPL_NAMEEXT     DownIntPtr
6373 #define SORTTPL_KEYTYPE     int
6374 #define SORTTPL_FIELD1TYPE  void*
6375 #define SORTTPL_BACKWARDS
6376 #include "scip/sorttpl.c" /*lint !e451*/
6377 
6378 
6379 /* SCIPsortDownIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6380 #define SORTTPL_NAMEEXT     DownIntIntInt
6381 #define SORTTPL_KEYTYPE     int
6382 #define SORTTPL_FIELD1TYPE  int
6383 #define SORTTPL_FIELD2TYPE  int
6384 #define SORTTPL_BACKWARDS
6385 #include "scip/sorttpl.c" /*lint !e451*/
6386 
6387 
6388 /* SCIPsortDownIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6389 #define SORTTPL_NAMEEXT     DownIntIntLong
6390 #define SORTTPL_KEYTYPE     int
6391 #define SORTTPL_FIELD1TYPE  int
6392 #define SORTTPL_FIELD2TYPE  SCIP_Longint
6393 #define SORTTPL_BACKWARDS
6394 #include "scip/sorttpl.c" /*lint !e451*/
6395 
6396 
6397 /* SCIPsortDownIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6398 #define SORTTPL_NAMEEXT     DownIntIntPtr
6399 #define SORTTPL_KEYTYPE     int
6400 #define SORTTPL_FIELD1TYPE  int
6401 #define SORTTPL_FIELD2TYPE  void*
6402 #define SORTTPL_BACKWARDS
6403 #include "scip/sorttpl.c" /*lint !e451*/
6404 
6405 
6406 /* SCIPsortDownIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6407 #define SORTTPL_NAMEEXT     DownIntIntIntPtr
6408 #define SORTTPL_KEYTYPE     int
6409 #define SORTTPL_FIELD1TYPE  int
6410 #define SORTTPL_FIELD2TYPE  int
6411 #define SORTTPL_FIELD3TYPE  void*
6412 #define SORTTPL_BACKWARDS
6413 #include "scip/sorttpl.c" /*lint !e451*/
6414 
6415 
6416 /* SCIPsortDownIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6417 #define SORTTPL_NAMEEXT     DownIntPtrIntReal
6418 #define SORTTPL_KEYTYPE     int
6419 #define SORTTPL_FIELD1TYPE  void*
6420 #define SORTTPL_FIELD2TYPE  int
6421 #define SORTTPL_FIELD3TYPE  SCIP_Real
6422 #define SORTTPL_BACKWARDS
6423 #include "scip/sorttpl.c" /*lint !e451*/
6424 
6425 
6426 /* SCIPsortDownLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6427 #define SORTTPL_NAMEEXT     DownLong
6428 #define SORTTPL_KEYTYPE     SCIP_Longint
6429 #define SORTTPL_BACKWARDS
6430 #include "scip/sorttpl.c" /*lint !e451*/
6431 
6432 
6433 /* SCIPsortDownLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6434 #define SORTTPL_NAMEEXT     DownLongPtr
6435 #define SORTTPL_KEYTYPE     SCIP_Longint
6436 #define SORTTPL_FIELD1TYPE  void*
6437 #define SORTTPL_BACKWARDS
6438 #include "scip/sorttpl.c" /*lint !e451*/
6439 
6440 
6441 /* SCIPsortDownLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6442 #define SORTTPL_NAMEEXT     DownLongPtrInt
6443 #define SORTTPL_KEYTYPE     SCIP_Longint
6444 #define SORTTPL_FIELD1TYPE  void*
6445 #define SORTTPL_FIELD2TYPE  int
6446 #define SORTTPL_BACKWARDS
6447 #include "scip/sorttpl.c" /*lint !e451*/
6448 
6449 
6450 /* SCIPsortDownLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6451 #define SORTTPL_NAMEEXT     DownLongPtrRealBool
6452 #define SORTTPL_KEYTYPE     SCIP_Longint
6453 #define SORTTPL_FIELD1TYPE  void*
6454 #define SORTTPL_FIELD2TYPE  SCIP_Real
6455 #define SORTTPL_FIELD3TYPE  SCIP_Bool
6456 #define SORTTPL_BACKWARDS
6457 #include "scip/sorttpl.c" /*lint !e451*/
6458 
6459 
6460 /* SCIPsortDownLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6461 #define SORTTPL_NAMEEXT     DownLongPtrRealRealBool
6462 #define SORTTPL_KEYTYPE     SCIP_Longint
6463 #define SORTTPL_FIELD1TYPE  void*
6464 #define SORTTPL_FIELD2TYPE  SCIP_Real
6465 #define SORTTPL_FIELD3TYPE  SCIP_Real
6466 #define SORTTPL_FIELD4TYPE  SCIP_Bool
6467 #define SORTTPL_BACKWARDS
6468 #include "scip/sorttpl.c" /*lint !e451*/
6469 
6470 
6471 /* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6472 #define SORTTPL_NAMEEXT     DownLongPtrRealRealIntBool
6473 #define SORTTPL_KEYTYPE     SCIP_Longint
6474 #define SORTTPL_FIELD1TYPE  void*
6475 #define SORTTPL_FIELD2TYPE  SCIP_Real
6476 #define SORTTPL_FIELD3TYPE  SCIP_Real
6477 #define SORTTPL_FIELD4TYPE  int
6478 #define SORTTPL_FIELD5TYPE  SCIP_Bool
6479 #define SORTTPL_BACKWARDS
6480 #include "scip/sorttpl.c" /*lint !e451*/
6481 
6482 
6483 /* SCIPsortDownLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6484 #define SORTTPL_NAMEEXT     DownLongPtrPtrInt
6485 #define SORTTPL_KEYTYPE     SCIP_Longint
6486 #define SORTTPL_FIELD1TYPE  void*
6487 #define SORTTPL_FIELD2TYPE  void*
6488 #define SORTTPL_FIELD3TYPE  int
6489 #define SORTTPL_BACKWARDS
6490 #include "scip/sorttpl.c" /*lint !e451*/
6491 
6492 
6493 /* SCIPsortDownLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6494 #define SORTTPL_NAMEEXT     DownLongPtrPtrIntInt
6495 #define SORTTPL_KEYTYPE     SCIP_Longint
6496 #define SORTTPL_FIELD1TYPE  void*
6497 #define SORTTPL_FIELD2TYPE  void*
6498 #define SORTTPL_FIELD3TYPE  int
6499 #define SORTTPL_FIELD4TYPE  int
6500 #define SORTTPL_BACKWARDS
6501 #include "scip/sorttpl.c" /*lint !e451*/
6502 
6503 
6504 /* SCIPsortDownLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6505 #define SORTTPL_NAMEEXT     DownLongPtrPtrBoolInt
6506 #define SORTTPL_KEYTYPE     SCIP_Longint
6507 #define SORTTPL_FIELD1TYPE  void*
6508 #define SORTTPL_FIELD2TYPE  void*
6509 #define SORTTPL_FIELD3TYPE  SCIP_Bool
6510 #define SORTTPL_FIELD4TYPE  int
6511 #define SORTTPL_BACKWARDS
6512 #include "scip/sorttpl.c" /*lint !e451*/
6513 
6514 
6515 /* SCIPsortDownPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6516 #define SORTTPL_NAMEEXT     DownPtrIntIntBoolBool
6517 #define SORTTPL_KEYTYPE     void*
6518 #define SORTTPL_FIELD1TYPE  int
6519 #define SORTTPL_FIELD2TYPE  int
6520 #define SORTTPL_FIELD3TYPE  SCIP_Bool
6521 #define SORTTPL_FIELD4TYPE  SCIP_Bool
6522 #define SORTTPL_PTRCOMP
6523 #define SORTTPL_BACKWARDS
6524 #include "scip/sorttpl.c" /*lint !e451*/
6525 
6526 
6527 /* SCIPsortDownIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6528 #define SORTTPL_NAMEEXT     DownIntPtrIntIntBoolBool
6529 #define SORTTPL_KEYTYPE     int
6530 #define SORTTPL_FIELD1TYPE  void*
6531 #define SORTTPL_FIELD2TYPE  int
6532 #define SORTTPL_FIELD3TYPE  int
6533 #define SORTTPL_FIELD4TYPE  SCIP_Bool
6534 #define SORTTPL_FIELD5TYPE  SCIP_Bool
6535 #define SORTTPL_BACKWARDS
6536 #include "scip/sorttpl.c" /*lint !e451*/
6537 
6538 /*
6539  * Resulting activity
6540  */
6541 
6542 /** create a resource activity */
SCIPactivityCreate(SCIP_RESOURCEACTIVITY ** activity,SCIP_VAR * var,int duration,int demand)6543 SCIP_RETCODE SCIPactivityCreate(
6544    SCIP_RESOURCEACTIVITY** activity,         /**< pointer to store the resource activity */
6545    SCIP_VAR*             var,                /**< start time variable of the activity */
6546    int                   duration,           /**< duration of the activity */
6547    int                   demand              /**< demand of the activity */
6548    )
6549 {
6550    assert(activity != NULL);
6551 
6552    SCIP_ALLOC( BMSallocMemory(activity) );
6553 
6554    (*activity)->var = var;
6555    (*activity)->duration = duration;
6556    (*activity)->demand = demand;
6557 
6558    return SCIP_OKAY;
6559 }
6560 
6561 /** frees a resource activity */
SCIPactivityFree(SCIP_RESOURCEACTIVITY ** activity)6562 void SCIPactivityFree(
6563    SCIP_RESOURCEACTIVITY** activity          /**< pointer to the resource activity */
6564    )
6565 {
6566    assert(activity != NULL);
6567    assert(*activity != NULL);
6568 
6569    BMSfreeMemory(activity);
6570 }
6571 
6572 /* some simple variable functions implemented as defines */
6573 
6574 #ifndef NDEBUG
6575 
6576 /* In debug mode, the following methods are implemented as function calls to ensure
6577  * type validity.
6578  * In optimized mode, the methods are implemented as defines to improve performance.
6579  * However, we want to have them in the library anyways, so we have to undef the defines.
6580  */
6581 
6582 #undef SCIPactivityGetVar
6583 #undef SCIPactivityGetDuration
6584 #undef SCIPactivityGetDemand
6585 #undef SCIPactivityGetEnergy
6586 
6587 /** returns the start time variable of the resource activity */
SCIPactivityGetVar(SCIP_RESOURCEACTIVITY * activity)6588 SCIP_VAR* SCIPactivityGetVar(
6589    SCIP_RESOURCEACTIVITY* activity           /**< resource activity */
6590    )
6591 {
6592    assert(activity != NULL);
6593 
6594    return activity->var;
6595 }
6596 
6597 /** returns the duration of the resource activity */
SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY * activity)6598 int SCIPactivityGetDuration(
6599    SCIP_RESOURCEACTIVITY* activity           /**< resource activity */
6600    )
6601 {
6602    assert(activity != NULL);
6603 
6604    return activity->duration;
6605 }
6606 
6607 /** returns the demand of the resource activity */
SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY * activity)6608 int SCIPactivityGetDemand(
6609    SCIP_RESOURCEACTIVITY* activity           /**< resource activity */
6610    )
6611 {
6612    assert(activity != NULL);
6613 
6614    return activity->demand;
6615 }
6616 
6617 /** returns the energy of the resource activity */
SCIPactivityGetEnergy(SCIP_RESOURCEACTIVITY * activity)6618 int SCIPactivityGetEnergy(
6619    SCIP_RESOURCEACTIVITY* activity           /**< resource activity */
6620    )
6621 {
6622    assert(activity != NULL);
6623 
6624    return activity->duration * activity->demand ;
6625 }
6626 
6627 #endif
6628 
6629 /*
6630  * Resource Profile
6631  */
6632 
6633 /** helper method to create a profile */
6634 static
doProfileCreate(SCIP_PROFILE ** profile,int capacity)6635 SCIP_RETCODE doProfileCreate(
6636    SCIP_PROFILE**        profile,            /**< pointer to store the resource profile */
6637    int                   capacity            /**< resource capacity */
6638    )
6639 {
6640    SCIP_ALLOC( BMSallocMemory(profile) );
6641    BMSclearMemory(*profile);
6642 
6643    (*profile)->arraysize = 10;
6644    SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->timepoints, (*profile)->arraysize) );
6645    SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->loads, (*profile)->arraysize) );
6646 
6647    /* setup resource profile for use */
6648    (*profile)->ntimepoints = 1;
6649    (*profile)->timepoints[0] = 0;
6650    (*profile)->loads[0] = 0;
6651    (*profile)->capacity = capacity;
6652 
6653    return SCIP_OKAY;
6654 }
6655 
6656 /** creates resource profile */
SCIPprofileCreate(SCIP_PROFILE ** profile,int capacity)6657 SCIP_RETCODE SCIPprofileCreate(
6658    SCIP_PROFILE**        profile,            /**< pointer to store the resource profile */
6659    int                   capacity            /**< resource capacity */
6660    )
6661 {
6662    assert(profile != NULL);
6663    assert(capacity > 0);
6664 
6665    SCIP_CALL_FINALLY( doProfileCreate(profile, capacity), SCIPprofileFree(profile) );
6666 
6667    return SCIP_OKAY;
6668 }
6669 
6670 /** frees given resource profile */
SCIPprofileFree(SCIP_PROFILE ** profile)6671 void SCIPprofileFree(
6672    SCIP_PROFILE**        profile             /**< pointer to the resource profile */
6673    )
6674 {
6675    assert(profile != NULL);
6676 
6677    /* free resource profile */
6678    if( *profile != NULL )
6679    {
6680       BMSfreeMemoryArrayNull(&(*profile)->loads);
6681       BMSfreeMemoryArrayNull(&(*profile)->timepoints);
6682       BMSfreeMemory(profile);
6683    }
6684 }
6685 
6686 /** output of the given resource profile */
SCIPprofilePrint(SCIP_PROFILE * profile,SCIP_MESSAGEHDLR * messagehdlr,FILE * file)6687 void SCIPprofilePrint(
6688    SCIP_PROFILE*         profile,            /**< resource profile to output */
6689    SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
6690    FILE*                 file                /**< output file (or NULL for standard output) */
6691    )
6692 {
6693    int t;
6694 
6695    SCIPmessageFPrintInfo(messagehdlr, file, "Profile <%p> (capacity %d) --> ", (void*)profile, profile->capacity);
6696 
6697    for( t = 0; t < profile->ntimepoints; ++t )
6698    {
6699       if( t == 0 )
6700          SCIPmessageFPrintInfo(messagehdlr, file, "%d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6701       else
6702          SCIPmessageFPrintInfo(messagehdlr, file, ", %d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6703    }
6704 
6705    SCIPmessageFPrintInfo(messagehdlr, file,"\n");
6706 }
6707 
6708 /** returns the capacity of the resource profile */
SCIPprofileGetCapacity(SCIP_PROFILE * profile)6709 int SCIPprofileGetCapacity(
6710    SCIP_PROFILE*         profile             /**< resource profile to use */
6711    )
6712 {
6713    assert(profile != NULL);
6714 
6715    return profile->capacity;
6716 }
6717 
6718 /** returns the number time points of the resource profile */
SCIPprofileGetNTimepoints(SCIP_PROFILE * profile)6719 int SCIPprofileGetNTimepoints(
6720    SCIP_PROFILE*         profile             /**< resource profile to use */
6721    )
6722 {
6723    assert(profile != NULL);
6724 
6725    return profile->ntimepoints;
6726 }
6727 
6728 /** returns the time points of the resource profile */
SCIPprofileGetTimepoints(SCIP_PROFILE * profile)6729 int* SCIPprofileGetTimepoints(
6730    SCIP_PROFILE*         profile             /**< resource profile to use */
6731    )
6732 {
6733    assert(profile != NULL);
6734 
6735    return profile->timepoints;
6736 }
6737 
6738 /** returns the loads of the resource profile */
SCIPprofileGetLoads(SCIP_PROFILE * profile)6739 int* SCIPprofileGetLoads(
6740    SCIP_PROFILE*         profile             /**< resource profile to use */
6741    )
6742 {
6743    assert(profile != NULL);
6744 
6745    return profile->loads;
6746 }
6747 
6748 /** returns the time point for given position of the resource profile */
SCIPprofileGetTime(SCIP_PROFILE * profile,int pos)6749 int SCIPprofileGetTime(
6750    SCIP_PROFILE*         profile,            /**< resource profile to use */
6751    int                   pos                 /**< position */
6752    )
6753 {
6754    assert(profile != NULL);
6755    assert(pos >= 0 && pos < profile->ntimepoints);
6756 
6757    return profile->timepoints[pos];
6758 }
6759 
6760 /** returns the loads of the resource profile at the given position */
SCIPprofileGetLoad(SCIP_PROFILE * profile,int pos)6761 int SCIPprofileGetLoad(
6762    SCIP_PROFILE*         profile,            /**< resource profile */
6763    int                   pos                 /**< position */
6764    )
6765 {
6766    assert(profile != NULL);
6767    assert(pos >= 0 && pos < profile->ntimepoints);
6768 
6769    return profile->loads[pos];
6770 }
6771 
6772 /** returns if the given time point exists in the resource profile and stores the position of the given time point if it
6773  *  exists; otherwise the position of the next smaller existing time point is stored
6774  */
SCIPprofileFindLeft(SCIP_PROFILE * profile,int timepoint,int * pos)6775 SCIP_Bool SCIPprofileFindLeft(
6776    SCIP_PROFILE*         profile,            /**< resource profile to search */
6777    int                   timepoint,          /**< time point to search for */
6778    int*                  pos                 /**< pointer to store the position */
6779    )
6780 {
6781    assert(profile != NULL);
6782    assert(timepoint >= 0);
6783    assert(profile->ntimepoints > 0);
6784    assert(profile->timepoints[0] == 0);
6785 
6786    /* find the position of time point in the time points array via binary search */
6787    if( SCIPsortedvecFindInt(profile->timepoints, timepoint, profile->ntimepoints, pos) )
6788       return TRUE;
6789 
6790    assert(*pos > 0);
6791    (*pos)--;
6792 
6793    return FALSE;
6794 }
6795 
6796 /* ensures that resource profile arrays is big enough */
6797 static
ensureProfileSize(SCIP_PROFILE * profile,int neededsize)6798 SCIP_RETCODE ensureProfileSize(
6799    SCIP_PROFILE*         profile,            /**< resource profile to insert the time point */
6800    int                   neededsize          /**< needed size */
6801    )
6802 {
6803    assert(profile->arraysize > 0);
6804 
6805    /* check whether the arrays are big enough */
6806    if( neededsize <= profile->arraysize )
6807       return SCIP_OKAY;
6808 
6809    profile->arraysize *= 2;
6810 
6811    SCIP_ALLOC( BMSreallocMemoryArray(&profile->timepoints, profile->arraysize) );
6812    SCIP_ALLOC( BMSreallocMemoryArray(&profile->loads, profile->arraysize) );
6813 
6814    return SCIP_OKAY;
6815 }
6816 
6817 /** inserts the given time point into the resource profile if it this time point does not exists yet; returns its
6818  *  position in the time point array
6819  */
6820 static
profileInsertTimepoint(SCIP_PROFILE * profile,int timepoint,int * pos)6821 SCIP_RETCODE profileInsertTimepoint(
6822    SCIP_PROFILE*         profile,            /**< resource profile to insert the time point */
6823    int                   timepoint,          /**< time point to insert */
6824    int*                  pos                 /**< pointer to store the insert position */
6825    )
6826 {
6827    assert(profile != NULL);
6828    assert(timepoint >= 0);
6829    assert(profile->arraysize >= profile->ntimepoints);
6830 
6831    /* get the position of the given time point in the resource profile array if it exists; otherwise the position of the
6832     * next smaller existing time point
6833     */
6834    if( !SCIPprofileFindLeft(profile, timepoint, pos) )
6835    {
6836       assert(*pos >= 0 && *pos < profile->ntimepoints);
6837       assert(timepoint >= profile->timepoints[*pos]);
6838 
6839       /* ensure that the arrays are big enough */
6840       SCIP_CALL( ensureProfileSize(profile, profile->ntimepoints + 1) );
6841       assert(profile->arraysize > profile->ntimepoints);
6842 
6843       /* insert new time point into the (sorted) resource profile */
6844       SCIPsortedvecInsertIntInt(profile->timepoints, profile->loads, timepoint, profile->loads[*pos],
6845          &profile->ntimepoints, pos);
6846    }
6847 
6848 #ifndef NDEBUG
6849    /* check if the time points are sorted */
6850    {
6851       int i;
6852       for( i = 1; i < profile->ntimepoints; ++i )
6853          assert(profile->timepoints[i-1] < profile->timepoints[i]);
6854    }
6855 #endif
6856 
6857    return SCIP_OKAY;
6858 }
6859 
6860 /** updates the resource profile due to inserting of a core */
6861 static
profileUpdate(SCIP_PROFILE * profile,int left,int right,int demand,int * pos,SCIP_Bool * infeasible)6862 SCIP_RETCODE profileUpdate(
6863    SCIP_PROFILE*         profile,            /**< resource profile to update */
6864    int                   left,               /**< left side of core interval */
6865    int                   right,              /**< right side of core interval */
6866    int                   demand,             /**< demand of the core */
6867    int*                  pos,                /**< pointer to store the first position were it gets infeasible */
6868    SCIP_Bool*            infeasible          /**< pointer to store if the update is infeasible */
6869    )
6870 {
6871    int startpos;
6872    int endpos;
6873    int i;
6874 
6875    assert(profile != NULL);
6876    assert(profile->arraysize >= profile->ntimepoints);
6877    assert(left >= 0);
6878    assert(left < right);
6879    assert(infeasible != NULL);
6880 
6881    (*infeasible) = FALSE;
6882    (*pos) = -1;
6883 
6884    /* get position of the starttime in profile */
6885    SCIP_CALL( profileInsertTimepoint(profile, left, &startpos) );
6886    assert(profile->timepoints[startpos] == left);
6887 
6888    /* get position of the endtime in profile */
6889    SCIP_CALL( profileInsertTimepoint(profile, right, &endpos) );
6890    assert(profile->timepoints[endpos] == right);
6891 
6892    assert(startpos < endpos);
6893    assert(profile->arraysize >= profile->ntimepoints);
6894 
6895    /* remove/add the given demand from the core */
6896    for( i = startpos; i < endpos; ++i )
6897    {
6898       profile->loads[i] += demand;
6899 
6900       /* check if the core fits */
6901       if( profile->loads[i] > profile->capacity )
6902       {
6903          SCIPdebugMessage("core insertion detected infeasibility (pos %d)\n", i);
6904 
6905          (*infeasible) = TRUE;
6906          (*pos) = i;
6907 
6908          /* remove the partly inserted core since it does fit completely */
6909          for( ; i >= startpos; --i ) /*lint !e445*/
6910             profile->loads[i] -= demand;
6911 
6912          break;
6913       }
6914    }
6915 
6916    return SCIP_OKAY;
6917 }
6918 
6919 /** insert a core into resource profile; if the core is non-empty the resource profile will be updated otherwise nothing
6920  *  happens
6921  */
SCIPprofileInsertCore(SCIP_PROFILE * profile,int left,int right,int demand,int * pos,SCIP_Bool * infeasible)6922 SCIP_RETCODE SCIPprofileInsertCore(
6923    SCIP_PROFILE*         profile,            /**< resource profile */
6924    int                   left,               /**< left side of the core  */
6925    int                   right,              /**< right side of the core */
6926    int                   demand,             /**< demand of the core */
6927    int*                  pos,                /**< pointer to store the first position were it gets infeasible */
6928    SCIP_Bool*            infeasible          /**< pointer to store if the core does not fit due to capacity */
6929    )
6930 {
6931    assert(profile != NULL);
6932    assert(left < right);
6933    assert(demand >= 0);
6934    assert(infeasible != NULL);
6935 
6936    (*infeasible) = FALSE;
6937    (*pos) = -1;
6938 
6939    /* insert core into the resource profile */
6940    SCIPdebugMessage("insert core [%d,%d] with demand %d\n", left, right, demand);
6941 
6942    if( demand > 0 )
6943    {
6944       /* try to insert core into the resource profile */
6945       SCIP_CALL( profileUpdate(profile, left, right, demand, pos, infeasible) );
6946    }
6947 
6948    return SCIP_OKAY;
6949 }
6950 
6951 /** subtracts the demand from the resource profile during core time */
SCIPprofileDeleteCore(SCIP_PROFILE * profile,int left,int right,int demand)6952 SCIP_RETCODE SCIPprofileDeleteCore(
6953    SCIP_PROFILE*         profile,            /**< resource profile to use */
6954    int                   left,               /**< left side of the core  */
6955    int                   right,              /**< right side of the core */
6956    int                   demand              /**< demand of the core */
6957    )
6958 {
6959    SCIP_Bool infeasible;
6960    int pos;
6961 
6962    assert(left < right);
6963 #ifndef NDEBUG
6964    {
6965       /* check if the left and right time points of the core correspond to a time point in the resource profile; this
6966        * should be the case since we added the core before to the resource profile
6967        */
6968       assert(SCIPprofileFindLeft(profile, left, &pos));
6969       assert(SCIPprofileFindLeft(profile, right, &pos));
6970    }
6971 #endif
6972 
6973    /* remove the core from the resource profile */
6974    SCIPdebugMessage("delete core [%d,%d] with demand %d\n", left, right, demand);
6975 
6976    SCIP_CALL( profileUpdate(profile, left, right, -demand, &pos, &infeasible) );
6977    assert(!infeasible);
6978 
6979    return SCIP_OKAY; /*lint !e438*/
6980 }
6981 
6982 /** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
6983 static
profileFindFeasibleStart(SCIP_PROFILE * profile,int pos,int lst,int duration,int demand,SCIP_Bool * infeasible)6984 int profileFindFeasibleStart(
6985    SCIP_PROFILE*         profile,            /**< resource profile to use */
6986    int                   pos,                /**< pointer to store the position in the profile to start the serch */
6987    int                   lst,                /**< latest start time */
6988    int                   duration,           /**< duration of the core */
6989    int                   demand,             /**< demand of the core */
6990    SCIP_Bool*            infeasible          /**< pointer store if the corer cannot be inserted */
6991    )
6992 {
6993    int remainingduration;
6994    int startpos;
6995 
6996    assert(profile != NULL);
6997    assert(pos >= 0);
6998    assert(pos < profile->ntimepoints);
6999    assert(duration > 0);
7000    assert(demand > 0);
7001    assert(profile->loads[profile->ntimepoints-1] == 0);
7002 
7003    remainingduration = duration;
7004    startpos = pos;
7005    (*infeasible) = FALSE;
7006 
7007    if( profile->timepoints[startpos] > lst )
7008    {
7009       (*infeasible) = TRUE;
7010       return pos;
7011    }
7012 
7013    while( pos < profile->ntimepoints - 1 )
7014    {
7015       if( profile->loads[pos] + demand > profile->capacity )
7016       {
7017          SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos], pos);
7018          startpos = pos + 1;
7019          remainingduration = duration;
7020 
7021          if( profile->timepoints[startpos] > lst )
7022          {
7023             (*infeasible) = TRUE;
7024             return pos;
7025          }
7026       }
7027       else
7028          remainingduration -= profile->timepoints[pos+1] - profile->timepoints[pos];
7029 
7030       if( remainingduration <= 0 )
7031          break;
7032 
7033       pos++;
7034    }
7035 
7036    return startpos;
7037 }
7038 
7039 /** return the earliest possible starting point within the time interval [lb,ub] for a given core (given by its demand
7040  *  and duration)
7041  */
SCIPprofileGetEarliestFeasibleStart(SCIP_PROFILE * profile,int est,int lst,int duration,int demand,SCIP_Bool * infeasible)7042 int SCIPprofileGetEarliestFeasibleStart(
7043    SCIP_PROFILE*         profile,            /**< resource profile to use */
7044    int                   est,                /**< earliest starting time of the given core */
7045    int                   lst,                /**< latest starting time of the given core */
7046    int                   duration,           /**< duration of the core */
7047    int                   demand,             /**< demand of the core */
7048    SCIP_Bool*            infeasible          /**< pointer store if the corer cannot be inserted */
7049    )
7050 {
7051    SCIP_Bool found;
7052    int pos;
7053 
7054    assert(profile != NULL);
7055    assert(est >= 0);
7056    assert(est <= lst);
7057    assert(duration >= 0);
7058    assert(demand >= 0);
7059    assert(infeasible != NULL);
7060    assert(profile->ntimepoints > 0);
7061    assert(profile->loads[profile->ntimepoints-1] == 0);
7062 
7063    SCIPdebugMessage("profile <%p>: find earliest start time (demad %d, duration %d) [%d,%d]\n", (void*)profile, demand, duration, est, lst);
7064 
7065    if( duration == 0 || demand == 0 )
7066    {
7067       *infeasible = FALSE;
7068       return est;
7069    }
7070 
7071    found = SCIPprofileFindLeft(profile, est, &pos);
7072    SCIPdebugMessage("profile <%p>: earliest start time does %s exist as time point (pos %d)\n", (void*)profile, found ? "" : "not", pos);
7073 
7074    /* if the position is the last time point in the profile, the core can be inserted at its earliest start time */
7075    if( pos == profile->ntimepoints - 1 )
7076    {
7077       (*infeasible) = FALSE;
7078       return est;
7079    }
7080 
7081    if( found )
7082    {
7083       /* if the start time matches a time point in the profile we can just search */
7084       assert(profile->timepoints[pos] == est);
7085       pos = profileFindFeasibleStart(profile, pos, lst, duration, demand, infeasible);
7086 
7087       assert(pos < profile->ntimepoints);
7088       est = profile->timepoints[pos];
7089    }
7090    else if( profile->loads[pos] + demand > profile->capacity )
7091    {
7092       /* if the the time point left to the start time has not enough free capacity we can just search the profile
7093        * starting from the next time point
7094        */
7095       assert(profile->timepoints[pos] <= est);
7096       pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7097 
7098       assert(pos < profile->ntimepoints);
7099       est = profile->timepoints[pos];
7100    }
7101    else
7102    {
7103       int remainingduration;
7104 
7105       /* check if the core can be placed at its earliest start time */
7106 
7107       assert(pos < profile->ntimepoints - 1);
7108 
7109       remainingduration = duration - (profile->timepoints[pos+1] - est);
7110       SCIPdebugMessage("remaining duration %d\n", remainingduration);
7111 
7112       if( remainingduration <= 0 )
7113          (*infeasible) = FALSE;
7114       else
7115       {
7116          pos = profileFindFeasibleStart(profile, pos+1, profile->timepoints[pos+1], remainingduration, demand, infeasible);
7117          SCIPdebugMessage("remaining duration can%s be processed\n", *infeasible ? "not" : "");
7118 
7119          if( *infeasible )
7120          {
7121             pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7122 
7123             assert(pos < profile->ntimepoints);
7124             est = profile->timepoints[pos];
7125          }
7126       }
7127    }
7128 
7129    return est;
7130 }
7131 
7132 /** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7133 static
profileFindDownFeasibleStart(SCIP_PROFILE * profile,int pos,int ect,int duration,int demand,SCIP_Bool * infeasible)7134 int profileFindDownFeasibleStart(
7135    SCIP_PROFILE*         profile,            /**< resource profile to use */
7136    int                   pos,                /**< pointer to store the position in the profile to start the search */
7137    int                   ect,                /**< earliest completion time */
7138    int                   duration,           /**< duration of the core */
7139    int                   demand,             /**< demand of the core */
7140    SCIP_Bool*            infeasible          /**< pointer store if the corer cannot be inserted */
7141    )
7142 {
7143    int remainingduration;
7144    int endpos;
7145 
7146    assert(profile != NULL);
7147    assert(pos >= 0);
7148    assert(pos < profile->ntimepoints);
7149    assert(duration > 0);
7150    assert(demand > 0);
7151    assert(profile->ntimepoints > 0);
7152    assert(profile->loads[profile->ntimepoints-1] == 0);
7153 
7154    remainingduration = duration;
7155    endpos = pos;
7156    (*infeasible) = TRUE;
7157 
7158    if( profile->timepoints[endpos] < ect - duration )
7159       return pos;
7160 
7161    while( pos > 0 )
7162    {
7163       if( profile->loads[pos-1] + demand > profile->capacity )
7164       {
7165          SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos-1], pos-1);
7166 
7167          endpos = pos - 1;
7168          remainingduration = duration;
7169 
7170          if( profile->timepoints[endpos] < ect - duration )
7171             return pos;
7172       }
7173       else
7174          remainingduration -= profile->timepoints[pos] - profile->timepoints[pos-1];
7175 
7176       if( remainingduration <= 0 )
7177       {
7178          *infeasible = FALSE;
7179          break;
7180       }
7181 
7182       pos--;
7183    }
7184 
7185    return endpos;
7186 }
7187 
7188 /** return the latest possible starting point within the time interval [lb,ub] for a given core (given by its demand and
7189  *  duration)
7190  */
SCIPprofileGetLatestFeasibleStart(SCIP_PROFILE * profile,int est,int lst,int duration,int demand,SCIP_Bool * infeasible)7191 int SCIPprofileGetLatestFeasibleStart(
7192    SCIP_PROFILE*         profile,            /**< resource profile to use */
7193    int                   est,                /**< earliest possible start point */
7194    int                   lst,                /**< latest possible start point */
7195    int                   duration,           /**< duration of the core */
7196    int                   demand,             /**< demand of the core */
7197    SCIP_Bool*            infeasible          /**< pointer store if the core cannot be inserted */
7198    )
7199 {
7200    SCIP_Bool found;
7201    int ect;
7202    int lct;
7203    int pos;
7204 
7205    assert(profile != NULL);
7206    assert(est >= 0);
7207    assert(est <= lst);
7208    assert(duration >= 0);
7209    assert(demand >= 0);
7210    assert(infeasible != NULL);
7211    assert(profile->ntimepoints > 0);
7212    assert(profile->loads[profile->ntimepoints-1] == 0);
7213 
7214    if( duration == 0 || demand == 0 )
7215    {
7216       *infeasible = FALSE;
7217       return lst;
7218    }
7219 
7220    ect = est + duration;
7221    lct = lst + duration;
7222 
7223    found = SCIPprofileFindLeft(profile, lct, &pos);
7224    SCIPdebugMessage("profile <%p>: latest completion time %d does %s exist as time point (pos %d)\n", (void*)profile, lct, found ? "" : "not", pos);
7225 
7226    if( found )
7227    {
7228       /* if the start time matches a time point in the profile we can just search */
7229       assert(profile->timepoints[pos] == lct);
7230       pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7231 
7232       assert(pos < profile->ntimepoints && pos >= 0);
7233       lct = profile->timepoints[pos];
7234    }
7235    else if( profile->loads[pos] + demand > profile->capacity )
7236    {
7237       /* if the time point left to the start time has not enough free capacity we can just search the profile starting
7238        * from the next time point
7239        */
7240       assert(profile->timepoints[pos] < lct);
7241       pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7242 
7243       assert(pos < profile->ntimepoints && pos >= 0);
7244       lct = profile->timepoints[pos];
7245    }
7246    else
7247    {
7248       int remainingduration;
7249 
7250       /* check if the core can be placed at its latest start time */
7251       assert(profile->timepoints[pos] < lct);
7252 
7253       remainingduration = duration - (lct - profile->timepoints[pos]);
7254 
7255       if( remainingduration <= 0 )
7256          (*infeasible) = FALSE;
7257       else
7258       {
7259          pos = profileFindDownFeasibleStart(profile, pos, profile->timepoints[pos], remainingduration, demand, infeasible);
7260 
7261          if( *infeasible )
7262          {
7263             pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7264 
7265             assert(pos < profile->ntimepoints && pos >= 0);
7266             lct = profile->timepoints[pos];
7267          }
7268       }
7269    }
7270 
7271    return lct - duration;
7272 }
7273 
7274 /*
7275  * Directed graph
7276  */
7277 
7278 /** creates directed graph structure */
SCIPdigraphCreate(SCIP_DIGRAPH ** digraph,BMS_BLKMEM * blkmem,int nnodes)7279 SCIP_RETCODE SCIPdigraphCreate(
7280    SCIP_DIGRAPH**        digraph,            /**< pointer to store the created directed graph */
7281    BMS_BLKMEM*           blkmem,             /**< block memory to store the data */
7282    int                   nnodes              /**< number of nodes */
7283    )
7284 {
7285    assert(digraph != NULL);
7286    assert(blkmem != NULL);
7287    assert(nnodes > 0);
7288 
7289    /* allocate memory for the graph and the arrays storing arcs and data */
7290    SCIP_ALLOC( BMSallocBlockMemory(blkmem, digraph) );
7291    SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successors, nnodes) );
7292    SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->arcdata, nnodes) );
7293    SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successorssize, nnodes) );
7294    SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nsuccessors, nnodes) );
7295    SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nodedata, nnodes) );
7296 
7297    /* store number of nodes */
7298    (*digraph)->nnodes = nnodes;
7299 
7300    /* at the beginning, no components are stored */
7301    (*digraph)->blkmem = blkmem;
7302    (*digraph)->ncomponents = 0;
7303    (*digraph)->componentstartsize = 0;
7304    (*digraph)->components = NULL;
7305    (*digraph)->componentstarts = NULL;
7306 
7307    /* all nodes are initially considered as non-articulation points */
7308    (*digraph)->narticulations = -1;
7309    (*digraph)->articulations = NULL;
7310    (*digraph)->articulationscheck = FALSE;
7311 
7312    return SCIP_OKAY;
7313 }
7314 
7315 /** resize directed graph structure */
SCIPdigraphResize(SCIP_DIGRAPH * digraph,int nnodes)7316 SCIP_RETCODE SCIPdigraphResize(
7317    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7318    int                   nnodes              /**< new number of nodes */
7319    )
7320 {
7321    int n;
7322    assert(digraph != NULL);
7323    assert(digraph->blkmem != NULL);
7324 
7325    /* check if the digraph has already a proper size */
7326    if( nnodes <= digraph->nnodes )
7327       return SCIP_OKAY;
7328 
7329    /* reallocate memory for increasing the arrays storing arcs and data */
7330    SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successors, digraph->nnodes, nnodes) );
7331    SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->arcdata, digraph->nnodes, nnodes) );
7332    SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successorssize, digraph->nnodes, nnodes) );
7333    SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nsuccessors, digraph->nnodes, nnodes) );
7334    SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nodedata, digraph->nnodes, nnodes) );
7335 
7336    /* initialize the new node data structures */
7337    for( n = digraph->nnodes; n < nnodes; ++n )
7338    {
7339       digraph->nodedata[n] = NULL;
7340       digraph->arcdata[n] = NULL;
7341       digraph->successors[n] = NULL;
7342       digraph->successorssize[n] = 0;
7343       digraph->nsuccessors[n] = 0;
7344    }
7345 
7346    /* store the new number of nodes */
7347    digraph->nnodes = nnodes;
7348 
7349    return SCIP_OKAY;
7350 }
7351 
7352 /** copies directed graph structure
7353  *
7354  *  @note The data in nodedata is copied verbatim. This possibly has to be adapted by the user.
7355  */
SCIPdigraphCopy(SCIP_DIGRAPH ** targetdigraph,SCIP_DIGRAPH * sourcedigraph,BMS_BLKMEM * targetblkmem)7356 SCIP_RETCODE SCIPdigraphCopy(
7357    SCIP_DIGRAPH**        targetdigraph,      /**< pointer to store the copied directed graph */
7358    SCIP_DIGRAPH*         sourcedigraph,      /**< source directed graph */
7359    BMS_BLKMEM*           targetblkmem        /**< block memory to store the target block memory, or NULL to use the same
7360                                               *   the same block memory as used for the \p sourcedigraph */
7361    )
7362 {
7363    int ncomponents;
7364    int nnodes;
7365    int i;
7366    SCIP_Bool articulationscheck;
7367 
7368    assert(sourcedigraph != NULL);
7369    assert(targetdigraph != NULL);
7370 
7371    /* use the source digraph block memory if not specified otherwise */
7372    if( targetblkmem == NULL )
7373       targetblkmem = sourcedigraph->blkmem;
7374 
7375    assert(targetblkmem != NULL);
7376 
7377    SCIP_ALLOC( BMSallocBlockMemory(targetblkmem, targetdigraph) );
7378 
7379    nnodes = sourcedigraph->nnodes;
7380    ncomponents = sourcedigraph->ncomponents;
7381    articulationscheck = sourcedigraph->articulationscheck;
7382    (*targetdigraph)->nnodes = nnodes;
7383    (*targetdigraph)->ncomponents = ncomponents;
7384    (*targetdigraph)->blkmem = targetblkmem;
7385 
7386    /* copy arcs and data */
7387    SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->successors, nnodes) );
7388    SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->arcdata, nnodes) );
7389    SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->nodedata, nnodes) );
7390 
7391    /* copy lists of successors and arc data */
7392    for( i = 0; i < nnodes; ++i )
7393    {
7394       if( sourcedigraph->nsuccessors[i] > 0 )
7395       {
7396          assert(sourcedigraph->successors[i] != NULL);
7397          assert(sourcedigraph->arcdata[i] != NULL);
7398 
7399          SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->successors[i]),
7400                sourcedigraph->successors[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7401          SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->arcdata[i]),
7402                sourcedigraph->arcdata[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7403       }
7404       /* copy node data - careful if these are pointers to some information -> need to be copied by hand */
7405       (*targetdigraph)->nodedata[i] = sourcedigraph->nodedata[i];
7406    }
7407 
7408    /* use nsuccessors as size to save memory */
7409    SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->successorssize, sourcedigraph->nsuccessors, nnodes) );
7410    SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->nsuccessors, sourcedigraph->nsuccessors, nnodes) );
7411 
7412    /* copy component data */
7413    if( ncomponents > 0 )
7414    {
7415       SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->components, sourcedigraph->components,
7416             sourcedigraph->componentstarts[ncomponents]) );
7417       SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->componentstarts,
7418             sourcedigraph->componentstarts,ncomponents + 1) ); /*lint !e776*/
7419       (*targetdigraph)->componentstartsize = ncomponents + 1;
7420    }
7421    else
7422    {
7423       (*targetdigraph)->components = NULL;
7424       (*targetdigraph)->componentstarts = NULL;
7425       (*targetdigraph)->componentstartsize = 0;
7426    }
7427 
7428    /* copy the articulation point information if it has been computed and is up-to-date */
7429    if( articulationscheck )
7430    {
7431       SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->articulations, sourcedigraph->articulations, sourcedigraph->narticulations) );
7432       (*targetdigraph)->narticulations = sourcedigraph->narticulations;
7433       (*targetdigraph)->articulationscheck = TRUE;
7434    }
7435    else
7436    {
7437       (*targetdigraph)->narticulations = -1;
7438       (*targetdigraph)->articulations = NULL;
7439       (*targetdigraph)->articulationscheck = FALSE;
7440    }
7441 
7442    return SCIP_OKAY;
7443 }
7444 
7445 /** sets the sizes of the successor lists for the nodes in a directed graph and allocates memory for the lists */
SCIPdigraphSetSizes(SCIP_DIGRAPH * digraph,int * sizes)7446 SCIP_RETCODE SCIPdigraphSetSizes(
7447    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7448    int*                  sizes               /**< sizes of the successor lists */
7449    )
7450 {
7451    int i;
7452    BMS_BLKMEM* blkmem;
7453 
7454    assert(digraph != NULL);
7455    assert(digraph->nnodes > 0);
7456    blkmem = digraph->blkmem;
7457 
7458    for( i = 0; i < digraph->nnodes; ++i )
7459    {
7460       SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[i], sizes[i]) ); /*lint !e866*/
7461       SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[i], sizes[i]) ); /*lint !e866*/
7462       digraph->successorssize[i] = sizes[i];
7463       digraph->nsuccessors[i] = 0;
7464    }
7465 
7466    return SCIP_OKAY;
7467 }
7468 
7469 /** frees given directed graph structure */
SCIPdigraphFree(SCIP_DIGRAPH ** digraph)7470 void SCIPdigraphFree(
7471    SCIP_DIGRAPH**        digraph             /**< pointer to the directed graph */
7472    )
7473 {
7474    int i;
7475    BMS_BLKMEM* blkmem;
7476    SCIP_DIGRAPH* digraphptr;
7477 
7478    assert(digraph != NULL);
7479    assert(*digraph != NULL);
7480    assert((*digraph)->blkmem != NULL);
7481 
7482    blkmem = (*digraph)->blkmem;
7483    digraphptr = *digraph;
7484 
7485    /* free arrays storing the successor nodes and arc data */
7486    for( i = digraphptr->nnodes - 1; i >= 0; --i )
7487    {
7488       BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->successors[i], digraphptr->successorssize[i]);
7489       BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->arcdata[i], digraphptr->successorssize[i]);
7490    }
7491 
7492    /* free components structure */
7493    SCIPdigraphFreeComponents(digraphptr);
7494    assert(digraphptr->ncomponents == 0);
7495    assert(digraphptr->componentstartsize == 0);
7496    assert(digraphptr->components == NULL);
7497    assert(digraphptr->componentstarts == NULL);
7498 
7499    /* free the articulation points structure if it has been computed*/
7500    if( digraphptr->articulationscheck )
7501       BMSfreeBlockMemoryArray(blkmem, &digraphptr->articulations, digraphptr->narticulations);
7502 
7503    /* free directed graph data structure */
7504    BMSfreeBlockMemoryArray(blkmem, &digraphptr->nodedata, digraphptr->nnodes);
7505    BMSfreeBlockMemoryArray(blkmem, &digraphptr->successorssize, digraphptr->nnodes);
7506    BMSfreeBlockMemoryArray(blkmem, &digraphptr->nsuccessors, digraphptr->nnodes);
7507    BMSfreeBlockMemoryArray(blkmem, &digraphptr->successors, digraphptr->nnodes);
7508    BMSfreeBlockMemoryArray(blkmem, &digraphptr->arcdata, digraphptr->nnodes);
7509 
7510    BMSfreeBlockMemory(blkmem, digraph);
7511 }
7512 
7513 #define STARTSUCCESSORSSIZE 5
7514 
7515 /** ensures that successors array of one node in a directed graph is big enough */
7516 static
ensureSuccessorsSize(SCIP_DIGRAPH * digraph,int idx,int newsize)7517 SCIP_RETCODE ensureSuccessorsSize(
7518    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7519    int                   idx,                /**< index for which the size is ensured */
7520    int                   newsize             /**< needed size */
7521    )
7522 {
7523    BMS_BLKMEM* blkmem;
7524 
7525    assert(digraph != NULL);
7526    assert(digraph->blkmem != NULL);
7527    assert(idx >= 0);
7528    assert(idx < digraph->nnodes);
7529    assert(newsize > 0);
7530    assert(digraph->successorssize[idx] == 0 || digraph->successors[idx] != NULL);
7531    assert(digraph->successorssize[idx] == 0 || digraph->arcdata[idx] != NULL);
7532 
7533    blkmem = digraph->blkmem;
7534 
7535    /* check whether array is big enough, and realloc, if needed */
7536    if( newsize > digraph->successorssize[idx] )
7537    {
7538       if( digraph->successors[idx] == NULL )
7539       {
7540          assert(digraph->arcdata[idx] == NULL);
7541          digraph->successorssize[idx] = STARTSUCCESSORSSIZE;
7542          SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7543          SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7544       }
7545       else
7546       {
7547          newsize = MAX(newsize, 2 * digraph->successorssize[idx]);
7548          assert(digraph->arcdata[idx] != NULL);
7549          SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7550          SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7551          digraph->successorssize[idx] = newsize;
7552       }
7553    }
7554 
7555    assert(newsize <= digraph->successorssize[idx]);
7556 
7557    return SCIP_OKAY;
7558 }
7559 
7560 /** add (directed) arc and a related data to the directed graph structure
7561  *
7562  *  @note if the arc is already contained, it is added a second time
7563  */
SCIPdigraphAddArc(SCIP_DIGRAPH * digraph,int startnode,int endnode,void * data)7564 SCIP_RETCODE SCIPdigraphAddArc(
7565    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7566    int                   startnode,          /**< start node of the arc */
7567    int                   endnode,            /**< start node of the arc */
7568    void*                 data                /**< data that should be stored for the arc; or NULL */
7569    )
7570 {
7571    assert(digraph != NULL);
7572    assert(startnode >= 0);
7573    assert(endnode >= 0);
7574    assert(startnode < digraph->nnodes);
7575    assert(endnode < digraph->nnodes);
7576 
7577    SCIP_CALL( ensureSuccessorsSize(digraph, startnode, digraph->nsuccessors[startnode] + 1) );
7578 
7579    /* add arc */
7580    digraph->successors[startnode][digraph->nsuccessors[startnode]] = endnode;
7581    digraph->arcdata[startnode][digraph->nsuccessors[startnode]] = data;
7582    digraph->nsuccessors[startnode]++;
7583 
7584    /* the articulation points are not up-to-date */
7585    digraph->articulationscheck = FALSE;
7586 
7587    return SCIP_OKAY;
7588 }
7589 
7590 /** add (directed) arc to the directed graph structure, if it is not contained, yet
7591  *
7592  * @note if there already exists an arc from startnode to endnode, the new arc is not added,
7593  *       even if its data is different
7594  */
SCIPdigraphAddArcSafe(SCIP_DIGRAPH * digraph,int startnode,int endnode,void * data)7595 SCIP_RETCODE SCIPdigraphAddArcSafe(
7596    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7597    int                   startnode,          /**< start node of the arc */
7598    int                   endnode,            /**< start node of the arc */
7599    void*                 data                /**< data that should be stored for the arc; or NULL */
7600    )
7601 {
7602    int nsuccessors;
7603    int i;
7604 
7605    assert(digraph != NULL);
7606    assert(startnode >= 0);
7607    assert(endnode >= 0);
7608    assert(startnode < digraph->nnodes);
7609    assert(endnode < digraph->nnodes);
7610 
7611    nsuccessors = digraph->nsuccessors[startnode];
7612 
7613    /* search for the arc in existing arcs */
7614    for( i = 0; i < nsuccessors; ++i )
7615       if( digraph->successors[startnode][i] == endnode )
7616          return SCIP_OKAY;
7617 
7618    SCIP_CALL( ensureSuccessorsSize(digraph, startnode, nsuccessors + 1) );
7619 
7620    /* add arc */
7621    digraph->successors[startnode][nsuccessors] = endnode;
7622    digraph->arcdata[startnode][nsuccessors] = data;
7623    ++(digraph->nsuccessors[startnode]);
7624 
7625    /* the articulation points are not up-to-date */
7626    digraph->articulationscheck = FALSE;
7627 
7628    return SCIP_OKAY;
7629 }
7630 
7631 /** sets the number of successors to a given value */
SCIPdigraphSetNSuccessors(SCIP_DIGRAPH * digraph,int node,int nsuccessors)7632 SCIP_RETCODE SCIPdigraphSetNSuccessors(
7633    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7634    int                   node,               /**< node for which the number of successors has to be changed */
7635    int                   nsuccessors         /**< new number of successors */
7636    )
7637 {
7638    assert(digraph != NULL);
7639    assert(node >= 0);
7640    assert(node < digraph->nnodes);
7641 
7642    digraph->nsuccessors[node] = nsuccessors;
7643 
7644    return SCIP_OKAY;
7645 }
7646 
7647 /** returns the number of nodes of the given digraph */
SCIPdigraphGetNNodes(SCIP_DIGRAPH * digraph)7648 int SCIPdigraphGetNNodes(
7649    SCIP_DIGRAPH*         digraph             /**< directed graph */
7650    )
7651 {
7652    assert(digraph != NULL);
7653 
7654    return digraph->nnodes;
7655 }
7656 
7657 /** returns the node data, or NULL if no data exist */
SCIPdigraphGetNodeData(SCIP_DIGRAPH * digraph,int node)7658 void* SCIPdigraphGetNodeData(
7659    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7660    int                   node                /**< node for which the node data is returned */
7661    )
7662 {
7663    assert(digraph != NULL);
7664    assert(node >= 0);
7665    assert(node < digraph->nnodes);
7666 
7667    return digraph->nodedata[node];
7668 }
7669 
7670 /** sets the node data
7671  *
7672  *  @note The old user pointer is not freed. This has to be done by the user
7673  */
SCIPdigraphSetNodeData(SCIP_DIGRAPH * digraph,void * dataptr,int node)7674 void SCIPdigraphSetNodeData(
7675    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7676    void*                 dataptr,            /**< user node data pointer, or NULL */
7677    int                   node                /**< node for which the node data is returned */
7678    )
7679 {
7680    assert(digraph != NULL);
7681    assert(node >= 0);
7682    assert(node < digraph->nnodes);
7683 
7684    digraph->nodedata[node] = dataptr;
7685 }
7686 
7687 /** returns the total number of arcs in the given digraph */
SCIPdigraphGetNArcs(SCIP_DIGRAPH * digraph)7688 int SCIPdigraphGetNArcs(
7689    SCIP_DIGRAPH*         digraph             /**< directed graph */
7690    )
7691 {
7692    int i;
7693    int narcs;
7694 
7695    assert(digraph != NULL);
7696 
7697    /* count number of arcs */
7698    narcs = 0;
7699    for( i = 0; i < digraph->nnodes; ++i )
7700       narcs += digraph->nsuccessors[i];
7701 
7702    return narcs;
7703 }
7704 
7705 /** returns the number of successor nodes of the given node */
SCIPdigraphGetNSuccessors(SCIP_DIGRAPH * digraph,int node)7706 int SCIPdigraphGetNSuccessors(
7707    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7708    int                   node                /**< node for which the number of outgoing arcs is returned */
7709    )
7710 {
7711    assert(digraph != NULL);
7712    assert(node >= 0);
7713    assert(node < digraph->nnodes);
7714    assert(digraph->nsuccessors[node] >= 0);
7715    assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7716 
7717    return digraph->nsuccessors[node];
7718 }
7719 
7720 /** returns the array of indices of the successor nodes; this array must not be changed from outside */
SCIPdigraphGetSuccessors(SCIP_DIGRAPH * digraph,int node)7721 int* SCIPdigraphGetSuccessors(
7722    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7723    int                   node                /**< node for which the array of outgoing arcs is returned */
7724    )
7725 {
7726    assert(digraph != NULL);
7727    assert(node >= 0);
7728    assert(node < digraph->nnodes);
7729    assert(digraph->nsuccessors[node] >= 0);
7730    assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7731    assert((digraph->nsuccessors[node] == 0) || (digraph->successors[node] != NULL));
7732 
7733    return digraph->successors[node];
7734 }
7735 
7736 /** returns the array of data corresponding to the arcs originating at the given node, or NULL if no data exist; this
7737  *  array must not be changed from outside
7738  */
SCIPdigraphGetSuccessorsData(SCIP_DIGRAPH * digraph,int node)7739 void** SCIPdigraphGetSuccessorsData(
7740    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7741    int                   node                /**< node for which the data corresponding to the outgoing arcs is returned */
7742    )
7743 {
7744    assert(digraph != NULL);
7745    assert(node >= 0);
7746    assert(node < digraph->nnodes);
7747    assert(digraph->nsuccessors[node] >= 0);
7748    assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7749    assert(digraph->arcdata != NULL);
7750 
7751    return digraph->arcdata[node];
7752 }
7753 
7754 /** performs depth-first-search in the given directed graph from the given start node */
7755 static
depthFirstSearch(SCIP_DIGRAPH * digraph,int startnode,SCIP_Bool * visited,int * dfsstack,int * stackadjvisited,int * dfsnodes,int * ndfsnodes)7756 void depthFirstSearch(
7757    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7758    int                   startnode,          /**< node to start the depth-first-search */
7759    SCIP_Bool*            visited,            /**< array to store for each node, whether it was already visited */
7760    int*                  dfsstack,           /**< array of size number of nodes to store the stack;
7761                                               *   only needed for performance reasons */
7762    int*                  stackadjvisited,    /**< array of size number of nodes to store the number of adjacent nodes already visited
7763                                               *   for each node on the stack; only needed for performance reasons */
7764    int*                  dfsnodes,           /**< array of nodes that can be reached starting at startnode, in reverse dfs order */
7765    int*                  ndfsnodes           /**< pointer to store number of nodes that can be reached starting at startnode */
7766    )
7767 {
7768    int stackidx;
7769 
7770    assert(digraph != NULL);
7771    assert(startnode >= 0);
7772    assert(startnode < digraph->nnodes);
7773    assert(visited != NULL);
7774    assert(visited[startnode] == FALSE);
7775    assert(dfsstack != NULL);
7776    assert(dfsnodes != NULL);
7777    assert(ndfsnodes != NULL);
7778 
7779    /* put start node on the stack */
7780    dfsstack[0] = startnode;
7781    stackadjvisited[0] = 0;
7782    stackidx = 0;
7783 
7784    while( stackidx >= 0 )
7785    {
7786       int currnode;
7787       int sadv;
7788 
7789       /* get next node from stack */
7790       currnode = dfsstack[stackidx];
7791 
7792       sadv = stackadjvisited[stackidx];
7793       assert( 0 <= sadv && sadv <= digraph->nsuccessors[currnode] );
7794 
7795       /* mark current node as visited */
7796       assert( visited[currnode] == (sadv > 0) );
7797       visited[currnode] = TRUE;
7798 
7799       /* iterate through the successor list until we reach unhandled node */
7800       while( sadv < digraph->nsuccessors[currnode] && visited[digraph->successors[currnode][sadv]] )
7801          ++sadv;
7802 
7803       /* the current node was completely handled, remove it from stack */
7804       if( sadv == digraph->nsuccessors[currnode] )
7805       {
7806          --stackidx;
7807 
7808          /* store node in the sorted nodes array */
7809          dfsnodes[(*ndfsnodes)++] = currnode;
7810       }
7811       /* handle next unhandled successor node */
7812       else
7813       {
7814          assert( ! visited[digraph->successors[currnode][sadv]] );
7815 
7816          /* store current stackadjvisted index */
7817          stackadjvisited[stackidx] = sadv + 1;
7818 
7819          /* put the successor node onto the stack */
7820          ++stackidx;
7821          dfsstack[stackidx] = digraph->successors[currnode][sadv];
7822          stackadjvisited[stackidx] = 0;
7823          assert( stackidx < digraph->nnodes );
7824       }
7825    }
7826 }
7827 
7828 /** checks for articulation points in a given directed graph through a recursive depth-first-search.
7829  *  starts from a given start node and keeps track of the nodes' discovery time in search for back edges.
7830  *
7831  *  @note an articulation point is a node whose removal disconnects a connected graph or increases
7832  *  the number of connected components in a disconnected graph
7833  */
7834 static
findArticulationPointsUtil(SCIP_DIGRAPH * digraph,int startnode,SCIP_Bool * visited,int * tdisc,int * mindisc,int * parent,SCIP_Bool * articulationflag,int time)7835 void findArticulationPointsUtil(
7836    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7837    int                   startnode,          /**< node to start the depth-first-search */
7838    SCIP_Bool*            visited,            /**< array to store for each node, whether it was already visited */
7839    int*                  tdisc,              /**< array of size number of nodes to store each node's discovery time */
7840    int*                  mindisc,            /**< array of size number of nodes to store the discovery time of the earliest discovered vertex
7841                                               *   to which startnode (or any node in the subtree rooted at it) is having a back edge */
7842    int*                  parent,             /**< array to store the parent of each node in the DFS tree */
7843    SCIP_Bool*            articulationflag,   /**< array to mark whether a node is identified as an articulation point */
7844    int                   time                /**< current discovery time in the DFS */
7845    )
7846 {
7847    int n;
7848    int nchildren = 0;
7849    int nsucc;
7850    int* succnodes;
7851 
7852    assert(digraph != NULL);
7853    assert(startnode >= 0);
7854    assert(startnode < digraph->nnodes);
7855    assert(visited != NULL);
7856    assert(visited[startnode] == FALSE);
7857    assert(tdisc != NULL);
7858    assert(mindisc != NULL);
7859    assert(parent != NULL);
7860    assert(articulationflag != NULL);
7861    assert(time >= 0);
7862 
7863    nsucc = (int) SCIPdigraphGetNSuccessors(digraph, startnode);
7864    succnodes = (int*) SCIPdigraphGetSuccessors(digraph, startnode);
7865    visited[startnode] = TRUE;
7866    tdisc[startnode] = time + 1;
7867    mindisc[startnode] = time + 1;
7868 
7869    /* process all the adjacent nodes to startnode */
7870    for( n = 0; n < nsucc; ++n)
7871    {
7872       if( !visited[succnodes[n]] )
7873       {
7874          parent[succnodes[n]] = startnode;
7875          ++nchildren;
7876          findArticulationPointsUtil(digraph, succnodes[n], visited, tdisc, mindisc, parent, articulationflag, time + 1);
7877          /* updated the mindisc of startnode when the DFS concludes for node n*/
7878          mindisc[startnode] = MIN(mindisc[startnode], mindisc[succnodes[n]]);
7879 
7880          /* the root is an articulation point if it has more than 2 children*/
7881          if( parent[startnode] == -1 && nchildren > 1 )
7882             articulationflag[startnode] = TRUE;
7883          /* a vertex startnode is an articulation point if it is not the root and
7884           * there is no back edge from the subtree rooted at child n to any of the ancestors of startnode */
7885          if( parent[startnode] > -1 && mindisc[succnodes[n]] >= tdisc[startnode] )
7886             articulationflag[startnode] = TRUE;
7887       }
7888       else
7889       {
7890          if( parent[startnode] != succnodes[n] )
7891             mindisc[startnode] = MIN(mindisc[startnode], tdisc[succnodes[n]]);
7892       }
7893    }
7894 
7895    if( articulationflag[startnode] )
7896       ++digraph->narticulations;
7897 }
7898 
7899 /** identifies the articulation points in a given directed graph
7900  *  uses the helper recursive function findArticulationPointsUtil
7901  */
SCIPdigraphGetArticulationPoints(SCIP_DIGRAPH * digraph,int ** articulations,int * narticulations)7902 SCIP_RETCODE SCIPdigraphGetArticulationPoints(
7903    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7904    int**                 articulations,      /**< array to store the sorted node indices of the computed articulation points, or NULL */
7905    int*                  narticulations      /**< number of the computed articulation points, or NULL */
7906    )
7907 {
7908    SCIP_RETCODE retcode = SCIP_OKAY;
7909    BMS_BLKMEM* blkmem;
7910    SCIP_Bool* visited = NULL;
7911    SCIP_Bool* articulationflag = NULL;
7912    int* tdisc = NULL;
7913    int* mindisc = NULL;
7914    int* parent = NULL;
7915    int n;
7916    int articulationidx = 0;
7917    int time = 0;
7918 
7919    assert(digraph != NULL);
7920    assert(digraph->nnodes > 0);
7921 
7922    /* Only perform the computation if the articulation points are NOT up-to-date */
7923    if( !digraph->articulationscheck )
7924    {
7925       SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&visited, digraph->nnodes), TERMINATE );
7926       SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&tdisc, digraph->nnodes), TERMINATE );
7927       SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&mindisc, digraph->nnodes), TERMINATE );
7928       SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&parent, digraph->nnodes), TERMINATE );
7929       SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&articulationflag, digraph->nnodes), TERMINATE );
7930 
7931       assert(digraph->blkmem != NULL);
7932       blkmem = digraph->blkmem;
7933 
7934       if( digraph->narticulations >= 0 ) /* case: articulations have already been computed but not up-to-date */
7935          BMSfreeBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations);
7936 
7937       /* Initialize the no. of articulation points ahead of the recursive computation */
7938       digraph->narticulations = 0;
7939 
7940       for( n = 0; n < digraph->nnodes; ++n )
7941       {
7942          visited[n] = FALSE;
7943          parent[n] = -1;
7944          articulationflag[n] = FALSE;
7945       }
7946 
7947       /* the function is called on every unvisited node in the graph to cover the disconnected graph case */
7948       for( n = 0; n < digraph->nnodes; ++n )
7949       {
7950          if( !visited[n] )
7951             findArticulationPointsUtil(digraph, n, visited, tdisc, mindisc, parent, articulationflag, time);
7952       }
7953 
7954       /* allocation of the block memory for the node indices of the articulation points*/
7955       SCIP_ALLOC_TERMINATE( retcode, BMSallocBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations), TERMINATE );
7956 
7957       for( n = 0; n < digraph->nnodes; ++n )
7958       {
7959          if( articulationflag[n] )
7960          {
7961             digraph->articulations[articulationidx] = n;
7962             ++articulationidx;
7963          }
7964       }
7965    }
7966 
7967    if( articulations != NULL )
7968       (*articulations) = digraph->articulations;
7969    if( narticulations != NULL )
7970       (*narticulations) = digraph->narticulations;
7971 
7972    /* the articulation points are now up-to-date */
7973    digraph->articulationscheck = TRUE;
7974 
7975 /* cppcheck-suppress unusedLabel */
7976 TERMINATE:
7977    BMSfreeMemoryArrayNull(&articulationflag);
7978    BMSfreeMemoryArrayNull(&parent);
7979    BMSfreeMemoryArrayNull(&mindisc);
7980    BMSfreeMemoryArrayNull(&tdisc);
7981    BMSfreeMemoryArrayNull(&visited);
7982 
7983    return retcode;
7984 }
7985 
7986 /** Compute undirected connected components on the given graph.
7987  *
7988  *  @note For each arc, its reverse is added, so the graph does not need to be the directed representation of an
7989  *        undirected graph.
7990  */
SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH * digraph,int minsize,int * components,int * ncomponents)7991 SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(
7992    SCIP_DIGRAPH*         digraph,            /**< directed graph */
7993    int                   minsize,            /**< all components with less nodes are ignored */
7994    int*                  components,         /**< array with as many slots as there are nodes in the directed graph
7995                                               *   to store for each node the component to which it belongs
7996                                               *   (components are numbered 0 to ncomponents - 1); or NULL, if components
7997                                               *   are accessed one-by-one using SCIPdigraphGetComponent() */
7998    int*                  ncomponents         /**< pointer to store the number of components; or NULL, if the
7999                                               *   number of components is accessed by SCIPdigraphGetNComponents() */
8000    )
8001 {
8002    BMS_BLKMEM* blkmem;
8003    SCIP_Bool* visited;
8004    int* ndirectedsuccessors;
8005    int* stackadjvisited;
8006    int* dfsstack;
8007    int ndfsnodes;
8008    int compstart;
8009    int v;
8010    int i;
8011    int j;
8012 
8013    SCIP_RETCODE retcode = SCIP_OKAY;
8014 
8015    assert(digraph != NULL);
8016    assert(digraph->nnodes > 0);
8017    assert(digraph->blkmem != NULL);
8018 
8019    blkmem = digraph->blkmem;
8020 
8021    /* first free the old components */
8022    if( digraph->ncomponents > 0 )
8023    {
8024       SCIPdigraphFreeComponents(digraph);
8025    }
8026 
8027    digraph->ncomponents = 0;
8028    digraph->componentstartsize = 10;
8029 
8030    /* storage to hold components is stored in block memory */
8031    SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes) );
8032    SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize) );
8033 
8034    /* allocate temporary arrays */
8035    SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8036    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8037    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8038    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&ndirectedsuccessors, digraph->nnodes), TERMINATE );
8039 
8040    digraph->componentstarts[0] = 0;
8041 
8042    /* store the number of directed arcs per node */
8043    BMScopyMemoryArray(ndirectedsuccessors, digraph->nsuccessors, digraph->nnodes);
8044 
8045    /* add reverse arcs to the graph */
8046    for( i = digraph->nnodes - 1; i >= 0; --i )
8047    {
8048       for( j = 0; j < ndirectedsuccessors[i]; ++j )
8049       {
8050          SCIP_CALL_TERMINATE( retcode, SCIPdigraphAddArc(digraph, digraph->successors[i][j], i, NULL), TERMINATE );
8051       }
8052    }
8053 
8054    for( v = 0; v < digraph->nnodes; ++v )
8055    {
8056       if( visited[v] )
8057          continue;
8058 
8059       compstart = digraph->componentstarts[digraph->ncomponents];
8060       ndfsnodes = 0;
8061       depthFirstSearch(digraph, v, visited, dfsstack, stackadjvisited,
8062          &digraph->components[compstart], &ndfsnodes);
8063 
8064       /* forget about this component if it is too small */
8065       if( ndfsnodes >= minsize )
8066       {
8067          digraph->ncomponents++;
8068 
8069          /* enlarge componentstartsize array, if needed */
8070          if( digraph->ncomponents >= digraph->componentstartsize )
8071          {
8072             int newsize;
8073 
8074             newsize = 2 * digraph->componentstartsize;
8075             assert(digraph->ncomponents < newsize);
8076 
8077             SCIP_ALLOC_TERMINATE( retcode, BMSreallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize, newsize), TERMINATE );
8078             digraph->componentstartsize = newsize;
8079          }
8080          digraph->componentstarts[digraph->ncomponents] = compstart + ndfsnodes;
8081 
8082          /* store component number for contained nodes if array was given */
8083          if( components != NULL )
8084          {
8085             for( i = digraph->componentstarts[digraph->ncomponents] - 1; i >= compstart; --i )
8086             {
8087                components[digraph->components[i]] = digraph->ncomponents - 1;
8088             }
8089          }
8090       }
8091    }
8092 
8093    /* restore the number of directed arcs per node */
8094    BMScopyMemoryArray(digraph->nsuccessors, ndirectedsuccessors, digraph->nnodes);
8095    BMSclearMemoryArray(visited, digraph->nnodes);
8096 
8097    /* return number of components, if the pointer was given */
8098    if( ncomponents != NULL )
8099       (*ncomponents) = digraph->ncomponents;
8100 
8101 TERMINATE:
8102    if( retcode != SCIP_OKAY )
8103    {
8104       SCIPdigraphFreeComponents(digraph);
8105    }
8106    BMSfreeMemoryArrayNull(&ndirectedsuccessors);
8107    BMSfreeMemoryArrayNull(&stackadjvisited);
8108    BMSfreeMemoryArrayNull(&dfsstack);
8109    BMSfreeMemoryArrayNull(&visited);
8110 
8111    return retcode;
8112 }
8113 
8114 /** Performs an (almost) topological sort on the undirected components of the given directed graph. The undirected
8115  *  components should be computed before using SCIPdigraphComputeUndirectedComponents().
8116  *
8117  *  @note In general a topological sort is not unique.  Note, that there might be directed cycles, that are randomly
8118  *        broken, which is the reason for having only almost topologically sorted arrays.
8119  */
SCIPdigraphTopoSortComponents(SCIP_DIGRAPH * digraph)8120 SCIP_RETCODE SCIPdigraphTopoSortComponents(
8121    SCIP_DIGRAPH*         digraph             /**< directed graph */
8122    )
8123 {
8124    SCIP_Bool* visited = NULL;
8125    int* comps;
8126    int* compstarts;
8127    int* stackadjvisited = NULL;
8128    int* dfsstack = NULL;
8129    int* dfsnodes = NULL;
8130    int ndfsnodes;
8131    int ncomps;
8132    int i;
8133    int j;
8134    int k;
8135    int endidx;
8136    SCIP_RETCODE retcode = SCIP_OKAY;
8137 
8138    assert(digraph != NULL);
8139 
8140    ncomps = digraph->ncomponents;
8141    comps = digraph->components;
8142    compstarts = digraph->componentstarts;
8143 
8144    SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8145    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsnodes, digraph->nnodes), TERMINATE );
8146    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8147    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8148 
8149    /* sort the components (almost) topologically */
8150    for( i = 0; i < ncomps; ++i )
8151    {
8152       endidx = compstarts[i+1] - 1;
8153       ndfsnodes = 0;
8154       for( j = compstarts[i]; j < compstarts[i+1]; ++j )
8155       {
8156          if( visited[comps[j]] )
8157             continue;
8158 
8159          /* perform depth first search, nodes visited in this call are appended to the list dfsnodes in reverse
8160           * dfs order, after the nodes already contained;
8161           * so at every point in time, the nodes in dfsnode are in reverse (almost) topological order
8162           */
8163          depthFirstSearch(digraph, comps[j], visited, dfsstack, stackadjvisited, dfsnodes, &ndfsnodes);
8164       }
8165       assert(endidx - ndfsnodes == compstarts[i] - 1);
8166 
8167       /* copy reverse (almost) topologically sorted array of nodes reached by the dfs searches;
8168        * reverse their order to get an (almost) topologically sort
8169        */
8170       for( k = 0; k < ndfsnodes; ++k )
8171       {
8172          digraph->components[endidx - k] = dfsnodes[k];
8173       }
8174    }
8175 
8176 TERMINATE:
8177    BMSfreeMemoryArrayNull(&stackadjvisited);
8178    BMSfreeMemoryArrayNull(&dfsstack);
8179    BMSfreeMemoryArrayNull(&dfsnodes);
8180    BMSfreeMemoryArrayNull(&visited);
8181 
8182    return retcode;
8183 }
8184 
8185 /** returns the number of previously computed undirected components for the given directed graph */
SCIPdigraphGetNComponents(SCIP_DIGRAPH * digraph)8186 int SCIPdigraphGetNComponents(
8187    SCIP_DIGRAPH*         digraph             /**< directed graph */
8188    )
8189 {
8190    assert(digraph != NULL);
8191    assert(digraph->componentstartsize > 0); /* components should have been computed */
8192 
8193    return digraph->ncomponents;
8194 }
8195 
8196 /** Returns the previously computed undirected component of the given number for the given directed graph.
8197  *  If the components were sorted using SCIPdigraphTopoSortComponents(), the component is (almost) topologically sorted.
8198  */
SCIPdigraphGetComponent(SCIP_DIGRAPH * digraph,int compidx,int ** nodes,int * nnodes)8199 void SCIPdigraphGetComponent(
8200    SCIP_DIGRAPH*         digraph,            /**< directed graph */
8201    int                   compidx,            /**< number of the component to return */
8202    int**                 nodes,              /**< pointer to store the nodes in the component; or NULL, if not needed */
8203    int*                  nnodes              /**< pointer to store the number of nodes in the component;
8204                                               *   or NULL, if not needed */
8205    )
8206 {
8207    assert(digraph != NULL);
8208    assert(compidx >= 0);
8209    assert(compidx < digraph->ncomponents);
8210    assert(nodes != NULL || nnodes != NULL);
8211 
8212    if( nodes != NULL )
8213       (*nodes) = &(digraph->components[digraph->componentstarts[compidx]]);
8214    if( nnodes != NULL )
8215       (*nnodes) = digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx];
8216 }
8217 
8218 /* Performs Tarjan's algorithm for a given directed graph to obtain the strongly connected components
8219  * which are reachable from a given node.
8220  */
8221 static
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)8222 void tarjan(
8223    SCIP_DIGRAPH*         digraph,            /**< directed graph */
8224    int                   v,                  /**< node to start the algorithm */
8225    int*                  lowlink,            /**< array to store lowlink values */
8226    int*                  dfsidx,             /**< array to store dfs indices */
8227    int*                  stack,              /**< array to store a stack */
8228    int*                  stacksize,          /**< pointer to store the size of the stack */
8229    SCIP_Bool*            unprocessed,        /**< array to store which node is unprocessed yet */
8230    SCIP_Bool*            nodeinstack,        /**< array to store which nodes are in the stack */
8231    int*                  maxdfs,             /**< pointer to store index for DFS */
8232    int*                  strongcomponents,   /**< array to store for each node the strongly connected
8233                                               *   component to which it belongs (components are
8234                                               *   numbered 0 to nstrongcomponents - 1); */
8235    int*                  nstrongcomponents,  /**< pointer to store the number of computed components so far */
8236    int*                  strongcompstartidx, /**< array to store the start index of the computed components */
8237    int*                  nstorednodes        /**< pointer to store the number of already stored nodes */
8238    )
8239 {
8240    int i;
8241 
8242    assert(digraph != NULL);
8243    assert(v >= 0);
8244    assert(v < digraph->nnodes);
8245    assert(lowlink != NULL);
8246    assert(dfsidx != NULL);
8247    assert(stack != NULL);
8248    assert(stacksize != NULL);
8249    assert(*stacksize >= 0);
8250    assert(*stacksize < digraph->nnodes);
8251    assert(unprocessed != NULL);
8252    assert(nodeinstack != NULL);
8253    assert(maxdfs != NULL);
8254    assert(strongcomponents != NULL);
8255    assert(nstrongcomponents != NULL);
8256    assert(strongcompstartidx != NULL);
8257    assert(nstorednodes != NULL);
8258    assert(*nstorednodes >= 0 && *nstorednodes < digraph->nnodes);
8259 
8260    dfsidx[v] = *maxdfs;
8261    lowlink[v] = *maxdfs;
8262    *maxdfs += 1;
8263 
8264    /* add v to the stack */
8265    stack[*stacksize] = v;
8266    *stacksize += 1;
8267    nodeinstack[v] = TRUE;
8268 
8269    /* mark v as processed */
8270    unprocessed[v] = FALSE;
8271 
8272    for( i = 0; i < digraph->nsuccessors[v]; ++i )
8273    {
8274       int w;
8275 
8276       /* edge (v,w) */
8277       w = digraph->successors[v][i];
8278 
8279       if( unprocessed[w] )
8280       {
8281          tarjan(digraph, w, lowlink, dfsidx, stack, stacksize, unprocessed, nodeinstack, maxdfs, strongcomponents,
8282                nstrongcomponents, strongcompstartidx, nstorednodes);
8283 
8284          assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8285          assert(lowlink[w] >= 0 && lowlink[w] < digraph->nnodes);
8286 
8287          /* update lowlink */
8288          lowlink[v] = MIN(lowlink[v], lowlink[w]);
8289       }
8290       else if( nodeinstack[w] )
8291       {
8292          assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8293          assert(dfsidx[w] >= 0 && dfsidx[w] < digraph->nnodes);
8294 
8295          /* update lowlink */
8296          lowlink[v] = MIN(lowlink[v], dfsidx[w]);
8297       }
8298    }
8299 
8300    /* found a root of a strong component */
8301    if( lowlink[v] == dfsidx[v] )
8302    {
8303       int w;
8304 
8305       strongcompstartidx[*nstrongcomponents] = *nstorednodes;
8306       *nstrongcomponents += 1;
8307 
8308       do
8309       {
8310          assert(*stacksize > 0);
8311 
8312          /* stack.pop() */
8313          w = stack[*stacksize - 1];
8314          *stacksize -= 1;
8315          nodeinstack[w] = FALSE;
8316 
8317          /* store the node in the corresponding component */
8318          strongcomponents[*nstorednodes] = w;
8319          *nstorednodes += 1;
8320       }
8321       while( v != w );
8322    }
8323 }
8324 
8325 /** Computes all strongly connected components of an undirected connected component with Tarjan's Algorithm.
8326  *  The resulting strongly connected components are sorted topologically (starting from the end of the
8327  *  strongcomponents array).
8328  *
8329  *  @note In general a topological sort of the strongly connected components is not unique.
8330  */
SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH * digraph,int compidx,int * strongcomponents,int * strongcompstartidx,int * nstrongcomponents)8331 SCIP_RETCODE SCIPdigraphComputeDirectedComponents(
8332    SCIP_DIGRAPH*         digraph,            /**< directed graph */
8333    int                   compidx,            /**< number of the undirected connected component */
8334    int*                  strongcomponents,   /**< array to store the strongly connected components
8335                                               *   (length >= size of the component) */
8336    int*                  strongcompstartidx, /**< array to store the start indices of the strongly connected
8337                                               *   components (length >= size of the component) */
8338    int*                  nstrongcomponents   /**< pointer to store the number of strongly connected
8339                                               *   components */
8340    )
8341 {
8342    int* lowlink;
8343    int* dfsidx;
8344    int* stack;
8345    int stacksize;
8346    SCIP_Bool* unprocessed;
8347    SCIP_Bool* nodeinstack;
8348    int maxdfs;
8349    int nstorednodes;
8350    int i;
8351    SCIP_RETCODE retcode;
8352 
8353    assert(digraph != NULL);
8354    assert(compidx >= 0);
8355    assert(compidx < digraph->ncomponents);
8356    assert(strongcomponents != NULL);
8357    assert(strongcompstartidx != NULL);
8358    assert(nstrongcomponents != NULL);
8359 
8360    retcode = SCIP_OKAY;
8361 
8362    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&lowlink, digraph->nnodes), TERMINATE );
8363    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsidx, digraph->nnodes), TERMINATE );
8364    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stack, digraph->nnodes), TERMINATE );
8365    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&unprocessed, digraph->nnodes), TERMINATE );
8366    SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&nodeinstack, digraph->nnodes), TERMINATE );
8367 
8368    for( i = 0; i < digraph->nnodes; ++i )
8369    {
8370       lowlink[i] = -1;
8371       dfsidx[i] = -1;
8372       stack[i] = -1;
8373       unprocessed[i] = TRUE;
8374       nodeinstack[i] = FALSE;
8375    }
8376 
8377    nstorednodes = 0;
8378    stacksize = 0;
8379    maxdfs = 0;
8380    *nstrongcomponents = 0;
8381 
8382    /* iterate over all nodes in the undirected connected component */
8383    for( i = digraph->componentstarts[compidx]; i < digraph->componentstarts[compidx + 1]; ++i )
8384    {
8385       int v;
8386 
8387       v = digraph->components[i];
8388       assert(v >= 0 && v < digraph->nnodes);
8389 
8390       /* call Tarjan's algorithm for unprocessed nodes */
8391       if( unprocessed[v] )
8392       {
8393          SCIPdebugMessage("apply Tarjan's algorithm for node %d\n", v);
8394          tarjan(digraph, v, lowlink, dfsidx, stack, &stacksize, unprocessed, nodeinstack, &maxdfs,
8395                strongcomponents, nstrongcomponents, strongcompstartidx, &nstorednodes);
8396       }
8397    }
8398 
8399    /* we should have stored as many nodes as in the undirected connected component */
8400    assert(nstorednodes == digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx]);
8401 
8402    /* to simplify the iteration over all strongly connected components */
8403    assert(*nstrongcomponents < digraph->nnodes + 1);
8404    strongcompstartidx[*nstrongcomponents] = nstorednodes;
8405 
8406    assert(retcode == SCIP_OKAY);
8407 
8408 TERMINATE:
8409    BMSfreeMemoryArrayNull(&lowlink);
8410    BMSfreeMemoryArrayNull(&dfsidx);
8411    BMSfreeMemoryArrayNull(&stack);
8412    BMSfreeMemoryArrayNull(&unprocessed);
8413    BMSfreeMemoryArrayNull(&nodeinstack);
8414 
8415    return retcode;
8416 }
8417 
8418 /** frees the component information for the given directed graph */
SCIPdigraphFreeComponents(SCIP_DIGRAPH * digraph)8419 void SCIPdigraphFreeComponents(
8420    SCIP_DIGRAPH*         digraph             /**< directed graph */
8421    )
8422 {
8423    BMS_BLKMEM* blkmem;
8424 
8425    assert(digraph != NULL);
8426    assert(digraph->blkmem != NULL);
8427 
8428    blkmem = digraph->blkmem;
8429 
8430    /* free components structure */
8431    if( digraph->componentstartsize > 0 )
8432    {
8433       BMSfreeBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize);
8434       BMSfreeBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes);
8435       digraph->components = NULL;
8436       digraph->componentstarts = NULL;
8437       digraph->ncomponents = 0;
8438       digraph->componentstartsize = 0;
8439    }
8440 #ifndef NDEBUG
8441    else
8442    {
8443       assert(digraph->components == NULL);
8444       assert(digraph->componentstarts == NULL);
8445       assert(digraph->ncomponents == 0);
8446    }
8447 #endif
8448 }
8449 
8450 /** output of the given directed graph via the given message handler */
SCIPdigraphPrint(SCIP_DIGRAPH * digraph,SCIP_MESSAGEHDLR * messagehdlr,FILE * file)8451 void SCIPdigraphPrint(
8452    SCIP_DIGRAPH*         digraph,            /**< directed graph */
8453    SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
8454    FILE*                 file                /**< output file (or NULL for standard output) */
8455    )
8456 {
8457    int n;
8458 
8459    for( n = 0; n < digraph->nnodes; ++n )
8460    {
8461       int* successors;
8462       int nsuccessors;
8463       int m;
8464 
8465       nsuccessors = digraph->nsuccessors[n];
8466       successors = digraph->successors[n];
8467 
8468       SCIPmessageFPrintInfo(messagehdlr, file, "node %d --> ", n);
8469 
8470       for( m = 0; m < nsuccessors ; ++m )
8471       {
8472          if( m == 0 )
8473          {
8474             SCIPmessageFPrintInfo(messagehdlr, file, "%d", successors[m]);
8475          }
8476          else
8477          {
8478             SCIPmessageFPrintInfo(messagehdlr, file, ", %d", successors[m]);
8479          }
8480       }
8481       SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8482    }
8483 }
8484 
8485 /** prints the given directed graph structure in GML format into the given file */
SCIPdigraphPrintGml(SCIP_DIGRAPH * digraph,FILE * file)8486 void SCIPdigraphPrintGml(
8487    SCIP_DIGRAPH*         digraph,            /**< directed graph */
8488    FILE*                 file                /**< file to write to */
8489    )
8490 {
8491    int n;
8492 
8493    /* write GML format opening */
8494    SCIPgmlWriteOpening(file, TRUE);
8495 
8496    /* write all nodes of the graph */
8497    for( n = 0; n < digraph->nnodes; ++n )
8498    {
8499       char label[SCIP_MAXSTRLEN];
8500 
8501       (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", n);
8502       SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", NULL, NULL);
8503    }
8504 
8505    /* write all edges */
8506    for( n = 0; n < digraph->nnodes; ++n )
8507    {
8508       int* successors;
8509       int nsuccessors;
8510       int m;
8511 
8512       nsuccessors = digraph->nsuccessors[n];
8513       successors = digraph->successors[n];
8514 
8515       for( m = 0; m < nsuccessors; ++m )
8516       {
8517          SCIPgmlWriteArc(file, (unsigned int)n, (unsigned int)successors[m], NULL, NULL);
8518       }
8519    }
8520    /* write GML format closing */
8521    SCIPgmlWriteClosing(file);
8522 }
8523 
8524 /** output of the given directed graph via the given message handler */
SCIPdigraphPrintComponents(SCIP_DIGRAPH * digraph,SCIP_MESSAGEHDLR * messagehdlr,FILE * file)8525 void SCIPdigraphPrintComponents(
8526    SCIP_DIGRAPH*         digraph,            /**< directed graph */
8527    SCIP_MESSAGEHDLR*     messagehdlr,        /**< message handler */
8528    FILE*                 file                /**< output file (or NULL for standard output) */
8529    )
8530 {
8531    int c;
8532    int i;
8533 
8534    for( c = 0; c < digraph->ncomponents; ++c )
8535    {
8536       int start = digraph->componentstarts[c];
8537       int end =  digraph->componentstarts[c+1];
8538 
8539       SCIPmessageFPrintInfo(messagehdlr, file, "Components %d --> ", c);
8540 
8541       for( i = start; i < end; ++i )
8542       {
8543          if( i == start )
8544          {
8545             SCIPmessageFPrintInfo(messagehdlr, file, "%d", digraph->components[i]);
8546          }
8547          else
8548          {
8549             SCIPmessageFPrintInfo(messagehdlr, file, ", %d", digraph->components[i]);
8550          }
8551       }
8552       SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8553    }
8554 }
8555 
8556 /*
8557  * Binary tree
8558  */
8559 
8560 /** creates a node for a binary tree */
8561 static
btnodeCreateEmpty(SCIP_BT * tree,SCIP_BTNODE ** node)8562 SCIP_RETCODE btnodeCreateEmpty(
8563    SCIP_BT*              tree,               /**< binary tree */
8564    SCIP_BTNODE**         node                /**< pointer to store the created node */
8565    )
8566 {
8567    SCIP_ALLOC( BMSallocBlockMemory(tree->blkmem, node) );
8568 
8569    (*node)->parent = NULL;
8570    (*node)->left = NULL;
8571    (*node)->right = NULL;
8572    (*node)->dataptr = NULL;
8573 
8574    return SCIP_OKAY;
8575 }
8576 
8577 /** creates a tree node with (optinal) user data */
SCIPbtnodeCreate(SCIP_BT * tree,SCIP_BTNODE ** node,void * dataptr)8578 SCIP_RETCODE SCIPbtnodeCreate(
8579    SCIP_BT*              tree,               /**< binary tree */
8580    SCIP_BTNODE**         node,               /**< pointer to store the created node */
8581    void*                 dataptr             /**< user node data pointer, or NULL */
8582    )
8583 {
8584    assert(tree != NULL);
8585    assert(node != NULL);
8586 
8587    SCIP_CALL( btnodeCreateEmpty(tree, node) );
8588 
8589    assert((*node)->parent == NULL);
8590    assert((*node)->left == NULL);
8591    assert((*node)->right == NULL);
8592 
8593    /* initialize user data */
8594    (*node)->dataptr = dataptr;
8595 
8596    return SCIP_OKAY;
8597 }
8598 
8599 /** frees a tree leaf */
8600 static
btnodeFreeLeaf(SCIP_BT * tree,SCIP_BTNODE ** node)8601 void btnodeFreeLeaf(
8602    SCIP_BT*              tree,               /**< binary tree */
8603    SCIP_BTNODE**         node                /**< pointer to node which has to be freed */
8604    )
8605 {
8606    assert(tree != NULL);
8607    assert(node != NULL);
8608    assert(*node != NULL);
8609 
8610    assert((*node)->left == NULL);
8611    assert((*node)->right == NULL);
8612 
8613 #if 0
8614    /* remove reference from parent node */
8615    if( (*node)->parent != NULL )
8616    {
8617       assert(*node != NULL);
8618 
8619       assert((*node)->parent->left == *node || ((*node)->parent->right == *node));
8620 
8621       if( (*node)->parent->left == *node )
8622       {
8623          (*node)->parent->left = NULL;
8624       }
8625       else
8626       {
8627          assert((*node)->parent->right == *node);
8628          (*node)->parent->right = NULL;
8629       }
8630    }
8631 #endif
8632 
8633    assert(*node != NULL);
8634    BMSfreeBlockMemory(tree->blkmem, node);
8635    assert(*node == NULL);
8636 }
8637 
8638 /** frees the node including the rooted subtree
8639  *
8640  *  @note The user pointer (object) is not freed. If needed, it has to be done by the user.
8641  */
SCIPbtnodeFree(SCIP_BT * tree,SCIP_BTNODE ** node)8642 void SCIPbtnodeFree(
8643    SCIP_BT*              tree,               /**< binary tree */
8644    SCIP_BTNODE**         node                /**< node to be freed */
8645    )
8646 {
8647    assert(tree != NULL);
8648    assert(node != NULL);
8649    assert(*node != NULL);
8650 
8651    if( (*node)->left != NULL )
8652    {
8653       SCIPbtnodeFree(tree, &(*node)->left);
8654       assert((*node)->left == NULL);
8655    }
8656 
8657    if( (*node)->right != NULL )
8658    {
8659       SCIPbtnodeFree(tree, &(*node)->right);
8660       assert((*node)->right == NULL);
8661    }
8662 
8663    btnodeFreeLeaf(tree, node);
8664    assert(*node == NULL);
8665 }
8666 
8667 /* some simple variable functions implemented as defines */
8668 
8669 /* In debug mode, the following methods are implemented as function calls to ensure
8670  * type validity.
8671  * In optimized mode, the methods are implemented as defines to improve performance.
8672  * However, we want to have them in the library anyways, so we have to undef the defines.
8673  */
8674 
8675 #undef SCIPbtnodeGetData
8676 #undef SCIPbtnodeGetKey
8677 #undef SCIPbtnodeGetParent
8678 #undef SCIPbtnodeGetLeftchild
8679 #undef SCIPbtnodeGetRightchild
8680 #undef SCIPbtnodeGetSibling
8681 #undef SCIPbtnodeIsRoot
8682 #undef SCIPbtnodeIsLeaf
8683 #undef SCIPbtnodeIsLeftchild
8684 #undef SCIPbtnodeIsRightchild
8685 
8686 /** returns the user data pointer stored in that node */
SCIPbtnodeGetData(SCIP_BTNODE * node)8687 void* SCIPbtnodeGetData(
8688    SCIP_BTNODE*          node                /**< node */
8689    )
8690 {
8691    assert(node != NULL);
8692 
8693    return node->dataptr;
8694 }
8695 
8696 /** returns the parent which can be NULL if the given node is the root */
SCIPbtnodeGetParent(SCIP_BTNODE * node)8697 SCIP_BTNODE* SCIPbtnodeGetParent(
8698    SCIP_BTNODE*          node                /**< node */
8699    )
8700 {
8701    assert(node != NULL);
8702 
8703    return node->parent;
8704 }
8705 
8706 /** returns left child which can be NULL if the given node is a leaf */
SCIPbtnodeGetLeftchild(SCIP_BTNODE * node)8707 SCIP_BTNODE* SCIPbtnodeGetLeftchild(
8708    SCIP_BTNODE*          node                /**< node */
8709    )
8710 {
8711    assert(node != NULL);
8712 
8713    return node->left;
8714 }
8715 
8716 /** returns right child which can be NULL if the given node is a leaf */
SCIPbtnodeGetRightchild(SCIP_BTNODE * node)8717 SCIP_BTNODE* SCIPbtnodeGetRightchild(
8718    SCIP_BTNODE*          node                /**< node */
8719    )
8720 {
8721    assert(node != NULL);
8722 
8723    return node->right;
8724 }
8725 
8726 /** returns the sibling of the node or NULL if does not exist */
SCIPbtnodeGetSibling(SCIP_BTNODE * node)8727 SCIP_BTNODE* SCIPbtnodeGetSibling(
8728    SCIP_BTNODE*          node                /**< node */
8729    )
8730 {
8731    SCIP_BTNODE* parent;
8732 
8733    parent = SCIPbtnodeGetParent(node);
8734 
8735    if( parent == NULL )
8736       return NULL;
8737 
8738    if( SCIPbtnodeGetLeftchild(parent) == node )
8739       return SCIPbtnodeGetRightchild(parent);
8740 
8741    assert(SCIPbtnodeGetRightchild(parent) == node);
8742 
8743    return SCIPbtnodeGetLeftchild(parent);
8744 }
8745 
8746 /** returns whether the node is a root node */
SCIPbtnodeIsRoot(SCIP_BTNODE * node)8747 SCIP_Bool SCIPbtnodeIsRoot(
8748    SCIP_BTNODE*          node                /**< node */
8749    )
8750 {
8751    assert(node != NULL);
8752 
8753    return (node->parent == NULL);
8754 }
8755 
8756 /** returns whether the node is a leaf */
SCIPbtnodeIsLeaf(SCIP_BTNODE * node)8757 SCIP_Bool SCIPbtnodeIsLeaf(
8758    SCIP_BTNODE*          node                /**< node */
8759    )
8760 {
8761    assert(node != NULL);
8762 
8763    return (node->left == NULL && node->right == NULL);
8764 }
8765 
8766 /** returns TRUE if the given node is left child */
SCIPbtnodeIsLeftchild(SCIP_BTNODE * node)8767 SCIP_Bool SCIPbtnodeIsLeftchild(
8768    SCIP_BTNODE*          node                /**< node */
8769    )
8770 {
8771    SCIP_BTNODE* parent;
8772 
8773    if( SCIPbtnodeIsRoot(node) )
8774       return FALSE;
8775 
8776    parent = SCIPbtnodeGetParent(node);
8777 
8778    if( SCIPbtnodeGetLeftchild(parent) == node )
8779       return TRUE;
8780 
8781    return FALSE;
8782 }
8783 
8784 /** returns TRUE if the given node is right child */
SCIPbtnodeIsRightchild(SCIP_BTNODE * node)8785 SCIP_Bool SCIPbtnodeIsRightchild(
8786    SCIP_BTNODE*          node                /**< node */
8787    )
8788 {
8789    SCIP_BTNODE* parent;
8790 
8791    if( SCIPbtnodeIsRoot(node) )
8792       return FALSE;
8793 
8794    parent = SCIPbtnodeGetParent(node);
8795 
8796    if( SCIPbtnodeGetRightchild(parent) == node )
8797       return TRUE;
8798 
8799    return FALSE;
8800 }
8801 
8802 /** sets the give node data
8803  *
8804  *  @note The old user pointer is not freed.
8805  */
SCIPbtnodeSetData(SCIP_BTNODE * node,void * dataptr)8806 void SCIPbtnodeSetData(
8807    SCIP_BTNODE*          node,               /**< node */
8808    void*                 dataptr             /**< node user data pointer */
8809    )
8810 {
8811    assert(node != NULL);
8812 
8813    node->dataptr = dataptr;
8814 }
8815 
8816 /** sets parent node
8817  *
8818  *  @note The old parent including the rooted subtree is not delete.
8819  */
SCIPbtnodeSetParent(SCIP_BTNODE * node,SCIP_BTNODE * parent)8820 void SCIPbtnodeSetParent(
8821    SCIP_BTNODE*          node,               /**< node */
8822    SCIP_BTNODE*          parent              /**< new parent node, or NULL */
8823    )
8824 {
8825    assert(node != NULL);
8826 
8827    node->parent = parent;
8828 }
8829 
8830 /** sets left child
8831  *
8832  *  @note The old left child including the rooted subtree is not delete.
8833  */
SCIPbtnodeSetLeftchild(SCIP_BTNODE * node,SCIP_BTNODE * left)8834 void SCIPbtnodeSetLeftchild(
8835    SCIP_BTNODE*          node,               /**< node */
8836    SCIP_BTNODE*          left                /**< new left child, or NULL */
8837    )
8838 {
8839    assert(node != NULL);
8840 
8841    node->left = left;
8842 }
8843 
8844 /** sets right child
8845  *
8846  *  @note The old right child including the rooted subtree is not delete.
8847  */
SCIPbtnodeSetRightchild(SCIP_BTNODE * node,SCIP_BTNODE * right)8848 void SCIPbtnodeSetRightchild(
8849    SCIP_BTNODE*          node,               /**< node */
8850    SCIP_BTNODE*          right               /**< new right child, or NULL */
8851    )
8852 {
8853    assert(node != NULL);
8854 
8855    node->right = right;
8856 }
8857 
8858 /** creates an binary tree */
SCIPbtCreate(SCIP_BT ** tree,BMS_BLKMEM * blkmem)8859 SCIP_RETCODE SCIPbtCreate(
8860    SCIP_BT**             tree,               /**< pointer to store the created binary tree */
8861    BMS_BLKMEM*           blkmem              /**< block memory used to createnode */
8862    )
8863 {
8864    assert(tree != NULL);
8865    assert(blkmem != NULL);
8866 
8867    SCIP_ALLOC( BMSallocBlockMemory(blkmem, tree) );
8868    (*tree)->blkmem = blkmem;
8869    (*tree)->root = NULL;
8870 
8871    return SCIP_OKAY;
8872 }
8873 
8874 /** frees binary tree
8875  *
8876  *  @note The user pointers (object) of the nodes are not freed. If needed, it has to be done by the user.
8877  */
SCIPbtFree(SCIP_BT ** tree)8878 void SCIPbtFree(
8879    SCIP_BT**             tree                /**< pointer to binary tree */
8880    )
8881 {
8882    assert(tree != NULL);
8883 
8884    if( (*tree)->root != NULL )
8885    {
8886       SCIPbtnodeFree(*tree, &((*tree)->root));
8887    }
8888 
8889    BMSfreeBlockMemory((*tree)->blkmem, tree);
8890 }
8891 
8892 /** prints the rooted subtree of the given binary tree node in GML format into the given file */
8893 static
btPrintSubtree(SCIP_BTNODE * node,FILE * file,int * nnodes)8894 void btPrintSubtree(
8895    SCIP_BTNODE*          node,               /**< binary tree node */
8896    FILE*                 file,               /**< file to write to */
8897    int*                  nnodes              /**< pointer to count the number of nodes */
8898    )
8899 {
8900    SCIP_BTNODE* left;
8901    SCIP_BTNODE* right;
8902    char label[SCIP_MAXSTRLEN];
8903 
8904    assert(node != NULL);
8905 
8906    (*nnodes)++;
8907    (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", *nnodes);
8908 
8909    SCIPgmlWriteNode(file, (unsigned int)(size_t)node, label, "circle", NULL, NULL);
8910 
8911    left = SCIPbtnodeGetLeftchild(node);
8912    right = SCIPbtnodeGetRightchild(node);
8913 
8914    if( left != NULL )
8915    {
8916       btPrintSubtree(left, file, nnodes);
8917 
8918       SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)left, NULL, NULL);
8919    }
8920 
8921    if( right != NULL )
8922    {
8923       btPrintSubtree(right, file, nnodes);
8924 
8925       SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)right, NULL, NULL);
8926    }
8927 }
8928 
8929 /** prints the binary tree in GML format into the given file */
SCIPbtPrintGml(SCIP_BT * tree,FILE * file)8930 void SCIPbtPrintGml(
8931    SCIP_BT*              tree,               /**< binary tree */
8932    FILE*                 file                /**< file to write to */
8933    )
8934 {
8935    /* write GML opening */
8936    SCIPgmlWriteOpening(file, TRUE);
8937 
8938    if( !SCIPbtIsEmpty(tree) )
8939    {
8940       SCIP_BTNODE* root;
8941       int nnodes;
8942 
8943       root = SCIPbtGetRoot(tree);
8944       assert(root != NULL);
8945 
8946       nnodes = 0;
8947 
8948       btPrintSubtree(root, file, &nnodes);
8949    }
8950 
8951    /* write GML closing */
8952    SCIPgmlWriteClosing(file);
8953 }
8954 
8955 /* some simple variable functions implemented as defines */
8956 #undef SCIPbtIsEmpty
8957 #undef SCIPbtGetRoot
8958 
8959 /** returns whether the binary tree is empty (has no nodes) */
SCIPbtIsEmpty(SCIP_BT * tree)8960 SCIP_Bool SCIPbtIsEmpty(
8961    SCIP_BT*              tree                /**< binary tree */
8962    )
8963 {
8964    assert(tree != NULL);
8965 
8966    return (tree->root == NULL);
8967 }
8968 
8969 /** returns the the root node of the binary or NULL if the binary tree is empty */
SCIPbtGetRoot(SCIP_BT * tree)8970 SCIP_BTNODE* SCIPbtGetRoot(
8971    SCIP_BT*              tree                /**< tree to be evaluated */
8972    )
8973 {
8974    assert(tree != NULL);
8975 
8976    return tree->root;
8977 }
8978 
8979 /** sets root node
8980  *
8981  *  @note The old root including the rooted subtree is not delete.
8982  */
SCIPbtSetRoot(SCIP_BT * tree,SCIP_BTNODE * root)8983 void SCIPbtSetRoot(
8984    SCIP_BT*              tree,               /**< tree to be evaluated */
8985    SCIP_BTNODE*          root                /**< new root, or NULL */
8986    )
8987 {
8988    assert(tree != NULL);
8989 
8990    tree->root = root;
8991 }
8992 
8993 
8994 /*
8995  * Numerical methods
8996  */
8997 
8998 /** returns the machine epsilon: the smallest number eps > 0, for which 1.0 + eps > 1.0 */
SCIPcalcMachineEpsilon(void)8999 SCIP_Real SCIPcalcMachineEpsilon(
9000    void
9001    )
9002 {
9003    SCIP_Real eps;
9004    SCIP_Real lasteps;
9005    SCIP_Real one;
9006    SCIP_Real onepluseps;
9007 
9008    one = 1.0;
9009    eps = 1.0;
9010    do
9011    {
9012       lasteps = eps;
9013       eps /= 2.0;
9014       onepluseps = one + eps;
9015    }
9016    while( onepluseps > one );
9017 
9018    return lasteps;
9019 }
9020 
9021 /** calculates the greatest common divisor of the two given values */
SCIPcalcGreComDiv(SCIP_Longint val1,SCIP_Longint val2)9022 SCIP_Longint SCIPcalcGreComDiv(
9023    SCIP_Longint          val1,               /**< first value of greatest common devisor calculation */
9024    SCIP_Longint          val2                /**< second value of greatest common devisor calculation */
9025    )
9026 {
9027    int t;
9028 
9029    assert(val1 > 0);
9030    assert(val2 > 0);
9031 
9032    t = 0;
9033    /* if val1 is even, divide it by 2 */
9034    while( !(val1 & 1) )
9035    {
9036       val1 >>= 1; /*lint !e704*/
9037 
9038       /* if val2 is even too, divide it by 2 and increase t(=number of e) */
9039       if( !(val2 & 1) )
9040       {
9041          val2 >>= 1; /*lint !e704*/
9042          ++t;
9043       }
9044       /* only val1 can be odd */
9045       else
9046       {
9047          /* while val1 is even, divide it by 2 */
9048          while( !(val1 & 1) )
9049             val1 >>= 1; /*lint !e704*/
9050 
9051          break;
9052       }
9053    }
9054 
9055    /* while val2 is even, divide it by 2 */
9056    while( !(val2 & 1) )
9057       val2 >>= 1; /*lint !e704*/
9058 
9059    /* the following if/else condition is only to make sure that we do not overflow when adding up both values before
9060     * dividing them by 4 in the following while loop
9061     */
9062    if( t == 0 )
9063    {
9064       if( val1 > val2 )
9065       {
9066          val1 -= val2;
9067 
9068          /* divide val1 by 2 as long as possible  */
9069          while( !(val1 & 1) )
9070             val1 >>= 1;   /*lint !e704*/
9071       }
9072       else if( val1 < val2 )
9073       {
9074          val2 -= val1;
9075 
9076          /* divide val2 by 2 as long as possible  */
9077          while( !(val2 & 1) )
9078             val2 >>= 1;   /*lint !e704*/
9079       }
9080    }
9081 
9082    /* val1 and val2 are odd */
9083    while( val1 != val2 )
9084    {
9085       if( val1 > val2 )
9086       {
9087          /* we can stop if one value reached one */
9088          if( val2 == 1 )
9089             return (val2 << t);  /*lint !e647 !e703*/
9090 
9091          /* if ((val1 xor val2) and 2) = 2, then gcd(val1, val2) = gcd((val1 + val2)/4, val2),
9092           * and otherwise                        gcd(val1, val2) = gcd((val1 − val2)/4, val2)
9093           */
9094          if( ((val1 ^ val2) & 2) == 2 )
9095             val1 += val2;
9096          else
9097             val1 -= val2;
9098 
9099          assert((val1 & 3) == 0);
9100          val1 >>= 2;   /*lint !e704*/
9101 
9102          /* if val1 is still even, divide it by 2  */
9103          while( !(val1 & 1) )
9104             val1 >>= 1;   /*lint !e704*/
9105       }
9106       else
9107       {
9108          /* we can stop if one value reached one */
9109          if( val1 == 1 )
9110             return (val1 << t);  /*lint !e647 !e703*/
9111 
9112          /* if ((val2 xor val1) and 2) = 2, then gcd(val2, val1) = gcd((val2 + val1)/4, val1),
9113           * and otherwise                        gcd(val2, val1) = gcd((val2 − val1)/4, val1)
9114           */
9115          if( ((val2 ^ val1) & 2) == 2 )
9116             val2 += val1;
9117          else
9118             val2 -= val1;
9119 
9120          assert((val2 & 3) == 0);
9121          val2 >>= 2;   /*lint !e704*/
9122 
9123          /* if val2 is still even, divide it by 2  */
9124          while( !(val2 & 1) )
9125             val2 >>= 1;   /*lint !e704*/
9126       }
9127    }
9128 
9129    return (val1 << t);  /*lint !e703*/
9130 }
9131 
9132 
9133 /* for the MS compiler, the function nextafter is named _nextafter */
9134 #if defined(_MSC_VER) && !defined(NO_NEXTAFTER)
9135 #define nextafter(x,y) _nextafter(x,y)
9136 #endif
9137 
9138 /* on systems where the function nextafter is not defined, we provide an implementation from Sun */
9139 #ifdef NO_NEXTAFTER
9140 /* The following implementation of the routine nextafter() comes with the following license:
9141  *
9142  * ====================================================
9143  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9144  *
9145  * Developed at SunSoft, a Sun Microsystems, Inc. business.
9146  * Permission to use, copy, modify, and distribute this
9147  * software is freely granted, provided that this notice
9148  * is preserved.
9149  * ====================================================
9150  */
9151 
9152 #define __HI(x) *(1+(int*)&x)
9153 #define __LO(x) *(int*)&x
9154 #define __HIp(x) *(1+(int*)x)
9155 #define __LOp(x) *(int*)x
9156 
9157 static
nextafter(double x,double y)9158 double nextafter(double x, double y)
9159 {
9160    int hx;
9161    int hy;
9162    int ix;
9163    int iy;
9164    unsigned lx;
9165    unsigned ly;
9166 
9167    /* cppcheck-suppress invalidPointerCast */
9168    hx = __HI(x);     /* high word of x */
9169    /* cppcheck-suppress invalidPointerCast */
9170    lx = __LO(x);     /* low  word of x */
9171    /* cppcheck-suppress invalidPointerCast */
9172    hy = __HI(y);     /* high word of y */
9173    /* cppcheck-suppress invalidPointerCast */
9174    ly = __LO(y);     /* low  word of y */
9175    ix = hx&0x7fffffff;     /* |x| */
9176    iy = hy&0x7fffffff;     /* |y| */
9177 
9178    if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) ||   /* x is nan */
9179       ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 ))     /* y is nan */
9180       return x + y;
9181 
9182    /* x == y, return x */
9183    if( x == y )
9184       return x;
9185 
9186    /* x == 0 */
9187    if( (ix|lx) == 0 )
9188    {
9189       /* return +-minsubnormal */
9190       /* cppcheck-suppress invalidPointerCast */
9191       __HI(x) = hy&0x80000000;
9192       /* cppcheck-suppress invalidPointerCast */
9193       __LO(x) = 1;
9194       y = x * x;
9195       if ( y == x )
9196          return y;
9197       else
9198          return x;  /* raise underflow flag */
9199    }
9200    /* x > 0 */
9201    if( hx >= 0 )
9202    {
9203       /* x > y, x -= ulp */
9204       if( hx > hy || ((hx == hy) && (lx > ly)) )
9205       {
9206          if ( lx == 0 )
9207             hx -= 1;
9208          lx -= 1;
9209       }
9210       else
9211       {
9212          /* x < y, x += ulp */
9213          lx += 1;
9214          if ( lx == 0 )
9215             hx += 1;
9216       }
9217    }
9218    else
9219    {
9220       /* x < 0 */
9221       if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
9222       {
9223          /* x < y, x -= ulp */
9224          if ( lx == 0 )
9225             hx -= 1;
9226          lx -= 1;
9227       }
9228       else
9229       {
9230          /* x > y, x += ulp */
9231          lx += 1;
9232          if( lx == 0 )
9233             hx += 1;
9234       }
9235    }
9236    hy = hx&0x7ff00000;
9237    /* overflow  */
9238    if( hy >= 0x7ff00000 )
9239       return x + x;
9240    if( hy < 0x00100000 )
9241    {
9242       /* underflow */
9243       y = x*x;
9244       if( y != x )
9245       {
9246          /* raise underflow flag */
9247          /* cppcheck-suppress invalidPointerCast */
9248          __HI(y) = hx;
9249          /* cppcheck-suppress invalidPointerCast */
9250          __LO(y) = lx;
9251          return y;
9252       }
9253    }
9254 
9255    /* cppcheck-suppress invalidPointerCast */
9256    __HI(x) = hx;
9257    /* cppcheck-suppress invalidPointerCast */
9258    __LO(x) = lx;
9259    return x;
9260 }
9261 #endif
9262 
9263 
9264 /** returns the next representable value of from in the direction of to */
SCIPnextafter(SCIP_Real from,SCIP_Real to)9265 SCIP_Real SCIPnextafter(
9266    SCIP_Real             from,               /**< value from which the next representable value should be returned */
9267    SCIP_Real             to                  /**< direction in which the next representable value should be returned */
9268    )
9269 {
9270    return nextafter(from, to);
9271 }
9272 
9273 /** calculates the smallest common multiple of the two given values */
SCIPcalcSmaComMul(SCIP_Longint val1,SCIP_Longint val2)9274 SCIP_Longint SCIPcalcSmaComMul(
9275    SCIP_Longint          val1,               /**< first value of smallest common multiple calculation */
9276    SCIP_Longint          val2                /**< second value of smallest common multiple calculation */
9277    )
9278 {
9279    SCIP_Longint gcd;
9280 
9281    assert(val1 > 0);
9282    assert(val2 > 0);
9283 
9284    gcd = SCIPcalcGreComDiv(val1, val2);
9285 
9286    return val1/gcd * val2;
9287 }
9288 
9289 static 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,
9290                                    17.0, 18.0, 19.0, 25.0, -1.0};
9291 
9292 /** converts a real number into a (approximate) rational representation, and returns TRUE iff the conversion was
9293  *  successful
9294  */
SCIPrealToRational(SCIP_Real val,SCIP_Real mindelta,SCIP_Real maxdelta,SCIP_Longint maxdnom,SCIP_Longint * nominator,SCIP_Longint * denominator)9295 SCIP_Bool SCIPrealToRational(
9296    SCIP_Real             val,                /**< real value r to convert into rational number */
9297    SCIP_Real             mindelta,           /**< minimal allowed difference r - q of real r and rational q = n/d */
9298    SCIP_Real             maxdelta,           /**< maximal allowed difference r - q of real r and rational q = n/d */
9299    SCIP_Longint          maxdnom,            /**< maximal denominator allowed */
9300    SCIP_Longint*         nominator,          /**< pointer to store the nominator n of the rational number */
9301    SCIP_Longint*         denominator         /**< pointer to store the denominator d of the rational number */
9302    )
9303 {
9304    SCIP_Real a;
9305    SCIP_Real b;
9306    SCIP_Real g0;
9307    SCIP_Real g1;
9308    SCIP_Real gx;
9309    SCIP_Real h0;
9310    SCIP_Real h1;
9311    SCIP_Real hx;
9312    SCIP_Real delta0;
9313    SCIP_Real delta1;
9314    SCIP_Real epsilon;
9315    int i;
9316 
9317    assert(mindelta < 0.0);
9318    assert(maxdelta > 0.0);
9319    assert(nominator != NULL);
9320    assert(denominator != NULL);
9321 
9322    if( REALABS(val) >= ((SCIP_Real)SCIP_LONGINT_MAX) / maxdnom )
9323       return FALSE;
9324 
9325    /* try the simple denominators first: each value of the simpledenoms table multiplied by powers of 10
9326     * is tried as denominator
9327     */
9328    for( i = 0; simplednoms[i] > 0.0; ++i )
9329    {
9330       SCIP_Real nom;
9331       SCIP_Real dnom;
9332       SCIP_Real ratval0;
9333       SCIP_Real ratval1;
9334 
9335       /* try powers of 10 (including 10^0) */
9336       dnom = simplednoms[i];
9337       while( dnom <= maxdnom )
9338       {
9339          nom = floor(val * dnom);
9340          ratval0 = nom/dnom;
9341          ratval1 = (nom+1.0)/dnom;
9342          if( mindelta <= val - ratval0 && val - ratval1 <= maxdelta )
9343          {
9344             if( val - ratval0 <= maxdelta )
9345             {
9346                *nominator = (SCIP_Longint)nom;
9347                *denominator = (SCIP_Longint)dnom;
9348                return TRUE;
9349             }
9350             if( mindelta <= val - ratval1 )
9351             {
9352                *nominator = (SCIP_Longint)(nom+1.0);
9353                *denominator = (SCIP_Longint)dnom;
9354                return TRUE;
9355             }
9356          }
9357          dnom *= 10.0;
9358       }
9359    }
9360 
9361    /* the simple denominators didn't work: calculate rational representation with arbitrary denominator */
9362    epsilon = MIN(-mindelta, maxdelta)/2.0;
9363 
9364    b = val;
9365    a = EPSFLOOR(b, epsilon);
9366    g0 = a;
9367    h0 = 1.0;
9368    g1 = 1.0;
9369    h1 = 0.0;
9370    delta0 = val - g0/h0;
9371    delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9372 
9373    while( (delta0 < mindelta || delta0 > maxdelta) && (delta1 < mindelta || delta1 > maxdelta) )
9374    {
9375       assert(EPSGT(b, a, epsilon));
9376       assert(h0 >= 0.0);
9377       assert(h1 >= 0.0);
9378 
9379       b = 1.0 / (b - a);
9380       a = EPSFLOOR(b, epsilon);
9381 
9382       assert(a >= 0.0);
9383       gx = g0;
9384       hx = h0;
9385 
9386       g0 = a * g0 + g1;
9387       h0 = a * h0 + h1;
9388 
9389       g1 = gx;
9390       h1 = hx;
9391 
9392       if( h0 > maxdnom )
9393          return FALSE;
9394 
9395       delta0 = val - g0/h0;
9396       delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9397    }
9398 
9399    if( REALABS(g0) > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) || h0 > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) )
9400       return FALSE;
9401 
9402    assert(h0 > 0.5);
9403 
9404    if( delta0 < mindelta )
9405    {
9406       assert(mindelta <= delta1 && delta1 <= maxdelta);
9407       *nominator = (SCIP_Longint)(g0 - 1.0);
9408       *denominator = (SCIP_Longint)h0;
9409    }
9410    else if( delta0 > maxdelta )
9411    {
9412       assert(mindelta <= delta1 && delta1 <= maxdelta);
9413       *nominator = (SCIP_Longint)(g0 + 1.0);
9414       *denominator = (SCIP_Longint)h0;
9415    }
9416    else
9417    {
9418       *nominator = (SCIP_Longint)g0;
9419       *denominator = (SCIP_Longint)h0;
9420    }
9421    assert(*denominator >= 1);
9422    assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) >= mindelta);
9423    assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) <= maxdelta);
9424 
9425    return TRUE;
9426 }
9427 
9428 /** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
9429 static
isIntegralScalar(SCIP_Real val,SCIP_Real scalar,SCIP_Real mindelta,SCIP_Real maxdelta)9430 SCIP_Bool isIntegralScalar(
9431    SCIP_Real             val,                /**< value that should be scaled to an integral value */
9432    SCIP_Real             scalar,             /**< scalar that should be tried */
9433    SCIP_Real             mindelta,           /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9434    SCIP_Real             maxdelta            /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9435    )
9436 {
9437    SCIP_Real sval;
9438    SCIP_Real downval;
9439    SCIP_Real upval;
9440 
9441    assert(mindelta <= 0.0);
9442    assert(maxdelta >= 0.0);
9443 
9444    sval = val * scalar;
9445    downval = floor(sval);
9446    upval = ceil(sval);
9447 
9448    return (SCIPrelDiff(sval, downval) <= maxdelta || SCIPrelDiff(sval, upval) >= mindelta);
9449 }
9450 
9451 /** additional scalars that are tried in integrality scaling */
9452 static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
9453 static const int nscalars = 9;
9454 
9455 /** tries to find a value, such that all given values, if scaled with this value become integral in relative allowed
9456  *  difference in between mindelta and maxdelta
9457  */
SCIPcalcIntegralScalar(SCIP_Real * vals,int nvals,SCIP_Real mindelta,SCIP_Real maxdelta,SCIP_Longint maxdnom,SCIP_Real maxscale,SCIP_Real * intscalar,SCIP_Bool * success)9458 SCIP_RETCODE SCIPcalcIntegralScalar(
9459    SCIP_Real*            vals,               /**< values to scale */
9460    int                   nvals,              /**< number of values to scale */
9461    SCIP_Real             mindelta,           /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9462    SCIP_Real             maxdelta,           /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9463    SCIP_Longint          maxdnom,            /**< maximal denominator allowed in rational numbers */
9464    SCIP_Real             maxscale,           /**< maximal allowed scalar */
9465    SCIP_Real*            intscalar,          /**< pointer to store scalar that would make the coefficients integral, or NULL */
9466    SCIP_Bool*            success             /**< stores whether returned value is valid */
9467    )
9468 {
9469    SCIP_Real bestscalar;
9470    SCIP_Longint gcd;
9471    SCIP_Longint scm;
9472    SCIP_Longint nominator;
9473    SCIP_Longint denominator;
9474    SCIP_Real val;
9475    SCIP_Real minval;
9476    SCIP_Real absval;
9477    SCIP_Real scaleval;
9478    SCIP_Bool scalable;
9479    SCIP_Bool rational;
9480    int c;
9481    int s;
9482    int i;
9483 
9484    assert(vals != NULL);
9485    assert(nvals >= 0);
9486    assert(maxdnom >= 1);
9487    assert(mindelta < 0.0);
9488    assert(maxdelta > 0.0);
9489    assert(success != NULL);
9490 
9491    SCIPdebugMessage("trying to find rational representation for given values\n");
9492 
9493    if( intscalar != NULL )
9494       *intscalar = SCIP_INVALID;
9495    *success = FALSE;
9496 
9497    /* get minimal absolute non-zero value */
9498    minval = SCIP_REAL_MAX;
9499    for( c = 0; c < nvals; ++c )
9500    {
9501       val = vals[c];
9502       if( val < mindelta || val > maxdelta )
9503       {
9504          absval = REALABS(val);
9505          minval = MIN(minval, absval);
9506       }
9507    }
9508 
9509    if( minval == SCIP_REAL_MAX ) /*lint !e777*/
9510    {
9511       /* all coefficients are zero (inside tolerances) */
9512       if( intscalar != NULL )
9513          *intscalar = 1.0;
9514       *success = TRUE;
9515       SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
9516 
9517       return SCIP_OKAY;
9518    }
9519    assert(minval > MIN(-mindelta, maxdelta));
9520 
9521    bestscalar = SCIP_INVALID;
9522 
9523    for( i = 0; i < 2; ++i )
9524    {
9525       scalable = TRUE;
9526 
9527       /* try, if values can be made integral multiplying them with the reciprocal of the smallest value and a power of 2 */
9528       if( i == 0 )
9529 	 scaleval = 1.0/minval;
9530       /* try, if values can be made integral by multiplying them by a power of 2 */
9531       else
9532 	 scaleval = 1.0;
9533 
9534       for( c = 0; c < nvals && scalable; ++c )
9535       {
9536 	 /* check, if the value can be scaled with a simple scalar */
9537 	 val = vals[c];
9538 	 if( val == 0.0 ) /* zeros are allowed in the vals array */
9539 	    continue;
9540 
9541 	 absval = REALABS(val);
9542 	 while( scaleval <= maxscale
9543 	    && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta)) )
9544 	 {
9545 	    for( s = 0; s < nscalars; ++s )
9546 	    {
9547 	       if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta) )
9548 	       {
9549 		  scaleval *= scalars[s];
9550 		  break;
9551 	       }
9552 	    }
9553 	    if( s >= nscalars )
9554 	       scaleval *= 2.0;
9555 	 }
9556 	 scalable = (scaleval <= maxscale);
9557 	 SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
9558 	    val, scaleval, val*scaleval, scalable);
9559       }
9560       if( scalable )
9561       {
9562 	 /* make values integral by dividing them by the smallest value (and multiplying them with a power of 2) */
9563 	 assert(scaleval <= maxscale);
9564 
9565 	 /* check if we found a better scaling value */
9566 	 if( scaleval < bestscalar )
9567 	    bestscalar = scaleval;
9568 
9569 	 SCIPdebugMessage(" -> integrality could be achieved by scaling with %g\n", scaleval);
9570 
9571 	 /* if the scalar is still the reciprocal of the minimal value, all coeffcients are the same and we do not get a better scalar */
9572 	 if( i == 0 && EPSEQ(scaleval, 1.0/minval, SCIP_DEFAULT_EPSILON) )
9573 	 {
9574 	    if( intscalar != NULL )
9575 	       *intscalar = bestscalar;
9576 	    *success = TRUE;
9577 
9578 	    return SCIP_OKAY;
9579 	 }
9580       }
9581    }
9582 
9583    /* convert each value into a rational number, calculate the greatest common divisor of the nominators
9584     * and the smallest common multiple of the denominators
9585     */
9586    gcd = 1;
9587    scm = 1;
9588    rational = TRUE;
9589 
9590    /* first value (to initialize gcd) */
9591    for( c = 0; c < nvals && rational; ++c )
9592    {
9593       val = vals[c];
9594       if( val == 0.0 ) /* zeros are allowed in the vals array */
9595          continue;
9596 
9597       rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9598       if( rational && nominator != 0 )
9599       {
9600          assert(denominator > 0);
9601          gcd = ABS(nominator);
9602          scm = denominator;
9603          rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9604          SCIPdebugMessage(" -> c=%d first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9605             c, val, nominator, denominator, gcd, scm, rational);
9606          break;
9607       }
9608    }
9609 
9610    /* remaining values */
9611    for( ++c; c < nvals && rational; ++c )
9612    {
9613       val = vals[c];
9614       if( val == 0.0 ) /* zeros are allowed in the vals array */
9615          continue;
9616 
9617       rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9618       if( rational && nominator != 0 )
9619       {
9620          assert(denominator > 0);
9621          gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
9622          scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
9623          rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9624          SCIPdebugMessage(" -> c=%d next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9625             c, val, nominator, denominator, gcd, scm, rational);
9626       }
9627       else
9628       {
9629          SCIPdebugMessage(" -> failed to convert %g into a rational representation\n", val);
9630       }
9631    }
9632 
9633    if( rational )
9634    {
9635       /* make values integral by multiplying them with the smallest common multiple of the denominators */
9636       assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9637 
9638       /* check if we found a better scaling value */
9639       if( (SCIP_Real)scm/(SCIP_Real)gcd < bestscalar )
9640 	 bestscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
9641 
9642       SCIPdebugMessage(" -> integrality could be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
9643          (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
9644    }
9645 
9646    if( bestscalar < SCIP_INVALID )
9647    {
9648       if( intscalar != NULL )
9649          *intscalar = bestscalar;
9650       *success = TRUE;
9651 
9652       SCIPdebugMessage(" -> smallest value to achieve integrality is %g \n", bestscalar);
9653    }
9654 
9655    return SCIP_OKAY;
9656 }
9657 
9658 /* Inform compiler that this code accesses the floating-point environment, so that
9659  * certain optimizations should be omitted (http://www.cplusplus.com/reference/cfenv/FENV_ACCESS/).
9660  * Not supported by Clang (gives warning) and GCC (silently), at the moment.
9661  */
9662 #if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9663 #pragma fenv_access (on)
9664 #elif defined __GNUC__
9665 #pragma STDC FENV_ACCESS ON
9666 #endif
9667 
9668 /** given a (usually very small) interval, tries to find a rational number with simple denominator (i.e. a small
9669  *  number, probably multiplied with powers of 10) out of this interval; returns TRUE iff a valid rational
9670  *  number inside the interval was found
9671  */
SCIPfindSimpleRational(SCIP_Real lb,SCIP_Real ub,SCIP_Longint maxdnom,SCIP_Longint * nominator,SCIP_Longint * denominator)9672 SCIP_Bool SCIPfindSimpleRational(
9673    SCIP_Real             lb,                 /**< lower bound of the interval */
9674    SCIP_Real             ub,                 /**< upper bound of the interval */
9675    SCIP_Longint          maxdnom,            /**< maximal denominator allowed for resulting rational number */
9676    SCIP_Longint*         nominator,          /**< pointer to store the nominator n of the rational number */
9677    SCIP_Longint*         denominator         /**< pointer to store the denominator d of the rational number */
9678    )
9679 {
9680    SCIP_Real center;
9681    SCIP_Real delta;
9682 
9683    assert(lb <= ub);
9684 
9685    center = 0.5*(lb+ub);
9686 
9687    /* in order to compute a rational number that is exactly within the bounds (as the user expects),
9688     * we computed the allowed delta with downward rounding, if available
9689     */
9690    if( SCIPintervalHasRoundingControl() )
9691    {
9692       SCIP_ROUNDMODE roundmode;
9693 
9694       roundmode = SCIPintervalGetRoundingMode();
9695       SCIPintervalSetRoundingModeDownwards();
9696 
9697       delta = 0.5*(ub-lb);
9698 
9699       SCIPintervalSetRoundingMode(roundmode);
9700    }
9701    else
9702    {
9703       delta = 0.5*(ub-lb);
9704    }
9705 
9706    return SCIPrealToRational(center, -delta, +delta, maxdnom, nominator, denominator);
9707 }
9708 
9709 #if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9710 #pragma fenv_access (off)
9711 #elif defined __GNUC__
9712 #pragma STDC FENV_ACCESS OFF
9713 #endif
9714 
9715 /** given a (usually very small) interval, selects a value inside this interval; it is tried to select a rational number
9716  *  with simple denominator (i.e. a small number, probably multiplied with powers of 10);
9717  *  if no valid rational number inside the interval was found, selects the central value of the interval
9718  */
SCIPselectSimpleValue(SCIP_Real lb,SCIP_Real ub,SCIP_Longint maxdnom)9719 SCIP_Real SCIPselectSimpleValue(
9720    SCIP_Real             lb,                 /**< lower bound of the interval */
9721    SCIP_Real             ub,                 /**< upper bound of the interval */
9722    SCIP_Longint          maxdnom             /**< maximal denominator allowed for resulting rational number */
9723    )
9724 {
9725    SCIP_Real val;
9726 
9727    val = 0.5*(lb+ub);
9728    if( lb < ub )
9729    {
9730       SCIP_Longint nominator;
9731       SCIP_Longint denominator;
9732       SCIP_Bool success;
9733 
9734       /* try to find a "simple" rational number inside the interval */
9735       SCIPdebugMessage("simple rational in [%.9f,%.9f]:", lb, ub);
9736       success = SCIPfindSimpleRational(lb, ub, maxdnom, &nominator, &denominator);
9737       if( success )
9738       {
9739          val = (SCIP_Real)nominator/(SCIP_Real)denominator;
9740          SCIPdebugPrintf(" %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT " == %.9f\n", nominator, denominator, val);
9741 
9742          if( val - lb < 0.0 || val - ub > 0.0 )
9743          {
9744             SCIPdebugPrintf(" value is out of interval bounds by %g -> failed\n", MAX(lb-val, val-ub));
9745             val = 0.5*(lb+ub);
9746          }
9747       }
9748       else
9749       {
9750          SCIPdebugPrintf(" failed\n");
9751       }
9752    }
9753 
9754    return val;
9755 }
9756 
9757 
9758 
9759 
9760 /*
9761  * Random Numbers
9762  */
9763 
9764 #if defined(NO_RAND_R) || defined(_WIN32) || defined(_WIN64)
9765 
9766 #define SCIP_RAND_MAX 32767
9767 /** returns a random number between 0 and SCIP_RAND_MAX */
9768 static
getRand(unsigned int * seedp)9769 int getRand(
9770    unsigned int*         seedp               /**< pointer to seed value */
9771    )
9772 {
9773    SCIP_Longint nextseed;
9774 
9775    assert(seedp != NULL);
9776 
9777    nextseed = (*seedp) * (SCIP_Longint)1103515245 + 12345;
9778    *seedp = (unsigned int)nextseed;
9779 
9780    return (int)((unsigned int)(nextseed/(2*(SCIP_RAND_MAX+1))) % (SCIP_RAND_MAX+1));
9781 }
9782 
9783 #else
9784 
9785 #define SCIP_RAND_MAX RAND_MAX
9786 
9787 /** returns a random number between 0 and SCIP_RAND_MAX */
9788 static
getRand(unsigned int * seedp)9789 int getRand(
9790    unsigned int*         seedp               /**< pointer to seed value */
9791    )
9792 {
9793    return rand_r(seedp);
9794 }
9795 
9796 #endif
9797 
9798 /** returns a random integer between minrandval and maxrandval */
9799 static
getRandomInt(int minrandval,int maxrandval,unsigned int * seedp)9800 int getRandomInt(
9801    int                   minrandval,         /**< minimal value to return */
9802    int                   maxrandval,         /**< maximal value to return */
9803    unsigned int*         seedp               /**< pointer to seed value */
9804    )
9805 {
9806    SCIP_Real randnumber;
9807 
9808    randnumber = (SCIP_Real)getRand(seedp)/(SCIP_RAND_MAX+1.0);
9809    assert(randnumber >= 0.0);
9810    assert(randnumber < 1.0);
9811 
9812    /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than INT_MAX
9813     * apart
9814     */
9815    return (int) (minrandval*(1.0 - randnumber) + maxrandval*randnumber + randnumber);
9816 }
9817 
9818 /** returns a random real between minrandval and maxrandval */
9819 static
getRandomReal(SCIP_Real minrandval,SCIP_Real maxrandval,unsigned int * seedp)9820 SCIP_Real getRandomReal(
9821    SCIP_Real             minrandval,         /**< minimal value to return */
9822    SCIP_Real             maxrandval,         /**< maximal value to return */
9823    unsigned int*         seedp               /**< pointer to seed value */
9824    )
9825 {
9826    SCIP_Real randnumber;
9827 
9828    randnumber = (SCIP_Real)getRand(seedp)/(SCIP_Real)SCIP_RAND_MAX;
9829    assert(randnumber >= 0.0);
9830    assert(randnumber <= 1.0);
9831 
9832    /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
9833     * SCIP_REAL_MAX apart
9834     */
9835    return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
9836 }
9837 
9838 /** returns a random integer between minrandval and maxrandval
9839  *
9840  *  @deprecated Please use SCIPrandomGetInt() to request a random integer.
9841  */
SCIPgetRandomInt(int minrandval,int maxrandval,unsigned int * seedp)9842 int SCIPgetRandomInt(
9843    int                   minrandval,         /**< minimal value to return */
9844    int                   maxrandval,         /**< maximal value to return */
9845    unsigned int*         seedp               /**< pointer to seed value */
9846    )
9847 {
9848    return getRandomInt(minrandval, maxrandval, seedp);
9849 }
9850 
9851 /** returns a random real between minrandval and maxrandval
9852  *
9853  *  @deprecated Please use SCIPrandomGetReal() to request a random real.
9854  */
SCIPgetRandomReal(SCIP_Real minrandval,SCIP_Real maxrandval,unsigned int * seedp)9855 SCIP_Real SCIPgetRandomReal(
9856    SCIP_Real             minrandval,         /**< minimal value to return */
9857    SCIP_Real             maxrandval,         /**< maximal value to return */
9858    unsigned int*         seedp               /**< pointer to seed value */
9859    )
9860 {
9861    return getRandomReal(minrandval, maxrandval, seedp);
9862 }
9863 
9864 
9865 /* initial seeds for KISS random number generator */
9866 #define DEFAULT_SEED UINT32_C(123456789)
9867 #define DEFAULT_XOR  UINT32_C(362436000)
9868 #define DEFAULT_MWC  UINT32_C(521288629)
9869 #define DEFAULT_CST  UINT32_C(7654321)
9870 
9871 
9872 /** initializes a random number generator with a given start seed */
SCIPrandomSetSeed(SCIP_RANDNUMGEN * randnumgen,unsigned int initseed)9873 void SCIPrandomSetSeed(
9874    SCIP_RANDNUMGEN*      randnumgen,         /**< random number generator */
9875    unsigned int          initseed            /**< initial random seed */
9876    )
9877 {
9878    assert(randnumgen != NULL);
9879 
9880    /* use MAX() to avoid zero after over flowing */
9881    randnumgen->seed = MAX(SCIPhashTwo(DEFAULT_SEED, initseed), 1u);
9882    randnumgen->xor_seed = MAX(SCIPhashTwo(DEFAULT_XOR, initseed), 1u);
9883    randnumgen->mwc_seed = MAX(SCIPhashTwo(DEFAULT_MWC, initseed), 1u);
9884    randnumgen->cst_seed = SCIPhashTwo(DEFAULT_CST, initseed);
9885 
9886    assert(randnumgen->seed > 0);
9887    assert(randnumgen->xor_seed > 0);
9888    assert(randnumgen->mwc_seed > 0);
9889 }
9890 
9891 /** returns a random number between 0 and UINT32_MAX
9892  *
9893  *  implementation of KISS random number generator developed by George Marsaglia.
9894  *  KISS is combination of three different random number generators:
9895  *   - Linear congruential generator
9896  *   - Xorshift
9897  *   - Lag-1 Multiply-with-carry
9898  *
9899  *  KISS has a period of 2^123 and passes all statistical test part of BigCrush-Test of TestU01 [1].
9900  *
9901  *  [1] http://dl.acm.org/citation.cfm?doid=1268776.1268777
9902  */
9903 static
randomGetRand(SCIP_RANDNUMGEN * randnumgen)9904 uint32_t randomGetRand(
9905    SCIP_RANDNUMGEN*      randnumgen          /**< random number generator */
9906    )
9907 {
9908    uint64_t t;
9909 
9910    /* linear congruential */
9911    randnumgen->seed = (uint32_t) (randnumgen->seed * UINT64_C(1103515245) + UINT64_C(12345));
9912 
9913    /* Xorshift */
9914    randnumgen->xor_seed ^= (randnumgen->xor_seed << 13);
9915    randnumgen->xor_seed ^= (randnumgen->xor_seed >> 17);
9916    randnumgen->xor_seed ^= (randnumgen->xor_seed << 5);
9917 
9918    /* Multiply-with-carry */
9919    t = UINT64_C(698769069) * randnumgen->mwc_seed + randnumgen->cst_seed;
9920    randnumgen->cst_seed = (uint32_t) (t >> 32);
9921    randnumgen->mwc_seed = (uint32_t) t;
9922 
9923    return randnumgen->seed + randnumgen->xor_seed + randnumgen->mwc_seed;
9924 }
9925 
9926 /** creates and initializes a random number generator */
SCIPrandomCreate(SCIP_RANDNUMGEN ** randnumgen,BMS_BLKMEM * blkmem,unsigned int initialseed)9927 SCIP_RETCODE SCIPrandomCreate(
9928    SCIP_RANDNUMGEN**     randnumgen,         /**< random number generator */
9929    BMS_BLKMEM*           blkmem,             /**< block memory */
9930    unsigned int          initialseed         /**< initial random seed */
9931    )
9932 {
9933    assert(randnumgen != NULL);
9934 
9935    SCIP_ALLOC( BMSallocBlockMemory(blkmem, randnumgen) );
9936 
9937    SCIPrandomSetSeed((*randnumgen), initialseed);
9938 
9939    return SCIP_OKAY;
9940 }
9941 
9942 /** frees a random number generator */
SCIPrandomFree(SCIP_RANDNUMGEN ** randnumgen,BMS_BLKMEM * blkmem)9943 void SCIPrandomFree(
9944    SCIP_RANDNUMGEN**     randnumgen,         /**< random number generator */
9945    BMS_BLKMEM*           blkmem              /**< block memory */
9946    )
9947 {
9948    assert(randnumgen != NULL);
9949    assert((*randnumgen) != NULL);
9950 
9951    BMSfreeBlockMemory(blkmem, randnumgen);
9952 
9953    return;
9954 }
9955 
9956 
9957 
9958 /** returns a random integer between minrandval and maxrandval */
SCIPrandomGetInt(SCIP_RANDNUMGEN * randnumgen,int minrandval,int maxrandval)9959 int SCIPrandomGetInt(
9960    SCIP_RANDNUMGEN*      randnumgen,         /**< random number generator */
9961    int                   minrandval,         /**< minimal value to return */
9962    int                   maxrandval          /**< maximal value to return */
9963    )
9964 {
9965    SCIP_Real randnumber;
9966    SCIP_Longint zeromax;
9967 
9968    randnumber = (SCIP_Real)randomGetRand(randnumgen)/(UINT32_MAX+1.0);
9969    assert(randnumber >= 0.0);
9970    assert(randnumber < 1.0);
9971 
9972    /* we need to shift the range to the non-negative integers to handle negative integer values correctly.
9973     * we use a long integer to avoid overflows.
9974     */
9975    zeromax = (SCIP_Longint)maxrandval - (SCIP_Longint)minrandval + 1;
9976 
9977    return (int) ((SCIP_Longint)(zeromax * randnumber) + (SCIP_Longint)minrandval);
9978 }
9979 
9980 /** returns a random real between minrandval and maxrandval */
SCIPrandomGetReal(SCIP_RANDNUMGEN * randnumgen,SCIP_Real minrandval,SCIP_Real maxrandval)9981 SCIP_Real SCIPrandomGetReal(
9982    SCIP_RANDNUMGEN*      randnumgen,         /**< random number generator */
9983    SCIP_Real             minrandval,         /**< minimal value to return */
9984    SCIP_Real             maxrandval          /**< maximal value to return */
9985    )
9986 {
9987    SCIP_Real randnumber;
9988 
9989    randnumber = (SCIP_Real)randomGetRand(randnumgen)/(SCIP_Real)UINT32_MAX;
9990    assert(randnumber >= 0.0);
9991    assert(randnumber <= 1.0);
9992 
9993    /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
9994     * SCIP_REAL_MAX apart
9995     */
9996    return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
9997 }
9998 
9999 /** randomly shuffles parts of an integer array using the Fisher-Yates algorithm */
SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN * randnumgen,int * array,int begin,int end)10000 void SCIPrandomPermuteIntArray(
10001    SCIP_RANDNUMGEN*      randnumgen,         /**< random number generator */
10002    int*                  array,              /**< array to be shuffled */
10003    int                   begin,              /**< first included index that should be subject to shuffling
10004                                               *   (0 for first array entry)
10005                                               */
10006    int                   end                 /**< first excluded index that should not be subject to shuffling
10007                                               *   (array size for last array entry)
10008                                               */
10009    )
10010 {
10011    int tmp;
10012    int i;
10013 
10014    /* loop backwards through all elements and always swap the current last element to a random position */
10015    while( end > begin+1 )
10016    {
10017       --end;
10018 
10019       /* get a random position into which the last entry should be shuffled */
10020       i = SCIPrandomGetInt(randnumgen, begin, end);
10021 
10022       /* swap the last element and the random element */
10023       tmp = array[i];
10024       array[i] = array[end];
10025       array[end] = tmp;
10026    }
10027 }
10028 
10029 /** randomly shuffles parts of an array using the Fisher-Yates algorithm */
SCIPrandomPermuteArray(SCIP_RANDNUMGEN * randnumgen,void ** array,int begin,int end)10030 void SCIPrandomPermuteArray(
10031    SCIP_RANDNUMGEN*      randnumgen,         /**< random number generator */
10032    void**                array,              /**< array to be shuffled */
10033    int                   begin,              /**< first included index that should be subject to shuffling
10034                                               *   (0 for first array entry)
10035                                               */
10036    int                   end                 /**< first excluded index that should not be subject to shuffling
10037                                               *   (array size for last array entry)
10038                                               */
10039    )
10040 {
10041    void* tmp;
10042    int i;
10043 
10044    /* loop backwards through all elements and always swap the current last element to a random position */
10045    while( end > begin+1 )
10046    {
10047       end--;
10048 
10049       /* get a random position into which the last entry should be shuffled */
10050       i = SCIPrandomGetInt(randnumgen, begin, end);
10051 
10052       /* swap the last element and the random element */
10053       tmp = array[i];
10054       array[i] = array[end];
10055       array[end] = tmp;
10056    }
10057 }
10058 
10059 /** draws a random subset of disjoint elements from a given set of disjoint elements;
10060  *  this implementation is suited for the case that nsubelems is considerably smaller then nelems
10061  */
SCIPrandomGetSubset(SCIP_RANDNUMGEN * randnumgen,void ** set,int nelems,void ** subset,int nsubelems)10062 SCIP_RETCODE SCIPrandomGetSubset(
10063    SCIP_RANDNUMGEN*      randnumgen,         /**< random number generator */
10064    void**                set,                /**< original set, from which elements should be drawn */
10065    int                   nelems,             /**< number of elements in original set */
10066    void**                subset,             /**< subset in which drawn elements should be stored */
10067    int                   nsubelems           /**< number of elements that should be drawn and stored */
10068    )
10069 {
10070    int i;
10071    int j;
10072 
10073    /* if both sets are of equal size, we just copy the array */
10074    if( nelems == nsubelems)
10075    {
10076       BMScopyMemoryArray(subset,set,nelems);
10077       return SCIP_OKAY;
10078    }
10079 
10080    /* abort, if size of subset is too big */
10081    if( nsubelems > nelems )
10082    {
10083       SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10084       return SCIP_INVALIDDATA;
10085    }
10086 #ifndef NDEBUG
10087    for( i = 0; i < nsubelems; i++ )
10088       for( j = 0; j < i; j++ )
10089          assert(set[i] != set[j]);
10090 #endif
10091 
10092    /* draw each element individually */
10093    i = 0;
10094    while( i < nsubelems )
10095    {
10096       int r;
10097 
10098       r = SCIPrandomGetInt(randnumgen, 0, nelems-1);
10099       subset[i] = set[r];
10100 
10101       /* if we get an element that we already had, we will draw again */
10102       for( j = 0; j < i; j++ )
10103       {
10104          if( subset[i] == subset[j] )
10105          {
10106             --i;
10107             break;
10108          }
10109       }
10110       ++i;
10111    }
10112    return SCIP_OKAY;
10113 }
10114 
10115 /*
10116  * Additional math functions
10117  */
10118 
10119 /** calculates a binomial coefficient n over m, choose m elements out of n, maximal value will be 33 over 16 (because
10120  *  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
10121  *  big numbers or an negative value m (and m < n) and -1 will be returned
10122  */
SCIPcalcBinomCoef(int n,int m)10123 SCIP_Longint SCIPcalcBinomCoef(
10124    int                   n,                  /**< number of different elements */
10125    int                   m                   /**< number to choose out of the above */
10126    )
10127 {
10128    if( m == 0 || m >= n )
10129       return 1;
10130 
10131    if( m < 0 )
10132       return -1;
10133 
10134    /* symmetry of the binomial coefficient, choose smaller m */
10135    if( m > n/2 )
10136       m = n - m;
10137 
10138    /* trivial case m == 1 */
10139    if( m == 1 )
10140       return n;
10141 
10142    /* simple case m == 2 */
10143    if( m == 2 )
10144    {
10145       if( ((SCIP_Real)SCIP_LONGINT_MAX) / n >= (n-1) * 2 ) /*lint !e790*/
10146          return ((SCIP_Longint)n*(n-1)/2); /*lint !e647*/
10147       else
10148          return -1;
10149    }
10150 
10151    /* abort on to big numbers */
10152    if( m > 16 || n > 33 )
10153       return -1;
10154 
10155    /* simple case m == 3 */
10156    if( m == 3 )
10157       return (n*(n-1)*(n-2)/6); /*lint !e647*/
10158    else
10159    {
10160       /* first half of Pascal's triangle numbers(without the symmetric part) backwards from (33,16) over (32,16),
10161        * (33,15), (32,15),(31,15, (30,15), (33,14) to (8,4) (rest is calculated directly)
10162        *
10163        * due to this order we can extract the right binomial coefficient by (16-m)^2+(16-m)+(33-n)
10164        */
10165       static const SCIP_Longint binoms[182] = {
10166          1166803110, 601080390, 1037158320, 565722720, 300540195, 155117520, 818809200, 471435600, 265182525, 145422675,
10167          77558760, 40116600, 573166440, 347373600, 206253075, 119759850, 67863915, 37442160, 20058300, 10400600,
10168          354817320, 225792840, 141120525, 86493225, 51895935, 30421755, 17383860, 9657700, 5200300, 2704156, 193536720,
10169          129024480, 84672315, 54627300, 34597290, 21474180, 13037895, 7726160, 4457400, 2496144, 1352078, 705432,
10170          92561040, 64512240, 44352165, 30045015, 20030010, 13123110, 8436285, 5311735, 3268760, 1961256, 1144066,
10171          646646, 352716, 184756, 38567100, 28048800, 20160075, 14307150, 10015005, 6906900, 4686825, 3124550, 2042975,
10172          1307504, 817190, 497420, 293930, 167960, 92378, 48620, 13884156, 10518300, 7888725, 5852925, 4292145, 3108105,
10173          2220075, 1562275, 1081575, 735471, 490314, 319770, 203490, 125970, 75582, 43758, 24310, 12870, 4272048, 3365856,
10174          2629575, 2035800, 1560780, 1184040, 888030, 657800, 480700, 346104, 245157, 170544, 116280, 77520, 50388, 31824,
10175          19448, 11440, 6435, 3432, 1107568, 906192, 736281, 593775, 475020, 376740, 296010, 230230, 177100, 134596,
10176          100947, 74613, 54264, 38760, 27132, 18564, 12376, 8008, 5005, 3003, 1716, 924, 237336, 201376, 169911, 142506,
10177          118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, 11628, 8568, 6188, 4368, 3003, 2002,
10178          1287, 792, 462, 252, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985,
10179          4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70};
10180 
10181       /* m can at most be 16 */
10182       const int t = 16-m;
10183       assert(t >= 0);
10184       assert(n <= 33);
10185 
10186       /* binoms array hast exactly 182 elements */
10187       assert(t*(t+1)+(33-n) < 182);
10188 
10189       return binoms[t*(t+1)+(33-n)]; /*lint !e662 !e661*/
10190    }
10191 }
10192 
10193 /** negates a number */
SCIPnegateReal(SCIP_Real x)10194 SCIP_Real SCIPnegateReal(
10195    SCIP_Real             x                   /**< value to negate */
10196    )
10197 {
10198    return -x;
10199 }
10200 
10201 /*
10202  * Permutations / Shuffling
10203  */
10204 
10205 /** swaps two ints */
SCIPswapInts(int * value1,int * value2)10206 void SCIPswapInts(
10207    int*                  value1,             /**< pointer to first integer */
10208    int*                  value2              /**< pointer to second integer */
10209    )
10210 {
10211    int tmp;
10212 
10213    tmp = *value1;
10214    *value1 = *value2;
10215    *value2 = tmp;
10216 }
10217 
10218 /** swaps two real values */
SCIPswapReals(SCIP_Real * value1,SCIP_Real * value2)10219 void SCIPswapReals(
10220    SCIP_Real*            value1,             /**< pointer to first real value */
10221    SCIP_Real*            value2              /**< pointer to second real value */
10222    )
10223 {
10224    SCIP_Real tmp;
10225 
10226    tmp = *value1;
10227    *value1 = *value2;
10228    *value2 = tmp;
10229 }
10230 
10231 /** swaps the addresses of two pointers */
SCIPswapPointers(void ** pointer1,void ** pointer2)10232 void SCIPswapPointers(
10233    void**                pointer1,           /**< first pointer */
10234    void**                pointer2            /**< second pointer */
10235    )
10236 {
10237    void* tmp;
10238 
10239    tmp = *pointer1;
10240    *pointer1 = *pointer2;
10241    *pointer2 = tmp;
10242 }
10243 
10244 /** randomly shuffles parts of an integer array using the Fisher-Yates algorithm
10245  *
10246  *  @deprecated Please use SCIPrandomPermuteIntArray()
10247  */
SCIPpermuteIntArray(int * array,int begin,int end,unsigned int * randseed)10248 void SCIPpermuteIntArray(
10249    int*                  array,              /**< array to be shuffled */
10250    int                   begin,              /**< first included index that should be subject to shuffling
10251                                               *   (0 for first array entry)
10252                                               */
10253    int                   end,                /**< first excluded index that should not be subject to shuffling
10254                                               *   (array size for last array entry)
10255                                               */
10256    unsigned int*         randseed            /**< seed value for the random generator */
10257    )
10258 {
10259    int tmp;
10260    int i;
10261 
10262    /* loop backwards through all elements and always swap the current last element to a random position */
10263    while( end > begin+1 )
10264    {
10265       --end;
10266 
10267       /* get a random position into which the last entry should be shuffled */
10268       i = getRandomInt(begin, end, randseed);
10269 
10270       /* swap the last element and the random element */
10271       tmp = array[i];
10272       array[i] = array[end];
10273       array[end] = tmp;
10274    }
10275 }
10276 
10277 
10278 /** randomly shuffles parts of an array using the Fisher-Yates algorithm
10279  *
10280  *  @deprecated Please use SCIPrandomPermuteArray()
10281  */
SCIPpermuteArray(void ** array,int begin,int end,unsigned int * randseed)10282 void SCIPpermuteArray(
10283    void**                array,              /**< array to be shuffled */
10284    int                   begin,              /**< first included index that should be subject to shuffling
10285                                               *   (0 for first array entry)
10286                                               */
10287    int                   end,                /**< first excluded index that should not be subject to shuffling
10288                                               *   (array size for last array entry)
10289                                               */
10290    unsigned int*         randseed            /**< seed value for the random generator */
10291    )
10292 {
10293    void* tmp;
10294    int i;
10295 
10296    /* loop backwards through all elements and always swap the current last element to a random position */
10297    while( end > begin+1 )
10298    {
10299       end--;
10300 
10301       /* get a random position into which the last entry should be shuffled */
10302       i = getRandomInt(begin, end, randseed);
10303 
10304       /* swap the last element and the random element */
10305       tmp = array[i];
10306       array[i] = array[end];
10307       array[end] = tmp;
10308    }
10309 }
10310 
10311 /** draws a random subset of disjoint elements from a given set of disjoint elements;
10312  *  this implementation is suited for the case that nsubelems is considerably smaller then nelems
10313  *
10314  *  @deprecated Please use SCIPrandomGetSubset()
10315  */
SCIPgetRandomSubset(void ** set,int nelems,void ** subset,int nsubelems,unsigned int randseed)10316 SCIP_RETCODE SCIPgetRandomSubset(
10317    void**                set,                /**< original set, from which elements should be drawn */
10318    int                   nelems,             /**< number of elements in original set */
10319    void**                subset,             /**< subset in which drawn elements should be stored */
10320    int                   nsubelems,          /**< number of elements that should be drawn and stored */
10321    unsigned int          randseed            /**< seed value for random generator */
10322    )
10323 {
10324    int i;
10325    int j;
10326 
10327    /* if both sets are of equal size, we just copy the array */
10328    if( nelems == nsubelems)
10329    {
10330       BMScopyMemoryArray(subset,set,nelems);
10331       return SCIP_OKAY;
10332    }
10333 
10334    /* abort, if size of subset is too big */
10335    if( nsubelems > nelems )
10336    {
10337       SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10338       return SCIP_INVALIDDATA;
10339    }
10340 #ifndef NDEBUG
10341    for( i = 0; i < nsubelems; i++ )
10342       for( j = 0; j < i; j++ )
10343          assert(set[i] != set[j]);
10344 #endif
10345 
10346    /* draw each element individually */
10347    i = 0;
10348    while( i < nsubelems )
10349    {
10350       int r;
10351 
10352       r = getRandomInt(0, nelems-1, &randseed);
10353       subset[i] = set[r];
10354 
10355       /* if we get an element that we already had, we will draw again */
10356       for( j = 0; j < i; j++ )
10357       {
10358          if( subset[i] == subset[j] )
10359          {
10360             --i;
10361             break;
10362          }
10363       }
10364       ++i;
10365    }
10366    return SCIP_OKAY;
10367 }
10368 
10369 
10370 /*
10371  * Arrays
10372  */
10373 
10374 /** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly */
SCIPcomputeArraysIntersection(int * array1,int narray1,int * array2,int narray2,int * intersectarray,int * nintersectarray)10375 SCIP_RETCODE SCIPcomputeArraysIntersection(
10376    int*                  array1,             /**< first array (in ascending order) */
10377    int                   narray1,            /**< number of entries of first array */
10378    int*                  array2,             /**< second array (in ascending order) */
10379    int                   narray2,            /**< number of entries of second array */
10380    int*                  intersectarray,     /**< intersection of array1 and array2
10381                                               *   (note: it is possible to use array1 for this input argument) */
10382    int*                  nintersectarray     /**< pointer to store number of entries of intersection array
10383                                               *   (note: it is possible to use narray1 for this input argument) */
10384    )
10385 {
10386    int cnt = 0;
10387    int k = 0;
10388    int v1;
10389    int v2;
10390 
10391    assert( array1 != NULL );
10392    assert( array2 != NULL );
10393    assert( intersectarray != NULL );
10394    assert( nintersectarray != NULL );
10395 
10396    /* determine intersection of array1 and array2 */
10397    for (v1 = 0; v1 < narray1; ++v1)
10398    {
10399       assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10400 
10401       /* skip duplicate entries */
10402       if ( v1+1 < narray1 && array1[v1] == array1[v1+1])
10403          continue;
10404 
10405       for (v2 = k; v2 < narray2; ++v2)
10406       {
10407          assert( v2 == 0 || array2[v2] >= array2[v2-1] );
10408 
10409          if ( array2[v2] > array1[v1] )
10410          {
10411             k = v2;
10412             break;
10413          }
10414          else if ( array2[v2] == array1[v1] )
10415          {
10416             intersectarray[cnt++] = array2[v2];
10417             k = v2 + 1;
10418             break;
10419          }
10420       }
10421    }
10422 
10423    /* store size of intersection array */
10424    *nintersectarray = cnt;
10425 
10426    return SCIP_OKAY;
10427 }
10428 
10429 
10430 /** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly */
SCIPcomputeArraysSetminus(int * array1,int narray1,int * array2,int narray2,int * setminusarray,int * nsetminusarray)10431 SCIP_RETCODE SCIPcomputeArraysSetminus(
10432    int*                  array1,             /**< first array (in ascending order) */
10433    int                   narray1,            /**< number of entries of first array */
10434    int*                  array2,             /**< second array (in ascending order) */
10435    int                   narray2,            /**< number of entries of second array */
10436    int*                  setminusarray,      /**< array to store entries of array1 that are not an entry of array2
10437                                               *   (note: it is possible to use array1 for this input argument) */
10438    int*                  nsetminusarray      /**< pointer to store number of entries of setminus array
10439                                               *   (note: it is possible to use narray1 for this input argument) */
10440    )
10441 {
10442    int cnt = 0;
10443    int v1 = 0;
10444    int v2 = 0;
10445 
10446    assert( array1 != NULL );
10447    assert( array2 != NULL );
10448    assert( setminusarray != NULL );
10449    assert( nsetminusarray != NULL );
10450 
10451    while ( v1 < narray1 )
10452    {
10453       int entry1;
10454 
10455       assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10456 
10457       /* skip duplicate entries */
10458       while ( v1 + 1 < narray1 && array1[v1] == array1[v1 + 1] )
10459          ++v1;
10460 
10461       entry1 = array1[v1];
10462 
10463       while ( v2 < narray2 && array2[v2] < entry1 )
10464          ++v2;
10465 
10466       if ( v2 >= narray2 || entry1 < array2[v2] )
10467          setminusarray[cnt++] = entry1;
10468       ++v1;
10469    }
10470 
10471    /* store size of setminus array */
10472    *nsetminusarray = cnt;
10473 
10474    return SCIP_OKAY;
10475 }
10476 
10477 
10478 /*
10479  * Strings
10480  */
10481 
10482 
10483 /** copies characters from 'src' to 'dest', copying is stopped when either the 'stop' character is reached or after
10484  *  'cnt' characters have been copied, whichever comes first.
10485  *
10486  *  @note undefined behavior on overlapping arrays
10487  */
SCIPmemccpy(char * dest,const char * src,char stop,unsigned int cnt)10488 int SCIPmemccpy(
10489    char*                 dest,               /**< destination pointer to copy to */
10490    const char*           src,                /**< source pointer to copy from */
10491    char                  stop,               /**< character when found stop copying */
10492    unsigned int          cnt                 /**< maximal number of characters to copy */
10493    )
10494 {
10495    if( dest == NULL || src == NULL || cnt == 0 )
10496       return -1;
10497    else
10498    {
10499       char* destination = dest;
10500 
10501       while( cnt-- && (*destination++ = *src++) != stop ); /*lint !e722*/
10502 
10503       return (int)(destination - dest);
10504    }
10505 }
10506 
10507 /** prints an error message containing of the given string followed by a string describing the current system error
10508  *
10509  *  Prefers to use the strerror_r method, which is threadsafe. On systems where this method does not exist,
10510  *  NO_STRERROR_R should be defined (see INSTALL). In this case, strerror is used which is not guaranteed to be
10511  *  threadsafe (on SUN-systems, it actually is).
10512  */
SCIPprintSysError(const char * message)10513 void SCIPprintSysError(
10514    const char*           message             /**< first part of the error message, e.g. the filename */
10515    )
10516 {
10517 #ifdef NO_STRERROR_R
10518    SCIPmessagePrintError("%s: %s\n", message, strerror(errno));
10519 #else
10520    char buf[SCIP_MAXSTRLEN];
10521 
10522 #if defined(_WIN32) || defined(_WIN64)
10523    /* strerror_s returns 0 on success; the string is \0 terminated. */
10524    if ( strerror_s(buf, SCIP_MAXSTRLEN, errno) != 0 )
10525       SCIPmessagePrintError("Unknown error number %d or error message too long.\n", errno);
10526    SCIPmessagePrintError("%s: %s\n", message, buf);
10527 #elif (_POSIX_C_SOURCE >= 200112L || __DARWIN_C_LEVEL > 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
10528    /* We are in the POSIX/XSI case, where strerror_r returns 0 on success; \0 termination is unclear. */
10529    if ( strerror_r(errno, buf, SCIP_MAXSTRLEN) != 0 )
10530       SCIPmessagePrintError("Unknown error number %d.\n", errno);
10531    buf[SCIP_MAXSTRLEN - 1] = '\0';
10532    SCIPmessagePrintError("%s: %s\n", message, buf);
10533 #else
10534    /* We are in the GNU case, where strerror_r returns a pointer to the error string. This string is possibly stored
10535     * in buf and is always \0 terminated.
10536     * However, if compiling on one system and executing on another system, we might actually call a different
10537     * variant of the strerror_r function than we had at compile time.
10538     */
10539    char* errordescr;
10540    *buf = '\0';
10541    errordescr = strerror_r(errno, buf, SCIP_MAXSTRLEN);
10542    if( *buf != '\0' )
10543    {
10544       /* strerror_r wrote into buf */
10545       SCIPmessagePrintError("%s: %s\n", message, buf);
10546    }
10547    else if( errordescr != NULL )
10548    {
10549       /* strerror_r returned something non-NULL */
10550       SCIPmessagePrintError("%s: %s\n", message, errordescr);
10551    }
10552    else
10553    {
10554       /* strerror_r did return NULL and did not write into buf */
10555       SCIPmessagePrintError("Could not obtain description for error %d.\n", errno);
10556    }
10557 #endif
10558 #endif
10559 }
10560 
10561 /** extracts tokens from strings - wrapper method for strtok_r() */
SCIPstrtok(char * s,const char * delim,char ** ptrptr)10562 char* SCIPstrtok(
10563    char*                 s,                  /**< string to parse */
10564    const char*           delim,              /**< delimiters for parsing */
10565    char**                ptrptr              /**< pointer to working char pointer - must stay the same while parsing */
10566    )
10567 {
10568 #ifdef SCIP_NO_STRTOK_R
10569    return strtok(s, delim);
10570 #else
10571    return strtok_r(s, delim, ptrptr);
10572 #endif
10573 }
10574 
10575 /** translates the given string into a string where symbols ", ', and spaces are escaped with a \ prefix */
SCIPescapeString(char * t,int bufsize,const char * s)10576 void SCIPescapeString(
10577    char*                 t,                  /**< target buffer to store escaped string */
10578    int                   bufsize,            /**< size of buffer t */
10579    const char*           s                   /**< string to transform into escaped string */
10580    )
10581 {
10582    int len;
10583    int i;
10584    int p;
10585 
10586    assert(t != NULL);
10587    assert(bufsize > 0);
10588 
10589    len = (int)strlen(s);
10590    for( p = 0, i = 0; i <= len && p < bufsize; ++i, ++p )
10591    {
10592       if( s[i] == ' ' || s[i] == '"' || s[i] == '\'' )
10593       {
10594          t[p] = '\\';
10595          p++;
10596       }
10597       if( p < bufsize )
10598          t[p] = s[i];
10599    }
10600    t[bufsize-1] = '\0';
10601 }
10602 
10603 /* safe version of snprintf */
SCIPsnprintf(char * t,int len,const char * s,...)10604 int SCIPsnprintf(
10605    char*                 t,                  /**< target string */
10606    int                   len,                /**< length of the string to copy */
10607    const char*           s,                  /**< source string */
10608    ...                                       /**< further parameters */
10609    )
10610 {
10611    va_list ap;
10612    int n;
10613 
10614    assert(t != NULL);
10615    assert(len > 0);
10616 
10617    va_start(ap, s); /*lint !e826*/
10618 
10619 #if defined(_WIN32) || defined(_WIN64)
10620    n = _vsnprintf(t, (size_t) len, s, ap);
10621 #else
10622    n = vsnprintf(t, (size_t) len, s, ap); /*lint !e571*/
10623 #endif
10624    va_end(ap);
10625 
10626    if( n < 0 || n >= len )
10627    {
10628 #ifndef NDEBUG
10629       if( n < 0 )
10630       {
10631          SCIPerrorMessage("vsnprintf returned %d\n",n);
10632       }
10633 #endif
10634       t[len-1] = '\0';
10635       n = len-1;
10636    }
10637    return n;
10638 }
10639 
10640 /** safe version of strncpy
10641  *
10642  *  Copies string in s to t using at most @a size-1 nonzero characters (strncpy copies size characters). It always adds
10643  *  a terminating zero char. Does not pad the remaining string with zero characters (unlike strncpy). Returns the number
10644  *  of copied nonzero characters, if the length of s is at most size - 1, and returns size otherwise. Thus, the original
10645  *  string was truncated if the return value is size.
10646  */
SCIPstrncpy(char * t,const char * s,int size)10647 int SCIPstrncpy(
10648    char*                 t,                  /**< target string */
10649    const char*           s,                  /**< source string */
10650    int                   size                /**< maximal size of t */
10651    )
10652 {
10653    int n;
10654 
10655    if( size <= 0 )
10656       return 0;
10657 
10658    /* decrease size by 1 to create space for terminating zero char */
10659    --size;
10660    for( n = 0; n < size && *s != '\0'; n++ )
10661       *(t++) = *(s++);
10662    *t = '\0';
10663 
10664    if( *s != '\0' )
10665       ++n;
10666 
10667    return n;
10668 }
10669 
10670 /** 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
10671  *
10672  *  @return Returns TRUE if a value could be extracted, otherwise FALSE
10673  */
SCIPstrToIntValue(const char * str,int * value,char ** endptr)10674 SCIP_Bool SCIPstrToIntValue(
10675    const char*           str,                /**< string to search */
10676    int*                  value,              /**< pointer to store the parsed value */
10677    char**                endptr              /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10678    )
10679 {
10680    assert(str != NULL);
10681    assert(value != NULL);
10682    assert(endptr != NULL);
10683 
10684    /* init errno to detect possible errors */
10685    errno = 0;
10686 
10687    *value = (int) strtol(str, endptr, 10);
10688 
10689    if( *endptr != str && *endptr != NULL )
10690    {
10691       SCIPdebugMessage("parsed integer value <%d>\n", *value);
10692       return TRUE;
10693    }
10694    *endptr = (char*)str;
10695 
10696    SCIPdebugMessage("failed parsing integer value <%s>\n", str);
10697 
10698    return FALSE;
10699 }
10700 
10701 /** 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
10702  *
10703  *  @return Returns TRUE if a value could be extracted, otherwise FALSE
10704  */
SCIPstrToRealValue(const char * str,SCIP_Real * value,char ** endptr)10705 SCIP_Bool SCIPstrToRealValue(
10706    const char*           str,                /**< string to search */
10707    SCIP_Real*            value,              /**< pointer to store the parsed value */
10708    char**                endptr              /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10709    )
10710 {
10711    assert(str != NULL);
10712    assert(value != NULL);
10713    assert(endptr != NULL);
10714 
10715    /* init errno to detect possible errors */
10716    errno = 0;
10717 
10718    *value = strtod(str, endptr);
10719 
10720    if( *endptr != str && *endptr != NULL )
10721    {
10722       SCIPdebugMessage("parsed real value <%g>\n", *value);
10723       return TRUE;
10724    }
10725    *endptr = (char*)str;
10726 
10727    SCIPdebugMessage("failed parsing real value <%s>\n", str);
10728 
10729    return FALSE;
10730 }
10731 
10732 /** copies the first size characters between a start and end character of str into token, if no error occurred endptr
10733  *  will point to the position after the read part, otherwise it will point to @p str
10734  */
SCIPstrCopySection(const char * str,char startchar,char endchar,char * token,int size,char ** endptr)10735 void SCIPstrCopySection(
10736    const char*           str,                /**< string to search */
10737    char                  startchar,          /**< character which defines the beginning */
10738    char                  endchar,            /**< character which defines the ending */
10739    char*                 token,              /**< string to store the copy */
10740    int                   size,               /**< size of the token char array */
10741    char**                endptr              /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10742    )
10743 {
10744    const char* copystr;
10745    int nchars;
10746 
10747    assert(str != NULL);
10748    assert(token != NULL);
10749    assert(size > 0);
10750    assert(endptr != NULL);
10751 
10752    nchars = 0;
10753 
10754    copystr = str;
10755 
10756    /* find starting character */
10757    while( *str != '\0' && *str != startchar )
10758       ++str;
10759 
10760    /* did not find start character */
10761    if( *str == '\0' )
10762    {
10763       *endptr = (char*)copystr;
10764       return;
10765    }
10766 
10767    /* skip start character */
10768    ++str;
10769 
10770    /* copy string */
10771    while( *str != '\0' && *str != endchar && nchars < size-1 )
10772    {
10773       assert(nchars < SCIP_MAXSTRLEN);
10774       token[nchars] = *str;
10775       nchars++;
10776       ++str;
10777    }
10778 
10779    /* add end to token */
10780    token[nchars] = '\0';
10781 
10782    /* if section was longer than size, we want to reach the end of the parsing section anyway */
10783    if( nchars == (size-1) )
10784       while( *str != '\0' && *str != endchar )
10785          ++str;
10786 
10787    /* did not find end character */
10788    if( *str == '\0' )
10789    {
10790       *endptr = (char*)copystr;
10791       return;
10792    }
10793 
10794    /* skip end character */
10795    ++str;
10796 
10797    SCIPdebugMessage("parsed section <%s>\n", token);
10798 
10799    *endptr = (char*) str;
10800 }
10801 
10802 /*
10803  * File methods
10804  */
10805 
10806 /** returns, whether the given file exists */
SCIPfileExists(const char * filename)10807 SCIP_Bool SCIPfileExists(
10808    const char*           filename            /**< file name */
10809    )
10810 {
10811    FILE* f;
10812 
10813    f = fopen(filename, "r");
10814    if( f == NULL )
10815       return FALSE;
10816 
10817    fclose(f);
10818 
10819    return TRUE;
10820 }
10821 
10822 /** splits filename into path, name, and extension */
SCIPsplitFilename(char * filename,char ** path,char ** name,char ** extension,char ** compression)10823 void SCIPsplitFilename(
10824    char*                 filename,           /**< filename to split; is destroyed (but not freed) during process */
10825    char**                path,               /**< pointer to store path, or NULL if not needed */
10826    char**                name,               /**< pointer to store name, or NULL if not needed */
10827    char**                extension,          /**< pointer to store extension, or NULL if not needed */
10828    char**                compression         /**< pointer to store compression extension, or NULL if not needed */
10829    )
10830 {
10831    char* lastslash;
10832    char* lastbackslash;
10833    char* lastdot;
10834 
10835    assert(filename != NULL);
10836 
10837    if( path != NULL )
10838       *path = NULL;
10839    if( name != NULL )
10840       *name = NULL;
10841    if( extension != NULL )
10842       *extension = NULL;
10843    if( compression != NULL )
10844       *compression = NULL;
10845 
10846    /* treat both slashes '/' and '\' as directory delimiters */
10847    lastslash = strrchr(filename, '/');
10848    lastbackslash = strrchr(filename, '\\');
10849    lastslash = MAX(lastslash, lastbackslash); /*lint !e613*/
10850    lastdot = strrchr(filename, '.');
10851    if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
10852       lastdot = NULL;
10853 
10854    /* detect known compression extensions */
10855 #ifdef SCIP_WITH_ZLIB
10856    if( lastdot != NULL )
10857    {
10858       char* compext;
10859 
10860       compext = lastdot+1;
10861       if( strcmp(compext, "gz") == 0
10862         || strcmp(compext, "z") == 0
10863         || strcmp(compext, "Z") == 0 )
10864       {
10865          if( compression != NULL )
10866             *compression = compext;
10867          *lastdot = '\0';
10868       }
10869 
10870       /* find again the last dot in the filename without compression extension */
10871       lastdot = strrchr(filename, '.');
10872       if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
10873          lastdot = NULL;
10874    }
10875 #endif
10876 
10877    if( lastslash == NULL )
10878    {
10879       if( name != NULL )
10880          *name = filename;
10881    }
10882    else
10883    {
10884       if( path != NULL )
10885          *path = filename;
10886       if( name != NULL )
10887          *name = lastslash+1;
10888       *lastslash = '\0';
10889    }
10890 
10891    if( lastdot != NULL )
10892    {
10893       if( extension != NULL )
10894          *extension = lastdot+1;
10895       *lastdot = '\0';
10896    }
10897 }
10898 
10899 /*
10900  * simple functions implemented as defines
10901  */
10902 
10903 /* In debug mode, the following methods are implemented as function calls to ensure
10904  * type validity.
10905  * In optimized mode, the methods are implemented as defines to improve performance.
10906  * However, we want to have them in the library anyways, so we have to undef the defines.
10907  */
10908 
10909 #undef SCIPrelDiff
10910 
10911 /** returns the relative difference: (val1-val2)/max(|val1|,|val2|,1.0) */
SCIPrelDiff(SCIP_Real val1,SCIP_Real val2)10912 SCIP_Real SCIPrelDiff(
10913    SCIP_Real             val1,               /**< first value to be compared */
10914    SCIP_Real             val2                /**< second value to be compared */
10915    )
10916 {
10917    SCIP_Real absval1;
10918    SCIP_Real absval2;
10919    SCIP_Real quot;
10920 
10921    absval1 = REALABS(val1);
10922    absval2 = REALABS(val2);
10923    quot = MAX3(1.0, absval1, absval2);
10924 
10925    return (val1-val2)/quot;
10926 }
10927 
10928 
10929 /** computes the gap from the primal and the dual bound */
SCIPcomputeGap(SCIP_Real eps,SCIP_Real inf,SCIP_Real primalbound,SCIP_Real dualbound)10930 SCIP_Real SCIPcomputeGap(
10931    SCIP_Real             eps,                /**< the value treated as zero */
10932    SCIP_Real             inf,                /**< the value treated as infinity */
10933    SCIP_Real             primalbound,        /**< the primal bound */
10934    SCIP_Real             dualbound           /**< the dual bound */
10935    )
10936 {
10937    if( EPSEQ(primalbound, dualbound, eps) )
10938       return 0.0;
10939    else
10940    {
10941       SCIP_Real absdual = REALABS(dualbound);
10942       SCIP_Real absprimal = REALABS(primalbound);
10943 
10944       if( EPSZ(dualbound, eps) || EPSZ(primalbound, eps) || absprimal >= inf || absdual >= inf ||
10945          primalbound * dualbound < 0.0 )
10946          return inf;
10947       else
10948          return REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
10949    }
10950 }
10951 
10952 /*
10953  * disjoint set (union-find) data structure
10954  */
10955 
10956 /** creates a disjoint set (union find) structure \p djset for \p ncomponents many components (of size one) */
SCIPdisjointsetCreate(SCIP_DISJOINTSET ** djset,BMS_BLKMEM * blkmem,int ncomponents)10957 SCIP_RETCODE SCIPdisjointsetCreate(
10958    SCIP_DISJOINTSET**    djset,              /**< disjoint set (union find) data structure */
10959    BMS_BLKMEM*           blkmem,             /**< block memory */
10960    int                   ncomponents         /**< number of components */
10961    )
10962 {
10963    assert(djset != NULL);
10964    assert(blkmem != NULL);
10965 
10966    /* allocate the necessary memory */
10967    assert(ncomponents > 0);
10968    SCIP_ALLOC( BMSallocBlockMemory(blkmem, djset) );
10969    SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->parents), ncomponents) );
10970    SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->sizes), ncomponents) );
10971    (*djset)->size = ncomponents;
10972 
10973    /* clear the data structure */
10974    SCIPdisjointsetClear(*djset);
10975 
10976    return SCIP_OKAY;
10977 }
10978 
10979 /** clears the disjoint set (union find) structure \p djset */
SCIPdisjointsetClear(SCIP_DISJOINTSET * djset)10980 void SCIPdisjointsetClear(
10981    SCIP_DISJOINTSET*     djset               /**< disjoint set (union find) data structure */
10982    )
10983 {
10984    int i;
10985 
10986    djset->componentcount = djset->size;
10987 
10988    /* reset all components to be unconnected */
10989    for( i = 0; i < djset->componentcount; i++ )
10990    {
10991       djset->parents[i] = i;
10992       djset->sizes[i] = 1;
10993    }
10994 }
10995 
10996 /** finds and returns the component identifier of this \p element */
SCIPdisjointsetFind(SCIP_DISJOINTSET * djset,int element)10997 int SCIPdisjointsetFind(
10998    SCIP_DISJOINTSET*     djset,              /**< disjoint set (union find) data structure */
10999    int                   element             /**< element to be found */
11000    )
11001 {
11002    int newelement;
11003    int root = element;
11004    int* parents = djset->parents;
11005 
11006    /* find root of this element */
11007    while( root != parents[root] )
11008    {
11009       root = parents[root];
11010    }
11011 
11012    /* compress the path to make future queries faster */
11013    while( element != root )
11014    {
11015       newelement = parents[element];
11016       parents[element] = root;
11017       element = newelement;
11018    }
11019 
11020    return root;
11021 }
11022 
11023 /** merges the components containing the elements \p p and \p q */
SCIPdisjointsetUnion(SCIP_DISJOINTSET * djset,int p,int q,SCIP_Bool forcerepofp)11024 void SCIPdisjointsetUnion(
11025    SCIP_DISJOINTSET*     djset,              /**< disjoint set (union find) data structure */
11026    int                   p,                  /**< first element */
11027    int                   q,                  /**< second element */
11028    SCIP_Bool             forcerepofp         /**< force representative of p to be new representative */
11029    )
11030 {
11031    int idp;
11032    int idq;
11033    int* sizes;
11034    int* parents;
11035 
11036    assert(djset != NULL);
11037    assert(0 <= p);
11038    assert(0 <= q);
11039    assert(djset->size > p);
11040    assert(djset->size > q);
11041 
11042    idp = SCIPdisjointsetFind(djset, p);
11043    idq = SCIPdisjointsetFind(djset, q);
11044 
11045    /* if p and q lie in the same component, there is nothing to be done */
11046    if( idp == idq )
11047       return;
11048 
11049    sizes = djset->sizes;
11050    parents = djset->parents;
11051 
11052    if( forcerepofp )
11053    {
11054       parents[idq] = idp;
11055       sizes[idp] += sizes[idq];
11056    }
11057    else
11058    {
11059       if( sizes[idp] < sizes[idq] )
11060       {
11061          parents[idp] = idq;
11062          sizes[idq] += sizes[idp];
11063       }
11064       else
11065       {
11066          parents[idq] = idp;
11067          sizes[idp] += sizes[idq];
11068       }
11069    }
11070    /* one less component */
11071    djset->componentcount--;
11072 }
11073 
11074 /** frees the disjoint set (union find) data structure */
SCIPdisjointsetFree(SCIP_DISJOINTSET ** djset,BMS_BLKMEM * blkmem)11075 void SCIPdisjointsetFree(
11076    SCIP_DISJOINTSET**    djset,              /**< pointer to disjoint set (union find) data structure */
11077    BMS_BLKMEM*           blkmem              /**< block memory */
11078    )
11079 {
11080    SCIP_DISJOINTSET* dsptr;
11081 
11082    assert(djset != NULL);
11083    assert(*djset != NULL);
11084 
11085    dsptr = *djset;
11086 
11087    BMSfreeBlockMemoryArray(blkmem, &dsptr->sizes, dsptr->size);
11088    BMSfreeBlockMemoryArray(blkmem, &dsptr->parents, dsptr->size);
11089 
11090    BMSfreeBlockMemory(blkmem, djset);
11091 }
11092 
11093 /** returns the number of independent components in this disjoint set (union find) data structure */
SCIPdisjointsetGetComponentCount(SCIP_DISJOINTSET * djset)11094 int SCIPdisjointsetGetComponentCount(
11095    SCIP_DISJOINTSET*     djset               /**< disjoint set (union find) data structure */
11096    )
11097 {
11098    assert(djset != NULL);
11099 
11100    return djset->componentcount;
11101 }
11102 
11103 /** returns the size (number of nodes) of this disjoint set (union find) data structure */
SCIPdisjointsetGetSize(SCIP_DISJOINTSET * djset)11104 int SCIPdisjointsetGetSize(
11105    SCIP_DISJOINTSET*     djset               /**< disjoint set (union find) data structure */
11106    )
11107 {
11108    assert(djset != NULL);
11109 
11110    return djset->size;
11111 }
11112 
11113 /** checks whether a given string t appears at the beginning of the string s (up to spaces at beginning) */
SCIPstrAtStart(const char * s,const char * t,size_t tlen)11114 SCIP_Bool SCIPstrAtStart(
11115         const char*           s,                  /**< string to search in */
11116         const char*           t,                  /**< string to search for */
11117         size_t                tlen                /**< length of t */
11118 )
11119 {
11120    int idxctr = 0;
11121 
11122    assert(s != NULL);
11123    assert(t != NULL);
11124 
11125    /* skip whitespace at beginning */
11126    while( idxctr < SCIP_MAXSTRLEN && isspace((unsigned char)s[idxctr]) )
11127       ++idxctr;
11128    if( strncmp(&s[idxctr], t, tlen) == 0 )
11129       return TRUE;
11130    return FALSE;
11131 }
11132