Scippy

SCIP

Solving Constraint Integer Programs

misc.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-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  */
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 */
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  */
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 */
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 */
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  */
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 */
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 */
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 */
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
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
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 */
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) */
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 */
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 */
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 */
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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 */
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 */
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 */
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
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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 */
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 */
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 */
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
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
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 */
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 */
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 */
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 */
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 */
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! */
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 */
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
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 */
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
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
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
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
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 {
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
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 {
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
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
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 */
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 */
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  */
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 */
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  */
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 */
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  */
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 */
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 */
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  */
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 */
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 */
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 */
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 */
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 */
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  */
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
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
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  */
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  */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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) */
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 */
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 */
2817 SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqPtr)
2818 { /*lint --e{715}*/
2819  return (key1 == key2);
2820 }
2821 
2822 /** returns the hash value of the key */
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
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
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
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 */
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 */
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  */
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 )
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  */
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  */
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 )
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 */
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 */
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 */
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  */
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 )
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  */
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  */
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 )
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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. */
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
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
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
3949  SCIP_HASHSET* hashset /**< hash set */
3950  )
3951 {
3952  return hashset->slots;
3953 }
3954 
3955 /** removes all entries in a hash set. */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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  */
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
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
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
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  */
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 */
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
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  */
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
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  */
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 */
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 */
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  */
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 */
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 */
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
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  */
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  */
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 */
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 */
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 */
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  */
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 */
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 */
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 */
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  */
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
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
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  */
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  */
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) );
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  */
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 */
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  */
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
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  */
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 */
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 */
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 */
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 */
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
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 */
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
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  */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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  */
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  */
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  */
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  */
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 */
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  */
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
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 */
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) */
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 */
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  */
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 */
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 */
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
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 */
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 */
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  */
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
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  */
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  */
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  */
9691  {
9692  SCIP_ROUNDMODE roundmode;
9693 
9694  roundmode = SCIPintervalGetRoundingMode();
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  */
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
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
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
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
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  */
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  */
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 */
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
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 */
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 */
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 */
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 */
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 */
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 */
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  */
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  */
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 */
10195  SCIP_Real x /**< value to negate */
10196  )
10197 {
10198  return -x;
10199 }
10200 
10201 /*
10202  * Permutations / Shuffling
10203  */
10204 
10205 /** swaps two ints */
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 */
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 */
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  */
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  */
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  */
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 */
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 */
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  */
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  */
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() */
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 */
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 */
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  */
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  */
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  */
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  */
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 */
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 */
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) */
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 */
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) */
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 */
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 */
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 */
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 */
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 */
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 */
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) */
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 }
int SCIPprofileGetEarliestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7042
int SCIPcalcMultihashSize(int minsize)
Definition: misc.c:1578
uint32_t * hashes
Definition: struct_misc.h:132
SCIP_BTNODE * parent
Definition: struct_misc.h:231
SCIP_RETCODE SCIPqueueInsertUInt(SCIP_QUEUE *queue, unsigned int elem)
Definition: misc.c:1046
int SCIPrealarrayGetMaxIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4332
void ** SCIPdigraphGetSuccessorsData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7739
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:96
SCIP_Longint SCIPcalcBinomCoef(int n, int m)
Definition: misc.c:10123
void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
Definition: misc.c:1434
void ** slots
Definition: struct_misc.h:87
void SCIPescapeString(char *t, int bufsize, const char *s)
Definition: misc.c:10576
static void regressionRecompute(SCIP_REGRESSION *regression)
Definition: misc.c:275
SCIP_Bool SCIPmultihashExists(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2090
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3096
SCIP_RETCODE SCIPrandomGetSubset(SCIP_RANDNUMGEN *randnumgen, void **set, int nelems, void **subset, int nsubelems)
Definition: misc.c:10062
void SCIPgmlWriteEdge(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:585
SCIP_BTNODE * SCIPbtnodeGetRightchild(SCIP_BTNODE *node)
Definition: misc.c:8717
SCIP_Real * vals
Definition: struct_misc.h:151
static void * multihashlistRetrieveNext(SCIP_MULTIHASHLIST **multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1719
BMS_BLKMEM * blkmem
Definition: struct_misc.h:85
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2519
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:459
SCIP_QUEUEELEMENT * slots
Definition: struct_misc.h:54
static SCIP_Bool hashmapLookup(SCIP_HASHMAP *hashmap, void *origin, uint32_t *pos)
Definition: misc.c:2918
int SCIPhashtableGetNEntries(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2717
int SCIPqueueNElems(SCIP_QUEUE *queue)
Definition: misc.c:1188
void SCIPpqueueFree(SCIP_PQUEUE **pqueue)
Definition: misc.c:1263
unsigned int SCIPqueueRemoveUInt(SCIP_QUEUE *queue)
Definition: misc.c:1105
#define narcs
Definition: gastrans.c:68
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2487
void SCIPpqueueDelPos(SCIP_PQUEUE *pqueue, int pos)
Definition: misc.c:1374
static SCIP_Bool multihashlistRemove(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1752
SCIP_Real SCIPcalcMachineEpsilon(void)
Definition: misc.c:8999
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:7648
int SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6598
SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
Definition: misc.c:5420
static SCIP_RETCODE hashmapCheckLoad(SCIP_HASHMAP *hashmap)
Definition: misc.c:2963
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8186
void SCIPhashsetRemoveAll(SCIP_HASHSET *hashset)
Definition: misc.c:3956
void *** arcdata
Definition: struct_misc.h:214
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:140
static const int nscalars
Definition: misc.c:9453
static SCIP_RETCODE hashmapInsert(SCIP_HASHMAP *hashmap, void *origin, SCIP_HASHMAPIMAGE image, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2842
BMS_BLKMEM * blkmem
Definition: struct_misc.h:212
void * SCIPmultihashRetrieveNext(SCIP_MULTIHASH *multihash, SCIP_MULTIHASHLIST **multihashlist, void *key)
Definition: misc.c:2054
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1454
uint32_t shift
Definition: struct_misc.h:133
SCIP_BTNODE * SCIPbtnodeGetSibling(SCIP_BTNODE *node)
Definition: misc.c:8727
static void message(unsigned int type, const CURF *curf, const char *msg,...)
Definition: grphload.c:317
BMS_BLKMEM * blkmem
Definition: struct_misc.h:241
SCIP_Bool SCIPfileExists(const char *filename)
Definition: misc.c:10807
SCIP_BTNODE * SCIPbtnodeGetLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8707
SCIP_Real intercept
Definition: struct_misc.h:247
int SCIPprofileGetLoad(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6761
SCIP_RETCODE SCIPintarrayIncVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int incval)
Definition: misc.c:4674
static SCIP_RETCODE multihashlistAppend(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1592
int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
Definition: misc.c:10997
void * SCIPhashtableGetEntry(SCIP_HASHTABLE *hashtable, int entryidx)
Definition: misc.c:2725
int SCIPhashmapGetNElements(SCIP_HASHMAP *hashmap)
Definition: misc.c:3473
SCIP_Longint SCIPhashtableGetNElements(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2707
int SCIPdisjointsetGetSize(SCIP_DISJOINTSET *djset)
Definition: misc.c:11104
SCIP_RETCODE SCIPqueueInsert(SCIP_QUEUE *queue, void *elem)
Definition: misc.c:1020
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2599
#define SCIP_MAXSTRLEN
Definition: def.h:279
static uint32_t hashSetDesiredPos(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3598
void ** nodedata
Definition: struct_misc.h:215
static SCIP_RETCODE hashtableCheckLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2434
SCIP_RETCODE SCIPcomputeArraysSetminus(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10431
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2548
int SCIPintarrayGetMinIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4686
void SCIPsparseSolGetFirstSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:810
SCIP_RETCODE SCIPrealarrayCreate(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem)
Definition: misc.c:3970
static SCIP_RETCODE btnodeCreateEmpty(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8562
SCIP_RETCODE SCIPintarrayCopy(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem, SCIP_INTARRAY *sourceintarray)
Definition: misc.c:4362
SCIP_Bool SCIPboolarrayGetVal(SCIP_BOOLARRAY *boolarray, int idx)
Definition: misc.c:4953
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:412
static SCIP_RETCODE ensureSuccessorsSize(SCIP_DIGRAPH *digraph, int idx, int newsize)
Definition: misc.c:7517
void SCIPpermuteArray(void **array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10282
int firstfree
Definition: struct_misc.h:55
SCIP_RETCODE SCIPregressionCreate(SCIP_REGRESSION **regression)
Definition: misc.c:406
SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
Definition: misc.c:8331
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9022
SCIP_RETCODE SCIPmultihashSafeInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2006
static SCIP_RETCODE doProfileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6635
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:113
SCIP_Bool SCIPbtnodeIsLeaf(SCIP_BTNODE *node)
Definition: misc.c:8757
int SCIPintarrayGetVal(SCIP_INTARRAY *intarray, int idx)
Definition: misc.c:4585
SCIP_BTNODE * SCIPbtnodeGetParent(SCIP_BTNODE *node)
Definition: misc.c:8697
int * componentstarts
Definition: struct_misc.h:219
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3132
uint32_t * hashes
Definition: struct_misc.h:88
uint32_t shift
Definition: struct_misc.h:143
static int calcGrowSize(int initsize, SCIP_Real growfac, int num)
Definition: misc.c:431
SCIP_RETCODE SCIPbtCreate(SCIP_BT **tree, BMS_BLKMEM *blkmem)
Definition: misc.c:8859
#define DEFAULT_MWC
Definition: misc.c:9868
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
void * SCIPqueueRemove(SCIP_QUEUE *queue)
Definition: misc.c:1071
#define SCIP_RAND_MAX
Definition: misc.c:9785
void * SCIPptrarrayGetVal(SCIP_PTRARRAY *ptrarray, int idx)
Definition: misc.c:5306
#define FALSE
Definition: def.h:73
static SCIP_RETCODE hashtableInsert(SCIP_HASHTABLE *hashtable, void *element, void *key, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2350
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10735
#define GMLNODEWIDTH
Definition: misc.c:477
#define EPSEQ(x, y, eps)
Definition: def.h:188
static const SCIP_Real studentt_quartilesabove[]
Definition: misc.c:88
int SCIPboolarrayGetMaxIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5052
uint32_t mwc_seed
Definition: struct_misc.h:263
uint32_t mask
Definition: struct_misc.h:90
void ** slots
Definition: struct_misc.h:142
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3510
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:9981
#define SCIP_MULTIHASH_MAXSIZE
Definition: misc.c:1779
miscellaneous datastructures
#define TRUE
Definition: def.h:72
uint32_t cst_seed
Definition: struct_misc.h:264
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7706
SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
Definition: misc.c:2782
int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1468
SCIP_RETCODE SCIPptrarrayExtend(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:5120
SCIP_RETCODE SCIPboolarrayCopy(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem, SCIP_BOOLARRAY *sourceboolarray)
Definition: misc.c:4727
void * SCIPmultihashRetrieve(SCIP_MULTIHASH *multihash, void *key)
Definition: misc.c:2025
SCIPInterval exp(const SCIPInterval &x)
SCIP_RETCODE SCIPdigraphAddArcSafe(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7595
uint32_t nelements
Definition: struct_misc.h:91
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
Definition: misc.c:7470
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3201
void SCIPhashtableClear(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2338
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:115
int SCIPhashmapEntryGetImageInt(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3520
void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
Definition: misc.c:10219
static SCIP_MULTIHASHLIST * multihashlistFind(SCIP_MULTIHASHLIST *multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1638
#define SCIP_MULTIHASH_RESIZE_PERCENTAGE
Definition: misc.c:1780
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2617
#define SCIPdebugMessage
Definition: pub_message.h:87
#define DEFAULT_XOR
Definition: misc.c:9867
SCIP_RETCODE SCIPmultihashInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:1965
void SCIPqueueClear(SCIP_QUEUE *queue)
Definition: misc.c:969
SCIP_VAR ** vars
Definition: struct_misc.h:39
void SCIPdigraphPrintComponents(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8525
SCIP_Longint * SCIPsparseSolGetLbs(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:790
#define SCIP_LONGINT_MAX
Definition: def.h:149
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10562
int SCIPptrarrayGetMinIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5395
#define BMSfreeMemory(ptr)
Definition: memory.h:137
SCIP_Real SCIPnegateReal(SCIP_Real x)
Definition: misc.c:10194
static void queueCheckMarker(SCIP_QUEUE *queue)
Definition: misc.c:1006
SCIP_RETCODE SCIPdigraphResize(SCIP_DIGRAPH *digraph, int nnodes)
Definition: misc.c:7316
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3500
SCIP_Real SCIPmultihashGetLoad(SCIP_MULTIHASH *multihash)
Definition: misc.c:2182
SCIP_MULTIHASHLIST ** lists
Definition: struct_misc.h:108
template functions for sorting
void * dataptr
Definition: struct_misc.h:234
void SCIPprofilePrint(SCIP_PROFILE *profile, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:6687
SCIP_VAR ** x
Definition: circlepacking.c:54
void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
Definition: misc.c:1274
#define SCIP_MULTIHASH_GROW_FACTOR
Definition: misc.c:1781
int SCIPrealarrayGetMinIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4322
real eps
void * SCIPbtnodeGetData(SCIP_BTNODE *node)
Definition: misc.c:8687
void SCIPbtnodeSetData(SCIP_BTNODE *node, void *dataptr)
Definition: misc.c:8806
SCIP_Real SCIPerf(SCIP_Real x)
Definition: misc.c:146
SCIP_Bool SCIPbtnodeIsLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8767
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition: misc.c:673
unsigned int uinteger
Definition: struct_misc.h:47
SCIP_Real corrcoef
Definition: struct_misc.h:254
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:629
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2236
SCIP_RETCODE SCIPboolarraySetVal(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Bool val)
Definition: misc.c:4974
SCIP_Real SCIPregressionGetIntercept(SCIP_REGRESSION *regression)
Definition: misc.c:264
#define SCIP_DEFAULT_EPSILON
Definition: def.h:169
BMS_BLKMEM * blkmem
Definition: struct_misc.h:130
int SCIPregressionGetNObservations(SCIP_REGRESSION *regression)
Definition: misc.c:244
void * userptr
Definition: struct_misc.h:86
SCIP_BTNODE * root
Definition: struct_misc.h:240
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3221
SCIP_RETCODE SCIPintarrayFree(SCIP_INTARRAY **intarray)
Definition: misc.c:4385
int ** successors
Definition: struct_misc.h:213
void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:339
SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
Definition: misc.c:4304
SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
Definition: misc.c:1175
void ** slots
Definition: struct_misc.h:74
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3363
SCIP_VAR * w
Definition: circlepacking.c:58
static const int studentt_maxdf
Definition: misc.c:93
SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
Definition: misc.c:7991
int SCIPprofileGetNTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6719
SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3757
SCIP_Real inf
Definition: intervalarith.h:39
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3489
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:10912
SCIP_Real meany
Definition: struct_misc.h:250
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:453
SCIP_EXPORT void SCIPsortDownInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
void SCIPregressionReset(SCIP_REGRESSION *regression)
Definition: misc.c:390
SCIP_RETCODE SCIPrealarrayCopy(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem, SCIP_REALARRAY *sourcerealarray)
Definition: misc.c:3990
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10647
SCIP_BTNODE * left
Definition: struct_misc.h:232
void SCIPhashsetPrintStatistics(SCIP_HASHSET *hashset, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3873
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:139
int SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6608
#define GMLNODEHEIGTH
Definition: misc.c:478
void SCIPsortDown(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5979
void SCIPmessagePrintError(const char *formatstr,...)
Definition: message.c:782
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10705
interval arithmetics for provable bounds
SCIP_RETCODE SCIPactivityCreate(SCIP_RESOURCEACTIVITY **activity, SCIP_VAR *var, int duration, int demand)
Definition: misc.c:6543
#define SCIPdebugPrintf
Definition: pub_message.h:90
static SCIP_RETCODE multihashResize(SCIP_MULTIHASH *multihash)
Definition: misc.c:1785
SCIP_Real SCIPregressionGetSlope(SCIP_REGRESSION *regression)
Definition: misc.c:254
void SCIPdisjointsetFree(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem)
Definition: misc.c:11075
#define GMLNODETYPE
Definition: misc.c:480
int SCIPprofileGetCapacity(SCIP_PROFILE *profile)
Definition: misc.c:6709
SCIP_RETCODE SCIPboolarrayCreate(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4707
int * timepoints
Definition: struct_misc.h:202
uint32_t mask
Definition: struct_misc.h:134
SCIP_Real variancesumx
Definition: struct_misc.h:252
void SCIPdisjointsetUnion(SCIP_DISJOINTSET *djset, int p, int q, SCIP_Bool forcerepofp)
Definition: misc.c:11024
#define BMSmoveMemoryArray(ptr, source, num)
Definition: memory.h:130
SCIPInterval sqrt(const SCIPInterval &x)
int SCIPhashsetGetNSlots(SCIP_HASHSET *hashset)
Definition: misc.c:3940
Definition: pqueue.h:28
void SCIPmultihashPrintStatistics(SCIP_MULTIHASH *multihash, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2192
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3481
SCIP_Real SCIPrealarrayGetVal(SCIP_REALARRAY *realarray, int idx)
Definition: misc.c:4214
#define SQRTOFTWO
Definition: misc.c:51
int SCIPintarrayGetMaxIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4696
void SCIPbtPrintGml(SCIP_BT *tree, FILE *file)
Definition: misc.c:8930
SCIPInterval sign(const SCIPInterval &x)
void SCIPbtnodeFree(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8642
SCIP_Real sizefac
Definition: struct_misc.h:71
SCIP_RETCODE SCIPdigraphCreate(SCIP_DIGRAPH **digraph, BMS_BLKMEM *blkmem, int nnodes)
Definition: misc.c:7279
SCIP_Longint * SCIPsparseSolGetUbs(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:800
static int profileFindFeasibleStart(SCIP_PROFILE *profile, int pos, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:6984
int SCIPdisjointsetGetComponentCount(SCIP_DISJOINTSET *djset)
Definition: misc.c:11094
SCIP_EXPORT SCIP_Bool SCIPsortedvecFindInt(int *intarray, int val, int len, int *pos)
#define BMSallocClearBlockMemoryArray(mem, ptr, num)
Definition: memory.h:446
internal miscellaneous methods
SCIP_RETCODE SCIPboolarrayClear(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:4922
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_RETCODE SCIPmultihashCreate(SCIP_MULTIHASH **multihash, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1901
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
Definition: misc.c:9943
SCIP_Longint * lbvalues
Definition: struct_misc.h:40
uint32_t shift
Definition: struct_misc.h:89
#define REALABS(x)
Definition: def.h:187
void SCIPrandomSetSeed(SCIP_RANDNUMGEN *randnumgen, unsigned int initseed)
Definition: misc.c:9873
SCIP_Bool SCIPsparseSolGetNextSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:833
#define DEFAULT_SEED
Definition: misc.c:9866
int narticulations
Definition: struct_misc.h:224
int SCIPptrarrayGetMaxIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5405
void SCIPhashmapEntrySetImageReal(SCIP_HASHMAPENTRY *entry, SCIP_Real image)
Definition: misc.c:3562
#define SCIP_CALL(x)
Definition: def.h:370
#define SCIPhashTwo(a, b)
Definition: pub_misc.h:509
void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
Definition: misc.c:10823
#define PQ_LEFTCHILD(p)
Definition: misc.c:1213
SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3168
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:8199
void SCIPswapInts(int *value1, int *value2)
Definition: misc.c:10206
#define GMLNODEFILLCOLOR
Definition: misc.c:481
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:186
static SCIP_RETCODE profileUpdate(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:6862
SCIP_VAR * h
Definition: circlepacking.c:59
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:585
SCIP_RETCODE SCIPintarraySetVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int val)
Definition: misc.c:4606
Definition: grphload.c:88
SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
Definition: misc.c:934
SCIP_Bool SCIPstrAtStart(const char *s, const char *t, size_t tlen)
Definition: misc.c:11114
static SCIP_RETCODE ensureProfileSize(SCIP_PROFILE *profile, int neededsize)
Definition: misc.c:6798
SCIP_Real slope
Definition: struct_misc.h:248
SCIP_Bool SCIPfindSimpleRational(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9672
uint32_t xor_seed
Definition: struct_misc.h:262
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:135
void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3730
SCIP_Real SCIPhashtableGetLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2734
int SCIPpqueueFind(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1490
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:456
SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
Definition: misc.c:3699
static int getRand(unsigned int *seedp)
Definition: misc.c:9789
SCIP_Bool * vals
Definition: struct_misc.h:173
static SCIP_RETCODE pqueueResize(SCIP_PQUEUE *pqueue, int minsize)
Definition: misc.c:1219
int * components
Definition: struct_misc.h:218
#define PQ_PARENT(q)
Definition: misc.c:1212
public data structures and miscellaneous methods
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:9959
static const int primetablesize
Definition: misc.c:1566
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2286
void SCIPdisjointsetClear(SCIP_DISJOINTSET *djset)
Definition: misc.c:10980
#define SCIP_Bool
Definition: def.h:70
SCIP_VAR * SCIPactivityGetVar(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6588
#define GMLFONTSIZE
Definition: misc.c:479
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:445
SCIP_RETCODE SCIPhashsetRemove(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3798
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3014
SCIP_Bool SCIPbtnodeIsRoot(SCIP_BTNODE *node)
Definition: misc.c:8747
SCIP_Real variancesumy
Definition: struct_misc.h:253
static const SCIP_Real studentt_quartiles[]
Definition: misc.c:67
#define ELEM_DISTANCE(pos)
Definition: misc.c:3594
SCIP_RETCODE SCIPgetRandomSubset(void **set, int nelems, void **subset, int nsubelems, unsigned int randseed)
Definition: misc.c:10316
void SCIPsparseSolFree(SCIP_SPARSESOL **sparsesol)
Definition: misc.c:756
static uint32_t randomGetRand(SCIP_RANDNUMGEN *randnumgen)
Definition: misc.c:9904
SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
Definition: misc.c:6952
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7721
SCIP_RETCODE SCIPrealarrayFree(SCIP_REALARRAY **realarray)
Definition: misc.c:4014
void SCIPactivityFree(SCIP_RESOURCEACTIVITY **activity)
Definition: misc.c:6562
int SCIPprofileGetTime(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6749
void SCIPbtSetRoot(SCIP_BT *tree, SCIP_BTNODE *root)
Definition: misc.c:8983
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:458
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9295
SCIP_Bool SCIPprofileFindLeft(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6775
static const SCIP_Real simplednoms[]
Definition: misc.c:9289
#define MAX(x, y)
Definition: tclique_def.h:83
static int getRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9800
void SCIPgmlWriteClosing(FILE *file)
Definition: misc.c:689
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5440
void SCIPmultihashFree(SCIP_MULTIHASH **multihash)
Definition: misc.c:1934
SCIP_RETCODE SCIPdigraphSetNSuccessors(SCIP_DIGRAPH *digraph, int node, int nsuccessors)
Definition: misc.c:7632
#define DEFAULT_CST
Definition: misc.c:9869
SCIP_RETCODE SCIPbtnodeCreate(SCIP_BT *tree, SCIP_BTNODE **node, void *dataptr)
Definition: misc.c:8578
static const unsigned int randseed
Definition: circle.c:46
void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
Definition: misc.c:10000
SCIP_Bool SCIPintervalHasRoundingControl(void)
SCIP_Bool SCIPbtIsEmpty(SCIP_BT *tree)
Definition: misc.c:8960
SCIP_Real SCIPhashmapEntryGetImageReal(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3530
int SCIPboolarrayGetMinIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5042
int * successorssize
Definition: struct_misc.h:216
#define SCIP_DECL_PQUEUEELEMCHGPOS(x)
Definition: type_misc.h:184
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:126
unsigned int SCIPqueueFirstUInt(SCIP_QUEUE *queue)
Definition: misc.c:1157
SCIPInterval log(const SCIPInterval &x)
SCIP_Bool SCIPhashsetIsEmpty(SCIP_HASHSET *hashset)
Definition: misc.c:3924
SCIP_RETCODE SCIPdigraphSetSizes(SCIP_DIGRAPH *digraph, int *sizes)
Definition: misc.c:7446
int * SCIPprofileGetLoads(SCIP_PROFILE *profile)
Definition: misc.c:6739
SCIP_BTNODE * SCIPbtGetRoot(SCIP_BT *tree)
Definition: misc.c:8970
int * articulations
Definition: struct_misc.h:220
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3573
static SCIP_Real getRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9820
SCIP_Longint * ubvalues
Definition: struct_misc.h:41
static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta)
Definition: misc.c:9430
#define BMSclearMemory(ptr)
Definition: memory.h:121
SCIP_Real SCIPcomputeGap(SCIP_Real eps, SCIP_Real inf, SCIP_Real primalbound, SCIP_Real dualbound)
Definition: misc.c:10930
SCIP_Real sumxy
Definition: struct_misc.h:251
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10232
void SCIPregressionFree(SCIP_REGRESSION **regression)
Definition: misc.c:422
SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
Definition: misc.c:9265
static void depthFirstSearch(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *dfsstack, int *stackadjvisited, int *dfsnodes, int *ndfsnodes)
Definition: misc.c:7756
#define BMSallocClearMemoryArray(ptr, num)
Definition: memory.h:117
static void incrementalStatsUpdate(SCIP_Real value, SCIP_Real *meanptr, SCIP_Real *sumvarptr, int nobservations, SCIP_Bool add)
Definition: misc.c:313
SCIP_VAR ** SCIPsparseSolGetVars(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:770
SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3241
SCIP_RETCODE SCIPptrarrayClear(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5275
#define GMLEDGECOLOR
Definition: misc.c:482
uint32_t nelements
Definition: struct_misc.h:144
void SCIPhashmapPrintStatistics(SCIP_HASHMAP *hashmap, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3425
static void tarjan(SCIP_DIGRAPH *digraph, int v, int *lowlink, int *dfsidx, int *stack, int *stacksize, SCIP_Bool *unprocessed, SCIP_Bool *nodeinstack, int *maxdfs, int *strongcomponents, int *nstrongcomponents, int *strongcompstartidx, int *nstorednodes)
Definition: misc.c:8222
#define SCIP_REAL_MAX
Definition: def.h:164
static SCIP_RETCODE queueCheckSize(SCIP_QUEUE *queue)
Definition: misc.c:981
SCIP_Bool articulationscheck
Definition: struct_misc.h:225
static uint32_t hashvalue(uint64_t input)
Definition: misc.c:1570
void SCIPpermuteIntArray(int *array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10248
SCIP_Real * r
Definition: circlepacking.c:50
int SCIPprofileGetLatestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7191
void SCIPmultihashRemoveAll(SCIP_MULTIHASH *multihash)
Definition: misc.c:2151
#define EPSGT(x, y, eps)
Definition: def.h:191
#define SCIP_DECL_SORTINDCOMP(x)
Definition: type_misc.h:164
SCIP_Real meanx
Definition: struct_misc.h:249
SCIP_VAR ** b
Definition: circlepacking.c:56
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:7688
SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)))
Definition: misc.c:1236
SCIP_RETCODE SCIPptrarrayFree(SCIP_PTRARRAY **ptrarray)
Definition: misc.c:5106
SCIP_EXPORT void SCIPsortedvecInsertIntInt(int *intarray1, int *intarray2, int keyval, int field1val, int *len, int *pos)
#define GMLNODEBORDERCOLOR
Definition: misc.c:483
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1479
static SCIP_RETCODE hashsetCheckLoad(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3658
SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:3740
SCIP_RETCODE SCIPmultihashRemove(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2117
int * SCIPprofileGetTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6729
SCIP_RETCODE SCIPdigraphGetArticulationPoints(SCIP_DIGRAPH *digraph, int **articulations, int *narticulations)
Definition: misc.c:7902
void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2695
void SCIPbtnodeSetParent(SCIP_BTNODE *node, SCIP_BTNODE *parent)
Definition: misc.c:8820
SCIP_HASHMAPTYPE hashmaptype
Definition: struct_misc.h:136
SCIP_RETCODE SCIPintarrayExtend(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4399
SCIP_RETCODE SCIPptrarraySetVal(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, void *val)
Definition: misc.c:5327
SCIP_HASHMAPENTRY * slots
Definition: struct_misc.h:131
int SCIPgetRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9842
void SCIPgmlWriteNodeWeight(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor, SCIP_Real weight)
Definition: misc.c:535
SCIP_EXPORT void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
static int profileFindDownFeasibleStart(SCIP_PROFILE *profile, int pos, int ect, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7134
SCIP_BTNODE * right
Definition: struct_misc.h:233
SCIP_RETCODE SCIPdigraphCopy(SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph, BMS_BLKMEM *targetblkmem)
Definition: misc.c:7356
SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
Definition: misc.c:2791
void SCIPbtnodeSetLeftchild(SCIP_BTNODE *node, SCIP_BTNODE *left)
Definition: misc.c:8834
void SCIPprofileFree(SCIP_PROFILE **profile)
Definition: misc.c:6671
SCIP_RETCODE SCIPboolarrayFree(SCIP_BOOLARRAY **boolarray)
Definition: misc.c:4751
public methods for message output
int SCIPactivityGetEnergy(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6618
SCIP_VAR * a
Definition: circlepacking.c:57
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10604
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:609
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2744
static const SCIP_Real scalars[]
Definition: misc.c:9452
void * SCIPdigraphGetNodeData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7658
void SCIPbtnodeSetRightchild(SCIP_BTNODE *node, SCIP_BTNODE *right)
Definition: misc.c:8848
SCIP_Real SCIPgetRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9855
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3048
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9719
static SCIP_RETCODE profileInsertTimepoint(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6821
void SCIPdigraphPrintGml(SCIP_DIGRAPH *digraph, FILE *file)
Definition: misc.c:8486
#define SCIP_Real
Definition: def.h:163
int componentstartsize
Definition: struct_misc.h:222
uint32_t nelements
Definition: struct_misc.h:135
BMS_BLKMEM * blkmem
Definition: struct_misc.h:107
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:391
SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4028
SCIP_VAR ** y
Definition: circlepacking.c:55
SCIP_Bool SCIPbtnodeIsRightchild(SCIP_BTNODE *node)
Definition: misc.c:8785
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:9927
SCIP_RETCODE SCIPcomputeArraysIntersection(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10375
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8120
void SCIPhashmapEntrySetImageInt(SCIP_HASHMAPENTRY *entry, int image)
Definition: misc.c:3551
#define BMSallocMemory(ptr)
Definition: memory.h:111
#define SCIP_INVALID
Definition: def.h:183
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:119
static int primetable[]
Definition: misc.c:1514
static void hashsetInsert(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3607
static void multihashlistFree(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem)
Definition: misc.c:1614
void SCIPprintSysError(const char *message)
Definition: misc.c:10513
static void btnodeFreeLeaf(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8601
#define SCIP_Longint
Definition: def.h:148
static void btPrintSubtree(SCIP_BTNODE *node, FILE *file, int *nnodes)
Definition: misc.c:8894
SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
Definition: misc.c:2810
SCIP_RETCODE SCIPdisjointsetCreate(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem, int ncomponents)
Definition: misc.c:10957
SCIP_RETCODE SCIPrealarraySetVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real val)
Definition: misc.c:4235
SCIP_RETCODE SCIPintarrayClear(SCIP_INTARRAY *intarray)
Definition: misc.c:4554
int SCIP_ROUNDMODE
Definition: intervalarith.h:46
void ** vals
Definition: struct_misc.h:184
void SCIPdigraphPrint(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8451
#define STARTSUCCESSORSSIZE
Definition: misc.c:7513
#define nnodes
Definition: gastrans.c:65
SCIP_MULTIHASHLIST * next
Definition: struct_misc.h:98
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:443
SCIP_RETCODE SCIPboolarrayExtend(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4765
static void pqueueElemChgPos(SCIP_PQUEUE *pqueue, void *elem, int oldpos, int newpos)
Definition: misc.c:1285
int * nsuccessors
Definition: struct_misc.h:217
#define EPSFLOOR(x, eps)
Definition: def.h:196
SCIP_Longint nelements
Definition: struct_misc.h:111
SCIP_Real sizefac
Definition: struct_misc.h:53
void SCIPqueueFree(SCIP_QUEUE **queue)
Definition: misc.c:958
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:122
void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:371
common defines and data types used in all packages of SCIP
void SCIPdigraphSetNodeData(SCIP_DIGRAPH *digraph, void *dataptr, int node)
Definition: misc.c:7674
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:429
SCIP_Bool SCIPstrToIntValue(const char *str, int *value, char **endptr)
Definition: misc.c:10674
SCIP_RETCODE SCIPhashmapSetImageReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3331
#define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
Definition: def.h:401
static SCIP_RETCODE queueResize(SCIP_QUEUE *queue, int minsize)
Definition: misc.c:915
#define SCIP_CALL_ABORT(x)
Definition: def.h:349
static void findArticulationPointsUtil(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *tdisc, int *mindisc, int *parent, SCIP_Bool *articulationflag, int time)
Definition: misc.c:7835
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:487
static void * multihashlistRetrieve(SCIP_MULTIHASHLIST *multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1669
SCIP_RETCODE SCIPcalcIntegralScalar(SCIP_Real *vals, int nvals, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Real *intscalar, SCIP_Bool *success)
Definition: misc.c:9458
SCIP_RETCODE SCIPptrarrayCreate(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem)
Definition: misc.c:5063
int SCIPsparseSolGetNVars(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:780
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9274
#define SCIP_ALLOC(x)
Definition: def.h:381
SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
Definition: misc.c:3463
SCIP_RETCODE SCIPsparseSolCreate(SCIP_SPARSESOL **sparsesol, SCIP_VAR **vars, int nvars, SCIP_Bool cleared)
Definition: misc.c:704
void SCIPbtFree(SCIP_BT **tree)
Definition: misc.c:8878
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
void ** SCIPhashsetGetSlots(SCIP_HASHSET *hashset)
Definition: misc.c:3948
SCIP_RETCODE SCIPprofileInsertCore(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:6922
SCIP_Longint SCIPmultihashGetNElements(SCIP_MULTIHASH *multihash)
Definition: misc.c:2172
void * SCIPqueueFirst(SCIP_QUEUE *queue)
Definition: misc.c:1139
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:10488
SCIP_HASHMAPIMAGE image
Definition: struct_misc.h:124
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3379
SCIP_RETCODE SCIPintarrayCreate(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4342
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:449
void SCIPhashmapEntrySetImage(SCIP_HASHMAPENTRY *entry, void *image)
Definition: misc.c:3540
void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8419
SCIP_RETCODE SCIPprofileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6657
void SCIPintervalSetRoundingModeDownwards(void)
int SCIPhashsetGetNElements(SCIP_HASHSET *hashset)
Definition: misc.c:3932
void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
Definition: misc.c:10030
#define EPSZ(x, eps)
Definition: def.h:193
int firstused
Definition: struct_misc.h:56
SCIP_RETCODE SCIPptrarrayCopy(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem, SCIP_PTRARRAY *sourceptrarray)
Definition: misc.c:5083
#define PQ_RIGHTCHILD(p)
Definition: misc.c:1214
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3263
SCIP_Real SCIPnormalGetCriticalValue(SCIP_CONFIDENCELEVEL clevel)
Definition: misc.c:173
SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7564
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:4183
SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1335
SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3297