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