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 visit 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-4);
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 {
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 {
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 /* SCIPsortDownRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5819 #define SORTTPL_NAMEEXT DownRealIntInt
5820 #define SORTTPL_KEYTYPE SCIP_Real
5821 #define SORTTPL_FIELD1TYPE int
5822 #define SORTTPL_FIELD2TYPE int
5823 #define SORTTPL_BACKWARDS
5824 #include "scip/sorttpl.c" /*lint !e451*/
5825 
5826 /* SCIPsortDownRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5827 #define SORTTPL_NAMEEXT DownRealIntLong
5828 #define SORTTPL_KEYTYPE SCIP_Real
5829 #define SORTTPL_FIELD1TYPE int
5830 #define SORTTPL_FIELD2TYPE SCIP_Longint
5831 #define SORTTPL_BACKWARDS
5832 #include "scip/sorttpl.c" /*lint !e451*/
5833 
5834 
5835 /* SCIPsortDownRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5836 #define SORTTPL_NAMEEXT DownRealIntPtr
5837 #define SORTTPL_KEYTYPE SCIP_Real
5838 #define SORTTPL_FIELD1TYPE int
5839 #define SORTTPL_FIELD2TYPE void*
5840 #define SORTTPL_BACKWARDS
5841 #include "scip/sorttpl.c" /*lint !e451*/
5842 
5843 
5844 /* SCIPsortDownRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5845 #define SORTTPL_NAMEEXT DownRealPtrPtr
5846 #define SORTTPL_KEYTYPE SCIP_Real
5847 #define SORTTPL_FIELD1TYPE void*
5848 #define SORTTPL_FIELD2TYPE void*
5849 #define SORTTPL_BACKWARDS
5850 #include "scip/sorttpl.c" /*lint !e451*/
5851 
5852 /* SCIPsortDownRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5853 #define SORTTPL_NAMEEXT DownRealRealInt
5854 #define SORTTPL_KEYTYPE SCIP_Real
5855 #define SORTTPL_FIELD1TYPE SCIP_Real
5856 #define SORTTPL_FIELD2TYPE int
5857 #define SORTTPL_BACKWARDS
5858 #include "scip/sorttpl.c" /*lint !e451*/
5859 
5860 /* SCIPsortDownRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5861 #define SORTTPL_NAMEEXT DownRealRealPtr
5862 #define SORTTPL_KEYTYPE SCIP_Real
5863 #define SORTTPL_FIELD1TYPE SCIP_Real
5864 #define SORTTPL_FIELD2TYPE void*
5865 #define SORTTPL_BACKWARDS
5866 #include "scip/sorttpl.c" /*lint !e451*/
5867 
5868 /* SCIPsortDownRealRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5869 #define SORTTPL_NAMEEXT DownRealRealPtrPtr
5870 #define SORTTPL_KEYTYPE SCIP_Real
5871 #define SORTTPL_FIELD1TYPE SCIP_Real
5872 #define SORTTPL_FIELD2TYPE void*
5873 #define SORTTPL_FIELD3TYPE void*
5874 #define SORTTPL_BACKWARDS
5875 #include "scip/sorttpl.c" /*lint !e451*/
5876 
5877 
5878 /* SCIPsortDownRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5879 #define SORTTPL_NAMEEXT DownRealLongRealInt
5880 #define SORTTPL_KEYTYPE SCIP_Real
5881 #define SORTTPL_FIELD1TYPE SCIP_Longint
5882 #define SORTTPL_FIELD2TYPE SCIP_Real
5883 #define SORTTPL_FIELD3TYPE int
5884 #define SORTTPL_BACKWARDS
5885 #include "scip/sorttpl.c" /*lint !e451*/
5886 
5887 
5888 /* SCIPsortDownRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5889 #define SORTTPL_NAMEEXT DownRealRealIntInt
5890 #define SORTTPL_KEYTYPE SCIP_Real
5891 #define SORTTPL_FIELD1TYPE SCIP_Real
5892 #define SORTTPL_FIELD2TYPE int
5893 #define SORTTPL_FIELD3TYPE int
5894 #define SORTTPL_BACKWARDS
5895 #include "scip/sorttpl.c" /*lint !e451*/
5896 
5897 
5898 /* SCIPsortDownRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5899 #define SORTTPL_NAMEEXT DownRealRealRealInt
5900 #define SORTTPL_KEYTYPE SCIP_Real
5901 #define SORTTPL_FIELD1TYPE SCIP_Real
5902 #define SORTTPL_FIELD2TYPE SCIP_Real
5903 #define SORTTPL_FIELD3TYPE int
5904 #define SORTTPL_BACKWARDS
5905 #include "scip/sorttpl.c" /*lint !e451*/
5906 
5907 
5908 /* SCIPsortDownRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5909 #define SORTTPL_NAMEEXT DownRealRealRealPtr
5910 #define SORTTPL_KEYTYPE SCIP_Real
5911 #define SORTTPL_FIELD1TYPE SCIP_Real
5912 #define SORTTPL_FIELD2TYPE SCIP_Real
5913 #define SORTTPL_FIELD3TYPE void*
5914 #define SORTTPL_BACKWARDS
5915 #include "scip/sorttpl.c" /*lint !e451*/
5916 
5917 
5918 /* SCIPsortDownRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5919 #define SORTTPL_NAMEEXT DownRealPtrPtrInt
5920 #define SORTTPL_KEYTYPE SCIP_Real
5921 #define SORTTPL_FIELD1TYPE void*
5922 #define SORTTPL_FIELD2TYPE void*
5923 #define SORTTPL_FIELD3TYPE int
5924 #define SORTTPL_BACKWARDS
5925 #include "scip/sorttpl.c" /*lint !e451*/
5926 
5927 /* SCIPsortDownRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5928 #define SORTTPL_NAMEEXT DownRealPtrPtrIntInt
5929 #define SORTTPL_KEYTYPE SCIP_Real
5930 #define SORTTPL_FIELD1TYPE void*
5931 #define SORTTPL_FIELD2TYPE void*
5932 #define SORTTPL_FIELD3TYPE int
5933 #define SORTTPL_FIELD4TYPE int
5934 #define SORTTPL_BACKWARDS
5935 #include "scip/sorttpl.c" /*lint !e451*/
5936 
5937 
5938 /* SCIPsortDownRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5939 #define SORTTPL_NAMEEXT DownRealRealRealBoolPtr
5940 #define SORTTPL_KEYTYPE SCIP_Real
5941 #define SORTTPL_FIELD1TYPE SCIP_Real
5942 #define SORTTPL_FIELD2TYPE SCIP_Real
5943 #define SORTTPL_FIELD3TYPE SCIP_Bool
5944 #define SORTTPL_FIELD4TYPE void*
5945 #define SORTTPL_BACKWARDS
5946 #include "scip/sorttpl.c" /*lint !e451*/
5947 
5948 
5949 /* SCIPsortDownRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5950 #define SORTTPL_NAMEEXT DownRealRealRealBoolBoolPtr
5951 #define SORTTPL_KEYTYPE SCIP_Real
5952 #define SORTTPL_FIELD1TYPE SCIP_Real
5953 #define SORTTPL_FIELD2TYPE SCIP_Real
5954 #define SORTTPL_FIELD3TYPE SCIP_Bool
5955 #define SORTTPL_FIELD4TYPE SCIP_Bool
5956 #define SORTTPL_FIELD5TYPE void*
5957 #include "scip/sorttpl.c" /*lint !e451*/
5958 
5959 
5960 /* SCIPsortDownInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5961 #define SORTTPL_NAMEEXT DownInt
5962 #define SORTTPL_KEYTYPE int
5963 #define SORTTPL_BACKWARDS
5964 #include "scip/sorttpl.c" /*lint !e451*/
5965 
5966 
5967 /* SCIPsortDownIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5968 #define SORTTPL_NAMEEXT DownIntInt
5969 #define SORTTPL_KEYTYPE int
5970 #define SORTTPL_FIELD1TYPE int
5971 #define SORTTPL_BACKWARDS
5972 #include "scip/sorttpl.c" /*lint !e451*/
5973 
5974 
5975 /* SCIPsortDownIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5976 #define SORTTPL_NAMEEXT DownIntIntReal
5977 #define SORTTPL_KEYTYPE int
5978 #define SORTTPL_FIELD1TYPE int
5979 #define SORTTPL_FIELD2TYPE SCIP_Real
5980 #define SORTTPL_BACKWARDS
5981 #include "scip/sorttpl.c" /*lint !e451*/
5982 
5983 
5984 /* SCIPsortDownIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5985 #define SORTTPL_NAMEEXT DownIntReal
5986 #define SORTTPL_KEYTYPE int
5987 #define SORTTPL_FIELD1TYPE SCIP_Real
5988 #define SORTTPL_BACKWARDS
5989 #include "scip/sorttpl.c" /*lint !e451*/
5990 
5991 
5992 /* SCIPsortDownIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5993 #define SORTTPL_NAMEEXT DownIntPtr
5994 #define SORTTPL_KEYTYPE int
5995 #define SORTTPL_FIELD1TYPE void*
5996 #define SORTTPL_BACKWARDS
5997 #include "scip/sorttpl.c" /*lint !e451*/
5998 
5999 
6000 /* SCIPsortDownIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6001 #define SORTTPL_NAMEEXT DownIntIntInt
6002 #define SORTTPL_KEYTYPE int
6003 #define SORTTPL_FIELD1TYPE int
6004 #define SORTTPL_FIELD2TYPE int
6005 #define SORTTPL_BACKWARDS
6006 #include "scip/sorttpl.c" /*lint !e451*/
6007 
6008 
6009 /* SCIPsortDownIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6010 #define SORTTPL_NAMEEXT DownIntIntLong
6011 #define SORTTPL_KEYTYPE int
6012 #define SORTTPL_FIELD1TYPE int
6013 #define SORTTPL_FIELD2TYPE SCIP_Longint
6014 #define SORTTPL_BACKWARDS
6015 #include "scip/sorttpl.c" /*lint !e451*/
6016 
6017 
6018 /* SCIPsortDownIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6019 #define SORTTPL_NAMEEXT DownIntIntPtr
6020 #define SORTTPL_KEYTYPE int
6021 #define SORTTPL_FIELD1TYPE int
6022 #define SORTTPL_FIELD2TYPE void*
6023 #define SORTTPL_BACKWARDS
6024 #include "scip/sorttpl.c" /*lint !e451*/
6025 
6026 
6027 /* SCIPsortDownIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6028 #define SORTTPL_NAMEEXT DownIntIntIntPtr
6029 #define SORTTPL_KEYTYPE int
6030 #define SORTTPL_FIELD1TYPE int
6031 #define SORTTPL_FIELD2TYPE int
6032 #define SORTTPL_FIELD3TYPE void*
6033 #define SORTTPL_BACKWARDS
6034 #include "scip/sorttpl.c" /*lint !e451*/
6035 
6036 
6037 /* SCIPsortDownIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6038 #define SORTTPL_NAMEEXT DownIntPtrIntReal
6039 #define SORTTPL_KEYTYPE int
6040 #define SORTTPL_FIELD1TYPE void*
6041 #define SORTTPL_FIELD2TYPE int
6042 #define SORTTPL_FIELD3TYPE SCIP_Real
6043 #define SORTTPL_BACKWARDS
6044 #include "scip/sorttpl.c" /*lint !e451*/
6045 
6046 
6047 /* SCIPsortDownLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6048 #define SORTTPL_NAMEEXT DownLong
6049 #define SORTTPL_KEYTYPE SCIP_Longint
6050 #define SORTTPL_BACKWARDS
6051 #include "scip/sorttpl.c" /*lint !e451*/
6052 
6053 
6054 /* SCIPsortDownLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6055 #define SORTTPL_NAMEEXT DownLongPtr
6056 #define SORTTPL_KEYTYPE SCIP_Longint
6057 #define SORTTPL_FIELD1TYPE void*
6058 #define SORTTPL_BACKWARDS
6059 #include "scip/sorttpl.c" /*lint !e451*/
6060 
6061 
6062 /* SCIPsortDownLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6063 #define SORTTPL_NAMEEXT DownLongPtrInt
6064 #define SORTTPL_KEYTYPE SCIP_Longint
6065 #define SORTTPL_FIELD1TYPE void*
6066 #define SORTTPL_FIELD2TYPE int
6067 #define SORTTPL_BACKWARDS
6068 #include "scip/sorttpl.c" /*lint !e451*/
6069 
6070 
6071 /* SCIPsortDownLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6072 #define SORTTPL_NAMEEXT DownLongPtrRealBool
6073 #define SORTTPL_KEYTYPE SCIP_Longint
6074 #define SORTTPL_FIELD1TYPE void*
6075 #define SORTTPL_FIELD2TYPE SCIP_Real
6076 #define SORTTPL_FIELD3TYPE SCIP_Bool
6077 #define SORTTPL_BACKWARDS
6078 #include "scip/sorttpl.c" /*lint !e451*/
6079 
6080 
6081 /* SCIPsortDownLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6082 #define SORTTPL_NAMEEXT DownLongPtrRealRealBool
6083 #define SORTTPL_KEYTYPE SCIP_Longint
6084 #define SORTTPL_FIELD1TYPE void*
6085 #define SORTTPL_FIELD2TYPE SCIP_Real
6086 #define SORTTPL_FIELD3TYPE SCIP_Real
6087 #define SORTTPL_FIELD4TYPE SCIP_Bool
6088 #define SORTTPL_BACKWARDS
6089 #include "scip/sorttpl.c" /*lint !e451*/
6090 
6091 
6092 /* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6093 #define SORTTPL_NAMEEXT DownLongPtrRealRealIntBool
6094 #define SORTTPL_KEYTYPE SCIP_Longint
6095 #define SORTTPL_FIELD1TYPE void*
6096 #define SORTTPL_FIELD2TYPE SCIP_Real
6097 #define SORTTPL_FIELD3TYPE SCIP_Real
6098 #define SORTTPL_FIELD4TYPE int
6099 #define SORTTPL_FIELD5TYPE SCIP_Bool
6100 #define SORTTPL_BACKWARDS
6101 #include "scip/sorttpl.c" /*lint !e451*/
6102 
6103 
6104 /* SCIPsortDownLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6105 #define SORTTPL_NAMEEXT DownLongPtrPtrInt
6106 #define SORTTPL_KEYTYPE SCIP_Longint
6107 #define SORTTPL_FIELD1TYPE void*
6108 #define SORTTPL_FIELD2TYPE void*
6109 #define SORTTPL_FIELD3TYPE int
6110 #define SORTTPL_BACKWARDS
6111 #include "scip/sorttpl.c" /*lint !e451*/
6112 
6113 
6114 /* SCIPsortDownLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6115 #define SORTTPL_NAMEEXT DownLongPtrPtrIntInt
6116 #define SORTTPL_KEYTYPE SCIP_Longint
6117 #define SORTTPL_FIELD1TYPE void*
6118 #define SORTTPL_FIELD2TYPE void*
6119 #define SORTTPL_FIELD3TYPE int
6120 #define SORTTPL_FIELD4TYPE int
6121 #define SORTTPL_BACKWARDS
6122 #include "scip/sorttpl.c" /*lint !e451*/
6123 
6124 
6125 /* SCIPsortDownLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6126 #define SORTTPL_NAMEEXT DownLongPtrPtrBoolInt
6127 #define SORTTPL_KEYTYPE SCIP_Longint
6128 #define SORTTPL_FIELD1TYPE void*
6129 #define SORTTPL_FIELD2TYPE void*
6130 #define SORTTPL_FIELD3TYPE SCIP_Bool
6131 #define SORTTPL_FIELD4TYPE int
6132 #define SORTTPL_BACKWARDS
6133 #include "scip/sorttpl.c" /*lint !e451*/
6134 
6135 
6136 /* SCIPsortDownPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6137 #define SORTTPL_NAMEEXT DownPtrIntIntBoolBool
6138 #define SORTTPL_KEYTYPE void*
6139 #define SORTTPL_FIELD1TYPE int
6140 #define SORTTPL_FIELD2TYPE int
6141 #define SORTTPL_FIELD3TYPE SCIP_Bool
6142 #define SORTTPL_FIELD4TYPE SCIP_Bool
6143 #define SORTTPL_PTRCOMP
6144 #define SORTTPL_BACKWARDS
6145 #include "scip/sorttpl.c" /*lint !e451*/
6146 
6147 
6148 /* SCIPsortDownIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6149 #define SORTTPL_NAMEEXT DownIntPtrIntIntBoolBool
6150 #define SORTTPL_KEYTYPE int
6151 #define SORTTPL_FIELD1TYPE void*
6152 #define SORTTPL_FIELD2TYPE int
6153 #define SORTTPL_FIELD3TYPE int
6154 #define SORTTPL_FIELD4TYPE SCIP_Bool
6155 #define SORTTPL_FIELD5TYPE SCIP_Bool
6156 #define SORTTPL_BACKWARDS
6157 #include "scip/sorttpl.c" /*lint !e451*/
6158 
6159 /*
6160  * Resulting activity
6161  */
6162 
6163 /** create a resource activity */
6165  SCIP_RESOURCEACTIVITY** activity, /**< pointer to store the resource activity */
6166  SCIP_VAR* var, /**< start time variable of the activity */
6167  int duration, /**< duration of the activity */
6168  int demand /**< demand of the activity */
6169  )
6170 {
6171  assert(activity != NULL);
6172 
6173  SCIP_ALLOC( BMSallocMemory(activity) );
6174 
6175  (*activity)->var = var;
6176  (*activity)->duration = duration;
6177  (*activity)->demand = demand;
6178 
6179  return SCIP_OKAY;
6180 }
6181 
6182 /** frees a resource activity */
6184  SCIP_RESOURCEACTIVITY** activity /**< pointer to the resource activity */
6185  )
6186 {
6187  assert(activity != NULL);
6188  assert(*activity != NULL);
6189 
6190  BMSfreeMemory(activity);
6191 }
6192 
6193 /* some simple variable functions implemented as defines */
6194 
6195 #ifndef NDEBUG
6196 
6197 /* In debug mode, the following methods are implemented as function calls to ensure
6198  * type validity.
6199  * In optimized mode, the methods are implemented as defines to improve performance.
6200  * However, we want to have them in the library anyways, so we have to undef the defines.
6201  */
6202 
6203 #undef SCIPactivityGetVar
6204 #undef SCIPactivityGetDuration
6205 #undef SCIPactivityGetDemand
6206 #undef SCIPactivityGetEnergy
6207 
6208 /** returns the start time variable of the resource activity */
6210  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6211  )
6212 {
6213  assert(activity != NULL);
6214 
6215  return activity->var;
6216 }
6217 
6218 /** returns the duration of the resource activity */
6220  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6221  )
6222 {
6223  assert(activity != NULL);
6224 
6225  return activity->duration;
6226 }
6227 
6228 /** returns the demand of the resource activity */
6230  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6231  )
6232 {
6233  assert(activity != NULL);
6234 
6235  return activity->demand;
6236 }
6237 
6238 /** returns the energy of the resource activity */
6240  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6241  )
6242 {
6243  assert(activity != NULL);
6244 
6245  return activity->duration * activity->demand ;
6246 }
6247 
6248 #endif
6249 
6250 /*
6251  * Resource Profile
6252  */
6253 
6254 /** helper method to create a profile */
6255 static
6257  SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6258  int capacity /**< resource capacity */
6259  )
6260 {
6261  SCIP_ALLOC( BMSallocMemory(profile) );
6262  BMSclearMemory(*profile);
6263 
6264  (*profile)->arraysize = 10;
6265  SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->timepoints, (*profile)->arraysize) );
6266  SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->loads, (*profile)->arraysize) );
6267 
6268  /* setup resource profile for use */
6269  (*profile)->ntimepoints = 1;
6270  (*profile)->timepoints[0] = 0;
6271  (*profile)->loads[0] = 0;
6272  (*profile)->capacity = capacity;
6273 
6274  return SCIP_OKAY;
6275 }
6276 
6277 /** creates resource profile */
6279  SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6280  int capacity /**< resource capacity */
6281  )
6282 {
6283  assert(profile != NULL);
6284  assert(capacity > 0);
6285 
6286  SCIP_CALL_FINALLY( doProfileCreate(profile, capacity), SCIPprofileFree(profile) );
6287 
6288  return SCIP_OKAY;
6289 }
6290 
6291 /** frees given resource profile */
6293  SCIP_PROFILE** profile /**< pointer to the resource profile */
6294  )
6295 {
6296  assert(profile != NULL);
6297 
6298  /* free resource profile */
6299  if( *profile != NULL )
6300  {
6301  BMSfreeMemoryArrayNull(&(*profile)->loads);
6302  BMSfreeMemoryArrayNull(&(*profile)->timepoints);
6303  BMSfreeMemory(profile);
6304  }
6305 }
6306 
6307 /** output of the given resource profile */
6309  SCIP_PROFILE* profile, /**< resource profile to output */
6310  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
6311  FILE* file /**< output file (or NULL for standard output) */
6312  )
6313 {
6314  int t;
6315 
6316  SCIPmessageFPrintInfo(messagehdlr, file, "Profile <%p> (capacity %d) --> ", profile, profile->capacity);
6317 
6318  for( t = 0; t < profile->ntimepoints; ++t )
6319  {
6320  if( t == 0 )
6321  SCIPmessageFPrintInfo(messagehdlr, file, "%d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6322  else
6323  SCIPmessageFPrintInfo(messagehdlr, file, ", %d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6324  }
6325 
6326  SCIPmessageFPrintInfo(messagehdlr, file,"\n");
6327 }
6328 
6329 /** returns the capacity of the resource profile */
6331  SCIP_PROFILE* profile /**< resource profile to use */
6332  )
6333 {
6334  assert(profile != NULL);
6335 
6336  return profile->capacity;
6337 }
6338 
6339 /** returns the number time points of the resource profile */
6341  SCIP_PROFILE* profile /**< resource profile to use */
6342  )
6343 {
6344  assert(profile != NULL);
6345 
6346  return profile->ntimepoints;
6347 }
6348 
6349 /** returns the time points of the resource profile */
6351  SCIP_PROFILE* profile /**< resource profile to use */
6352  )
6353 {
6354  assert(profile != NULL);
6355 
6356  return profile->timepoints;
6357 }
6358 
6359 /** returns the loads of the resource profile */
6361  SCIP_PROFILE* profile /**< resource profile to use */
6362  )
6363 {
6364  assert(profile != NULL);
6365 
6366  return profile->loads;
6367 }
6368 
6369 /** returns the time point for given position of the resource profile */
6371  SCIP_PROFILE* profile, /**< resource profile to use */
6372  int pos /**< position */
6373  )
6374 {
6375  assert(profile != NULL);
6376  assert(pos >= 0 && pos < profile->ntimepoints);
6377 
6378  return profile->timepoints[pos];
6379 }
6380 
6381 /** returns the loads of the resource profile at the given position */
6383  SCIP_PROFILE* profile, /**< resource profile */
6384  int pos /**< position */
6385  )
6386 {
6387  assert(profile != NULL);
6388  assert(pos >= 0 && pos < profile->ntimepoints);
6389 
6390  return profile->loads[pos];
6391 }
6392 
6393 /** returns if the given time point exists in the resource profile and stores the position of the given time point if it
6394  * exists; otherwise the position of the next smaller existing time point is stored
6395  */
6397  SCIP_PROFILE* profile, /**< resource profile to search */
6398  int timepoint, /**< time point to search for */
6399  int* pos /**< pointer to store the position */
6400  )
6401 {
6402  assert(profile != NULL);
6403  assert(timepoint >= 0);
6404  assert(profile->ntimepoints > 0);
6405  assert(profile->timepoints[0] == 0);
6406 
6407  /* find the position of time point in the time points array via binary search */
6408  if( SCIPsortedvecFindInt(profile->timepoints, timepoint, profile->ntimepoints, pos) )
6409  return TRUE;
6410 
6411  assert(*pos > 0);
6412  (*pos)--;
6413 
6414  return FALSE;
6415 }
6416 
6417 /* ensures that resource profile arrays is big enough */
6418 static
6420  SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6421  int neededsize /**< needed size */
6422  )
6423 {
6424  assert(profile->arraysize > 0);
6425 
6426  /* check whether the arrays are big enough */
6427  if( neededsize <= profile->arraysize )
6428  return SCIP_OKAY;
6429 
6430  profile->arraysize *= 2;
6431 
6432  SCIP_ALLOC( BMSreallocMemoryArray(&profile->timepoints, profile->arraysize) );
6433  SCIP_ALLOC( BMSreallocMemoryArray(&profile->loads, profile->arraysize) );
6434 
6435  return SCIP_OKAY;
6436 }
6437 
6438 /** inserts the given time point into the resource profile if it this time point does not exists yet; returns its
6439  * position in the time point array
6440  */
6441 static
6443  SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6444  int timepoint, /**< time point to insert */
6445  int* pos /**< pointer to store the insert position */
6446  )
6447 {
6448  assert(profile != NULL);
6449  assert(timepoint >= 0);
6450  assert(profile->arraysize >= profile->ntimepoints);
6451 
6452  /* get the position of the given time point in the resource profile array if it exists; otherwise the position of the
6453  * next smaller existing time point
6454  */
6455  if( !SCIPprofileFindLeft(profile, timepoint, pos) )
6456  {
6457  assert(*pos >= 0 && *pos < profile->ntimepoints);
6458  assert(timepoint >= profile->timepoints[*pos]);
6459 
6460  /* ensure that the arrays are big enough */
6461  SCIP_CALL( ensureProfileSize(profile, profile->ntimepoints + 1) );
6462  assert(profile->arraysize > profile->ntimepoints);
6463 
6464  /* insert new time point into the (sorted) resource profile */
6465  SCIPsortedvecInsertIntInt(profile->timepoints, profile->loads, timepoint, profile->loads[*pos],
6466  &profile->ntimepoints, pos);
6467  }
6468 
6469 #ifndef NDEBUG
6470  /* check if the time points are sorted */
6471  {
6472  int i;
6473  for( i = 1; i < profile->ntimepoints; ++i )
6474  assert(profile->timepoints[i-1] < profile->timepoints[i]);
6475  }
6476 #endif
6477 
6478  return SCIP_OKAY;
6479 }
6480 
6481 /** updates the resource profile due to inserting of a core */
6482 static
6484  SCIP_PROFILE* profile, /**< resource profile to update */
6485  int left, /**< left side of core interval */
6486  int right, /**< right side of core interval */
6487  int demand, /**< demand of the core */
6488  int* pos, /**< pointer to store the first position were it gets infeasible */
6489  SCIP_Bool* infeasible /**< pointer to store if the update is infeasible */
6490  )
6491 {
6492  int startpos;
6493  int endpos;
6494  int i;
6495 
6496  assert(profile != NULL);
6497  assert(profile->arraysize >= profile->ntimepoints);
6498  assert(left >= 0);
6499  assert(left < right);
6500  assert(infeasible != NULL);
6501 
6502  (*infeasible) = FALSE;
6503  (*pos) = -1;
6504 
6505  /* get position of the starttime in profile */
6506  SCIP_CALL( profileInsertTimepoint(profile, left, &startpos) );
6507  assert(profile->timepoints[startpos] == left);
6508 
6509  /* get position of the endtime in profile */
6510  SCIP_CALL( profileInsertTimepoint(profile, right, &endpos) );
6511  assert(profile->timepoints[endpos] == right);
6512 
6513  assert(startpos < endpos);
6514  assert(profile->arraysize >= profile->ntimepoints);
6515 
6516  /* remove/add the given demand from the core */
6517  for( i = startpos; i < endpos; ++i )
6518  {
6519  profile->loads[i] += demand;
6520 
6521  /* check if the core fits */
6522  if( profile->loads[i] > profile->capacity )
6523  {
6524  SCIPdebugMessage("core insertion detected infeasibility (pos %d)\n", i);
6525 
6526  (*infeasible) = TRUE;
6527  (*pos) = i;
6528 
6529  /* remove the partly inserted core since it does fit completely */
6530  for( ; i >= startpos; --i ) /*lint !e445*/
6531  profile->loads[i] -= demand;
6532 
6533  break;
6534  }
6535  }
6536 
6537  return SCIP_OKAY;
6538 }
6539 
6540 /** insert a core into resource profile; if the core is non-empty the resource profile will be updated otherwise nothing
6541  * happens
6542  */
6544  SCIP_PROFILE* profile, /**< resource profile */
6545  int left, /**< left side of the core */
6546  int right, /**< right side of the core */
6547  int demand, /**< demand of the core */
6548  int* pos, /**< pointer to store the first position were it gets infeasible */
6549  SCIP_Bool* infeasible /**< pointer to store if the core does not fit due to capacity */
6550  )
6551 {
6552  assert(profile != NULL);
6553  assert(left < right);
6554  assert(demand >= 0);
6555  assert(infeasible != NULL);
6556 
6557  (*infeasible) = FALSE;
6558  (*pos) = -1;
6559 
6560  /* insert core into the resource profile */
6561  SCIPdebugMessage("insert core [%d,%d] with demand %d\n", left, right, demand);
6562 
6563  if( demand > 0 )
6564  {
6565  /* try to insert core into the resource profile */
6566  SCIP_CALL( profileUpdate(profile, left, right, demand, pos, infeasible) );
6567  }
6568 
6569  return SCIP_OKAY;
6570 }
6571 
6572 /** subtracts the demand from the resource profile during core time */
6574  SCIP_PROFILE* profile, /**< resource profile to use */
6575  int left, /**< left side of the core */
6576  int right, /**< right side of the core */
6577  int demand /**< demand of the core */
6578  )
6579 {
6580  SCIP_Bool infeasible;
6581  int pos;
6582 
6583  assert(left < right);
6584 #ifndef NDEBUG
6585  {
6586  /* check if the left and right time points of the core correspond to a time point in the resource profile; this
6587  * should be the case since we added the core before to the resource profile
6588  */
6589  assert(SCIPprofileFindLeft(profile, left, &pos));
6590  assert(SCIPprofileFindLeft(profile, right, &pos));
6591  }
6592 #endif
6593 
6594  /* remove the core from the resource profile */
6595  SCIPdebugMessage("delete core [%d,%d] with demand %d\n", left, right, demand);
6596 
6597  SCIP_CALL( profileUpdate(profile, left, right, -demand, &pos, &infeasible) );
6598  assert(!infeasible);
6599 
6600  return SCIP_OKAY;
6601 }
6602 
6603 /** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
6604 static
6606  SCIP_PROFILE* profile, /**< resource profile to use */
6607  int pos, /**< pointer to store the position in the profile to start the serch */
6608  int lst, /**< latest start time */
6609  int duration, /**< duration of the core */
6610  int demand, /**< demand of the core */
6611  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
6612  )
6613 {
6614  int remainingduration;
6615  int startpos;
6616 
6617  assert(profile != NULL);
6618  assert(pos >= 0);
6619  assert(pos < profile->ntimepoints);
6620  assert(duration > 0);
6621  assert(demand > 0);
6622  assert(profile->loads[profile->ntimepoints-1] == 0);
6623 
6624  remainingduration = duration;
6625  startpos = pos;
6626  (*infeasible) = FALSE;
6627 
6628  if( profile->timepoints[startpos] > lst )
6629  {
6630  (*infeasible) = TRUE;
6631  return pos;
6632  }
6633 
6634  while( pos < profile->ntimepoints - 1 )
6635  {
6636  if( profile->loads[pos] + demand > profile->capacity )
6637  {
6638  SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos], pos);
6639  startpos = pos + 1;
6640  remainingduration = duration;
6641 
6642  if( profile->timepoints[startpos] > lst )
6643  {
6644  (*infeasible) = TRUE;
6645  return pos;
6646  }
6647  }
6648  else
6649  remainingduration -= profile->timepoints[pos+1] - profile->timepoints[pos];
6650 
6651  if( remainingduration <= 0 )
6652  break;
6653 
6654  pos++;
6655  }
6656 
6657  return startpos;
6658 }
6659 
6660 /** return the earliest possible starting point within the time interval [lb,ub] for a given core (given by its demand
6661  * and duration)
6662  */
6664  SCIP_PROFILE* profile, /**< resource profile to use */
6665  int est, /**< earliest starting time of the given core */
6666  int lst, /**< latest starting time of the given core */
6667  int duration, /**< duration of the core */
6668  int demand, /**< demand of the core */
6669  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
6670  )
6671 {
6672  SCIP_Bool found;
6673  int pos;
6674 
6675  assert(profile != NULL);
6676  assert(est >= 0);
6677  assert(est <= lst);
6678  assert(duration >= 0);
6679  assert(demand >= 0);
6680  assert(infeasible != NULL);
6681  assert(profile->ntimepoints > 0);
6682  assert(profile->loads[profile->ntimepoints-1] == 0);
6683 
6684  SCIPdebugMessage("profile <%p>: find earliest start time (demad %d, duration %d) [%d,%d]\n", (void*)profile, demand, duration, est, lst);
6685 
6686  if( duration == 0 || demand == 0 )
6687  {
6688  *infeasible = FALSE;
6689  return est;
6690  }
6691 
6692  found = SCIPprofileFindLeft(profile, est, &pos);
6693  SCIPdebugMessage("profile <%p>: earliest start time does %s exist as time point (pos %d)\n", (void*)profile, found ? "" : "not", pos);
6694 
6695  /* if the position is the last time point in the profile, the core can be inserted at its earliest start time */
6696  if( pos == profile->ntimepoints - 1 )
6697  {
6698  (*infeasible) = FALSE;
6699  return est;
6700  }
6701 
6702  if( found )
6703  {
6704  /* if the start time matches a time point in the profile we can just search */
6705  assert(profile->timepoints[pos] == est);
6706  pos = profileFindFeasibleStart(profile, pos, lst, duration, demand, infeasible);
6707 
6708  assert(pos < profile->ntimepoints);
6709  est = profile->timepoints[pos];
6710  }
6711  else if( profile->loads[pos] + demand > profile->capacity )
6712  {
6713  /* if the the time point left to the start time has not enough free capacity we can just search the profile
6714  * starting from the next time point
6715  */
6716  assert(profile->timepoints[pos] <= est);
6717  pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
6718 
6719  assert(pos < profile->ntimepoints);
6720  est = profile->timepoints[pos];
6721  }
6722  else
6723  {
6724  int remainingduration;
6725 
6726  /* check if the core can be placed at its earliest start time */
6727 
6728  assert(pos < profile->ntimepoints - 1);
6729 
6730  remainingduration = duration - (profile->timepoints[pos+1] - est);
6731  SCIPdebugMessage("remaining duration %d\n", remainingduration);
6732 
6733  if( remainingduration <= 0 )
6734  (*infeasible) = FALSE;
6735  else
6736  {
6737  pos = profileFindFeasibleStart(profile, pos+1, profile->timepoints[pos+1], remainingduration, demand, infeasible);
6738  SCIPdebugMessage("remaining duration can%s be processed\n", *infeasible ? "not" : "");
6739 
6740  if( *infeasible )
6741  {
6742  pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
6743 
6744  assert(pos < profile->ntimepoints);
6745  est = profile->timepoints[pos];
6746  }
6747  }
6748  }
6749 
6750  return est;
6751 }
6752 
6753 /** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
6754 static
6756  SCIP_PROFILE* profile, /**< resource profile to use */
6757  int pos, /**< pointer to store the position in the profile to start the search */
6758  int ect, /**< earliest completion time */
6759  int duration, /**< duration of the core */
6760  int demand, /**< demand of the core */
6761  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
6762  )
6763 {
6764  int remainingduration;
6765  int endpos;
6766 
6767  assert(profile != NULL);
6768  assert(pos >= 0);
6769  assert(pos < profile->ntimepoints);
6770  assert(duration > 0);
6771  assert(demand > 0);
6772  assert(profile->ntimepoints > 0);
6773  assert(profile->loads[profile->ntimepoints-1] == 0);
6774 
6775  remainingduration = duration;
6776  endpos = pos;
6777  (*infeasible) = TRUE;
6778 
6779  if( profile->timepoints[endpos] < ect - duration )
6780  return pos;
6781 
6782  while( pos > 0 )
6783  {
6784  if( profile->loads[pos-1] + demand > profile->capacity )
6785  {
6786  SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos-1], pos-1);
6787 
6788  endpos = pos - 1;
6789  remainingduration = duration;
6790 
6791  if( profile->timepoints[endpos] < ect - duration )
6792  return pos;
6793  }
6794  else
6795  remainingduration -= profile->timepoints[pos] - profile->timepoints[pos-1];
6796 
6797  if( remainingduration <= 0 )
6798  {
6799  *infeasible = FALSE;
6800  break;
6801  }
6802 
6803  pos--;
6804  }
6805 
6806  return endpos;
6807 }
6808 
6809 /** return the latest possible starting point within the time interval [lb,ub] for a given core (given by its demand and
6810  * duration)
6811  */
6813  SCIP_PROFILE* profile, /**< resource profile to use */
6814  int est, /**< earliest possible start point */
6815  int lst, /**< latest possible start point */
6816  int duration, /**< duration of the core */
6817  int demand, /**< demand of the core */
6818  SCIP_Bool* infeasible /**< pointer store if the core cannot be inserted */
6819  )
6820 {
6821  SCIP_Bool found;
6822  int ect;
6823  int lct;
6824  int pos;
6825 
6826  assert(profile != NULL);
6827  assert(est >= 0);
6828  assert(est <= lst);
6829  assert(duration >= 0);
6830  assert(demand >= 0);
6831  assert(infeasible != NULL);
6832  assert(profile->ntimepoints > 0);
6833  assert(profile->loads[profile->ntimepoints-1] == 0);
6834 
6835  if( duration == 0 || demand == 0 )
6836  {
6837  *infeasible = FALSE;
6838  return lst;
6839  }
6840 
6841  ect = est + duration;
6842  lct = lst + duration;
6843 
6844  found = SCIPprofileFindLeft(profile, lct, &pos);
6845  SCIPdebugMessage("profile <%p>: latest completion time %d does %s exist as time point (pos %d)\n", (void*)profile, lct, found ? "" : "not", pos);
6846 
6847  if( found )
6848  {
6849  /* if the start time matches a time point in the profile we can just search */
6850  assert(profile->timepoints[pos] == lct);
6851  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
6852 
6853  assert(pos < profile->ntimepoints && pos >= 0);
6854  lct = profile->timepoints[pos];
6855  }
6856  else if( profile->loads[pos] + demand > profile->capacity )
6857  {
6858  /* if the time point left to the start time has not enough free capacity we can just search the profile starting
6859  * from the next time point
6860  */
6861  assert(profile->timepoints[pos] < lct);
6862  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
6863 
6864  assert(pos < profile->ntimepoints && pos >= 0);
6865  lct = profile->timepoints[pos];
6866  }
6867  else
6868  {
6869  int remainingduration;
6870 
6871  /* check if the core can be placed at its latest start time */
6872  assert(profile->timepoints[pos] < lct);
6873 
6874  remainingduration = duration - (lct - profile->timepoints[pos]);
6875 
6876  if( remainingduration <= 0 )
6877  (*infeasible) = FALSE;
6878  else
6879  {
6880  pos = profileFindDownFeasibleStart(profile, pos, profile->timepoints[pos], remainingduration, demand, infeasible);
6881 
6882  if( *infeasible )
6883  {
6884  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
6885 
6886  assert(pos < profile->ntimepoints && pos >= 0);
6887  lct = profile->timepoints[pos];
6888  }
6889  }
6890  }
6891 
6892  return lct - duration;
6893 }
6894 
6895 /*
6896  * Directed graph
6897  */
6898 
6899 /** creates directed graph structure */
6901  SCIP_DIGRAPH** digraph, /**< pointer to store the created directed graph */
6902  BMS_BLKMEM* blkmem, /**< block memory to store the data */
6903  int nnodes /**< number of nodes */
6904  )
6905 {
6906  assert(digraph != NULL);
6907  assert(blkmem != NULL);
6908  assert(nnodes > 0);
6909 
6910  /* allocate memory for the graph and the arrays storing arcs and data */
6911  SCIP_ALLOC( BMSallocBlockMemory(blkmem, digraph) );
6912  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successors, nnodes) );
6913  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->arcdata, nnodes) );
6914  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successorssize, nnodes) );
6915  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nsuccessors, nnodes) );
6916  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nodedata, nnodes) );
6917 
6918  /* store number of nodes */
6919  (*digraph)->nnodes = nnodes;
6920 
6921  /* at the beginning, no components are stored */
6922  (*digraph)->blkmem = blkmem;
6923  (*digraph)->ncomponents = 0;
6924  (*digraph)->componentstartsize = 0;
6925  (*digraph)->components = NULL;
6926  (*digraph)->componentstarts = NULL;
6927 
6928  return SCIP_OKAY;
6929 }
6930 
6931 /** resize directed graph structure */
6933  SCIP_DIGRAPH* digraph, /**< directed graph */
6934  int nnodes /**< new number of nodes */
6935  )
6936 {
6937  int n;
6938  assert(digraph != NULL);
6939  assert(digraph->blkmem != NULL);
6940 
6941  /* check if the digraph has already a proper size */
6942  if( nnodes <= digraph->nnodes )
6943  return SCIP_OKAY;
6944 
6945  /* reallocate memory for increasing the arrays storing arcs and data */
6946  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successors, digraph->nnodes, nnodes) );
6947  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->arcdata, digraph->nnodes, nnodes) );
6948  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successorssize, digraph->nnodes, nnodes) );
6949  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nsuccessors, digraph->nnodes, nnodes) );
6950  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nodedata, digraph->nnodes, nnodes) );
6951 
6952  /* initialize the new node data structures */
6953  for( n = digraph->nnodes; n < nnodes; ++n )
6954  {
6955  digraph->nodedata[n] = NULL;
6956  digraph->arcdata[n] = NULL;
6957  digraph->successors[n] = NULL;
6958  digraph->successorssize[n] = 0;
6959  digraph->nsuccessors[n] = 0;
6960  }
6961 
6962  /* store the new number of nodes */
6963  digraph->nnodes = nnodes;
6964 
6965  return SCIP_OKAY;
6966 }
6967 
6968 /** copies directed graph structure
6969  *
6970  * @note The data in nodedata is copied verbatim. This possibly has to be adapted by the user.
6971  */
6973  SCIP_DIGRAPH** targetdigraph, /**< pointer to store the copied directed graph */
6974  SCIP_DIGRAPH* sourcedigraph, /**< source directed graph */
6975  BMS_BLKMEM* targetblkmem /**< block memory to store the target block memory, or NULL to use the same
6976  * the same block memory as used for the \p sourcedigraph */
6977  )
6978 {
6979  int ncomponents;
6980  int nnodes;
6981  int i;
6982 
6983  assert(sourcedigraph != NULL);
6984  assert(targetdigraph != NULL);
6985 
6986  /* use the source digraph block memory if not specified otherwise */
6987  if( targetblkmem == NULL )
6988  targetblkmem = sourcedigraph->blkmem;
6989 
6990  assert(targetblkmem != NULL);
6991 
6992  SCIP_ALLOC( BMSallocBlockMemory(targetblkmem, targetdigraph) );
6993 
6994  nnodes = sourcedigraph->nnodes;
6995  ncomponents = sourcedigraph->ncomponents;
6996  (*targetdigraph)->nnodes = nnodes;
6997  (*targetdigraph)->ncomponents = ncomponents;
6998  (*targetdigraph)->blkmem = targetblkmem;
6999 
7000  /* copy arcs and data */
7001  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->successors, nnodes) );
7002  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->arcdata, nnodes) );
7003  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->nodedata, nnodes) );
7004 
7005  /* copy lists of successors and arc data */
7006  for( i = 0; i < nnodes; ++i )
7007  {
7008  if( sourcedigraph->nsuccessors[i] > 0 )
7009  {
7010  assert(sourcedigraph->successors[i] != NULL);
7011  assert(sourcedigraph->arcdata[i] != NULL);
7012 
7013  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->successors[i]),
7014  sourcedigraph->successors[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7015  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->arcdata[i]),
7016  sourcedigraph->arcdata[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7017  }
7018  /* copy node data - careful if these are pointers to some information -> need to be copied by hand */
7019  (*targetdigraph)->nodedata[i] = sourcedigraph->nodedata[i];
7020  }
7021 
7022  /* use nsuccessors as size to save memory */
7023  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->successorssize, sourcedigraph->nsuccessors, nnodes) );
7024  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->nsuccessors, sourcedigraph->nsuccessors, nnodes) );
7025 
7026  /* copy component data */
7027  if( ncomponents > 0 )
7028  {
7029  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->components, sourcedigraph->components,
7030  sourcedigraph->componentstarts[ncomponents]) );
7031  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->componentstarts,
7032  sourcedigraph->componentstarts,ncomponents + 1) ); /*lint !e776*/
7033  (*targetdigraph)->componentstartsize = ncomponents + 1;
7034  }
7035  else
7036  {
7037  (*targetdigraph)->components = NULL;
7038  (*targetdigraph)->componentstarts = NULL;
7039  (*targetdigraph)->componentstartsize = 0;
7040  }
7041 
7042  return SCIP_OKAY;
7043 }
7044 
7045 /** sets the sizes of the successor lists for the nodes in a directed graph and allocates memory for the lists */
7047  SCIP_DIGRAPH* digraph, /**< directed graph */
7048  int* sizes /**< sizes of the successor lists */
7049  )
7050 {
7051  int i;
7052  BMS_BLKMEM* blkmem;
7053 
7054  assert(digraph != NULL);
7055  assert(digraph->nnodes > 0);
7056  blkmem = digraph->blkmem;
7057 
7058  for( i = 0; i < digraph->nnodes; ++i )
7059  {
7060  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[i], sizes[i]) ); /*lint !e866*/
7061  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[i], sizes[i]) ); /*lint !e866*/
7062  digraph->successorssize[i] = sizes[i];
7063  digraph->nsuccessors[i] = 0;
7064  }
7065 
7066  return SCIP_OKAY;
7067 }
7068 
7069 /** frees given directed graph structure */
7071  SCIP_DIGRAPH** digraph /**< pointer to the directed graph */
7072  )
7073 {
7074  int i;
7075  BMS_BLKMEM* blkmem;
7076  SCIP_DIGRAPH* digraphptr;
7077 
7078  assert(digraph != NULL);
7079  assert(*digraph != NULL);
7080  assert((*digraph)->blkmem != NULL);
7081 
7082  blkmem = (*digraph)->blkmem;
7083  digraphptr = *digraph;
7084 
7085  /* free arrays storing the successor nodes and arc data */
7086  for( i = digraphptr->nnodes - 1; i >= 0; --i )
7087  {
7088  BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->successors[i], digraphptr->successorssize[i]);
7089  BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->arcdata[i], digraphptr->successorssize[i]);
7090  }
7091 
7092  /* free components structure */
7093  SCIPdigraphFreeComponents(digraphptr);
7094  assert(digraphptr->ncomponents == 0);
7095  assert(digraphptr->componentstartsize == 0);
7096  assert(digraphptr->components == NULL);
7097  assert(digraphptr->componentstarts == NULL);
7098 
7099  /* free directed graph data structure */
7100  BMSfreeBlockMemoryArray(blkmem, &digraphptr->nodedata, digraphptr->nnodes);
7101  BMSfreeBlockMemoryArray(blkmem, &digraphptr->successorssize, digraphptr->nnodes);
7102  BMSfreeBlockMemoryArray(blkmem, &digraphptr->nsuccessors, digraphptr->nnodes);
7103  BMSfreeBlockMemoryArray(blkmem, &digraphptr->successors, digraphptr->nnodes);
7104  BMSfreeBlockMemoryArray(blkmem, &digraphptr->arcdata, digraphptr->nnodes);
7105 
7106  BMSfreeBlockMemory(blkmem, digraph);
7107 }
7108 
7109 #define STARTSUCCESSORSSIZE 5
7110 
7111 /** ensures that successors array of one node in a directed graph is big enough */
7112 static
7114  SCIP_DIGRAPH* digraph, /**< directed graph */
7115  int idx, /**< index for which the size is ensured */
7116  int newsize /**< needed size */
7117  )
7118 {
7119  BMS_BLKMEM* blkmem;
7120 
7121  assert(digraph != NULL);
7122  assert(digraph->blkmem != NULL);
7123  assert(idx >= 0);
7124  assert(idx < digraph->nnodes);
7125  assert(newsize > 0);
7126  assert(digraph->successorssize[idx] == 0 || digraph->successors[idx] != NULL);
7127  assert(digraph->successorssize[idx] == 0 || digraph->arcdata[idx] != NULL);
7128 
7129  blkmem = digraph->blkmem;
7130 
7131  /* check whether array is big enough, and realloc, if needed */
7132  if( newsize > digraph->successorssize[idx] )
7133  {
7134  if( digraph->successors[idx] == NULL )
7135  {
7136  assert(digraph->arcdata[idx] == NULL);
7137  digraph->successorssize[idx] = STARTSUCCESSORSSIZE;
7138  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7139  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7140  }
7141  else
7142  {
7143  newsize = MAX(newsize, 2 * digraph->successorssize[idx]);
7144  assert(digraph->arcdata[idx] != NULL);
7145  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7146  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7147  digraph->successorssize[idx] = newsize;
7148  }
7149  }
7150 
7151  assert(newsize <= digraph->successorssize[idx]);
7152 
7153  return SCIP_OKAY;
7154 }
7155 
7156 /** add (directed) arc and a related data to the directed graph structure
7157  *
7158  * @note if the arc is already contained, it is added a second time
7159  */
7161  SCIP_DIGRAPH* digraph, /**< directed graph */
7162  int startnode, /**< start node of the arc */
7163  int endnode, /**< start node of the arc */
7164  void* data /**< data that should be stored for the arc; or NULL */
7165  )
7166 {
7167  assert(digraph != NULL);
7168  assert(startnode >= 0);
7169  assert(endnode >= 0);
7170  assert(startnode < digraph->nnodes);
7171  assert(endnode < digraph->nnodes);
7172 
7173  SCIP_CALL( ensureSuccessorsSize(digraph, startnode, digraph->nsuccessors[startnode] + 1) );
7174 
7175  /* add arc */
7176  digraph->successors[startnode][digraph->nsuccessors[startnode]] = endnode;
7177  digraph->arcdata[startnode][digraph->nsuccessors[startnode]] = data;
7178  digraph->nsuccessors[startnode]++;
7179 
7180  return SCIP_OKAY;
7181 }
7182 
7183 /** add (directed) arc to the directed graph structure, if it is not contained, yet
7184  *
7185  * @note if there already exists an arc from startnode to endnode, the new arc is not added,
7186  * even if its data is different
7187  */
7189  SCIP_DIGRAPH* digraph, /**< directed graph */
7190  int startnode, /**< start node of the arc */
7191  int endnode, /**< start node of the arc */
7192  void* data /**< data that should be stored for the arc; or NULL */
7193  )
7194 {
7195  int nsuccessors;
7196  int i;
7197 
7198  assert(digraph != NULL);
7199  assert(startnode >= 0);
7200  assert(endnode >= 0);
7201  assert(startnode < digraph->nnodes);
7202  assert(endnode < digraph->nnodes);
7203 
7204  nsuccessors = digraph->nsuccessors[startnode];
7205 
7206  /* search for the arc in existing arcs */
7207  for( i = 0; i < nsuccessors; ++i )
7208  if( digraph->successors[startnode][i] == endnode )
7209  return SCIP_OKAY;
7210 
7211  SCIP_CALL( ensureSuccessorsSize(digraph, startnode, nsuccessors + 1) );
7212 
7213  /* add arc */
7214  digraph->successors[startnode][nsuccessors] = endnode;
7215  digraph->arcdata[startnode][nsuccessors] = data;
7216  ++(digraph->nsuccessors[startnode]);
7217 
7218  return SCIP_OKAY;
7219 }
7220 
7221 /** sets the number of successors to a given value */
7223  SCIP_DIGRAPH* digraph, /**< directed graph */
7224  int node, /**< node for which the number of successors has to be changed */
7225  int nsuccessors /**< new number of successors */
7226  )
7227 {
7228  assert(digraph != NULL);
7229  assert(node >= 0);
7230  assert(node < digraph->nnodes);
7231 
7232  digraph->nsuccessors[node] = nsuccessors;
7233 
7234  return SCIP_OKAY;
7235 }
7236 
7237 /** returns the number of nodes of the given digraph */
7239  SCIP_DIGRAPH* digraph /**< directed graph */
7240  )
7241 {
7242  assert(digraph != NULL);
7243 
7244  return digraph->nnodes;
7245 }
7246 
7247 /** returns the node data, or NULL if no data exist */
7249  SCIP_DIGRAPH* digraph, /**< directed graph */
7250  int node /**< node for which the node data is returned */
7251  )
7252 {
7253  assert(digraph != NULL);
7254  assert(node >= 0);
7255  assert(node < digraph->nnodes);
7256 
7257  return digraph->nodedata[node];
7258 }
7259 
7260 /** sets the node data
7261  *
7262  * @note The old user pointer is not freed. This has to be done by the user
7263  */
7265  SCIP_DIGRAPH* digraph, /**< directed graph */
7266  void* dataptr, /**< user node data pointer, or NULL */
7267  int node /**< node for which the node data is returned */
7268  )
7269 {
7270  assert(digraph != NULL);
7271  assert(node >= 0);
7272  assert(node < digraph->nnodes);
7273 
7274  digraph->nodedata[node] = dataptr;
7275 }
7276 
7277 /** returns the total number of arcs in the given digraph */
7279  SCIP_DIGRAPH* digraph /**< directed graph */
7280  )
7281 {
7282  int i;
7283  int narcs;
7284 
7285  assert(digraph != NULL);
7286 
7287  /* count number of arcs */
7288  narcs = 0;
7289  for( i = 0; i < digraph->nnodes; ++i )
7290  narcs += digraph->nsuccessors[i];
7291 
7292  return narcs;
7293 }
7294 
7295 /** returns the number of successor nodes of the given node */
7297  SCIP_DIGRAPH* digraph, /**< directed graph */
7298  int node /**< node for which the number of outgoing arcs is returned */
7299  )
7300 {
7301  assert(digraph != NULL);
7302  assert(node >= 0);
7303  assert(node < digraph->nnodes);
7304  assert(digraph->nsuccessors[node] >= 0);
7305  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7306 
7307  return digraph->nsuccessors[node];
7308 }
7309 
7310 /** returns the array of indices of the successor nodes; this array must not be changed from outside */
7312  SCIP_DIGRAPH* digraph, /**< directed graph */
7313  int node /**< node for which the array of outgoing arcs is returned */
7314  )
7315 {
7316  assert(digraph != NULL);
7317  assert(node >= 0);
7318  assert(node < digraph->nnodes);
7319  assert(digraph->nsuccessors[node] >= 0);
7320  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7321  assert((digraph->nsuccessors[node] == 0) || (digraph->successors[node] != NULL));
7322 
7323  return digraph->successors[node];
7324 }
7325 
7326 /** returns the array of data corresponding to the arcs originating at the given node, or NULL if no data exist; this
7327  * array must not be changed from outside
7328  */
7330  SCIP_DIGRAPH* digraph, /**< directed graph */
7331  int node /**< node for which the data corresponding to the outgoing arcs is returned */
7332  )
7333 {
7334  assert(digraph != NULL);
7335  assert(node >= 0);
7336  assert(node < digraph->nnodes);
7337  assert(digraph->nsuccessors[node] >= 0);
7338  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7339  assert(digraph->arcdata != NULL);
7340 
7341  return digraph->arcdata[node];
7342 }
7343 
7344 /** performs depth-first-search in the given directed graph from the given start node */
7345 static
7347  SCIP_DIGRAPH* digraph, /**< directed graph */
7348  int startnode, /**< node to start the depth-first-search */
7349  SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7350  int* dfsstack, /**< array of size number of nodes to store the stack;
7351  * only needed for performance reasons */
7352  int* stackadjvisited, /**< array of size number of nodes to store the number of adjacent nodes already visited
7353  * for each node on the stack; only needed for performance reasons */
7354  int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse dfs order */
7355  int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at startnode */
7356  )
7357 {
7358  int stackidx;
7359 
7360  assert(digraph != NULL);
7361  assert(startnode >= 0);
7362  assert(startnode < digraph->nnodes);
7363  assert(visited != NULL);
7364  assert(visited[startnode] == FALSE);
7365  assert(dfsstack != NULL);
7366  assert(dfsnodes != NULL);
7367  assert(ndfsnodes != NULL);
7368 
7369  /* put start node on the stack */
7370  dfsstack[0] = startnode;
7371  stackadjvisited[0] = 0;
7372  stackidx = 0;
7373 
7374  while( stackidx >= 0 )
7375  {
7376  int currnode;
7377  int sadv;
7378 
7379  /* get next node from stack */
7380  currnode = dfsstack[stackidx];
7381 
7382  sadv = stackadjvisited[stackidx];
7383  assert( 0 <= sadv && sadv <= digraph->nsuccessors[currnode] );
7384 
7385  /* mark current node as visited */
7386  assert( visited[currnode] == (sadv > 0) );
7387  visited[currnode] = TRUE;
7388 
7389  /* iterate through the successor list until we reach unhandled node */
7390  while( sadv < digraph->nsuccessors[currnode] && visited[digraph->successors[currnode][sadv]] )
7391  ++sadv;
7392 
7393  /* the current node was completely handled, remove it from stack */
7394  if( sadv == digraph->nsuccessors[currnode] )
7395  {
7396  --stackidx;
7397 
7398  /* store node in the sorted nodes array */
7399  dfsnodes[(*ndfsnodes)++] = currnode;
7400  }
7401  /* handle next unhandled successor node */
7402  else
7403  {
7404  assert( ! visited[digraph->successors[currnode][sadv]] );
7405 
7406  /* store current stackadjvisted index */
7407  stackadjvisited[stackidx] = sadv + 1;
7408 
7409  /* put the successor node onto the stack */
7410  ++stackidx;
7411  dfsstack[stackidx] = digraph->successors[currnode][sadv];
7412  stackadjvisited[stackidx] = 0;
7413  assert( stackidx < digraph->nnodes );
7414  }
7415  }
7416 }
7417 
7418 /** Compute undirected connected components on the given graph.
7419  *
7420  * @note For each arc, its reverse is added, so the graph does not need to be the directed representation of an
7421  * undirected graph.
7422  */
7424  SCIP_DIGRAPH* digraph, /**< directed graph */
7425  int minsize, /**< all components with less nodes are ignored */
7426  int* components, /**< array with as many slots as there are nodes in the directed graph
7427  * to store for each node the component to which it belongs
7428  * (components are numbered 0 to ncomponents - 1); or NULL, if components
7429  * are accessed one-by-one using SCIPdigraphGetComponent() */
7430  int* ncomponents /**< pointer to store the number of components; or NULL, if the
7431  * number of components is accessed by SCIPdigraphGetNComponents() */
7432  )
7433 {
7434  BMS_BLKMEM* blkmem;
7435  SCIP_Bool* visited;
7436  int* ndirectedsuccessors;
7437  int* stackadjvisited;
7438  int* dfsstack;
7439  int ndfsnodes;
7440  int compstart;
7441  int v;
7442  int i;
7443  int j;
7444 
7445  SCIP_RETCODE retcode = SCIP_OKAY;
7446 
7447  assert(digraph != NULL);
7448  assert(digraph->nnodes > 0);
7449  assert(digraph->blkmem != NULL);
7450 
7451  blkmem = digraph->blkmem;
7452 
7453  /* first free the old components */
7454  if( digraph->ncomponents > 0 )
7455  {
7456  SCIPdigraphFreeComponents(digraph);
7457  }
7458 
7459  digraph->ncomponents = 0;
7460  digraph->componentstartsize = 10;
7461 
7462  /* storage to hold components is stored in block memory */
7463  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes) );
7465 
7466  /* allocate temporary arrays */
7467  SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
7468  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
7469  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
7470  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&ndirectedsuccessors, digraph->nnodes), TERMINATE );
7471 
7472  digraph->componentstarts[0] = 0;
7473 
7474  /* store the number of directed arcs per node */
7475  BMScopyMemoryArray(ndirectedsuccessors, digraph->nsuccessors, digraph->nnodes);
7476 
7477  /* add reverse arcs to the graph */
7478  for( i = digraph->nnodes - 1; i >= 0; --i )
7479  {
7480  for( j = 0; j < ndirectedsuccessors[i]; ++j )
7481  {
7482  SCIP_CALL_TERMINATE( retcode, SCIPdigraphAddArc(digraph, digraph->successors[i][j], i, NULL), TERMINATE );
7483  }
7484  }
7485 
7486  for( v = 0; v < digraph->nnodes; ++v )
7487  {
7488  if( visited[v] )
7489  continue;
7490 
7491  compstart = digraph->componentstarts[digraph->ncomponents];
7492  ndfsnodes = 0;
7493  depthFirstSearch(digraph, v, visited, dfsstack, stackadjvisited,
7494  &digraph->components[compstart], &ndfsnodes);
7495 
7496  /* forget about this component if it is too small */
7497  if( ndfsnodes >= minsize )
7498  {
7499  digraph->ncomponents++;
7500 
7501  /* enlarge componentstartsize array, if needed */
7502  if( digraph->ncomponents >= digraph->componentstartsize )
7503  {
7504  int newsize;
7505 
7506  newsize = 2 * digraph->componentstartsize;
7507  assert(digraph->ncomponents < newsize);
7508 
7509  SCIP_ALLOC_TERMINATE( retcode, BMSreallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize, newsize), TERMINATE );
7510  digraph->componentstartsize = newsize;
7511  }
7512  digraph->componentstarts[digraph->ncomponents] = compstart + ndfsnodes;
7513 
7514  /* store component number for contained nodes if array was given */
7515  if( components != NULL )
7516  {
7517  for( i = digraph->componentstarts[digraph->ncomponents] - 1; i >= compstart; --i )
7518  {
7519  components[digraph->components[i]] = digraph->ncomponents - 1;
7520  }
7521  }
7522  }
7523  }
7524 
7525  /* restore the number of directed arcs per node */
7526  BMScopyMemoryArray(digraph->nsuccessors, ndirectedsuccessors, digraph->nnodes);
7527  BMSclearMemoryArray(visited, digraph->nnodes);
7528 
7529  /* return number of components, if the pointer was given */
7530  if( ncomponents != NULL )
7531  (*ncomponents) = digraph->ncomponents;
7532 
7533 TERMINATE:
7534  if( retcode != SCIP_OKAY )
7535  {
7536  SCIPdigraphFreeComponents(digraph);
7537  }
7538  BMSfreeMemoryArrayNull(&ndirectedsuccessors);
7539  BMSfreeMemoryArrayNull(&stackadjvisited);
7540  BMSfreeMemoryArrayNull(&dfsstack);
7541  BMSfreeMemoryArrayNull(&visited);
7542 
7543  return retcode;
7544 }
7545 
7546 /** Performs an (almost) topological sort on the undirected components of the given directed graph. The undirected
7547  * components should be computed before using SCIPdigraphComputeUndirectedComponents().
7548  *
7549  * @note In general a topological sort is not unique. Note, that there might be directed cycles, that are randomly
7550  * broken, which is the reason for having only almost topologically sorted arrays.
7551  */
7553  SCIP_DIGRAPH* digraph /**< directed graph */
7554  )
7555 {
7556  SCIP_Bool* visited = NULL;
7557  int* comps;
7558  int* compstarts;
7559  int* stackadjvisited = NULL;
7560  int* dfsstack = NULL;
7561  int* dfsnodes = NULL;
7562  int ndfsnodes;
7563  int ncomps;
7564  int i;
7565  int j;
7566  int k;
7567  int endidx;
7568  SCIP_RETCODE retcode = SCIP_OKAY;
7569 
7570  assert(digraph != NULL);
7571 
7572  ncomps = digraph->ncomponents;
7573  comps = digraph->components;
7574  compstarts = digraph->componentstarts;
7575 
7576  SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
7577  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsnodes, digraph->nnodes), TERMINATE );
7578  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
7579  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
7580 
7581  /* sort the components (almost) topologically */
7582  for( i = 0; i < ncomps; ++i )
7583  {
7584  endidx = compstarts[i+1] - 1;
7585  ndfsnodes = 0;
7586  for( j = compstarts[i]; j < compstarts[i+1]; ++j )
7587  {
7588  if( visited[comps[j]] )
7589  continue;
7590 
7591  /* perform depth first search, nodes visited in this call are appended to the list dfsnodes in reverse
7592  * dfs order, after the nodes already contained;
7593  * so at every point in time, the nodes in dfsnode are in reverse (almost) topological order
7594  */
7595  depthFirstSearch(digraph, comps[j], visited, dfsstack, stackadjvisited, dfsnodes, &ndfsnodes);
7596  }
7597  assert(endidx - ndfsnodes == compstarts[i] - 1);
7598 
7599  /* copy reverse (almost) topologically sorted array of nodes reached by the dfs searches;
7600  * reverse their order to get an (almost) topologically sort
7601  */
7602  for( k = 0; k < ndfsnodes; ++k )
7603  {
7604  digraph->components[endidx - k] = dfsnodes[k];
7605  }
7606  }
7607 
7608 TERMINATE:
7609  BMSfreeMemoryArrayNull(&stackadjvisited);
7610  BMSfreeMemoryArrayNull(&dfsstack);
7611  BMSfreeMemoryArrayNull(&dfsnodes);
7612  BMSfreeMemoryArrayNull(&visited);
7613 
7614  return retcode;
7615 }
7616 
7617 /** returns the number of previously computed undirected components for the given directed graph */
7619  SCIP_DIGRAPH* digraph /**< directed graph */
7620  )
7621 {
7622  assert(digraph != NULL);
7623  assert(digraph->componentstartsize > 0); /* components should have been computed */
7624 
7625  return digraph->ncomponents;
7626 }
7627 
7628 /** Returns the previously computed undirected component of the given number for the given directed graph.
7629  * If the components were sorted using SCIPdigraphTopoSortComponents(), the component is (almost) topologically sorted.
7630  */
7632  SCIP_DIGRAPH* digraph, /**< directed graph */
7633  int compidx, /**< number of the component to return */
7634  int** nodes, /**< pointer to store the nodes in the component; or NULL, if not needed */
7635  int* nnodes /**< pointer to store the number of nodes in the component;
7636  * or NULL, if not needed */
7637  )
7638 {
7639  assert(digraph != NULL);
7640  assert(compidx >= 0);
7641  assert(compidx < digraph->ncomponents);
7642  assert(nodes != NULL || nnodes != NULL);
7643 
7644  if( nodes != NULL )
7645  (*nodes) = &(digraph->components[digraph->componentstarts[compidx]]);
7646  if( nnodes != NULL )
7647  (*nnodes) = digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx];
7648 }
7649 
7650 /* Performs Tarjan's algorithm for a given directed graph to obtain the strongly connected components
7651  * which are reachable from a given node.
7652  */
7653 static
7654 void tarjan(
7655  SCIP_DIGRAPH* digraph, /**< directed graph */
7656  int v, /**< node to start the algorithm */
7657  int* lowlink, /**< array to store lowlink values */
7658  int* dfsidx, /**< array to store dfs indices */
7659  int* stack, /**< array to store a stack */
7660  int* stacksize, /**< pointer to store the size of the stack */
7661  SCIP_Bool* unprocessed, /**< array to store which node is unprocessed yet */
7662  SCIP_Bool* nodeinstack, /**< array to store which nodes are in the stack */
7663  int* maxdfs, /**< pointer to store index for DFS */
7664  int* strongcomponents, /**< array to store for each node the strongly connected
7665  * component to which it belongs (components are
7666  * numbered 0 to nstrongcomponents - 1); */
7667  int* nstrongcomponents, /**< pointer to store the number of computed components so far */
7668  int* strongcompstartidx, /**< array to store the start index of the computed components */
7669  int* nstorednodes /**< pointer to store the number of already stored nodes */
7670  )
7671 {
7672  int i;
7673 
7674  assert(digraph != NULL);
7675  assert(v >= 0);
7676  assert(v < digraph->nnodes);
7677  assert(lowlink != NULL);
7678  assert(dfsidx != NULL);
7679  assert(stack != NULL);
7680  assert(stacksize != NULL);
7681  assert(*stacksize >= 0);
7682  assert(*stacksize < digraph->nnodes);
7683  assert(unprocessed != NULL);
7684  assert(nodeinstack != NULL);
7685  assert(maxdfs != NULL);
7686  assert(strongcomponents != NULL);
7687  assert(nstrongcomponents != NULL);
7688  assert(strongcompstartidx != NULL);
7689  assert(nstorednodes != NULL);
7690  assert(*nstorednodes >= 0 && *nstorednodes < digraph->nnodes);
7691 
7692  dfsidx[v] = *maxdfs;
7693  lowlink[v] = *maxdfs;
7694  *maxdfs += 1;
7695 
7696  /* add v to the stack */
7697  stack[*stacksize] = v;
7698  *stacksize += 1;
7699  nodeinstack[v] = TRUE;
7700 
7701  /* mark v as processed */
7702  unprocessed[v] = FALSE;
7703 
7704  for( i = 0; i < digraph->nsuccessors[v]; ++i )
7705  {
7706  int w;
7707 
7708  /* edge (v,w) */
7709  w = digraph->successors[v][i];
7710 
7711  if( unprocessed[w] )
7712  {
7713  tarjan(digraph, w, lowlink, dfsidx, stack, stacksize, unprocessed, nodeinstack, maxdfs, strongcomponents,
7714  nstrongcomponents, strongcompstartidx, nstorednodes);
7715 
7716  assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
7717  assert(lowlink[w] >= 0 && lowlink[w] < digraph->nnodes);
7718 
7719  /* update lowlink */
7720  lowlink[v] = MIN(lowlink[v], lowlink[w]);
7721  }
7722  else if( nodeinstack[w] )
7723  {
7724  assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
7725  assert(dfsidx[w] >= 0 && dfsidx[w] < digraph->nnodes);
7726 
7727  /* update lowlink */
7728  lowlink[v] = MIN(lowlink[v], dfsidx[w]);
7729  }
7730  }
7731 
7732  /* found a root of a strong component */
7733  if( lowlink[v] == dfsidx[v] )
7734  {
7735  int w;
7736 
7737  strongcompstartidx[*nstrongcomponents] = *nstorednodes;
7738  *nstrongcomponents += 1;
7739 
7740  do
7741  {
7742  assert(*stacksize > 0);
7743 
7744  /* stack.pop() */
7745  w = stack[*stacksize - 1];
7746  *stacksize -= 1;
7747  nodeinstack[w] = FALSE;
7748 
7749  /* store the node in the corresponding component */
7750  strongcomponents[*nstorednodes] = w;
7751  *nstorednodes += 1;
7752  }
7753  while( v != w );
7754  }
7755 }
7756 
7757 /** Computes all strongly connected components of an undirected connected component with Tarjan's Algorithm.
7758  * The resulting strongly connected components are sorted topologically (starting from the end of the
7759  * strongcomponents array).
7760  *
7761  * @note In general a topological sort of the strongly connected components is not unique.
7762  */
7764  SCIP_DIGRAPH* digraph, /**< directed graph */
7765  int compidx, /**< number of the undirected connected component */
7766  int* strongcomponents, /**< array to store the strongly connected components
7767  * (length >= size of the component) */
7768  int* strongcompstartidx, /**< array to store the start indices of the strongly connected
7769  * components (length >= size of the component) */
7770  int* nstrongcomponents /**< pointer to store the number of strongly connected
7771  * components */
7772  )
7773 {
7774  int* lowlink;
7775  int* dfsidx;
7776  int* stack;
7777  int stacksize;
7778  SCIP_Bool* unprocessed;
7779  SCIP_Bool* nodeinstack;
7780  int maxdfs;
7781  int nstorednodes;
7782  int i;
7783  SCIP_RETCODE retcode;
7784 
7785  assert(digraph != NULL);
7786  assert(compidx >= 0);
7787  assert(compidx < digraph->ncomponents);
7788  assert(strongcomponents != NULL);
7789  assert(strongcompstartidx != NULL);
7790  assert(nstrongcomponents != NULL);
7791 
7792  retcode = SCIP_OKAY;
7793 
7794  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&lowlink, digraph->nnodes), TERMINATE );
7795  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsidx, digraph->nnodes), TERMINATE );
7796  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stack, digraph->nnodes), TERMINATE );
7797  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&unprocessed, digraph->nnodes), TERMINATE );
7798  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&nodeinstack, digraph->nnodes), TERMINATE );
7799 
7800  for( i = 0; i < digraph->nnodes; ++i )
7801  {
7802  lowlink[i] = -1;
7803  dfsidx[i] = -1;
7804  stack[i] = -1;
7805  unprocessed[i] = TRUE;
7806  nodeinstack[i] = FALSE;
7807  }
7808 
7809  nstorednodes = 0;
7810  stacksize = 0;
7811  maxdfs = 0;
7812  *nstrongcomponents = 0;
7813 
7814  /* iterate over all nodes in the undirected connected component */
7815  for( i = digraph->componentstarts[compidx]; i < digraph->componentstarts[compidx + 1]; ++i )
7816  {
7817  int v;
7818 
7819  v = digraph->components[i];
7820  assert(v >= 0 && v < digraph->nnodes);
7821 
7822  /* call Tarjan's algorithm for unprocessed nodes */
7823  if( unprocessed[v] )
7824  {
7825  SCIPdebugMessage("apply Tarjan's algorithm for node %d\n", v);
7826  tarjan(digraph, v, lowlink, dfsidx, stack, &stacksize, unprocessed, nodeinstack, &maxdfs,
7827  strongcomponents, nstrongcomponents, strongcompstartidx, &nstorednodes);
7828  }
7829  }
7830 
7831  /* we should have stored as many nodes as in the undirected connected component */
7832  assert(nstorednodes == digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx]);
7833 
7834  /* to simplify the iteration over all strongly connected components */
7835  assert(*nstrongcomponents < digraph->nnodes + 1);
7836  strongcompstartidx[*nstrongcomponents] = nstorednodes;
7837 
7838  assert(retcode == SCIP_OKAY);
7839 
7840 TERMINATE:
7841  BMSfreeMemoryArrayNull(&lowlink);
7842  BMSfreeMemoryArrayNull(&dfsidx);
7843  BMSfreeMemoryArrayNull(&stack);
7844  BMSfreeMemoryArrayNull(&unprocessed);
7845  BMSfreeMemoryArrayNull(&nodeinstack);
7846 
7847  return retcode;
7848 }
7849 
7850 /** frees the component information for the given directed graph */
7852  SCIP_DIGRAPH* digraph /**< directed graph */
7853  )
7854 {
7855  BMS_BLKMEM* blkmem;
7856 
7857  assert(digraph != NULL);
7858  assert(digraph->blkmem != NULL);
7859 
7860  blkmem = digraph->blkmem;
7861 
7862  /* free components structure */
7863  if( digraph->componentstartsize > 0 )
7864  {
7865  BMSfreeBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize);
7866  BMSfreeBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes);
7867  digraph->components = NULL;
7868  digraph->componentstarts = NULL;
7869  digraph->ncomponents = 0;
7870  digraph->componentstartsize = 0;
7871  }
7872 #ifndef NDEBUG
7873  else
7874  {
7875  assert(digraph->components == NULL);
7876  assert(digraph->componentstarts == NULL);
7877  assert(digraph->ncomponents == 0);
7878  }
7879 #endif
7880 }
7881 
7882 /** output of the given directed graph via the given message handler */
7884  SCIP_DIGRAPH* digraph, /**< directed graph */
7885  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
7886  FILE* file /**< output file (or NULL for standard output) */
7887  )
7888 {
7889  int n;
7890 
7891  for( n = 0; n < digraph->nnodes; ++n )
7892  {
7893  int* successors;
7894  int nsuccessors;
7895  int m;
7896 
7897  nsuccessors = digraph->nsuccessors[n];
7898  successors = digraph->successors[n];
7899 
7900  SCIPmessageFPrintInfo(messagehdlr, file, "node %d --> ", n);
7901 
7902  for( m = 0; m < nsuccessors ; ++m )
7903  {
7904  if( m == 0 )
7905  {
7906  SCIPmessageFPrintInfo(messagehdlr, file, "%d", successors[m]);
7907  }
7908  else
7909  {
7910  SCIPmessageFPrintInfo(messagehdlr, file, ", %d", successors[m]);
7911  }
7912  }
7913  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
7914  }
7915 }
7916 
7917 /** prints the given directed graph structure in GML format into the given file */
7919  SCIP_DIGRAPH* digraph, /**< directed graph */
7920  FILE* file /**< file to write to */
7921  )
7922 {
7923  int n;
7924 
7925  /* write GML format opening */
7926  SCIPgmlWriteOpening(file, TRUE);
7927 
7928  /* write all nodes of the graph */
7929  for( n = 0; n < digraph->nnodes; ++n )
7930  {
7931  char label[SCIP_MAXSTRLEN];
7932 
7933  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", n);
7934  SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", NULL, NULL);
7935  }
7936 
7937  /* write all edges */
7938  for( n = 0; n < digraph->nnodes; ++n )
7939  {
7940  int* successors;
7941  int nsuccessors;
7942  int m;
7943 
7944  nsuccessors = digraph->nsuccessors[n];
7945  successors = digraph->successors[n];
7946 
7947  for( m = 0; m < nsuccessors; ++m )
7948  {
7949  SCIPgmlWriteArc(file, (unsigned int)n, (unsigned int)successors[m], NULL, NULL);
7950  }
7951  }
7952  /* write GML format closing */
7953  SCIPgmlWriteClosing(file);
7954 }
7955 
7956 /** output of the given directed graph via the given message handler */
7958  SCIP_DIGRAPH* digraph, /**< directed graph */
7959  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
7960  FILE* file /**< output file (or NULL for standard output) */
7961  )
7962 {
7963  int c;
7964  int i;
7965 
7966  for( c = 0; c < digraph->ncomponents; ++c )
7967  {
7968  int start = digraph->componentstarts[c];
7969  int end = digraph->componentstarts[c+1];
7970 
7971  SCIPmessageFPrintInfo(messagehdlr, file, "Components %d --> ", c);
7972 
7973  for( i = start; i < end; ++i )
7974  {
7975  if( i == start )
7976  {
7977  SCIPmessageFPrintInfo(messagehdlr, file, "%d", digraph->components[i]);
7978  }
7979  else
7980  {
7981  SCIPmessageFPrintInfo(messagehdlr, file, ", %d", digraph->components[i]);
7982  }
7983  }
7984  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
7985  }
7986 }
7987 
7988 /*
7989  * Binary tree
7990  */
7991 
7992 /** creates a node for a binary tree */
7993 static
7995  SCIP_BT* tree, /**< binary tree */
7996  SCIP_BTNODE** node /**< pointer to store the created node */
7997  )
7998 {
7999  SCIP_ALLOC( BMSallocBlockMemory(tree->blkmem, node) );
8000 
8001  (*node)->parent = NULL;
8002  (*node)->left = NULL;
8003  (*node)->right = NULL;
8004  (*node)->dataptr = NULL;
8005 
8006  return SCIP_OKAY;
8007 }
8008 
8009 /** creates a tree node with (optinal) user data */
8011  SCIP_BT* tree, /**< binary tree */
8012  SCIP_BTNODE** node, /**< pointer to store the created node */
8013  void* dataptr /**< user node data pointer, or NULL */
8014  )
8015 {
8016  assert(tree != NULL);
8017  assert(node != NULL);
8018 
8019  SCIP_CALL( btnodeCreateEmpty(tree, node) );
8020 
8021  assert((*node)->parent == NULL);
8022  assert((*node)->left == NULL);
8023  assert((*node)->right == NULL);
8024 
8025  /* initialize user data */
8026  (*node)->dataptr = dataptr;
8027 
8028  return SCIP_OKAY;
8029 }
8030 
8031 /** frees a tree leaf */
8032 static
8034  SCIP_BT* tree, /**< binary tree */
8035  SCIP_BTNODE** node /**< pointer to node which has to be freed */
8036  )
8037 {
8038  assert(tree != NULL);
8039  assert(node != NULL);
8040  assert(*node != NULL);
8041 
8042  assert((*node)->left == NULL);
8043  assert((*node)->right == NULL);
8044 
8045 #if 0
8046  /* remove reference from parent node */
8047  if( (*node)->parent != NULL )
8048  {
8049  assert(*node != NULL);
8050 
8051  assert((*node)->parent->left == *node || ((*node)->parent->right == *node));
8052 
8053  if( (*node)->parent->left == *node )
8054  {
8055  (*node)->parent->left = NULL;
8056  }
8057  else
8058  {
8059  assert((*node)->parent->right == *node);
8060  (*node)->parent->right = NULL;
8061  }
8062  }
8063 #endif
8064 
8065  assert(*node != NULL);
8066  BMSfreeBlockMemory(tree->blkmem, node);
8067  assert(*node == NULL);
8068 }
8069 
8070 /** frees the node including the rooted subtree
8071  *
8072  * @note The user pointer (object) is not freed. If needed, it has to be done by the user.
8073  */
8075  SCIP_BT* tree, /**< binary tree */
8076  SCIP_BTNODE** node /**< node to be freed */
8077  )
8078 {
8079  assert(tree != NULL);
8080  assert(node != NULL);
8081  assert(*node != NULL);
8082 
8083  if( (*node)->left != NULL )
8084  {
8085  SCIPbtnodeFree(tree, &(*node)->left);
8086  assert((*node)->left == NULL);
8087  }
8088 
8089  if( (*node)->right != NULL )
8090  {
8091  SCIPbtnodeFree(tree, &(*node)->right);
8092  assert((*node)->right == NULL);
8093  }
8094 
8095  btnodeFreeLeaf(tree, node);
8096  assert(*node == NULL);
8097 }
8098 
8099 /* some simple variable functions implemented as defines */
8100 
8101 /* In debug mode, the following methods are implemented as function calls to ensure
8102  * type validity.
8103  * In optimized mode, the methods are implemented as defines to improve performance.
8104  * However, we want to have them in the library anyways, so we have to undef the defines.
8105  */
8106 
8107 #undef SCIPbtnodeGetData
8108 #undef SCIPbtnodeGetKey
8109 #undef SCIPbtnodeGetParent
8110 #undef SCIPbtnodeGetLeftchild
8111 #undef SCIPbtnodeGetRightchild
8112 #undef SCIPbtnodeGetSibling
8113 #undef SCIPbtnodeIsRoot
8114 #undef SCIPbtnodeIsLeaf
8115 #undef SCIPbtnodeIsLeftchild
8116 #undef SCIPbtnodeIsRightchild
8117 
8118 /** returns the user data pointer stored in that node */
8120  SCIP_BTNODE* node /**< node */
8121  )
8122 {
8123  assert(node != NULL);
8124 
8125  return node->dataptr;
8126 }
8127 
8128 /** returns the parent which can be NULL if the given node is the root */
8130  SCIP_BTNODE* node /**< node */
8131  )
8132 {
8133  assert(node != NULL);
8134 
8135  return node->parent;
8136 }
8137 
8138 /** returns left child which can be NULL if the given node is a leaf */
8140  SCIP_BTNODE* node /**< node */
8141  )
8142 {
8143  assert(node != NULL);
8144 
8145  return node->left;
8146 }
8147 
8148 /** returns right child which can be NULL if the given node is a leaf */
8150  SCIP_BTNODE* node /**< node */
8151  )
8152 {
8153  assert(node != NULL);
8154 
8155  return node->right;
8156 }
8157 
8158 /** returns the sibling of the node or NULL if does not exist */
8160  SCIP_BTNODE* node /**< node */
8161  )
8162 {
8163  SCIP_BTNODE* parent;
8164 
8165  parent = SCIPbtnodeGetParent(node);
8166 
8167  if( parent == NULL )
8168  return NULL;
8169 
8170  if( SCIPbtnodeGetLeftchild(parent) == node )
8171  return SCIPbtnodeGetRightchild(parent);
8172 
8173  assert(SCIPbtnodeGetRightchild(parent) == node);
8174 
8175  return SCIPbtnodeGetLeftchild(parent);
8176 }
8177 
8178 /** returns whether the node is a root node */
8180  SCIP_BTNODE* node /**< node */
8181  )
8182 {
8183  assert(node != NULL);
8184 
8185  return (node->parent == NULL);
8186 }
8187 
8188 /** returns whether the node is a leaf */
8190  SCIP_BTNODE* node /**< node */
8191  )
8192 {
8193  assert(node != NULL);
8194 
8195  return (node->left == NULL && node->right == NULL);
8196 }
8197 
8198 /** returns TRUE if the given node is left child */
8200  SCIP_BTNODE* node /**< node */
8201  )
8202 {
8203  SCIP_BTNODE* parent;
8204 
8205  if( SCIPbtnodeIsRoot(node) )
8206  return FALSE;
8207 
8208  parent = SCIPbtnodeGetParent(node);
8209 
8210  if( SCIPbtnodeGetLeftchild(parent) == node )
8211  return TRUE;
8212 
8213  return FALSE;
8214 }
8215 
8216 /** returns TRUE if the given node is right child */
8218  SCIP_BTNODE* node /**< node */
8219  )
8220 {
8221  SCIP_BTNODE* parent;
8222 
8223  if( SCIPbtnodeIsRoot(node) )
8224  return FALSE;
8225 
8226  parent = SCIPbtnodeGetParent(node);
8227 
8228  if( SCIPbtnodeGetRightchild(parent) == node )
8229  return TRUE;
8230 
8231  return FALSE;
8232 }
8233 
8234 /** sets the give node data
8235  *
8236  * @note The old user pointer is not freed.
8237  */
8239  SCIP_BTNODE* node, /**< node */
8240  void* dataptr /**< node user data pointer */
8241  )
8242 {
8243  assert(node != NULL);
8244 
8245  node->dataptr = dataptr;
8246 }
8247 
8248 /** sets parent node
8249  *
8250  * @note The old parent including the rooted subtree is not delete.
8251  */
8253  SCIP_BTNODE* node, /**< node */
8254  SCIP_BTNODE* parent /**< new parent node, or NULL */
8255  )
8256 {
8257  assert(node != NULL);
8258 
8259  node->parent = parent;
8260 }
8261 
8262 /** sets left child
8263  *
8264  * @note The old left child including the rooted subtree is not delete.
8265  */
8267  SCIP_BTNODE* node, /**< node */
8268  SCIP_BTNODE* left /**< new left child, or NULL */
8269  )
8270 {
8271  assert(node != NULL);
8272 
8273  node->left = left;
8274 }
8275 
8276 /** sets right child
8277  *
8278  * @note The old right child including the rooted subtree is not delete.
8279  */
8281  SCIP_BTNODE* node, /**< node */
8282  SCIP_BTNODE* right /**< new right child, or NULL */
8283  )
8284 {
8285  assert(node != NULL);
8286 
8287  node->right = right;
8288 }
8289 
8290 /** creates an binary tree */
8292  SCIP_BT** tree, /**< pointer to store the created binary tree */
8293  BMS_BLKMEM* blkmem /**< block memory used to createnode */
8294  )
8295 {
8296  assert(tree != NULL);
8297  assert(blkmem != NULL);
8298 
8299  SCIP_ALLOC( BMSallocBlockMemory(blkmem, tree) );
8300  (*tree)->blkmem = blkmem;
8301  (*tree)->root = NULL;
8302 
8303  return SCIP_OKAY;
8304 }
8305 
8306 /** frees binary tree
8307  *
8308  * @note The user pointers (object) of the nodes are not freed. If needed, it has to be done by the user.
8309  */
8311  SCIP_BT** tree /**< pointer to binary tree */
8312  )
8313 {
8314  assert(tree != NULL);
8315 
8316  if( (*tree)->root != NULL )
8317  {
8318  SCIPbtnodeFree(*tree, &((*tree)->root));
8319  }
8320 
8321  BMSfreeBlockMemory((*tree)->blkmem, tree);
8322 }
8323 
8324 /** prints the rooted subtree of the given binary tree node in GML format into the given file */
8325 static
8327  SCIP_BTNODE* node, /**< binary tree node */
8328  FILE* file, /**< file to write to */
8329  int* nnodes /**< pointer to count the number of nodes */
8330  )
8331 {
8332  SCIP_BTNODE* left;
8333  SCIP_BTNODE* right;
8334  char label[SCIP_MAXSTRLEN];
8335 
8336  assert(node != NULL);
8337 
8338  (*nnodes)++;
8339  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", *nnodes);
8340 
8341  SCIPgmlWriteNode(file, (unsigned int)(size_t)node, label, "circle", NULL, NULL);
8342 
8343  left = SCIPbtnodeGetLeftchild(node);
8344  right = SCIPbtnodeGetRightchild(node);
8345 
8346  if( left != NULL )
8347  {
8348  btPrintSubtree(left, file, nnodes);
8349 
8350  SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)left, NULL, NULL);
8351  }
8352 
8353  if( right != NULL )
8354  {
8355  btPrintSubtree(right, file, nnodes);
8356 
8357  SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)right, NULL, NULL);
8358  }
8359 }
8360 
8361 /** prints the binary tree in GML format into the given file */
8363  SCIP_BT* tree, /**< binary tree */
8364  FILE* file /**< file to write to */
8365  )
8366 {
8367  /* write GML opening */
8368  SCIPgmlWriteOpening(file, TRUE);
8369 
8370  if( !SCIPbtIsEmpty(tree) )
8371  {
8372  SCIP_BTNODE* root;
8373  int nnodes;
8374 
8375  root = SCIPbtGetRoot(tree);
8376  assert(root != NULL);
8377 
8378  nnodes = 0;
8379 
8380  btPrintSubtree(root, file, &nnodes);
8381  }
8382 
8383  /* write GML closing */
8384  SCIPgmlWriteClosing(file);
8385 }
8386 
8387 /* some simple variable functions implemented as defines */
8388 #undef SCIPbtIsEmpty
8389 #undef SCIPbtGetRoot
8390 
8391 /** returns whether the binary tree is empty (has no nodes) */
8393  SCIP_BT* tree /**< binary tree */
8394  )
8395 {
8396  assert(tree != NULL);
8397 
8398  return (tree->root == NULL);
8399 }
8400 
8401 /** returns the the root node of the binary or NULL if the binary tree is empty */
8403  SCIP_BT* tree /**< tree to be evaluated */
8404  )
8405 {
8406  assert(tree != NULL);
8407 
8408  return tree->root;
8409 }
8410 
8411 /** sets root node
8412  *
8413  * @note The old root including the rooted subtree is not delete.
8414  */
8416  SCIP_BT* tree, /**< tree to be evaluated */
8417  SCIP_BTNODE* root /**< new root, or NULL */
8418  )
8419 {
8420  assert(tree != NULL);
8421 
8422  tree->root = root;
8423 }
8424 
8425 
8426 /*
8427  * Numerical methods
8428  */
8429 
8430 /** returns the machine epsilon: the smallest number eps > 0, for which 1.0 + eps > 1.0 */
8432  void
8433  )
8434 {
8435  SCIP_Real eps;
8436  SCIP_Real lasteps;
8437  SCIP_Real one;
8438  SCIP_Real onepluseps;
8439 
8440  one = 1.0;
8441  eps = 1.0;
8442  do
8443  {
8444  lasteps = eps;
8445  eps /= 2.0;
8446  onepluseps = one + eps;
8447  }
8448  while( onepluseps > one );
8449 
8450  return lasteps;
8451 }
8452 
8453 /** calculates the greatest common divisor of the two given values */
8455  SCIP_Longint val1, /**< first value of greatest common devisor calculation */
8456  SCIP_Longint val2 /**< second value of greatest common devisor calculation */
8457  )
8458 {
8459  int t;
8460 
8461  assert(val1 > 0);
8462  assert(val2 > 0);
8463 
8464  t = 0;
8465  /* if val1 is even, divide it by 2 */
8466  while( !(val1 & 1) )
8467  {
8468  val1 >>= 1; /*lint !e704*/
8469 
8470  /* if val2 is even too, divide it by 2 and increase t(=number of e) */
8471  if( !(val2 & 1) )
8472  {
8473  val2 >>= 1; /*lint !e704*/
8474  ++t;
8475  }
8476  /* only val1 can be odd */
8477  else
8478  {
8479  /* while val1 is even, divide it by 2 */
8480  while( !(val1 & 1) )
8481  val1 >>= 1; /*lint !e704*/
8482 
8483  break;
8484  }
8485  }
8486 
8487  /* while val2 is even, divide it by 2 */
8488  while( !(val2 & 1) )
8489  val2 >>= 1; /*lint !e704*/
8490 
8491  /* the following if/else condition is only to make sure that we do not overflow when adding up both values before
8492  * dividing them by 4 in the following while loop
8493  */
8494  if( t == 0 )
8495  {
8496  if( val1 > val2 )
8497  {
8498  val1 -= val2;
8499 
8500  /* divide val1 by 2 as long as possible */
8501  while( !(val1 & 1) )
8502  val1 >>= 1; /*lint !e704*/
8503  }
8504  else if( val1 < val2 )
8505  {
8506  val2 -= val1;
8507 
8508  /* divide val2 by 2 as long as possible */
8509  while( !(val2 & 1) )
8510  val2 >>= 1; /*lint !e704*/
8511  }
8512  }
8513 
8514  /* val1 and val2 are odd */
8515  while( val1 != val2 )
8516  {
8517  if( val1 > val2 )
8518  {
8519  /* we can stop if one value reached one */
8520  if( val2 == 1 )
8521  return (val2 << t); /*lint !e647 !e703*/
8522 
8523  /* if ((val1 xor val2) and 2) = 2, then gcd(val1, val2) = gcd((val1 + val2)/4, val2),
8524  * and otherwise gcd(val1, val2) = gcd((val1 − val2)/4, val2)
8525  */
8526  if( ((val1 ^ val2) & 2) == 2 )
8527  val1 += val2;
8528  else
8529  val1 -= val2;
8530 
8531  assert((val1 & 3) == 0);
8532  val1 >>= 2; /*lint !e704*/
8533 
8534  /* if val1 is still even, divide it by 2 */
8535  while( !(val1 & 1) )
8536  val1 >>= 1; /*lint !e704*/
8537  }
8538  else
8539  {
8540  /* we can stop if one value reached one */
8541  if( val1 == 1 )
8542  return (val1 << t); /*lint !e647 !e703*/
8543 
8544  /* if ((val2 xor val1) and 2) = 2, then gcd(val2, val1) = gcd((val2 + val1)/4, val1),
8545  * and otherwise gcd(val2, val1) = gcd((val2 − val1)/4, val1)
8546  */
8547  if( ((val2 ^ val1) & 2) == 2 )
8548  val2 += val1;
8549  else
8550  val2 -= val1;
8551 
8552  assert((val2 & 3) == 0);
8553  val2 >>= 2; /*lint !e704*/
8554 
8555  /* if val2 is still even, divide it by 2 */
8556  while( !(val2 & 1) )
8557  val2 >>= 1; /*lint !e704*/
8558  }
8559  }
8560 
8561  return (val1 << t); /*lint !e703*/
8562 }
8563 
8564 
8565 /* for the MS compiler, the function nextafter is named _nextafter */
8566 #if defined(_MSC_VER) && !defined(NO_NEXTAFTER)
8567 #define nextafter(x,y) _nextafter(x,y)
8568 #endif
8569 
8570 /* on systems where the function nextafter is not defined, we provide an implementation from Sun */
8571 #ifdef NO_NEXTAFTER
8572 /* The following implementation of the routine nextafter() comes with the following license:
8573  *
8574  * ====================================================
8575  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8576  *
8577  * Developed at SunSoft, a Sun Microsystems, Inc. business.
8578  * Permission to use, copy, modify, and distribute this
8579  * software is freely granted, provided that this notice
8580  * is preserved.
8581  * ====================================================
8582  */
8583 
8584 #define __HI(x) *(1+(int*)&x)
8585 #define __LO(x) *(int*)&x
8586 #define __HIp(x) *(1+(int*)x)
8587 #define __LOp(x) *(int*)x
8588 
8589 static
8590 double nextafter(double x, double y)
8591 {
8592  int hx;
8593  int hy;
8594  int ix;
8595  int iy;
8596  unsigned lx;
8597  unsigned ly;
8598 
8599  /* cppcheck-suppress invalidPointerCast */
8600  hx = __HI(x); /* high word of x */
8601  /* cppcheck-suppress invalidPointerCast */
8602  lx = __LO(x); /* low word of x */
8603  /* cppcheck-suppress invalidPointerCast */
8604  hy = __HI(y); /* high word of y */
8605  /* cppcheck-suppress invalidPointerCast */
8606  ly = __LO(y); /* low word of y */
8607  ix = hx&0x7fffffff; /* |x| */
8608  iy = hy&0x7fffffff; /* |y| */
8609 
8610  if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) || /* x is nan */
8611  ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 )) /* y is nan */
8612  return x + y;
8613 
8614  /* x == y, return x */
8615  if( x == y )
8616  return x;
8617 
8618  /* x == 0 */
8619  if( (ix|lx) == 0 )
8620  {
8621  /* return +-minsubnormal */
8622  /* cppcheck-suppress invalidPointerCast */
8623  __HI(x) = hy&0x80000000;
8624  /* cppcheck-suppress invalidPointerCast */
8625  __LO(x) = 1;
8626  y = x * x;
8627  if ( y == x )
8628  return y;
8629  else
8630  return x; /* raise underflow flag */
8631  }
8632  /* x > 0 */
8633  if( hx >= 0 )
8634  {
8635  /* x > y, x -= ulp */
8636  if( hx > hy || ((hx == hy) && (lx > ly)) )
8637  {
8638  if ( lx == 0 )
8639  hx -= 1;
8640  lx -= 1;
8641  }
8642  else
8643  {
8644  /* x < y, x += ulp */
8645  lx += 1;
8646  if ( lx == 0 )
8647  hx += 1;
8648  }
8649  }
8650  else
8651  {
8652  /* x < 0 */
8653  if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
8654  {
8655  /* x < y, x -= ulp */
8656  if ( lx == 0 )
8657  hx -= 1;
8658  lx -= 1;
8659  }
8660  else
8661  {
8662  /* x > y, x += ulp */
8663  lx += 1;
8664  if( lx == 0 )
8665  hx += 1;
8666  }
8667  }
8668  hy = hx&0x7ff00000;
8669  /* overflow */
8670  if( hy >= 0x7ff00000 )
8671  return x + x;
8672  if( hy < 0x00100000 )
8673  {
8674  /* underflow */
8675  y = x*x;
8676  if( y != x )
8677  {
8678  /* raise underflow flag */
8679  /* cppcheck-suppress invalidPointerCast */
8680  __HI(y) = hx;
8681  /* cppcheck-suppress invalidPointerCast */
8682  __LO(y) = lx;
8683  return y;
8684  }
8685  }
8686 
8687  /* cppcheck-suppress invalidPointerCast */
8688  __HI(x) = hx;
8689  /* cppcheck-suppress invalidPointerCast */
8690  __LO(x) = lx;
8691  return x;
8692 }
8693 #endif
8694 
8695 
8696 /** returns the next representable value of from in the direction of to */
8698  SCIP_Real from, /**< value from which the next representable value should be returned */
8699  SCIP_Real to /**< direction in which the next representable value should be returned */
8700  )
8701 {
8702  return nextafter(from, to);
8703 }
8704 
8705 /** calculates the smallest common multiple of the two given values */
8707  SCIP_Longint val1, /**< first value of smallest common multiple calculation */
8708  SCIP_Longint val2 /**< second value of smallest common multiple calculation */
8709  )
8710 {
8711  SCIP_Longint gcd;
8712 
8713  assert(val1 > 0);
8714  assert(val2 > 0);
8715 
8716  gcd = SCIPcalcGreComDiv(val1, val2);
8717 
8718  return val1/gcd * val2;
8719 }
8720 
8721 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,
8722  17.0, 18.0, 19.0, 25.0, -1.0};
8723 
8724 /** converts a real number into a (approximate) rational representation, and returns TRUE iff the conversion was
8725  * successful
8726  */
8728  SCIP_Real val, /**< real value r to convert into rational number */
8729  SCIP_Real mindelta, /**< minimal allowed difference r - q of real r and rational q = n/d */
8730  SCIP_Real maxdelta, /**< maximal allowed difference r - q of real r and rational q = n/d */
8731  SCIP_Longint maxdnom, /**< maximal denominator allowed */
8732  SCIP_Longint* nominator, /**< pointer to store the nominator n of the rational number */
8733  SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
8734  )
8735 {
8736  SCIP_Real a;
8737  SCIP_Real b;
8738  SCIP_Real g0;
8739  SCIP_Real g1;
8740  SCIP_Real gx;
8741  SCIP_Real h0;
8742  SCIP_Real h1;
8743  SCIP_Real hx;
8744  SCIP_Real delta0;
8745  SCIP_Real delta1;
8746  SCIP_Real epsilon;
8747  int i;
8748 
8749  assert(mindelta < 0.0);
8750  assert(maxdelta > 0.0);
8751  assert(nominator != NULL);
8752  assert(denominator != NULL);
8753 
8754  /* try the simple denominators first: each value of the simpledenoms table multiplied by powers of 10
8755  * is tried as denominator
8756  */
8757  for( i = 0; simplednoms[i] > 0.0; ++i )
8758  {
8759  SCIP_Real nom;
8760  SCIP_Real dnom;
8761  SCIP_Real ratval0;
8762  SCIP_Real ratval1;
8763 
8764  /* try powers of 10 (including 10^0) */
8765  dnom = simplednoms[i];
8766  while( dnom <= maxdnom )
8767  {
8768  nom = floor(val * dnom);
8769  ratval0 = nom/dnom;
8770  ratval1 = (nom+1.0)/dnom;
8771  if( mindelta <= val - ratval0 && val - ratval1 <= maxdelta )
8772  {
8773  if( val - ratval0 <= maxdelta )
8774  {
8775  *nominator = (SCIP_Longint)nom;
8776  *denominator = (SCIP_Longint)dnom;
8777  return TRUE;
8778  }
8779  if( mindelta <= val - ratval1 )
8780  {
8781  *nominator = (SCIP_Longint)(nom+1.0);
8782  *denominator = (SCIP_Longint)dnom;
8783  return TRUE;
8784  }
8785  }
8786  dnom *= 10.0;
8787  }
8788  }
8789 
8790  /* the simple denominators didn't work: calculate rational representation with arbitrary denominator */
8791  epsilon = MIN(-mindelta, maxdelta)/2.0;
8792 
8793  b = val;
8794  a = EPSFLOOR(b, epsilon);
8795  g0 = a;
8796  h0 = 1.0;
8797  g1 = 1.0;
8798  h1 = 0.0;
8799  delta0 = val - g0/h0;
8800  delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
8801 
8802  while( (delta0 < mindelta || delta0 > maxdelta) && (delta1 < mindelta || delta1 > maxdelta) )
8803  {
8804  assert(EPSGT(b, a, epsilon));
8805  assert(h0 >= 0.0);
8806  assert(h1 >= 0.0);
8807 
8808  b = 1.0 / (b - a);
8809  a = EPSFLOOR(b, epsilon);
8810 
8811  assert(a >= 0.0);
8812  gx = g0;
8813  hx = h0;
8814 
8815  g0 = a * g0 + g1;
8816  h0 = a * h0 + h1;
8817 
8818  g1 = gx;
8819  h1 = hx;
8820 
8821  if( h0 > maxdnom )
8822  return FALSE;
8823 
8824  delta0 = val - g0/h0;
8825  delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
8826  }
8827 
8828  if( REALABS(g0) > (SCIP_LONGINT_MAX >> 4) || h0 > (SCIP_LONGINT_MAX >> 4) )
8829  return FALSE;
8830 
8831  assert(h0 > 0.5);
8832 
8833  if( delta0 < mindelta )
8834  {
8835  assert(mindelta <= delta1 && delta1 <= maxdelta);
8836  *nominator = (SCIP_Longint)(g0 - 1.0);
8837  *denominator = (SCIP_Longint)h0;
8838  }
8839  else if( delta0 > maxdelta )
8840  {
8841  assert(mindelta <= delta1 && delta1 <= maxdelta);
8842  *nominator = (SCIP_Longint)(g0 + 1.0);
8843  *denominator = (SCIP_Longint)h0;
8844  }
8845  else
8846  {
8847  *nominator = (SCIP_Longint)g0;
8848  *denominator = (SCIP_Longint)h0;
8849  }
8850  assert(*denominator >= 1);
8851  assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) >= mindelta);
8852  assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) <= maxdelta);
8853 
8854  return TRUE;
8855 }
8856 
8857 /** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
8858 static
8860  SCIP_Real val, /**< value that should be scaled to an integral value */
8861  SCIP_Real scalar, /**< scalar that should be tried */
8862  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
8863  SCIP_Real maxdelta /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
8864  )
8865 {
8866  SCIP_Real sval;
8867  SCIP_Real downval;
8868  SCIP_Real upval;
8869 
8870  assert(mindelta <= 0.0);
8871  assert(maxdelta >= 0.0);
8872 
8873  sval = val * scalar;
8874  downval = floor(sval);
8875  upval = ceil(sval);
8876 
8877  return (SCIPrelDiff(sval, downval) <= maxdelta || SCIPrelDiff(sval, upval) >= mindelta);
8878 }
8879 
8880 /** additional scalars that are tried in integrality scaling */
8881 static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
8882 static const int nscalars = 9;
8883 
8884 /** tries to find a value, such that all given values, if scaled with this value become integral in relative allowed
8885  * difference in between mindelta and maxdelta
8886  */
8888  SCIP_Real* vals, /**< values to scale */
8889  int nvals, /**< number of values to scale */
8890  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
8891  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
8892  SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
8893  SCIP_Real maxscale, /**< maximal allowed scalar */
8894  SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
8895  SCIP_Bool* success /**< stores whether returned value is valid */
8896  )
8897 {
8898  SCIP_Real bestscalar;
8899  SCIP_Longint gcd;
8900  SCIP_Longint scm;
8901  SCIP_Longint nominator;
8902  SCIP_Longint denominator;
8903  SCIP_Real val;
8904  SCIP_Real minval;
8905  SCIP_Real absval;
8906  SCIP_Real scaleval;
8907  SCIP_Bool scalable;
8908  SCIP_Bool rational;
8909  int c;
8910  int s;
8911  int i;
8912 
8913  assert(vals != NULL);
8914  assert(nvals >= 0);
8915  assert(maxdnom >= 1);
8916  assert(mindelta < 0.0);
8917  assert(maxdelta > 0.0);
8918  assert(success != NULL);
8919 
8920  SCIPdebugMessage("trying to find rational representation for given values\n");
8921 
8922  if( intscalar != NULL )
8923  *intscalar = SCIP_INVALID;
8924  *success = FALSE;
8925 
8926  /* get minimal absolute non-zero value */
8927  minval = SCIP_REAL_MAX;
8928  for( c = 0; c < nvals; ++c )
8929  {
8930  val = vals[c];
8931  if( val < mindelta || val > maxdelta )
8932  {
8933  absval = REALABS(val);
8934  minval = MIN(minval, absval);
8935  }
8936  }
8937 
8938  if( minval == SCIP_REAL_MAX ) /*lint !e777*/
8939  {
8940  /* all coefficients are zero (inside tolerances) */
8941  if( intscalar != NULL )
8942  *intscalar = 1.0;
8943  *success = TRUE;
8944  SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
8945 
8946  return SCIP_OKAY;
8947  }
8948  assert(minval > MIN(-mindelta, maxdelta));
8949 
8950  bestscalar = SCIP_INVALID;
8951 
8952  for( i = 0; i < 2; ++i )
8953  {
8954  scalable = TRUE;
8955 
8956  /* try, if values can be made integral multiplying them with the reciprocal of the smallest value and a power of 2 */
8957  if( i == 0 )
8958  scaleval = 1.0/minval;
8959  /* try, if values can be made integral by multiplying them by a power of 2 */
8960  else
8961  scaleval = 1.0;
8962 
8963  for( c = 0; c < nvals && scalable; ++c )
8964  {
8965  /* check, if the value can be scaled with a simple scalar */
8966  val = vals[c];
8967  if( val == 0.0 ) /* zeros are allowed in the vals array */
8968  continue;
8969 
8970  absval = REALABS(val);
8971  while( scaleval <= maxscale
8972  && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta)) )
8973  {
8974  for( s = 0; s < nscalars; ++s )
8975  {
8976  if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta) )
8977  {
8978  scaleval *= scalars[s];
8979  break;
8980  }
8981  }
8982  if( s >= nscalars )
8983  scaleval *= 2.0;
8984  }
8985  scalable = (scaleval <= maxscale);
8986  SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
8987  val, scaleval, val*scaleval, scalable);
8988  }
8989  if( scalable )
8990  {
8991  /* make values integral by dividing them by the smallest value (and multiplying them with a power of 2) */
8992  assert(scaleval <= maxscale);
8993 
8994  /* check if we found a better scaling value */
8995  if( scaleval < bestscalar )
8996  bestscalar = scaleval;
8997 
8998  SCIPdebugMessage(" -> integrality could be achieved by scaling with %g\n", scaleval);
8999 
9000  /* if the scalar is still the reciprocal of the minimal value, all coeffcients are the same and we do not get a better scalar */
9001  if( i == 0 && EPSEQ(scaleval, 1.0/minval, SCIP_DEFAULT_EPSILON) )
9002  {
9003  if( intscalar != NULL )
9004  *intscalar = bestscalar;
9005  *success = TRUE;
9006 
9007  return SCIP_OKAY;
9008  }
9009  }
9010  }
9011 
9012  /* convert each value into a rational number, calculate the greatest common divisor of the nominators
9013  * and the smallest common multiple of the denominators
9014  */
9015  gcd = 1;
9016  scm = 1;
9017  rational = TRUE;
9018 
9019  /* first value (to initialize gcd) */
9020  for( c = 0; c < nvals && rational; ++c )
9021  {
9022  val = vals[c];
9023  if( val == 0.0 ) /* zeros are allowed in the vals array */
9024  continue;
9025 
9026  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9027  if( rational && nominator != 0 )
9028  {
9029  assert(denominator > 0);
9030  gcd = ABS(nominator);
9031  scm = denominator;
9032  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9033  SCIPdebugMessage(" -> c=%d first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9034  c, val, nominator, denominator, gcd, scm, rational);
9035  break;
9036  }
9037  }
9038 
9039  /* remaining values */
9040  for( ++c; c < nvals && rational; ++c )
9041  {
9042  val = vals[c];
9043  if( val == 0.0 ) /* zeros are allowed in the vals array */
9044  continue;
9045 
9046  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9047  if( rational && nominator != 0 )
9048  {
9049  assert(denominator > 0);
9050  gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
9051  scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
9052  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9053  SCIPdebugMessage(" -> c=%d next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9054  c, val, nominator, denominator, gcd, scm, rational);
9055  }
9056  else
9057  {
9058  SCIPdebugMessage(" -> failed to convert %g into a rational representation\n", val);
9059  }
9060  }
9061 
9062  if( rational )
9063  {
9064  /* make values integral by multiplying them with the smallest common multiple of the denominators */
9065  assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9066 
9067  /* check if we found a better scaling value */
9068  if( (SCIP_Real)scm/(SCIP_Real)gcd < bestscalar )
9069  bestscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
9070 
9071  SCIPdebugMessage(" -> integrality could be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
9072  (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
9073  }
9074 
9075  if( bestscalar < SCIP_INVALID )
9076  {
9077  if( intscalar != NULL )
9078  *intscalar = bestscalar;
9079  *success = TRUE;
9080 
9081  SCIPdebugMessage(" -> smallest value to achieve integrality is %g \n", bestscalar);
9082  }
9083 
9084  return SCIP_OKAY;
9085 }
9086 
9087 /** given a (usually very small) interval, tries to find a rational number with simple denominator (i.e. a small
9088  * number, probably multiplied with powers of 10) out of this interval; returns TRUE iff a valid rational
9089  * number inside the interval was found
9090  */
9092  SCIP_Real lb, /**< lower bound of the interval */
9093  SCIP_Real ub, /**< upper bound of the interval */
9094  SCIP_Longint maxdnom, /**< maximal denominator allowed for resulting rational number */
9095  SCIP_Longint* nominator, /**< pointer to store the nominator n of the rational number */
9096  SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9097  )
9098 {
9099  SCIP_Real center;
9100  SCIP_Real delta;
9101 
9102  assert(lb <= ub);
9103 
9104  center = 0.5*(lb+ub);
9105 
9106  /* in order to compute a rational number that is exactly within the bounds (as the user expects),
9107  * we computed the allowed delta with downward rounding, if available
9108  */
9110  {
9111  SCIP_ROUNDMODE roundmode;
9112 
9113  roundmode = SCIPintervalGetRoundingMode();
9115 
9116  delta = 0.5*(ub-lb);
9117 
9118  SCIPintervalSetRoundingMode(roundmode);
9119  }
9120  else
9121  {
9122  delta = 0.5*(ub-lb);
9123  }
9124 
9125  return SCIPrealToRational(center, -delta, +delta, maxdnom, nominator, denominator);
9126 }
9127 
9128 /** given a (usually very small) interval, selects a value inside this interval; it is tried to select a rational number
9129  * with simple denominator (i.e. a small number, probably multiplied with powers of 10);
9130  * if no valid rational number inside the interval was found, selects the central value of the interval
9131  */
9133  SCIP_Real lb, /**< lower bound of the interval */
9134  SCIP_Real ub, /**< upper bound of the interval */
9135  SCIP_Longint maxdnom /**< maximal denominator allowed for resulting rational number */
9136  )
9137 {
9138  SCIP_Real val;
9139 
9140  val = 0.5*(lb+ub);
9141  if( lb < ub )
9142  {
9143  SCIP_Longint nominator;
9144  SCIP_Longint denominator;
9145  SCIP_Bool success;
9146 
9147  /* try to find a "simple" rational number inside the interval */
9148  SCIPdebugMessage("simple rational in [%.9f,%.9f]:", lb, ub);
9149  success = SCIPfindSimpleRational(lb, ub, maxdnom, &nominator, &denominator);
9150  if( success )
9151  {
9152  val = (SCIP_Real)nominator/(SCIP_Real)denominator;
9153  SCIPdebugPrintf(" %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT " == %.9f\n", nominator, denominator, val);
9154 
9155  if( val - lb < 0.0 || val - ub > 0.0 )
9156  {
9157  SCIPdebugPrintf(" value is out of interval bounds by %g -> failed\n", MAX(lb-val, val-ub));
9158  val = 0.5*(lb+ub);
9159  }
9160  }
9161  else
9162  {
9163  SCIPdebugPrintf(" failed\n");
9164  }
9165  }
9166 
9167  return val;
9168 }
9169 
9170 
9171 
9172 
9173 /*
9174  * Random Numbers
9175  */
9176 
9177 #if defined(NO_RAND_R) || defined(_WIN32) || defined(_WIN64)
9178 
9179 #define SCIP_RAND_MAX 32767
9180 /** returns a random number between 0 and SCIP_RAND_MAX */
9181 static
9182 int getRand(
9183  unsigned int* seedp /**< pointer to seed value */
9184  )
9185 {
9186  SCIP_Longint nextseed;
9187 
9188  assert(seedp != NULL);
9189 
9190  nextseed = (*seedp) * (SCIP_Longint)1103515245 + 12345;
9191  *seedp = (unsigned int)nextseed;
9192 
9193  return (int)((unsigned int)(nextseed/(2*(SCIP_RAND_MAX+1))) % (SCIP_RAND_MAX+1));
9194 }
9195 
9196 #else
9197 
9198 #define SCIP_RAND_MAX RAND_MAX
9199 
9200 /** returns a random number between 0 and SCIP_RAND_MAX */
9201 static
9203  unsigned int* seedp /**< pointer to seed value */
9204  )
9205 {
9206  return rand_r(seedp);
9207 }
9208 
9209 #endif
9210 
9211 /** returns a random integer between minrandval and maxrandval */
9212 static
9214  int minrandval, /**< minimal value to return */
9215  int maxrandval, /**< maximal value to return */
9216  unsigned int* seedp /**< pointer to seed value */
9217  )
9218 {
9219  SCIP_Real randnumber;
9220 
9221  randnumber = (SCIP_Real)getRand(seedp)/(SCIP_RAND_MAX+1.0);
9222  assert(randnumber >= 0.0);
9223  assert(randnumber < 1.0);
9224 
9225  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than INT_MAX
9226  * apart
9227  */
9228  return (int) (minrandval*(1.0 - randnumber) + maxrandval*randnumber + randnumber);
9229 }
9230 
9231 /** returns a random real between minrandval and maxrandval */
9232 static
9234  SCIP_Real minrandval, /**< minimal value to return */
9235  SCIP_Real maxrandval, /**< maximal value to return */
9236  unsigned int* seedp /**< pointer to seed value */
9237  )
9238 {
9239  SCIP_Real randnumber;
9240 
9241  randnumber = (SCIP_Real)getRand(seedp)/(SCIP_Real)SCIP_RAND_MAX;
9242  assert(randnumber >= 0.0);
9243  assert(randnumber <= 1.0);
9244 
9245  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
9246  * SCIP_REAL_MAX apart
9247  */
9248  return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
9249 }
9250 
9251 /** returns a random integer between minrandval and maxrandval
9252  *
9253  * @deprecated Please use SCIPrandomGetInt() to request a random integer.
9254  */
9256  int minrandval, /**< minimal value to return */
9257  int maxrandval, /**< maximal value to return */
9258  unsigned int* seedp /**< pointer to seed value */
9259  )
9260 {
9261  return getRandomInt(minrandval, maxrandval, seedp);
9262 }
9263 
9264 /** returns a random real between minrandval and maxrandval
9265  *
9266  * @deprecated Please use SCIPrandomGetReal() to request a random real.
9267  */
9269  SCIP_Real minrandval, /**< minimal value to return */
9270  SCIP_Real maxrandval, /**< maximal value to return */
9271  unsigned int* seedp /**< pointer to seed value */
9272  )
9273 {
9274  return getRandomReal(minrandval, maxrandval, seedp);
9275 }
9276 
9277 
9278 /* initial seeds for KISS random number generator */
9279 #define DEFAULT_SEED UINT32_C(123456789)
9280 #define DEFAULT_XOR UINT32_C(362436000)
9281 #define DEFAULT_MWC UINT32_C(521288629)
9282 #define DEFAULT_CST UINT32_C(7654321)
9283 
9284 
9285 /** initializes a random number generator with a given start seed */
9287  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
9288  unsigned int initseed /**< initial random seed */
9289  )
9290 {
9291  assert(randnumgen != NULL);
9292 
9293  /* use MAX() to avoid zero after over flowing */
9294  randnumgen->seed = MAX(SCIPhashTwo(DEFAULT_SEED, initseed), 1u);
9295  randnumgen->xor_seed = MAX(SCIPhashTwo(DEFAULT_XOR, initseed), 1u);
9296  randnumgen->mwc_seed = MAX(SCIPhashTwo(DEFAULT_MWC, initseed), 1u);
9297  randnumgen->cst_seed = SCIPhashTwo(DEFAULT_CST, initseed);
9298 
9299  assert(randnumgen->seed > 0);
9300  assert(randnumgen->xor_seed > 0);
9301  assert(randnumgen->mwc_seed > 0);
9302 }
9303 
9304 /** returns a random number between 0 and UINT32_MAX
9305  *
9306  * implementation of KISS random number generator developed by George Marsaglia.
9307  * KISS is combination of three different random number generators:
9308  * - Linear congruential generator
9309  * - Xorshift
9310  * - Lag-1 Multiply-with-carry
9311  *
9312  * KISS has a period of 2^123 and passes all statistical test part of BigCrush-Test of TestU01 [1].
9313  *
9314  * [1] http://dl.acm.org/citation.cfm?doid=1268776.1268777
9315  */
9316 static
9317 uint32_t randomGetRand(
9318  SCIP_RANDNUMGEN* randnumgen /**< random number generator */
9319  )
9320 {
9321  uint64_t t;
9322 
9323  /* linear congruential */
9324  randnumgen->seed = (uint32_t) (randnumgen->seed * UINT64_C(1103515245) + UINT64_C(12345));
9325 
9326  /* Xorshift */
9327  randnumgen->xor_seed ^= (randnumgen->xor_seed << 13);
9328  randnumgen->xor_seed ^= (randnumgen->xor_seed >> 17);
9329  randnumgen->xor_seed ^= (randnumgen->xor_seed << 5);
9330 
9331  /* Multiply-with-carry */
9332  t = UINT64_C(698769069) * randnumgen->mwc_seed + randnumgen->cst_seed;
9333  randnumgen->cst_seed = (uint32_t) (t >> 32);
9334  randnumgen->mwc_seed = (uint32_t) t;
9335 
9336  return randnumgen->seed + randnumgen->xor_seed + randnumgen->mwc_seed;
9337 }
9338 
9339 /** creates and initializes a random number generator */
9341  SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
9342  BMS_BLKMEM* blkmem, /**< block memory */
9343  unsigned int initialseed /**< initial random seed */
9344  )
9345 {
9346  assert(randnumgen != NULL);
9347 
9348  SCIP_ALLOC( BMSallocBlockMemory(blkmem, randnumgen) );
9349 
9350  SCIPrandomSetSeed((*randnumgen), initialseed);
9351 
9352  return SCIP_OKAY;
9353 }
9354 
9355 /** frees a random number generator */
9357  SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
9358  BMS_BLKMEM* blkmem /**< block memory */
9359  )
9360 {
9361  assert(randnumgen != NULL);
9362  assert((*randnumgen) != NULL);
9363 
9364  BMSfreeBlockMemory(blkmem, randnumgen);
9365 
9366  return;
9367 }
9368 
9369 
9370 
9371 /** returns a random integer between minrandval and maxrandval */
9373  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
9374  int minrandval, /**< minimal value to return */
9375  int maxrandval /**< maximal value to return */
9376  )
9377 {
9378  SCIP_Real randnumber;
9379  SCIP_Longint zeromax;
9380 
9381  randnumber = (SCIP_Real)randomGetRand(randnumgen)/(UINT32_MAX+1.0);
9382  assert(randnumber >= 0.0);
9383  assert(randnumber < 1.0);
9384 
9385  /* we need to shift the range to the non-negative integers to handle negative integer values correctly.
9386  * we use a long integer to avoid overflows.
9387  */
9388  zeromax = (SCIP_Longint)maxrandval - (SCIP_Longint)minrandval + 1;
9389 
9390  return (int) ((SCIP_Longint)(zeromax * randnumber) + (SCIP_Longint)minrandval);
9391 }
9392 
9393 /** returns a random real between minrandval and maxrandval */
9395  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
9396  SCIP_Real minrandval, /**< minimal value to return */
9397  SCIP_Real maxrandval /**< maximal value to return */
9398  )
9399 {
9400  SCIP_Real randnumber;
9401 
9402  randnumber = (SCIP_Real)randomGetRand(randnumgen)/(SCIP_Real)UINT32_MAX;
9403  assert(randnumber >= 0.0);
9404  assert(randnumber <= 1.0);
9405 
9406  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
9407  * SCIP_REAL_MAX apart
9408  */
9409  return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
9410 }
9411 
9412 /** randomly shuffles parts of an integer array using the Fisher-Yates algorithm */
9414  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
9415  int* array, /**< array to be shuffled */
9416  int begin, /**< first included index that should be subject to shuffling
9417  * (0 for first array entry)
9418  */
9419  int end /**< first excluded index that should not be subject to shuffling
9420  * (array size for last array entry)
9421  */
9422  )
9423 {
9424  int tmp;
9425  int i;
9426 
9427  /* loop backwards through all elements and always swap the current last element to a random position */
9428  while( end > begin+1 )
9429  {
9430  --end;
9431 
9432  /* get a random position into which the last entry should be shuffled */
9433  i = SCIPrandomGetInt(randnumgen, begin, end);
9434 
9435  /* swap the last element and the random element */
9436  tmp = array[i];
9437  array[i] = array[end];
9438  array[end] = tmp;
9439  }
9440 }
9441 
9442 /** randomly shuffles parts of an array using the Fisher-Yates algorithm */
9444  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
9445  void** array, /**< array to be shuffled */
9446  int begin, /**< first included index that should be subject to shuffling
9447  * (0 for first array entry)
9448  */
9449  int end /**< first excluded index that should not be subject to shuffling
9450  * (array size for last array entry)
9451  */
9452  )
9453 {
9454  void* tmp;
9455  int i;
9456 
9457  /* loop backwards through all elements and always swap the current last element to a random position */
9458  while( end > begin+1 )
9459  {
9460  end--;
9461 
9462  /* get a random position into which the last entry should be shuffled */
9463  i = SCIPrandomGetInt(randnumgen, begin, end);
9464 
9465  /* swap the last element and the random element */
9466  tmp = array[i];
9467  array[i] = array[end];
9468  array[end] = tmp;
9469  }
9470 }
9471 
9472 /** draws a random subset of disjoint elements from a given set of disjoint elements;
9473  * this implementation is suited for the case that nsubelems is considerably smaller then nelems
9474  */
9476  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
9477  void** set, /**< original set, from which elements should be drawn */
9478  int nelems, /**< number of elements in original set */
9479  void** subset, /**< subset in which drawn elements should be stored */
9480  int nsubelems /**< number of elements that should be drawn and stored */
9481  )
9482 {
9483  int i;
9484  int j;
9485 
9486  /* if both sets are of equal size, we just copy the array */
9487  if( nelems == nsubelems)
9488  {
9489  BMScopyMemoryArray(subset,set,nelems);
9490  return SCIP_OKAY;
9491  }
9492 
9493  /* abort, if size of subset is too big */
9494  if( nsubelems > nelems )
9495  {
9496  SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
9497  return SCIP_INVALIDDATA;
9498  }
9499 #ifndef NDEBUG
9500  for( i = 0; i < nsubelems; i++ )
9501  for( j = 0; j < i; j++ )
9502  assert(set[i] != set[j]);
9503 #endif
9504 
9505  /* draw each element individually */
9506  i = 0;
9507  while( i < nsubelems )
9508  {
9509  int r;
9510 
9511  r = SCIPrandomGetInt(randnumgen, 0, nelems-1);
9512  subset[i] = set[r];
9513 
9514  /* if we get an element that we already had, we will draw again */
9515  for( j = 0; j < i; j++ )
9516  {
9517  if( subset[i] == subset[j] )
9518  {
9519  --i;
9520  break;
9521  }
9522  }
9523  ++i;
9524  }
9525  return SCIP_OKAY;
9526 }
9527 
9528 /*
9529  * Additional math functions
9530  */
9531 
9532 /** calculates a binomial coefficient n over m, choose m elements out of n, maximal value will be 33 over 16 (because
9533  * 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
9534  * big numbers or an negative value m (and m < n) and -1 will be returned
9535  */
9537  int n, /**< number of different elements */
9538  int m /**< number to choose out of the above */
9539  )
9540 {
9541  if( m == 0 || m >= n )
9542  return 1;
9543 
9544  if( m < 0 )
9545  return -1;
9546 
9547  /* symmetry of the binomial coefficient, choose smaller m */
9548  if( m > n/2 )
9549  m = n - m;
9550 
9551  /* trivial case m == 1 */
9552  if( m == 1 )
9553  return n;
9554 
9555  /* simple case m == 2 */
9556  if( m == 2 )
9557  {
9558  if( ((SCIP_Real)SCIP_LONGINT_MAX) / n >= (n-1) * 2 ) /*lint !e790*/
9559  return ((SCIP_Longint)n*(n-1)/2); /*lint !e647*/
9560  else
9561  return -1;
9562  }
9563 
9564  /* abort on to big numbers */
9565  if( m > 16 || n > 33 )
9566  return -1;
9567 
9568  /* simple case m == 3 */
9569  if( m == 3 )
9570  return (n*(n-1)*(n-2)/6); /*lint !e647*/
9571  else
9572  {
9573  /* first half of Pascal's triangle numbers(without the symmetric part) backwards from (33,16) over (32,16),
9574  * (33,15), (32,15),(31,15, (30,15), (33,14) to (8,4) (rest is calculated directly)
9575  *
9576  * due to this order we can extract the right binomial coefficient by (16-m)^2+(16-m)+(33-n)
9577  */
9578  static const SCIP_Longint binoms[182] = {
9579  1166803110, 601080390, 1037158320, 565722720, 300540195, 155117520, 818809200, 471435600, 265182525, 145422675,
9580  77558760, 40116600, 573166440, 347373600, 206253075, 119759850, 67863915, 37442160, 20058300, 10400600,
9581  354817320, 225792840, 141120525, 86493225, 51895935, 30421755, 17383860, 9657700, 5200300, 2704156, 193536720,
9582  129024480, 84672315, 54627300, 34597290, 21474180, 13037895, 7726160, 4457400, 2496144, 1352078, 705432,
9583  92561040, 64512240, 44352165, 30045015, 20030010, 13123110, 8436285, 5311735, 3268760, 1961256, 1144066,
9584  646646, 352716, 184756, 38567100, 28048800, 20160075, 14307150, 10015005, 6906900, 4686825, 3124550, 2042975,
9585  1307504, 817190, 497420, 293930, 167960, 92378, 48620, 13884156, 10518300, 7888725, 5852925, 4292145, 3108105,
9586  2220075, 1562275, 1081575, 735471, 490314, 319770, 203490, 125970, 75582, 43758, 24310, 12870, 4272048, 3365856,
9587  2629575, 2035800, 1560780, 1184040, 888030, 657800, 480700, 346104, 245157, 170544, 116280, 77520, 50388, 31824,
9588  19448, 11440, 6435, 3432, 1107568, 906192, 736281, 593775, 475020, 376740, 296010, 230230, 177100, 134596,
9589  100947, 74613, 54264, 38760, 27132, 18564, 12376, 8008, 5005, 3003, 1716, 924, 237336, 201376, 169911, 142506,
9590  118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, 11628, 8568, 6188, 4368, 3003, 2002,
9591  1287, 792, 462, 252, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985,
9592  4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70};
9593 
9594  /* m can at most be 16 */
9595  const int t = 16-m;
9596  assert(t >= 0);
9597  assert(n <= 33);
9598 
9599  /* binoms array hast exactly 182 elements */
9600  assert(t*(t+1)+(33-n) < 182);
9601 
9602  return binoms[t*(t+1)+(33-n)]; /*lint !e662 !e661*/
9603  }
9604 }
9605 
9606 /** negates a number */
9608  SCIP_Real x /**< value to negate */
9609  )
9610 {
9611  return -x;
9612 }
9613 
9614 /*
9615  * Permutations / Shuffling
9616  */
9617 
9618 /** swaps two ints */
9620  int* value1, /**< pointer to first integer */
9621  int* value2 /**< pointer to second integer */
9622  )
9623 {
9624  int tmp;
9625 
9626  tmp = *value1;
9627  *value1 = *value2;
9628  *value2 = tmp;
9629 }
9630 
9631 /** swaps two real values */
9633  SCIP_Real* value1, /**< pointer to first real value */
9634  SCIP_Real* value2 /**< pointer to second real value */
9635  )
9636 {
9637  SCIP_Real tmp;
9638 
9639  tmp = *value1;
9640  *value1 = *value2;
9641  *value2 = tmp;
9642 }
9643 
9644 /** swaps the addresses of two pointers */
9646  void** pointer1, /**< first pointer */
9647  void** pointer2 /**< second pointer */
9648  )
9649 {
9650  void* tmp;
9651 
9652  tmp = *pointer1;
9653  *pointer1 = *pointer2;
9654  *pointer2 = tmp;
9655 }
9656 
9657 /** randomly shuffles parts of an integer array using the Fisher-Yates algorithm
9658  *
9659  * @deprecated Please use SCIPrandomPermuteIntArray()
9660  */
9662  int* array, /**< array to be shuffled */
9663  int begin, /**< first included index that should be subject to shuffling
9664  * (0 for first array entry)
9665  */
9666  int end, /**< first excluded index that should not be subject to shuffling
9667  * (array size for last array entry)
9668  */
9669  unsigned int* randseed /**< seed value for the random generator */
9670  )
9671 {
9672  int tmp;
9673  int i;
9674 
9675  /* loop backwards through all elements and always swap the current last element to a random position */
9676  while( end > begin+1 )
9677  {
9678  --end;
9679 
9680  /* get a random position into which the last entry should be shuffled */
9681  i = getRandomInt(begin, end, randseed);
9682 
9683  /* swap the last element and the random element */
9684  tmp = array[i];
9685  array[i] = array[end];
9686  array[end] = tmp;
9687  }
9688 }
9689 
9690 
9691 /** randomly shuffles parts of an array using the Fisher-Yates algorithm
9692  *
9693  * @deprecated Please use SCIPrandomPermuteArray()
9694  */
9696  void** array, /**< array to be shuffled */
9697  int begin, /**< first included index that should be subject to shuffling
9698  * (0 for first array entry)
9699  */
9700  int end, /**< first excluded index that should not be subject to shuffling
9701  * (array size for last array entry)
9702  */
9703  unsigned int* randseed /**< seed value for the random generator */
9704  )
9705 {
9706  void* tmp;
9707  int i;
9708 
9709  /* loop backwards through all elements and always swap the current last element to a random position */
9710  while( end > begin+1 )
9711  {
9712  end--;
9713 
9714  /* get a random position into which the last entry should be shuffled */
9715  i = getRandomInt(begin, end, randseed);
9716 
9717  /* swap the last element and the random element */
9718  tmp = array[i];
9719  array[i] = array[end];
9720  array[end] = tmp;
9721  }
9722 }
9723 
9724 /** draws a random subset of disjoint elements from a given set of disjoint elements;
9725  * this implementation is suited for the case that nsubelems is considerably smaller then nelems
9726  *
9727  * @deprecated Please use SCIPrandomGetSubset()
9728  */
9730  void** set, /**< original set, from which elements should be drawn */
9731  int nelems, /**< number of elements in original set */
9732  void** subset, /**< subset in which drawn elements should be stored */
9733  int nsubelems, /**< number of elements that should be drawn and stored */
9734  unsigned int randseed /**< seed value for random generator */
9735  )
9736 {
9737  int i;
9738  int j;
9739 
9740  /* if both sets are of equal size, we just copy the array */
9741  if( nelems == nsubelems)
9742  {
9743  BMScopyMemoryArray(subset,set,nelems);
9744  return SCIP_OKAY;
9745  }
9746 
9747  /* abort, if size of subset is too big */
9748  if( nsubelems > nelems )
9749  {
9750  SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
9751  return SCIP_INVALIDDATA;
9752  }
9753 #ifndef NDEBUG
9754  for( i = 0; i < nsubelems; i++ )
9755  for( j = 0; j < i; j++ )
9756  assert(set[i] != set[j]);
9757 #endif
9758 
9759  /* draw each element individually */
9760  i = 0;
9761  while( i < nsubelems )
9762  {
9763  int r;
9764 
9765  r = getRandomInt(0, nelems-1, &randseed);
9766  subset[i] = set[r];
9767 
9768  /* if we get an element that we already had, we will draw again */
9769  for( j = 0; j < i; j++ )
9770  {
9771  if( subset[i] == subset[j] )
9772  {
9773  --i;
9774  break;
9775  }
9776  }
9777  ++i;
9778  }
9779  return SCIP_OKAY;
9780 }
9781 
9782 
9783 /*
9784  * Arrays
9785  */
9786 
9787 /** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly */
9789  int* array1, /**< first array (in ascending order) */
9790  int narray1, /**< number of entries of first array */
9791  int* array2, /**< second array (in ascending order) */
9792  int narray2, /**< number of entries of second array */
9793  int* intersectarray, /**< intersection of array1 and array2
9794  * (note: it is possible to use array1 for this input argument) */
9795  int* nintersectarray /**< pointer to store number of entries of intersection array
9796  * (note: it is possible to use narray1 for this input argument) */
9797  )
9798 {
9799  int cnt = 0;
9800  int k = 0;
9801  int v1;
9802  int v2;
9803 
9804  assert( array1 != NULL );
9805  assert( array2 != NULL );
9806  assert( intersectarray != NULL );
9807  assert( nintersectarray != NULL );
9808 
9809  /* determine intersection of array1 and array2 */
9810  for (v1 = 0; v1 < narray1; ++v1)
9811  {
9812  assert( v1 == 0 || array1[v1] >= array1[v1-1] );
9813 
9814  /* skip duplicate entries */
9815  if ( v1+1 < narray1 && array1[v1] == array1[v1+1])
9816  continue;
9817 
9818  for (v2 = k; v2 < narray2; ++v2)
9819  {
9820  assert( v2 == 0 || array2[v2] >= array2[v2-1] );
9821 
9822  if ( array2[v2] > array1[v1] )
9823  {
9824  k = v2;
9825  break;
9826  }
9827  else if ( array2[v2] == array1[v1] )
9828  {
9829  intersectarray[cnt++] = array2[v2];
9830  k = v2 + 1;
9831  break;
9832  }
9833  }
9834  }
9835 
9836  /* store size of intersection array */
9837  *nintersectarray = cnt;
9838 
9839  return SCIP_OKAY;
9840 }
9841 
9842 
9843 /** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly */
9845  int* array1, /**< first array (in ascending order) */
9846  int narray1, /**< number of entries of first array */
9847  int* array2, /**< second array (in ascending order) */
9848  int narray2, /**< number of entries of second array */
9849  int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
9850  * (note: it is possible to use array1 for this input argument) */
9851  int* nsetminusarray /**< pointer to store number of entries of setminus array
9852  * (note: it is possible to use narray1 for this input argument) */
9853  )
9854 {
9855  int cnt = 0;
9856  int v1 = 0;
9857  int v2 = 0;
9858 
9859  assert( array1 != NULL );
9860  assert( array2 != NULL );
9861  assert( setminusarray != NULL );
9862  assert( nsetminusarray != NULL );
9863 
9864  while ( v1 < narray1 )
9865  {
9866  int entry1;
9867 
9868  assert( v1 == 0 || array1[v1] >= array1[v1-1] );
9869 
9870  /* skip duplicate entries */
9871  while ( v1 + 1 < narray1 && array1[v1] == array1[v1 + 1] )
9872  ++v1;
9873 
9874  entry1 = array1[v1];
9875 
9876  while ( v2 < narray2 && array2[v2] < entry1 )
9877  ++v2;
9878 
9879  if ( v2 >= narray2 || entry1 < array2[v2] )
9880  setminusarray[cnt++] = entry1;
9881  ++v1;
9882  }
9883 
9884  /* store size of setminus array */
9885  *nsetminusarray = cnt;
9886 
9887  return SCIP_OKAY;
9888 }
9889 
9890 
9891 /*
9892  * Strings
9893  */
9894 
9895 
9896 /** copies characters from 'src' to 'dest', copying is stopped when either the 'stop' character is reached or after
9897  * 'cnt' characters have been copied, whichever comes first.
9898  *
9899  * @note undefined behavior on overlapping arrays
9900  */
9902  char* dest, /**< destination pointer to copy to */
9903  const char* src, /**< source pointer to copy from */
9904  char stop, /**< character when found stop copying */
9905  unsigned int cnt /**< maximal number of characters to copy */
9906  )
9907 {
9908  if( dest == NULL || src == NULL || cnt == 0 )
9909  return -1;
9910  else
9911  {
9912  char* destination = dest;
9913 
9914  while( cnt-- && (*destination++ = *src++) != stop ); /*lint !e722*/
9915 
9916  return (int)(destination - dest);
9917  }
9918 }
9919 
9920 /** prints an error message containing of the given string followed by a string describing the current system error
9921  *
9922  * Prefers to use the strerror_r method, which is threadsafe. On systems where this method does not exist,
9923  * NO_STRERROR_R should be defined (see INSTALL). In this case, strerror is used which is not guaranteed to be
9924  * threadsafe (on SUN-systems, it actually is).
9925  */
9927  const char* message /**< first part of the error message, e.g. the filename */
9928  )
9929 {
9930 #ifdef NO_STRERROR_R
9931  SCIPmessagePrintError("%s: %s\n", message, strerror(errno));
9932 #else
9933  char buf[SCIP_MAXSTRLEN];
9934 
9935 #if defined(_WIN32) || defined(_WIN64)
9936  /* strerror_s returns 0 on success; the string is \0 terminated. */
9937  if ( strerror_s(buf, SCIP_MAXSTRLEN, errno) != 0 )
9938  SCIPmessagePrintError("Unknown error number %d or error message too long.\n", errno);
9939  SCIPmessagePrintError("%s: %s\n", message, buf);
9940 #elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
9941  /* We are in the POSIX/XSI case, where strerror_r returns 0 on success; \0 termination is unclear. */
9942  if ( strerror_r(errno, buf, SCIP_MAXSTRLEN) != 0 )
9943  SCIPmessagePrintError("Unknown error number %d.\n", errno);
9944  buf[SCIP_MAXSTRLEN - 1] = '\0';
9945  SCIPmessagePrintError("%s: %s\n", message, buf);
9946 #else
9947  /* We are in the GNU case, where strerror_r returns a pointer to the error string. This string is possibly stored
9948  * in buf and is always \0 terminated.
9949  * However, if compiling on one system and executing on another system, we might actually call a different
9950  * variant of the strerror_r function than we had at compile time.
9951  */
9952  char* errordescr;
9953  *buf = '\0';
9954  errordescr = strerror_r(errno, buf, SCIP_MAXSTRLEN);
9955  if( *buf != '\0' )
9956  {
9957  /* strerror_r wrote into buf */
9958  SCIPmessagePrintError("%s: %s\n", message, buf);
9959  }
9960  else if( errordescr != NULL )
9961  {
9962  /* strerror_r returned something non-NULL */
9963  SCIPmessagePrintError("%s: %s\n", message, errordescr);
9964  }
9965  else
9966  {
9967  /* strerror_r did return NULL and did not write into buf */
9968  SCIPmessagePrintError("Could not obtain description for error %d.\n", errno);
9969  }
9970 #endif
9971 #endif
9972 }
9973 
9974 /** extracts tokens from strings - wrapper method for strtok_r() */
9976  char* s, /**< string to parse */
9977  const char* delim, /**< delimiters for parsing */
9978  char** ptrptr /**< pointer to working char pointer - must stay the same while parsing */
9979  )
9980 {
9981 #ifdef NO_STRTOK_R
9982  return strtok(s, delim);
9983 #else
9984  return strtok_r(s, delim, ptrptr);
9985 #endif
9986 }
9987 
9988 /** translates the given string into a string where symbols ", ', and spaces are escaped with a \ prefix */
9990  char* t, /**< target buffer to store escaped string */
9991  int bufsize, /**< size of buffer t */
9992  const char* s /**< string to transform into escaped string */
9993  )
9994 {
9995  int len;
9996  int i;
9997  int p;
9998 
9999  assert(t != NULL);
10000  assert(bufsize > 0);
10001 
10002  len = (int)strlen(s);
10003  for( p = 0, i = 0; i <= len && p < bufsize; ++i, ++p )
10004  {
10005  if( s[i] == ' ' || s[i] == '"' || s[i] == '\'' )
10006  {
10007  t[p] = '\\';
10008  p++;
10009  }
10010  if( p < bufsize )
10011  t[p] = s[i];
10012  }
10013  t[bufsize-1] = '\0';
10014 }
10015 
10016 /* safe version of snprintf */
10018  char* t, /**< target string */
10019  int len, /**< length of the string to copy */
10020  const char* s, /**< source string */
10021  ... /**< further parameters */
10022  )
10023 {
10024  va_list ap;
10025  int n;
10026 
10027  assert(t != NULL);
10028  assert(len > 0);
10029 
10030  va_start(ap, s); /*lint !e826*/
10031 
10032 #if defined(_WIN32) || defined(_WIN64)
10033  n = _vsnprintf(t, (size_t) len, s, ap);
10034 #else
10035  n = vsnprintf(t, (size_t) len, s, ap); /*lint !e571*/
10036 #endif
10037  va_end(ap);
10038 
10039  if( n < 0 || n >= len )
10040  {
10041 #ifndef NDEBUG
10042  if( n < 0 )
10043  {
10044  SCIPerrorMessage("vsnprintf returned %d\n",n);
10045  }
10046 #endif
10047  t[len-1] = '\0';
10048  n = len-1;
10049  }
10050  return n;
10051 }
10052 
10053 /** safe version of strncpy
10054  *
10055  * Copies string in s to t using at most @a size-1 nonzero characters (strncpy copies size characters). It always adds
10056  * a terminating zero char. Does not pad the remaining string with zero characters (unlike strncpy). Returns the number
10057  * of copied nonzero characters, if the length of s is at most size - 1, and returns size otherwise. Thus, the original
10058  * string was truncated if the return value is size.
10059  */
10061  char* t, /**< target string */
10062  const char* s, /**< source string */
10063  int size /**< maximal size of t */
10064  )
10065 {
10066  int n;
10067 
10068  if( size <= 0 )
10069  return 0;
10070 
10071  /* decrease size by 1 to create space for terminating zero char */
10072  --size;
10073  for( n = 0; n < size && *s != '\0'; n++ )
10074  *(t++) = *(s++);
10075  *t = '\0';
10076 
10077  if( *s != '\0' )
10078  ++n;
10079 
10080  return n;
10081 }
10082 
10083 /** 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
10084  *
10085  * @return Returns TRUE if a value could be extracted, otherwise FALSE
10086  */
10088  const char* str, /**< string to search */
10089  int* value, /**< pointer to store the parsed value */
10090  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10091  )
10092 {
10093  assert(str != NULL);
10094  assert(value != NULL);
10095  assert(endptr != NULL);
10096 
10097  /* init errno to detect possible errors */
10098  errno = 0;
10099 
10100  *value = (int) strtol(str, endptr, 10);
10101 
10102  if( *endptr != str && *endptr != NULL )
10103  {
10104  SCIPdebugMessage("parsed integer value <%d>\n", *value);
10105  return TRUE;
10106  }
10107  *endptr = (char*)str;
10108 
10109  SCIPdebugMessage("failed parsing integer value <%s>\n", str);
10110 
10111  return FALSE;
10112 }
10113 
10114 /** 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
10115  *
10116  * @return Returns TRUE if a value could be extracted, otherwise FALSE
10117  */
10119  const char* str, /**< string to search */
10120  SCIP_Real* value, /**< pointer to store the parsed value */
10121  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10122  )
10123 {
10124  assert(str != NULL);
10125  assert(value != NULL);
10126  assert(endptr != NULL);
10127 
10128  /* init errno to detect possible errors */
10129  errno = 0;
10130 
10131  *value = strtod(str, endptr);
10132 
10133  if( *endptr != str && *endptr != NULL )
10134  {
10135  SCIPdebugMessage("parsed real value <%g>\n", *value);
10136  return TRUE;
10137  }
10138  *endptr = (char*)str;
10139 
10140  SCIPdebugMessage("failed parsing real value <%s>\n", str);
10141 
10142  return FALSE;
10143 }
10144 
10145 /** copies the first size characters between a start and end character of str into token, if no error occured endptr
10146  * will point to the position after the read part, otherwise it will point to @p str
10147  */
10149  const char* str, /**< string to search */
10150  char startchar, /**< character which defines the beginning */
10151  char endchar, /**< character which defines the ending */
10152  char* token, /**< string to store the copy */
10153  int size, /**< size of the token char array */
10154  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10155  )
10156 {
10157  const char* copystr;
10158  int nchars;
10159 
10160  assert(str != NULL);
10161  assert(token != NULL);
10162  assert(size > 0);
10163  assert(endptr != NULL);
10164 
10165  nchars = 0;
10166 
10167  copystr = str;
10168 
10169  /* find starting character */
10170  while( *str != '\0' && *str != startchar )
10171  ++str;
10172 
10173  /* did not find start character */
10174  if( *str == '\0' )
10175  {
10176  *endptr = (char*)copystr;
10177  return;
10178  }
10179 
10180  /* skip start character */
10181  ++str;
10182 
10183  /* copy string */
10184  while( *str != '\0' && *str != endchar && nchars < size-1 )
10185  {
10186  assert(nchars < SCIP_MAXSTRLEN);
10187  token[nchars] = *str;
10188  nchars++;
10189  ++str;
10190  }
10191 
10192  /* add end to token */
10193  token[nchars] = '\0';
10194 
10195  /* if section was longer than size, we want to reach the end of the parsing section anyway */
10196  if( nchars == (size-1) )
10197  while( *str != '\0' && *str != endchar )
10198  ++str;
10199 
10200  /* did not find end character */
10201  if( *str == '\0' )
10202  {
10203  *endptr = (char*)copystr;
10204  return;
10205  }
10206 
10207  /* skip end character */
10208  ++str;
10209 
10210  SCIPdebugMessage("parsed section <%s>\n", token);
10211 
10212  *endptr = (char*) str;
10213 }
10214 
10215 /*
10216  * File methods
10217  */
10218 
10219 /** returns, whether the given file exists */
10221  const char* filename /**< file name */
10222  )
10223 {
10224  FILE* f;
10225 
10226  f = fopen(filename, "r");
10227  if( f == NULL )
10228  return FALSE;
10229 
10230  fclose(f);
10231 
10232  return TRUE;
10233 }
10234 
10235 /** splits filename into path, name, and extension */
10237  char* filename, /**< filename to split; is destroyed (but not freed) during process */
10238  char** path, /**< pointer to store path, or NULL if not needed */
10239  char** name, /**< pointer to store name, or NULL if not needed */
10240  char** extension, /**< pointer to store extension, or NULL if not needed */
10241  char** compression /**< pointer to store compression extension, or NULL if not needed */
10242  )
10243 {
10244  char* lastslash;
10245  char* lastbackslash;
10246  char* lastdot;
10247 
10248  assert(filename != NULL);
10249 
10250  if( path != NULL )
10251  *path = NULL;
10252  if( name != NULL )
10253  *name = NULL;
10254  if( extension != NULL )
10255  *extension = NULL;
10256  if( compression != NULL )
10257  *compression = NULL;
10258 
10259  /* treat both slashes '/' and '\' as directory delimiters */
10260  lastslash = strrchr(filename, '/');
10261  lastbackslash = strrchr(filename, '\\');
10262  lastslash = MAX(lastslash, lastbackslash); /*lint !e613*/
10263  lastdot = strrchr(filename, '.');
10264  if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
10265  lastdot = NULL;
10266 
10267  /* detect known compression extensions */
10268 #ifdef WITH_ZLIB
10269  if( lastdot != NULL )
10270  {
10271  char* compext;
10272 
10273  compext = lastdot+1;
10274  if( strcmp(compext, "gz") == 0
10275  || strcmp(compext, "z") == 0
10276  || strcmp(compext, "Z") == 0 )
10277  {
10278  if( compression != NULL )
10279  *compression = compext;
10280  *lastdot = '\0';
10281  }
10282 
10283  /* find again the last dot in the filename without compression extension */
10284  lastdot = strrchr(filename, '.');
10285  if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
10286  lastdot = NULL;
10287  }
10288 #endif
10289 
10290  if( lastslash == NULL )
10291  {
10292  if( name != NULL )
10293  *name = filename;
10294  }
10295  else
10296  {
10297  if( path != NULL )
10298  *path = filename;
10299  if( name != NULL )
10300  *name = lastslash+1;
10301  *lastslash = '\0';
10302  }
10303 
10304  if( lastdot != NULL )
10305  {
10306  if( extension != NULL )
10307  *extension = lastdot+1;
10308  *lastdot = '\0';
10309  }
10310 }
10311 
10312 /*
10313  * simple functions implemented as defines
10314  */
10315 
10316 /* In debug mode, the following methods are implemented as function calls to ensure
10317  * type validity.
10318  * In optimized mode, the methods are implemented as defines to improve performance.
10319  * However, we want to have them in the library anyways, so we have to undef the defines.
10320  */
10321 
10322 #undef SCIPrelDiff
10323 
10324 /** returns the relative difference: (val1-val2)/max(|val1|,|val2|,1.0) */
10326  SCIP_Real val1, /**< first value to be compared */
10327  SCIP_Real val2 /**< second value to be compared */
10328  )
10329 {
10330  SCIP_Real absval1;
10331  SCIP_Real absval2;
10332  SCIP_Real quot;
10333 
10334  absval1 = REALABS(val1);
10335  absval2 = REALABS(val2);
10336  quot = MAX3(1.0, absval1, absval2);
10337 
10338  return (val1-val2)/quot;
10339 }
10340 
10341 
10342 /** computes the gap from the primal and the dual bound */
10344  SCIP_Real eps, /**< the value treated as zero */
10345  SCIP_Real inf, /**< the value treated as infinity */
10346  SCIP_Real primalbound, /**< the primal bound */
10347  SCIP_Real dualbound /**< the dual bound */
10348  )
10349 {
10350  if( EPSEQ(primalbound, dualbound, eps) )
10351  return 0.0;
10352  else
10353  {
10354  SCIP_Real absdual = REALABS(dualbound);
10355  SCIP_Real absprimal = REALABS(primalbound);
10356 
10357  if( EPSZ(dualbound, eps) || EPSZ(primalbound, eps) || absprimal >= inf || absdual >= inf ||
10358  primalbound * dualbound < 0.0 )
10359  return inf;
10360  else
10361  return REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
10362  }
10363 }
10364 
10365 /*
10366  *Union-Find data structure
10367  */
10368 
10369 /** creates a disjoint set (union find) structure \p uf for \p ncomponents many components (of size one) */
10371  SCIP_DISJOINTSET** djset, /**< disjoint set (union find) data structure */
10372  BMS_BLKMEM* blkmem, /**< block memory */
10373  int ncomponents /**< number of components */
10374  )
10375 {
10376  assert(djset != NULL);
10377  assert(blkmem != NULL);
10378 
10379  /* allocate the necessary memory */
10380  assert(ncomponents > 0);
10381  SCIP_ALLOC( BMSallocBlockMemory(blkmem, djset) );
10382  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->parents), ncomponents) );
10383  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->sizes), ncomponents) );
10384  (*djset)->size = ncomponents;
10385 
10386  /* clear the data structure */
10387  SCIPdisjointsetClear(*djset);
10388 
10389  return SCIP_OKAY;
10390 }
10391 
10392 /** clears the disjoint set (union find) structure \p uf */
10394  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
10395  )
10396 {
10397  int i;
10398  djset->componentcount = djset->size;
10399 
10400  /* reset all components to be unconnected */
10401  for( i = 0; i < djset->componentcount; i++ )
10402  {
10403  djset->parents[i] = i;
10404  djset->sizes[i] = 1;
10405  }
10406 }
10407 
10408 
10409 /** finds and returns the component identifier of this \p element */
10411  SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
10412  int element /**< element to be found */
10413  )
10414 {
10415  int newelement;
10416  int root = element;
10417  int* parents = djset->parents;
10418 
10419  /* find root of this element */
10420  while( root != parents[root] )
10421  {
10422  root = parents[root];
10423  }
10424 
10425  /* compress the path to make future queries faster */
10426  while( element != root )
10427  {
10428  newelement = parents[element];
10429  parents[element] = root;
10430  element = newelement;
10431  }
10432 
10433  return root;
10434 }
10435 
10436 /** merges the components containing the elements \p p and \p q */
10438  SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
10439  int p, /**< first element */
10440  int q, /**< second element */
10441  SCIP_Bool forcerepofp /**< force representative of p to be new representative */
10442  )
10443 {
10444  int idp;
10445  int idq;
10446  int* sizes;
10447  int* parents;
10448 
10449  assert(djset != NULL);
10450  assert(0 <= p);
10451  assert(0 <= q);
10452  assert(djset->size > p);
10453  assert(djset->size > q);
10454 
10455  idp = SCIPdisjointsetFind(djset, p);
10456  idq = SCIPdisjointsetFind(djset, q);
10457 
10458  /* if p and q lie in the same component, there is nothing to be done */
10459  if( idp == idq )
10460  return;
10461 
10462  sizes = djset->sizes;
10463  parents = djset->parents;
10464 
10465  if( forcerepofp )
10466  {
10467  parents[idq] = idp;
10468  sizes[idp] += sizes[idq];
10469  }
10470  else
10471  {
10472  if( sizes[idp] < sizes[idq] )
10473  {
10474  parents[idp] = idq;
10475  sizes[idq] += sizes[idp];
10476  }
10477  else
10478  {
10479  parents[idq] = idp;
10480  sizes[idp] += sizes[idq];
10481  }
10482  }
10483  /* one less component */
10484  djset->componentcount--;
10485 }
10486 
10487 /** frees the disjoint set (union find) data structure */
10489  SCIP_DISJOINTSET** djset, /**< pointer to disjoint set (union find) data structure */
10490  BMS_BLKMEM* blkmem /**< block memory */
10491  )
10492 {
10493  SCIP_DISJOINTSET* dsptr;
10494 
10495  assert(djset != NULL);
10496  assert(*djset != NULL);
10497 
10498  dsptr = *djset;
10499 
10500  BMSfreeBlockMemoryArray(blkmem, &dsptr->sizes, dsptr->size);
10501  BMSfreeBlockMemoryArray(blkmem, &dsptr->parents, dsptr->size);
10502 
10503  BMSfreeBlockMemory(blkmem, djset);
10504 }
10505 
10506 /** returns the number of independent components in this disjoint set (union find) data structure */
10508  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
10509  )
10510 {
10511  assert(djset != NULL);
10512 
10513  return djset->componentcount;
10514 }
10515 
10516 /** returns the size (number of nodes) of this disjoint set (union find) data structure */
10518  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
10519  )
10520 {
10521  assert(djset != NULL);
10522 
10523  return djset->size;
10524 }
void SCIPmultihashFree(SCIP_MULTIHASH **multihash)
Definition: misc.c:1712
void SCIPpermuteArray(void **array, int begin, int end, unsigned int *randseed)
Definition: misc.c:9695
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:8010
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:7329
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:8074
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
#define NULL
Definition: def.h:239
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:9901
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:8882
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:10437
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:8159
uint32_t shift
Definition: struct_misc.h:126
SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
Definition: misc.c:6573
void * SCIPbtnodeGetData(SCIP_BTNODE *node)
Definition: misc.c:8119
void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2265
static void message(unsigned int type, const CURF *curf, const char *msg,...)
Definition: grphload.c:317
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:7851
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:260
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:7423
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:7994
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:393
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7311
static SCIP_RETCODE ensureSuccessorsSize(SCIP_DIGRAPH *digraph, int idx, int newsize)
Definition: misc.c:7113
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:6256
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:10236
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:6370
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:9645
void SCIPbtnodeSetRightchild(SCIP_BTNODE *node, SCIP_BTNODE *right)
Definition: misc.c:8280
#define DEFAULT_MWC
Definition: misc.c:9281
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
#define SCIP_RAND_MAX
Definition: misc.c:9198
void * SCIPptrarrayGetVal(SCIP_PTRARRAY *ptrarray, int idx)
Definition: misc.c:4947
#define FALSE
Definition: def.h:65
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:175
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:10325
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:6663
#define SCIP_MULTIHASH_MAXSIZE
Definition: misc.c:1557
miscellaneous datastructures
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10017
void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
Definition: misc.c:9443
#define TRUE
Definition: def.h:64
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:7046
void SCIPdigraphPrintComponents(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:7957
SCIP_VAR * SCIPactivityGetVar(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6209
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:9788
#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:9632
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:7618
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:10087
#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:6543
#define SCIPdebugMessage
Definition: pub_message.h:77
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:9372
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9132
#define DEFAULT_XOR
Definition: misc.c:9280
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:7631
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:10517
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
#define SCIP_LONGINT_MAX
Definition: def.h:136
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:9607
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:6382
SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2950
void * dataptr
Definition: struct_misc.h:223
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10060
int SCIPhashsetGetNSlots(SCIP_HASHSET *hashset)
Definition: misc.c:3581
SCIP_VAR ** x
Definition: circlepacking.c:54
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:7552
#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:8179
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:156
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:10220
void SCIPqueueClear(SCIP_QUEUE *queue)
Definition: misc.c:967
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:7238
int SCIPprofileGetCapacity(SCIP_PROFILE *profile)
Definition: misc.c:6330
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:8727
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:6164
void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:337
SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
Definition: misc.c:2560
SCIP_VAR * w
Definition: circlepacking.c:58
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:10393
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:8129
#define GMLNODEHEIGTH
Definition: misc.c:476
SCIP_RETCODE SCIPdigraphSetNSuccessors(SCIP_DIGRAPH *digraph, int node, int nsuccessors)
Definition: misc.c:7222
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:6239
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:10488
#define GMLNODETYPE
Definition: misc.c:478
void SCIPbtnodeSetLeftchild(SCIP_BTNODE *node, SCIP_BTNODE *left)
Definition: misc.c:8266
SCIP_RETCODE SCIPboolarrayCreate(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4348
void * SCIPdigraphGetNodeData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7248
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)
Definition: pqueue.h:28
SCIP_Real SCIPrealarrayGetVal(SCIP_REALARRAY *realarray, int idx)
Definition: misc.c:3855
void SCIPdigraphSetNodeData(SCIP_DIGRAPH *digraph, void *dataptr, int node)
Definition: misc.c:7264
#define SQRTOFTWO
Definition: misc.c:49
void SCIPescapeString(char *t, int bufsize, const char *s)
Definition: misc.c:9989
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:10148
#define MAX3(x, y, z)
Definition: def.h:213
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:6900
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:6605
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
void SCIPdigraphPrint(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:7883
#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:9356
SCIP_Longint * lbvalues
Definition: struct_misc.h:40
uint32_t shift
Definition: struct_misc.h:83
#define REALABS(x)
Definition: def.h:174
void SCIPactivityFree(SCIP_RESOURCEACTIVITY **activity)
Definition: misc.c:6183
void SCIPrandomSetSeed(SCIP_RANDNUMGEN *randnumgen, unsigned int initseed)
Definition: misc.c:9286
int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
Definition: misc.c:10410
#define DEFAULT_SEED
Definition: misc.c:9279
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:351
#define SCIPhashTwo(a, b)
Definition: pub_misc.h:474
#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:6483
#define LOG2(x)
Definition: def.h:199
SCIP_VAR * h
Definition: circlepacking.c:59
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:6278
Definition: grphload.c:88
static SCIP_RETCODE ensureProfileSize(SCIP_PROFILE *profile, int neededsize)
Definition: misc.c:6419
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:7160
SCIP_Bool SCIPbtnodeIsRightchild(SCIP_BTNODE *node)
Definition: misc.c:8217
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:10507
SCIP_RETCODE SCIPgetRandomSubset(void **set, int nelems, void **subset, int nsubelems, unsigned int randseed)
Definition: misc.c:9729
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:8402
#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:9844
#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:9202
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:8149
public data structures and miscellaneous methods
SCIP_RETCODE SCIPdigraphAddArcSafe(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7188
static const int primetablesize
Definition: misc.c:1344
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7296
#define SCIP_Bool
Definition: def.h:62
#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:9926
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:9317
void ** slots
Definition: struct_misc.h:49
SCIP_Bool SCIPprofileFindLeft(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6396
SCIP_RETCODE SCIPrealarrayFree(SCIP_REALARRAY **realarray)
Definition: misc.c:3655
SCIP_RETCODE SCIPdigraphResize(SCIP_DIGRAPH *digraph, int nnodes)
Definition: misc.c:6932
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:448
void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
Definition: misc.c:9413
static const SCIP_Real simplednoms[]
Definition: misc.c:8721
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10118
static int getRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9213
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:7278
#define MIN(x, y)
Definition: def.h:209
void SCIPbtFree(SCIP_BT **tree)
Definition: misc.c:8310
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2297
SCIP_Bool SCIPbtnodeIsLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8199
SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
Definition: misc.c:8697
#define DEFAULT_CST
Definition: misc.c:9282
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:7763
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:6308
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:9091
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:9233
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:8859
#define BMSclearMemory(ptr)
Definition: memory.h:111
int * SCIPprofileGetTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6350
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:9394
int * SCIPprofileGetLoads(SCIP_PROFILE *profile)
Definition: misc.c:6360
static void depthFirstSearch(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *dfsstack, int *stackadjvisited, int *dfsnodes, int *ndfsnodes)
Definition: misc.c:7346
#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:9255
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2064
SCIP_Bool SCIPbtIsEmpty(SCIP_BT *tree)
Definition: misc.c:8392
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:7654
#define SCIP_REAL_MAX
Definition: def.h:151
SCIP_Real SCIPgetRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9268
SCIP_BTNODE * SCIPbtnodeGetLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8139
static uint32_t hashvalue(uint64_t input)
Definition: misc.c:1348
SCIP_Real * r
Definition: circlepacking.c:50
#define SCIP_LONGINT_FORMAT
Definition: def.h:142
#define EPSGT(x, y, eps)
Definition: def.h:178
#define SQRT(x)
Definition: def.h:192
#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
SCIP_VAR ** b
Definition: circlepacking.c:56
void SCIPbtSetRoot(SCIP_BT *tree, SCIP_BTNODE *root)
Definition: misc.c:8415
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
#define MAX(x, y)
Definition: def.h:208
void SCIPbtnodeSetParent(SCIP_BTNODE *node, SCIP_BTNODE *parent)
Definition: misc.c:8252
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:8431
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:6755
int SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6219
SCIP_BTNODE * right
Definition: struct_misc.h:222
SCIP_RETCODE SCIPdigraphCopy(SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph, BMS_BLKMEM *targetblkmem)
Definition: misc.c:6972
SCIP_RETCODE SCIPboolarrayFree(SCIP_BOOLARRAY **boolarray)
Definition: misc.c:4392
public methods for message output
SCIP_VAR * a
Definition: circlepacking.c:57
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:8881
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:6442
#define SCIP_Real
Definition: def.h:150
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:9661
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:372
SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:3669
SCIP_VAR ** y
Definition: circlepacking.c:55
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:9340
SCIP_RETCODE SCIPrandomGetSubset(SCIP_RANDNUMGEN *randnumgen, void **set, int nelems, void **subset, int nsubelems)
Definition: misc.c:9475
SCIP_Longint SCIPcalcBinomCoef(int n, int m)
Definition: misc.c:9536
#define BMSallocMemory(ptr)
Definition: memory.h:101
#define SCIP_INVALID
Definition: def.h:170
#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:8033
#define SCIP_Longint
Definition: def.h:135
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:8887
static void btPrintSubtree(SCIP_BTNODE *node, FILE *file, int *nnodes)
Definition: misc.c:8326
void SCIPregressionReset(SCIP_REGRESSION *regression)
Definition: misc.c:388
SCIP_RETCODE SCIPdisjointsetCreate(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem, int ncomponents)
Definition: misc.c:10370
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:7109
#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:6812
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:183
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:9619
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:419
SCIP_RETCODE SCIPbtCreate(SCIP_BT **tree, BMS_BLKMEM *blkmem)
Definition: misc.c:8291
#define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
Definition: def.h:382
static SCIP_RETCODE queueResize(SCIP_QUEUE *queue, int minsize)
Definition: misc.c:913
#define SCIP_CALL_ABORT(x)
Definition: def.h:330
int SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6229
void SCIPbtnodeSetData(SCIP_BTNODE *node, void *dataptr)
Definition: misc.c:8238
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:7070
int SCIPprofileGetNTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6340
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:362
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:9975
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8454
void SCIPdigraphPrintGml(SCIP_DIGRAPH *digraph, FILE *file)
Definition: misc.c:7918
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:8362
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:8706
#define EPSZ(x, eps)
Definition: def.h:180
#define ABS(x)
Definition: def.h:204
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:8189
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:10343
void SCIPprofileFree(SCIP_PROFILE **profile)
Definition: misc.c:6292
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:3824