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 2002-2022 Zuse Institute Berlin */
7 /* */
8 /* Licensed under the Apache License, Version 2.0 (the "License"); */
9 /* you may not use this file except in compliance with the License. */
10 /* You may obtain a copy of the License at */
11 /* */
12 /* http://www.apache.org/licenses/LICENSE-2.0 */
13 /* */
14 /* Unless required by applicable law or agreed to in writing, software */
15 /* distributed under the License is distributed on an "AS IS" BASIS, */
16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17 /* See the License for the specific language governing permissions and */
18 /* limitations under the License. */
19 /* */
20 /* You should have received a copy of the Apache-2.0 license */
21 /* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22 /* */
23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24 
25 /**@file misc.c
26  * @ingroup OTHER_CFILES
27  * @brief miscellaneous methods
28  * @author Tobias Achterberg
29  * @author Gerald Gamrath
30  * @author Stefan Heinz
31  * @author Michael Winkler
32  * @author Kati Wolter
33  * @author Gregor Hendel
34  */
35 
36 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37 
38 #include <assert.h>
39 #include <string.h>
40 #include <stdarg.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <errno.h>
44 #include <ctype.h>
45 
46 #include "scip/def.h"
47 #include "scip/pub_message.h"
48 #include "scip/misc.h"
49 #include "scip/intervalarith.h"
50 #include "scip/pub_misc.h"
51 
52 #ifndef NDEBUG
53 #include "scip/struct_misc.h"
54 #endif
55 
56 /*
57  * methods for statistical tests
58  */
59 
60 #define SQRTOFTWO 1.4142136 /**< the square root of 2 with sufficient precision */
61 
62 /**< contains all critical values for a one-sided two sample t-test up to 15 degrees of freedom
63  * a critical value represents a threshold for rejecting the null-hypothesis in hypothesis testing at
64  * a certain confidence level;
65  *
66  * access through method SCIPstudentTGetCriticalValue()
67  *
68  * source: German Wikipedia
69  *
70  * for confidence levels
71  * c =
72  * 0.75 0.875 0.90 0.95 0.975 (one-sided)
73  * 0.50 0.750 0.80 0.90 0.950 (two-sided)
74  *
75  */
76 static const SCIP_Real studentt_quartiles[] = { /* df:*/
77  1.000, 2.414, 3.078, 6.314, 12.706, /* 1 */
78  0.816, 1.604, 1.886, 2.920, 4.303, /* 2 */
79  0.765, 1.423, 1.638, 2.353, 3.182, /* 3 */
80  0.741, 1.344, 1.533, 2.132, 2.776, /* 4 */
81  0.727, 1.301, 1.476, 2.015, 2.571, /* 5 */
82  0.718, 1.273, 1.440, 1.943, 2.447, /* 6 */
83  0.711, 1.254, 1.415, 1.895, 2.365, /* 7 */
84  0.706, 1.240, 1.397, 1.860, 2.306, /* 8 */
85  0.703, 1.230, 1.383, 1.833, 2.262, /* 9 */
86  0.700, 1.221, 1.372, 1.812, 2.228, /* 10 */
87  0.697, 1.214, 1.363, 1.796, 2.201, /* 11 */
88  0.695, 1.209, 1.356, 1.782, 2.179, /* 12 */
89  0.694, 1.204, 1.350, 1.771, 2.160, /* 13 */
90  0.692, 1.200, 1.345, 1.761, 2.145, /* 14 */
91  0.691, 1.197, 1.341, 1.753, 2.131 /* 15 */
92 };
93 
94 /**< critical values for higher degrees of freedom of Student-T distribution for the same error probabilities; infact,
95  * these are critical values of the standard normal distribution with mean 0 and variance 1
96  */
98  0.674, 1.150, 1.282, 1.645, 1.960
99 };
100 
101 /** the maximum degrees of freedom represented before switching to normal approximation */
102 static const int studentt_maxdf = sizeof(studentt_quartiles)/(5 * sizeof(SCIP_Real));
103 
104 /** get critical value of a Student-T distribution for a given number of degrees of freedom at a confidence level */
106  SCIP_CONFIDENCELEVEL clevel, /**< (one-sided) confidence level */
107  int df /**< degrees of freedom */
108  )
109 {
110  if( df > studentt_maxdf )
111  return studentt_quartilesabove[(int)clevel];
112  else
113  return studentt_quartiles[(int)clevel + 5 * (df - 1)];
114 }
115 
116 /** compute a t-value for the hypothesis that x and y are from the same population; Assuming that
117  * x and y represent normally distributed random samples with equal variance, the returned value
118  * comes from a Student-T distribution with countx + county - 2 degrees of freedom; this
119  * value can be compared with a critical value (see also SCIPstudentTGetCriticalValue()) at
120  * a predefined confidence level for checking if x and y significantly differ in location
121  */
123  SCIP_Real meanx, /**< the mean of the first distribution */
124  SCIP_Real meany, /**< the mean of the second distribution */
125  SCIP_Real variancex, /**< the variance of the x-distribution */
126  SCIP_Real variancey, /**< the variance of the y-distribution */
127  SCIP_Real countx, /**< number of samples of x */
128  SCIP_Real county /**< number of samples of y */
129  )
130 {
131  SCIP_Real pooledvariance;
132  SCIP_Real tresult;
133 
134  /* too few samples */
135  if( countx < 1.9 || county < 1.9 )
136  return SCIP_INVALID;
137 
138  /* pooled variance is the weighted average of the two variances */
139  pooledvariance = (countx - 1) * variancex + (county - 1) * variancey;
140  pooledvariance /= (countx + county - 2);
141 
142  /* a variance close to zero means the distributions are basically constant */
143  pooledvariance = MAX(pooledvariance, 1e-9);
144 
145  /* tresult can be understood as realization of a Student-T distributed variable with
146  * countx + county - 2 degrees of freedom
147  */
148  tresult = (meanx - meany) / SQRT(pooledvariance);
149  tresult *= SQRT(countx * county / (countx + county));
150 
151  return tresult;
152 }
153 
154 /** returns the value of the Gauss error function evaluated at a given point */
156  SCIP_Real x /**< value to evaluate */
157  )
158 {
159 #if defined(_WIN32) || defined(_WIN64)
160  SCIP_Real a1, a2, a3, a4, a5, p, t, y;
161  int sign;
162 
163  a1 = 0.254829592;
164  a2 = -0.284496736;
165  a3 = 1.421413741;
166  a4 = -1.453152027;
167  a5 = 1.061405429;
168  p = 0.3275911;
169 
170  sign = (x >= 0) ? 1 : -1;
171  x = REALABS(x);
172 
173  t = 1.0/(1.0 + p*x);
174  y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);
175  return sign * y;
176 #else
177  return erf(x);
178 #endif
179 }
180 
181 /** get critical value of a standard normal distribution at a given confidence level */
183  SCIP_CONFIDENCELEVEL clevel /**< (one-sided) confidence level */
184  )
185 {
186  return studentt_quartilesabove[(int)clevel];
187 }
188 
189 /** calculates the cumulative distribution P(-infinity <= x <= value) that a normally distributed
190  * random variable x takes a value between -infinity and parameter \p value.
191  *
192  * The distribution is given by the respective mean and deviation. This implementation
193  * uses the error function SCIPerf().
194  */
196  SCIP_Real mean, /**< the mean value of the distribution */
197  SCIP_Real variance, /**< the square of the deviation of the distribution */
198  SCIP_Real value /**< the upper limit of the calculated distribution integral */
199  )
200 {
201  SCIP_Real normvalue;
202  SCIP_Real std;
203 
204  /* we need to calculate the standard deviation from the variance */
205  assert(variance >= -1e-9);
206  if( variance < 1e-9 )
207  std = 0.0;
208  else
209  std = sqrt(variance);
210 
211  /* special treatment for zero variance */
212  if( std < 1e-9 )
213  {
214  if( value < mean + 1e-9 )
215  return 1.0;
216  else
217  return 0.0;
218  }
219  assert( std != 0.0 ); /* for lint */
220 
221  /* scale and translate to standard normal distribution. Factor sqrt(2) is needed for SCIPerf() function */
222  normvalue = (value - mean)/(std * SQRTOFTWO);
223 
224  SCIPdebugMessage(" Normalized value %g = ( %g - %g ) / (%g * 1.4142136)\n", normvalue, value, mean, std);
225 
226  /* calculate the cumulative distribution function for normvalue. For negative normvalues, we negate the normvalue and
227  * use the oddness of the SCIPerf()-function; special treatment for values close to zero.
228  */
229  if( normvalue < 1e-9 && normvalue > -1e-9 )
230  return .5;
231  else if( normvalue > 0 )
232  {
233  SCIP_Real erfresult;
234 
235  erfresult = SCIPerf(normvalue);
236  return erfresult / 2.0 + 0.5;
237  }
238  else
239  {
240  SCIP_Real erfresult;
241 
242  erfresult = SCIPerf(-normvalue);
243 
244  return 0.5 - erfresult / 2.0;
245  }
246 }
247 
248 /*
249  * SCIP regression methods
250  */
251 
252 /** returns the number of observations of this regression */
254  SCIP_REGRESSION* regression /**< regression data structure */
255  )
256 {
257  assert(regression != NULL);
258 
259  return regression->nobservations;
260 }
261 
262 /** return the current slope of the regression */
264  SCIP_REGRESSION* regression /**< regression data structure */
265  )
266 {
267  assert(regression != NULL);
268 
269  return regression->slope;
270 }
271 
272 /** get the current y-intercept of the regression */
274  SCIP_REGRESSION* regression /**< regression data structure */
275  )
276 {
277  assert(regression != NULL);
278 
279  return regression->intercept;
280 }
281 
282 /** recomputes regression coefficients from available observation data */
283 static
285  SCIP_REGRESSION* regression /**< regression data structure */
286  )
287 {
288  /* regression coefficients require two or more observations and variance in x */
289  if( regression->nobservations <= 1 || EPSZ(regression->variancesumx, 1e-9) )
290  {
291  regression->slope = SCIP_INVALID;
292  regression->intercept = SCIP_INVALID;
293  regression->corrcoef = SCIP_INVALID;
294  }
295  else if( EPSZ(regression->variancesumy, 1e-9) )
296  {
297  /* 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 */
298  regression->slope = 0.0;
299  regression->corrcoef = 0.0;
300  regression->intercept = regression->meany;
301  }
302  else
303  {
304  /* we ruled this case out already, but to please some compilers... */
305  assert(regression->variancesumx > 0.0);
306  assert(regression->variancesumy > 0.0);
307 
308  /* compute slope */
309  regression->slope = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) / regression->variancesumx;
310 
311  /* compute y-intercept */
312  regression->intercept = regression->meany - regression->slope * regression->meanx;
313 
314  /* compute empirical correlation coefficient */
315  regression->corrcoef = (regression->sumxy - regression->nobservations * regression->meanx * regression->meany) /
316  sqrt(regression->variancesumx * regression->variancesumy);
317  }
318 }
319 
320 /* incremental update of statistics describing mean and variance */
321 static
323  SCIP_Real value, /**< current value to be added to incremental statistics */
324  SCIP_Real* meanptr, /**< pointer to value of current mean */
325  SCIP_Real* sumvarptr, /**< pointer to the value of the current variance sum term */
326  int nobservations, /**< total number of observations */
327  SCIP_Bool add /**< TRUE if the value should be added, FALSE for removing it */
328  )
329 {
330  SCIP_Real oldmean;
331  SCIP_Real addfactor;
332  assert(meanptr != NULL);
333  assert(sumvarptr != NULL);
334  assert(nobservations > 0 || add);
335 
336  addfactor = add ? 1.0 : -1.0;
337 
338  oldmean = *meanptr;
339  *meanptr = oldmean + addfactor * (value - oldmean)/(SCIP_Real)nobservations;
340  *sumvarptr += addfactor * (value - oldmean) * (value - (*meanptr));
341 
342  /* it may happen that *sumvarptr is slightly negative, especially after a series of add/removal operations */
343  assert(*sumvarptr >= -1e-4);
344  *sumvarptr = MAX(0.0, *sumvarptr);
345 }
346 
347 /** removes an observation (x,y) from the regression */
349  SCIP_REGRESSION* regression, /**< regression data structure */
350  SCIP_Real x, /**< X of observation */
351  SCIP_Real y /**< Y of the observation */
352  )
353 {
354  assert(regression != NULL);
355  assert(regression->nobservations > 0);
356 
357  /* simply call the reset function in the case of a single remaining observation to avoid numerical troubles */
358  if( regression->nobservations == 1 )
359  {
360  SCIPregressionReset(regression);
361  }
362  else
363  {
364  SCIP_Bool add = FALSE;
365  --regression->nobservations;
366 
367  /* decrement individual means and variances */
368  incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
369  incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
370 
371  /* decrement product sum */
372  regression->sumxy -= (x * y);
373  }
374 
375  /* recompute regression parameters */
376  regressionRecompute(regression);
377 }
378 
379 /** update regression by a new observation (x,y) */
381  SCIP_REGRESSION* regression, /**< regression data structure */
382  SCIP_Real x, /**< X of observation */
383  SCIP_Real y /**< Y of the observation */
384  )
385 {
386  SCIP_Bool add = TRUE;
387  assert(regression != NULL);
388 
389  ++(regression->nobservations);
390  incrementalStatsUpdate(x, &regression->meanx, &regression->variancesumx, regression->nobservations, add);
391  incrementalStatsUpdate(y, &regression->meany, &regression->variancesumy, regression->nobservations, add);
392 
393  regression->sumxy += x * y;
394 
395  regressionRecompute(regression);
396 }
397 
398 /** reset regression data structure */
400  SCIP_REGRESSION* regression /**< regression data structure */
401  )
402 {
403  regression->intercept = SCIP_INVALID;
404  regression->slope = SCIP_INVALID;
405  regression->corrcoef = SCIP_INVALID;
406  regression->meanx = 0;
407  regression->variancesumx = 0;
408  regression->sumxy = 0;
409  regression->meany = 0;
410  regression->variancesumy = 0;
411  regression->nobservations = 0;
412 }
413 
414 /** creates and resets a regression */
416  SCIP_REGRESSION** regression /**< regression data structure */
417  )
418 {
419  assert(regression != NULL);
420 
421  /* allocate necessary memory */
422  SCIP_ALLOC (BMSallocMemory(regression) );
423 
424  /* reset the regression */
425  SCIPregressionReset(*regression);
426 
427  return SCIP_OKAY;
428 }
429 
430 /** creates and resets a regression */
432  SCIP_REGRESSION** regression /**< regression data structure */
433  )
434 {
435  BMSfreeMemory(regression);
436 }
437 
438 /** calculate memory size for dynamically allocated arrays (copied from scip/set.c) */
439 static
441  int initsize, /**< initial size of array */
442  SCIP_Real growfac, /**< growing factor of array */
443  int num /**< minimum number of entries to store */
444  )
445 {
446  int size;
447 
448  assert(initsize >= 0);
449  assert(growfac >= 1.0);
450  assert(num >= 0);
451 
452  if( growfac == 1.0 )
453  size = MAX(initsize, num);
454  else
455  {
456  int oldsize;
457 
458  /* calculate the size with this loop, such that the resulting numbers are always the same (-> block memory) */
459  initsize = MAX(initsize, 4);
460  size = initsize;
461  oldsize = size - 1;
462 
463  /* second condition checks against overflow */
464  while( size < num && size > oldsize )
465  {
466  oldsize = size;
467  size = (int)(growfac * size + initsize);
468  }
469 
470  /* if an overflow happened, set the correct value */
471  if( size <= oldsize )
472  size = num;
473  }
474 
475  assert(size >= initsize);
476  assert(size >= num);
477 
478  return size;
479 }
480 
481 /*
482  * GML graphical printing methods
483  * For a detailed format decription see http://docs.yworks.com/yfiles/doc/developers-guide/gml.html
484  */
485 
486 #define GMLNODEWIDTH 120.0
487 #define GMLNODEHEIGTH 30.0
488 #define GMLFONTSIZE 13
489 #define GMLNODETYPE "rectangle"
490 #define GMLNODEFILLCOLOR "#ff0000"
491 #define GMLEDGECOLOR "black"
492 #define GMLNODEBORDERCOLOR "#000000"
493 
494 
495 /** writes a node section to the given graph file */
497  FILE* file, /**< file to write to */
498  unsigned int id, /**< id of the node */
499  const char* label, /**< label of the node */
500  const char* nodetype, /**< type of the node, or NULL */
501  const char* fillcolor, /**< color of the node's interior, or NULL */
502  const char* bordercolor /**< color of the node's border, or NULL */
503  )
504 {
505  assert(file != NULL);
506  assert(label != NULL);
507 
508  fprintf(file, " node\n");
509  fprintf(file, " [\n");
510  fprintf(file, " id %u\n", id);
511  fprintf(file, " label \"%s\"\n", label);
512  fprintf(file, " graphics\n");
513  fprintf(file, " [\n");
514  fprintf(file, " w %g\n", GMLNODEWIDTH);
515  fprintf(file, " h %g\n", GMLNODEHEIGTH);
516 
517  if( nodetype != NULL )
518  fprintf(file, " type \"%s\"\n", nodetype);
519  else
520  fprintf(file, " type \"%s\"\n", GMLNODETYPE);
521 
522  if( fillcolor != NULL )
523  fprintf(file, " fill \"%s\"\n", fillcolor);
524  else
525  fprintf(file, " fill \"%s\"\n", GMLNODEFILLCOLOR);
526 
527  if( bordercolor != NULL )
528  fprintf(file, " outline \"%s\"\n", bordercolor);
529  else
530  fprintf(file, " outline \"%s\"\n", GMLNODEBORDERCOLOR);
531 
532  fprintf(file, " ]\n");
533  fprintf(file, " LabelGraphics\n");
534  fprintf(file, " [\n");
535  fprintf(file, " text \"%s\"\n", label);
536  fprintf(file, " fontSize %d\n", GMLFONTSIZE);
537  fprintf(file, " fontName \"Dialog\"\n");
538  fprintf(file, " anchor \"c\"\n");
539  fprintf(file, " ]\n");
540  fprintf(file, " ]\n");
541 }
542 
543 /** writes a node section including weight to the given graph file */
545  FILE* file, /**< file to write to */
546  unsigned int id, /**< id of the node */
547  const char* label, /**< label of the node */
548  const char* nodetype, /**< type of the node, or NULL */
549  const char* fillcolor, /**< color of the node's interior, or NULL */
550  const char* bordercolor, /**< color of the node's border, or NULL */
551  SCIP_Real weight /**< weight of node */
552  )
553 {
554  assert(file != NULL);
555  assert(label != NULL);
556 
557  fprintf(file, " node\n");
558  fprintf(file, " [\n");
559  fprintf(file, " id %u\n", id);
560  fprintf(file, " label \"%s\"\n", label);
561  fprintf(file, " weight %g\n", weight);
562  fprintf(file, " graphics\n");
563  fprintf(file, " [\n");
564  fprintf(file, " w %g\n", GMLNODEWIDTH);
565  fprintf(file, " h %g\n", GMLNODEHEIGTH);
566 
567  if( nodetype != NULL )
568  fprintf(file, " type \"%s\"\n", nodetype);
569  else
570  fprintf(file, " type \"%s\"\n", GMLNODETYPE);
571 
572  if( fillcolor != NULL )
573  fprintf(file, " fill \"%s\"\n", fillcolor);
574  else
575  fprintf(file, " fill \"%s\"\n", GMLNODEFILLCOLOR);
576 
577  if( bordercolor != NULL )
578  fprintf(file, " outline \"%s\"\n", bordercolor);
579  else
580  fprintf(file, " outline \"%s\"\n", GMLNODEBORDERCOLOR);
581 
582  fprintf(file, " ]\n");
583  fprintf(file, " LabelGraphics\n");
584  fprintf(file, " [\n");
585  fprintf(file, " text \"%s\"\n", label);
586  fprintf(file, " fontSize %d\n", GMLFONTSIZE);
587  fprintf(file, " fontName \"Dialog\"\n");
588  fprintf(file, " anchor \"c\"\n");
589  fprintf(file, " ]\n");
590  fprintf(file, " ]\n");
591 }
592 
593 /** writes an edge section to the given graph file */
595  FILE* file, /**< file to write to */
596  unsigned int source, /**< source node id of the node */
597  unsigned int target, /**< target node id of the edge */
598  const char* label, /**< label of the edge, or NULL */
599  const char* color /**< color of the edge, or NULL */
600  )
601 {
602  assert(file != NULL);
603 
604  fprintf(file, " edge\n");
605  fprintf(file, " [\n");
606  fprintf(file, " source %u\n", source);
607  fprintf(file, " target %u\n", target);
608 
609  if( label != NULL)
610  fprintf(file, " label \"%s\"\n", label);
611 
612  fprintf(file, " graphics\n");
613  fprintf(file, " [\n");
614 
615  if( color != NULL )
616  fprintf(file, " fill \"%s\"\n", color);
617  else
618  fprintf(file, " fill \"%s\"\n", GMLEDGECOLOR);
619 
620  /* fprintf(file, " arrow \"both\"\n"); */
621  fprintf(file, " ]\n");
622 
623  if( label != NULL)
624  {
625  fprintf(file, " LabelGraphics\n");
626  fprintf(file, " [\n");
627  fprintf(file, " text \"%s\"\n", label);
628  fprintf(file, " fontSize %d\n", GMLFONTSIZE);
629  fprintf(file, " fontName \"Dialog\"\n");
630  fprintf(file, " anchor \"c\"\n");
631  fprintf(file, " ]\n");
632  }
633 
634  fprintf(file, " ]\n");
635 }
636 
637 /** writes an arc section to the given graph file */
639  FILE* file, /**< file to write to */
640  unsigned int source, /**< source node id of the node */
641  unsigned int target, /**< target node id of the edge */
642  const char* label, /**< label of the edge, or NULL */
643  const char* color /**< color of the edge, or NULL */
644  )
645 {
646  assert(file != NULL);
647 
648  fprintf(file, " edge\n");
649  fprintf(file, " [\n");
650  fprintf(file, " source %u\n", source);
651  fprintf(file, " target %u\n", target);
652 
653  if( label != NULL)
654  fprintf(file, " label \"%s\"\n", label);
655 
656  fprintf(file, " graphics\n");
657  fprintf(file, " [\n");
658 
659  if( color != NULL )
660  fprintf(file, " fill \"%s\"\n", color);
661  else
662  fprintf(file, " fill \"%s\"\n", GMLEDGECOLOR);
663 
664  fprintf(file, " targetArrow \"standard\"\n");
665  fprintf(file, " ]\n");
666 
667  if( label != NULL)
668  {
669  fprintf(file, " LabelGraphics\n");
670  fprintf(file, " [\n");
671  fprintf(file, " text \"%s\"\n", label);
672  fprintf(file, " fontSize %d\n", GMLFONTSIZE);
673  fprintf(file, " fontName \"Dialog\"\n");
674  fprintf(file, " anchor \"c\"\n");
675  fprintf(file, " ]\n");
676  }
677 
678  fprintf(file, " ]\n");
679 }
680 
681 /** writes the starting line to a GML graph file, does not open a file */
683  FILE* file, /**< file to write to */
684  SCIP_Bool directed /**< is the graph directed */
685  )
686 {
687  assert(file != NULL);
688 
689  fprintf(file, "graph\n");
690  fprintf(file, "[\n");
691  fprintf(file, " hierarchic 1\n");
692 
693  if( directed )
694  fprintf(file, " directed 1\n");
695 }
696 
697 /** writes the ending lines to a GML graph file, does not close a file */
699  FILE* file /**< file to close */
700  )
701 {
702  assert(file != NULL);
703 
704  fprintf(file, "]\n");
705 }
706 
707 
708 /*
709  * Sparse solution
710  */
711 
712 /** creates a sparse solution */
714  SCIP_SPARSESOL** sparsesol, /**< pointer to store the created sparse solution */
715  SCIP_VAR** vars, /**< variables in the sparse solution, must not contain continuous
716  * variables
717  */
718  int nvars, /**< number of variables to store, size of the lower and upper bound
719  * arrays
720  */
721  SCIP_Bool cleared /**< should the lower and upper bound arrays be cleared (entries set to
722  * 0)
723  */
724  )
725 {
726  assert(sparsesol != NULL);
727  assert(vars != NULL);
728  assert(nvars >= 0);
729 
730  SCIP_ALLOC( BMSallocMemory(sparsesol) );
731 
732 #ifndef NDEBUG
733  {
734  int v;
735 
736  for( v = nvars - 1; v >= 0; --v )
737  {
738  assert(vars[v] != NULL);
739  /* assert(SCIPvarGetType(vars[v]) != SCIP_VARTYPE_CONTINUOUS); */
740  }
741  }
742 #endif
743 
744  /* copy variables */
745  SCIP_ALLOC( BMSduplicateMemoryArray(&((*sparsesol)->vars), vars, nvars) );
746 
747  /* create bound arrays */
748  if( cleared )
749  {
750  SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->lbvalues), nvars) );
751  SCIP_ALLOC( BMSallocClearMemoryArray(&((*sparsesol)->ubvalues), nvars) );
752  }
753  else
754  {
755  SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->lbvalues), nvars) );
756  SCIP_ALLOC( BMSallocMemoryArray(&((*sparsesol)->ubvalues), nvars) );
757  }
758 
759  (*sparsesol)->nvars = nvars;
760 
761  return SCIP_OKAY;
762 }
763 
764 /** frees sparse solution */
766  SCIP_SPARSESOL** sparsesol /**< pointer to a sparse solution */
767  )
768 {
769  assert(sparsesol != NULL);
770  assert(*sparsesol != NULL);
771 
772  BMSfreeMemoryArray(&((*sparsesol)->vars));
773  BMSfreeMemoryArray(&((*sparsesol)->ubvalues));
774  BMSfreeMemoryArray(&((*sparsesol)->lbvalues));
775  BMSfreeMemory(sparsesol);
776 }
777 
778 /** returns the variables stored in the given sparse solution */
780  SCIP_SPARSESOL* sparsesol /**< a sparse solution */
781  )
782 {
783  assert(sparsesol != NULL);
784 
785  return sparsesol->vars;
786 }
787 
788 /** returns the number of variables stored in the given sparse solution */
790  SCIP_SPARSESOL* sparsesol /**< a sparse solution */
791  )
792 {
793  assert(sparsesol != NULL);
794 
795  return sparsesol->nvars;
796 }
797 
798 /** returns the lower bound array for all variables for a given sparse solution */
800  SCIP_SPARSESOL* sparsesol /**< a sparse solution */
801  )
802 {
803  assert(sparsesol != NULL);
804 
805  return sparsesol->lbvalues;
806 }
807 
808 /** returns the upper bound array for all variables for a given sparse solution */
810  SCIP_SPARSESOL* sparsesol /**< a sparse solution */
811  )
812 {
813  assert(sparsesol != NULL);
814 
815  return sparsesol->ubvalues;
816 }
817 
818 /** constructs the first solution of sparse solution (all variables are set to their lower bound value */
820  SCIP_SPARSESOL* sparsesol, /**< sparse solutions */
821  SCIP_Longint* sol, /**< array to store the first solution */
822  int nvars /**< number of variables */
823  )
824 {
825  SCIP_Longint* lbvalues;
826  int v;
827 
828  assert(sparsesol != NULL);
829  assert(sol != NULL);
830  assert(nvars == SCIPsparseSolGetNVars(sparsesol));
831 
832  lbvalues = SCIPsparseSolGetLbs(sparsesol);
833  assert(lbvalues != NULL);
834 
835  /* copy the lower bounds */
836  for( v = 0; v < nvars; ++v )
837  sol[v] = lbvalues[v];
838 }
839 
840 
841 /** constructs the next solution of the sparse solution and return whether there was one more or not */
843  SCIP_SPARSESOL* sparsesol, /**< sparse solutions */
844  SCIP_Longint* sol, /**< current solution array which get changed to the next solution */
845  int nvars /**< number of variables */
846  )
847 {
848  SCIP_Longint* lbvalues;
849  SCIP_Longint* ubvalues;
850  SCIP_Longint lbvalue;
851  SCIP_Longint ubvalue;
852  SCIP_Bool singular;
853  SCIP_Bool carryflag;
854  int v;
855 
856  assert(sparsesol != NULL);
857  assert(sol != NULL);
858 
859  if( nvars == 0 )
860  return FALSE;
861 
862  assert(nvars > 0);
863  assert(nvars == SCIPsparseSolGetNVars(sparsesol));
864 
865  lbvalues = SCIPsparseSolGetLbs(sparsesol);
866  ubvalues = SCIPsparseSolGetUbs(sparsesol);
867  assert(lbvalues != NULL);
868  assert(ubvalues != NULL);
869 
870  singular = TRUE;
871  carryflag = FALSE;
872 
873  for( v = 0; v < nvars; ++v )
874  {
875  lbvalue = lbvalues[v];
876  ubvalue = ubvalues[v];
877 
878  if( lbvalue < ubvalue )
879  {
880  singular = FALSE;
881 
882  if( carryflag == FALSE )
883  {
884  if( sol[v] < ubvalue )
885  {
886  sol[v]++;
887  break;
888  }
889  else
890  {
891  /* in the last solution the variables v was set to its upper bound value */
892  assert(sol[v] == ubvalue);
893  sol[v] = lbvalue;
894  carryflag = TRUE;
895  }
896  }
897  else
898  {
899  if( sol[v] < ubvalue )
900  {
901  sol[v]++;
902  carryflag = FALSE;
903  break;
904  }
905  else
906  {
907  assert(sol[v] == ubvalue);
908  sol[v] = lbvalue;
909  }
910  }
911  }
912  }
913 
914  return (!carryflag && !singular);
915 }
916 
917 
918 /*
919  * Queue
920  */
921 
922 /** resizes element memory to hold at least the given number of elements */
923 static
925  SCIP_QUEUE* queue, /**< pointer to a queue */
926  int minsize /**< minimal number of storable elements */
927  )
928 {
929  assert(queue != NULL);
930  assert(minsize > 0);
931 
932  if( minsize <= queue->size )
933  return SCIP_OKAY;
934 
935  queue->size = MAX(minsize, (int)(queue->size * queue->sizefac));
936  SCIP_ALLOC( BMSreallocMemoryArray(&queue->slots, queue->size) );
937 
938  return SCIP_OKAY;
939 }
940 
941 
942 /** creates a (circular) queue, best used if the size will be fixed or will not be increased that much */
944  SCIP_QUEUE** queue, /**< pointer to the new queue */
945  int initsize, /**< initial number of available element slots */
946  SCIP_Real sizefac /**< memory growing factor applied, if more element slots are needed */
947  )
948 {
949  assert(queue != NULL);
950 
951  initsize = MAX(1, initsize);
952  sizefac = MAX(1.0, sizefac);
953 
954  SCIP_ALLOC( BMSallocMemory(queue) );
955  (*queue)->firstfree = 0;
956  (*queue)->firstused = -1;
957  (*queue)->size = 0;
958  (*queue)->sizefac = sizefac;
959  (*queue)->slots = NULL;
960 
961  SCIP_CALL( queueResize(*queue, initsize) );
962 
963  return SCIP_OKAY;
964 }
965 
966 /** frees queue, but not the data elements themselves */
968  SCIP_QUEUE** queue /**< pointer to a queue */
969  )
970 {
971  assert(queue != NULL);
972 
973  BMSfreeMemoryArray(&(*queue)->slots);
974  BMSfreeMemory(queue);
975 }
976 
977 /** clears the queue, but doesn't free the data elements themselves */
979  SCIP_QUEUE* queue /**< queue */
980  )
981 {
982  assert(queue != NULL);
983 
984  queue->firstfree = 0;
985  queue->firstused = -1;
986 }
987 
988 /** reallocates slots if queue is necessary */
989 static
991  SCIP_QUEUE* queue /**< queue */
992  )
993 {
994  if( queue->firstfree == queue->firstused )
995  {
996  int sizediff;
997  int oldsize = queue->size;
998 
999  SCIP_CALL( queueResize(queue, queue->size+1) );
1000  assert(oldsize < queue->size);
1001 
1002  sizediff = queue->size - oldsize;
1003 
1004  /* move the used memory at the slots to the end */
1005  BMSmoveMemoryArray(&(queue->slots[queue->firstused + sizediff]), &(queue->slots[queue->firstused]), oldsize - queue->firstused); /*lint !e866*/
1006  queue->firstused += sizediff;
1007  }
1008  assert(queue->firstfree != queue->firstused);
1009 
1010  return SCIP_OKAY;
1011 }
1012 
1013 /** checks and adjusts marker of first free and first used slot */
1014 static
1016  SCIP_QUEUE* queue /**< queue */
1017  )
1018 {
1019  /* if we saved the value at the last position we need to reset the firstfree position */
1020  if( queue->firstfree == queue->size )
1021  queue->firstfree = 0;
1022 
1023  /* if a first element was added, we need to update the firstused counter */
1024  if( queue->firstused == -1 )
1025  queue->firstused = 0;
1026 }
1027 
1028 /** inserts pointer element at the end of the queue */
1030  SCIP_QUEUE* queue, /**< queue */
1031  void* elem /**< element to be inserted */
1032  )
1033 {
1034  assert(queue != NULL);
1035  assert(queue->slots != NULL);
1036  assert(queue->firstused >= -1 && queue->firstused < queue->size);
1037  assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1038  assert(queue->firstused > -1 || queue->firstfree == 0);
1039  assert(elem != NULL);
1040 
1041  /* check allocated memory */
1042  SCIP_CALL( queueCheckSize(queue) );
1043 
1044  /* insert element at the first free slot */
1045  queue->slots[queue->firstfree].ptr = elem;
1046  ++(queue->firstfree);
1047 
1048  /* check and adjust marker */
1049  queueCheckMarker(queue);
1050 
1051  return SCIP_OKAY;
1052 }
1053 
1054 /** inserts unsigned integer element at the end of the queue */
1056  SCIP_QUEUE* queue, /**< queue */
1057  unsigned int elem /**< element to be inserted */
1058  )
1059 {
1060  assert(queue != NULL);
1061  assert(queue->slots != NULL);
1062  assert(queue->firstused >= -1 && queue->firstused < queue->size);
1063  assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1064  assert(queue->firstused > -1 || queue->firstfree == 0);
1065 
1066  /* check allocated memory */
1067  SCIP_CALL( queueCheckSize(queue) );
1068 
1069  /* insert element at the first free slot */
1070  queue->slots[queue->firstfree].uinteger = elem;
1071  ++(queue->firstfree);
1072 
1073  /* check and adjust marker */
1074  queueCheckMarker(queue);
1075 
1076  return SCIP_OKAY;
1077 }
1078 
1079 /** removes and returns the first pointer element of the queue, or NULL if no element exists */
1081  SCIP_QUEUE* queue /**< queue */
1082  )
1083 {
1084  int pos;
1085 
1086  assert(queue != NULL);
1087  assert(queue->firstused >= -1 && queue->firstused < queue->size);
1088  assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1089  assert(queue->firstused > -1 || queue->firstfree == 0);
1090 
1091  if( queue->firstused == -1 )
1092  return NULL;
1093 
1094  assert(queue->slots != NULL);
1095 
1096  pos = queue->firstused;
1097  ++(queue->firstused);
1098 
1099  /* if we removed the value at the last position we need to reset the firstused position */
1100  if( queue->firstused == queue->size )
1101  queue->firstused = 0;
1102 
1103  /* if we reached the first free position we can reset both, firstused and firstused, positions */
1104  if( queue->firstused == queue->firstfree )
1105  {
1106  queue->firstused = -1;
1107  queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
1108  }
1109 
1110  return (queue->slots[pos].ptr);
1111 }
1112 
1113 /** removes and returns the first unsigned integer element of the queue, or UINT_MAX if no element exists */
1114 unsigned int SCIPqueueRemoveUInt(
1115  SCIP_QUEUE* queue /**< queue */
1116  )
1117 {
1118  int pos;
1119 
1120  assert(queue != NULL);
1121  assert(queue->firstused >= -1 && queue->firstused < queue->size);
1122  assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1123  assert(queue->firstused > -1 || queue->firstfree == 0);
1124 
1125  if( queue->firstused == -1 )
1126  return UINT_MAX;
1127 
1128  assert(queue->slots != NULL);
1129 
1130  pos = queue->firstused;
1131  ++(queue->firstused);
1132 
1133  /* if we removed the value at the last position we need to reset the firstused position */
1134  if( queue->firstused == queue->size )
1135  queue->firstused = 0;
1136 
1137  /* if we reached the first free position we can reset both, firstused and firstused, positions */
1138  if( queue->firstused == queue->firstfree )
1139  {
1140  queue->firstused = -1;
1141  queue->firstfree = 0; /* this is not necessary but looks better if we have an empty list to reset this value */
1142  }
1143 
1144  return (queue->slots[pos].uinteger);
1145 }
1146 
1147 /** returns the first element of the queue without removing it, or NULL if no element exists */
1149  SCIP_QUEUE* queue /**< queue */
1150  )
1151 {
1152  assert(queue != NULL);
1153  assert(queue->firstused >= -1 && queue->firstused < queue->size);
1154  assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1155  assert(queue->firstused > -1 || queue->firstfree == 0);
1156 
1157  if( queue->firstused == -1 )
1158  return NULL;
1159 
1160  assert(queue->slots != NULL);
1161 
1162  return queue->slots[queue->firstused].ptr;
1163 }
1164 
1165 /** returns the first unsigned integer element of the queue without removing it, or UINT_MAX if no element exists */
1166 unsigned int SCIPqueueFirstUInt(
1167  SCIP_QUEUE* queue /**< queue */
1168  )
1169 {
1170  assert(queue != NULL);
1171  assert(queue->firstused >= -1 && queue->firstused < queue->size);
1172  assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1173  assert(queue->firstused > -1 || queue->firstfree == 0);
1174 
1175  if( queue->firstused == -1 )
1176  return UINT_MAX;
1177 
1178  assert(queue->slots != NULL);
1179 
1180  return queue->slots[queue->firstused].uinteger;
1181 }
1182 
1183 /** returns whether the queue is empty */
1185  SCIP_QUEUE* queue /**< queue */
1186  )
1187 {
1188  assert(queue != NULL);
1189  assert(queue->firstused >= -1 && queue->firstused < queue->size);
1190  assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1191  assert(queue->firstused > -1 || queue->firstfree == 0);
1192 
1193  return (queue->firstused == -1);
1194 }
1195 
1196 /** returns the number of elements in the queue */
1198  SCIP_QUEUE* queue /**< queue */
1199  )
1200 {
1201  assert(queue != NULL);
1202  assert(queue->firstused >= -1 && queue->firstused < queue->size);
1203  assert(queue->firstfree >= 0 && queue->firstused < queue->size);
1204  assert(queue->firstused > -1 || queue->firstfree == 0);
1205 
1206  if( queue->firstused == -1 )
1207  return 0;
1208  else if( queue->firstused < queue->firstfree )
1209  return queue->firstfree - queue->firstused;
1210  else if( queue->firstused == queue->firstfree )
1211  return queue->size;
1212  else
1213  return queue->firstfree + (queue->size - queue->firstused);
1214 }
1215 
1216 
1217 /*
1218  * Priority Queue
1219  */
1220 
1221 #define PQ_PARENT(q) (((q)+1)/2-1)
1222 #define PQ_LEFTCHILD(p) (2*(p)+1)
1223 #define PQ_RIGHTCHILD(p) (2*(p)+2)
1224 
1225 
1226 /** resizes element memory to hold at least the given number of elements */
1227 static
1229  SCIP_PQUEUE* pqueue, /**< pointer to a priority queue */
1230  int minsize /**< minimal number of storable elements */
1231  )
1232 {
1233  assert(pqueue != NULL);
1234 
1235  if( minsize <= pqueue->size )
1236  return SCIP_OKAY;
1237 
1238  pqueue->size = MAX(minsize, (int)(pqueue->size * pqueue->sizefac));
1239  SCIP_ALLOC( BMSreallocMemoryArray(&pqueue->slots, pqueue->size) );
1240 
1241  return SCIP_OKAY;
1242 }
1243 
1244 /** creates priority queue */
1246  SCIP_PQUEUE** pqueue, /**< pointer to a priority queue */
1247  int initsize, /**< initial number of available element slots */
1248  SCIP_Real sizefac, /**< memory growing factor applied, if more element slots are needed */
1249  SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
1250  SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)) /**< callback to act on position change of elem in priority queue, or NULL */
1251  )
1252 {
1253  assert(pqueue != NULL);
1254  assert(ptrcomp != NULL);
1255 
1256  initsize = MAX(1, initsize);
1257  sizefac = MAX(1.0, sizefac);
1258 
1259  SCIP_ALLOC( BMSallocMemory(pqueue) );
1260  (*pqueue)->len = 0;
1261  (*pqueue)->size = 0;
1262  (*pqueue)->sizefac = sizefac;
1263  (*pqueue)->slots = NULL;
1264  (*pqueue)->ptrcomp = ptrcomp;
1265  (*pqueue)->elemchgpos = elemchgpos;
1266  SCIP_CALL( pqueueResize(*pqueue, initsize) );
1267 
1268  return SCIP_OKAY;
1269 }
1270 
1271 /** frees priority queue, but not the data elements themselves */
1273  SCIP_PQUEUE** pqueue /**< pointer to a priority queue */
1274  )
1275 {
1276  assert(pqueue != NULL);
1277 
1278  BMSfreeMemoryArray(&(*pqueue)->slots);
1279  BMSfreeMemory(pqueue);
1280 }
1281 
1282 /** clears the priority queue, but doesn't free the data elements themselves */
1284  SCIP_PQUEUE* pqueue /**< priority queue */
1285  )
1286 {
1287  assert(pqueue != NULL);
1288 
1289  pqueue->len = 0;
1290 }
1291 
1292 /** assign element to new slot in priority queue */
1293 static
1295  SCIP_PQUEUE* pqueue, /**< priority queue */
1296  void* elem, /**< element whose position changes */
1297  int oldpos, /**< old position or -1 if elem is newly inserted */
1298  int newpos /**< new position */
1299  )
1300 {
1301  pqueue->slots[newpos] = elem;
1302 
1303  /* act on position change */
1304  if( pqueue->elemchgpos != NULL )
1305  {
1306  pqueue->elemchgpos(elem, oldpos, newpos);
1307  }
1308 }
1309 
1310 #ifdef SCIP_MORE_DEBUG
1311 /** ensure that the priority queue still has the heap property */
1312 static
1313 SCIP_Bool pqueueHasHeapProperty(
1314  SCIP_PQUEUE* pqueue /**< priority queue */
1315  )
1316 {
1317  int i;
1318 
1319  if( SCIPpqueueNElems(pqueue) == 0 )
1320  return TRUE;
1321 
1322  /* check local heap property between parents and children */
1323  for( i = 0; i < SCIPpqueueNElems(pqueue); ++i )
1324  {
1325  if( i > 0 && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[PQ_PARENT(i)]) < 0 )
1326  return FALSE;
1327  if( i < PQ_PARENT(SCIPpqueueNElems(pqueue)) )
1328  {
1329  int leftchild = PQ_LEFTCHILD(i);
1330  int rightchild = PQ_RIGHTCHILD(i);
1331  assert(leftchild < SCIPpqueueNElems(pqueue));
1332  assert(rightchild <= SCIPpqueueNElems(pqueue));
1333  if( pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[leftchild]) > 0 )
1334  return FALSE;
1335  if( rightchild < SCIPpqueueNElems(pqueue) && pqueue->ptrcomp(pqueue->slots[i], pqueue->slots[rightchild]) > 0)
1336  return FALSE;
1337  }
1338  }
1339  return TRUE;
1340 }
1341 #endif
1342 
1343 /** inserts element into priority queue */
1345  SCIP_PQUEUE* pqueue, /**< priority queue */
1346  void* elem /**< element to be inserted */
1347  )
1348 {
1349  int pos;
1350  int parentpos;
1351 
1352  assert(pqueue != NULL);
1353  assert(pqueue->len >= 0);
1354  assert(elem != NULL);
1355 
1356  SCIP_CALL( pqueueResize(pqueue, pqueue->len+1) );
1357 
1358  /* insert element as leaf in the tree, move it towards the root as long it is better than its parent */
1359  pos = pqueue->len;
1360  pqueue->len++;
1361  parentpos = PQ_PARENT(pos);
1362  while( pos > 0 && (*pqueue->ptrcomp)(elem, pqueue->slots[parentpos]) < 0 )
1363  {
1364  assert((*pqueue->ptrcomp)(pqueue->slots[parentpos], elem) >= 0);
1365  pqueueElemChgPos(pqueue, pqueue->slots[parentpos], parentpos, pos);
1366 
1367  pos = parentpos;
1368  parentpos = PQ_PARENT(pos);
1369  }
1370 
1371  /* insert element at the found position */
1372  pqueueElemChgPos(pqueue, elem, -1, pos);
1373 
1374 #ifdef SCIP_MORE_DEBUG
1375  assert(pqueueHasHeapProperty(pqueue));
1376 #endif
1377 
1378  return SCIP_OKAY;
1379 }
1380 
1381 
1382 /** delete element at specified position, maintaining the heap property */
1384  SCIP_PQUEUE* pqueue, /**< priority queue */
1385  int pos /**< position of element that should be deleted */
1386  )
1387 {
1388  void* last;
1389 
1390  assert(pqueue != NULL);
1391  assert(pos >= 0);
1392  assert(pos < SCIPpqueueNElems(pqueue));
1393 
1394  /* remove element at specified position of the tree, move the better child to its parents position until the last element
1395  * of the queue could be placed in the empty slot
1396  */
1397  pqueue->len--;
1398 
1399  /* everything in place */
1400  if( pos == pqueue->len )
1401  return;
1402 
1403  last = pqueue->slots[pqueue->len];
1404 
1405  /* last element is brought to pos. it may now violate the heap property compared to its parent, or to its children.
1406  * In the first case, move it up, otherwise, move it down.
1407  */
1408  while( pos > 0 && (*pqueue->ptrcomp)(last, pqueue->slots[PQ_PARENT(pos)]) < 0 )
1409  {
1410  pqueueElemChgPos(pqueue, pqueue->slots[PQ_PARENT(pos)], PQ_PARENT(pos), pos);
1411  pos = PQ_PARENT(pos);
1412  }
1413 
1414  while( pos <= PQ_PARENT(pqueue->len-1) )
1415  {
1416  int childpos = PQ_LEFTCHILD(pos);
1417  int brotherpos = PQ_RIGHTCHILD(pos);
1418 
1419  /* determine better of the two children */
1420  if( brotherpos < pqueue->len && (*pqueue->ptrcomp)(pqueue->slots[brotherpos], pqueue->slots[childpos]) < 0 )
1421  childpos = brotherpos;
1422 
1423  if( (*pqueue->ptrcomp)(last, pqueue->slots[childpos]) <= 0 )
1424  break;
1425 
1426  /* move better element from childpos to pos */
1427  pqueueElemChgPos(pqueue, pqueue->slots[childpos], childpos, pos);
1428 
1429  pos = childpos;
1430  }
1431 
1432  /* pos must point into a valid position */
1433  assert(pos <= pqueue->len - 1);
1434 
1435  pqueueElemChgPos(pqueue, last, pqueue->len, pos);
1436 
1437 #ifdef SCIP_MORE_DEBUG
1438  assert(pqueueHasHeapProperty(pqueue));
1439 #endif
1440 }
1441 
1442 /** removes and returns best element from the priority queue */
1444  SCIP_PQUEUE* pqueue /**< priority queue */
1445  )
1446 {
1447  void* root;
1448 
1449  assert(pqueue != NULL);
1450  assert(pqueue->len >= 0);
1451 
1452  if( pqueue->len == 0 )
1453  return NULL;
1454 
1455  root = pqueue->slots[0];
1456 
1457  SCIPpqueueDelPos(pqueue, 0);
1458 
1459  return root;
1460 }
1461 
1462 /** returns the best element of the queue without removing it */
1464  SCIP_PQUEUE* pqueue /**< priority queue */
1465  )
1466 {
1467  assert(pqueue != NULL);
1468  assert(pqueue->len >= 0);
1469 
1470  if( pqueue->len == 0 )
1471  return NULL;
1472 
1473  return pqueue->slots[0];
1474 }
1475 
1476 /** returns the number of elements in the queue */
1478  SCIP_PQUEUE* pqueue /**< priority queue */
1479  )
1480 {
1481  assert(pqueue != NULL);
1482  assert(pqueue->len >= 0);
1483 
1484  return pqueue->len;
1485 }
1486 
1487 /** returns the elements of the queue; changing the returned array may destroy the queue's ordering! */
1489  SCIP_PQUEUE* pqueue /**< priority queue */
1490  )
1491 {
1492  assert(pqueue != NULL);
1493  assert(pqueue->len >= 0);
1494 
1495  return pqueue->slots;
1496 }
1497 
1498 /** return the position of @p elem in the priority queue, or -1 if element is not found */
1500  SCIP_PQUEUE* pqueue, /**< priority queue */
1501  void* elem /**< element to be inserted */
1502  )
1503 {
1504  int pos = -1;
1505 
1506  while( ++pos < SCIPpqueueNElems(pqueue) )
1507  {
1508  if( pqueue->slots[pos] == elem )
1509  return pos;
1510  }
1511 
1512  return -1;
1513 }
1514 
1515 
1516 
1517 
1518 /*
1519  * Hash Table
1520  */
1521 
1522 /** table of some prime numbers */
1523 static int primetable[] = {
1524  2,
1525  7,
1526  19,
1527  31,
1528  59,
1529  227,
1530  617,
1531  1523,
1532  3547,
1533  8011,
1534  17707,
1535  38723,
1536  83833,
1537  180317,
1538  385897,
1539  821411,
1540  1742369,
1541  3680893,
1542  5693959,
1543  7753849,
1544  9849703,
1545  11973277,
1546  14121853,
1547  17643961,
1548  24273817,
1549  32452843,
1550  49979687,
1551  67867967,
1552  86028121,
1553  104395301,
1554  122949823,
1555  141650939,
1556  160481183,
1557  179424673,
1558  198491317,
1559  217645177,
1560  256203161,
1561  314606869,
1562  373587883,
1563  433024223,
1564  492876847,
1565  553105243,
1566  613651349,
1567  694847533,
1568  756065159,
1569  817504243,
1570  879190747,
1571  941083981,
1572  982451653,
1573  INT_MAX
1574 };
1575 static const int primetablesize = sizeof(primetable)/sizeof(int);
1576 
1577 /** simple and fast 2-universal hash function using multiply and shift */
1578 static
1579 uint32_t hashvalue(
1580  uint64_t input /**< key value */
1581  )
1582 {
1583  return ( (uint32_t) ((UINT64_C(0x9e3779b97f4a7c15) * input)>>32) ) | 1u;
1584 }
1585 
1586 /** returns a reasonable hash table size (a prime number) that is at least as large as the specified value */
1588  int minsize /**< minimal size of the hash table */
1589  )
1590 {
1591  int pos;
1592 
1593  (void) SCIPsortedvecFindInt(primetable, minsize, primetablesize, &pos);
1594  assert(0 <= pos && pos < primetablesize);
1595 
1596  return primetable[pos];
1597 }
1598 
1599 /** appends element to the multihash list */
1600 static
1602  SCIP_MULTIHASHLIST** multihashlist, /**< pointer to hash list */
1603  BMS_BLKMEM* blkmem, /**< block memory */
1604  void* element /**< element to append to the list */
1605  )
1606 {
1607  SCIP_MULTIHASHLIST* newlist;
1608 
1609  assert(multihashlist != NULL);
1610  assert(blkmem != NULL);
1611  assert(element != NULL);
1612 
1613  SCIP_ALLOC( BMSallocBlockMemory(blkmem, &newlist) );
1614  newlist->element = element;
1615  newlist->next = *multihashlist;
1616  *multihashlist = newlist;
1617 
1618  return SCIP_OKAY;
1619 }
1620 
1621 /** frees a multihash list entry and all its successors */
1622 static
1624  SCIP_MULTIHASHLIST** multihashlist, /**< pointer to multihash list to free */
1625  BMS_BLKMEM* blkmem /**< block memory */
1626  )
1627 {
1628  SCIP_MULTIHASHLIST* list;
1629  SCIP_MULTIHASHLIST* nextlist;
1630 
1631  assert(multihashlist != NULL);
1632  assert(blkmem != NULL);
1633 
1634  list = *multihashlist;
1635  while( list != NULL )
1636  {
1637  nextlist = list->next;
1638  BMSfreeBlockMemory(blkmem, &list);
1639  list = nextlist;
1640  }
1641 
1642  *multihashlist = NULL;
1643 }
1644 
1645 /** finds multihash list entry pointing to element with given key in the multihash list, returns NULL if not found */
1646 static
1648  SCIP_MULTIHASHLIST* multihashlist, /**< multihash list */
1649  SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1650  SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1651  SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1652  void* userptr, /**< user pointer */
1653  uint64_t keyval, /**< hash value of key */
1654  void* key /**< key to retrieve */
1655  )
1656 {
1657  uint64_t currentkeyval;
1658  void* currentkey;
1659 
1660  assert(hashkeyeq != NULL);
1661  assert(key != NULL);
1662 
1663  while( multihashlist != NULL )
1664  {
1665  currentkey = hashgetkey(userptr, multihashlist->element);
1666  currentkeyval = hashkeyval(userptr, currentkey);
1667  if( currentkeyval == keyval && hashkeyeq(userptr, currentkey, key) )
1668  return multihashlist;
1669 
1670  multihashlist = multihashlist->next;
1671  }
1672 
1673  return NULL;
1674 }
1675 
1676 /** retrieves element with given key from the multihash list, or NULL */
1677 static
1679  SCIP_MULTIHASHLIST* multihashlist, /**< hash list */
1680  SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1681  SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1682  SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1683  void* userptr, /**< user pointer */
1684  uint64_t keyval, /**< hash value of key */
1685  void* key /**< key to retrieve */
1686  )
1687 {
1689 
1690  /* find hash list entry */
1691  h = multihashlistFind(multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1692 
1693  /* return element */
1694  if( h != NULL )
1695  {
1696 #ifndef NDEBUG
1697  SCIP_MULTIHASHLIST* h2;
1698 
1699  h2 = multihashlistFind(h->next, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1700 
1701  if( h2 != NULL )
1702  {
1703  void* key1;
1704  void* key2;
1705 
1706  key1 = hashgetkey(userptr, h->element);
1707  key2 = hashgetkey(userptr, h2->element);
1708  assert(hashkeyval(userptr, key1) == hashkeyval(userptr, key2));
1709 
1710  if( hashkeyeq(userptr, key1, key2) )
1711  {
1712  SCIPerrorMessage("WARNING: hashkey with same value exists multiple times (e.g. duplicate constraint/variable names), so the return value is maybe not correct\n");
1713  }
1714  }
1715 #endif
1716 
1717  return h->element;
1718  }
1719  else
1720  return NULL;
1721 }
1722 
1723 
1724 /** retrieves element with given key from the multihash list, or NULL
1725  * returns pointer to multihash table list entry
1726  */
1727 static
1729  SCIP_MULTIHASHLIST** multihashlist, /**< on input: hash list to search; on exit: hash list entry corresponding
1730  * to element after retrieved one, or NULL */
1731  SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1732  SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1733  SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1734  void* userptr, /**< user pointer */
1735  uint64_t keyval, /**< hash value of key */
1736  void* key /**< key to retrieve */
1737  )
1738 {
1740 
1741  assert(multihashlist != NULL);
1742 
1743  /* find hash list entry */
1744  h = multihashlistFind(*multihashlist, hashgetkey, hashkeyeq, hashkeyval, userptr, keyval, key);
1745 
1746  /* return element */
1747  if( h != NULL )
1748  {
1749  *multihashlist = h->next;
1750 
1751  return h->element;
1752  }
1753 
1754  *multihashlist = NULL;
1755 
1756  return NULL;
1757 }
1758 
1759 /** removes element from the multihash list */
1760 static
1762  SCIP_MULTIHASHLIST** multihashlist, /**< pointer to hash list */
1763  BMS_BLKMEM* blkmem, /**< block memory */
1764  void* element /**< element to remove from the list */
1765  )
1766 {
1767  SCIP_MULTIHASHLIST* nextlist;
1768 
1769  assert(multihashlist != NULL);
1770  assert(blkmem != NULL);
1771  assert(element != NULL);
1772 
1773  while( *multihashlist != NULL && (*multihashlist)->element != element )
1774  multihashlist = &(*multihashlist)->next;
1775 
1776  if( *multihashlist != NULL )
1777  {
1778  nextlist = (*multihashlist)->next;
1779  BMSfreeBlockMemory(blkmem, multihashlist);
1780  *multihashlist = nextlist;
1781 
1782  return TRUE;
1783  }
1784 
1785  return FALSE;
1786 }
1787 
1788 #define SCIP_MULTIHASH_MAXSIZE 33554431 /* 2^25 - 1*/
1789 #define SCIP_MULTIHASH_RESIZE_PERCENTAGE 65
1790 #define SCIP_MULTIHASH_GROW_FACTOR 1.31
1791 
1792 /** resizing(increasing) the given multihash */
1793 static
1795  SCIP_MULTIHASH* multihash /**< hash table */
1796  )
1797 {
1798  SCIP_MULTIHASHLIST** newlists;
1799  SCIP_MULTIHASHLIST* multihashlist;
1800  SCIP_Longint nelements;
1801  int nnewlists;
1802  int l;
1803 
1804  assert(multihash != NULL);
1805  assert(multihash->lists != NULL);
1806  assert(multihash->nlists > 0);
1807  assert(multihash->hashgetkey != NULL);
1808  assert(multihash->hashkeyeq != NULL);
1809  assert(multihash->hashkeyval != NULL);
1810 
1811  /* get new memeory for hash table lists */
1812  nnewlists = (int) MIN((unsigned int)(multihash->nlists * SCIP_MULTIHASH_GROW_FACTOR), SCIP_MULTIHASH_MAXSIZE);
1813  nnewlists = MAX(nnewlists, multihash->nlists);
1814 
1815  SCIPdebugMessage("load = %g, nelements = %" SCIP_LONGINT_FORMAT ", nlists = %d, nnewlist = %d\n", SCIPmultihashGetLoad(multihash), multihash->nelements, multihash->nlists, nnewlists);
1816 
1817  if( nnewlists > multihash->nlists )
1818  {
1819  SCIP_Bool onlyone;
1820  void* key;
1821  uint64_t keyval;
1822  unsigned int hashval;
1823 
1824  SCIP_ALLOC( BMSallocClearBlockMemoryArray(multihash->blkmem, &newlists, nnewlists) );
1825 
1826  /* move all lists */
1827  for( l = multihash->nlists - 1; l >= 0; --l )
1828  {
1829  multihashlist = multihash->lists[l];
1830  onlyone = TRUE;
1831 
1832  /* move all elements frmm the old lists into the new lists */
1833  while( multihashlist != NULL )
1834  {
1835  /* get the hash key and its hash value */
1836  key = multihash->hashgetkey(multihash->userptr, multihashlist->element);
1837  keyval = multihash->hashkeyval(multihash->userptr, key);
1838  hashval = (unsigned int) (keyval % (unsigned) nnewlists); /*lint !e573*/
1839 
1840  /* if the old hash table list consists of only one entry, we still can use this old memory block instead
1841  * of creating a new one
1842  */
1843  if( multihashlist->next == NULL && onlyone )
1844  {
1845  /* the new list is also empty, we can directly copy the entry */
1846  if( newlists[hashval] == NULL )
1847  newlists[hashval] = multihashlist;
1848  /* the new list is not empty, so we need to find the first empty spot */
1849  else
1850  {
1851  SCIP_MULTIHASHLIST* lastnext = newlists[hashval];
1852  SCIP_MULTIHASHLIST* next = lastnext->next;
1853 
1854  while( next != NULL )
1855  {
1856  lastnext = next;
1857  next = next->next;
1858  }
1859 
1860  lastnext->next = multihashlist;
1861  }
1862 
1863  multihash->lists[l] = NULL;
1864  }
1865  else
1866  {
1867  /* append old element to the list at the hash position */
1868  SCIP_CALL( multihashlistAppend(&(newlists[hashval]), multihash->blkmem, multihashlist->element) );
1869  }
1870 
1871  onlyone = FALSE;
1872  multihashlist = multihashlist->next;
1873  }
1874  }
1875 
1876  /* remember number of elements */
1877  nelements = multihash->nelements;
1878  /* clear old lists */
1879  SCIPmultihashRemoveAll(multihash);
1880  /* free old lists */
1881  BMSfreeBlockMemoryArray(multihash->blkmem, &(multihash->lists), multihash->nlists);
1882 
1883  /* set new data */
1884  multihash->lists = newlists;
1885  multihash->nlists = nnewlists;
1886  multihash->nelements = nelements;
1887 
1888 #ifdef SCIP_MORE_DEBUG
1889  {
1890  SCIP_Longint sumslotsize = 0;
1891 
1892  for( l = 0; l < multihash->nlists; ++l )
1893  {
1894  multihashlist = multihash->lists[l];
1895  while( multihashlist != NULL )
1896  {
1897  sumslotsize++;
1898  multihashlist = multihashlist->next;
1899  }
1900  }
1901  assert(sumslotsize == multihash->nelements);
1902  }
1903 #endif
1904  }
1905 
1906  return SCIP_OKAY;
1907 }
1908 
1909 /** creates a multihash table */
1911  SCIP_MULTIHASH** multihash, /**< pointer to store the created multihash table */
1912  BMS_BLKMEM* blkmem, /**< block memory used to store multihash table entries */
1913  int tablesize, /**< size of the hash table */
1914  SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
1915  SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
1916  SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
1917  void* userptr /**< user pointer */
1918  )
1919 {
1920  /* only assert non negative to catch overflow errors
1921  * but not zeros due to integer divison
1922  */
1923  assert(tablesize >= 0);
1924  assert(multihash != NULL);
1925  assert(hashgetkey != NULL);
1926  assert(hashkeyeq != NULL);
1927  assert(hashkeyval != NULL);
1928 
1929  SCIP_ALLOC( BMSallocBlockMemory(blkmem, multihash) );
1930  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*multihash)->lists, tablesize) );
1931  (*multihash)->blkmem = blkmem;
1932  (*multihash)->nlists = tablesize;
1933  (*multihash)->hashgetkey = hashgetkey;
1934  (*multihash)->hashkeyeq = hashkeyeq;
1935  (*multihash)->hashkeyval = hashkeyval;
1936  (*multihash)->userptr = userptr;
1937  (*multihash)->nelements = 0;
1938 
1939  return SCIP_OKAY;
1940 }
1941 
1942 /** frees the multihash table */
1944  SCIP_MULTIHASH** multihash /**< pointer to the multihash table */
1945  )
1946 {
1947  int i;
1948  SCIP_MULTIHASH* table;
1949  BMS_BLKMEM* blkmem;
1950  SCIP_MULTIHASHLIST** lists;
1951 
1952  assert(multihash != NULL);
1953  assert(*multihash != NULL);
1954 
1955  table = (*multihash);
1956  blkmem = table->blkmem;
1957  lists = table->lists;
1958 
1959  /* free hash lists */
1960  for( i = table->nlists - 1; i >= 0; --i )
1961  multihashlistFree(&lists[i], blkmem);
1962 
1963  /* free main hash table data structure */
1964  BMSfreeBlockMemoryArray(blkmem, &table->lists, table->nlists);
1965  BMSfreeBlockMemory(blkmem, multihash);
1966 }
1967 
1968 
1969 /** inserts element in multihash table (multiple inserts of same element possible)
1970  *
1971  * @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding an element
1972  * to the hash table, due to dynamic resizing.
1973  */
1975  SCIP_MULTIHASH* multihash, /**< multihash table */
1976  void* element /**< element to insert into the table */
1977  )
1978 {
1979  void* key;
1980  uint64_t keyval;
1981  unsigned int hashval;
1982 
1983  assert(multihash != NULL);
1984  assert(multihash->lists != NULL);
1985  assert(multihash->nlists > 0);
1986  assert(multihash->hashgetkey != NULL);
1987  assert(multihash->hashkeyeq != NULL);
1988  assert(multihash->hashkeyval != NULL);
1989  assert(element != NULL);
1990 
1991  /* dynamically resizing the hashtables */
1993  {
1994  SCIP_CALL( multihashResize(multihash) );
1995  }
1996 
1997  /* get the hash key and its hash value */
1998  key = multihash->hashgetkey(multihash->userptr, element);
1999  keyval = multihash->hashkeyval(multihash->userptr, key);
2000  hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2001 
2002  /* append element to the list at the hash position */
2003  SCIP_CALL( multihashlistAppend(&multihash->lists[hashval], multihash->blkmem, element) );
2004 
2005  ++(multihash->nelements);
2006 
2007  return SCIP_OKAY;
2008 }
2009 
2010 /** inserts element in multihash table (multiple insertion of same element is checked and results in an error)
2011  *
2012  * @note A pointer to a multihashlist returned by SCIPmultihashRetrieveNext() might get invalid when adding a new
2013  * element to the multihash table, due to dynamic resizing.
2014  */
2016  SCIP_MULTIHASH* multihash, /**< multihash table */
2017  void* element /**< element to insert into the table */
2018  )
2019 {
2020  assert(multihash != NULL);
2021  assert(multihash->hashgetkey != NULL);
2022 
2023  /* check, if key is already existing */
2024  if( SCIPmultihashRetrieve(multihash, multihash->hashgetkey(multihash->userptr, element)) != NULL )
2025  return SCIP_KEYALREADYEXISTING;
2026 
2027  /* insert element in hash table */
2028  SCIP_CALL( SCIPmultihashInsert(multihash, element) );
2029 
2030  return SCIP_OKAY;
2031 }
2032 
2033 /** retrieve element with key from multihash table, returns NULL if not existing */
2035  SCIP_MULTIHASH* multihash, /**< multihash table */
2036  void* key /**< key to retrieve */
2037  )
2038 {
2039  uint64_t keyval;
2040  unsigned int hashval;
2041 
2042  assert(multihash != NULL);
2043  assert(multihash->lists != NULL);
2044  assert(multihash->nlists > 0);
2045  assert(multihash->hashgetkey != NULL);
2046  assert(multihash->hashkeyeq != NULL);
2047  assert(multihash->hashkeyval != NULL);
2048  assert(key != NULL);
2049 
2050  /* get the hash value of the key */
2051  keyval = multihash->hashkeyval(multihash->userptr, key);
2052  hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2053 
2054  return multihashlistRetrieve(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
2055  multihash->hashkeyval, multihash->userptr, keyval, key);
2056 }
2057 
2058 /** retrieve element with key from multihash table, returns NULL if not existing
2059  * can be used to retrieve all entries with the same key (one-by-one)
2060  *
2061  * @note The returned multimultihashlist pointer might get invalid when adding a new element to the multihash table.
2062  */
2064  SCIP_MULTIHASH* multihash, /**< multihash table */
2065  SCIP_MULTIHASHLIST** multihashlist, /**< input: entry in hash table list from which to start searching, or NULL
2066  * output: entry in hash table list corresponding to element after
2067  * retrieved one, or NULL */
2068  void* key /**< key to retrieve */
2069  )
2070 {
2071  uint64_t keyval;
2072 
2073  assert(multihash != NULL);
2074  assert(multihash->lists != NULL);
2075  assert(multihash->nlists > 0);
2076  assert(multihash->hashgetkey != NULL);
2077  assert(multihash->hashkeyeq != NULL);
2078  assert(multihash->hashkeyval != NULL);
2079  assert(multihashlist != NULL);
2080  assert(key != NULL);
2081 
2082  keyval = multihash->hashkeyval(multihash->userptr, key);
2083 
2084  if( *multihashlist == NULL )
2085  {
2086  unsigned int hashval;
2087 
2088  /* get the hash value of the key */
2089  hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2090 
2091  *multihashlist = multihash->lists[hashval];
2092  }
2093 
2094  return multihashlistRetrieveNext(multihashlist, multihash->hashgetkey, multihash->hashkeyeq,
2095  multihash->hashkeyval, multihash->userptr, keyval, key);
2096 }
2097 
2098 /** returns whether the given element exists in the multihash table */
2100  SCIP_MULTIHASH* multihash, /**< multihash table */
2101  void* element /**< element to search in the table */
2102  )
2103 {
2104  void* key;
2105  uint64_t keyval;
2106  unsigned int hashval;
2107 
2108  assert(multihash != NULL);
2109  assert(multihash->lists != NULL);
2110  assert(multihash->nlists > 0);
2111  assert(multihash->hashgetkey != NULL);
2112  assert(multihash->hashkeyeq != NULL);
2113  assert(multihash->hashkeyval != NULL);
2114  assert(element != NULL);
2115 
2116  /* get the hash key and its hash value */
2117  key = multihash->hashgetkey(multihash->userptr, element);
2118  keyval = multihash->hashkeyval(multihash->userptr, key);
2119  hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2120 
2121  return (multihashlistFind(multihash->lists[hashval], multihash->hashgetkey, multihash->hashkeyeq,
2122  multihash->hashkeyval, multihash->userptr, keyval, key) != NULL);
2123 }
2124 
2125 /** removes element from the multihash table, if it exists */
2127  SCIP_MULTIHASH* multihash, /**< multihash table */
2128  void* element /**< element to remove from the table */
2129  )
2130 {
2131  void* key;
2132  uint64_t keyval;
2133  unsigned int hashval;
2134 
2135  assert(multihash != NULL);
2136  assert(multihash->lists != NULL);
2137  assert(multihash->nlists > 0);
2138  assert(multihash->hashgetkey != NULL);
2139  assert(multihash->hashkeyeq != NULL);
2140  assert(multihash->hashkeyval != NULL);
2141  assert(element != NULL);
2142 
2143  /* get the hash key and its hash value */
2144  key = multihash->hashgetkey(multihash->userptr, element);
2145  keyval = multihash->hashkeyval(multihash->userptr, key);
2146  hashval = (unsigned int) (keyval % (unsigned) multihash->nlists); /*lint !e573*/
2147 
2148  /* remove element from the list at the hash position */
2149  if( multihashlistRemove(&multihash->lists[hashval], multihash->blkmem, element) )
2150  --(multihash->nelements);
2151 
2152  return SCIP_OKAY;
2153 }
2154 
2155 /** removes all elements of the multihash table
2156  *
2157  * @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
2158  * be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
2159  */
2161  SCIP_MULTIHASH* multihash /**< multihash table */
2162  )
2163 {
2164  BMS_BLKMEM* blkmem;
2165  SCIP_MULTIHASHLIST** lists;
2166  int i;
2167 
2168  assert(multihash != NULL);
2169 
2170  blkmem = multihash->blkmem;
2171  lists = multihash->lists;
2172 
2173  /* free hash lists */
2174  for( i = multihash->nlists - 1; i >= 0; --i )
2175  multihashlistFree(&lists[i], blkmem);
2176 
2177  multihash->nelements = 0;
2178 }
2179 
2180 /** returns number of multihash table elements */
2182  SCIP_MULTIHASH* multihash /**< multihash table */
2183  )
2184 {
2185  assert(multihash != NULL);
2186 
2187  return multihash->nelements;
2188 }
2189 
2190 /** returns the load of the given multihash table in percentage */
2192  SCIP_MULTIHASH* multihash /**< multihash table */
2193  )
2194 {
2195  assert(multihash != NULL);
2196 
2197  return ((SCIP_Real)(multihash->nelements) / (multihash->nlists) * 100.0);
2198 }
2199 
2200 /** prints statistics about multihash table usage */
2202  SCIP_MULTIHASH* multihash, /**< multihash table */
2203  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
2204  )
2205 {
2206  SCIP_MULTIHASHLIST* multihashlist;
2207  int usedslots;
2208  int maxslotsize;
2209  int sumslotsize;
2210  int slotsize;
2211  int i;
2212 
2213  assert(multihash != NULL);
2214 
2215  usedslots = 0;
2216  maxslotsize = 0;
2217  sumslotsize = 0;
2218  for( i = 0; i < multihash->nlists; ++i )
2219  {
2220  multihashlist = multihash->lists[i];
2221  if( multihashlist != NULL )
2222  {
2223  usedslots++;
2224  slotsize = 0;
2225  while( multihashlist != NULL )
2226  {
2227  slotsize++;
2228  multihashlist = multihashlist->next;
2229  }
2230  maxslotsize = MAX(maxslotsize, slotsize);
2231  sumslotsize += slotsize;
2232  }
2233  }
2234  assert(sumslotsize == multihash->nelements);
2235 
2236  SCIPmessagePrintInfo(messagehdlr, "%" SCIP_LONGINT_FORMAT " multihash entries, used %d/%d slots (%.1f%%)",
2237  multihash->nelements, usedslots, multihash->nlists, 100.0*(SCIP_Real)usedslots/(SCIP_Real)(multihash->nlists));
2238  if( usedslots > 0 )
2239  SCIPmessagePrintInfo(messagehdlr, ", avg. %.1f entries/used slot, max. %d entries in slot",
2240  (SCIP_Real)(multihash->nelements)/(SCIP_Real)usedslots, maxslotsize);
2241  SCIPmessagePrintInfo(messagehdlr, "\n");
2242 }
2243 
2244 /** creates a hash table */
2246  SCIP_HASHTABLE** hashtable, /**< pointer to store the created hash table */
2247  BMS_BLKMEM* blkmem, /**< block memory used to store hash table entries */
2248  int tablesize, /**< size of the hash table */
2249  SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
2250  SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
2251  SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
2252  void* userptr /**< user pointer */
2253  )
2254 {
2255  unsigned int nslots;
2256 
2257  /* only assert non negative to catch overflow errors
2258  * but not zeros due to integer divison
2259  */
2260  assert(tablesize >= 0);
2261  assert(hashtable != NULL);
2262  assert(hashgetkey != NULL);
2263  assert(hashkeyeq != NULL);
2264  assert(hashkeyval != NULL);
2265  assert(blkmem != NULL);
2266 
2267  SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashtable) );
2268 
2269  /* dont create too small hashtables, i.e. at least size 32, and increase
2270  * the given size by divinding it by 0.9, since then no rebuilding will
2271  * be necessary if the given number of elements are inserted. Finally round
2272  * to the next power of two.
2273  */
2274  (*hashtable)->shift = 32;
2275  (*hashtable)->shift -= (unsigned int)ceil(LOG2(MAX(32.0, tablesize / 0.9)));
2276 
2277  /* compute size from shift */
2278  nslots = 1u << (32 - (*hashtable)->shift);
2279 
2280  /* compute mask to do a fast modulo by nslots using bitwise and */
2281  (*hashtable)->mask = nslots - 1;
2282  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*hashtable)->slots, nslots) );
2283  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashtable)->hashes, nslots) );
2284  (*hashtable)->blkmem = blkmem;
2285  (*hashtable)->hashgetkey = hashgetkey;
2286  (*hashtable)->hashkeyeq = hashkeyeq;
2287  (*hashtable)->hashkeyval = hashkeyval;
2288  (*hashtable)->userptr = userptr;
2289  (*hashtable)->nelements = 0;
2290 
2291  return SCIP_OKAY;
2292 }
2293 
2294 /** frees the hash table */
2296  SCIP_HASHTABLE** hashtable /**< pointer to the hash table */
2297  )
2298 {
2299  uint32_t nslots;
2300  SCIP_HASHTABLE* table;
2301 
2302  assert(hashtable != NULL);
2303  assert(*hashtable != NULL);
2304  table = *hashtable;
2305  nslots = (*hashtable)->mask + 1;
2306 #ifdef SCIP_DEBUG
2307  {
2308  uint32_t maxprobelen = 0;
2309  uint64_t probelensum = 0;
2310  uint32_t i;
2311 
2312  assert(table != NULL);
2313 
2314  for( i = 0; i < nslots; ++i )
2315  {
2316  if( table->hashes[i] != 0 )
2317  {
2318  uint32_t probelen = ((i + table->mask + 1 - (table->hashes[i]>>(table->shift))) & table->mask) + 1;
2319  probelensum += probelen;
2320  maxprobelen = MAX(probelen, maxprobelen);
2321  }
2322  }
2323 
2324  SCIPdebugMessage("%u hash table entries, used %u/%u slots (%.1f%%)",
2325  (unsigned int)table->nelements, (unsigned int)table->nelements, (unsigned int)nslots,
2326  100.0*(SCIP_Real)table->nelements/(SCIP_Real)(nslots));
2327  if( table->nelements > 0 )
2328  SCIPdebugMessage(", avg. probe length is %.1f, max. probe length is %u",
2329  (SCIP_Real)(probelensum)/(SCIP_Real)table->nelements, (unsigned int)maxprobelen);
2330  SCIPdebugMessage("\n");
2331  }
2332 #endif
2333 
2334  /* free main hash table data structure */
2335  BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->hashes, nslots);
2336  BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->slots, nslots);
2337  BMSfreeBlockMemory((*hashtable)->blkmem, hashtable);
2338 }
2339 
2340 /** removes all elements of the hash table
2341  *
2342  * @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
2343  * be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
2344  *
2345  * @deprecated Please use SCIPhashtableRemoveAll()
2346  */
2348  SCIP_HASHTABLE* hashtable /**< hash table */
2349  )
2350 {
2351  SCIPhashtableRemoveAll(hashtable);
2352 }
2353 
2354 /* computes the distance from it's desired position for the element stored at pos */
2355 #define ELEM_DISTANCE(pos) (((pos) + hashtable->mask + 1 - (hashtable->hashes[(pos)]>>(hashtable->shift))) & hashtable->mask)
2356 
2357 /** inserts element in hash table (multiple inserts of same element overrides previous one) */
2358 static
2360  SCIP_HASHTABLE* hashtable, /**< hash table */
2361  void* element, /**< element to insert into the table */
2362  void* key, /**< key of element */
2363  uint32_t hashval, /**< hash value of element */
2364  SCIP_Bool override /**< should element be overridden or an error be returned if already existing */
2365  )
2366 {
2367  uint32_t elemdistance;
2368  uint32_t pos;
2369 #ifndef NDEBUG
2370  SCIP_Bool swapped = FALSE;
2371 #endif
2372 
2373  assert(hashtable != NULL);
2374  assert(hashtable->slots != NULL);
2375  assert(hashtable->hashes != NULL);
2376  assert(hashtable->mask > 0);
2377  assert(hashtable->hashgetkey != NULL);
2378  assert(hashtable->hashkeyeq != NULL);
2379  assert(hashtable->hashkeyval != NULL);
2380  assert(element != NULL);
2381 
2382  pos = hashval>>(hashtable->shift);
2383  elemdistance = 0;
2384  while( TRUE ) /*lint !e716*/
2385  {
2386  uint32_t distance;
2387 
2388  /* if position is empty or key equal insert element */
2389  if( hashtable->hashes[pos] == 0 )
2390  {
2391  hashtable->slots[pos] = element;
2392  hashtable->hashes[pos] = hashval;
2393  ++hashtable->nelements;
2394  return SCIP_OKAY;
2395  }
2396 
2397  if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2398  hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2399  {
2400  if( override )
2401  {
2402 #ifndef NDEBUG
2403  assert(! swapped);
2404 #endif
2405  hashtable->slots[pos] = element;
2406  hashtable->hashes[pos] = hashval;
2407  return SCIP_OKAY;
2408  }
2409  else
2410  {
2411  return SCIP_KEYALREADYEXISTING;
2412  }
2413  }
2414 
2415  /* otherwise check if the current element at this position is closer to its hashvalue */
2416  distance = ELEM_DISTANCE(pos);
2417  if( distance < elemdistance )
2418  {
2419  uint32_t tmp;
2420 
2421  /* if this is the case we insert the new element here and find a new position for the old one */
2422  elemdistance = distance;
2423  SCIPswapPointers(&hashtable->slots[pos], &element);
2424  tmp = hashval;
2425  hashval = hashtable->hashes[pos];
2426  hashtable->hashes[pos] = tmp;
2427  key = hashtable->hashgetkey(hashtable->userptr, element);
2428 
2429  /* after doing a swap the case that other elements are replaced must not happen anymore */
2430 #ifndef NDEBUG
2431  swapped = TRUE;
2432 #endif
2433  }
2434 
2435  /* continue until we have found an empty position */
2436  pos = (pos + 1) & hashtable->mask;
2437  ++elemdistance;
2438  }
2439 }
2440 
2441 /** check if the load factor of the hashtable is too high and rebuild if necessary */
2442 static
2444  SCIP_HASHTABLE* hashtable /**< hash table */
2445  )
2446 {
2447  assert(hashtable != NULL);
2448  assert(hashtable->shift < 32);
2449 
2450  /* use integer arithmetic to approximately check if load factor is above 90% */
2451  if( ((((uint64_t)hashtable->nelements)<<10)>>(32-hashtable->shift) > 921) )
2452  {
2453  void** slots;
2454  uint32_t* hashes;
2455  uint32_t nslots;
2456  uint32_t newnslots;
2457  uint32_t i;
2458 
2459  /* calculate new size (always power of two) */
2460  nslots = hashtable->mask + 1;
2461  newnslots = 2*nslots;
2462  hashtable->mask = newnslots-1;
2463  --hashtable->shift;
2464 
2465  /* reallocate array */
2466  SCIP_ALLOC( BMSallocBlockMemoryArray(hashtable->blkmem, &slots, newnslots) );
2467  SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashtable->blkmem, &hashes, newnslots) );
2468 
2469  SCIPswapPointers((void**) &slots, (void**) &hashtable->slots);
2470  SCIPswapPointers((void**) &hashes, (void**) &hashtable->hashes);
2471  hashtable->nelements = 0;
2472 
2473  /* reinsert all elements */
2474  for( i = 0; i < nslots; ++i )
2475  {
2476  /* using SCIP_CALL_ABORT since there are no allocations or duplicates
2477  * and thus no bad return codes when inserting the elements
2478  */
2479  if( hashes[i] != 0 )
2480  {
2481  SCIP_CALL_ABORT( hashtableInsert(hashtable, slots[i], hashtable->hashgetkey(hashtable->userptr, slots[i]), hashes[i], FALSE) );
2482  }
2483  }
2484  BMSfreeBlockMemoryArray(hashtable->blkmem, &hashes, nslots);
2485  BMSfreeBlockMemoryArray(hashtable->blkmem, &slots, nslots);
2486  }
2487 
2488  return SCIP_OKAY;
2489 }
2490 
2491 
2492 /** inserts element in hash table
2493  *
2494  * @note multiple inserts of same element overrides previous one
2495  */
2497  SCIP_HASHTABLE* hashtable, /**< hash table */
2498  void* element /**< element to insert into the table */
2499  )
2500 {
2501  void* key;
2502  uint64_t keyval;
2503  uint32_t hashval;
2504 
2505  assert(hashtable != NULL);
2506  assert(hashtable->slots != NULL);
2507  assert(hashtable->hashes != NULL);
2508  assert(hashtable->mask > 0);
2509  assert(hashtable->hashgetkey != NULL);
2510  assert(hashtable->hashkeyeq != NULL);
2511  assert(hashtable->hashkeyval != NULL);
2512  assert(element != NULL);
2513 
2514  SCIP_CALL( hashtableCheckLoad(hashtable) );
2515 
2516  /* get the hash key and its hash value */
2517  key = hashtable->hashgetkey(hashtable->userptr, element);
2518  keyval = hashtable->hashkeyval(hashtable->userptr, key);
2519  hashval = hashvalue(keyval);
2520 
2521  return hashtableInsert(hashtable, element, key, hashval, TRUE);
2522 }
2523 
2524 /** inserts element in hash table
2525  *
2526  * @note multiple insertion of same element is checked and results in an error
2527  */
2529  SCIP_HASHTABLE* hashtable, /**< hash table */
2530  void* element /**< element to insert into the table */
2531  )
2532 {
2533  void* key;
2534  uint64_t keyval;
2535  uint32_t hashval;
2536 
2537  assert(hashtable != NULL);
2538  assert(hashtable->slots != NULL);
2539  assert(hashtable->hashes != NULL);
2540  assert(hashtable->mask > 0);
2541  assert(hashtable->hashgetkey != NULL);
2542  assert(hashtable->hashkeyeq != NULL);
2543  assert(hashtable->hashkeyval != NULL);
2544  assert(element != NULL);
2545 
2546  SCIP_CALL( hashtableCheckLoad(hashtable) );
2547 
2548  /* get the hash key and its hash value */
2549  key = hashtable->hashgetkey(hashtable->userptr, element);
2550  keyval = hashtable->hashkeyval(hashtable->userptr, key);
2551  hashval = hashvalue(keyval);
2552 
2553  return hashtableInsert(hashtable, element, key, hashval, FALSE);
2554 }
2555 
2556 /** retrieve element with key from hash table, returns NULL if not existing */
2558  SCIP_HASHTABLE* hashtable, /**< hash table */
2559  void* key /**< key to retrieve */
2560  )
2561 {
2562  uint64_t keyval;
2563  uint32_t hashval;
2564  uint32_t pos;
2565  uint32_t elemdistance;
2566 
2567  assert(hashtable != NULL);
2568  assert(hashtable->slots != NULL);
2569  assert(hashtable->hashes != NULL);
2570  assert(hashtable->mask > 0);
2571  assert(hashtable->hashgetkey != NULL);
2572  assert(hashtable->hashkeyeq != NULL);
2573  assert(hashtable->hashkeyval != NULL);
2574  assert(key != NULL);
2575 
2576  /* get the hash value of the key */
2577  keyval = hashtable->hashkeyval(hashtable->userptr, key);
2578  hashval = hashvalue(keyval);
2579 
2580  pos = hashval>>(hashtable->shift);
2581  elemdistance = 0;
2582 
2583  while( TRUE ) /*lint !e716*/
2584  {
2585  uint32_t distance;
2586 
2587  /* slots is empty so element cannot be contained */
2588  if( hashtable->hashes[pos] == 0 )
2589  return NULL;
2590 
2591  distance = ELEM_DISTANCE(pos);
2592 
2593  /* element cannot be contained since otherwise we would have swapped it with this one during insert */
2594  if( elemdistance > distance )
2595  return NULL;
2596 
2597  /* found element */
2598  if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2599  hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2600  return hashtable->slots[pos];
2601 
2602  pos = (pos + 1) & hashtable->mask;
2603  ++elemdistance;
2604  }
2605 }
2606 
2607 /** returns whether the given element exists in the table */
2609  SCIP_HASHTABLE* hashtable, /**< hash table */
2610  void* element /**< element to search in the table */
2611  )
2612 {
2613  assert(hashtable != NULL);
2614  assert(hashtable->slots != NULL);
2615  assert(hashtable->hashes != NULL);
2616  assert(hashtable->mask > 0);
2617  assert(hashtable->hashgetkey != NULL);
2618  assert(hashtable->hashkeyeq != NULL);
2619  assert(hashtable->hashkeyval != NULL);
2620  assert(element != NULL);
2621 
2622  return (SCIPhashtableRetrieve(hashtable, hashtable->hashgetkey(hashtable->userptr, element)) != NULL);
2623 }
2624 
2625 /** removes element from the hash table, if it exists */
2627  SCIP_HASHTABLE* hashtable, /**< hash table */
2628  void* element /**< element to remove from the table */
2629  )
2630 {
2631  void* key;
2632  uint64_t keyval;
2633  uint32_t hashval;
2634  uint32_t elemdistance;
2635  uint32_t distance;
2636  uint32_t pos;
2637 
2638  assert(hashtable != NULL);
2639  assert(hashtable->slots != NULL);
2640  assert(hashtable->hashes != NULL);
2641  assert(hashtable->mask > 0);
2642  assert(hashtable->hashgetkey != NULL);
2643  assert(hashtable->hashkeyeq != NULL);
2644  assert(hashtable->hashkeyval != NULL);
2645  assert(element != NULL);
2646 
2647  /* get the hash key and its hash value */
2648  key = hashtable->hashgetkey(hashtable->userptr, element);
2649  keyval = hashtable->hashkeyval(hashtable->userptr, key);
2650  hashval = hashvalue(keyval);
2651 
2652  elemdistance = 0;
2653  pos = hashval>>(hashtable->shift);
2654  while( TRUE ) /*lint !e716*/
2655  {
2656  /* slots empty so element not contained */
2657  if( hashtable->hashes[pos] == 0 )
2658  return SCIP_OKAY;
2659 
2660  distance = ELEM_DISTANCE(pos);
2661 
2662  /* element can not be contained since otherwise we would have swapped it with this one */
2663  if( elemdistance > distance )
2664  return SCIP_OKAY;
2665 
2666  if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2667  hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2668  {
2669  /* element exists at pos so break out of loop */
2670  break;
2671  }
2672 
2673  pos = (pos + 1) & hashtable->mask;
2674  ++elemdistance;
2675  }
2676 
2677  /* remove element */
2678  hashtable->hashes[pos] = 0;
2679  --hashtable->nelements;
2680  while( TRUE ) /*lint !e716*/
2681  {
2682  uint32_t nextpos = (pos + 1) & hashtable->mask;
2683 
2684  /* nothing to do since there is no chain that needs to be moved */
2685  if( hashtable->hashes[nextpos] == 0 )
2686  break;
2687 
2688  /* check if the element is the start of a new chain and return if that is the case */
2689  if( (hashtable->hashes[nextpos]>>(hashtable->shift)) == nextpos )
2690  break;
2691 
2692  /* element should be moved to the left and next element needs to be checked */
2693  hashtable->slots[pos] = hashtable->slots[nextpos];
2694  hashtable->hashes[pos] = hashtable->hashes[nextpos];
2695  hashtable->hashes[nextpos] = 0;
2696 
2697  pos = nextpos;
2698  }
2699 
2700  return SCIP_OKAY;
2701 }
2702 
2703 /** removes all elements of the hash table */
2705  SCIP_HASHTABLE* hashtable /**< hash table */
2706  )
2707 {
2708  assert(hashtable != NULL);
2709 
2710  BMSclearMemoryArray(hashtable->hashes, hashtable->mask + 1);
2711 
2712  hashtable->nelements = 0;
2713 }
2714 
2715 /** returns number of hash table elements */
2717  SCIP_HASHTABLE* hashtable /**< hash table */
2718  )
2719 {
2720  assert(hashtable != NULL);
2721 
2722  return hashtable->nelements;
2723 }
2724 
2725 /** gives the number of entries in the internal arrays of a hash table */
2727  SCIP_HASHTABLE* hashtable /**< hash table */
2728  )
2729 {
2730  return (int) hashtable->mask + 1;
2731 }
2732 
2733 /** gives the element at the given index or NULL if entry at that index has no element */
2735  SCIP_HASHTABLE* hashtable, /**< hash table */
2736  int entryidx /**< index of hash table entry */
2737  )
2738 {
2739  return hashtable->hashes[entryidx] == 0 ? NULL : hashtable->slots[entryidx];
2740 }
2741 
2742 /** returns the load of the given hash table in percentage */
2744  SCIP_HASHTABLE* hashtable /**< hash table */
2745  )
2746 {
2747  assert(hashtable != NULL);
2748 
2749  return ((SCIP_Real)(hashtable->nelements) / (hashtable->mask + 1) * 100.0);
2750 }
2751 
2752 /** prints statistics about hash table usage */
2754  SCIP_HASHTABLE* hashtable, /**< hash table */
2755  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
2756  )
2757 {
2758  uint32_t maxprobelen = 0;
2759  uint64_t probelensum = 0;
2760  uint32_t nslots;
2761  uint32_t i;
2762 
2763  assert(hashtable != NULL);
2764 
2765  nslots = hashtable->mask + 1;
2766 
2767  /* compute the maximum and average probe length */
2768  for( i = 0; i < nslots; ++i )
2769  {
2770  if( hashtable->hashes[i] != 0 )
2771  {
2772  uint32_t probelen = ELEM_DISTANCE(i) + 1;
2773  probelensum += probelen;
2774  maxprobelen = MAX(probelen, maxprobelen);
2775  }
2776  }
2777 
2778  /* print general hash table statistics */
2779  SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
2780  (unsigned int)hashtable->nelements, (unsigned int)hashtable->nelements,
2781  (unsigned int)nslots, 100.0*(SCIP_Real)hashtable->nelements/(SCIP_Real)(nslots));
2782 
2783  /* if not empty print average and maximum probe length */
2784  if( hashtable->nelements > 0 )
2785  SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
2786  (SCIP_Real)(probelensum)/(SCIP_Real)hashtable->nelements, (unsigned int)maxprobelen);
2787  SCIPmessagePrintInfo(messagehdlr, "\n");
2788 }
2789 
2790 /** returns TRUE iff both keys (i.e. strings) are equal */
2791 SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
2792 { /*lint --e{715}*/
2793  const char* string1 = (const char*)key1;
2794  const char* string2 = (const char*)key2;
2795 
2796  return (strcmp(string1, string2) == 0);
2797 }
2798 
2799 /** returns the hash value of the key (i.e. string) */
2800 SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
2801 { /*lint --e{715}*/
2802  const char* str;
2803  uint64_t hash;
2804 
2805  str = (const char*)key;
2806  hash = 37;
2807  while( *str != '\0' )
2808  {
2809  hash *= 11;
2810  hash += (unsigned int)(*str); /*lint !e571*/
2811  str++;
2812  }
2813 
2814  return hash;
2815 }
2816 
2817 
2818 /** gets the element as the key */
2819 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
2820 { /*lint --e{715}*/
2821  /* the key is the element itself */
2822  return elem;
2823 }
2824 
2825 /** returns TRUE iff both keys(pointer) are equal */
2826 SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqPtr)
2827 { /*lint --e{715}*/
2828  return (key1 == key2);
2829 }
2830 
2831 /** returns the hash value of the key */
2832 SCIP_DECL_HASHKEYVAL(SCIPhashKeyValPtr)
2833 { /*lint --e{715}*/
2834  /* the key is used as the keyvalue too */
2835  return (uint64_t) (uintptr_t) key;
2836 }
2837 
2838 
2839 
2840 /*
2841  * Hash Map
2842  */
2843 
2844 /* redefine ELEM_DISTANCE macro for hashmap */
2845 #undef ELEM_DISTANCE
2846 /* computes the distance from it's desired position for the element stored at pos */
2847 #define ELEM_DISTANCE(pos) (((pos) + hashmap->mask + 1 - (hashmap->hashes[(pos)]>>(hashmap->shift))) & hashmap->mask)
2848 
2849 /** inserts element in hash table */
2850 static
2852  SCIP_HASHMAP* hashmap, /**< hash map */
2853  void* origin, /**< element to insert into the table */
2854  SCIP_HASHMAPIMAGE image, /**< key of element */
2855  uint32_t hashval, /**< hash value of element */
2856  SCIP_Bool override /**< should element be overridden or error be returned if already existing */
2857  )
2858 {
2859  uint32_t elemdistance;
2860  uint32_t pos;
2861 
2862  assert(hashmap != NULL);
2863  assert(hashmap->slots != NULL);
2864  assert(hashmap->hashes != NULL);
2865  assert(hashmap->mask > 0);
2866  assert(hashval != 0);
2867 
2868  pos = hashval>>(hashmap->shift);
2869  elemdistance = 0;
2870  while( TRUE ) /*lint !e716*/
2871  {
2872  uint32_t distance;
2873 
2874  /* if position is empty or key equal insert element */
2875  if( hashmap->hashes[pos] == 0 )
2876  {
2877  hashmap->slots[pos].origin = origin;
2878  hashmap->slots[pos].image = image;
2879  hashmap->hashes[pos] = hashval;
2880  ++hashmap->nelements;
2881  return SCIP_OKAY;
2882  }
2883 
2884  if( hashval == hashmap->hashes[pos] && origin == hashmap->slots[pos].origin )
2885  {
2886  if( override )
2887  {
2888  hashmap->slots[pos].origin = origin;
2889  hashmap->slots[pos].image = image;
2890  hashmap->hashes[pos] = hashval;
2891  return SCIP_OKAY;
2892  }
2893  else
2894  {
2895  return SCIP_KEYALREADYEXISTING;
2896  }
2897  }
2898 
2899  /* otherwise check if the current element at this position is closer to its hashvalue */
2900  distance = ELEM_DISTANCE(pos);
2901  if( distance < elemdistance )
2902  {
2903  SCIP_HASHMAPIMAGE tmp;
2904  uint32_t tmphash;
2905 
2906  /* if this is the case we insert the new element here and find a new position for the old one */
2907  elemdistance = distance;
2908  tmphash = hashval;
2909  hashval = hashmap->hashes[pos];
2910  hashmap->hashes[pos] = tmphash;
2911  SCIPswapPointers(&hashmap->slots[pos].origin, &origin);
2912  tmp = image;
2913  image = hashmap->slots[pos].image;
2914  hashmap->slots[pos].image = tmp;
2915  }
2916 
2917  /* continue until we have found an empty position */
2918  pos = (pos + 1) & hashmap->mask;
2919  ++elemdistance;
2920  }
2921 }
2922 
2923 /** lookup origin in the hashmap. If element is found returns true and the position of the element,
2924  * otherwise returns FALSE.
2925  */
2926 static
2928  SCIP_HASHMAP* hashmap, /**< hash table */
2929  void* origin, /**< origin to lookup */
2930  uint32_t* pos /**< pointer to store position of element, if exists */
2931  )
2932 {
2933  uint32_t hashval;
2934  uint32_t elemdistance;
2935 
2936  assert(hashmap != NULL);
2937  assert(hashmap->slots != NULL);
2938  assert(hashmap->hashes != NULL);
2939  assert(hashmap->mask > 0);
2940 
2941  /* get the hash value */
2942  hashval = hashvalue((size_t)origin);
2943  assert(hashval != 0);
2944 
2945  *pos = hashval>>(hashmap->shift);
2946  elemdistance = 0;
2947 
2948  while( TRUE ) /*lint !e716*/
2949  {
2950  uint32_t distance;
2951 
2952  /* slots is empty so element cannot be contained */
2953  if( hashmap->hashes[*pos] == 0 )
2954  return FALSE;
2955 
2956  distance = ELEM_DISTANCE(*pos);
2957  /* element can not be contained since otherwise we would have swapped it with this one during insert */
2958  if( elemdistance > distance )
2959  return FALSE;
2960 
2961  /* found element */
2962  if( hashmap->hashes[*pos] == hashval && hashmap->slots[*pos].origin == origin )
2963  return TRUE;
2964 
2965  *pos = (*pos + 1) & hashmap->mask;
2966  ++elemdistance;
2967  }
2968 }
2969 
2970 /** check if the load factor of the hashmap is too high and rebuild if necessary */
2971 static
2973  SCIP_HASHMAP* hashmap /**< hash table */
2974  )
2975 {
2976  assert(hashmap != NULL);
2977  assert(hashmap->shift < 32);
2978 
2979  /* use integer arithmetic to approximately check if load factor is above 90% */
2980  if( ((((uint64_t)hashmap->nelements)<<10)>>(32-hashmap->shift) > 921) )
2981  {
2982  SCIP_HASHMAPENTRY* slots;
2983  uint32_t* hashes;
2984  uint32_t nslots;
2985  uint32_t newnslots;
2986  uint32_t i;
2987 
2988  /* calculate new size (always power of two) */
2989  nslots = hashmap->mask + 1;
2990  --hashmap->shift;
2991  newnslots = 2*nslots;
2992  hashmap->mask = newnslots-1;
2993 
2994  /* reallocate array */
2995  SCIP_ALLOC( BMSallocBlockMemoryArray(hashmap->blkmem, &slots, newnslots) );
2996  SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashmap->blkmem, &hashes, newnslots) );
2997 
2998  SCIPswapPointers((void**) &slots, (void**) &hashmap->slots);
2999  SCIPswapPointers((void**) &hashes, (void**) &hashmap->hashes);
3000  hashmap->nelements = 0;
3001 
3002  /* reinsert all elements */
3003  for( i = 0; i < nslots; ++i )
3004  {
3005  /* using SCIP_CALL_ABORT since there are no allocations or duplicates
3006  * and thus no bad return codes when inserting the elements
3007  */
3008  if( hashes[i] != 0 )
3009  {
3010  SCIP_CALL_ABORT( hashmapInsert(hashmap, slots[i].origin, slots[i].image, hashes[i], FALSE) );
3011  }
3012  }
3013 
3014  /* free old arrays */
3015  BMSfreeBlockMemoryArray(hashmap->blkmem, &hashes, nslots);
3016  BMSfreeBlockMemoryArray(hashmap->blkmem, &slots, nslots);
3017  }
3018 
3019  return SCIP_OKAY;
3020 }
3021 
3022 /** creates a hash map mapping pointers to pointers */
3024  SCIP_HASHMAP** hashmap, /**< pointer to store the created hash map */
3025  BMS_BLKMEM* blkmem, /**< block memory used to store hash map entries */
3026  int mapsize /**< size of the hash map */
3027  )
3028 {
3029  uint32_t nslots;
3030 
3031  assert(hashmap != NULL);
3032  assert(mapsize >= 0);
3033  assert(blkmem != NULL);
3034 
3035  SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashmap) );
3036 
3037  /* dont create too small hashtables, i.e. at least size 32, and increase
3038  * the given size by divinding it by 0.9, since then no rebuilding will
3039  * be necessary if the given number of elements are inserted. Finally round
3040  * to the next power of two.
3041  */
3042  (*hashmap)->shift = 32;
3043  (*hashmap)->shift -= (unsigned int)ceil(log(MAX(32, mapsize / 0.9)) / log(2.0));
3044  nslots = 1u << (32 - (*hashmap)->shift);
3045  (*hashmap)->mask = nslots - 1;
3046  (*hashmap)->blkmem = blkmem;
3047  (*hashmap)->nelements = 0;
3048  (*hashmap)->hashmaptype = SCIP_HASHMAPTYPE_UNKNOWN;
3049 
3050  SCIP_ALLOC( BMSallocBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots) );
3051  SCIP_ALLOC( BMSallocClearBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots) );
3052 
3053  return SCIP_OKAY;
3054 }
3055 
3056 /** frees the hash map */
3058  SCIP_HASHMAP** hashmap /**< pointer to the hash map */
3059  )
3060 {
3061  uint32_t nslots;
3062 
3063  assert(hashmap != NULL);
3064  assert(*hashmap != NULL);
3065 
3066  nslots = (*hashmap)->mask + 1;
3067 #ifdef SCIP_DEBUG
3068  {
3069  uint32_t maxprobelen = 0;
3070  uint64_t probelensum = 0;
3071  uint32_t i;
3072 
3073  assert(hashmap != NULL);
3074 
3075  for( i = 0; i < nslots; ++i )
3076  {
3077  if( (*hashmap)->hashes[i] != 0 )
3078  {
3079  uint32_t probelen = ((i + (*hashmap)->mask + 1 - ((*hashmap)->hashes[i]>>((*hashmap)->shift))) & (*hashmap)->mask) + 1;
3080  probelensum += probelen;
3081  maxprobelen = MAX(probelen, maxprobelen);
3082  }
3083  }
3084 
3085  SCIPdebugMessage("%u hash map entries, used %u/%u slots (%.1f%%)",
3086  (unsigned int)(*hashmap)->nelements, (unsigned int)(*hashmap)->nelements, (unsigned int)nslots,
3087  100.0*(SCIP_Real)(*hashmap)->nelements/(SCIP_Real)(nslots));
3088  if( (*hashmap)->nelements > 0 )
3089  SCIPdebugPrintf(", avg. probe length is %.1f, max. probe length is %u",
3090  (SCIP_Real)(probelensum)/(SCIP_Real)(*hashmap)->nelements, (unsigned int)maxprobelen);
3091  SCIPdebugPrintf("\n");
3092  }
3093 #endif
3094 
3095  /* free main hash map data structure */
3096  BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots);
3097  BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots);
3098  BMSfreeBlockMemory((*hashmap)->blkmem, hashmap);
3099 }
3100 
3101 /** inserts new origin->image pair in hash map
3102  *
3103  * @note multiple insertion of same element is checked and results in an error
3104  */
3106  SCIP_HASHMAP* hashmap, /**< hash map */
3107  void* origin, /**< origin to set image for */
3108  void* image /**< new image for origin */
3109  )
3110 {
3111  uint32_t hashval;
3112  SCIP_HASHMAPIMAGE img;
3113 
3114  assert(hashmap != NULL);
3115  assert(hashmap->slots != NULL);
3116  assert(hashmap->hashes != NULL);
3117  assert(hashmap->mask > 0);
3118  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3119 
3120 #ifndef NDEBUG
3121  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3123 #endif
3124 
3125  SCIP_CALL( hashmapCheckLoad(hashmap) );
3126 
3127  /* get the hash value */
3128  hashval = hashvalue((size_t)origin);
3129 
3130  /* append origin->image pair to hash map */
3131  img.ptr = image;
3132  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3133 
3134  return SCIP_OKAY;
3135 }
3136 
3137 /** inserts new origin->image pair in hash map
3138  *
3139  * @note multiple insertion of same element is checked and results in an error
3140  */
3142  SCIP_HASHMAP* hashmap, /**< hash map */
3143  void* origin, /**< origin to set image for */
3144  int image /**< new image for origin */
3145  )
3146 {
3147  uint32_t hashval;
3148  SCIP_HASHMAPIMAGE img;
3149 
3150  assert(hashmap != NULL);
3151  assert(hashmap->slots != NULL);
3152  assert(hashmap->hashes != NULL);
3153  assert(hashmap->mask > 0);
3154  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3155 
3156 #ifndef NDEBUG
3157  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3158  hashmap->hashmaptype = SCIP_HASHMAPTYPE_INT;
3159 #endif
3160 
3161  SCIP_CALL( hashmapCheckLoad(hashmap) );
3162 
3163  /* get the hash value */
3164  hashval = hashvalue((size_t)origin);
3165 
3166  /* append origin->image pair to hash map */
3167  img.integer = image;
3168  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3169 
3170  return SCIP_OKAY;
3171 }
3172 
3173 /** inserts new origin->image pair in hash map
3174  *
3175  * @note multiple insertion of same element is checked and results in an error
3176  */
3178  SCIP_HASHMAP* hashmap, /**< hash map */
3179  void* origin, /**< origin to set image for */
3180  SCIP_Real image /**< new image for origin */
3181  )
3182 {
3183  uint32_t hashval;
3184  SCIP_HASHMAPIMAGE img;
3185 
3186  assert(hashmap != NULL);
3187  assert(hashmap->slots != NULL);
3188  assert(hashmap->hashes != NULL);
3189  assert(hashmap->mask > 0);
3190  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3191 
3192 #ifndef NDEBUG
3193  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3195 #endif
3196 
3197  SCIP_CALL( hashmapCheckLoad(hashmap) );
3198 
3199  /* get the hash value */
3200  hashval = hashvalue((size_t)origin);
3201 
3202  /* append origin->image pair to hash map */
3203  img.real = image;
3204  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3205 
3206  return SCIP_OKAY;
3207 }
3208 
3209 /** retrieves image of given origin from the hash map, or NULL if no image exists */
3211  SCIP_HASHMAP* hashmap, /**< hash map */
3212  void* origin /**< origin to retrieve image for */
3213  )
3214 {
3215  uint32_t pos;
3216 
3217  assert(hashmap != NULL);
3218  assert(hashmap->slots != NULL);
3219  assert(hashmap->hashes != NULL);
3220  assert(hashmap->mask > 0);
3221  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3222 
3223  if( hashmapLookup(hashmap, origin, &pos) )
3224  return hashmap->slots[pos].image.ptr;
3225 
3226  return NULL;
3227 }
3228 
3229 /** retrieves image of given origin from the hash map, or INT_MAX if no image exists */
3231  SCIP_HASHMAP* hashmap, /**< hash map */
3232  void* origin /**< origin to retrieve image for */
3233  )
3234 {
3235  uint32_t pos;
3236 
3237  assert(hashmap != NULL);
3238  assert(hashmap->slots != NULL);
3239  assert(hashmap->hashes != NULL);
3240  assert(hashmap->mask > 0);
3241  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3242 
3243  if( hashmapLookup(hashmap, origin, &pos) )
3244  return hashmap->slots[pos].image.integer;
3245 
3246  return INT_MAX;
3247 }
3248 
3249 /** retrieves image of given origin from the hash map, or SCIP_INVALID if no image exists */
3251  SCIP_HASHMAP* hashmap, /**< hash map */
3252  void* origin /**< origin to retrieve image for */
3253  )
3254 {
3255  uint32_t pos;
3256 
3257  assert(hashmap != NULL);
3258  assert(hashmap->slots != NULL);
3259  assert(hashmap->hashes != NULL);
3260  assert(hashmap->mask > 0);
3261  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3262 
3263  if( hashmapLookup(hashmap, origin, &pos) )
3264  return hashmap->slots[pos].image.real;
3265 
3266  return SCIP_INVALID;
3267 }
3268 
3269 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3270  * or by appending a new origin->image pair
3271  */
3273  SCIP_HASHMAP* hashmap, /**< hash map */
3274  void* origin, /**< origin to set image for */
3275  void* image /**< new image for origin */
3276  )
3277 {
3278  uint32_t hashval;
3279  SCIP_HASHMAPIMAGE img;
3280 
3281  assert(hashmap != NULL);
3282  assert(hashmap->slots != NULL);
3283  assert(hashmap->mask > 0);
3284  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3285 
3286 #ifndef NDEBUG
3287  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3289 #endif
3290 
3291  SCIP_CALL( hashmapCheckLoad(hashmap) );
3292 
3293  /* get the hash value */
3294  hashval = hashvalue((size_t)origin);
3295 
3296  /* append origin->image pair to hash map */
3297  img.ptr = image;
3298  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3299 
3300  return SCIP_OKAY;
3301 }
3302 
3303 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3304  * or by appending a new origin->image pair
3305  */
3307  SCIP_HASHMAP* hashmap, /**< hash map */
3308  void* origin, /**< origin to set image for */
3309  int image /**< new image for origin */
3310  )
3311 {
3312  uint32_t hashval;
3313  SCIP_HASHMAPIMAGE img;
3314 
3315  assert(hashmap != NULL);
3316  assert(hashmap->slots != NULL);
3317  assert(hashmap->mask > 0);
3318  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3319 
3320 #ifndef NDEBUG
3321  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3322  hashmap->hashmaptype = SCIP_HASHMAPTYPE_INT;
3323 #endif
3324 
3325  SCIP_CALL( hashmapCheckLoad(hashmap) );
3326 
3327  /* get the hash value */
3328  hashval = hashvalue((size_t)origin);
3329 
3330  /* append origin->image pair to hash map */
3331  img.integer = image;
3332  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3333 
3334  return SCIP_OKAY;
3335 }
3336 
3337 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3338  * or by appending a new origin->image pair
3339  */
3341  SCIP_HASHMAP* hashmap, /**< hash map */
3342  void* origin, /**< origin to set image for */
3343  SCIP_Real image /**< new image for origin */
3344  )
3345 {
3346  uint32_t hashval;
3347  SCIP_HASHMAPIMAGE img;
3348 
3349  assert(hashmap != NULL);
3350  assert(hashmap->slots != NULL);
3351  assert(hashmap->mask > 0);
3352  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3353 
3354 #ifndef NDEBUG
3355  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3357 #endif
3358 
3359  SCIP_CALL( hashmapCheckLoad(hashmap) );
3360 
3361  /* get the hash value */
3362  hashval = hashvalue((size_t)origin);
3363 
3364  /* append origin->image pair to hash map */
3365  img.real = image;
3366  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3367 
3368  return SCIP_OKAY;
3369 }
3370 
3371 /** checks whether an image to the given origin exists in the hash map */
3373  SCIP_HASHMAP* hashmap, /**< hash map */
3374  void* origin /**< origin to search for */
3375  )
3376 {
3377  uint32_t pos;
3378 
3379  assert(hashmap != NULL);
3380  assert(hashmap->slots != NULL);
3381  assert(hashmap->hashes != NULL);
3382  assert(hashmap->mask > 0);
3383 
3384  return hashmapLookup(hashmap, origin, &pos);
3385 }
3386 
3387 /** removes origin->image pair from the hash map, if it exists */
3389  SCIP_HASHMAP* hashmap, /**< hash map */
3390  void* origin /**< origin to remove from the list */
3391  )
3392 {
3393  uint32_t pos;
3394 
3395  assert(hashmap != NULL);
3396  assert(hashmap->slots != NULL);
3397  assert(hashmap->mask > 0);
3398 
3399  assert(origin != NULL);
3400 
3401  if( hashmapLookup(hashmap, origin, &pos) )
3402  {
3403  /* remove element */
3404  hashmap->hashes[pos] = 0;
3405  --hashmap->nelements;
3406 
3407  /* move other elements if necessary */
3408  while( TRUE ) /*lint !e716*/
3409  {
3410  uint32_t nextpos = (pos + 1) & hashmap->mask;
3411 
3412  /* nothing to do since there is no chain that needs to be moved */
3413  if( hashmap->hashes[nextpos] == 0 )
3414  return SCIP_OKAY;
3415 
3416  /* check if the element is the start of a new chain and return if that is the case */
3417  if( (hashmap->hashes[nextpos]>>(hashmap->shift)) == nextpos )
3418  return SCIP_OKAY;
3419 
3420  /* element should be moved to the left and next element needs to be checked */
3421  hashmap->slots[pos].origin = hashmap->slots[nextpos].origin;
3422  hashmap->slots[pos].image = hashmap->slots[nextpos].image;
3423  hashmap->hashes[pos] = hashmap->hashes[nextpos];
3424  hashmap->hashes[nextpos] = 0;
3425 
3426  pos = nextpos;
3427  }
3428  }
3429 
3430  return SCIP_OKAY;
3431 }
3432 
3433 /** prints statistics about hash map usage */
3435  SCIP_HASHMAP* hashmap, /**< hash map */
3436  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3437  )
3438 {
3439  uint32_t maxprobelen = 0;
3440  uint64_t probelensum = 0;
3441  uint32_t nslots;
3442  uint32_t i;
3443 
3444  assert(hashmap != NULL);
3445 
3446  nslots = hashmap->mask + 1;
3447 
3448  /* compute the maximum and average probe length */
3449  for( i = 0; i < nslots; ++i )
3450  {
3451  if( hashmap->hashes[i] != 0 )
3452  {
3453  uint32_t probelen = ELEM_DISTANCE(i) + 1;
3454  probelensum += probelen;
3455  maxprobelen = MAX(probelen, maxprobelen);
3456  }
3457  }
3458 
3459  /* print general hash map statistics */
3460  SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3461  (unsigned int)hashmap->nelements, (unsigned int)hashmap->nelements,
3462  (unsigned int)nslots, 100.0*(SCIP_Real)hashmap->nelements/(SCIP_Real)(nslots));
3463 
3464  /* if not empty print average and maximum probe length */
3465  if( hashmap->nelements > 0 )
3466  SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3467  (SCIP_Real)(probelensum)/(SCIP_Real)hashmap->nelements, (unsigned int)maxprobelen);
3468  SCIPmessagePrintInfo(messagehdlr, "\n");
3469 }
3470 
3471 /** indicates whether a hash map has no entries */
3473  SCIP_HASHMAP* hashmap /**< hash map */
3474  )
3475 {
3476  assert(hashmap != NULL);
3477 
3478  return hashmap->nelements == 0;
3479 }
3480 
3481 /** gives the number of elements in a hash map */
3483  SCIP_HASHMAP* hashmap /**< hash map */
3484  )
3485 {
3486  return (int) hashmap->nelements;
3487 }
3488 
3489 /** gives the number of entries in the internal arrays of a hash map */
3491  SCIP_HASHMAP* hashmap /**< hash map */
3492  )
3493 {
3494  return (int) hashmap->mask + 1;
3495 }
3496 
3497 /** gives the hashmap entry at the given index or NULL if entry is empty */
3499  SCIP_HASHMAP* hashmap, /**< hash map */
3500  int entryidx /**< index of hash map entry */
3501  )
3502 {
3503  assert(hashmap != NULL);
3504 
3505  return hashmap->hashes[entryidx] == 0 ? NULL : &hashmap->slots[entryidx];
3506 }
3507 
3508 /** gives the origin of the hashmap entry */
3510  SCIP_HASHMAPENTRY* entry /**< hash map entry */
3511  )
3512 {
3513  assert(entry != NULL);
3514 
3515  return entry->origin;
3516 }
3517 
3518 /** gives the image of the hashmap entry */
3520  SCIP_HASHMAPENTRY* entry /**< hash map entry */
3521  )
3522 {
3523  assert(entry != NULL);
3524 
3525  return entry->image.ptr;
3526 }
3527 
3528 /** gives the image of the hashmap entry */
3530  SCIP_HASHMAPENTRY* entry /**< hash map entry */
3531  )
3532 {
3533  assert(entry != NULL);
3534 
3535  return entry->image.integer;
3536 }
3537 
3538 /** gives the image of the hashmap entry */
3540  SCIP_HASHMAPENTRY* entry /**< hash map entry */
3541  )
3542 {
3543  assert(entry != NULL);
3544 
3545  return entry->image.real;
3546 }
3547 
3548 /** sets pointer image of a hashmap entry */
3550  SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3551  void* image /**< new image */
3552  )
3553 {
3554  assert(entry != NULL);
3555 
3556  entry->image.ptr = image;
3557 }
3558 
3559 /** sets integer image of a hashmap entry */
3561  SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3562  int image /**< new image */
3563  )
3564 {
3565  assert(entry != NULL);
3566 
3567  entry->image.integer = image;
3568 }
3569 
3570 /** sets real image of a hashmap entry */
3572  SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3573  SCIP_Real image /**< new image */
3574  )
3575 {
3576  assert(entry != NULL);
3577 
3578  entry->image.real = image;
3579 }
3580 
3581 /** removes all entries in a hash map. */
3583  SCIP_HASHMAP* hashmap /**< hash map */
3584  )
3585 {
3586  assert(hashmap != NULL);
3587 
3588  BMSclearMemoryArray(hashmap->hashes, hashmap->mask + 1);
3589 
3590  hashmap->nelements = 0;
3591 
3592  return SCIP_OKAY;
3593 }
3594 
3595 
3596 /*
3597  * Hash Set
3598  */
3599 
3600 /* redefine ELEM_DISTANCE macro for hashset */
3601 #undef ELEM_DISTANCE
3602 /* computes the distance from it's desired position for the element stored at pos */
3603 #define ELEM_DISTANCE(pos) (((pos) + nslots - hashSetDesiredPos(hashset, hashset->slots[(pos)])) & mask)
3604 
3605 /* calculate desired position of element in hash set */
3606 static
3608  SCIP_HASHSET* hashset, /**< the hash set */
3609  void* element /**< element to calculate position for */
3610  )
3611 {
3612  return (uint32_t)((UINT64_C(0x9e3779b97f4a7c15) * (uintptr_t)element)>>(hashset->shift));
3613 }
3614 
3615 static
3617  SCIP_HASHSET* hashset, /**< hash set */
3618  void* element /**< element to insert */
3619  )
3620 {
3621  uint32_t elemdistance;
3622  uint32_t pos;
3623  uint32_t nslots;
3624  uint32_t mask;
3625 
3626  assert(hashset != NULL);
3627  assert(hashset->slots != NULL);
3628  assert(element != NULL);
3629 
3630  pos = hashSetDesiredPos(hashset, element);
3631  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3632  mask = nslots - 1;
3633 
3634  elemdistance = 0;
3635  while( TRUE ) /*lint !e716*/
3636  {
3637  uint32_t distance;
3638 
3639  /* if position is empty or key equal insert element */
3640  if( hashset->slots[pos] == NULL )
3641  {
3642  hashset->slots[pos] = element;
3643  ++hashset->nelements;
3644  return;
3645  }
3646 
3647  if( hashset->slots[pos] == element )
3648  return;
3649 
3650  /* otherwise check if the current element at this position is closer to its hashvalue */
3651  distance = ELEM_DISTANCE(pos);
3652  if( distance < elemdistance )
3653  {
3654  /* if this is the case we insert the new element here and find a new position for the old one */
3655  elemdistance = distance;
3656  SCIPswapPointers(&hashset->slots[pos], &element);
3657  }
3658 
3659  /* continue until we have found an empty position */
3660  pos = (pos + 1) & mask;
3661  ++elemdistance;
3662  }
3663 }
3664 
3665 /** check if the load factor of the hash set is too high and rebuild if necessary */
3666 static
3668  SCIP_HASHSET* hashset, /**< hash set */
3669  BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3670  )
3671 {
3672  assert(hashset != NULL);
3673  assert(hashset->shift < 64);
3674 
3675  /* use integer arithmetic to approximately check if load factor is above 90% */
3676  if( ((((uint64_t)hashset->nelements)<<10)>>(64-hashset->shift) > 921) )
3677  {
3678  void** slots;
3679  uint32_t nslots;
3680  uint32_t newnslots;
3681  uint32_t i;
3682 
3683  /* calculate new size (always power of two) */
3684  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3685  newnslots = 2*nslots;
3686  --hashset->shift;
3687 
3688  /* reallocate array */
3689  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &slots, newnslots) );
3690 
3691  SCIPswapPointers((void**) &slots, (void**) &hashset->slots);
3692  hashset->nelements = 0;
3693 
3694  /* reinsert all elements */
3695  for( i = 0; i < nslots; ++i )
3696  {
3697  if( slots[i] != NULL )
3698  hashsetInsert(hashset, slots[i]);
3699  }
3700 
3701  BMSfreeBlockMemoryArray(blkmem, &slots, nslots);
3702  }
3703 
3704  return SCIP_OKAY;
3705 }
3706 
3707 /** creates a hash set of pointers */
3709  SCIP_HASHSET** hashset, /**< pointer to store the created hash set */
3710  BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3711  int size /**< initial size of the hash set; it is guaranteed that the set is not
3712  * resized if at most that many elements are inserted */
3713  )
3714 {
3715  uint32_t nslots;
3716 
3717  assert(hashset != NULL);
3718  assert(size >= 0);
3719  assert(blkmem != NULL);
3720 
3721  SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashset) );
3722 
3723  /* do not create too small hashtables, i.e. at least size 32, and increase
3724  * the given size by dividing it by 0.9, since then no rebuilding will
3725  * be necessary if the given number of elements are inserted. Finally round
3726  * to the next power of two.
3727  */
3728  (*hashset)->shift = 64;
3729  (*hashset)->shift -= (unsigned int)ceil(log(MAX(8.0, size / 0.9)) / log(2.0));
3730  nslots = (uint32_t)SCIPhashsetGetNSlots(*hashset);
3731  (*hashset)->nelements = 0;
3732 
3733  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashset)->slots, nslots) );
3734 
3735  return SCIP_OKAY;
3736 }
3737 
3738 /** frees the hash set */
3740  SCIP_HASHSET** hashset, /**< pointer to the hash set */
3741  BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3742  )
3743 {
3744  BMSfreeBlockMemoryArray(blkmem, &(*hashset)->slots, SCIPhashsetGetNSlots(*hashset));
3745  BMSfreeBlockMemory(blkmem, hashset);
3746 }
3747 
3748 /** inserts new element into the hash set */
3750  SCIP_HASHSET* hashset, /**< hash set */
3751  BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3752  void* element /**< element to insert */
3753  )
3754 {
3755  assert(hashset != NULL);
3756  assert(hashset->slots != NULL);
3757 
3758  SCIP_CALL( hashsetCheckLoad(hashset, blkmem) );
3759 
3760  hashsetInsert(hashset, element);
3761 
3762  return SCIP_OKAY;
3763 }
3764 
3765 /** checks whether an element exists in the hash set */
3767  SCIP_HASHSET* hashset, /**< hash set */
3768  void* element /**< element to search for */
3769  )
3770 {
3771  uint32_t pos;
3772  uint32_t nslots;
3773  uint32_t mask;
3774  uint32_t elemdistance;
3775 
3776  assert(hashset != NULL);
3777  assert(hashset->slots != NULL);
3778 
3779  pos = hashSetDesiredPos(hashset, element);
3780  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3781  mask = nslots - 1;
3782  elemdistance = 0;
3783 
3784  while( TRUE ) /*lint !e716*/
3785  {
3786  uint32_t distance;
3787 
3788  /* found element */
3789  if( hashset->slots[pos] == element )
3790  return TRUE;
3791 
3792  /* slots is empty so element cannot be contained */
3793  if( hashset->slots[pos] == NULL )
3794  return FALSE;
3795 
3796  distance = ELEM_DISTANCE(pos);
3797  /* element can not be contained since otherwise we would have swapped it with this one during insert */
3798  if( elemdistance > distance )
3799  return FALSE;
3800 
3801  pos = (pos + 1) & mask;
3802  ++elemdistance;
3803  }
3804 }
3805 
3806 /** removes an element from the hash set, if it exists */
3808  SCIP_HASHSET* hashset, /**< hash set */
3809  void* element /**< origin to remove from the list */
3810  )
3811 {
3812  uint32_t pos;
3813  uint32_t nslots;
3814  uint32_t mask;
3815  uint32_t elemdistance;
3816 
3817  assert(hashset != NULL);
3818  assert(hashset->slots != NULL);
3819  assert(element != NULL);
3820 
3821  pos = hashSetDesiredPos(hashset, element);
3822  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3823  mask = nslots - 1;
3824  elemdistance = 0;
3825 
3826  while( TRUE ) /*lint !e716*/
3827  {
3828  uint32_t distance;
3829 
3830  /* found element */
3831  if( hashset->slots[pos] == element )
3832  break;
3833 
3834  /* slots is empty so element cannot be contained */
3835  if( hashset->slots[pos] == NULL )
3836  return SCIP_OKAY;
3837 
3838  distance = ELEM_DISTANCE(pos);
3839  /* element can not be contained since otherwise we would have swapped it with this one during insert */
3840  if( elemdistance > distance )
3841  return SCIP_OKAY;
3842 
3843  pos = (pos + 1) & mask;
3844  ++elemdistance;
3845  }
3846 
3847  assert(hashset->slots[pos] == element);
3848  assert(SCIPhashsetExists(hashset, element));
3849 
3850  /* remove element */
3851  --hashset->nelements;
3852 
3853  /* move other elements if necessary */
3854  while( TRUE ) /*lint !e716*/
3855  {
3856  uint32_t nextpos = (pos + 1) & mask;
3857 
3858  /* nothing to do since there is no chain that needs to be moved */
3859  if( hashset->slots[nextpos] == NULL )
3860  {
3861  hashset->slots[pos] = NULL;
3862  assert(!SCIPhashsetExists(hashset, element));
3863  return SCIP_OKAY;
3864  }
3865 
3866  /* check if the element is the start of a new chain and return if that is the case */
3867  if( hashSetDesiredPos(hashset, hashset->slots[nextpos]) == nextpos )
3868  {
3869  hashset->slots[pos] = NULL;
3870  assert(!SCIPhashsetExists(hashset, element));
3871  return SCIP_OKAY;
3872  }
3873 
3874  /* element should be moved to the left and next element needs to be checked */
3875  hashset->slots[pos] = hashset->slots[nextpos];
3876 
3877  pos = nextpos;
3878  }
3879 }
3880 
3881 /** prints statistics about hash set usage */
3883  SCIP_HASHSET* hashset, /**< hash set */
3884  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3885  )
3886 {
3887  uint32_t maxprobelen = 0;
3888  uint64_t probelensum = 0;
3889  uint32_t nslots;
3890  uint32_t mask;
3891  uint32_t i;
3892 
3893  assert(hashset != NULL);
3894 
3895  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3896  mask = nslots - 1;
3897 
3898  /* compute the maximum and average probe length */
3899  for( i = 0; i < nslots; ++i )
3900  {
3901  if( hashset->slots[i] != NULL )
3902  {
3903  uint32_t probelen = ((hashSetDesiredPos(hashset, hashset->slots[i]) + nslots - i) & mask) + 1;
3904  probelensum += probelen;
3905  maxprobelen = MAX(probelen, maxprobelen);
3906  }
3907  }
3908 
3909  /* print general hash set statistics */
3910  SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3911  (unsigned int)hashset->nelements, (unsigned int)hashset->nelements,
3912  (unsigned int)nslots, 100.0*(SCIP_Real)hashset->nelements/(SCIP_Real)(nslots));
3913 
3914  /* if not empty print average and maximum probe length */
3915  if( hashset->nelements > 0 )
3916  SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3917  (SCIP_Real)(probelensum)/(SCIP_Real)hashset->nelements, (unsigned int)maxprobelen);
3918  SCIPmessagePrintInfo(messagehdlr, "\n");
3919 }
3920 
3921 /* In debug mode, the following methods are implemented as function calls to ensure
3922  * type validity.
3923  * In optimized mode, the methods are implemented as defines to improve performance.
3924  * However, we want to have them in the library anyways, so we have to undef the defines.
3925  */
3926 
3927 #undef SCIPhashsetIsEmpty
3928 #undef SCIPhashsetGetNElements
3929 #undef SCIPhashsetGetNSlots
3930 #undef SCIPhashsetGetSlots
3931 
3932 /** indicates whether a hash set has no entries */
3934  SCIP_HASHSET* hashset /**< hash set */
3935  )
3936 {
3937  return hashset->nelements == 0;
3938 }
3939 
3940 /** gives the number of elements in a hash set */
3942  SCIP_HASHSET* hashset /**< hash set */
3943  )
3944 {
3945  return (int)hashset->nelements;
3946 }
3947 
3948 /** gives the number of slots of a hash set */
3950  SCIP_HASHSET* hashset /**< hash set */
3951  )
3952 {
3953  return (int) (1u << (64 - hashset->shift));
3954 }
3955 
3956 /** gives the array of hash set slots; contains all elements in indetermined order and may contain NULL values */
3958  SCIP_HASHSET* hashset /**< hash set */
3959  )
3960 {
3961  return hashset->slots;
3962 }
3963 
3964 /** removes all entries in a hash set. */
3966  SCIP_HASHSET* hashset /**< hash set */
3967  )
3968 {
3969  BMSclearMemoryArray(hashset->slots, SCIPhashsetGetNSlots(hashset));
3970 
3971  hashset->nelements = 0;
3972 }
3973 
3974 /*
3975  * Dynamic Arrays
3976  */
3977 
3978 /** creates a dynamic array of real values */
3980  SCIP_REALARRAY** realarray, /**< pointer to store the real array */
3981  BMS_BLKMEM* blkmem /**< block memory */
3982  )
3983 {
3984  assert(realarray != NULL);
3985  assert(blkmem != NULL);
3986 
3987  SCIP_ALLOC( BMSallocBlockMemory(blkmem, realarray) );
3988  (*realarray)->blkmem = blkmem;
3989  (*realarray)->vals = NULL;
3990  (*realarray)->valssize = 0;
3991  (*realarray)->firstidx = -1;
3992  (*realarray)->minusedidx = INT_MAX;
3993  (*realarray)->maxusedidx = INT_MIN;
3994 
3995  return SCIP_OKAY;
3996 }
3997 
3998 /** creates a copy of a dynamic array of real values */
4000  SCIP_REALARRAY** realarray, /**< pointer to store the copied real array */
4001  BMS_BLKMEM* blkmem, /**< block memory */
4002  SCIP_REALARRAY* sourcerealarray /**< dynamic real array to copy */
4003  )
4004 {
4005  assert(realarray != NULL);
4006  assert(sourcerealarray != NULL);
4007 
4008  SCIP_CALL( SCIPrealarrayCreate(realarray, blkmem) );
4009  if( sourcerealarray->valssize > 0 )
4010  {
4011  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*realarray)->vals, sourcerealarray->vals, \
4012  sourcerealarray->valssize) );
4013  }
4014  (*realarray)->valssize = sourcerealarray->valssize;
4015  (*realarray)->firstidx = sourcerealarray->firstidx;
4016  (*realarray)->minusedidx = sourcerealarray->minusedidx;
4017  (*realarray)->maxusedidx = sourcerealarray->maxusedidx;
4018 
4019  return SCIP_OKAY;
4020 }
4021 
4022 /** frees a dynamic array of real values */
4024  SCIP_REALARRAY** realarray /**< pointer to the real array */
4025  )
4026 {
4027  assert(realarray != NULL);
4028  assert(*realarray != NULL);
4029 
4030  BMSfreeBlockMemoryArrayNull((*realarray)->blkmem, &(*realarray)->vals, (*realarray)->valssize);
4031  BMSfreeBlockMemory((*realarray)->blkmem, realarray);
4032 
4033  return SCIP_OKAY;
4034 }
4035 
4036 /** extends dynamic array to be able to store indices from minidx to maxidx */
4038  SCIP_REALARRAY* realarray, /**< dynamic real array */
4039  int arraygrowinit, /**< initial size of array */
4040  SCIP_Real arraygrowfac, /**< growing factor of array */
4041  int minidx, /**< smallest index to allocate storage for */
4042  int maxidx /**< largest index to allocate storage for */
4043  )
4044 {
4045  int nused;
4046  int nfree;
4047  int newfirstidx;
4048  int i;
4049 
4050  assert(realarray != NULL);
4051  assert(realarray->minusedidx == INT_MAX || realarray->firstidx >= 0);
4052  assert(realarray->maxusedidx == INT_MIN || realarray->firstidx >= 0);
4053  assert(realarray->minusedidx == INT_MAX || realarray->minusedidx >= realarray->firstidx);
4054  assert(realarray->maxusedidx == INT_MIN || realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4055  assert(0 <= minidx);
4056  assert(minidx <= maxidx);
4057 
4058  minidx = MIN(minidx, realarray->minusedidx);
4059  maxidx = MAX(maxidx, realarray->maxusedidx);
4060  assert(0 <= minidx);
4061  assert(minidx <= maxidx);
4062 
4063  SCIPdebugMessage("extending realarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4064  (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, minidx, maxidx);
4065 
4066  /* check, whether we have to allocate additional memory, or shift the array */
4067  nused = maxidx - minidx + 1;
4068  if( nused > realarray->valssize )
4069  {
4070  SCIP_Real* newvals;
4071  int newvalssize;
4072 
4073  /* allocate new memory storage */
4074  newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4075  SCIP_ALLOC( BMSallocBlockMemoryArray(realarray->blkmem, &newvals, newvalssize) );
4076  nfree = newvalssize - nused;
4077  newfirstidx = minidx - nfree/2;
4078  newfirstidx = MAX(newfirstidx, 0);
4079  assert(newfirstidx <= minidx);
4080  assert(maxidx < newfirstidx + newvalssize);
4081 
4082  /* initialize memory array by copying old values and setting new values to zero */
4083  if( realarray->firstidx != -1 )
4084  {
4085  for( i = 0; i < realarray->minusedidx - newfirstidx; ++i )
4086  newvals[i] = 0.0;
4087 
4088  /* check for possible overflow or negative value */
4089  assert(realarray->maxusedidx - realarray->minusedidx + 1 > 0);
4090 
4091  BMScopyMemoryArray(&newvals[realarray->minusedidx - newfirstidx],
4092  &(realarray->vals[realarray->minusedidx - realarray->firstidx]),
4093  realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866 !e776*/
4094  for( i = realarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4095  newvals[i] = 0.0;
4096  }
4097  else
4098  {
4099  for( i = 0; i < newvalssize; ++i )
4100  newvals[i] = 0.0;
4101  }
4102 
4103  /* free old memory storage, and set the new array parameters */
4104  BMSfreeBlockMemoryArrayNull(realarray->blkmem, &realarray->vals, realarray->valssize);
4105  realarray->vals = newvals;
4106  realarray->valssize = newvalssize;
4107  realarray->firstidx = newfirstidx;
4108  }
4109  else if( realarray->firstidx == -1 )
4110  {
4111  /* a sufficiently large memory storage exists, but it was cleared */
4112  nfree = realarray->valssize - nused;
4113  assert(nfree >= 0);
4114  realarray->firstidx = minidx - nfree/2;
4115  assert(realarray->firstidx <= minidx);
4116  assert(maxidx < realarray->firstidx + realarray->valssize);
4117 #ifndef NDEBUG
4118  for( i = 0; i < realarray->valssize; ++i )
4119  assert(realarray->vals[i] == 0.0);
4120 #endif
4121  }
4122  else if( minidx < realarray->firstidx )
4123  {
4124  /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4125  nfree = realarray->valssize - nused;
4126  assert(nfree >= 0);
4127  newfirstidx = minidx - nfree/2;
4128  newfirstidx = MAX(newfirstidx, 0);
4129  assert(newfirstidx <= minidx);
4130  assert(maxidx < newfirstidx + realarray->valssize);
4131 
4132  if( realarray->minusedidx <= realarray->maxusedidx )
4133  {
4134  int shift;
4135 
4136  assert(realarray->firstidx <= realarray->minusedidx);
4137  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4138 
4139  /* shift used part of array to the right */
4140  shift = realarray->firstidx - newfirstidx;
4141  assert(shift > 0);
4142  for( i = realarray->maxusedidx - realarray->firstidx; i >= realarray->minusedidx - realarray->firstidx; --i )
4143  {
4144  assert(0 <= i + shift && i + shift < realarray->valssize);
4145  realarray->vals[i + shift] = realarray->vals[i];
4146  }
4147  /* clear the formerly used head of the array */
4148  for( i = 0; i < shift; ++i )
4149  realarray->vals[realarray->minusedidx - realarray->firstidx + i] = 0.0;
4150  }
4151  realarray->firstidx = newfirstidx;
4152  }
4153  else if( maxidx >= realarray->firstidx + realarray->valssize )
4154  {
4155  /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4156  nfree = realarray->valssize - nused;
4157  assert(nfree >= 0);
4158  newfirstidx = minidx - nfree/2;
4159  newfirstidx = MAX(newfirstidx, 0);
4160  assert(newfirstidx <= minidx);
4161  assert(maxidx < newfirstidx + realarray->valssize);
4162 
4163  if( realarray->minusedidx <= realarray->maxusedidx )
4164  {
4165  int shift;
4166 
4167  assert(realarray->firstidx <= realarray->minusedidx);
4168  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4169 
4170  /* shift used part of array to the left */
4171  shift = newfirstidx - realarray->firstidx;
4172  assert(shift > 0);
4173  for( i = realarray->minusedidx - realarray->firstidx; i <= realarray->maxusedidx - realarray->firstidx; ++i )
4174  {
4175  assert(0 <= i - shift && i - shift < realarray->valssize);
4176  realarray->vals[i - shift] = realarray->vals[i];
4177  }
4178  /* clear the formerly used tail of the array */
4179  for( i = 0; i < shift; ++i )
4180  realarray->vals[realarray->maxusedidx - realarray->firstidx - i] = 0.0;
4181  }
4182  realarray->firstidx = newfirstidx;
4183  }
4184 
4185  assert(minidx >= realarray->firstidx);
4186  assert(maxidx < realarray->firstidx + realarray->valssize);
4187 
4188  return SCIP_OKAY;
4189 }
4190 
4191 /** clears a dynamic real array */
4193  SCIP_REALARRAY* realarray /**< dynamic real array */
4194  )
4195 {
4196  assert(realarray != NULL);
4197 
4198  SCIPdebugMessage("clearing realarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4199  (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx);
4200 
4201  if( realarray->minusedidx <= realarray->maxusedidx )
4202  {
4203  assert(realarray->firstidx <= realarray->minusedidx);
4204  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4205  assert(realarray->firstidx != -1);
4206  assert(realarray->valssize > 0);
4207 
4208  /* clear the used part of array */
4209  BMSclearMemoryArray(&realarray->vals[realarray->minusedidx - realarray->firstidx],
4210  realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866*/
4211 
4212  /* mark the array cleared */
4213  realarray->minusedidx = INT_MAX;
4214  realarray->maxusedidx = INT_MIN;
4215  }
4216  assert(realarray->minusedidx == INT_MAX);
4217  assert(realarray->maxusedidx == INT_MIN);
4218 
4219  return SCIP_OKAY;
4220 }
4221 
4222 /** gets value of entry in dynamic array */
4224  SCIP_REALARRAY* realarray, /**< dynamic real array */
4225  int idx /**< array index to get value for */
4226  )
4227 {
4228  assert(realarray != NULL);
4229  assert(idx >= 0);
4230 
4231  if( idx < realarray->minusedidx || idx > realarray->maxusedidx )
4232  return 0.0;
4233  else
4234  {
4235  assert(realarray->vals != NULL);
4236  assert(idx - realarray->firstidx >= 0);
4237  assert(idx - realarray->firstidx < realarray->valssize);
4238 
4239  return realarray->vals[idx - realarray->firstidx];
4240  }
4241 }
4242 
4243 /** sets value of entry in dynamic array */
4245  SCIP_REALARRAY* realarray, /**< dynamic real array */
4246  int arraygrowinit, /**< initial size of array */
4247  SCIP_Real arraygrowfac, /**< growing factor of array */
4248  int idx, /**< array index to set value for */
4249  SCIP_Real val /**< value to set array index to */
4250  )
4251 {
4252  assert(realarray != NULL);
4253  assert(idx >= 0);
4254 
4255  SCIPdebugMessage("setting realarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %g\n",
4256  (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, idx, val);
4257 
4258  if( val != 0.0 )
4259  {
4260  /* extend array to be able to store the index */
4261  SCIP_CALL( SCIPrealarrayExtend(realarray, arraygrowinit, arraygrowfac, idx, idx) );
4262  assert(idx >= realarray->firstidx);
4263  assert(idx < realarray->firstidx + realarray->valssize);
4264 
4265  /* set the array value of the index */
4266  realarray->vals[idx - realarray->firstidx] = val;
4267 
4268  /* update min/maxusedidx */
4269  realarray->minusedidx = MIN(realarray->minusedidx, idx);
4270  realarray->maxusedidx = MAX(realarray->maxusedidx, idx);
4271  }
4272  else if( idx >= realarray->firstidx && idx < realarray->firstidx + realarray->valssize )
4273  {
4274  /* set the array value of the index to zero */
4275  realarray->vals[idx - realarray->firstidx] = 0.0;
4276 
4277  /* check, if we can tighten the min/maxusedidx */
4278  if( idx == realarray->minusedidx )
4279  {
4280  assert(realarray->maxusedidx >= 0);
4281  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4282  do
4283  {
4284  realarray->minusedidx++;
4285  }
4286  while( realarray->minusedidx <= realarray->maxusedidx
4287  && realarray->vals[realarray->minusedidx - realarray->firstidx] == 0.0 );
4288 
4289  if( realarray->minusedidx > realarray->maxusedidx )
4290  {
4291  realarray->minusedidx = INT_MAX;
4292  realarray->maxusedidx = INT_MIN;
4293  }
4294  }
4295  else if( idx == realarray->maxusedidx )
4296  {
4297  assert(realarray->minusedidx >= 0);
4298  assert(realarray->minusedidx < realarray->maxusedidx);
4299  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4300  do
4301  {
4302  realarray->maxusedidx--;
4303  assert(realarray->minusedidx <= realarray->maxusedidx);
4304  }
4305  while( realarray->vals[realarray->maxusedidx - realarray->firstidx] == 0.0 );
4306  }
4307  }
4308 
4309  return SCIP_OKAY;
4310 }
4311 
4312 /** increases value of entry in dynamic array */
4314  SCIP_REALARRAY* realarray, /**< dynamic real array */
4315  int arraygrowinit, /**< initial size of array */
4316  SCIP_Real arraygrowfac, /**< growing factor of array */
4317  int idx, /**< array index to increase value for */
4318  SCIP_Real incval /**< value to increase array index */
4319  )
4320 {
4321  SCIP_Real oldval;
4322 
4323  oldval = SCIPrealarrayGetVal(realarray, idx);
4324  if( oldval != SCIP_INVALID ) /*lint !e777*/
4325  return SCIPrealarraySetVal(realarray, arraygrowinit, arraygrowfac, idx, oldval + incval);
4326  else
4327  return SCIP_OKAY;
4328 }
4329 
4330 /** returns the minimal index of all stored non-zero elements */
4332  SCIP_REALARRAY* realarray /**< dynamic real array */
4333  )
4334 {
4335  assert(realarray != NULL);
4336 
4337  return realarray->minusedidx;
4338 }
4339 
4340 /** returns the maximal index of all stored non-zero elements */
4342  SCIP_REALARRAY* realarray /**< dynamic real array */
4343  )
4344 {
4345  assert(realarray != NULL);
4346 
4347  return realarray->maxusedidx;
4348 }
4349 
4350 /** creates a dynamic array of int values */
4352  SCIP_INTARRAY** intarray, /**< pointer to store the int array */
4353  BMS_BLKMEM* blkmem /**< block memory */
4354  )
4355 {
4356  assert(intarray != NULL);
4357  assert(blkmem != NULL);
4358 
4359  SCIP_ALLOC( BMSallocBlockMemory(blkmem, intarray) );
4360  (*intarray)->blkmem = blkmem;
4361  (*intarray)->vals = NULL;
4362  (*intarray)->valssize = 0;
4363  (*intarray)->firstidx = -1;
4364  (*intarray)->minusedidx = INT_MAX;
4365  (*intarray)->maxusedidx = INT_MIN;
4366 
4367  return SCIP_OKAY;
4368 }
4369 
4370 /** creates a copy of a dynamic array of int values */
4372  SCIP_INTARRAY** intarray, /**< pointer to store the copied int array */
4373  BMS_BLKMEM* blkmem, /**< block memory */
4374  SCIP_INTARRAY* sourceintarray /**< dynamic int array to copy */
4375  )
4376 {
4377  assert(intarray != NULL);
4378  assert(sourceintarray != NULL);
4379 
4380  SCIP_CALL( SCIPintarrayCreate(intarray, blkmem) );
4381  if( sourceintarray->valssize > 0 )
4382  {
4383  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*intarray)->vals, sourceintarray->vals, sourceintarray->valssize) );
4384  }
4385  (*intarray)->valssize = sourceintarray->valssize;
4386  (*intarray)->firstidx = sourceintarray->firstidx;
4387  (*intarray)->minusedidx = sourceintarray->minusedidx;
4388  (*intarray)->maxusedidx = sourceintarray->maxusedidx;
4389 
4390  return SCIP_OKAY;
4391 }
4392 
4393 /** frees a dynamic array of int values */
4395  SCIP_INTARRAY** intarray /**< pointer to the int array */
4396  )
4397 {
4398  assert(intarray != NULL);
4399  assert(*intarray != NULL);
4400 
4401  BMSfreeBlockMemoryArrayNull((*intarray)->blkmem, &(*intarray)->vals, (*intarray)->valssize);
4402  BMSfreeBlockMemory((*intarray)->blkmem, intarray);
4403 
4404  return SCIP_OKAY;
4405 }
4406 
4407 /** extends dynamic array to be able to store indices from minidx to maxidx */
4409  SCIP_INTARRAY* intarray, /**< dynamic int array */
4410  int arraygrowinit, /**< initial size of array */
4411  SCIP_Real arraygrowfac, /**< growing factor of array */
4412  int minidx, /**< smallest index to allocate storage for */
4413  int maxidx /**< largest index to allocate storage for */
4414  )
4415 {
4416  int nused;
4417  int nfree;
4418  int newfirstidx;
4419  int i;
4420 
4421  assert(intarray != NULL);
4422  assert(intarray->minusedidx == INT_MAX || intarray->firstidx >= 0);
4423  assert(intarray->maxusedidx == INT_MIN || intarray->firstidx >= 0);
4424  assert(intarray->minusedidx == INT_MAX || intarray->minusedidx >= intarray->firstidx);
4425  assert(intarray->maxusedidx == INT_MIN || intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4426  assert(0 <= minidx);
4427  assert(minidx <= maxidx);
4428 
4429  minidx = MIN(minidx, intarray->minusedidx);
4430  maxidx = MAX(maxidx, intarray->maxusedidx);
4431  assert(0 <= minidx);
4432  assert(minidx <= maxidx);
4433 
4434  SCIPdebugMessage("extending intarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4435  (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, minidx, maxidx);
4436 
4437  /* check, whether we have to allocate additional memory, or shift the array */
4438  nused = maxidx - minidx + 1;
4439  if( nused > intarray->valssize )
4440  {
4441  int* newvals;
4442  int newvalssize;
4443 
4444  /* allocate new memory storage */
4445  newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4446  SCIP_ALLOC( BMSallocBlockMemoryArray(intarray->blkmem, &newvals, newvalssize) );
4447  nfree = newvalssize - nused;
4448  newfirstidx = minidx - nfree/2;
4449  newfirstidx = MAX(newfirstidx, 0);
4450  assert(newfirstidx <= minidx);
4451  assert(maxidx < newfirstidx + newvalssize);
4452 
4453  /* initialize memory array by copying old values and setting new values to zero */
4454  if( intarray->firstidx != -1 )
4455  {
4456  for( i = 0; i < intarray->minusedidx - newfirstidx; ++i )
4457  newvals[i] = 0;
4458 
4459  /* check for possible overflow or negative value */
4460  assert(intarray->maxusedidx - intarray->minusedidx + 1 > 0);
4461 
4462  BMScopyMemoryArray(&newvals[intarray->minusedidx - newfirstidx],
4463  &intarray->vals[intarray->minusedidx - intarray->firstidx],
4464  intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866 !e776*/
4465  for( i = intarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4466  newvals[i] = 0;
4467  }
4468  else
4469  {
4470  for( i = 0; i < newvalssize; ++i )
4471  newvals[i] = 0;
4472  }
4473 
4474  /* free old memory storage, and set the new array parameters */
4475  BMSfreeBlockMemoryArrayNull(intarray->blkmem, &intarray->vals, intarray->valssize);
4476  intarray->vals = newvals;
4477  intarray->valssize = newvalssize;
4478  intarray->firstidx = newfirstidx;
4479  }
4480  else if( intarray->firstidx == -1 )
4481  {
4482  /* a sufficiently large memory storage exists, but it was cleared */
4483  nfree = intarray->valssize - nused;
4484  assert(nfree >= 0);
4485  intarray->firstidx = minidx - nfree/2;
4486  assert(intarray->firstidx <= minidx);
4487  assert(maxidx < intarray->firstidx + intarray->valssize);
4488 #ifndef NDEBUG
4489  for( i = 0; i < intarray->valssize; ++i )
4490  assert(intarray->vals[i] == 0);
4491 #endif
4492  }
4493  else if( minidx < intarray->firstidx )
4494  {
4495  /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4496  nfree = intarray->valssize - nused;
4497  assert(nfree >= 0);
4498  newfirstidx = minidx - nfree/2;
4499  newfirstidx = MAX(newfirstidx, 0);
4500  assert(newfirstidx <= minidx);
4501  assert(maxidx < newfirstidx + intarray->valssize);
4502 
4503  if( intarray->minusedidx <= intarray->maxusedidx )
4504  {
4505  int shift;
4506 
4507  assert(intarray->firstidx <= intarray->minusedidx);
4508  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4509 
4510  /* shift used part of array to the right */
4511  shift = intarray->firstidx - newfirstidx;
4512  assert(shift > 0);
4513  for( i = intarray->maxusedidx - intarray->firstidx; i >= intarray->minusedidx - intarray->firstidx; --i )
4514  {
4515  assert(0 <= i + shift && i + shift < intarray->valssize);
4516  intarray->vals[i + shift] = intarray->vals[i];
4517  }
4518  /* clear the formerly used head of the array */
4519  for( i = 0; i < shift; ++i )
4520  intarray->vals[intarray->minusedidx - intarray->firstidx + i] = 0;
4521  }
4522  intarray->firstidx = newfirstidx;
4523  }
4524  else if( maxidx >= intarray->firstidx + intarray->valssize )
4525  {
4526  /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4527  nfree = intarray->valssize - nused;
4528  assert(nfree >= 0);
4529  newfirstidx = minidx - nfree/2;
4530  newfirstidx = MAX(newfirstidx, 0);
4531  assert(newfirstidx <= minidx);
4532  assert(maxidx < newfirstidx + intarray->valssize);
4533 
4534  if( intarray->minusedidx <= intarray->maxusedidx )
4535  {
4536  int shift;
4537 
4538  assert(intarray->firstidx <= intarray->minusedidx);
4539  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4540 
4541  /* shift used part of array to the left */
4542  shift = newfirstidx - intarray->firstidx;
4543  assert(shift > 0);
4544  for( i = intarray->minusedidx - intarray->firstidx; i <= intarray->maxusedidx - intarray->firstidx; ++i )
4545  {
4546  assert(0 <= i - shift && i - shift < intarray->valssize);
4547  intarray->vals[i - shift] = intarray->vals[i];
4548  }
4549  /* clear the formerly used tail of the array */
4550  for( i = 0; i < shift; ++i )
4551  intarray->vals[intarray->maxusedidx - intarray->firstidx - i] = 0;
4552  }
4553  intarray->firstidx = newfirstidx;
4554  }
4555 
4556  assert(minidx >= intarray->firstidx);
4557  assert(maxidx < intarray->firstidx + intarray->valssize);
4558 
4559  return SCIP_OKAY;
4560 }
4561 
4562 /** clears a dynamic int array */
4564  SCIP_INTARRAY* intarray /**< dynamic int array */
4565  )
4566 {
4567  assert(intarray != NULL);
4568 
4569  SCIPdebugMessage("clearing intarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4570  (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx);
4571 
4572  if( intarray->minusedidx <= intarray->maxusedidx )
4573  {
4574  assert(intarray->firstidx <= intarray->minusedidx);
4575  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4576  assert(intarray->firstidx != -1);
4577  assert(intarray->valssize > 0);
4578 
4579  /* clear the used part of array */
4580  BMSclearMemoryArray(&intarray->vals[intarray->minusedidx - intarray->firstidx],
4581  intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866*/
4582 
4583  /* mark the array cleared */
4584  intarray->minusedidx = INT_MAX;
4585  intarray->maxusedidx = INT_MIN;
4586  }
4587  assert(intarray->minusedidx == INT_MAX);
4588  assert(intarray->maxusedidx == INT_MIN);
4589 
4590  return SCIP_OKAY;
4591 }
4592 
4593 /** gets value of entry in dynamic array */
4595  SCIP_INTARRAY* intarray, /**< dynamic int array */
4596  int idx /**< array index to get value for */
4597  )
4598 {
4599  assert(intarray != NULL);
4600  assert(idx >= 0);
4601 
4602  if( idx < intarray->minusedidx || idx > intarray->maxusedidx )
4603  return 0;
4604  else
4605  {
4606  assert(intarray->vals != NULL);
4607  assert(idx - intarray->firstidx >= 0);
4608  assert(idx - intarray->firstidx < intarray->valssize);
4609 
4610  return intarray->vals[idx - intarray->firstidx];
4611  }
4612 }
4613 
4614 /** sets value of entry in dynamic array */
4616  SCIP_INTARRAY* intarray, /**< dynamic int 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  int val /**< value to set array index to */
4621  )
4622 {
4623  assert(intarray != NULL);
4624  assert(idx >= 0);
4625 
4626  SCIPdebugMessage("setting intarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %d\n",
4627  (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, idx, val);
4628 
4629  if( val != 0 )
4630  {
4631  /* extend array to be able to store the index */
4632  SCIP_CALL( SCIPintarrayExtend(intarray, arraygrowinit, arraygrowfac, idx, idx) );
4633  assert(idx >= intarray->firstidx);
4634  assert(idx < intarray->firstidx + intarray->valssize);
4635 
4636  /* set the array value of the index */
4637  intarray->vals[idx - intarray->firstidx] = val;
4638 
4639  /* update min/maxusedidx */
4640  intarray->minusedidx = MIN(intarray->minusedidx, idx);
4641  intarray->maxusedidx = MAX(intarray->maxusedidx, idx);
4642  }
4643  else if( idx >= intarray->firstidx && idx < intarray->firstidx + intarray->valssize )
4644  {
4645  /* set the array value of the index to zero */
4646  intarray->vals[idx - intarray->firstidx] = 0;
4647 
4648  /* check, if we can tighten the min/maxusedidx */
4649  if( idx == intarray->minusedidx )
4650  {
4651  assert(intarray->maxusedidx >= 0);
4652  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4653  do
4654  {
4655  intarray->minusedidx++;
4656  }
4657  while( intarray->minusedidx <= intarray->maxusedidx
4658  && intarray->vals[intarray->minusedidx - intarray->firstidx] == 0 );
4659  if( intarray->minusedidx > intarray->maxusedidx )
4660  {
4661  intarray->minusedidx = INT_MAX;
4662  intarray->maxusedidx = INT_MIN;
4663  }
4664  }
4665  else if( idx == intarray->maxusedidx )
4666  {
4667  assert(intarray->minusedidx >= 0);
4668  assert(intarray->minusedidx < intarray->maxusedidx);
4669  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4670  do
4671  {
4672  intarray->maxusedidx--;
4673  assert(intarray->minusedidx <= intarray->maxusedidx);
4674  }
4675  while( intarray->vals[intarray->maxusedidx - intarray->firstidx] == 0 );
4676  }
4677  }
4678 
4679  return SCIP_OKAY;
4680 }
4681 
4682 /** increases value of entry in dynamic array */
4684  SCIP_INTARRAY* intarray, /**< dynamic int array */
4685  int arraygrowinit, /**< initial size of array */
4686  SCIP_Real arraygrowfac, /**< growing factor of array */
4687  int idx, /**< array index to increase value for */
4688  int incval /**< value to increase array index */
4689  )
4690 {
4691  return SCIPintarraySetVal(intarray, arraygrowinit, arraygrowfac, idx, SCIPintarrayGetVal(intarray, idx) + incval);
4692 }
4693 
4694 /** returns the minimal index of all stored non-zero elements */
4696  SCIP_INTARRAY* intarray /**< dynamic int array */
4697  )
4698 {
4699  assert(intarray != NULL);
4700 
4701  return intarray->minusedidx;
4702 }
4703 
4704 /** returns the maximal index of all stored non-zero elements */
4706  SCIP_INTARRAY* intarray /**< dynamic int array */
4707  )
4708 {
4709  assert(intarray != NULL);
4710 
4711  return intarray->maxusedidx;
4712 }
4713 
4714 
4715 /** creates a dynamic array of bool values */
4717  SCIP_BOOLARRAY** boolarray, /**< pointer to store the bool array */
4718  BMS_BLKMEM* blkmem /**< block memory */
4719  )
4720 {
4721  assert(boolarray != NULL);
4722  assert(blkmem != NULL);
4723 
4724  SCIP_ALLOC( BMSallocBlockMemory(blkmem, boolarray) );
4725  (*boolarray)->blkmem = blkmem;
4726  (*boolarray)->vals = NULL;
4727  (*boolarray)->valssize = 0;
4728  (*boolarray)->firstidx = -1;
4729  (*boolarray)->minusedidx = INT_MAX;
4730  (*boolarray)->maxusedidx = INT_MIN;
4731 
4732  return SCIP_OKAY;
4733 }
4734 
4735 /** creates a copy of a dynamic array of bool values */
4737  SCIP_BOOLARRAY** boolarray, /**< pointer to store the copied bool array */
4738  BMS_BLKMEM* blkmem, /**< block memory */
4739  SCIP_BOOLARRAY* sourceboolarray /**< dynamic bool array to copy */
4740  )
4741 {
4742  assert(boolarray != NULL);
4743  assert(sourceboolarray != NULL);
4744 
4745  SCIP_CALL( SCIPboolarrayCreate(boolarray, blkmem) );
4746  if( sourceboolarray->valssize > 0 )
4747  {
4748  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*boolarray)->vals, sourceboolarray->vals, \
4749  sourceboolarray->valssize) );
4750  }
4751  (*boolarray)->valssize = sourceboolarray->valssize;
4752  (*boolarray)->firstidx = sourceboolarray->firstidx;
4753  (*boolarray)->minusedidx = sourceboolarray->minusedidx;
4754  (*boolarray)->maxusedidx = sourceboolarray->maxusedidx;
4755 
4756  return SCIP_OKAY;
4757 }
4758 
4759 /** frees a dynamic array of bool values */
4761  SCIP_BOOLARRAY** boolarray /**< pointer to the bool array */
4762  )
4763 {
4764  assert(boolarray != NULL);
4765  assert(*boolarray != NULL);
4766 
4767  BMSfreeBlockMemoryArrayNull((*boolarray)->blkmem, &(*boolarray)->vals, (*boolarray)->valssize);
4768  BMSfreeBlockMemory((*boolarray)->blkmem, boolarray);
4769 
4770  return SCIP_OKAY;
4771 }
4772 
4773 /** extends dynamic array to be able to store indices from minidx to maxidx */
4775  SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4776  int arraygrowinit, /**< initial size of array */
4777  SCIP_Real arraygrowfac, /**< growing factor of array */
4778  int minidx, /**< smallest index to allocate storage for */
4779  int maxidx /**< largest index to allocate storage for */
4780  )
4781 {
4782  int nused;
4783  int nfree;
4784  int newfirstidx;
4785  int i;
4786 
4787  assert(boolarray != NULL);
4788  assert(boolarray->minusedidx == INT_MAX || boolarray->firstidx >= 0);
4789  assert(boolarray->maxusedidx == INT_MIN || boolarray->firstidx >= 0);
4790  assert(boolarray->minusedidx == INT_MAX || boolarray->minusedidx >= boolarray->firstidx);
4791  assert(boolarray->maxusedidx == INT_MIN || boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4792  assert(0 <= minidx);
4793  assert(minidx <= maxidx);
4794 
4795  minidx = MIN(minidx, boolarray->minusedidx);
4796  maxidx = MAX(maxidx, boolarray->maxusedidx);
4797  assert(0 <= minidx);
4798  assert(minidx <= maxidx);
4799 
4800  SCIPdebugMessage("extending boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4801  (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, minidx, maxidx);
4802 
4803  /* check, whether we have to allocate additional memory, or shift the array */
4804  nused = maxidx - minidx + 1;
4805  if( nused > boolarray->valssize )
4806  {
4807  SCIP_Bool* newvals;
4808  int newvalssize;
4809 
4810  /* allocate new memory storage */
4811  newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4812  SCIP_ALLOC( BMSallocBlockMemoryArray(boolarray->blkmem, &newvals, newvalssize) );
4813  nfree = newvalssize - nused;
4814  newfirstidx = minidx - nfree/2;
4815  newfirstidx = MAX(newfirstidx, 0);
4816  assert(newfirstidx <= minidx);
4817  assert(maxidx < newfirstidx + newvalssize);
4818 
4819  /* initialize memory array by copying old values and setting new values to zero */
4820  if( boolarray->firstidx != -1 )
4821  {
4822  for( i = 0; i < boolarray->minusedidx - newfirstidx; ++i )
4823  newvals[i] = FALSE;
4824 
4825  /* check for possible overflow or negative value */
4826  assert(boolarray->maxusedidx - boolarray->minusedidx + 1 > 0);
4827 
4828  BMScopyMemoryArray(&newvals[boolarray->minusedidx - newfirstidx],
4829  &boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4830  boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866 !e776*/
4831  for( i = boolarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4832  newvals[i] = FALSE;
4833  }
4834  else
4835  {
4836  for( i = 0; i < newvalssize; ++i )
4837  newvals[i] = FALSE;
4838  }
4839 
4840  /* free old memory storage, and set the new array parameters */
4841  BMSfreeBlockMemoryArrayNull(boolarray->blkmem, &boolarray->vals, boolarray->valssize);
4842  boolarray->vals = newvals;
4843  boolarray->valssize = newvalssize;
4844  boolarray->firstidx = newfirstidx;
4845  }
4846  else if( boolarray->firstidx == -1 )
4847  {
4848  /* a sufficiently large memory storage exists, but it was cleared */
4849  nfree = boolarray->valssize - nused;
4850  assert(nfree >= 0);
4851  boolarray->firstidx = minidx - nfree/2;
4852  assert(boolarray->firstidx <= minidx);
4853  assert(maxidx < boolarray->firstidx + boolarray->valssize);
4854 #ifndef NDEBUG
4855  for( i = 0; i < boolarray->valssize; ++i )
4856  assert(boolarray->vals[i] == FALSE);
4857 #endif
4858  }
4859  else if( minidx < boolarray->firstidx )
4860  {
4861  /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4862  nfree = boolarray->valssize - nused;
4863  assert(nfree >= 0);
4864  newfirstidx = minidx - nfree/2;
4865  newfirstidx = MAX(newfirstidx, 0);
4866  assert(newfirstidx <= minidx);
4867  assert(maxidx < newfirstidx + boolarray->valssize);
4868 
4869  if( boolarray->minusedidx <= boolarray->maxusedidx )
4870  {
4871  int shift;
4872 
4873  assert(boolarray->firstidx <= boolarray->minusedidx);
4874  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4875 
4876  /* shift used part of array to the right */
4877  shift = boolarray->firstidx - newfirstidx;
4878  assert(shift > 0);
4879  for( i = boolarray->maxusedidx - boolarray->firstidx; i >= boolarray->minusedidx - boolarray->firstidx; --i )
4880  {
4881  assert(0 <= i + shift && i + shift < boolarray->valssize);
4882  boolarray->vals[i + shift] = boolarray->vals[i];
4883  }
4884  /* clear the formerly used head of the array */
4885  for( i = 0; i < shift; ++i )
4886  boolarray->vals[boolarray->minusedidx - boolarray->firstidx + i] = FALSE;
4887  }
4888  boolarray->firstidx = newfirstidx;
4889  }
4890  else if( maxidx >= boolarray->firstidx + boolarray->valssize )
4891  {
4892  /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4893  nfree = boolarray->valssize - nused;
4894  assert(nfree >= 0);
4895  newfirstidx = minidx - nfree/2;
4896  newfirstidx = MAX(newfirstidx, 0);
4897  assert(newfirstidx <= minidx);
4898  assert(maxidx < newfirstidx + boolarray->valssize);
4899 
4900  if( boolarray->minusedidx <= boolarray->maxusedidx )
4901  {
4902  int shift;
4903 
4904  assert(boolarray->firstidx <= boolarray->minusedidx);
4905  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4906 
4907  /* shift used part of array to the left */
4908  shift = newfirstidx - boolarray->firstidx;
4909  assert(shift > 0);
4910 
4911  assert(0 <= boolarray->minusedidx - boolarray->firstidx - shift);
4912  assert(boolarray->maxusedidx - boolarray->firstidx - shift < boolarray->valssize);
4913  BMSmoveMemoryArray(&(boolarray->vals[boolarray->minusedidx - boolarray->firstidx - shift]),
4914  &(boolarray->vals[boolarray->minusedidx - boolarray->firstidx]),
4915  boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
4916 
4917  /* clear the formerly used tail of the array */
4918  for( i = 0; i < shift; ++i )
4919  boolarray->vals[boolarray->maxusedidx - boolarray->firstidx - i] = FALSE;
4920  }
4921  boolarray->firstidx = newfirstidx;
4922  }
4923 
4924  assert(minidx >= boolarray->firstidx);
4925  assert(maxidx < boolarray->firstidx + boolarray->valssize);
4926 
4927  return SCIP_OKAY;
4928 }
4929 
4930 /** clears a dynamic bool array */
4932  SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
4933  )
4934 {
4935  assert(boolarray != NULL);
4936 
4937  SCIPdebugMessage("clearing boolarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4938  (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx);
4939 
4940  if( boolarray->minusedidx <= boolarray->maxusedidx )
4941  {
4942  assert(boolarray->firstidx <= boolarray->minusedidx);
4943  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4944  assert(boolarray->firstidx != -1);
4945  assert(boolarray->valssize > 0);
4946 
4947  /* clear the used part of array */
4948  BMSclearMemoryArray(&boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4949  boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
4950 
4951  /* mark the array cleared */
4952  boolarray->minusedidx = INT_MAX;
4953  boolarray->maxusedidx = INT_MIN;
4954  }
4955  assert(boolarray->minusedidx == INT_MAX);
4956  assert(boolarray->maxusedidx == INT_MIN);
4957 
4958  return SCIP_OKAY;
4959 }
4960 
4961 /** gets value of entry in dynamic array */
4963  SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4964  int idx /**< array index to get value for */
4965  )
4966 {
4967  assert(boolarray != NULL);
4968  assert(idx >= 0);
4969 
4970  if( idx < boolarray->minusedidx || idx > boolarray->maxusedidx )
4971  return FALSE;
4972  else
4973  {
4974  assert(boolarray->vals != NULL);
4975  assert(idx - boolarray->firstidx >= 0);
4976  assert(idx - boolarray->firstidx < boolarray->valssize);
4977 
4978  return boolarray->vals[idx - boolarray->firstidx];
4979  }
4980 }
4981 
4982 /** sets value of entry in dynamic array */
4984  SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4985  int arraygrowinit, /**< initial size of array */
4986  SCIP_Real arraygrowfac, /**< growing factor of array */
4987  int idx, /**< array index to set value for */
4988  SCIP_Bool val /**< value to set array index to */
4989  )
4990 {
4991  assert(boolarray != NULL);
4992  assert(idx >= 0);
4993 
4994  SCIPdebugMessage("setting boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %u\n",
4995  (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, idx, val);
4996 
4997  if( val != FALSE )
4998  {
4999  /* extend array to be able to store the index */
5000  SCIP_CALL( SCIPboolarrayExtend(boolarray, arraygrowinit, arraygrowfac, idx, idx) );
5001  assert(idx >= boolarray->firstidx);
5002  assert(idx < boolarray->firstidx + boolarray->valssize);
5003 
5004  /* set the array value of the index */
5005  boolarray->vals[idx - boolarray->firstidx] = val;
5006 
5007  /* update min/maxusedidx */
5008  boolarray->minusedidx = MIN(boolarray->minusedidx, idx);
5009  boolarray->maxusedidx = MAX(boolarray->maxusedidx, idx);
5010  }
5011  else if( idx >= boolarray->firstidx && idx < boolarray->firstidx + boolarray->valssize )
5012  {
5013  /* set the array value of the index to zero */
5014  boolarray->vals[idx - boolarray->firstidx] = FALSE;
5015 
5016  /* check, if we can tighten the min/maxusedidx */
5017  if( idx == boolarray->minusedidx )
5018  {
5019  assert(boolarray->maxusedidx >= 0);
5020  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5021  do
5022  {
5023  boolarray->minusedidx++;
5024  }
5025  while( boolarray->minusedidx <= boolarray->maxusedidx
5026  && boolarray->vals[boolarray->minusedidx - boolarray->firstidx] == FALSE );
5027  if( boolarray->minusedidx > boolarray->maxusedidx )
5028  {
5029  boolarray->minusedidx = INT_MAX;
5030  boolarray->maxusedidx = INT_MIN;
5031  }
5032  }
5033  else if( idx == boolarray->maxusedidx )
5034  {
5035  assert(boolarray->minusedidx >= 0);
5036  assert(boolarray->minusedidx < boolarray->maxusedidx);
5037  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5038  do
5039  {
5040  boolarray->maxusedidx--;
5041  assert(boolarray->minusedidx <= boolarray->maxusedidx);
5042  }
5043  while( boolarray->vals[boolarray->maxusedidx - boolarray->firstidx] == FALSE );
5044  }
5045  }
5046 
5047  return SCIP_OKAY;
5048 }
5049 
5050 /** returns the minimal index of all stored non-zero elements */
5052  SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5053  )
5054 {
5055  assert(boolarray != NULL);
5056 
5057  return boolarray->minusedidx;
5058 }
5059 
5060 /** returns the maximal index of all stored non-zero elements */
5062  SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5063  )
5064 {
5065  assert(boolarray != NULL);
5066 
5067  return boolarray->maxusedidx;
5068 }
5069 
5070 
5071 /** creates a dynamic array of pointer values */
5073  SCIP_PTRARRAY** ptrarray, /**< pointer to store the ptr array */
5074  BMS_BLKMEM* blkmem /**< block memory */
5075  )
5076 {
5077  assert(ptrarray != NULL);
5078  assert(blkmem != NULL);
5079 
5080  SCIP_ALLOC( BMSallocBlockMemory(blkmem, ptrarray) );
5081  (*ptrarray)->blkmem = blkmem;
5082  (*ptrarray)->vals = NULL;
5083  (*ptrarray)->valssize = 0;
5084  (*ptrarray)->firstidx = -1;
5085  (*ptrarray)->minusedidx = INT_MAX;
5086  (*ptrarray)->maxusedidx = INT_MIN;
5087 
5088  return SCIP_OKAY;
5089 }
5090 
5091 /** creates a copy of a dynamic array of pointer values */
5093  SCIP_PTRARRAY** ptrarray, /**< pointer to store the copied ptr array */
5094  BMS_BLKMEM* blkmem, /**< block memory */
5095  SCIP_PTRARRAY* sourceptrarray /**< dynamic ptr array to copy */
5096  )
5097 {
5098  assert(ptrarray != NULL);
5099  assert(sourceptrarray != NULL);
5100 
5101  SCIP_CALL( SCIPptrarrayCreate(ptrarray, blkmem) );
5102  if( sourceptrarray->valssize > 0 )
5103  {
5104  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*ptrarray)->vals, sourceptrarray->vals, sourceptrarray->valssize) );
5105  }
5106  (*ptrarray)->valssize = sourceptrarray->valssize;
5107  (*ptrarray)->firstidx = sourceptrarray->firstidx;
5108  (*ptrarray)->minusedidx = sourceptrarray->minusedidx;
5109  (*ptrarray)->maxusedidx = sourceptrarray->maxusedidx;
5110 
5111  return SCIP_OKAY;
5112 }
5113 
5114 /** frees a dynamic array of pointer values */
5116  SCIP_PTRARRAY** ptrarray /**< pointer to the ptr array */
5117  )
5118 {
5119  assert(ptrarray != NULL);
5120  assert(*ptrarray != NULL);
5121 
5122  BMSfreeBlockMemoryArrayNull((*ptrarray)->blkmem, &(*ptrarray)->vals, (*ptrarray)->valssize);
5123  BMSfreeBlockMemory((*ptrarray)->blkmem, ptrarray);
5124 
5125  return SCIP_OKAY;
5126 }
5127 
5128 /** extends dynamic array to be able to store indices from minidx to maxidx */
5130  SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5131  int arraygrowinit, /**< initial size of array */
5132  SCIP_Real arraygrowfac, /**< growing factor of array */
5133  int minidx, /**< smallest index to allocate storage for */
5134  int maxidx /**< largest index to allocate storage for */
5135  )
5136 {
5137  int nused;
5138  int nfree;
5139  int newfirstidx;
5140  int i;
5141 
5142  assert(ptrarray != NULL);
5143  assert(ptrarray->minusedidx == INT_MAX || ptrarray->firstidx >= 0);
5144  assert(ptrarray->maxusedidx == INT_MIN || ptrarray->firstidx >= 0);
5145  assert(ptrarray->minusedidx == INT_MAX || ptrarray->minusedidx >= ptrarray->firstidx);
5146  assert(ptrarray->maxusedidx == INT_MIN || ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5147  assert(0 <= minidx);
5148  assert(minidx <= maxidx);
5149 
5150  minidx = MIN(minidx, ptrarray->minusedidx);
5151  maxidx = MAX(maxidx, ptrarray->maxusedidx);
5152  assert(0 <= minidx);
5153  assert(minidx <= maxidx);
5154 
5155  SCIPdebugMessage("extending ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
5156  (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, minidx, maxidx);
5157 
5158  /* check, whether we have to allocate additional memory, or shift the array */
5159  nused = maxidx - minidx + 1;
5160  if( nused > ptrarray->valssize )
5161  {
5162  void** newvals;
5163  int newvalssize;
5164 
5165  /* allocate new memory storage */
5166  newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
5167  SCIP_ALLOC( BMSallocBlockMemoryArray(ptrarray->blkmem, &newvals, newvalssize) );
5168  nfree = newvalssize - nused;
5169  newfirstidx = minidx - nfree/2;
5170  newfirstidx = MAX(newfirstidx, 0);
5171  assert(newfirstidx <= minidx);
5172  assert(maxidx < newfirstidx + newvalssize);
5173 
5174  /* initialize memory array by copying old values and setting new values to zero */
5175  if( ptrarray->firstidx != -1 )
5176  {
5177  for( i = 0; i < ptrarray->minusedidx - newfirstidx; ++i )
5178  newvals[i] = NULL;
5179 
5180  /* check for possible overflow or negative value */
5181  assert(ptrarray->maxusedidx - ptrarray->minusedidx + 1 > 0);
5182 
5183  BMScopyMemoryArray(&newvals[ptrarray->minusedidx - newfirstidx],
5184  &(ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx]),
5185  ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866 !e776*/
5186  for( i = ptrarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
5187  newvals[i] = NULL;
5188  }
5189  else
5190  {
5191  for( i = 0; i < newvalssize; ++i )
5192  newvals[i] = NULL;
5193  }
5194 
5195  /* free old memory storage, and set the new array parameters */
5196  BMSfreeBlockMemoryArrayNull(ptrarray->blkmem, &ptrarray->vals, ptrarray->valssize);
5197  ptrarray->vals = newvals;
5198  ptrarray->valssize = newvalssize;
5199  ptrarray->firstidx = newfirstidx;
5200  }
5201  else if( ptrarray->firstidx == -1 )
5202  {
5203  /* a sufficiently large memory storage exists, but it was cleared */
5204  nfree = ptrarray->valssize - nused;
5205  assert(nfree >= 0);
5206  ptrarray->firstidx = minidx - nfree/2;
5207  assert(ptrarray->firstidx <= minidx);
5208  assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5209 #ifndef NDEBUG
5210  for( i = 0; i < ptrarray->valssize; ++i )
5211  assert(ptrarray->vals[i] == NULL);
5212 #endif
5213  }
5214  else if( minidx < ptrarray->firstidx )
5215  {
5216  /* a sufficiently large memory storage exists, but it has to be shifted to the right */
5217  nfree = ptrarray->valssize - nused;
5218  assert(nfree >= 0);
5219  newfirstidx = minidx - nfree/2;
5220  newfirstidx = MAX(newfirstidx, 0);
5221  assert(newfirstidx <= minidx);
5222  assert(maxidx < newfirstidx + ptrarray->valssize);
5223 
5224  if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5225  {
5226  int shift;
5227 
5228  assert(ptrarray->firstidx <= ptrarray->minusedidx);
5229  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5230 
5231  /* shift used part of array to the right */
5232  shift = ptrarray->firstidx - newfirstidx;
5233  assert(shift > 0);
5234  for( i = ptrarray->maxusedidx - ptrarray->firstidx; i >= ptrarray->minusedidx - ptrarray->firstidx; --i )
5235  {
5236  assert(0 <= i + shift && i + shift < ptrarray->valssize);
5237  ptrarray->vals[i + shift] = ptrarray->vals[i];
5238  }
5239  /* clear the formerly used head of the array */
5240  for( i = 0; i < shift; ++i )
5241  ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx + i] = NULL;
5242  }
5243  ptrarray->firstidx = newfirstidx;
5244  }
5245  else if( maxidx >= ptrarray->firstidx + ptrarray->valssize )
5246  {
5247  /* a sufficiently large memory storage exists, but it has to be shifted to the left */
5248  nfree = ptrarray->valssize - nused;
5249  assert(nfree >= 0);
5250  newfirstidx = minidx - nfree/2;
5251  newfirstidx = MAX(newfirstidx, 0);
5252  assert(newfirstidx <= minidx);
5253  assert(maxidx < newfirstidx + ptrarray->valssize);
5254 
5255  if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5256  {
5257  int shift;
5258 
5259  assert(ptrarray->firstidx <= ptrarray->minusedidx);
5260  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5261 
5262  /* shift used part of array to the left */
5263  shift = newfirstidx - ptrarray->firstidx;
5264  assert(shift > 0);
5265  for( i = ptrarray->minusedidx - ptrarray->firstidx; i <= ptrarray->maxusedidx - ptrarray->firstidx; ++i )
5266  {
5267  assert(0 <= i - shift && i - shift < ptrarray->valssize);
5268  ptrarray->vals[i - shift] = ptrarray->vals[i];
5269  }
5270  /* clear the formerly used tail of the array */
5271  for( i = 0; i < shift; ++i )
5272  ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx - i] = NULL;
5273  }
5274  ptrarray->firstidx = newfirstidx;
5275  }
5276 
5277  assert(minidx >= ptrarray->firstidx);
5278  assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5279 
5280  return SCIP_OKAY;
5281 }
5282 
5283 /** clears a dynamic pointer array */
5285  SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5286  )
5287 {
5288  assert(ptrarray != NULL);
5289 
5290  SCIPdebugMessage("clearing ptrarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
5291  (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx);
5292 
5293  if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5294  {
5295  assert(ptrarray->firstidx <= ptrarray->minusedidx);
5296  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5297  assert(ptrarray->firstidx != -1);
5298  assert(ptrarray->valssize > 0);
5299 
5300  /* clear the used part of array */
5301  BMSclearMemoryArray(&ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx],
5302  ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866*/
5303 
5304  /* mark the array cleared */
5305  ptrarray->minusedidx = INT_MAX;
5306  ptrarray->maxusedidx = INT_MIN;
5307  }
5308  assert(ptrarray->minusedidx == INT_MAX);
5309  assert(ptrarray->maxusedidx == INT_MIN);
5310 
5311  return SCIP_OKAY;
5312 }
5313 
5314 /** gets value of entry in dynamic array */
5316  SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5317  int idx /**< array index to get value for */
5318  )
5319 {
5320  assert(ptrarray != NULL);
5321  assert(idx >= 0);
5322 
5323  if( idx < ptrarray->minusedidx || idx > ptrarray->maxusedidx )
5324  return NULL;
5325  else
5326  {
5327  assert(ptrarray->vals != NULL);
5328  assert(idx - ptrarray->firstidx >= 0);
5329  assert(idx - ptrarray->firstidx < ptrarray->valssize);
5330 
5331  return ptrarray->vals[idx - ptrarray->firstidx];
5332  }
5333 }
5334 
5335 /** sets value of entry in dynamic array */
5337  SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5338  int arraygrowinit, /**< initial size of array */
5339  SCIP_Real arraygrowfac, /**< growing factor of array */
5340  int idx, /**< array index to set value for */
5341  void* val /**< value to set array index to */
5342  )
5343 {
5344  assert(ptrarray != NULL);
5345  assert(idx >= 0);
5346 
5347  SCIPdebugMessage("setting ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %p\n",
5348  (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, idx, val);
5349 
5350  if( val != NULL )
5351  {
5352  /* extend array to be able to store the index */
5353  SCIP_CALL( SCIPptrarrayExtend(ptrarray, arraygrowinit, arraygrowfac, idx, idx) );
5354  assert(idx >= ptrarray->firstidx);
5355  assert(idx < ptrarray->firstidx + ptrarray->valssize);
5356 
5357  /* set the array value of the index */
5358  ptrarray->vals[idx - ptrarray->firstidx] = val;
5359 
5360  /* update min/maxusedidx */
5361  ptrarray->minusedidx = MIN(ptrarray->minusedidx, idx);
5362  ptrarray->maxusedidx = MAX(ptrarray->maxusedidx, idx);
5363  }
5364  else if( idx >= ptrarray->firstidx && idx < ptrarray->firstidx + ptrarray->valssize )
5365  {
5366  /* set the array value of the index to zero */
5367  ptrarray->vals[idx - ptrarray->firstidx] = NULL;
5368 
5369  /* check, if we can tighten the min/maxusedidx */
5370  if( idx == ptrarray->minusedidx )
5371  {
5372  assert(ptrarray->maxusedidx >= 0);
5373  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5374  do
5375  {
5376  ptrarray->minusedidx++;
5377  }
5378  while( ptrarray->minusedidx <= ptrarray->maxusedidx
5379  && ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx] == NULL );
5380  if( ptrarray->minusedidx > ptrarray->maxusedidx )
5381  {
5382  ptrarray->minusedidx = INT_MAX;
5383  ptrarray->maxusedidx = INT_MIN;
5384  }
5385  }
5386  else if( idx == ptrarray->maxusedidx )
5387  {
5388  assert(ptrarray->minusedidx >= 0);
5389  assert(ptrarray->minusedidx < ptrarray->maxusedidx);
5390  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5391  do
5392  {
5393  ptrarray->maxusedidx--;
5394  assert(ptrarray->minusedidx <= ptrarray->maxusedidx);
5395  }
5396  while( ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx] == NULL );
5397  }
5398  }
5399 
5400  return SCIP_OKAY;
5401 }
5402 
5403 /** returns the minimal index of all stored non-zero elements */
5405  SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5406  )
5407 {
5408  assert(ptrarray != NULL);
5409 
5410  return ptrarray->minusedidx;
5411 }
5412 
5413 /** returns the maximal index of all stored non-zero elements */
5415  SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5416  )
5417 {
5418  assert(ptrarray != NULL);
5419 
5420  return ptrarray->maxusedidx;
5421 }
5422 
5423 
5424 /*
5425  * Sorting algorithms
5426  */
5427 
5428 /** default comparer for integers */
5429 SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
5430 {
5431  int value1;
5432  int value2;
5433 
5434  value1 = (int)(size_t)elem1;
5435  value2 = (int)(size_t)elem2;
5436 
5437  if( value1 < value2 )
5438  return -1;
5439 
5440  if( value2 < value1 )
5441  return 1;
5442 
5443  return 0;
5444 }
5445 
5446 /* first all upwards-sorting methods */
5447 
5448 /** sort an indexed element set in non-decreasing order, resulting in a permutation index array */
5450  int* perm, /**< pointer to store the resulting permutation */
5451  SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
5452  void* dataptr, /**< pointer to data field that is given to the external compare method */
5453  int len /**< number of elements to be sorted (valid index range) */
5454  )
5455 {
5456  int pos;
5457 
5458  assert(indcomp != NULL);
5459  assert(len == 0 || perm != NULL);
5460 
5461  /* create identity permutation */
5462  for( pos = 0; pos < len; ++pos )
5463  perm[pos] = pos;
5464 
5465  SCIPsortInd(perm, indcomp, dataptr, len);
5466 }
5467 
5468 /* SCIPsortInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5469 #define SORTTPL_NAMEEXT Ind
5470 #define SORTTPL_KEYTYPE int
5471 #define SORTTPL_INDCOMP
5472 #include "scip/sorttpl.c" /*lint !e451*/
5473 
5474 
5475 /* SCIPsortPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5476 #define SORTTPL_NAMEEXT Ptr
5477 #define SORTTPL_KEYTYPE void*
5478 #define SORTTPL_PTRCOMP
5479 #include "scip/sorttpl.c" /*lint !e451*/
5480 
5481 
5482 /* SCIPsortPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5483 #define SORTTPL_NAMEEXT PtrPtr
5484 #define SORTTPL_KEYTYPE void*
5485 #define SORTTPL_FIELD1TYPE void*
5486 #define SORTTPL_PTRCOMP
5487 #include "scip/sorttpl.c" /*lint !e451*/
5488 
5489 
5490 /* SCIPsortPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5491 #define SORTTPL_NAMEEXT PtrReal
5492 #define SORTTPL_KEYTYPE void*
5493 #define SORTTPL_FIELD1TYPE SCIP_Real
5494 #define SORTTPL_PTRCOMP
5495 #include "scip/sorttpl.c" /*lint !e451*/
5496 
5497 
5498 /* SCIPsortPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5499 #define SORTTPL_NAMEEXT PtrInt
5500 #define SORTTPL_KEYTYPE void*
5501 #define SORTTPL_FIELD1TYPE int
5502 #define SORTTPL_PTRCOMP
5503 #include "scip/sorttpl.c" /*lint !e451*/
5504 
5505 
5506 /* SCIPsortPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5507 #define SORTTPL_NAMEEXT PtrBool
5508 #define SORTTPL_KEYTYPE void*
5509 #define SORTTPL_FIELD1TYPE SCIP_Bool
5510 #define SORTTPL_PTRCOMP
5511 #include "scip/sorttpl.c" /*lint !e451*/
5512 
5513 
5514 /* SCIPsortPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5515 #define SORTTPL_NAMEEXT PtrIntInt
5516 #define SORTTPL_KEYTYPE void*
5517 #define SORTTPL_FIELD1TYPE int
5518 #define SORTTPL_FIELD2TYPE int
5519 #define SORTTPL_PTRCOMP
5520 #include "scip/sorttpl.c" /*lint !e451*/
5521 
5522 
5523 /* SCIPsortPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5524 #define SORTTPL_NAMEEXT PtrRealInt
5525 #define SORTTPL_KEYTYPE void*
5526 #define SORTTPL_FIELD1TYPE SCIP_Real
5527 #define SORTTPL_FIELD2TYPE int
5528 #define SORTTPL_PTRCOMP
5529 #include "scip/sorttpl.c" /*lint !e451*/
5530 
5531 /* SCIPsortPtrRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5532 #define SORTTPL_NAMEEXT PtrRealRealInt
5533 #define SORTTPL_KEYTYPE void*
5534 #define SORTTPL_FIELD1TYPE SCIP_Real
5535 #define SORTTPL_FIELD2TYPE SCIP_Real
5536 #define SORTTPL_FIELD3TYPE int
5537 #define SORTTPL_PTRCOMP
5538 #include "scip/sorttpl.c" /*lint !e451*/
5539 
5540 /* SCIPsortPtrRealRealBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5541 #define SORTTPL_NAMEEXT PtrRealRealBoolBool
5542 #define SORTTPL_KEYTYPE void*
5543 #define SORTTPL_FIELD1TYPE SCIP_Real
5544 #define SORTTPL_FIELD2TYPE SCIP_Real
5545 #define SORTTPL_FIELD3TYPE SCIP_Bool
5546 #define SORTTPL_FIELD4TYPE SCIP_Bool
5547 #define SORTTPL_PTRCOMP
5548 #include "scip/sorttpl.c" /*lint !e451*/
5549 
5550 /* SCIPsortPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5551 #define SORTTPL_NAMEEXT PtrRealRealIntBool
5552 #define SORTTPL_KEYTYPE void*
5553 #define SORTTPL_FIELD1TYPE SCIP_Real
5554 #define SORTTPL_FIELD2TYPE SCIP_Real
5555 #define SORTTPL_FIELD3TYPE int
5556 #define SORTTPL_FIELD4TYPE SCIP_Bool
5557 #define SORTTPL_PTRCOMP
5558 #include "scip/sorttpl.c" /*lint !e451*/
5559 
5560 /* SCIPsortPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5561 #define SORTTPL_NAMEEXT PtrRealBool
5562 #define SORTTPL_KEYTYPE void*
5563 #define SORTTPL_FIELD1TYPE SCIP_Real
5564 #define SORTTPL_FIELD2TYPE SCIP_Bool
5565 #define SORTTPL_PTRCOMP
5566 #include "scip/sorttpl.c" /*lint !e451*/
5567 
5568 
5569 /* SCIPsortPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5570 #define SORTTPL_NAMEEXT PtrPtrInt
5571 #define SORTTPL_KEYTYPE void*
5572 #define SORTTPL_FIELD1TYPE void*
5573 #define SORTTPL_FIELD2TYPE int
5574 #define SORTTPL_PTRCOMP
5575 #include "scip/sorttpl.c" /*lint !e451*/
5576 
5577 
5578 /* SCIPsortPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5579 #define SORTTPL_NAMEEXT PtrPtrReal
5580 #define SORTTPL_KEYTYPE void*
5581 #define SORTTPL_FIELD1TYPE void*
5582 #define SORTTPL_FIELD2TYPE SCIP_Real
5583 #define SORTTPL_PTRCOMP
5584 #include "scip/sorttpl.c" /*lint !e451*/
5585 
5586 
5587 /* SCIPsortPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5588 #define SORTTPL_NAMEEXT PtrRealIntInt
5589 #define SORTTPL_KEYTYPE void*
5590 #define SORTTPL_FIELD1TYPE SCIP_Real
5591 #define SORTTPL_FIELD2TYPE int
5592 #define SORTTPL_FIELD3TYPE int
5593 #define SORTTPL_PTRCOMP
5594 #include "scip/sorttpl.c" /*lint !e451*/
5595 
5596 
5597 /* SCIPsortPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5598 #define SORTTPL_NAMEEXT PtrPtrIntInt
5599 #define SORTTPL_KEYTYPE void*
5600 #define SORTTPL_FIELD1TYPE void*
5601 #define SORTTPL_FIELD2TYPE int
5602 #define SORTTPL_FIELD3TYPE int
5603 #define SORTTPL_PTRCOMP
5604 #include "scip/sorttpl.c" /*lint !e451*/
5605 
5606 
5607 /* SCIPsortPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5608 #define SORTTPL_NAMEEXT PtrPtrRealInt
5609 #define SORTTPL_KEYTYPE void*
5610 #define SORTTPL_FIELD1TYPE void*
5611 #define SORTTPL_FIELD2TYPE SCIP_Real
5612 #define SORTTPL_FIELD3TYPE int
5613 #define SORTTPL_PTRCOMP
5614 #include "scip/sorttpl.c" /*lint !e451*/
5615 
5616 
5617 /* SCIPsortPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5618 #define SORTTPL_NAMEEXT PtrPtrRealBool
5619 #define SORTTPL_KEYTYPE void*
5620 #define SORTTPL_FIELD1TYPE void*
5621 #define SORTTPL_FIELD2TYPE SCIP_Real
5622 #define SORTTPL_FIELD3TYPE SCIP_Bool
5623 #define SORTTPL_PTRCOMP
5624 #include "scip/sorttpl.c" /*lint !e451*/
5625 
5626 
5627 /* SCIPsortPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5628 #define SORTTPL_NAMEEXT PtrPtrLongInt
5629 #define SORTTPL_KEYTYPE void*
5630 #define SORTTPL_FIELD1TYPE void*
5631 #define SORTTPL_FIELD2TYPE SCIP_Longint
5632 #define SORTTPL_FIELD3TYPE int
5633 #define SORTTPL_PTRCOMP
5634 #include "scip/sorttpl.c" /*lint !e451*/
5635 
5636 
5637 /* SCIPsortPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5638 #define SORTTPL_NAMEEXT PtrPtrLongIntInt
5639 #define SORTTPL_KEYTYPE void*
5640 #define SORTTPL_FIELD1TYPE void*
5641 #define SORTTPL_FIELD2TYPE SCIP_Longint
5642 #define SORTTPL_FIELD3TYPE int
5643 #define SORTTPL_FIELD4TYPE int
5644 #define SORTTPL_PTRCOMP
5645 #include "scip/sorttpl.c" /*lint !e451*/
5646 
5647 
5648 /* SCIPsortReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5649 #define SORTTPL_NAMEEXT Real
5650 #define SORTTPL_KEYTYPE SCIP_Real
5651 #include "scip/sorttpl.c" /*lint !e451*/
5652 
5653 
5654 /* SCIPsortRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5655 #define SORTTPL_NAMEEXT RealBoolPtr
5656 #define SORTTPL_KEYTYPE SCIP_Real
5657 #define SORTTPL_FIELD1TYPE SCIP_Bool
5658 #define SORTTPL_FIELD2TYPE void*
5659 #include "scip/sorttpl.c" /*lint !e451*/
5660 
5661 
5662 /* SCIPsortRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5663 #define SORTTPL_NAMEEXT RealPtr
5664 #define SORTTPL_KEYTYPE SCIP_Real
5665 #define SORTTPL_FIELD1TYPE void*
5666 #include "scip/sorttpl.c" /*lint !e451*/
5667 
5668 
5669 /* SCIPsortRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5670 #define SORTTPL_NAMEEXT RealInt
5671 #define SORTTPL_KEYTYPE SCIP_Real
5672 #define SORTTPL_FIELD1TYPE int
5673 #include "scip/sorttpl.c" /*lint !e451*/
5674 
5675 
5676 /* SCIPsortRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5677 #define SORTTPL_NAMEEXT RealIntInt
5678 #define SORTTPL_KEYTYPE SCIP_Real
5679 #define SORTTPL_FIELD1TYPE int
5680 #define SORTTPL_FIELD2TYPE int
5681 #include "scip/sorttpl.c" /*lint !e451*/
5682 
5683 
5684 /* SCIPsortRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5685 #define SORTTPL_NAMEEXT RealIntLong
5686 #define SORTTPL_KEYTYPE SCIP_Real
5687 #define SORTTPL_FIELD1TYPE int
5688 #define SORTTPL_FIELD2TYPE SCIP_Longint
5689 #include "scip/sorttpl.c" /*lint !e451*/
5690 
5691 
5692 /* SCIPsortRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5693 #define SORTTPL_NAMEEXT RealIntPtr
5694 #define SORTTPL_KEYTYPE SCIP_Real
5695 #define SORTTPL_FIELD1TYPE int
5696 #define SORTTPL_FIELD2TYPE void*
5697 #include "scip/sorttpl.c" /*lint !e451*/
5698 
5699 
5700 /* SCIPsortRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5701 #define SORTTPL_NAMEEXT RealRealPtr
5702 #define SORTTPL_KEYTYPE SCIP_Real
5703 #define SORTTPL_FIELD1TYPE SCIP_Real
5704 #define SORTTPL_FIELD2TYPE void*
5705 #include "scip/sorttpl.c" /*lint !e451*/
5706 
5707 
5708 /* SCIPsortRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5709 #define SORTTPL_NAMEEXT RealLongRealInt
5710 #define SORTTPL_KEYTYPE SCIP_Real
5711 #define SORTTPL_FIELD1TYPE SCIP_Longint
5712 #define SORTTPL_FIELD2TYPE SCIP_Real
5713 #define SORTTPL_FIELD3TYPE int
5714 #include "scip/sorttpl.c" /*lint !e451*/
5715 
5716 /* SCIPsortRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5717 #define SORTTPL_NAMEEXT RealRealIntInt
5718 #define SORTTPL_KEYTYPE SCIP_Real
5719 #define SORTTPL_FIELD1TYPE SCIP_Real
5720 #define SORTTPL_FIELD2TYPE int
5721 #define SORTTPL_FIELD3TYPE int
5722 #include "scip/sorttpl.c" /*lint !e451*/
5723 
5724 
5725 /* SCIPsortRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5726 #define SORTTPL_NAMEEXT RealRealRealInt
5727 #define SORTTPL_KEYTYPE SCIP_Real
5728 #define SORTTPL_FIELD1TYPE SCIP_Real
5729 #define SORTTPL_FIELD2TYPE SCIP_Real
5730 #define SORTTPL_FIELD3TYPE int
5731 #include "scip/sorttpl.c" /*lint !e451*/
5732 
5733 
5734 /* SCIPsortRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5735 #define SORTTPL_NAMEEXT RealRealRealPtr
5736 #define SORTTPL_KEYTYPE SCIP_Real
5737 #define SORTTPL_FIELD1TYPE SCIP_Real
5738 #define SORTTPL_FIELD2TYPE SCIP_Real
5739 #define SORTTPL_FIELD3TYPE void*
5740 #include "scip/sorttpl.c" /*lint !e451*/
5741 
5742 
5743 /* SCIPsortRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5744 #define SORTTPL_NAMEEXT RealPtrPtrInt
5745 #define SORTTPL_KEYTYPE SCIP_Real
5746 #define SORTTPL_FIELD1TYPE void*
5747 #define SORTTPL_FIELD2TYPE void*
5748 #define SORTTPL_FIELD3TYPE int
5749 #include "scip/sorttpl.c" /*lint !e451*/
5750 
5751 
5752 /* SCIPsortRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5753 #define SORTTPL_NAMEEXT RealPtrPtrIntInt
5754 #define SORTTPL_KEYTYPE SCIP_Real
5755 #define SORTTPL_FIELD1TYPE void*
5756 #define SORTTPL_FIELD2TYPE void*
5757 #define SORTTPL_FIELD3TYPE int
5758 #define SORTTPL_FIELD4TYPE int
5759 #include "scip/sorttpl.c" /*lint !e451*/
5760 
5761 
5762 /* SCIPsortRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5763 #define SORTTPL_NAMEEXT RealRealRealBoolPtr
5764 #define SORTTPL_KEYTYPE SCIP_Real
5765 #define SORTTPL_FIELD1TYPE SCIP_Real
5766 #define SORTTPL_FIELD2TYPE SCIP_Real
5767 #define SORTTPL_FIELD3TYPE SCIP_Bool
5768 #define SORTTPL_FIELD4TYPE void*
5769 #include "scip/sorttpl.c" /*lint !e451*/
5770 
5771 
5772 /* SCIPsortRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5773 #define SORTTPL_NAMEEXT RealRealRealBoolBoolPtr
5774 #define SORTTPL_KEYTYPE SCIP_Real
5775 #define SORTTPL_FIELD1TYPE SCIP_Real
5776 #define SORTTPL_FIELD2TYPE SCIP_Real
5777 #define SORTTPL_FIELD3TYPE SCIP_Bool
5778 #define SORTTPL_FIELD4TYPE SCIP_Bool
5779 #define SORTTPL_FIELD5TYPE void*
5780 #include "scip/sorttpl.c" /*lint !e451*/
5781 
5782 
5783 /* SCIPsortInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5784 #define SORTTPL_NAMEEXT Int
5785 #define SORTTPL_KEYTYPE int
5786 #include "scip/sorttpl.c" /*lint !e451*/
5787 
5788 
5789 /* SCIPsortIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5790 #define SORTTPL_NAMEEXT IntInt
5791 #define SORTTPL_KEYTYPE int
5792 #define SORTTPL_FIELD1TYPE int
5793 #include "scip/sorttpl.c" /*lint !e451*/
5794 
5795 
5796 /* SCIPsortIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5797 #define SORTTPL_NAMEEXT IntReal
5798 #define SORTTPL_KEYTYPE int
5799 #define SORTTPL_FIELD1TYPE SCIP_Real
5800 #include "scip/sorttpl.c" /*lint !e451*/
5801 
5802 
5803 /* SCIPsortIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5804 #define SORTTPL_NAMEEXT IntPtr
5805 #define SORTTPL_KEYTYPE int
5806 #define SORTTPL_FIELD1TYPE void*
5807 #include "scip/sorttpl.c" /*lint !e451*/
5808 
5809 
5810 /* SCIPsortIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5811 #define SORTTPL_NAMEEXT IntIntInt
5812 #define SORTTPL_KEYTYPE int
5813 #define SORTTPL_FIELD1TYPE int
5814 #define SORTTPL_FIELD2TYPE int
5815 #include "scip/sorttpl.c" /*lint !e451*/
5816 
5817 
5818 /* SCIPsortIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5819 #define SORTTPL_NAMEEXT IntIntLong
5820 #define SORTTPL_KEYTYPE int
5821 #define SORTTPL_FIELD1TYPE int
5822 #define SORTTPL_FIELD2TYPE SCIP_Longint
5823 #include "scip/sorttpl.c" /*lint !e451*/
5824 
5825 /* SCIPsortIntRealLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5826 #define SORTTPL_NAMEEXT IntRealLong
5827 #define SORTTPL_KEYTYPE int
5828 #define SORTTPL_FIELD1TYPE SCIP_Real
5829 #define SORTTPL_FIELD2TYPE SCIP_Longint
5830 #include "scip/sorttpl.c" /*lint !e451*/
5831 
5832 
5833 /* SCIPsortIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5834 #define SORTTPL_NAMEEXT IntIntPtr
5835 #define SORTTPL_KEYTYPE int
5836 #define SORTTPL_FIELD1TYPE int
5837 #define SORTTPL_FIELD2TYPE void*
5838 #include "scip/sorttpl.c" /*lint !e451*/
5839 
5840 
5841 /* SCIPsortIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5842 #define SORTTPL_NAMEEXT IntIntReal
5843 #define SORTTPL_KEYTYPE int
5844 #define SORTTPL_FIELD1TYPE int
5845 #define SORTTPL_FIELD2TYPE SCIP_Real
5846 #include "scip/sorttpl.c" /*lint !e451*/
5847 
5848 
5849 /* SCIPsortIntPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5850 #define SORTTPL_NAMEEXT IntPtrReal
5851 #define SORTTPL_KEYTYPE int
5852 #define SORTTPL_FIELD1TYPE void*
5853 #define SORTTPL_FIELD2TYPE SCIP_Real
5854 #include "scip/sorttpl.c" /*lint !e451*/
5855 
5856 
5857 /* SCIPsortIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5858 #define SORTTPL_NAMEEXT IntIntIntPtr
5859 #define SORTTPL_KEYTYPE int
5860 #define SORTTPL_FIELD1TYPE int
5861 #define SORTTPL_FIELD2TYPE int
5862 #define SORTTPL_FIELD3TYPE void*
5863 #include "scip/sorttpl.c" /*lint !e451*/
5864 
5865 /* SCIPsortIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5866 #define SORTTPL_NAMEEXT IntIntIntReal
5867 #define SORTTPL_KEYTYPE int
5868 #define SORTTPL_FIELD1TYPE int
5869 #define SORTTPL_FIELD2TYPE int
5870 #define SORTTPL_FIELD3TYPE SCIP_Real
5871 #include "scip/sorttpl.c" /*lint !e451*/
5872 
5873 /* SCIPsortIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5874 #define SORTTPL_NAMEEXT IntPtrIntReal
5875 #define SORTTPL_KEYTYPE int
5876 #define SORTTPL_FIELD1TYPE void*
5877 #define SORTTPL_FIELD2TYPE int
5878 #define SORTTPL_FIELD3TYPE SCIP_Real
5879 #include "scip/sorttpl.c" /*lint !e451*/
5880 
5881 
5882 /* SCIPsortLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5883 #define SORTTPL_NAMEEXT Long
5884 #define SORTTPL_KEYTYPE SCIP_Longint
5885 #include "scip/sorttpl.c" /*lint !e451*/
5886 
5887 
5888 /* SCIPsortLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5889 #define SORTTPL_NAMEEXT LongPtr
5890 #define SORTTPL_KEYTYPE SCIP_Longint
5891 #define SORTTPL_FIELD1TYPE void*
5892 #include "scip/sorttpl.c" /*lint !e451*/
5893 
5894 
5895 /* SCIPsortLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5896 #define SORTTPL_NAMEEXT LongPtrInt
5897 #define SORTTPL_KEYTYPE SCIP_Longint
5898 #define SORTTPL_FIELD1TYPE void*
5899 #define SORTTPL_FIELD2TYPE int
5900 #include "scip/sorttpl.c" /*lint !e451*/
5901 
5902 
5903 /* SCIPsortLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5904 #define SORTTPL_NAMEEXT LongPtrRealBool
5905 #define SORTTPL_KEYTYPE SCIP_Longint
5906 #define SORTTPL_FIELD1TYPE void*
5907 #define SORTTPL_FIELD2TYPE SCIP_Real
5908 #define SORTTPL_FIELD3TYPE SCIP_Bool
5909 #include "scip/sorttpl.c" /*lint !e451*/
5910 
5911 
5912 /* SCIPsortLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5913 #define SORTTPL_NAMEEXT LongPtrRealRealBool
5914 #define SORTTPL_KEYTYPE SCIP_Longint
5915 #define SORTTPL_FIELD1TYPE void*
5916 #define SORTTPL_FIELD2TYPE SCIP_Real
5917 #define SORTTPL_FIELD3TYPE SCIP_Real
5918 #define SORTTPL_FIELD4TYPE SCIP_Bool
5919 #include "scip/sorttpl.c" /*lint !e451*/
5920 
5921 
5922 /* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5923 #define SORTTPL_NAMEEXT LongPtrRealRealIntBool
5924 #define SORTTPL_KEYTYPE SCIP_Longint
5925 #define SORTTPL_FIELD1TYPE void*
5926 #define SORTTPL_FIELD2TYPE SCIP_Real
5927 #define SORTTPL_FIELD3TYPE SCIP_Real
5928 #define SORTTPL_FIELD4TYPE int
5929 #define SORTTPL_FIELD5TYPE SCIP_Bool
5930 #include "scip/sorttpl.c" /*lint !e451*/
5931 
5932 
5933 /* SCIPsortLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5934 #define SORTTPL_NAMEEXT LongPtrPtrInt
5935 #define SORTTPL_KEYTYPE SCIP_Longint
5936 #define SORTTPL_FIELD1TYPE void*
5937 #define SORTTPL_FIELD2TYPE void*
5938 #define SORTTPL_FIELD3TYPE int
5939 #include "scip/sorttpl.c" /*lint !e451*/
5940 
5941 
5942 /* SCIPsortLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5943 #define SORTTPL_NAMEEXT LongPtrPtrIntInt
5944 #define SORTTPL_KEYTYPE SCIP_Longint
5945 #define SORTTPL_FIELD1TYPE void*
5946 #define SORTTPL_FIELD2TYPE void*
5947 #define SORTTPL_FIELD3TYPE int
5948 #define SORTTPL_FIELD4TYPE int
5949 #include "scip/sorttpl.c" /*lint !e451*/
5950 
5951 
5952 /* SCIPsortLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5953 #define SORTTPL_NAMEEXT LongPtrPtrBoolInt
5954 #define SORTTPL_KEYTYPE SCIP_Longint
5955 #define SORTTPL_FIELD1TYPE void*
5956 #define SORTTPL_FIELD2TYPE void*
5957 #define SORTTPL_FIELD3TYPE SCIP_Bool
5958 #define SORTTPL_FIELD4TYPE int
5959 #include "scip/sorttpl.c" /*lint !e451*/
5960 
5961 
5962 /* SCIPsortPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5963 #define SORTTPL_NAMEEXT PtrIntIntBoolBool
5964 #define SORTTPL_KEYTYPE void*
5965 #define SORTTPL_FIELD1TYPE int
5966 #define SORTTPL_FIELD2TYPE int
5967 #define SORTTPL_FIELD3TYPE SCIP_Bool
5968 #define SORTTPL_FIELD4TYPE SCIP_Bool
5969 #define SORTTPL_PTRCOMP
5970 #include "scip/sorttpl.c" /*lint !e451*/
5971 
5972 
5973 /* SCIPsortIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5974 #define SORTTPL_NAMEEXT IntPtrIntIntBoolBool
5975 #define SORTTPL_KEYTYPE int
5976 #define SORTTPL_FIELD1TYPE void*
5977 #define SORTTPL_FIELD2TYPE int
5978 #define SORTTPL_FIELD3TYPE int
5979 #define SORTTPL_FIELD4TYPE SCIP_Bool
5980 #define SORTTPL_FIELD5TYPE SCIP_Bool
5981 #include "scip/sorttpl.c" /*lint !e451*/
5982 
5983 
5984 /* now all downwards-sorting methods */
5985 
5986 
5987 /** sort an indexed element set in non-increasing order, resulting in a permutation index array */
5989  int* perm, /**< pointer to store the resulting permutation */
5990  SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
5991  void* dataptr, /**< pointer to data field that is given to the external compare method */
5992  int len /**< number of elements to be sorted (valid index range) */
5993  )
5994 {
5995  int pos;
5996 
5997  assert(indcomp != NULL);
5998  assert(len == 0 || perm != NULL);
5999 
6000  /* create identity permutation */
6001  for( pos = 0; pos < len; ++pos )
6002  perm[pos] = pos;
6003 
6004  SCIPsortDownInd(perm, indcomp, dataptr, len);
6005 }
6006 
6007 
6008 /* SCIPsortDownInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6009 #define SORTTPL_NAMEEXT DownInd
6010 #define SORTTPL_KEYTYPE int
6011 #define SORTTPL_INDCOMP
6012 #define SORTTPL_BACKWARDS
6013 #include "scip/sorttpl.c" /*lint !e451*/
6014 
6015 
6016 /* SCIPsortDownPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6017 #define SORTTPL_NAMEEXT DownPtr
6018 #define SORTTPL_KEYTYPE void*
6019 #define SORTTPL_PTRCOMP
6020 #define SORTTPL_BACKWARDS
6021 #include "scip/sorttpl.c" /*lint !e451*/
6022 
6023 
6024 /* SCIPsortDownPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6025 #define SORTTPL_NAMEEXT DownPtrPtr
6026 #define SORTTPL_KEYTYPE void*
6027 #define SORTTPL_FIELD1TYPE void*
6028 #define SORTTPL_PTRCOMP
6029 #define SORTTPL_BACKWARDS
6030 #include "scip/sorttpl.c" /*lint !e451*/
6031 
6032 
6033 /* SCIPsortDownPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6034 #define SORTTPL_NAMEEXT DownPtrReal
6035 #define SORTTPL_KEYTYPE void*
6036 #define SORTTPL_FIELD1TYPE SCIP_Real
6037 #define SORTTPL_PTRCOMP
6038 #define SORTTPL_BACKWARDS
6039 #include "scip/sorttpl.c" /*lint !e451*/
6040 
6041 
6042 /* SCIPsortDownPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6043 #define SORTTPL_NAMEEXT DownPtrInt
6044 #define SORTTPL_KEYTYPE void*
6045 #define SORTTPL_FIELD1TYPE int
6046 #define SORTTPL_PTRCOMP
6047 #define SORTTPL_BACKWARDS
6048 #include "scip/sorttpl.c" /*lint !e451*/
6049 
6050 /* SCIPsortDownPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6051 #define SORTTPL_NAMEEXT DownPtrBool
6052 #define SORTTPL_KEYTYPE void*
6053 #define SORTTPL_FIELD1TYPE SCIP_Bool
6054 #define SORTTPL_PTRCOMP
6055 #define SORTTPL_BACKWARDS
6056 #include "scip/sorttpl.c" /*lint !e451*/
6057 
6058 /* SCIPsortDownPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6059 #define SORTTPL_NAMEEXT DownPtrIntInt
6060 #define SORTTPL_KEYTYPE void*
6061 #define SORTTPL_FIELD1TYPE int
6062 #define SORTTPL_FIELD2TYPE int
6063 #define SORTTPL_PTRCOMP
6064 #define SORTTPL_BACKWARDS
6065 #include "scip/sorttpl.c" /*lint !e451*/
6066 
6067 
6068 /* SCIPsortDownPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6069 #define SORTTPL_NAMEEXT DownPtrRealInt
6070 #define SORTTPL_KEYTYPE void*
6071 #define SORTTPL_FIELD1TYPE SCIP_Real
6072 #define SORTTPL_FIELD2TYPE int
6073 #define SORTTPL_PTRCOMP
6074 #define SORTTPL_BACKWARDS
6075 #include "scip/sorttpl.c" /*lint !e451*/
6076 
6077 
6078 /* SCIPsortDownPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6079 #define SORTTPL_NAMEEXT DownPtrRealBool
6080 #define SORTTPL_KEYTYPE void*
6081 #define SORTTPL_FIELD1TYPE SCIP_Real
6082 #define SORTTPL_FIELD2TYPE SCIP_Bool
6083 #define SORTTPL_PTRCOMP
6084 #define SORTTPL_BACKWARDS
6085 #include "scip/sorttpl.c" /*lint !e451*/
6086 
6087 
6088 /* SCIPsortDownPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6089 #define SORTTPL_NAMEEXT DownPtrPtrInt
6090 #define SORTTPL_KEYTYPE void*
6091 #define SORTTPL_FIELD1TYPE void*
6092 #define SORTTPL_FIELD2TYPE int
6093 #define SORTTPL_PTRCOMP
6094 #define SORTTPL_BACKWARDS
6095 #include "scip/sorttpl.c" /*lint !e451*/
6096 
6097 
6098 /* SCIPsortDownPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6099 #define SORTTPL_NAMEEXT DownPtrPtrReal
6100 #define SORTTPL_KEYTYPE void*
6101 #define SORTTPL_FIELD1TYPE void*
6102 #define SORTTPL_FIELD2TYPE SCIP_Real
6103 #define SORTTPL_PTRCOMP
6104 #define SORTTPL_BACKWARDS
6105 #include "scip/sorttpl.c" /*lint !e451*/
6106 
6107 
6108 /* SCIPsortDownPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6109 #define SORTTPL_NAMEEXT DownPtrRealIntInt
6110 #define SORTTPL_KEYTYPE void*
6111 #define SORTTPL_FIELD1TYPE SCIP_Real
6112 #define SORTTPL_FIELD2TYPE int
6113 #define SORTTPL_FIELD3TYPE int
6114 #define SORTTPL_PTRCOMP
6115 #define SORTTPL_BACKWARDS
6116 #include "scip/sorttpl.c" /*lint !e451*/
6117 
6118 
6119 /* SCIPsortDownPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6120 #define SORTTPL_NAMEEXT DownPtrPtrIntInt
6121 #define SORTTPL_KEYTYPE void*
6122 #define SORTTPL_FIELD1TYPE void*
6123 #define SORTTPL_FIELD2TYPE int
6124 #define SORTTPL_FIELD3TYPE int
6125 #define SORTTPL_PTRCOMP
6126 #define SORTTPL_BACKWARDS
6127 #include "scip/sorttpl.c" /*lint !e451*/
6128 
6129 
6130 /* SCIPsortDownPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6131 #define SORTTPL_NAMEEXT DownPtrPtrRealInt
6132 #define SORTTPL_KEYTYPE void*
6133 #define SORTTPL_FIELD1TYPE void*
6134 #define SORTTPL_FIELD2TYPE SCIP_Real
6135 #define SORTTPL_FIELD3TYPE int
6136 #define SORTTPL_PTRCOMP
6137 #define SORTTPL_BACKWARDS
6138 #include "scip/sorttpl.c" /*lint !e451*/
6139 
6140 
6141 /* SCIPsortDownPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6142 #define SORTTPL_NAMEEXT DownPtrPtrRealBool
6143 #define SORTTPL_KEYTYPE void*
6144 #define SORTTPL_FIELD1TYPE void*
6145 #define SORTTPL_FIELD2TYPE SCIP_Real
6146 #define SORTTPL_FIELD3TYPE SCIP_Bool
6147 #define SORTTPL_PTRCOMP
6148 #define SORTTPL_BACKWARDS
6149 #include "scip/sorttpl.c" /*lint !e451*/
6150 
6151 
6152 /* SCIPsortDownPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6153 #define SORTTPL_NAMEEXT DownPtrPtrLongInt
6154 #define SORTTPL_KEYTYPE void*
6155 #define SORTTPL_FIELD1TYPE void*
6156 #define SORTTPL_FIELD2TYPE SCIP_Longint
6157 #define SORTTPL_FIELD3TYPE int
6158 #define SORTTPL_PTRCOMP
6159 #define SORTTPL_BACKWARDS
6160 #include "scip/sorttpl.c" /*lint !e451*/
6161 
6162 
6163 /* SCIPsortDownPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6164 #define SORTTPL_NAMEEXT DownPtrPtrLongIntInt
6165 #define SORTTPL_KEYTYPE void*
6166 #define SORTTPL_FIELD1TYPE void*
6167 #define SORTTPL_FIELD2TYPE SCIP_Longint
6168 #define SORTTPL_FIELD3TYPE int
6169 #define SORTTPL_FIELD4TYPE int
6170 #define SORTTPL_PTRCOMP
6171 #define SORTTPL_BACKWARDS
6172 #include "scip/sorttpl.c" /*lint !e451*/
6173 
6174 
6175 /* SCIPsortDownReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6176 #define SORTTPL_NAMEEXT DownReal
6177 #define SORTTPL_KEYTYPE SCIP_Real
6178 #define SORTTPL_BACKWARDS
6179 #include "scip/sorttpl.c" /*lint !e451*/
6180 
6181 
6182 /* SCIPsortDownRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6183 #define SORTTPL_NAMEEXT DownRealBoolPtr
6184 #define SORTTPL_KEYTYPE SCIP_Real
6185 #define SORTTPL_FIELD1TYPE SCIP_Bool
6186 #define SORTTPL_FIELD2TYPE void*
6187 #define SORTTPL_BACKWARDS
6188 #include "scip/sorttpl.c" /*lint !e451*/
6189 
6190 
6191 /* SCIPsortDownRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6192 #define SORTTPL_NAMEEXT DownRealPtr
6193 #define SORTTPL_KEYTYPE SCIP_Real
6194 #define SORTTPL_FIELD1TYPE void*
6195 #define SORTTPL_BACKWARDS
6196 #include "scip/sorttpl.c" /*lint !e451*/
6197 
6198 
6199 /* SCIPsortDownRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6200