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 #define SORTTPL_NAMEEXT DownRealInt
6201 #define SORTTPL_KEYTYPE SCIP_Real
6202 #define SORTTPL_FIELD1TYPE int
6203 #define SORTTPL_BACKWARDS
6204 #include "scip/sorttpl.c" /*lint !e451*/
6205 
6206 /* SCIPsortDownRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6207 #define SORTTPL_NAMEEXT DownRealIntInt
6208 #define SORTTPL_KEYTYPE SCIP_Real
6209 #define SORTTPL_FIELD1TYPE int
6210 #define SORTTPL_FIELD2TYPE int
6211 #define SORTTPL_BACKWARDS
6212 #include "scip/sorttpl.c" /*lint !e451*/
6213 
6214 /* SCIPsortDownRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6215 #define SORTTPL_NAMEEXT DownRealIntLong
6216 #define SORTTPL_KEYTYPE SCIP_Real
6217 #define SORTTPL_FIELD1TYPE int
6218 #define SORTTPL_FIELD2TYPE SCIP_Longint
6219 #define SORTTPL_BACKWARDS
6220 #include "scip/sorttpl.c" /*lint !e451*/
6221 
6222 
6223 /* SCIPsortDownRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6224 #define SORTTPL_NAMEEXT DownRealIntPtr
6225 #define SORTTPL_KEYTYPE SCIP_Real
6226 #define SORTTPL_FIELD1TYPE int
6227 #define SORTTPL_FIELD2TYPE void*
6228 #define SORTTPL_BACKWARDS
6229 #include "scip/sorttpl.c" /*lint !e451*/
6230 
6231 
6232 /* SCIPsortDownRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6233 #define SORTTPL_NAMEEXT DownRealPtrPtr
6234 #define SORTTPL_KEYTYPE SCIP_Real
6235 #define SORTTPL_FIELD1TYPE void*
6236 #define SORTTPL_FIELD2TYPE void*
6237 #define SORTTPL_BACKWARDS
6238 #include "scip/sorttpl.c" /*lint !e451*/
6239 
6240 /* SCIPsortDownRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6241 #define SORTTPL_NAMEEXT DownRealRealInt
6242 #define SORTTPL_KEYTYPE SCIP_Real
6243 #define SORTTPL_FIELD1TYPE SCIP_Real
6244 #define SORTTPL_FIELD2TYPE int
6245 #define SORTTPL_BACKWARDS
6246 #include "scip/sorttpl.c" /*lint !e451*/
6247 
6248 /* SCIPsortDownRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6249 #define SORTTPL_NAMEEXT DownRealRealPtr
6250 #define SORTTPL_KEYTYPE SCIP_Real
6251 #define SORTTPL_FIELD1TYPE SCIP_Real
6252 #define SORTTPL_FIELD2TYPE void*
6253 #define SORTTPL_BACKWARDS
6254 #include "scip/sorttpl.c" /*lint !e451*/
6255 
6256 /* SCIPsortDownRealRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6257 #define SORTTPL_NAMEEXT DownRealRealPtrPtr
6258 #define SORTTPL_KEYTYPE SCIP_Real
6259 #define SORTTPL_FIELD1TYPE SCIP_Real
6260 #define SORTTPL_FIELD2TYPE void*
6261 #define SORTTPL_FIELD3TYPE void*
6262 #define SORTTPL_BACKWARDS
6263 #include "scip/sorttpl.c" /*lint !e451*/
6264 
6265 
6266 /* SCIPsortDownRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6267 #define SORTTPL_NAMEEXT DownRealLongRealInt
6268 #define SORTTPL_KEYTYPE SCIP_Real
6269 #define SORTTPL_FIELD1TYPE SCIP_Longint
6270 #define SORTTPL_FIELD2TYPE SCIP_Real
6271 #define SORTTPL_FIELD3TYPE int
6272 #define SORTTPL_BACKWARDS
6273 #include "scip/sorttpl.c" /*lint !e451*/
6274 
6275 
6276 /* SCIPsortDownRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6277 #define SORTTPL_NAMEEXT DownRealRealIntInt
6278 #define SORTTPL_KEYTYPE SCIP_Real
6279 #define SORTTPL_FIELD1TYPE SCIP_Real
6280 #define SORTTPL_FIELD2TYPE int
6281 #define SORTTPL_FIELD3TYPE int
6282 #define SORTTPL_BACKWARDS
6283 #include "scip/sorttpl.c" /*lint !e451*/
6284 
6285 
6286 /* SCIPsortDownRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6287 #define SORTTPL_NAMEEXT DownRealRealRealInt
6288 #define SORTTPL_KEYTYPE SCIP_Real
6289 #define SORTTPL_FIELD1TYPE SCIP_Real
6290 #define SORTTPL_FIELD2TYPE SCIP_Real
6291 #define SORTTPL_FIELD3TYPE int
6292 #define SORTTPL_BACKWARDS
6293 #include "scip/sorttpl.c" /*lint !e451*/
6294 
6295 
6296 /* SCIPsortDownRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6297 #define SORTTPL_NAMEEXT DownRealRealRealPtr
6298 #define SORTTPL_KEYTYPE SCIP_Real
6299 #define SORTTPL_FIELD1TYPE SCIP_Real
6300 #define SORTTPL_FIELD2TYPE SCIP_Real
6301 #define SORTTPL_FIELD3TYPE void*
6302 #define SORTTPL_BACKWARDS
6303 #include "scip/sorttpl.c" /*lint !e451*/
6304 
6305 
6306 /* SCIPsortDownRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6307 #define SORTTPL_NAMEEXT DownRealPtrPtrInt
6308 #define SORTTPL_KEYTYPE SCIP_Real
6309 #define SORTTPL_FIELD1TYPE void*
6310 #define SORTTPL_FIELD2TYPE void*
6311 #define SORTTPL_FIELD3TYPE int
6312 #define SORTTPL_BACKWARDS
6313 #include "scip/sorttpl.c" /*lint !e451*/
6314 
6315 /* SCIPsortDownRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6316 #define SORTTPL_NAMEEXT DownRealPtrPtrIntInt
6317 #define SORTTPL_KEYTYPE SCIP_Real
6318 #define SORTTPL_FIELD1TYPE void*
6319 #define SORTTPL_FIELD2TYPE void*
6320 #define SORTTPL_FIELD3TYPE int
6321 #define SORTTPL_FIELD4TYPE int
6322 #define SORTTPL_BACKWARDS
6323 #include "scip/sorttpl.c" /*lint !e451*/
6324 
6325 
6326 /* SCIPsortDownRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6327 #define SORTTPL_NAMEEXT DownRealRealRealBoolPtr
6328 #define SORTTPL_KEYTYPE SCIP_Real
6329 #define SORTTPL_FIELD1TYPE SCIP_Real
6330 #define SORTTPL_FIELD2TYPE SCIP_Real
6331 #define SORTTPL_FIELD3TYPE SCIP_Bool
6332 #define SORTTPL_FIELD4TYPE void*
6333 #define SORTTPL_BACKWARDS
6334 #include "scip/sorttpl.c" /*lint !e451*/
6335 
6336 
6337 /* SCIPsortDownRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6338 #define SORTTPL_NAMEEXT DownRealRealRealBoolBoolPtr
6339 #define SORTTPL_KEYTYPE SCIP_Real
6340 #define SORTTPL_FIELD1TYPE SCIP_Real
6341 #define SORTTPL_FIELD2TYPE SCIP_Real
6342 #define SORTTPL_FIELD3TYPE SCIP_Bool
6343 #define SORTTPL_FIELD4TYPE SCIP_Bool
6344 #define SORTTPL_FIELD5TYPE void*
6345 #include "scip/sorttpl.c" /*lint !e451*/
6346 
6347 
6348 /* SCIPsortDownInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6349 #define SORTTPL_NAMEEXT DownInt
6350 #define SORTTPL_KEYTYPE int
6351 #define SORTTPL_BACKWARDS
6352 #include "scip/sorttpl.c" /*lint !e451*/
6353 
6354 
6355 /* SCIPsortDownIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6356 #define SORTTPL_NAMEEXT DownIntInt
6357 #define SORTTPL_KEYTYPE int
6358 #define SORTTPL_FIELD1TYPE int
6359 #define SORTTPL_BACKWARDS
6360 #include "scip/sorttpl.c" /*lint !e451*/
6361 
6362 
6363 /* SCIPsortDownIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6364 #define SORTTPL_NAMEEXT DownIntIntReal
6365 #define SORTTPL_KEYTYPE int
6366 #define SORTTPL_FIELD1TYPE int
6367 #define SORTTPL_FIELD2TYPE SCIP_Real
6368 #define SORTTPL_BACKWARDS
6369 #include "scip/sorttpl.c" /*lint !e451*/
6370 
6371 
6372 /* SCIPsortDownIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6373 #define SORTTPL_NAMEEXT DownIntReal
6374 #define SORTTPL_KEYTYPE int
6375 #define SORTTPL_FIELD1TYPE SCIP_Real
6376 #define SORTTPL_BACKWARDS
6377 #include "scip/sorttpl.c" /*lint !e451*/
6378 
6379 
6380 /* SCIPsortDownIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6381 #define SORTTPL_NAMEEXT DownIntPtr
6382 #define SORTTPL_KEYTYPE int
6383 #define SORTTPL_FIELD1TYPE void*
6384 #define SORTTPL_BACKWARDS
6385 #include "scip/sorttpl.c" /*lint !e451*/
6386 
6387 
6388 /* SCIPsortDownIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6389 #define SORTTPL_NAMEEXT DownIntIntInt
6390 #define SORTTPL_KEYTYPE int
6391 #define SORTTPL_FIELD1TYPE int
6392 #define SORTTPL_FIELD2TYPE int
6393 #define SORTTPL_BACKWARDS
6394 #include "scip/sorttpl.c" /*lint !e451*/
6395 
6396 
6397 /* SCIPsortDownIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6398 #define SORTTPL_NAMEEXT DownIntIntLong
6399 #define SORTTPL_KEYTYPE int
6400 #define SORTTPL_FIELD1TYPE int
6401 #define SORTTPL_FIELD2TYPE SCIP_Longint
6402 #define SORTTPL_BACKWARDS
6403 #include "scip/sorttpl.c" /*lint !e451*/
6404 
6405 
6406 /* SCIPsortDownIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6407 #define SORTTPL_NAMEEXT DownIntIntPtr
6408 #define SORTTPL_KEYTYPE int
6409 #define SORTTPL_FIELD1TYPE int
6410 #define SORTTPL_FIELD2TYPE void*
6411 #define SORTTPL_BACKWARDS
6412 #include "scip/sorttpl.c" /*lint !e451*/
6413 
6414 
6415 /* SCIPsortDownIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6416 #define SORTTPL_NAMEEXT DownIntIntIntPtr
6417 #define SORTTPL_KEYTYPE int
6418 #define SORTTPL_FIELD1TYPE int
6419 #define SORTTPL_FIELD2TYPE int
6420 #define SORTTPL_FIELD3TYPE void*
6421 #define SORTTPL_BACKWARDS
6422 #include "scip/sorttpl.c" /*lint !e451*/
6423 
6424 
6425 /* SCIPsortDownIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6426 #define SORTTPL_NAMEEXT DownIntPtrIntReal
6427 #define SORTTPL_KEYTYPE int
6428 #define SORTTPL_FIELD1TYPE void*
6429 #define SORTTPL_FIELD2TYPE int
6430 #define SORTTPL_FIELD3TYPE SCIP_Real
6431 #define SORTTPL_BACKWARDS
6432 #include "scip/sorttpl.c" /*lint !e451*/
6433 
6434 
6435 /* SCIPsortDownLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6436 #define SORTTPL_NAMEEXT DownLong
6437 #define SORTTPL_KEYTYPE SCIP_Longint
6438 #define SORTTPL_BACKWARDS
6439 #include "scip/sorttpl.c" /*lint !e451*/
6440 
6441 
6442 /* SCIPsortDownLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6443 #define SORTTPL_NAMEEXT DownLongPtr
6444 #define SORTTPL_KEYTYPE SCIP_Longint
6445 #define SORTTPL_FIELD1TYPE void*
6446 #define SORTTPL_BACKWARDS
6447 #include "scip/sorttpl.c" /*lint !e451*/
6448 
6449 
6450 /* SCIPsortDownLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6451 #define SORTTPL_NAMEEXT DownLongPtrInt
6452 #define SORTTPL_KEYTYPE SCIP_Longint
6453 #define SORTTPL_FIELD1TYPE void*
6454 #define SORTTPL_FIELD2TYPE int
6455 #define SORTTPL_BACKWARDS
6456 #include "scip/sorttpl.c" /*lint !e451*/
6457 
6458 
6459 /* SCIPsortDownLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6460 #define SORTTPL_NAMEEXT DownLongPtrRealBool
6461 #define SORTTPL_KEYTYPE SCIP_Longint
6462 #define SORTTPL_FIELD1TYPE void*
6463 #define SORTTPL_FIELD2TYPE SCIP_Real
6464 #define SORTTPL_FIELD3TYPE SCIP_Bool
6465 #define SORTTPL_BACKWARDS
6466 #include "scip/sorttpl.c" /*lint !e451*/
6467 
6468 
6469 /* SCIPsortDownLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6470 #define SORTTPL_NAMEEXT DownLongPtrRealRealBool
6471 #define SORTTPL_KEYTYPE SCIP_Longint
6472 #define SORTTPL_FIELD1TYPE void*
6473 #define SORTTPL_FIELD2TYPE SCIP_Real
6474 #define SORTTPL_FIELD3TYPE SCIP_Real
6475 #define SORTTPL_FIELD4TYPE SCIP_Bool
6476 #define SORTTPL_BACKWARDS
6477 #include "scip/sorttpl.c" /*lint !e451*/
6478 
6479 
6480 /* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6481 #define SORTTPL_NAMEEXT DownLongPtrRealRealIntBool
6482 #define SORTTPL_KEYTYPE SCIP_Longint
6483 #define SORTTPL_FIELD1TYPE void*
6484 #define SORTTPL_FIELD2TYPE SCIP_Real
6485 #define SORTTPL_FIELD3TYPE SCIP_Real
6486 #define SORTTPL_FIELD4TYPE int
6487 #define SORTTPL_FIELD5TYPE SCIP_Bool
6488 #define SORTTPL_BACKWARDS
6489 #include "scip/sorttpl.c" /*lint !e451*/
6490 
6491 
6492 /* SCIPsortDownLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6493 #define SORTTPL_NAMEEXT DownLongPtrPtrInt
6494 #define SORTTPL_KEYTYPE SCIP_Longint
6495 #define SORTTPL_FIELD1TYPE void*
6496 #define SORTTPL_FIELD2TYPE void*
6497 #define SORTTPL_FIELD3TYPE int
6498 #define SORTTPL_BACKWARDS
6499 #include "scip/sorttpl.c" /*lint !e451*/
6500 
6501 
6502 /* SCIPsortDownLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6503 #define SORTTPL_NAMEEXT DownLongPtrPtrIntInt
6504 #define SORTTPL_KEYTYPE SCIP_Longint
6505 #define SORTTPL_FIELD1TYPE void*
6506 #define SORTTPL_FIELD2TYPE void*
6507 #define SORTTPL_FIELD3TYPE int
6508 #define SORTTPL_FIELD4TYPE int
6509 #define SORTTPL_BACKWARDS
6510 #include "scip/sorttpl.c" /*lint !e451*/
6511 
6512 
6513 /* SCIPsortDownLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6514 #define SORTTPL_NAMEEXT DownLongPtrPtrBoolInt
6515 #define SORTTPL_KEYTYPE SCIP_Longint
6516 #define SORTTPL_FIELD1TYPE void*
6517 #define SORTTPL_FIELD2TYPE void*
6518 #define SORTTPL_FIELD3TYPE SCIP_Bool
6519 #define SORTTPL_FIELD4TYPE int
6520 #define SORTTPL_BACKWARDS
6521 #include "scip/sorttpl.c" /*lint !e451*/
6522 
6523 
6524 /* SCIPsortDownPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6525 #define SORTTPL_NAMEEXT DownPtrIntIntBoolBool
6526 #define SORTTPL_KEYTYPE void*
6527 #define SORTTPL_FIELD1TYPE int
6528 #define SORTTPL_FIELD2TYPE int
6529 #define SORTTPL_FIELD3TYPE SCIP_Bool
6530 #define SORTTPL_FIELD4TYPE SCIP_Bool
6531 #define SORTTPL_PTRCOMP
6532 #define SORTTPL_BACKWARDS
6533 #include "scip/sorttpl.c" /*lint !e451*/
6534 
6535 
6536 /* SCIPsortDownIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6537 #define SORTTPL_NAMEEXT DownIntPtrIntIntBoolBool
6538 #define SORTTPL_KEYTYPE int
6539 #define SORTTPL_FIELD1TYPE void*
6540 #define SORTTPL_FIELD2TYPE int
6541 #define SORTTPL_FIELD3TYPE int
6542 #define SORTTPL_FIELD4TYPE SCIP_Bool
6543 #define SORTTPL_FIELD5TYPE SCIP_Bool
6544 #define SORTTPL_BACKWARDS
6545 #include "scip/sorttpl.c" /*lint !e451*/
6546 
6547 /*
6548  * Resulting activity
6549  */
6550 
6551 /** create a resource activity */
6553  SCIP_RESOURCEACTIVITY** activity, /**< pointer to store the resource activity */
6554  SCIP_VAR* var, /**< start time variable of the activity */
6555  int duration, /**< duration of the activity */
6556  int demand /**< demand of the activity */
6557  )
6558 {
6559  assert(activity != NULL);
6560 
6561  SCIP_ALLOC( BMSallocMemory(activity) );
6562 
6563  (*activity)->var = var;
6564  (*activity)->duration = duration;
6565  (*activity)->demand = demand;
6566 
6567  return SCIP_OKAY;
6568 }
6569 
6570 /** frees a resource activity */
6572  SCIP_RESOURCEACTIVITY** activity /**< pointer to the resource activity */
6573  )
6574 {
6575  assert(activity != NULL);
6576  assert(*activity != NULL);
6577 
6578  BMSfreeMemory(activity);
6579 }
6580 
6581 /* some simple variable functions implemented as defines */
6582 
6583 #ifndef NDEBUG
6584 
6585 /* In debug mode, the following methods are implemented as function calls to ensure
6586  * type validity.
6587  * In optimized mode, the methods are implemented as defines to improve performance.
6588  * However, we want to have them in the library anyways, so we have to undef the defines.
6589  */
6590 
6591 #undef SCIPactivityGetVar
6592 #undef SCIPactivityGetDuration
6593 #undef SCIPactivityGetDemand
6594 #undef SCIPactivityGetEnergy
6595 
6596 /** returns the start time variable of the resource activity */
6598  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6599  )
6600 {
6601  assert(activity != NULL);
6602 
6603  return activity->var;
6604 }
6605 
6606 /** returns the duration of the resource activity */
6608  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6609  )
6610 {
6611  assert(activity != NULL);
6612 
6613  return activity->duration;
6614 }
6615 
6616 /** returns the demand of the resource activity */
6618  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6619  )
6620 {
6621  assert(activity != NULL);
6622 
6623  return activity->demand;
6624 }
6625 
6626 /** returns the energy of the resource activity */
6628  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6629  )
6630 {
6631  assert(activity != NULL);
6632 
6633  return activity->duration * activity->demand ;
6634 }
6635 
6636 #endif
6637 
6638 /*
6639  * Resource Profile
6640  */
6641 
6642 /** helper method to create a profile */
6643 static
6645  SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6646  int capacity /**< resource capacity */
6647  )
6648 {
6649  SCIP_ALLOC( BMSallocMemory(profile) );
6650  BMSclearMemory(*profile);
6651 
6652  (*profile)->arraysize = 10;
6653  SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->timepoints, (*profile)->arraysize) );
6654  SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->loads, (*profile)->arraysize) );
6655 
6656  /* setup resource profile for use */
6657  (*profile)->ntimepoints = 1;
6658  (*profile)->timepoints[0] = 0;
6659  (*profile)->loads[0] = 0;
6660  (*profile)->capacity = capacity;
6661 
6662  return SCIP_OKAY;
6663 }
6664 
6665 /** creates resource profile */
6667  SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6668  int capacity /**< resource capacity */
6669  )
6670 {
6671  assert(profile != NULL);
6672  assert(capacity > 0);
6673 
6674  SCIP_CALL_FINALLY( doProfileCreate(profile, capacity), SCIPprofileFree(profile) );
6675 
6676  return SCIP_OKAY;
6677 }
6678 
6679 /** frees given resource profile */
6681  SCIP_PROFILE** profile /**< pointer to the resource profile */
6682  )
6683 {
6684  assert(profile != NULL);
6685 
6686  /* free resource profile */
6687  if( *profile != NULL )
6688  {
6689  BMSfreeMemoryArrayNull(&(*profile)->loads);
6690  BMSfreeMemoryArrayNull(&(*profile)->timepoints);
6691  BMSfreeMemory(profile);
6692  }
6693 }
6694 
6695 /** output of the given resource profile */
6697  SCIP_PROFILE* profile, /**< resource profile to output */
6698  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
6699  FILE* file /**< output file (or NULL for standard output) */
6700  )
6701 {
6702  int t;
6703 
6704  SCIPmessageFPrintInfo(messagehdlr, file, "Profile <%p> (capacity %d) --> ", (void*)profile, profile->capacity);
6705 
6706  for( t = 0; t < profile->ntimepoints; ++t )
6707  {
6708  if( t == 0 )
6709  SCIPmessageFPrintInfo(messagehdlr, file, "%d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6710  else
6711  SCIPmessageFPrintInfo(messagehdlr, file, ", %d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6712  }
6713 
6714  SCIPmessageFPrintInfo(messagehdlr, file,"\n");
6715 }
6716 
6717 /** returns the capacity of the resource profile */
6719  SCIP_PROFILE* profile /**< resource profile to use */
6720  )
6721 {
6722  assert(profile != NULL);
6723 
6724  return profile->capacity;
6725 }
6726 
6727 /** returns the number time points of the resource profile */
6729  SCIP_PROFILE* profile /**< resource profile to use */
6730  )
6731 {
6732  assert(profile != NULL);
6733 
6734  return profile->ntimepoints;
6735 }
6736 
6737 /** returns the time points of the resource profile */
6739  SCIP_PROFILE* profile /**< resource profile to use */
6740  )
6741 {
6742  assert(profile != NULL);
6743 
6744  return profile->timepoints;
6745 }
6746 
6747 /** returns the loads of the resource profile */
6749  SCIP_PROFILE* profile /**< resource profile to use */
6750  )
6751 {
6752  assert(profile != NULL);
6753 
6754  return profile->loads;
6755 }
6756 
6757 /** returns the time point for given position of the resource profile */
6759  SCIP_PROFILE* profile, /**< resource profile to use */
6760  int pos /**< position */
6761  )
6762 {
6763  assert(profile != NULL);
6764  assert(pos >= 0 && pos < profile->ntimepoints);
6765 
6766  return profile->timepoints[pos];
6767 }
6768 
6769 /** returns the loads of the resource profile at the given position */
6771  SCIP_PROFILE* profile, /**< resource profile */
6772  int pos /**< position */
6773  )
6774 {
6775  assert(profile != NULL);
6776  assert(pos >= 0 && pos < profile->ntimepoints);
6777 
6778  return profile->loads[pos];
6779 }
6780 
6781 /** returns if the given time point exists in the resource profile and stores the position of the given time point if it
6782  * exists; otherwise the position of the next smaller existing time point is stored
6783  */
6785  SCIP_PROFILE* profile, /**< resource profile to search */
6786  int timepoint, /**< time point to search for */
6787  int* pos /**< pointer to store the position */
6788  )
6789 {
6790  assert(profile != NULL);
6791  assert(timepoint >= 0);
6792  assert(profile->ntimepoints > 0);
6793  assert(profile->timepoints[0] == 0);
6794 
6795  /* find the position of time point in the time points array via binary search */
6796  if( SCIPsortedvecFindInt(profile->timepoints, timepoint, profile->ntimepoints, pos) )
6797  return TRUE;
6798 
6799  assert(*pos > 0);
6800  (*pos)--;
6801 
6802  return FALSE;
6803 }
6804 
6805 /* ensures that resource profile arrays is big enough */
6806 static
6808  SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6809  int neededsize /**< needed size */
6810  )
6811 {
6812  assert(profile->arraysize > 0);
6813 
6814  /* check whether the arrays are big enough */
6815  if( neededsize <= profile->arraysize )
6816  return SCIP_OKAY;
6817 
6818  profile->arraysize *= 2;
6819 
6820  SCIP_ALLOC( BMSreallocMemoryArray(&profile->timepoints, profile->arraysize) );
6821  SCIP_ALLOC( BMSreallocMemoryArray(&profile->loads, profile->arraysize) );
6822 
6823  return SCIP_OKAY;
6824 }
6825 
6826 /** inserts the given time point into the resource profile if it this time point does not exists yet; returns its
6827  * position in the time point array
6828  */
6829 static
6831  SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6832  int timepoint, /**< time point to insert */
6833  int* pos /**< pointer to store the insert position */
6834  )
6835 {
6836  assert(profile != NULL);
6837  assert(timepoint >= 0);
6838  assert(profile->arraysize >= profile->ntimepoints);
6839 
6840  /* get the position of the given time point in the resource profile array if it exists; otherwise the position of the
6841  * next smaller existing time point
6842  */
6843  if( !SCIPprofileFindLeft(profile, timepoint, pos) )
6844  {
6845  assert(*pos >= 0 && *pos < profile->ntimepoints);
6846  assert(timepoint >= profile->timepoints[*pos]);
6847 
6848  /* ensure that the arrays are big enough */
6849  SCIP_CALL( ensureProfileSize(profile, profile->ntimepoints + 1) );
6850  assert(profile->arraysize > profile->ntimepoints);
6851 
6852  /* insert new time point into the (sorted) resource profile */
6853  SCIPsortedvecInsertIntInt(profile->timepoints, profile->loads, timepoint, profile->loads[*pos],
6854  &profile->ntimepoints, pos);
6855  }
6856 
6857 #ifndef NDEBUG
6858  /* check if the time points are sorted */
6859  {
6860  int i;
6861  for( i = 1; i < profile->ntimepoints; ++i )
6862  assert(profile->timepoints[i-1] < profile->timepoints[i]);
6863  }
6864 #endif
6865 
6866  return SCIP_OKAY;
6867 }
6868 
6869 /** updates the resource profile due to inserting of a core */
6870 static
6872  SCIP_PROFILE* profile, /**< resource profile to update */
6873  int left, /**< left side of core interval */
6874  int right, /**< right side of core interval */
6875  int demand, /**< demand of the core */
6876  int* pos, /**< pointer to store the first position were it gets infeasible */
6877  SCIP_Bool* infeasible /**< pointer to store if the update is infeasible */
6878  )
6879 {
6880  int startpos;
6881  int endpos;
6882  int i;
6883 
6884  assert(profile != NULL);
6885  assert(profile->arraysize >= profile->ntimepoints);
6886  assert(left >= 0);
6887  assert(left < right);
6888  assert(infeasible != NULL);
6889 
6890  (*infeasible) = FALSE;
6891  (*pos) = -1;
6892 
6893  /* get position of the starttime in profile */
6894  SCIP_CALL( profileInsertTimepoint(profile, left, &startpos) );
6895  assert(profile->timepoints[startpos] == left);
6896 
6897  /* get position of the endtime in profile */
6898  SCIP_CALL( profileInsertTimepoint(profile, right, &endpos) );
6899  assert(profile->timepoints[endpos] == right);
6900 
6901  assert(startpos < endpos);
6902  assert(profile->arraysize >= profile->ntimepoints);
6903 
6904  /* remove/add the given demand from the core */
6905  for( i = startpos; i < endpos; ++i )
6906  {
6907  profile->loads[i] += demand;
6908 
6909  /* check if the core fits */
6910  if( profile->loads[i] > profile->capacity )
6911  {
6912  SCIPdebugMessage("core insertion detected infeasibility (pos %d)\n", i);
6913 
6914  (*infeasible) = TRUE;
6915  (*pos) = i;
6916 
6917  /* remove the partly inserted core since it does fit completely */
6918  for( ; i >= startpos; --i ) /*lint !e445*/
6919  profile->loads[i] -= demand;
6920 
6921  break;
6922  }
6923  }
6924 
6925  return SCIP_OKAY;
6926 }
6927 
6928 /** insert a core into resource profile; if the core is non-empty the resource profile will be updated otherwise nothing
6929  * happens
6930  */
6932  SCIP_PROFILE* profile, /**< resource profile */
6933  int left, /**< left side of the core */
6934  int right, /**< right side of the core */
6935  int demand, /**< demand of the core */
6936  int* pos, /**< pointer to store the first position were it gets infeasible */
6937  SCIP_Bool* infeasible /**< pointer to store if the core does not fit due to capacity */
6938  )
6939 {
6940  assert(profile != NULL);
6941  assert(left < right);
6942  assert(demand >= 0);
6943  assert(infeasible != NULL);
6944 
6945  (*infeasible) = FALSE;
6946  (*pos) = -1;
6947 
6948  /* insert core into the resource profile */
6949  SCIPdebugMessage("insert core [%d,%d] with demand %d\n", left, right, demand);
6950 
6951  if( demand > 0 )
6952  {
6953  /* try to insert core into the resource profile */
6954  SCIP_CALL( profileUpdate(profile, left, right, demand, pos, infeasible) );
6955  }
6956 
6957  return SCIP_OKAY;
6958 }
6959 
6960 /** subtracts the demand from the resource profile during core time */
6962  SCIP_PROFILE* profile, /**< resource profile to use */
6963  int left, /**< left side of the core */
6964  int right, /**< right side of the core */
6965  int demand /**< demand of the core */
6966  )
6967 {
6968  SCIP_Bool infeasible;
6969  int pos;
6970 
6971  assert(left < right);
6972 #ifndef NDEBUG
6973  {
6974  /* check if the left and right time points of the core correspond to a time point in the resource profile; this
6975  * should be the case since we added the core before to the resource profile
6976  */
6977  assert(SCIPprofileFindLeft(profile, left, &pos));
6978  assert(SCIPprofileFindLeft(profile, right, &pos));
6979  }
6980 #endif
6981 
6982  /* remove the core from the resource profile */
6983  SCIPdebugMessage("delete core [%d,%d] with demand %d\n", left, right, demand);
6984 
6985  SCIP_CALL( profileUpdate(profile, left, right, -demand, &pos, &infeasible) );
6986  assert(!infeasible);
6987 
6988  return SCIP_OKAY; /*lint !e438*/
6989 }
6990 
6991 /** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
6992 static
6994  SCIP_PROFILE* profile, /**< resource profile to use */
6995  int pos, /**< pointer to store the position in the profile to start the serch */
6996  int lst, /**< latest start time */
6997  int duration, /**< duration of the core */
6998  int demand, /**< demand of the core */
6999  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7000  )
7001 {
7002  int remainingduration;
7003  int startpos;
7004 
7005  assert(profile != NULL);
7006  assert(pos >= 0);
7007  assert(pos < profile->ntimepoints);
7008  assert(duration > 0);
7009  assert(demand > 0);
7010  assert(profile->loads[profile->ntimepoints-1] == 0);
7011 
7012  remainingduration = duration;
7013  startpos = pos;
7014  (*infeasible) = FALSE;
7015 
7016  if( profile->timepoints[startpos] > lst )
7017  {
7018  (*infeasible) = TRUE;
7019  return pos;
7020  }
7021 
7022  while( pos < profile->ntimepoints - 1 )
7023  {
7024  if( profile->loads[pos] + demand > profile->capacity )
7025  {
7026  SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos], pos);
7027  startpos = pos + 1;
7028  remainingduration = duration;
7029 
7030  if( profile->timepoints[startpos] > lst )
7031  {
7032  (*infeasible) = TRUE;
7033  return pos;
7034  }
7035  }
7036  else
7037  remainingduration -= profile->timepoints[pos+1] - profile->timepoints[pos];
7038 
7039  if( remainingduration <= 0 )
7040  break;
7041 
7042  pos++;
7043  }
7044 
7045  return startpos;
7046 }
7047 
7048 /** return the earliest possible starting point within the time interval [lb,ub] for a given core (given by its demand
7049  * and duration)
7050  */
7052  SCIP_PROFILE* profile, /**< resource profile to use */
7053  int est, /**< earliest starting time of the given core */
7054  int lst, /**< latest starting time of the given core */
7055  int duration, /**< duration of the core */
7056  int demand, /**< demand of the core */
7057  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7058  )
7059 {
7060  SCIP_Bool found;
7061  int pos;
7062 
7063  assert(profile != NULL);
7064  assert(est >= 0);
7065  assert(est <= lst);
7066  assert(duration >= 0);
7067  assert(demand >= 0);
7068  assert(infeasible != NULL);
7069  assert(profile->ntimepoints > 0);
7070  assert(profile->loads[profile->ntimepoints-1] == 0);
7071 
7072  SCIPdebugMessage("profile <%p>: find earliest start time (demad %d, duration %d) [%d,%d]\n", (void*)profile, demand, duration, est, lst);
7073 
7074  if( duration == 0 || demand == 0 )
7075  {
7076  *infeasible = FALSE;
7077  return est;
7078  }
7079 
7080  found = SCIPprofileFindLeft(profile, est, &pos);
7081  SCIPdebugMessage("profile <%p>: earliest start time does %s exist as time point (pos %d)\n", (void*)profile, found ? "" : "not", pos);
7082 
7083  /* if the position is the last time point in the profile, the core can be inserted at its earliest start time */
7084  if( pos == profile->ntimepoints - 1 )
7085  {
7086  (*infeasible) = FALSE;
7087  return est;
7088  }
7089 
7090  if( found )
7091  {
7092  /* if the start time matches a time point in the profile we can just search */
7093  assert(profile->timepoints[pos] == est);
7094  pos = profileFindFeasibleStart(profile, pos, lst, duration, demand, infeasible);
7095 
7096  assert(pos < profile->ntimepoints);
7097  est = profile->timepoints[pos];
7098  }
7099  else if( profile->loads[pos] + demand > profile->capacity )
7100  {
7101  /* if the the time point left to the start time has not enough free capacity we can just search the profile
7102  * starting from the next time point
7103  */
7104  assert(profile->timepoints[pos] <= est);
7105  pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7106 
7107  assert(pos < profile->ntimepoints);
7108  est = profile->timepoints[pos];
7109  }
7110  else
7111  {
7112  int remainingduration;
7113 
7114  /* check if the core can be placed at its earliest start time */
7115 
7116  assert(pos < profile->ntimepoints - 1);
7117 
7118  remainingduration = duration - (profile->timepoints[pos+1] - est);
7119  SCIPdebugMessage("remaining duration %d\n", remainingduration);
7120 
7121  if( remainingduration <= 0 )
7122  (*infeasible) = FALSE;
7123  else
7124  {
7125  pos = profileFindFeasibleStart(profile, pos+1, profile->timepoints[pos+1], remainingduration, demand, infeasible);
7126  SCIPdebugMessage("remaining duration can%s be processed\n", *infeasible ? "not" : "");
7127 
7128  if( *infeasible )
7129  {
7130  pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7131 
7132  assert(pos < profile->ntimepoints);
7133  est = profile->timepoints[pos];
7134  }
7135  }
7136  }
7137 
7138  return est;
7139 }
7140 
7141 /** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7142 static
7144  SCIP_PROFILE* profile, /**< resource profile to use */
7145  int pos, /**< pointer to store the position in the profile to start the search */
7146  int ect, /**< earliest completion time */
7147  int duration, /**< duration of the core */
7148  int demand, /**< demand of the core */
7149  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7150  )
7151 {
7152  int remainingduration;
7153  int endpos;
7154 
7155  assert(profile != NULL);
7156  assert(pos >= 0);
7157  assert(pos < profile->ntimepoints);
7158  assert(duration > 0);
7159  assert(demand > 0);
7160  assert(profile->ntimepoints > 0);
7161  assert(profile->loads[profile->ntimepoints-1] == 0);
7162 
7163  remainingduration = duration;
7164  endpos = pos;
7165  (*infeasible) = TRUE;
7166 
7167  if( profile->timepoints[endpos] < ect - duration )
7168  return pos;
7169 
7170  while( pos > 0 )
7171  {
7172  if( profile->loads[pos-1] + demand > profile->capacity )
7173  {
7174  SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos-1], pos-1);
7175 
7176  endpos = pos - 1;
7177  remainingduration = duration;
7178 
7179  if( profile->timepoints[endpos] < ect - duration )
7180  return pos;
7181  }
7182  else
7183  remainingduration -= profile->timepoints[pos] - profile->timepoints[pos-1];
7184 
7185  if( remainingduration <= 0 )
7186  {
7187  *infeasible = FALSE;
7188  break;
7189  }
7190 
7191  pos--;
7192  }
7193 
7194  return endpos;
7195 }
7196 
7197 /** return the latest possible starting point within the time interval [lb,ub] for a given core (given by its demand and
7198  * duration)
7199  */
7201  SCIP_PROFILE* profile, /**< resource profile to use */
7202  int est, /**< earliest possible start point */
7203  int lst, /**< latest possible start point */
7204  int duration, /**< duration of the core */
7205  int demand, /**< demand of the core */
7206  SCIP_Bool* infeasible /**< pointer store if the core cannot be inserted */
7207  )
7208 {
7209  SCIP_Bool found;
7210  int ect;
7211  int lct;
7212  int pos;
7213 
7214  assert(profile != NULL);
7215  assert(est >= 0);
7216  assert(est <= lst);
7217  assert(duration >= 0);
7218  assert(demand >= 0);
7219  assert(infeasible != NULL);
7220  assert(profile->ntimepoints > 0);
7221  assert(profile->loads[profile->ntimepoints-1] == 0);
7222 
7223  if( duration == 0 || demand == 0 )
7224  {
7225  *infeasible = FALSE;
7226  return lst;
7227  }
7228 
7229  ect = est + duration;
7230  lct = lst + duration;
7231 
7232  found = SCIPprofileFindLeft(profile, lct, &pos);
7233  SCIPdebugMessage("profile <%p>: latest completion time %d does %s exist as time point (pos %d)\n", (void*)profile, lct, found ? "" : "not", pos);
7234 
7235  if( found )
7236  {
7237  /* if the start time matches a time point in the profile we can just search */
7238  assert(profile->timepoints[pos] == lct);
7239  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7240 
7241  assert(pos < profile->ntimepoints && pos >= 0);
7242  lct = profile->timepoints[pos];
7243  }
7244  else if( profile->loads[pos] + demand > profile->capacity )
7245  {
7246  /* if the time point left to the start time has not enough free capacity we can just search the profile starting
7247  * from the next time point
7248  */
7249  assert(profile->timepoints[pos] < lct);
7250  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7251 
7252  assert(pos < profile->ntimepoints && pos >= 0);
7253  lct = profile->timepoints[pos];
7254  }
7255  else
7256  {
7257  int remainingduration;
7258 
7259  /* check if the core can be placed at its latest start time */
7260  assert(profile->timepoints[pos] < lct);
7261 
7262  remainingduration = duration - (lct - profile->timepoints[pos]);
7263 
7264  if( remainingduration <= 0 )
7265  (*infeasible) = FALSE;
7266  else
7267  {
7268  pos = profileFindDownFeasibleStart(profile, pos, profile->timepoints[pos], remainingduration, demand, infeasible);
7269 
7270  if( *infeasible )
7271  {
7272  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7273 
7274  assert(pos < profile->ntimepoints && pos >= 0);
7275  lct = profile->timepoints[pos];
7276  }
7277  }
7278  }
7279 
7280  return lct - duration;
7281 }
7282 
7283 /*
7284  * Directed graph
7285  */
7286 
7287 /** creates directed graph structure */
7289  SCIP_DIGRAPH** digraph, /**< pointer to store the created directed graph */
7290  BMS_BLKMEM* blkmem, /**< block memory to store the data */
7291  int nnodes /**< number of nodes */
7292  )
7293 {
7294  assert(digraph != NULL);
7295  assert(blkmem != NULL);
7296  assert(nnodes > 0);
7297 
7298  /* allocate memory for the graph and the arrays storing arcs and data */
7299  SCIP_ALLOC( BMSallocBlockMemory(blkmem, digraph) );
7300  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successors, nnodes) );
7301  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->arcdata, nnodes) );
7302  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successorssize, nnodes) );
7303  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nsuccessors, nnodes) );
7304  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nodedata, nnodes) );
7305 
7306  /* store number of nodes */
7307  (*digraph)->nnodes = nnodes;
7308 
7309  /* at the beginning, no components are stored */
7310  (*digraph)->blkmem = blkmem;
7311  (*digraph)->ncomponents = 0;
7312  (*digraph)->componentstartsize = 0;
7313  (*digraph)->components = NULL;
7314  (*digraph)->componentstarts = NULL;
7315 
7316  /* all nodes are initially considered as non-articulation points */
7317  (*digraph)->narticulations = -1;
7318  (*digraph)->articulations = NULL;
7319  (*digraph)->articulationscheck = FALSE;
7320 
7321  return SCIP_OKAY;
7322 }
7323 
7324 /** resize directed graph structure */
7326  SCIP_DIGRAPH* digraph, /**< directed graph */
7327  int nnodes /**< new number of nodes */
7328  )
7329 {
7330  int n;
7331  assert(digraph != NULL);
7332  assert(digraph->blkmem != NULL);
7333 
7334  /* check if the digraph has already a proper size */
7335  if( nnodes <= digraph->nnodes )
7336  return SCIP_OKAY;
7337 
7338  /* reallocate memory for increasing the arrays storing arcs and data */
7339  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successors, digraph->nnodes, nnodes) );
7340  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->arcdata, digraph->nnodes, nnodes) );
7341  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successorssize, digraph->nnodes, nnodes) );
7342  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nsuccessors, digraph->nnodes, nnodes) );
7343  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nodedata, digraph->nnodes, nnodes) );
7344 
7345  /* initialize the new node data structures */
7346  for( n = digraph->nnodes; n < nnodes; ++n )
7347  {
7348  digraph->nodedata[n] = NULL;
7349  digraph->arcdata[n] = NULL;
7350  digraph->successors[n] = NULL;
7351  digraph->successorssize[n] = 0;
7352  digraph->nsuccessors[n] = 0;
7353  }
7354 
7355  /* store the new number of nodes */
7356  digraph->nnodes = nnodes;
7357 
7358  return SCIP_OKAY;
7359 }
7360 
7361 /** copies directed graph structure
7362  *
7363  * @note The data in nodedata is copied verbatim. This possibly has to be adapted by the user.
7364  */
7366  SCIP_DIGRAPH** targetdigraph, /**< pointer to store the copied directed graph */
7367  SCIP_DIGRAPH* sourcedigraph, /**< source directed graph */
7368  BMS_BLKMEM* targetblkmem /**< block memory to store the target block memory, or NULL to use the same
7369  * the same block memory as used for the \p sourcedigraph */
7370  )
7371 {
7372  int ncomponents;
7373  int nnodes;
7374  int i;
7375  SCIP_Bool articulationscheck;
7376 
7377  assert(sourcedigraph != NULL);
7378  assert(targetdigraph != NULL);
7379 
7380  /* use the source digraph block memory if not specified otherwise */
7381  if( targetblkmem == NULL )
7382  targetblkmem = sourcedigraph->blkmem;
7383 
7384  assert(targetblkmem != NULL);
7385 
7386  SCIP_ALLOC( BMSallocBlockMemory(targetblkmem, targetdigraph) );
7387 
7388  nnodes = sourcedigraph->nnodes;
7389  ncomponents = sourcedigraph->ncomponents;
7390  articulationscheck = sourcedigraph->articulationscheck;
7391  (*targetdigraph)->nnodes = nnodes;
7392  (*targetdigraph)->ncomponents = ncomponents;
7393  (*targetdigraph)->blkmem = targetblkmem;
7394 
7395  /* copy arcs and data */
7396  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->successors, nnodes) );
7397  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->arcdata, nnodes) );
7398  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->nodedata, nnodes) );
7399 
7400  /* copy lists of successors and arc data */
7401  for( i = 0; i < nnodes; ++i )
7402  {
7403  if( sourcedigraph->nsuccessors[i] > 0 )
7404  {
7405  assert(sourcedigraph->successors[i] != NULL);
7406  assert(sourcedigraph->arcdata[i] != NULL);
7407 
7408  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->successors[i]),
7409  sourcedigraph->successors[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7410  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->arcdata[i]),
7411  sourcedigraph->arcdata[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7412  }
7413  /* copy node data - careful if these are pointers to some information -> need to be copied by hand */
7414  (*targetdigraph)->nodedata[i] = sourcedigraph->nodedata[i];
7415  }
7416 
7417  /* use nsuccessors as size to save memory */
7418  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->successorssize, sourcedigraph->nsuccessors, nnodes) );
7419  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->nsuccessors, sourcedigraph->nsuccessors, nnodes) );
7420 
7421  /* copy component data */
7422  if( ncomponents > 0 )
7423  {
7424  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->components, sourcedigraph->components,
7425  sourcedigraph->componentstarts[ncomponents]) );
7426  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->componentstarts,
7427  sourcedigraph->componentstarts,ncomponents + 1) ); /*lint !e776*/
7428  (*targetdigraph)->componentstartsize = ncomponents + 1;
7429  }
7430  else
7431  {
7432  (*targetdigraph)->components = NULL;
7433  (*targetdigraph)->componentstarts = NULL;
7434  (*targetdigraph)->componentstartsize = 0;
7435  }
7436 
7437  /* copy the articulation point information if it has been computed and is up-to-date */
7438  if( articulationscheck )
7439  {
7440  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->articulations, sourcedigraph->articulations, sourcedigraph->narticulations) );
7441  (*targetdigraph)->narticulations = sourcedigraph->narticulations;
7442  (*targetdigraph)->articulationscheck = TRUE;
7443  }
7444  else
7445  {
7446  (*targetdigraph)->narticulations = -1;
7447  (*targetdigraph)->articulations = NULL;
7448  (*targetdigraph)->articulationscheck = FALSE;
7449  }
7450 
7451  return SCIP_OKAY;
7452 }
7453 
7454 /** sets the sizes of the successor lists for the nodes in a directed graph and allocates memory for the lists */
7456  SCIP_DIGRAPH* digraph, /**< directed graph */
7457  int* sizes /**< sizes of the successor lists */
7458  )
7459 {
7460  int i;
7461  BMS_BLKMEM* blkmem;
7462 
7463  assert(digraph != NULL);
7464  assert(digraph->nnodes > 0);
7465  blkmem = digraph->blkmem;
7466 
7467  for( i = 0; i < digraph->nnodes; ++i )
7468  {
7469  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[i], sizes[i]) ); /*lint !e866*/
7470  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[i], sizes[i]) ); /*lint !e866*/
7471  digraph->successorssize[i] = sizes[i];
7472  digraph->nsuccessors[i] = 0;
7473  }
7474 
7475  return SCIP_OKAY;
7476 }
7477 
7478 /** frees given directed graph structure */
7480  SCIP_DIGRAPH** digraph /**< pointer to the directed graph */
7481  )
7482 {
7483  int i;
7484  BMS_BLKMEM* blkmem;
7485  SCIP_DIGRAPH* digraphptr;
7486 
7487  assert(digraph != NULL);
7488  assert(*digraph != NULL);
7489  assert((*digraph)->blkmem != NULL);
7490 
7491  blkmem = (*digraph)->blkmem;
7492  digraphptr = *digraph;
7493 
7494  /* free arrays storing the successor nodes and arc data */
7495  for( i = digraphptr->nnodes - 1; i >= 0; --i )
7496  {
7497  BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->successors[i], digraphptr->successorssize[i]);
7498  BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->arcdata[i], digraphptr->successorssize[i]);
7499  }
7500 
7501  /* free components structure */
7502  SCIPdigraphFreeComponents(digraphptr);
7503  assert(digraphptr->ncomponents == 0);
7504  assert(digraphptr->componentstartsize == 0);
7505  assert(digraphptr->components == NULL);
7506  assert(digraphptr->componentstarts == NULL);
7507 
7508  /* free the articulation points structure if it has been computed*/
7509  if( digraphptr->articulationscheck )
7510  BMSfreeBlockMemoryArray(blkmem, &digraphptr->articulations, digraphptr->narticulations);
7511 
7512  /* free directed graph data structure */
7513  BMSfreeBlockMemoryArray(blkmem, &digraphptr->nodedata, digraphptr->nnodes);
7514  BMSfreeBlockMemoryArray(blkmem, &digraphptr->successorssize, digraphptr->nnodes);
7515  BMSfreeBlockMemoryArray(blkmem, &digraphptr->nsuccessors, digraphptr->nnodes);
7516  BMSfreeBlockMemoryArray(blkmem, &digraphptr->successors, digraphptr->nnodes);
7517  BMSfreeBlockMemoryArray(blkmem, &digraphptr->arcdata, digraphptr->nnodes);
7518 
7519  BMSfreeBlockMemory(blkmem, digraph);
7520 }
7521 
7522 #define STARTSUCCESSORSSIZE 5
7523 
7524 /** ensures that successors array of one node in a directed graph is big enough */
7525 static
7527  SCIP_DIGRAPH* digraph, /**< directed graph */
7528  int idx, /**< index for which the size is ensured */
7529  int newsize /**< needed size */
7530  )
7531 {
7532  BMS_BLKMEM* blkmem;
7533 
7534  assert(digraph != NULL);
7535  assert(digraph->blkmem != NULL);
7536  assert(idx >= 0);
7537  assert(idx < digraph->nnodes);
7538  assert(newsize > 0);
7539  assert(digraph->successorssize[idx] == 0 || digraph->successors[idx] != NULL);
7540  assert(digraph->successorssize[idx] == 0 || digraph->arcdata[idx] != NULL);
7541 
7542  blkmem = digraph->blkmem;
7543 
7544  /* check whether array is big enough, and realloc, if needed */
7545  if( newsize > digraph->successorssize[idx] )
7546  {
7547  if( digraph->successors[idx] == NULL )
7548  {
7549  assert(digraph->arcdata[idx] == NULL);
7550  digraph->successorssize[idx] = STARTSUCCESSORSSIZE;
7551  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7552  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7553  }
7554  else
7555  {
7556  newsize = MAX(newsize, 2 * digraph->successorssize[idx]);
7557  assert(digraph->arcdata[idx] != NULL);
7558  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7559  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7560  digraph->successorssize[idx] = newsize;
7561  }
7562  }
7563 
7564  assert(newsize <= digraph->successorssize[idx]);
7565 
7566  return SCIP_OKAY;
7567 }
7568 
7569 /** add (directed) arc and a related data to the directed graph structure
7570  *
7571  * @note if the arc is already contained, it is added a second time
7572  */
7574  SCIP_DIGRAPH* digraph, /**< directed graph */
7575  int startnode, /**< start node of the arc */
7576  int endnode, /**< start node of the arc */
7577  void* data /**< data that should be stored for the arc; or NULL */
7578  )
7579 {
7580  assert(digraph != NULL);
7581  assert(startnode >= 0);
7582  assert(endnode >= 0);
7583  assert(startnode < digraph->nnodes);
7584  assert(endnode < digraph->nnodes);
7585 
7586  SCIP_CALL( ensureSuccessorsSize(digraph, startnode, digraph->nsuccessors[startnode] + 1) );
7587 
7588  /* add arc */
7589  digraph->successors[startnode][digraph->nsuccessors[startnode]] = endnode;
7590  digraph->arcdata[startnode][digraph->nsuccessors[startnode]] = data;
7591  digraph->nsuccessors[startnode]++;
7592 
7593  /* the articulation points are not up-to-date */
7594  digraph->articulationscheck = FALSE;
7595 
7596  return SCIP_OKAY;
7597 }
7598 
7599 /** add (directed) arc to the directed graph structure, if it is not contained, yet
7600  *
7601  * @note if there already exists an arc from startnode to endnode, the new arc is not added,
7602  * even if its data is different
7603  */
7605  SCIP_DIGRAPH* digraph, /**< directed graph */
7606  int startnode, /**< start node of the arc */
7607  int endnode, /**< start node of the arc */
7608  void* data /**< data that should be stored for the arc; or NULL */
7609  )
7610 {
7611  int nsuccessors;
7612  int i;
7613 
7614  assert(digraph != NULL);
7615  assert(startnode >= 0);
7616  assert(endnode >= 0);
7617  assert(startnode < digraph->nnodes);
7618  assert(endnode < digraph->nnodes);
7619 
7620  nsuccessors = digraph->nsuccessors[startnode];
7621 
7622  /* search for the arc in existing arcs */
7623  for( i = 0; i < nsuccessors; ++i )
7624  if( digraph->successors[startnode][i] == endnode )
7625  return SCIP_OKAY;
7626 
7627  SCIP_CALL( ensureSuccessorsSize(digraph, startnode, nsuccessors + 1) );
7628 
7629  /* add arc */
7630  digraph->successors[startnode][nsuccessors] = endnode;
7631  digraph->arcdata[startnode][nsuccessors] = data;
7632  ++(digraph->nsuccessors[startnode]);
7633 
7634  /* the articulation points are not up-to-date */
7635  digraph->articulationscheck = FALSE;
7636 
7637  return SCIP_OKAY;
7638 }
7639 
7640 /** sets the number of successors to a given value */
7642  SCIP_DIGRAPH* digraph, /**< directed graph */
7643  int node, /**< node for which the number of successors has to be changed */
7644  int nsuccessors /**< new number of successors */
7645  )
7646 {
7647  assert(digraph != NULL);
7648  assert(node >= 0);
7649  assert(node < digraph->nnodes);
7650 
7651  digraph->nsuccessors[node] = nsuccessors;
7652 
7653  return SCIP_OKAY;
7654 }
7655 
7656 /** returns the number of nodes of the given digraph */
7658  SCIP_DIGRAPH* digraph /**< directed graph */
7659  )
7660 {
7661  assert(digraph != NULL);
7662 
7663  return digraph->nnodes;
7664 }
7665 
7666 /** returns the node data, or NULL if no data exist */
7668  SCIP_DIGRAPH* digraph, /**< directed graph */
7669  int node /**< node for which the node data is returned */
7670  )
7671 {
7672  assert(digraph != NULL);
7673  assert(node >= 0);
7674  assert(node < digraph->nnodes);
7675 
7676  return digraph->nodedata[node];
7677 }
7678 
7679 /** sets the node data
7680  *
7681  * @note The old user pointer is not freed. This has to be done by the user
7682  */
7684  SCIP_DIGRAPH* digraph, /**< directed graph */
7685  void* dataptr, /**< user node data pointer, or NULL */
7686  int node /**< node for which the node data is returned */
7687  )
7688 {
7689  assert(digraph != NULL);
7690  assert(node >= 0);
7691  assert(node < digraph->nnodes);
7692 
7693  digraph->nodedata[node] = dataptr;
7694 }
7695 
7696 /** returns the total number of arcs in the given digraph */
7698  SCIP_DIGRAPH* digraph /**< directed graph */
7699  )
7700 {
7701  int i;
7702  int narcs;
7703 
7704  assert(digraph != NULL);
7705 
7706  /* count number of arcs */
7707  narcs = 0;
7708  for( i = 0; i < digraph->nnodes; ++i )
7709  narcs += digraph->nsuccessors[i];
7710 
7711  return narcs;
7712 }
7713 
7714 /** returns the number of successor nodes of the given node */
7716  SCIP_DIGRAPH* digraph, /**< directed graph */
7717  int node /**< node for which the number of outgoing arcs is returned */
7718  )
7719 {
7720  assert(digraph != NULL);
7721  assert(node >= 0);
7722  assert(node < digraph->nnodes);
7723  assert(digraph->nsuccessors[node] >= 0);
7724  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7725 
7726  return digraph->nsuccessors[node];
7727 }
7728 
7729 /** returns the array of indices of the successor nodes; this array must not be changed from outside */
7731  SCIP_DIGRAPH* digraph, /**< directed graph */
7732  int node /**< node for which the array of outgoing arcs is returned */
7733  )
7734 {
7735  assert(digraph != NULL);
7736  assert(node >= 0);
7737  assert(node < digraph->nnodes);
7738  assert(digraph->nsuccessors[node] >= 0);
7739  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7740  assert((digraph->nsuccessors[node] == 0) || (digraph->successors[node] != NULL));
7741 
7742  return digraph->successors[node];
7743 }
7744 
7745 /** returns the array of data corresponding to the arcs originating at the given node, or NULL if no data exist; this
7746  * array must not be changed from outside
7747  */
7749  SCIP_DIGRAPH* digraph, /**< directed graph */
7750  int node /**< node for which the data corresponding to the outgoing arcs is returned */
7751  )
7752 {
7753  assert(digraph != NULL);
7754  assert(node >= 0);
7755  assert(node < digraph->nnodes);
7756  assert(digraph->nsuccessors[node] >= 0);
7757  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7758  assert(digraph->arcdata != NULL);
7759 
7760  return digraph->arcdata[node];
7761 }
7762 
7763 /** performs depth-first-search in the given directed graph from the given start node */
7764 static
7766  SCIP_DIGRAPH* digraph, /**< directed graph */
7767  int startnode, /**< node to start the depth-first-search */
7768  SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7769  int* dfsstack, /**< array of size number of nodes to store the stack;
7770  * only needed for performance reasons */
7771  int* stackadjvisited, /**< array of size number of nodes to store the number of adjacent nodes already visited
7772  * for each node on the stack; only needed for performance reasons */
7773  int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse dfs order */
7774  int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at startnode */
7775  )
7776 {
7777  int stackidx;
7778 
7779  assert(digraph != NULL);
7780  assert(startnode >= 0);
7781  assert(startnode < digraph->nnodes);
7782  assert(visited != NULL);
7783  assert(visited[startnode] == FALSE);
7784  assert(dfsstack != NULL);
7785  assert(dfsnodes != NULL);
7786  assert(ndfsnodes != NULL);
7787 
7788  /* put start node on the stack */
7789  dfsstack[0] = startnode;
7790  stackadjvisited[0] = 0;
7791  stackidx = 0;
7792 
7793  while( stackidx >= 0 )
7794  {
7795  int currnode;
7796  int sadv;
7797 
7798  /* get next node from stack */
7799  currnode = dfsstack[stackidx];
7800 
7801  sadv = stackadjvisited[stackidx];
7802  assert( 0 <= sadv && sadv <= digraph->nsuccessors[currnode] );
7803 
7804  /* mark current node as visited */
7805  assert( visited[currnode] == (sadv > 0) );
7806  visited[currnode] = TRUE;
7807 
7808  /* iterate through the successor list until we reach unhandled node */
7809  while( sadv < digraph->nsuccessors[currnode] && visited[digraph->successors[currnode][sadv]] )
7810  ++sadv;
7811 
7812  /* the current node was completely handled, remove it from stack */
7813  if( sadv == digraph->nsuccessors[currnode] )
7814  {
7815  --stackidx;
7816 
7817  /* store node in the sorted nodes array */
7818  dfsnodes[(*ndfsnodes)++] = currnode;
7819  }
7820  /* handle next unhandled successor node */
7821  else
7822  {
7823  assert( ! visited[digraph->successors[currnode][sadv]] );
7824 
7825  /* store current stackadjvisted index */
7826  stackadjvisited[stackidx] = sadv + 1;
7827 
7828  /* put the successor node onto the stack */
7829  ++stackidx;
7830  dfsstack[stackidx] = digraph->successors[currnode][sadv];
7831  stackadjvisited[stackidx] = 0;
7832  assert( stackidx < digraph->nnodes );
7833  }
7834  }
7835 }
7836 
7837 /** checks for articulation points in a given directed graph through a recursive depth-first-search.
7838  * starts from a given start node and keeps track of the nodes' discovery time in search for back edges.
7839  *
7840  * @note an articulation point is a node whose removal disconnects a connected graph or increases
7841  * the number of connected components in a disconnected graph
7842  */
7843 static
7845  SCIP_DIGRAPH* digraph, /**< directed graph */
7846  int startnode, /**< node to start the depth-first-search */
7847  SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7848  int* tdisc, /**< array of size number of nodes to store each node's discovery time */
7849  int* mindisc, /**< array of size number of nodes to store the discovery time of the earliest discovered vertex
7850  * to which startnode (or any node in the subtree rooted at it) is having a back edge */
7851  int* parent, /**< array to store the parent of each node in the DFS tree */
7852  SCIP_Bool* articulationflag, /**< array to mark whether a node is identified as an articulation point */
7853  int time /**< current discovery time in the DFS */
7854  )
7855 {
7856  int n;
7857  int nchildren = 0;
7858  int nsucc;
7859  int* succnodes;
7860 
7861  assert(digraph != NULL);
7862  assert(startnode >= 0);
7863  assert(startnode < digraph->nnodes);
7864  assert(visited != NULL);
7865  assert(visited[startnode] == FALSE);
7866  assert(tdisc != NULL);
7867  assert(mindisc != NULL);
7868  assert(parent != NULL);
7869  assert(articulationflag != NULL);
7870  assert(time >= 0);
7871 
7872  nsucc = (int) SCIPdigraphGetNSuccessors(digraph, startnode);
7873  succnodes = (int*) SCIPdigraphGetSuccessors(digraph, startnode);
7874  visited[startnode] = TRUE;
7875  tdisc[startnode] = time + 1;
7876  mindisc[startnode] = time + 1;
7877 
7878  /* process all the adjacent nodes to startnode */
7879  for( n = 0; n < nsucc; ++n)
7880  {
7881  if( !visited[succnodes[n]] )
7882  {
7883  parent[succnodes[n]] = startnode;
7884  ++nchildren;
7885  findArticulationPointsUtil(digraph, succnodes[n], visited, tdisc, mindisc, parent, articulationflag, time + 1);
7886  /* updated the mindisc of startnode when the DFS concludes for node n*/
7887  mindisc[startnode] = MIN(mindisc[startnode], mindisc[succnodes[n]]);
7888 
7889  /* the root is an articulation point if it has more than 2 children*/
7890  if( parent[startnode] == -1 && nchildren > 1 )
7891  articulationflag[startnode] = TRUE;
7892  /* a vertex startnode is an articulation point if it is not the root and
7893  * there is no back edge from the subtree rooted at child n to any of the ancestors of startnode */
7894  if( parent[startnode] > -1 && mindisc[succnodes[n]] >= tdisc[startnode] )
7895  articulationflag[startnode] = TRUE;
7896  }
7897  else
7898  {
7899  if( parent[startnode] != succnodes[n] )
7900  mindisc[startnode] = MIN(mindisc[startnode], tdisc[succnodes[n]]);
7901  }
7902  }
7903 
7904  if( articulationflag[startnode] )
7905  ++digraph->narticulations;
7906 }
7907 
7908 /** identifies the articulation points in a given directed graph
7909  * uses the helper recursive function findArticulationPointsUtil
7910  */
7912  SCIP_DIGRAPH* digraph, /**< directed graph */
7913  int** articulations, /**< array to store the sorted node indices of the computed articulation points, or NULL */
7914  int* narticulations /**< number of the computed articulation points, or NULL */
7915  )
7916 {
7917  SCIP_RETCODE retcode = SCIP_OKAY;
7918  BMS_BLKMEM* blkmem;
7919  SCIP_Bool* visited = NULL;
7920  SCIP_Bool* articulationflag = NULL;
7921  int* tdisc = NULL;
7922  int* mindisc = NULL;
7923  int* parent = NULL;
7924  int n;
7925  int articulationidx = 0;
7926  int time = 0;
7927 
7928  assert(digraph != NULL);
7929  assert(digraph->nnodes > 0);
7930 
7931  /* Only perform the computation if the articulation points are NOT up-to-date */
7932  if( !digraph->articulationscheck )
7933  {
7934  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&visited, digraph->nnodes), TERMINATE );
7935  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&tdisc, digraph->nnodes), TERMINATE );
7936  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&mindisc, digraph->nnodes), TERMINATE );
7937  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&parent, digraph->nnodes), TERMINATE );
7938  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&articulationflag, digraph->nnodes), TERMINATE );
7939 
7940  assert(digraph->blkmem != NULL);
7941  blkmem = digraph->blkmem;
7942 
7943  if( digraph->narticulations >= 0 ) /* case: articulations have already been computed but not up-to-date */
7944  BMSfreeBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations);
7945 
7946  /* Initialize the no. of articulation points ahead of the recursive computation */
7947  digraph->narticulations = 0;
7948 
7949  for( n = 0; n < digraph->nnodes; ++n )
7950  {
7951  visited[n] = FALSE;
7952  parent[n] = -1;
7953  articulationflag[n] = FALSE;
7954  }
7955 
7956  /* the function is called on every unvisited node in the graph to cover the disconnected graph case */
7957  for( n = 0; n < digraph->nnodes; ++n )
7958  {
7959  if( !visited[n] )
7960  findArticulationPointsUtil(digraph, n, visited, tdisc, mindisc, parent, articulationflag, time);
7961  }
7962 
7963  /* allocation of the block memory for the node indices of the articulation points*/
7964  SCIP_ALLOC_TERMINATE( retcode, BMSallocBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations), TERMINATE );
7965 
7966  for( n = 0; n < digraph->nnodes; ++n )
7967  {
7968  if( articulationflag[n] )
7969  {
7970  digraph->articulations[articulationidx] = n;
7971  ++articulationidx;
7972  }
7973  }
7974  }
7975 
7976  if( articulations != NULL )
7977  (*articulations) = digraph->articulations;
7978  if( narticulations != NULL )
7979  (*narticulations) = digraph->narticulations;
7980 
7981  /* the articulation points are now up-to-date */
7982  digraph->articulationscheck = TRUE;
7983 
7984 /* cppcheck-suppress unusedLabel */
7985 TERMINATE:
7986  BMSfreeMemoryArrayNull(&articulationflag);
7987  BMSfreeMemoryArrayNull(&parent);
7988  BMSfreeMemoryArrayNull(&mindisc);
7989  BMSfreeMemoryArrayNull(&tdisc);
7990  BMSfreeMemoryArrayNull(&visited);
7991 
7992  return retcode;
7993 }
7994 
7995 /** Compute undirected connected components on the given graph.
7996  *
7997  * @note For each arc, its reverse is added, so the graph does not need to be the directed representation of an
7998  * undirected graph.
7999  */
8001  SCIP_DIGRAPH* digraph, /**< directed graph */
8002  int minsize, /**< all components with less nodes are ignored */
8003  int* components, /**< array with as many slots as there are nodes in the directed graph
8004  * to store for each node the component to which it belongs
8005  * (components are numbered 0 to ncomponents - 1); or NULL, if components
8006  * are accessed one-by-one using SCIPdigraphGetComponent() */
8007  int* ncomponents /**< pointer to store the number of components; or NULL, if the
8008  * number of components is accessed by SCIPdigraphGetNComponents() */
8009  )
8010 {
8011  BMS_BLKMEM* blkmem;
8012  SCIP_Bool* visited;
8013  int* ndirectedsuccessors;
8014  int* stackadjvisited;
8015  int* dfsstack;
8016  int ndfsnodes;
8017  int compstart;
8018  int v;
8019  int i;
8020  int j;
8021 
8022  SCIP_RETCODE retcode = SCIP_OKAY;
8023 
8024  assert(digraph != NULL);
8025  assert(digraph->nnodes > 0);
8026  assert(digraph->blkmem != NULL);
8027 
8028  blkmem = digraph->blkmem;
8029 
8030  /* first free the old components */
8031  if( digraph->ncomponents > 0 )
8032  {
8033  SCIPdigraphFreeComponents(digraph);
8034  }
8035 
8036  digraph->ncomponents = 0;
8037  digraph->componentstartsize = 10;
8038 
8039  /* storage to hold components is stored in block memory */
8040  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes) );
8042 
8043  /* allocate temporary arrays */
8044  SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8045  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8046  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8047  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&ndirectedsuccessors, digraph->nnodes), TERMINATE );
8048 
8049  digraph->componentstarts[0] = 0;
8050 
8051  /* store the number of directed arcs per node */
8052  BMScopyMemoryArray(ndirectedsuccessors, digraph->nsuccessors, digraph->nnodes);
8053 
8054  /* add reverse arcs to the graph */
8055  for( i = digraph->nnodes - 1; i >= 0; --i )
8056  {
8057  for( j = 0; j < ndirectedsuccessors[i]; ++j )
8058  {
8059  SCIP_CALL_TERMINATE( retcode, SCIPdigraphAddArc(digraph, digraph->successors[i][j], i, NULL), TERMINATE );
8060  }
8061  }
8062 
8063  for( v = 0; v < digraph->nnodes; ++v )
8064  {
8065  if( visited[v] )
8066  continue;
8067 
8068  compstart = digraph->componentstarts[digraph->ncomponents];
8069  ndfsnodes = 0;
8070  depthFirstSearch(digraph, v, visited, dfsstack, stackadjvisited,
8071  &digraph->components[compstart], &ndfsnodes);
8072 
8073  /* forget about this component if it is too small */
8074  if( ndfsnodes >= minsize )
8075  {
8076  digraph->ncomponents++;
8077 
8078  /* enlarge componentstartsize array, if needed */
8079  if( digraph->ncomponents >= digraph->componentstartsize )
8080  {
8081  int newsize;
8082 
8083  newsize = 2 * digraph->componentstartsize;
8084  assert(digraph->ncomponents < newsize);
8085 
8086  SCIP_ALLOC_TERMINATE( retcode, BMSreallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize, newsize), TERMINATE );
8087  digraph->componentstartsize = newsize;
8088  }
8089  digraph->componentstarts[digraph->ncomponents] = compstart + ndfsnodes;
8090 
8091  /* store component number for contained nodes if array was given */
8092  if( components != NULL )
8093  {
8094  for( i = digraph->componentstarts[digraph->ncomponents] - 1; i >= compstart; --i )
8095  {
8096  components[digraph->components[i]] = digraph->ncomponents - 1;
8097  }
8098  }
8099  }
8100  }
8101 
8102  /* restore the number of directed arcs per node */
8103  BMScopyMemoryArray(digraph->nsuccessors, ndirectedsuccessors, digraph->nnodes);
8104  BMSclearMemoryArray(visited, digraph->nnodes);
8105 
8106  /* return number of components, if the pointer was given */
8107  if( ncomponents != NULL )
8108  (*ncomponents) = digraph->ncomponents;
8109 
8110 TERMINATE:
8111  if( retcode != SCIP_OKAY )
8112  {
8113  SCIPdigraphFreeComponents(digraph);
8114  }
8115  BMSfreeMemoryArrayNull(&ndirectedsuccessors);
8116  BMSfreeMemoryArrayNull(&stackadjvisited);
8117  BMSfreeMemoryArrayNull(&dfsstack);
8118  BMSfreeMemoryArrayNull(&visited);
8119 
8120  return retcode;
8121 }
8122 
8123 /** Performs an (almost) topological sort on the undirected components of the given directed graph. The undirected
8124  * components should be computed before using SCIPdigraphComputeUndirectedComponents().
8125  *
8126  * @note In general a topological sort is not unique. Note, that there might be directed cycles, that are randomly
8127  * broken, which is the reason for having only almost topologically sorted arrays.
8128  */
8130  SCIP_DIGRAPH* digraph /**< directed graph */
8131  )
8132 {
8133  SCIP_Bool* visited = NULL;
8134  int* comps;
8135  int* compstarts;
8136  int* stackadjvisited = NULL;
8137  int* dfsstack = NULL;
8138  int* dfsnodes = NULL;
8139  int ndfsnodes;
8140  int ncomps;
8141  int i;
8142  int j;
8143  int k;
8144  int endidx;
8145  SCIP_RETCODE retcode = SCIP_OKAY;
8146 
8147  assert(digraph != NULL);
8148 
8149  ncomps = digraph->ncomponents;
8150  comps = digraph->components;
8151  compstarts = digraph->componentstarts;
8152 
8153  SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8154  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsnodes, digraph->nnodes), TERMINATE );
8155  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8156  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8157 
8158  /* sort the components (almost) topologically */
8159  for( i = 0; i < ncomps; ++i )
8160  {
8161  endidx = compstarts[i+1] - 1;
8162  ndfsnodes = 0;
8163  for( j = compstarts[i]; j < compstarts[i+1]; ++j )
8164  {
8165  if( visited[comps[j]] )
8166  continue;
8167 
8168  /* perform depth first search, nodes visited in this call are appended to the list dfsnodes in reverse
8169  * dfs order, after the nodes already contained;
8170  * so at every point in time, the nodes in dfsnode are in reverse (almost) topological order
8171  */
8172  depthFirstSearch(digraph, comps[j], visited, dfsstack, stackadjvisited, dfsnodes, &ndfsnodes);
8173  }
8174  assert(endidx - ndfsnodes == compstarts[i] - 1);
8175 
8176  /* copy reverse (almost) topologically sorted array of nodes reached by the dfs searches;
8177  * reverse their order to get an (almost) topologically sort
8178  */
8179  for( k = 0; k < ndfsnodes; ++k )
8180  {
8181  digraph->components[endidx - k] = dfsnodes[k];
8182  }
8183  }
8184 
8185 TERMINATE:
8186  BMSfreeMemoryArrayNull(&stackadjvisited);
8187  BMSfreeMemoryArrayNull(&dfsstack);
8188  BMSfreeMemoryArrayNull(&dfsnodes);
8189  BMSfreeMemoryArrayNull(&visited);
8190 
8191  return retcode;
8192 }
8193 
8194 /** returns the number of previously computed undirected components for the given directed graph */
8196  SCIP_DIGRAPH* digraph /**< directed graph */
8197  )
8198 {
8199  assert(digraph != NULL);
8200  assert(digraph->componentstartsize > 0); /* components should have been computed */
8201 
8202  return digraph->ncomponents;
8203 }
8204 
8205 /** Returns the previously computed undirected component of the given number for the given directed graph.
8206  * If the components were sorted using SCIPdigraphTopoSortComponents(), the component is (almost) topologically sorted.
8207  */
8209  SCIP_DIGRAPH* digraph, /**< directed graph */
8210  int compidx, /**< number of the component to return */
8211  int** nodes, /**< pointer to store the nodes in the component; or NULL, if not needed */
8212  int* nnodes /**< pointer to store the number of nodes in the component;
8213  * or NULL, if not needed */
8214  )
8215 {
8216  assert(digraph != NULL);
8217  assert(compidx >= 0);
8218  assert(compidx < digraph->ncomponents);
8219  assert(nodes != NULL || nnodes != NULL);
8220 
8221  if( nodes != NULL )
8222  (*nodes) = &(digraph->components[digraph->componentstarts[compidx]]);
8223  if( nnodes != NULL )
8224  (*nnodes) = digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx];
8225 }
8226 
8227 /* Performs Tarjan's algorithm for a given directed graph to obtain the strongly connected components
8228  * which are reachable from a given node.
8229  */
8230 static
8231 void tarjan(
8232  SCIP_DIGRAPH* digraph, /**< directed graph */
8233  int v, /**< node to start the algorithm */
8234  int* lowlink, /**< array to store lowlink values */
8235  int* dfsidx, /**< array to store dfs indices */
8236  int* stack, /**< array to store a stack */
8237  int* stacksize, /**< pointer to store the size of the stack */
8238  SCIP_Bool* unprocessed, /**< array to store which node is unprocessed yet */
8239  SCIP_Bool* nodeinstack, /**< array to store which nodes are in the stack */
8240  int* maxdfs, /**< pointer to store index for DFS */
8241  int* strongcomponents, /**< array to store for each node the strongly connected
8242  * component to which it belongs (components are
8243  * numbered 0 to nstrongcomponents - 1); */
8244  int* nstrongcomponents, /**< pointer to store the number of computed components so far */
8245  int* strongcompstartidx, /**< array to store the start index of the computed components */
8246  int* nstorednodes /**< pointer to store the number of already stored nodes */
8247  )
8248 {
8249  int i;
8250 
8251  assert(digraph != NULL);
8252  assert(v >= 0);
8253  assert(v < digraph->nnodes);
8254  assert(lowlink != NULL);
8255  assert(dfsidx != NULL);
8256  assert(stack != NULL);
8257  assert(stacksize != NULL);
8258  assert(*stacksize >= 0);
8259  assert(*stacksize < digraph->nnodes);
8260  assert(unprocessed != NULL);
8261  assert(nodeinstack != NULL);
8262  assert(maxdfs != NULL);
8263  assert(strongcomponents != NULL);
8264  assert(nstrongcomponents != NULL);
8265  assert(strongcompstartidx != NULL);
8266  assert(nstorednodes != NULL);
8267  assert(*nstorednodes >= 0 && *nstorednodes < digraph->nnodes);
8268 
8269  dfsidx[v] = *maxdfs;
8270  lowlink[v] = *maxdfs;
8271  *maxdfs += 1;
8272 
8273  /* add v to the stack */
8274  stack[*stacksize] = v;
8275  *stacksize += 1;
8276  nodeinstack[v] = TRUE;
8277 
8278  /* mark v as processed */
8279  unprocessed[v] = FALSE;
8280 
8281  for( i = 0; i < digraph->nsuccessors[v]; ++i )
8282  {
8283  int w;
8284 
8285  /* edge (v,w) */
8286  w = digraph->successors[v][i];
8287 
8288  if( unprocessed[w] )
8289  {
8290  tarjan(digraph, w, lowlink, dfsidx, stack, stacksize, unprocessed, nodeinstack, maxdfs, strongcomponents,
8291  nstrongcomponents, strongcompstartidx, nstorednodes);
8292 
8293  assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8294  assert(lowlink[w] >= 0 && lowlink[w] < digraph->nnodes);
8295 
8296  /* update lowlink */
8297  lowlink[v] = MIN(lowlink[v], lowlink[w]);
8298  }
8299  else if( nodeinstack[w] )
8300  {
8301  assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8302  assert(dfsidx[w] >= 0 && dfsidx[w] < digraph->nnodes);
8303 
8304  /* update lowlink */
8305  lowlink[v] = MIN(lowlink[v], dfsidx[w]);
8306  }
8307  }
8308 
8309  /* found a root of a strong component */
8310  if( lowlink[v] == dfsidx[v] )
8311  {
8312  int w;
8313 
8314  strongcompstartidx[*nstrongcomponents] = *nstorednodes;
8315  *nstrongcomponents += 1;
8316 
8317  do
8318  {
8319  assert(*stacksize > 0);
8320 
8321  /* stack.pop() */
8322  w = stack[*stacksize - 1];
8323  *stacksize -= 1;
8324  nodeinstack[w] = FALSE;
8325 
8326  /* store the node in the corresponding component */
8327  strongcomponents[*nstorednodes] = w;
8328  *nstorednodes += 1;
8329  }
8330  while( v != w );
8331  }
8332 }
8333 
8334 /** Computes all strongly connected components of an undirected connected component with Tarjan's Algorithm.
8335  * The resulting strongly connected components are sorted topologically (starting from the end of the
8336  * strongcomponents array).
8337  *
8338  * @note In general a topological sort of the strongly connected components is not unique.
8339  */
8341  SCIP_DIGRAPH* digraph, /**< directed graph */
8342  int compidx, /**< number of the undirected connected component */
8343  int* strongcomponents, /**< array to store the strongly connected components
8344  * (length >= size of the component) */
8345  int* strongcompstartidx, /**< array to store the start indices of the strongly connected
8346  * components (length >= size of the component) */
8347  int* nstrongcomponents /**< pointer to store the number of strongly connected
8348  * components */
8349  )
8350 {
8351  int* lowlink = NULL;
8352  int* dfsidx = NULL;
8353  int* stack = NULL;
8354  int stacksize;
8355  SCIP_Bool* unprocessed = NULL;
8356  SCIP_Bool* nodeinstack = NULL;
8357  int maxdfs;
8358  int nstorednodes;
8359  int i;
8360  SCIP_RETCODE retcode;
8361 
8362  assert(digraph != NULL);
8363  assert(compidx >= 0);
8364  assert(compidx < digraph->ncomponents);
8365  assert(strongcomponents != NULL);
8366  assert(strongcompstartidx != NULL);
8367  assert(nstrongcomponents != NULL);
8368 
8369  retcode = SCIP_OKAY;
8370 
8371  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&lowlink, digraph->nnodes), TERMINATE );
8372  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsidx, digraph->nnodes), TERMINATE );
8373  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stack, digraph->nnodes), TERMINATE );
8374  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&unprocessed, digraph->nnodes), TERMINATE );
8375  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&nodeinstack, digraph->nnodes), TERMINATE );
8376 
8377  for( i = 0; i < digraph->nnodes; ++i )
8378  {
8379  lowlink[i] = -1;
8380  dfsidx[i] = -1;
8381  stack[i] = -1;
8382  unprocessed[i] = TRUE;
8383  nodeinstack[i] = FALSE;
8384  }
8385 
8386  nstorednodes = 0;
8387  stacksize = 0;
8388  maxdfs = 0;
8389  *nstrongcomponents = 0;
8390 
8391  /* iterate over all nodes in the undirected connected component */
8392  for( i = digraph->componentstarts[compidx]; i < digraph->componentstarts[compidx + 1]; ++i )
8393  {
8394  int v;
8395 
8396  v = digraph->components[i];
8397  assert(v >= 0 && v < digraph->nnodes);
8398 
8399  /* call Tarjan's algorithm for unprocessed nodes */
8400  if( unprocessed[v] )
8401  {
8402  SCIPdebugMessage("apply Tarjan's algorithm for node %d\n", v);
8403  tarjan(digraph, v, lowlink, dfsidx, stack, &stacksize, unprocessed, nodeinstack, &maxdfs,
8404  strongcomponents, nstrongcomponents, strongcompstartidx, &nstorednodes);
8405  }
8406  }
8407 
8408  /* we should have stored as many nodes as in the undirected connected component */
8409  assert(nstorednodes == digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx]);
8410 
8411  /* to simplify the iteration over all strongly connected components */
8412  assert(*nstrongcomponents < digraph->nnodes + 1);
8413  strongcompstartidx[*nstrongcomponents] = nstorednodes;
8414 
8415  assert(retcode == SCIP_OKAY);
8416 
8417 TERMINATE:
8418  BMSfreeMemoryArrayNull(&lowlink);
8419  BMSfreeMemoryArrayNull(&dfsidx);
8420  BMSfreeMemoryArrayNull(&stack);
8421  BMSfreeMemoryArrayNull(&unprocessed);
8422  BMSfreeMemoryArrayNull(&nodeinstack);
8423 
8424  return retcode;
8425 }
8426 
8427 /** frees the component information for the given directed graph */
8429  SCIP_DIGRAPH* digraph /**< directed graph */
8430  )
8431 {
8432  BMS_BLKMEM* blkmem;
8433 
8434  assert(digraph != NULL);
8435  assert(digraph->blkmem != NULL);
8436 
8437  blkmem = digraph->blkmem;
8438 
8439  /* free components structure */
8440  if( digraph->componentstartsize > 0 )
8441  {
8442  BMSfreeBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize);
8443  BMSfreeBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes);
8444  digraph->components = NULL;
8445  digraph->componentstarts = NULL;
8446  digraph->ncomponents = 0;
8447  digraph->componentstartsize = 0;
8448  }
8449 #ifndef NDEBUG
8450  else
8451  {
8452  assert(digraph->components == NULL);
8453  assert(digraph->componentstarts == NULL);
8454  assert(digraph->ncomponents == 0);
8455  }
8456 #endif
8457 }
8458 
8459 /** output of the given directed graph via the given message handler */
8461  SCIP_DIGRAPH* digraph, /**< directed graph */
8462  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8463  FILE* file /**< output file (or NULL for standard output) */
8464  )
8465 {
8466  int n;
8467 
8468  for( n = 0; n < digraph->nnodes; ++n )
8469  {
8470  int* successors;
8471  int nsuccessors;
8472  int m;
8473 
8474  nsuccessors = digraph->nsuccessors[n];
8475  successors = digraph->successors[n];
8476 
8477  SCIPmessageFPrintInfo(messagehdlr, file, "node %d --> ", n);
8478 
8479  for( m = 0; m < nsuccessors ; ++m )
8480  {
8481  if( m == 0 )
8482  {
8483  SCIPmessageFPrintInfo(messagehdlr, file, "%d", successors[m]);
8484  }
8485  else
8486  {
8487  SCIPmessageFPrintInfo(messagehdlr, file, ", %d", successors[m]);
8488  }
8489  }
8490  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8491  }
8492 }
8493 
8494 /** prints the given directed graph structure in GML format into the given file */
8496  SCIP_DIGRAPH* digraph, /**< directed graph */
8497  FILE* file /**< file to write to */
8498  )
8499 {
8500  int n;
8501 
8502  /* write GML format opening */
8503  SCIPgmlWriteOpening(file, TRUE);
8504 
8505  /* write all nodes of the graph */
8506  for( n = 0; n < digraph->nnodes; ++n )
8507  {
8508  char label[SCIP_MAXSTRLEN];
8509 
8510  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", n);
8511  SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", NULL, NULL);
8512  }
8513 
8514  /* write all edges */
8515  for( n = 0; n < digraph->nnodes; ++n )
8516  {
8517  int* successors;
8518  int nsuccessors;
8519  int m;
8520 
8521  nsuccessors = digraph->nsuccessors[n];
8522  successors = digraph->successors[n];
8523 
8524  for( m = 0; m < nsuccessors; ++m )
8525  {
8526  SCIPgmlWriteArc(file, (unsigned int)n, (unsigned int)successors[m], NULL, NULL);
8527  }
8528  }
8529  /* write GML format closing */
8530  SCIPgmlWriteClosing(file);
8531 }
8532 
8533 /** output of the given directed graph via the given message handler */
8535  SCIP_DIGRAPH* digraph, /**< directed graph */
8536  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8537  FILE* file /**< output file (or NULL for standard output) */
8538  )
8539 {
8540  int c;
8541  int i;
8542 
8543  for( c = 0; c < digraph->ncomponents; ++c )
8544  {
8545  int start = digraph->componentstarts[c];
8546  int end = digraph->componentstarts[c+1];
8547 
8548  SCIPmessageFPrintInfo(messagehdlr, file, "Components %d --> ", c);
8549 
8550  for( i = start; i < end; ++i )
8551  {
8552  if( i == start )
8553  {
8554  SCIPmessageFPrintInfo(messagehdlr, file, "%d", digraph->components[i]);
8555  }
8556  else
8557  {
8558  SCIPmessageFPrintInfo(messagehdlr, file, ", %d", digraph->components[i]);
8559  }
8560  }
8561  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8562  }
8563 }
8564 
8565 /*
8566  * Binary tree
8567  */
8568 
8569 /** creates a node for a binary tree */
8570 static
8572  SCIP_BT* tree, /**< binary tree */
8573  SCIP_BTNODE** node /**< pointer to store the created node */
8574  )
8575 {
8576  SCIP_ALLOC( BMSallocBlockMemory(tree->blkmem, node) );
8577 
8578  (*node)->parent = NULL;
8579  (*node)->left = NULL;
8580  (*node)->right = NULL;
8581  (*node)->dataptr = NULL;
8582 
8583  return SCIP_OKAY;
8584 }
8585 
8586 /** creates a tree node with (optinal) user data */
8588  SCIP_BT* tree, /**< binary tree */
8589  SCIP_BTNODE** node, /**< pointer to store the created node */
8590  void* dataptr /**< user node data pointer, or NULL */
8591  )
8592 {
8593  assert(tree != NULL);
8594  assert(node != NULL);
8595 
8596  SCIP_CALL( btnodeCreateEmpty(tree, node) );
8597 
8598  assert((*node)->parent == NULL);
8599  assert((*node)->left == NULL);
8600  assert((*node)->right == NULL);
8601 
8602  /* initialize user data */
8603  (*node)->dataptr = dataptr;
8604 
8605  return SCIP_OKAY;
8606 }
8607 
8608 /** frees a tree leaf */
8609 static
8611  SCIP_BT* tree, /**< binary tree */
8612  SCIP_BTNODE** node /**< pointer to node which has to be freed */
8613  )
8614 {
8615  assert(tree != NULL);
8616  assert(node != NULL);
8617  assert(*node != NULL);
8618 
8619  assert((*node)->left == NULL);
8620  assert((*node)->right == NULL);
8621 
8622 #if 0
8623  /* remove reference from parent node */
8624  if( (*node)->parent != NULL )
8625  {
8626  assert(*node != NULL);
8627 
8628  assert((*node)->parent->left == *node || ((*node)->parent->right == *node));
8629 
8630  if( (*node)->parent->left == *node )
8631  {
8632  (*node)->parent->left = NULL;
8633  }
8634  else
8635  {
8636  assert((*node)->parent->right == *node);
8637  (*node)->parent->right = NULL;
8638  }
8639  }
8640 #endif
8641 
8642  assert(*node != NULL);
8643  BMSfreeBlockMemory(tree->blkmem, node);
8644  assert(*node == NULL);
8645 }
8646 
8647 /** frees the node including the rooted subtree
8648  *
8649  * @note The user pointer (object) is not freed. If needed, it has to be done by the user.
8650  */
8652  SCIP_BT* tree, /**< binary tree */
8653  SCIP_BTNODE** node /**< node to be freed */
8654  )
8655 {
8656  assert(tree != NULL);
8657  assert(node != NULL);
8658  assert(*node != NULL);
8659 
8660  if( (*node)->left != NULL )
8661  {
8662  SCIPbtnodeFree(tree, &(*node)->left);
8663  assert((*node)->left == NULL);
8664  }
8665 
8666  if( (*node)->right != NULL )
8667  {
8668  SCIPbtnodeFree(tree, &(*node)->right);
8669  assert((*node)->right == NULL);
8670  }
8671 
8672  btnodeFreeLeaf(tree, node);
8673  assert(*node == NULL);
8674 }
8675 
8676 /* some simple variable functions implemented as defines */
8677 
8678 /* In debug mode, the following methods are implemented as function calls to ensure
8679  * type validity.
8680  * In optimized mode, the methods are implemented as defines to improve performance.
8681  * However, we want to have them in the library anyways, so we have to undef the defines.
8682  */
8683 
8684 #undef SCIPbtnodeGetData
8685 #undef SCIPbtnodeGetKey
8686 #undef SCIPbtnodeGetParent
8687 #undef SCIPbtnodeGetLeftchild
8688 #undef SCIPbtnodeGetRightchild
8689 #undef SCIPbtnodeGetSibling
8690 #undef SCIPbtnodeIsRoot
8691 #undef SCIPbtnodeIsLeaf
8692 #undef SCIPbtnodeIsLeftchild
8693 #undef SCIPbtnodeIsRightchild
8694 
8695 /** returns the user data pointer stored in that node */
8697  SCIP_BTNODE* node /**< node */
8698  )
8699 {
8700  assert(node != NULL);
8701 
8702  return node->dataptr;
8703 }
8704 
8705 /** returns the parent which can be NULL if the given node is the root */
8707  SCIP_BTNODE* node /**< node */
8708  )
8709 {
8710  assert(node != NULL);
8711 
8712  return node->parent;
8713 }
8714 
8715 /** returns left child which can be NULL if the given node is a leaf */
8717  SCIP_BTNODE* node /**< node */
8718  )
8719 {
8720  assert(node != NULL);
8721 
8722  return node->left;
8723 }
8724 
8725 /** returns right child which can be NULL if the given node is a leaf */
8727  SCIP_BTNODE* node /**< node */
8728  )
8729 {
8730  assert(node != NULL);
8731 
8732  return node->right;
8733 }
8734 
8735 /** returns the sibling of the node or NULL if does not exist */
8737  SCIP_BTNODE* node /**< node */
8738  )
8739 {
8740  SCIP_BTNODE* parent;
8741 
8742  parent = SCIPbtnodeGetParent(node);
8743 
8744  if( parent == NULL )
8745  return NULL;
8746 
8747  if( SCIPbtnodeGetLeftchild(parent) == node )
8748  return SCIPbtnodeGetRightchild(parent);
8749 
8750  assert(SCIPbtnodeGetRightchild(parent) == node);
8751 
8752  return SCIPbtnodeGetLeftchild(parent);
8753 }
8754 
8755 /** returns whether the node is a root node */
8757  SCIP_BTNODE* node /**< node */
8758  )
8759 {
8760  assert(node != NULL);
8761 
8762  return (node->parent == NULL);
8763 }
8764 
8765 /** returns whether the node is a leaf */
8767  SCIP_BTNODE* node /**< node */
8768  )
8769 {
8770  assert(node != NULL);
8771 
8772  return (node->left == NULL && node->right == NULL);
8773 }
8774 
8775 /** returns TRUE if the given node is left child */
8777  SCIP_BTNODE* node /**< node */
8778  )
8779 {
8780  SCIP_BTNODE* parent;
8781 
8782  if( SCIPbtnodeIsRoot(node) )
8783  return FALSE;
8784 
8785  parent = SCIPbtnodeGetParent(node);
8786 
8787  if( SCIPbtnodeGetLeftchild(parent) == node )
8788  return TRUE;
8789 
8790  return FALSE;
8791 }
8792 
8793 /** returns TRUE if the given node is right child */
8795  SCIP_BTNODE* node /**< node */
8796  )
8797 {
8798  SCIP_BTNODE* parent;
8799 
8800  if( SCIPbtnodeIsRoot(node) )
8801  return FALSE;
8802 
8803  parent = SCIPbtnodeGetParent(node);
8804 
8805  if( SCIPbtnodeGetRightchild(parent) == node )
8806  return TRUE;
8807 
8808  return FALSE;
8809 }
8810 
8811 /** sets the give node data
8812  *
8813  * @note The old user pointer is not freed.
8814  */
8816  SCIP_BTNODE* node, /**< node */
8817  void* dataptr /**< node user data pointer */
8818  )
8819 {
8820  assert(node != NULL);
8821 
8822  node->dataptr = dataptr;
8823 }
8824 
8825 /** sets parent node
8826  *
8827  * @note The old parent including the rooted subtree is not delete.
8828  */
8830  SCIP_BTNODE* node, /**< node */
8831  SCIP_BTNODE* parent /**< new parent node, or NULL */
8832  )
8833 {
8834  assert(node != NULL);
8835 
8836  node->parent = parent;
8837 }
8838 
8839 /** sets left child
8840  *
8841  * @note The old left child including the rooted subtree is not delete.
8842  */
8844  SCIP_BTNODE* node, /**< node */
8845  SCIP_BTNODE* left /**< new left child, or NULL */
8846  )
8847 {
8848  assert(node != NULL);
8849 
8850  node->left = left;
8851 }
8852 
8853 /** sets right child
8854  *
8855  * @note The old right child including the rooted subtree is not delete.
8856  */
8858  SCIP_BTNODE* node, /**< node */
8859  SCIP_BTNODE* right /**< new right child, or NULL */
8860  )
8861 {
8862  assert(node != NULL);
8863 
8864  node->right = right;
8865 }
8866 
8867 /** creates an binary tree */
8869  SCIP_BT** tree, /**< pointer to store the created binary tree */
8870  BMS_BLKMEM* blkmem /**< block memory used to createnode */
8871  )
8872 {
8873  assert(tree != NULL);
8874  assert(blkmem != NULL);
8875 
8876  SCIP_ALLOC( BMSallocBlockMemory(blkmem, tree) );
8877  (*tree)->blkmem = blkmem;
8878  (*tree)->root = NULL;
8879 
8880  return SCIP_OKAY;
8881 }
8882 
8883 /** frees binary tree
8884  *
8885  * @note The user pointers (object) of the nodes are not freed. If needed, it has to be done by the user.
8886  */
8888  SCIP_BT** tree /**< pointer to binary tree */
8889  )
8890 {
8891  assert(tree != NULL);
8892 
8893  if( (*tree)->root != NULL )
8894  {
8895  SCIPbtnodeFree(*tree, &((*tree)->root));
8896  }
8897 
8898  BMSfreeBlockMemory((*tree)->blkmem, tree);
8899 }
8900 
8901 /** prints the rooted subtree of the given binary tree node in GML format into the given file */
8902 static
8904  SCIP_BTNODE* node, /**< binary tree node */
8905  FILE* file, /**< file to write to */
8906  int* nnodes /**< pointer to count the number of nodes */
8907  )
8908 {
8909  SCIP_BTNODE* left;
8910  SCIP_BTNODE* right;
8911  char label[SCIP_MAXSTRLEN];
8912 
8913  assert(node != NULL);
8914 
8915  (*nnodes)++;
8916  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", *nnodes);
8917 
8918  SCIPgmlWriteNode(file, (unsigned int)(size_t)node, label, "circle", NULL, NULL);
8919 
8920  left = SCIPbtnodeGetLeftchild(node);
8921  right = SCIPbtnodeGetRightchild(node);
8922 
8923  if( left != NULL )
8924  {
8925  btPrintSubtree(left, file, nnodes);
8926 
8927  SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)left, NULL, NULL);
8928  }
8929 
8930  if( right != NULL )
8931  {
8932  btPrintSubtree(right, file, nnodes);
8933 
8934  SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)right, NULL, NULL);
8935  }
8936 }
8937 
8938 /** prints the binary tree in GML format into the given file */
8940  SCIP_BT* tree, /**< binary tree */
8941  FILE* file /**< file to write to */
8942  )
8943 {
8944  /* write GML opening */
8945  SCIPgmlWriteOpening(file, TRUE);
8946 
8947  if( !SCIPbtIsEmpty(tree) )
8948  {
8949  SCIP_BTNODE* root;
8950  int nnodes;
8951 
8952  root = SCIPbtGetRoot(tree);
8953  assert(root != NULL);
8954 
8955  nnodes = 0;
8956 
8957  btPrintSubtree(root, file, &nnodes);
8958  }
8959 
8960  /* write GML closing */
8961  SCIPgmlWriteClosing(file);
8962 }
8963 
8964 /* some simple variable functions implemented as defines */
8965 #undef SCIPbtIsEmpty
8966 #undef SCIPbtGetRoot
8967 
8968 /** returns whether the binary tree is empty (has no nodes) */
8970  SCIP_BT* tree /**< binary tree */
8971  )
8972 {
8973  assert(tree != NULL);
8974 
8975  return (tree->root == NULL);
8976 }
8977 
8978 /** returns the the root node of the binary or NULL if the binary tree is empty */
8980  SCIP_BT* tree /**< tree to be evaluated */
8981  )
8982 {
8983  assert(tree != NULL);
8984 
8985  return tree->root;
8986 }
8987 
8988 /** sets root node
8989  *
8990  * @note The old root including the rooted subtree is not delete.
8991  */
8993  SCIP_BT* tree, /**< tree to be evaluated */
8994  SCIP_BTNODE* root /**< new root, or NULL */
8995  )
8996 {
8997  assert(tree != NULL);
8998 
8999  tree->root = root;
9000 }
9001 
9002 
9003 /*
9004  * Numerical methods
9005  */
9006 
9007 /** returns the machine epsilon: the smallest number eps > 0, for which 1.0 + eps > 1.0 */
9009  void
9010  )
9011 {
9012  SCIP_Real eps;
9013  SCIP_Real lasteps;
9014  SCIP_Real one;
9015  SCIP_Real onepluseps;
9016 
9017  one = 1.0;
9018  eps = 1.0;
9019  do
9020  {
9021  lasteps = eps;
9022  eps /= 2.0;
9023  onepluseps = one + eps;
9024  }
9025  while( onepluseps > one );
9026 
9027  return lasteps;
9028 }
9029 
9030 /** calculates the greatest common divisor of the two given values */
9032  SCIP_Longint val1, /**< first value of greatest common devisor calculation */
9033  SCIP_Longint val2 /**< second value of greatest common devisor calculation */
9034  )
9035 {
9036  int t;
9037 
9038  assert(val1 > 0);
9039  assert(val2 > 0);
9040 
9041  t = 0;
9042  /* if val1 is even, divide it by 2 */
9043  while( !(val1 & 1) )
9044  {
9045  val1 >>= 1; /*lint !e704*/
9046 
9047  /* if val2 is even too, divide it by 2 and increase t(=number of e) */
9048  if( !(val2 & 1) )
9049  {
9050  val2 >>= 1; /*lint !e704*/
9051  ++t;
9052  }
9053  /* only val1 can be odd */
9054  else
9055  {
9056  /* while val1 is even, divide it by 2 */
9057  while( !(val1 & 1) )
9058  val1 >>= 1; /*lint !e704*/
9059 
9060  break;
9061  }
9062  }
9063 
9064  /* while val2 is even, divide it by 2 */
9065  while( !(val2 & 1) )
9066  val2 >>= 1; /*lint !e704*/
9067 
9068  /* the following if/else condition is only to make sure that we do not overflow when adding up both values before
9069  * dividing them by 4 in the following while loop
9070  */
9071  if( t == 0 )
9072  {
9073  if( val1 > val2 )
9074  {
9075  val1 -= val2;
9076 
9077  /* divide val1 by 2 as long as possible */
9078  while( !(val1 & 1) )
9079  val1 >>= 1; /*lint !e704*/
9080  }
9081  else if( val1 < val2 )
9082  {
9083  val2 -= val1;
9084 
9085  /* divide val2 by 2 as long as possible */
9086  while( !(val2 & 1) )
9087  val2 >>= 1; /*lint !e704*/
9088  }
9089  }
9090 
9091  /* val1 and val2 are odd */
9092  while( val1 != val2 )
9093  {
9094  if( val1 > val2 )
9095  {
9096  /* we can stop if one value reached one */
9097  if( val2 == 1 )
9098  return (val2 << t); /*lint !e647 !e703*/
9099 
9100  /* if ((val1 xor val2) and 2) = 2, then gcd(val1, val2) = gcd((val1 + val2)/4, val2),
9101  * and otherwise gcd(val1, val2) = gcd((val1 − val2)/4, val2)
9102  */
9103  if( ((val1 ^ val2) & 2) == 2 )
9104  val1 += val2;
9105  else
9106  val1 -= val2;
9107 
9108  assert((val1 & 3) == 0);
9109  val1 >>= 2; /*lint !e704*/
9110 
9111  /* if val1 is still even, divide it by 2 */
9112  while( !(val1 & 1) )
9113  val1 >>= 1; /*lint !e704*/
9114  }
9115  else
9116  {
9117  /* we can stop if one value reached one */
9118  if( val1 == 1 )
9119  return (val1 << t); /*lint !e647 !e703*/
9120 
9121  /* if ((val2 xor val1) and 2) = 2, then gcd(val2, val1) = gcd((val2 + val1)/4, val1),
9122  * and otherwise gcd(val2, val1) = gcd((val2 − val1)/4, val1)
9123  */
9124  if( ((val2 ^ val1) & 2) == 2 )
9125  val2 += val1;
9126  else
9127  val2 -= val1;
9128 
9129  assert((val2 & 3) == 0);
9130  val2 >>= 2; /*lint !e704*/
9131 
9132  /* if val2 is still even, divide it by 2 */
9133  while( !(val2 & 1) )
9134  val2 >>= 1; /*lint !e704*/
9135  }
9136  }
9137 
9138  return (val1 << t); /*lint !e703*/
9139 }
9140 
9141 
9142 /* for the MS compiler, the function nextafter is named _nextafter */
9143 #if defined(_MSC_VER) && !defined(NO_NEXTAFTER)
9144 #define nextafter(x,y) _nextafter(x,y)
9145 #endif
9146 
9147 /* on systems where the function nextafter is not defined, we provide an implementation from Sun */
9148 #ifdef NO_NEXTAFTER
9149 /* The following implementation of the routine nextafter() comes with the following license:
9150  *
9151  * ====================================================
9152  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9153  *
9154  * Developed at SunSoft, a Sun Microsystems, Inc. business.
9155  * Permission to use, copy, modify, and distribute this
9156  * software is freely granted, provided that this notice
9157  * is preserved.
9158  * ====================================================
9159  */
9160 
9161 #define __HI(x) *(1+(int*)&x)
9162 #define __LO(x) *(int*)&x
9163 #define __HIp(x) *(1+(int*)x)
9164 #define __LOp(x) *(int*)x
9165 
9166 static
9167 double nextafter(double x, double y)
9168 {
9169  int hx;
9170  int hy;
9171  int ix;
9172  int iy;
9173  unsigned lx;
9174  unsigned ly;
9175 
9176  /* cppcheck-suppress invalidPointerCast */
9177  hx = __HI(x); /* high word of x */
9178  /* cppcheck-suppress invalidPointerCast */
9179  lx = __LO(x); /* low word of x */
9180  /* cppcheck-suppress invalidPointerCast */
9181  hy = __HI(y); /* high word of y */
9182  /* cppcheck-suppress invalidPointerCast */
9183  ly = __LO(y); /* low word of y */
9184  ix = hx&0x7fffffff; /* |x| */
9185  iy = hy&0x7fffffff; /* |y| */
9186 
9187  if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) || /* x is nan */
9188  ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 )) /* y is nan */
9189  return x + y;
9190 
9191  /* x == y, return x */
9192  if( x == y )
9193  return x;
9194 
9195  /* x == 0 */
9196  if( (ix|lx) == 0 )
9197  {
9198  /* return +-minsubnormal */
9199  /* cppcheck-suppress invalidPointerCast */
9200  __HI(x) = hy&0x80000000;
9201  /* cppcheck-suppress invalidPointerCast */
9202  __LO(x) = 1;
9203  y = x * x;
9204  if ( y == x )
9205  return y;
9206  else
9207  return x; /* raise underflow flag */
9208  }
9209  /* x > 0 */
9210  if( hx >= 0 )
9211  {
9212  /* x > y, x -= ulp */
9213  if( hx > hy || ((hx == hy) && (lx > ly)) )
9214  {
9215  if ( lx == 0 )
9216  hx -= 1;
9217  lx -= 1;
9218  }
9219  else
9220  {
9221  /* x < y, x += ulp */
9222  lx += 1;
9223  if ( lx == 0 )
9224  hx += 1;
9225  }
9226  }
9227  else
9228  {
9229  /* x < 0 */
9230  if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
9231  {
9232  /* x < y, x -= ulp */
9233  if ( lx == 0 )
9234  hx -= 1;
9235  lx -= 1;
9236  }
9237  else
9238  {
9239  /* x > y, x += ulp */
9240  lx += 1;
9241  if( lx == 0 )
9242  hx += 1;
9243  }
9244  }
9245  hy = hx&0x7ff00000;
9246  /* overflow */
9247  if( hy >= 0x7ff00000 )
9248  return x + x;
9249  if( hy < 0x00100000 )
9250  {
9251  /* underflow */
9252  y = x*x;
9253  if( y != x )
9254  {
9255  /* raise underflow flag */
9256  /* cppcheck-suppress invalidPointerCast */
9257  __HI(y) = hx;
9258  /* cppcheck-suppress invalidPointerCast */
9259  __LO(y) = lx;
9260  return y;
9261  }
9262  }
9263 
9264  /* cppcheck-suppress invalidPointerCast */
9265  __HI(x) = hx;
9266  /* cppcheck-suppress invalidPointerCast */
9267  __LO(x) = lx;
9268  return x;
9269 }
9270 #endif
9271 
9272 
9273 /** returns the next representable value of from in the direction of to */
9275  SCIP_Real from, /**< value from which the next representable value should be returned */
9276  SCIP_Real to /**< direction in which the next representable value should be returned */
9277  )
9278 {
9279  return nextafter(from, to);
9280 }
9281 
9282 /** calculates the smallest common multiple of the two given values */
9284  SCIP_Longint val1, /**< first value of smallest common multiple calculation */
9285  SCIP_Longint val2 /**< second value of smallest common multiple calculation */
9286  )
9287 {
9288  SCIP_Longint gcd;
9289 
9290  assert(val1 > 0);
9291  assert(val2 > 0);
9292 
9293  gcd = SCIPcalcGreComDiv(val1, val2);
9294 
9295  return val1/gcd * val2;
9296 }
9297 
9298 static const SCIP_Real simplednoms[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0,
9299  17.0, 18.0, 19.0, 25.0, -1.0};
9300 
9301 /** converts a real number into a (approximate) rational representation, and returns TRUE iff the conversion was
9302  * successful
9303  */
9305  SCIP_Real val, /**< real value r to convert into rational number */
9306  SCIP_Real mindelta, /**< minimal allowed difference r - q of real r and rational q = n/d */
9307  SCIP_Real maxdelta, /**< maximal allowed difference r - q of real r and rational q = n/d */
9308  SCIP_Longint maxdnom, /**< maximal denominator allowed */
9309  SCIP_Longint* nominator, /**< pointer to store the nominator n of the rational number */
9310  SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9311  )
9312 {
9313  SCIP_Real a;
9314  SCIP_Real b;
9315  SCIP_Real g0;
9316  SCIP_Real g1;
9317  SCIP_Real gx;
9318  SCIP_Real h0;
9319  SCIP_Real h1;
9320  SCIP_Real hx;
9321  SCIP_Real delta0;
9322  SCIP_Real delta1;
9323  SCIP_Real epsilon;
9324  int i;
9325 
9326  assert(mindelta < 0.0);
9327  assert(maxdelta > 0.0);
9328  assert(nominator != NULL);
9329  assert(denominator != NULL);
9330 
9331  if( REALABS(val) >= ((SCIP_Real)SCIP_LONGINT_MAX) / maxdnom )
9332  return FALSE;
9333 
9334  /* try the simple denominators first: each value of the simpledenoms table multiplied by powers of 10
9335  * is tried as denominator
9336  */
9337  for( i = 0; simplednoms[i] > 0.0; ++i )
9338  {
9339  SCIP_Real nom;
9340  SCIP_Real dnom;
9341  SCIP_Real ratval0;
9342  SCIP_Real ratval1;
9343 
9344  /* try powers of 10 (including 10^0) */
9345  dnom = simplednoms[i];
9346  while( dnom <= maxdnom )
9347  {
9348  nom = floor(val * dnom);
9349  ratval0 = nom/dnom;
9350  ratval1 = (nom+1.0)/dnom;
9351  if( mindelta <= val - ratval0 && val - ratval1 <= maxdelta )
9352  {
9353  if( val - ratval0 <= maxdelta )
9354  {
9355  *nominator = (SCIP_Longint)nom;
9356  *denominator = (SCIP_Longint)dnom;
9357  return TRUE;
9358  }
9359  if( mindelta <= val - ratval1 )
9360  {
9361  *nominator = (SCIP_Longint)(nom+1.0);
9362  *denominator = (SCIP_Longint)dnom;
9363  return TRUE;
9364  }
9365  }
9366  dnom *= 10.0;
9367  }
9368  }
9369 
9370  /* the simple denominators didn't work: calculate rational representation with arbitrary denominator */
9371  epsilon = MIN(-mindelta, maxdelta)/2.0;
9372 
9373  b = val;
9374  a = EPSFLOOR(b, epsilon);
9375  g0 = a;
9376  h0 = 1.0;
9377  g1 = 1.0;
9378  h1 = 0.0;
9379  delta0 = val - g0/h0;
9380  delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9381 
9382  while( (delta0 < mindelta || delta0 > maxdelta) && (delta1 < mindelta || delta1 > maxdelta) )
9383  {
9384  assert(EPSGT(b, a, epsilon));
9385  assert(h0 >= 0.0);
9386  assert(h1 >= 0.0);
9387 
9388  b = 1.0 / (b - a);
9389  a = EPSFLOOR(b, epsilon);
9390 
9391  assert(a >= 0.0);
9392  gx = g0;
9393  hx = h0;
9394 
9395  g0 = a * g0 + g1;
9396  h0 = a * h0 + h1;
9397 
9398  g1 = gx;
9399  h1 = hx;
9400 
9401  if( h0 > maxdnom )
9402  return FALSE;
9403 
9404  delta0 = val - g0/h0;
9405  delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9406  }
9407 
9408  if( REALABS(g0) > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) || h0 > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) )
9409  return FALSE;
9410 
9411  assert(h0 > 0.5);
9412 
9413  if( delta0 < mindelta )
9414  {
9415  assert(mindelta <= delta1 && delta1 <= maxdelta);
9416  *nominator = (SCIP_Longint)(g0 - 1.0);
9417  *denominator = (SCIP_Longint)h0;
9418  }
9419  else if( delta0 > maxdelta )
9420  {
9421  assert(mindelta <= delta1 && delta1 <= maxdelta);
9422  *nominator = (SCIP_Longint)(g0 + 1.0);
9423  *denominator = (SCIP_Longint)h0;
9424  }
9425  else
9426  {
9427  *nominator = (SCIP_Longint)g0;
9428  *denominator = (SCIP_Longint)h0;
9429  }
9430  assert(*denominator >= 1);
9431  assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) >= mindelta);
9432  assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) <= maxdelta);
9433 
9434  return TRUE;
9435 }
9436 
9437 /** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
9438 static
9440  SCIP_Real val, /**< value that should be scaled to an integral value */
9441  SCIP_Real scalar, /**< scalar that should be tried */
9442  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9443  SCIP_Real maxdelta /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9444  )
9445 {
9446  SCIP_Real sval;
9447  SCIP_Real downval;
9448  SCIP_Real upval;
9449 
9450  assert(mindelta <= 0.0);
9451  assert(maxdelta >= 0.0);
9452 
9453  sval = val * scalar;
9454  downval = floor(sval);
9455  upval = ceil(sval);
9456 
9457  return (SCIPrelDiff(sval, downval) <= maxdelta || SCIPrelDiff(sval, upval) >= mindelta);
9458 }
9459 
9460 /** additional scalars that are tried in integrality scaling */
9461 static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
9462 static const int nscalars = 9;
9463 
9464 /** tries to find a value, such that all given values, if scaled with this value become integral in relative allowed
9465  * difference in between mindelta and maxdelta
9466  */
9468  SCIP_Real* vals, /**< values to scale */
9469  int nvals, /**< number of values to scale */
9470  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9471  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9472  SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
9473  SCIP_Real maxscale, /**< maximal allowed scalar */
9474  SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
9475  SCIP_Bool* success /**< stores whether returned value is valid */
9476  )
9477 {
9478  SCIP_Real bestscalar;
9479  SCIP_Longint gcd;
9480  SCIP_Longint scm;
9481  SCIP_Longint nominator;
9482  SCIP_Longint denominator;
9483  SCIP_Real val;
9484  SCIP_Real minval;
9485  SCIP_Real absval;
9486  SCIP_Real scaleval;
9487  SCIP_Bool scalable;
9488  SCIP_Bool rational;
9489  int c;
9490  int s;
9491  int i;
9492 
9493  assert(vals != NULL);
9494  assert(nvals >= 0);
9495  assert(maxdnom >= 1);
9496  assert(mindelta < 0.0);
9497  assert(maxdelta > 0.0);
9498  assert(success != NULL);
9499 
9500  SCIPdebugMessage("trying to find rational representation for given values\n");
9501 
9502  if( intscalar != NULL )
9503  *intscalar = SCIP_INVALID;
9504  *success = FALSE;
9505 
9506  /* get minimal absolute non-zero value */
9507  minval = SCIP_REAL_MAX;
9508  for( c = 0; c < nvals; ++c )
9509  {
9510  val = vals[c];
9511  if( val < mindelta || val > maxdelta )
9512  {
9513  absval = REALABS(val);
9514  minval = MIN(minval, absval);
9515  }
9516  }
9517 
9518  if( minval == SCIP_REAL_MAX ) /*lint !e777*/
9519  {
9520  /* all coefficients are zero (inside tolerances) */
9521  if( intscalar != NULL )
9522  *intscalar = 1.0;
9523  *success = TRUE;
9524  SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
9525 
9526  return SCIP_OKAY;
9527  }
9528  assert(minval > MIN(-mindelta, maxdelta));
9529 
9530  bestscalar = SCIP_INVALID;
9531 
9532  for( i = 0; i < 2; ++i )
9533  {
9534  scalable = TRUE;
9535 
9536  /* try, if values can be made integral multiplying them with the reciprocal of the smallest value and a power of 2 */
9537  if( i == 0 )
9538  scaleval = 1.0/minval;
9539  /* try, if values can be made integral by multiplying them by a power of 2 */
9540  else
9541  scaleval = 1.0;
9542 
9543  for( c = 0; c < nvals && scalable; ++c )
9544  {
9545  /* check, if the value can be scaled with a simple scalar */
9546  val = vals[c];
9547  if( val == 0.0 ) /* zeros are allowed in the vals array */
9548  continue;
9549 
9550  absval = REALABS(val);
9551  while( scaleval <= maxscale
9552  && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta)) )
9553  {
9554  for( s = 0; s < nscalars; ++s )
9555  {
9556  if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta) )
9557  {
9558  scaleval *= scalars[s];
9559  break;
9560  }
9561  }
9562  if( s >= nscalars )
9563  scaleval *= 2.0;
9564  }
9565  scalable = (scaleval <= maxscale);
9566  SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
9567  val, scaleval, val*scaleval, scalable);
9568  }
9569  if( scalable )
9570  {
9571  /* make values integral by dividing them by the smallest value (and multiplying them with a power of 2) */
9572  assert(scaleval <= maxscale);
9573 
9574  /* check if we found a better scaling value */
9575  if( scaleval < bestscalar )
9576  bestscalar = scaleval;
9577 
9578  SCIPdebugMessage(" -> integrality could be achieved by scaling with %g\n", scaleval);
9579 
9580  /* if the scalar is still the reciprocal of the minimal value, all coeffcients are the same and we do not get a better scalar */
9581  if( i == 0 && EPSEQ(scaleval, 1.0/minval, SCIP_DEFAULT_EPSILON) )
9582  {
9583  if( intscalar != NULL )
9584  *intscalar = bestscalar;
9585  *success = TRUE;
9586 
9587  return SCIP_OKAY;
9588  }
9589  }
9590  }
9591 
9592  /* convert each value into a rational number, calculate the greatest common divisor of the nominators
9593  * and the smallest common multiple of the denominators
9594  */
9595  gcd = 1;
9596  scm = 1;
9597  rational = TRUE;
9598 
9599  /* first value (to initialize gcd) */
9600  for( c = 0; c < nvals && rational; ++c )
9601  {
9602  val = vals[c];
9603  if( val == 0.0 ) /* zeros are allowed in the vals array */
9604  continue;
9605 
9606  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9607  if( rational && nominator != 0 )
9608  {
9609  assert(denominator > 0);
9610  gcd = ABS(nominator);
9611  scm = denominator;
9612  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9613  SCIPdebugMessage(" -> c=%d first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9614  c, val, nominator, denominator, gcd, scm, rational);
9615  break;
9616  }
9617  }
9618 
9619  /* remaining values */
9620  for( ++c; c < nvals && rational; ++c )
9621  {
9622  val = vals[c];
9623  if( val == 0.0 ) /* zeros are allowed in the vals array */
9624  continue;
9625 
9626  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9627  if( rational && nominator != 0 )
9628  {
9629  assert(denominator > 0);
9630  gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
9631  scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
9632  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9633  SCIPdebugMessage(" -> c=%d next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9634  c, val, nominator, denominator, gcd, scm, rational);
9635  }
9636  else
9637  {
9638  SCIPdebugMessage(" -> failed to convert %g into a rational representation\n", val);
9639  }
9640  }
9641 
9642  if( rational )
9643  {
9644  /* make values integral by multiplying them with the smallest common multiple of the denominators */
9645  assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9646 
9647  /* check if we found a better scaling value */
9648  if( (SCIP_Real)scm/(SCIP_Real)gcd < bestscalar )
9649  bestscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
9650 
9651  SCIPdebugMessage(" -> integrality could be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
9652  (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
9653  }
9654 
9655  if( bestscalar < SCIP_INVALID )
9656  {
9657  if( intscalar != NULL )
9658  *intscalar = bestscalar;
9659  *success = TRUE;
9660 
9661  SCIPdebugMessage(" -> smallest value to achieve integrality is %g \n", bestscalar);
9662  }
9663 
9664  return SCIP_OKAY;
9665 }
9666 
9667 /* Inform compiler that this code accesses the floating-point environment, so that
9668  * certain optimizations should be omitted (http://www.cplusplus.com/reference/cfenv/FENV_ACCESS/).
9669  * Not supported by Clang (gives warning) and GCC (silently), at the moment.
9670  */
9671 #if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9672 #pragma fenv_access (on)
9673 #elif defined __GNUC__
9674 #pragma STDC FENV_ACCESS ON
9675 #endif
9676 
9677 /** given a (usually very small) interval, tries to find a rational number with simple denominator (i.e. a small
9678  * number, probably multiplied with powers of 10) out of this interval; returns TRUE iff a valid rational
9679  * number inside the interval was found
9680  */
9682  SCIP_Real lb, /**< lower bound of the interval */
9683  SCIP_Real ub, /**< upper bound of the interval */
9684  SCIP_Longint maxdnom, /**< maximal denominator allowed for resulting rational number */
9685  SCIP_Longint* nominator, /**< pointer to store the nominator n of the rational number */
9686  SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9687  )
9688 {
9689  SCIP_Real center;
9690  SCIP_Real delta;
9691 
9692  assert(lb <= ub);
9693 
9694  center = 0.5*(lb+ub);
9695 
9696  /* in order to compute a rational number that is exactly within the bounds (as the user expects),
9697  * we computed the allowed delta with downward rounding, if available
9698  */
9700  {
9701  SCIP_ROUNDMODE roundmode;
9702 
9703  roundmode = SCIPintervalGetRoundingMode();
9705 
9706  delta = 0.5*(ub-lb);
9707 
9708  SCIPintervalSetRoundingMode(roundmode);
9709  }
9710  else
9711  {
9712  delta = 0.5*(ub-lb);
9713  }
9714 
9715  return SCIPrealToRational(center, -delta, +delta, maxdnom, nominator, denominator);
9716 }
9717 
9718 #if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9719 #pragma fenv_access (off)
9720 #elif defined __GNUC__
9721 #pragma STDC FENV_ACCESS OFF
9722 #endif
9723 
9724 /** given a (usually very small) interval, selects a value inside this interval; it is tried to select a rational number
9725  * with simple denominator (i.e. a small number, probably multiplied with powers of 10);
9726  * if no valid rational number inside the interval was found, selects the central value of the interval
9727  */
9729  SCIP_Real lb, /**< lower bound of the interval */
9730  SCIP_Real ub, /**< upper bound of the interval */
9731  SCIP_Longint maxdnom /**< maximal denominator allowed for resulting rational number */
9732  )
9733 {
9734  SCIP_Real val;
9735 
9736  val = 0.5*(lb+ub);
9737  if( lb < ub )
9738  {
9739  SCIP_Longint nominator;
9740  SCIP_Longint denominator;
9741  SCIP_Bool success;
9742 
9743  /* try to find a "simple" rational number inside the interval */
9744  SCIPdebugMessage("simple rational in [%.9f,%.9f]:", lb, ub);
9745  success = SCIPfindSimpleRational(lb, ub, maxdnom, &nominator, &denominator);
9746  if( success )
9747  {
9748  val = (SCIP_Real)nominator/(SCIP_Real)denominator;
9749  SCIPdebugPrintf(" %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT " == %.9f\n", nominator, denominator, val);
9750 
9751  if( val - lb < 0.0 || val - ub > 0.0 )
9752  {
9753  SCIPdebugPrintf(" value is out of interval bounds by %g -> failed\n", MAX(lb-val, val-ub));
9754  val = 0.5*(lb+ub);
9755  }
9756  }
9757  else
9758  {
9759  SCIPdebugPrintf(" failed\n");
9760  }
9761  }
9762 
9763  return val;
9764 }
9765 
9766 /** Performs the Newton Procedure from a given starting point to compute a root of the given function with
9767  * specified precision and maximum number of iterations. If the procedure fails, SCIP_INVALID is returned.
9768  */
9770  SCIP_DECL_NEWTONEVAL((*function)), /**< pointer to function for which roots are computed */
9771  SCIP_DECL_NEWTONEVAL((*derivative)), /**< pointer to derivative of above function */
9772  SCIP_Real* params, /**< parameters needed for function (can be NULL) */
9773  int nparams, /**< number of parameters (can be 0) */
9774  SCIP_Real x, /**< starting point */
9775  SCIP_Real eps, /**< tolerance */
9776  int k /**< iteration limit */
9777  )
9778 {
9779  SCIP_Real result = x;
9780  int iteration = 0;
9781 
9782  assert(function != NULL);
9783  assert(derivative != NULL);
9784  assert(params != NULL || nparams == 0);
9785  assert(eps > 0.0);
9786  assert(k >= 0);
9787  assert(x != SCIP_INVALID); /*lint !e777*/
9788 
9789  while( iteration < k )
9790  {
9791  SCIP_Real deriv = derivative(result, params, nparams);
9792 
9793  /* if we arrive at a stationary point, the procedure is aborted */
9794  if( REALABS(deriv) <= eps || deriv == SCIP_INVALID ) /*lint !e777*/
9795  return SCIP_INVALID;
9796 
9797  result = result - function(result, params, nparams) / deriv;
9798 
9799  /* if new point is within eps-range of 0, we are done */
9800  if( REALABS(function(result, params, nparams)) <= eps )
9801  break;
9802 
9803  ++iteration;
9804  }
9805 
9806  if( k == iteration )
9807  return SCIP_INVALID;
9808  else
9809  return result;
9810 }
9811 
9812 
9813 /*
9814  * Random Numbers
9815  */
9816 
9817 #if defined(NO_RAND_R) || defined(_WIN32) || defined(_WIN64)
9818 
9819 #define SCIP_RAND_MAX 32767
9820 /** returns a random number between 0 and SCIP_RAND_MAX */
9821 static
9822 int getRand(
9823  unsigned int* seedp /**< pointer to seed value */
9824  )
9825 {
9826  SCIP_Longint nextseed;
9827 
9828  assert(seedp != NULL);
9829 
9830  nextseed = (*seedp) * (SCIP_Longint)1103515245 + 12345;
9831  *seedp = (unsigned int)nextseed;
9832 
9833  return (int)((unsigned int)(nextseed/(2*(SCIP_RAND_MAX+1))) % (SCIP_RAND_MAX+1));
9834 }
9835 
9836 #else
9837 
9838 #define SCIP_RAND_MAX RAND_MAX
9839 
9840 /** returns a random number between 0 and SCIP_RAND_MAX */
9841 static
9843  unsigned int* seedp /**< pointer to seed value */
9844  )
9845 {
9846  return rand_r(seedp);
9847 }
9848 
9849 #endif
9850 
9851 /** returns a random integer between minrandval and maxrandval */
9852 static
9854  int minrandval, /**< minimal value to return */
9855  int maxrandval, /**< maximal value to return */
9856  unsigned int* seedp /**< pointer to seed value */
9857  )
9858 {
9859  SCIP_Real randnumber;
9860 
9861  randnumber = (SCIP_Real)getRand(seedp)/(SCIP_RAND_MAX+1.0);
9862  assert(randnumber >= 0.0);
9863  assert(randnumber < 1.0);
9864 
9865  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than INT_MAX
9866  * apart
9867  */
9868  return (int) (minrandval*(1.0 - randnumber) + maxrandval*randnumber + randnumber);
9869 }
9870 
9871 /** returns a random real between minrandval and maxrandval */
9872 static
9874  SCIP_Real minrandval, /**< minimal value to return */
9875  SCIP_Real maxrandval, /**< maximal value to return */
9876  unsigned int* seedp /**< pointer to seed value */
9877  )
9878 {
9879  SCIP_Real randnumber;
9880 
9881  randnumber = (SCIP_Real)getRand(seedp)/(SCIP_Real)SCIP_RAND_MAX;
9882  assert(randnumber >= 0.0);
9883  assert(randnumber <= 1.0);
9884 
9885  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
9886  * SCIP_REAL_MAX apart
9887  */
9888  return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
9889 }
9890 
9891 /** returns a random integer between minrandval and maxrandval
9892  *
9893  * @deprecated Please use SCIPrandomGetInt() to request a random integer.
9894  */
9896  int minrandval, /**< minimal value to return */
9897  int maxrandval, /**< maximal value to return */
9898  unsigned int* seedp /**< pointer to seed value */
9899  )
9900 {
9901  return getRandomInt(minrandval, maxrandval, seedp);
9902 }
9903 
9904 /** returns a random real between minrandval and maxrandval
9905  *
9906  * @deprecated Please use SCIPrandomGetReal() to request a random real.
9907  */
9909  SCIP_Real minrandval, /**< minimal value to return */
9910  SCIP_Real maxrandval, /**< maximal value to return */
9911  unsigned int* seedp /**< pointer to seed value */
9912  )
9913 {
9914  return getRandomReal(minrandval, maxrandval, seedp);
9915 }
9916 
9917 
9918 /* initial seeds for KISS random number generator */
9919 #define DEFAULT_SEED UINT32_C(123456789)
9920 #define DEFAULT_XOR UINT32_C(362436000)
9921 #define DEFAULT_MWC UINT32_C(521288629)
9922 #define DEFAULT_CST UINT32_C(7654321)
9923 
9924 
9925 /** initializes a random number generator with a given start seed */
9927  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
9928  unsigned int initseed /**< initial random seed */
9929  )
9930 {
9931  assert(randnumgen != NULL);
9932 
9933  /* use MAX() to avoid zero after over flowing */
9934  randnumgen->seed = MAX(SCIPhashTwo(DEFAULT_SEED, initseed), 1u);
9935  randnumgen->xor_seed = MAX(SCIPhashTwo(DEFAULT_XOR, initseed), 1u);
9936  randnumgen->mwc_seed = MAX(SCIPhashTwo(DEFAULT_MWC, initseed), 1u);
9937  randnumgen->cst_seed = SCIPhashTwo(DEFAULT_CST, initseed);
9938 
9939  assert(randnumgen->seed > 0);
9940  assert(randnumgen->xor_seed > 0);
9941  assert(randnumgen->mwc_seed > 0);
9942 }
9943 
9944 /** returns a random number between 0 and UINT32_MAX
9945  *
9946  * implementation of KISS random number generator developed by George Marsaglia.
9947  * KISS is combination of three different random number generators:
9948  * - Linear congruential generator
9949  * - Xorshift
9950  * - Lag-1 Multiply-with-carry
9951  *
9952  * KISS has a period of 2^123 and passes all statistical test part of BigCrush-Test of TestU01 [1].
9953  *
9954  * [1] http://dl.acm.org/citation.cfm?doid=1268776.1268777
9955  */
9956 static
9957 uint32_t randomGetRand(
9958  SCIP_RANDNUMGEN* randnumgen /**< random number generator */
9959  )
9960 {
9961  uint64_t t;
9962 
9963  /* linear congruential */
9964  randnumgen->seed = (uint32_t) (randnumgen->seed * UINT64_C(1103515245) + UINT64_C(12345));
9965 
9966  /* Xorshift */
9967  randnumgen->xor_seed ^= (randnumgen->xor_seed << 13);
9968  randnumgen->xor_seed ^= (randnumgen->xor_seed >> 17);
9969  randnumgen->xor_seed ^= (randnumgen->xor_seed << 5);
9970 
9971  /* Multiply-with-carry */
9972  t = UINT64_C(698769069) * randnumgen->mwc_seed + randnumgen->cst_seed;
9973  randnumgen->cst_seed = (uint32_t) (t >> 32);
9974  randnumgen->mwc_seed = (uint32_t) t;
9975 
9976  return randnumgen->seed + randnumgen->xor_seed + randnumgen->mwc_seed;
9977 }
9978 
9979 /** creates and initializes a random number generator */
9981  SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
9982  BMS_BLKMEM* blkmem, /**< block memory */
9983  unsigned int initialseed /**< initial random seed */
9984  )
9985 {
9986  assert(randnumgen != NULL);
9987 
9988  SCIP_ALLOC( BMSallocBlockMemory(blkmem, randnumgen) );
9989 
9990  SCIPrandomSetSeed((*randnumgen), initialseed);
9991 
9992  return SCIP_OKAY;
9993 }
9994 
9995 /** frees a random number generator */
9997  SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
9998  BMS_BLKMEM* blkmem /**< block memory */
9999  )
10000 {
10001  assert(randnumgen != NULL);
10002  assert((*randnumgen) != NULL);
10003 
10004  BMSfreeBlockMemory(blkmem, randnumgen);
10005 
10006  return;
10007 }
10008 
10009 
10010 
10011 /** returns a random integer between minrandval and maxrandval */
10013  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10014  int minrandval, /**< minimal value to return */
10015  int maxrandval /**< maximal value to return */
10016  )
10017 {
10018  SCIP_Real randnumber;
10019  SCIP_Longint zeromax;
10020 
10021  randnumber = (SCIP_Real)randomGetRand(randnumgen)/(UINT32_MAX+1.0);
10022  assert(randnumber >= 0.0);
10023  assert(randnumber < 1.0);
10024 
10025  /* we need to shift the range to the non-negative integers to handle negative integer values correctly.
10026  * we use a long integer to avoid overflows.
10027  */
10028  zeromax = (SCIP_Longint)maxrandval - (SCIP_Longint)minrandval + 1;
10029 
10030  return (int) ((SCIP_Longint)(zeromax * randnumber) + (SCIP_Longint)minrandval);
10031 }
10032 
10033 /** returns a random real between minrandval and maxrandval */
10035  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10036  SCIP_Real minrandval, /**< minimal value to return */
10037  SCIP_Real maxrandval /**< maximal value to return */
10038  )
10039 {
10040  SCIP_Real randnumber;
10041 
10042  randnumber = (SCIP_Real)randomGetRand(randnumgen)/(SCIP_Real)UINT32_MAX;
10043  assert(randnumber >= 0.0);
10044  assert(randnumber <= 1.0);
10045 
10046  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
10047  * SCIP_REAL_MAX apart
10048  */
10049  return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
10050 }
10051 
10052 /** randomly shuffles parts of an integer array using the Fisher-Yates algorithm */
10054  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10055  int* array, /**< array to be shuffled */
10056  int begin, /**< first included index that should be subject to shuffling
10057  * (0 for first array entry)
10058  */
10059  int end /**< first excluded index that should not be subject to shuffling
10060  * (array size for last array entry)
10061  */
10062  )
10063 {
10064  int tmp;
10065  int i;
10066 
10067  /* loop backwards through all elements and always swap the current last element to a random position */
10068  while( end > begin+1 )
10069  {
10070  --end;
10071 
10072  /* get a random position into which the last entry should be shuffled */
10073  i = SCIPrandomGetInt(randnumgen, begin, end);
10074 
10075  /* swap the last element and the random element */
10076  tmp = array[i];
10077  array[i] = array[end];
10078  array[end] = tmp;
10079  }
10080 }
10081 
10082 /** randomly shuffles parts of an array using the Fisher-Yates algorithm */
10084  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10085  void** array, /**< array to be shuffled */
10086  int begin, /**< first included index that should be subject to shuffling
10087  * (0 for first array entry)
10088  */
10089  int end /**< first excluded index that should not be subject to shuffling
10090  * (array size for last array entry)
10091  */
10092  )
10093 {
10094  void* tmp;
10095  int i;
10096 
10097  /* loop backwards through all elements and always swap the current last element to a random position */
10098  while( end > begin+1 )
10099  {
10100  end--;
10101 
10102  /* get a random position into which the last entry should be shuffled */
10103  i = SCIPrandomGetInt(randnumgen, begin, end);
10104 
10105  /* swap the last element and the random element */
10106  tmp = array[i];
10107  array[i] = array[end];
10108  array[end] = tmp;
10109  }
10110 }
10111 
10112 /** draws a random subset of disjoint elements from a given set of disjoint elements;
10113  * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10114  */
10116  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10117  void** set, /**< original set, from which elements should be drawn */
10118  int nelems, /**< number of elements in original set */
10119  void** subset, /**< subset in which drawn elements should be stored */
10120  int nsubelems /**< number of elements that should be drawn and stored */
10121  )
10122 {
10123  int i;
10124  int j;
10125 
10126  /* if both sets are of equal size, we just copy the array */
10127  if( nelems == nsubelems)
10128  {
10129  BMScopyMemoryArray(subset,set,nelems);
10130  return SCIP_OKAY;
10131  }
10132 
10133  /* abort, if size of subset is too big */
10134  if( nsubelems > nelems )
10135  {
10136  SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10137  return SCIP_INVALIDDATA;
10138  }
10139 #ifndef NDEBUG
10140  for( i = 0; i < nsubelems; i++ )
10141  for( j = 0; j < i; j++ )
10142  assert(set[i] != set[j]);
10143 #endif
10144 
10145  /* draw each element individually */
10146  i = 0;
10147  while( i < nsubelems )
10148  {
10149  int r;
10150 
10151  r = SCIPrandomGetInt(randnumgen, 0, nelems-1);
10152  subset[i] = set[r];
10153 
10154  /* if we get an element that we already had, we will draw again */
10155  for( j = 0; j < i; j++ )
10156  {
10157  if( subset[i] == subset[j] )
10158  {
10159  --i;
10160  break;
10161  }
10162  }
10163  ++i;
10164  }
10165  return SCIP_OKAY;
10166 }
10167 
10168 /*
10169  * Additional math functions
10170  */
10171 
10172 /** calculates a binomial coefficient n over m, choose m elements out of n, maximal value will be 33 over 16 (because
10173  * the n=33 is the last line in the Pascal's triangle where each entry fits in a 4 byte value), an error occurs due to
10174  * big numbers or an negative value m (and m < n) and -1 will be returned
10175  */
10177  int n, /**< number of different elements */
10178  int m /**< number to choose out of the above */
10179  )
10180 {
10181  if( m == 0 || m >= n )
10182  return 1;
10183 
10184  if( m < 0 )
10185  return -1;
10186 
10187  /* symmetry of the binomial coefficient, choose smaller m */
10188  if( m > n/2 )
10189  m = n - m;
10190 
10191  /* trivial case m == 1 */
10192  if( m == 1 )
10193  return n;
10194 
10195  /* simple case m == 2 */
10196  if( m == 2 )
10197  {
10198  if( ((SCIP_Real)SCIP_LONGINT_MAX) / n >= (n-1) * 2 ) /*lint !e790*/
10199  return ((SCIP_Longint)n*(n-1)/2); /*lint !e647*/
10200  else
10201  return -1;
10202  }
10203 
10204  /* abort on to big numbers */
10205  if( m > 16 || n > 33 )
10206  return -1;
10207 
10208  /* simple case m == 3 */
10209  if( m == 3 )
10210  return (n*(n-1)*(n-2)/6); /*lint !e647*/
10211  else
10212  {
10213  /* first half of Pascal's triangle numbers(without the symmetric part) backwards from (33,16) over (32,16),
10214  * (33,15), (32,15),(31,15, (30,15), (33,14) to (8,4) (rest is calculated directly)
10215  *
10216  * due to this order we can extract the right binomial coefficient by (16-m)^2+(16-m)+(33-n)
10217  */
10218  static const SCIP_Longint binoms[182] = {
10219  1166803110, 601080390, 1037158320, 565722720, 300540195, 155117520, 818809200, 471435600, 265182525, 145422675,
10220  77558760, 40116600, 573166440, 347373600, 206253075, 119759850, 67863915, 37442160, 20058300, 10400600,
10221  354817320, 225792840, 141120525, 86493225, 51895935, 30421755, 17383860, 9657700, 5200300, 2704156, 193536720,
10222  129024480, 84672315, 54627300, 34597290, 21474180, 13037895, 7726160, 4457400, 2496144, 1352078, 705432,
10223  92561040, 64512240, 44352165, 30045015, 20030010, 13123110, 8436285, 5311735, 3268760, 1961256, 1144066,
10224  646646, 352716, 184756, 38567100, 28048800, 20160075, 14307150, 10015005, 6906900, 4686825, 3124550, 2042975,
10225  1307504, 817190, 497420, 293930, 167960, 92378, 48620, 13884156, 10518300, 7888725, 5852925, 4292145, 3108105,
10226  2220075, 1562275, 1081575, 735471, 490314, 319770, 203490, 125970, 75582, 43758, 24310, 12870, 4272048, 3365856,
10227  2629575, 2035800, 1560780, 1184040, 888030, 657800, 480700, 346104, 245157, 170544, 116280, 77520, 50388, 31824,
10228  19448, 11440, 6435, 3432, 1107568, 906192, 736281, 593775, 475020, 376740, 296010, 230230, 177100, 134596,
10229  100947, 74613, 54264, 38760, 27132, 18564, 12376, 8008, 5005, 3003, 1716, 924, 237336, 201376, 169911, 142506,
10230  118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, 11628, 8568, 6188, 4368, 3003, 2002,
10231  1287, 792, 462, 252, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985,
10232  4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70};
10233 
10234  /* m can at most be 16 */
10235  const int t = 16-m;
10236  assert(t >= 0);
10237  assert(n <= 33);
10238 
10239  /* binoms array hast exactly 182 elements */
10240  assert(t*(t+1)+(33-n) < 182);
10241 
10242  return binoms[t*(t+1)+(33-n)]; /*lint !e662 !e661*/
10243  }
10244 }
10245 
10246 #ifndef NDEBUG
10247 /** calculates hash for floating-point number by using Fibonacci hashing */
10248 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ * 10 >= 490 && !defined(__INTEL_COMPILER)
10249 __attribute__((no_sanitize_undefined))
10250 #endif
10251 unsigned int SCIPcalcFibHash(
10252  SCIP_Real v /**< number to hash */
10253  )
10254 {
10255  if( v >= 0 )
10256  return ((unsigned long long)(v * 2654435769)) % UINT_MAX;
10257  return ((unsigned long long)(-v * 683565275)) % UINT_MAX;
10258 }
10259 #endif
10260 
10261 /** negates a number */
10263  SCIP_Real x /**< value to negate */
10264  )
10265 {
10266  return -x;
10267 }
10268 
10269 /*
10270  * Permutations / Shuffling
10271  */
10272 
10273 /** swaps two ints */
10275  int* value1, /**< pointer to first integer */
10276  int* value2 /**< pointer to second integer */
10277  )
10278 {
10279  int tmp;
10280 
10281  tmp = *value1;
10282  *value1 = *value2;
10283  *value2 = tmp;
10284 }
10285 
10286 /** swaps two real values */
10288  SCIP_Real* value1, /**< pointer to first real value */
10289  SCIP_Real* value2 /**< pointer to second real value */
10290  )
10291 {
10292  SCIP_Real tmp;
10293 
10294  tmp = *value1;
10295  *value1 = *value2;
10296  *value2 = tmp;
10297 }
10298 
10299 /** swaps the addresses of two pointers */
10301  void** pointer1, /**< first pointer */
10302  void** pointer2 /**< second pointer */
10303  )
10304 {
10305  void* tmp;
10306 
10307  tmp = *pointer1;
10308  *pointer1 = *pointer2;
10309  *pointer2 = tmp;
10310 }
10311 
10312 /** randomly shuffles parts of an integer array using the Fisher-Yates algorithm
10313  *
10314  * @deprecated Please use SCIPrandomPermuteIntArray()
10315  */
10317  int* array, /**< array to be shuffled */
10318  int begin, /**< first included index that should be subject to shuffling
10319  * (0 for first array entry)
10320  */
10321  int end, /**< first excluded index that should not be subject to shuffling
10322  * (array size for last array entry)
10323  */
10324  unsigned int* randseed /**< seed value for the random generator */
10325  )
10326 {
10327  int tmp;
10328  int i;
10329 
10330  /* loop backwards through all elements and always swap the current last element to a random position */
10331  while( end > begin+1 )
10332  {
10333  --end;
10334 
10335  /* get a random position into which the last entry should be shuffled */
10336  i = getRandomInt(begin, end, randseed);
10337 
10338  /* swap the last element and the random element */
10339  tmp = array[i];
10340  array[i] = array[end];
10341  array[end] = tmp;
10342  }
10343 }
10344 
10345 
10346 /** randomly shuffles parts of an array using the Fisher-Yates algorithm
10347  *
10348  * @deprecated Please use SCIPrandomPermuteArray()
10349  */
10351  void** array, /**< array to be shuffled */
10352  int begin, /**< first included index that should be subject to shuffling
10353  * (0 for first array entry)
10354  */
10355  int end, /**< first excluded index that should not be subject to shuffling
10356  * (array size for last array entry)
10357  */
10358  unsigned int* randseed /**< seed value for the random generator */
10359  )
10360 {
10361  void* tmp;
10362  int i;
10363 
10364  /* loop backwards through all elements and always swap the current last element to a random position */
10365  while( end > begin+1 )
10366  {
10367  end--;
10368 
10369  /* get a random position into which the last entry should be shuffled */
10370  i = getRandomInt(begin, end, randseed);
10371 
10372  /* swap the last element and the random element */
10373  tmp = array[i];
10374  array[i] = array[end];
10375  array[end] = tmp;
10376  }
10377 }
10378 
10379 /** draws a random subset of disjoint elements from a given set of disjoint elements;
10380  * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10381  *
10382  * @deprecated Please use SCIPrandomGetSubset()
10383  */
10385  void** set, /**< original set, from which elements should be drawn */
10386  int nelems, /**< number of elements in original set */
10387  void** subset, /**< subset in which drawn elements should be stored */
10388  int nsubelems, /**< number of elements that should be drawn and stored */
10389  unsigned int randseed /**< seed value for random generator */
10390  )
10391 {
10392  int i;
10393  int j;
10394 
10395  /* if both sets are of equal size, we just copy the array */
10396  if( nelems == nsubelems)
10397  {
10398  BMScopyMemoryArray(subset,set,nelems);
10399  return SCIP_OKAY;
10400  }
10401 
10402  /* abort, if size of subset is too big */
10403  if( nsubelems > nelems )
10404  {
10405  SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10406  return SCIP_INVALIDDATA;
10407  }
10408 #ifndef NDEBUG
10409  for( i = 0; i < nsubelems; i++ )
10410  for( j = 0; j < i; j++ )
10411  assert(set[i] != set[j]);
10412 #endif
10413 
10414  /* draw each element individually */
10415  i = 0;
10416  while( i < nsubelems )
10417  {
10418  int r;
10419 
10420  r = getRandomInt(0, nelems-1, &randseed);
10421  subset[i] = set[r];
10422 
10423  /* if we get an element that we already had, we will draw again */
10424  for( j = 0; j < i; j++ )
10425  {
10426  if( subset[i] == subset[j] )
10427  {
10428  --i;
10429  break;
10430  }
10431  }
10432  ++i;
10433  }
10434  return SCIP_OKAY;
10435 }
10436 
10437 
10438 /*
10439  * Arrays
10440  */
10441 
10442 /** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly
10443  *
10444  * @deprecated Switch to SCIPcomputeArraysIntersectionInt().
10445  */
10447  int* array1, /**< first array (in ascending order) */
10448  int narray1, /**< number of entries of first array */
10449  int* array2, /**< second array (in ascending order) */
10450  int narray2, /**< number of entries of second array */
10451  int* intersectarray, /**< intersection of array1 and array2
10452  * (note: it is possible to use array1 for this input argument) */
10453  int* nintersectarray /**< pointer to store number of entries of intersection array
10454  * (note: it is possible to use narray1 for this input argument) */
10455  )
10456 {
10457  SCIPcomputeArraysIntersectionInt(array1, narray1, array2, narray2, intersectarray, nintersectarray);
10458 
10459  return SCIP_OKAY;
10460 }
10461 
10462 /** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly */
10464  int* array1, /**< first array (in ascending order) */
10465  int narray1, /**< number of entries of first array */
10466  int* array2, /**< second array (in ascending order) */
10467  int narray2, /**< number of entries of second array */
10468  int* intersectarray, /**< intersection of array1 and array2
10469  * (note: it is possible to use array1 for this input argument) */
10470  int* nintersectarray /**< pointer to store number of entries of intersection array
10471  * (note: it is possible to use narray1 for this input argument) */
10472  )
10473 {
10474  int cnt = 0;
10475  int k = 0;
10476  int v1;
10477  int v2;
10478 
10479  assert( array1 != NULL );
10480  assert( array2 != NULL );
10481  assert( intersectarray != NULL );
10482  assert( nintersectarray != NULL );
10483 
10484  /* determine intersection of array1 and array2 */
10485  for (v1 = 0; v1 < narray1; ++v1)
10486  {
10487  assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10488 
10489  /* skip duplicate entries */
10490  if ( v1+1 < narray1 && array1[v1] == array1[v1+1])
10491  continue;
10492 
10493  for (v2 = k; v2 < narray2; ++v2)
10494  {
10495  assert( v2 == 0 || array2[v2] >= array2[v2-1] );
10496 
10497  if ( array2[v2] > array1[v1] )
10498  {
10499  k = v2;
10500  break;
10501  }
10502  else if ( array2[v2] == array1[v1] )
10503  {
10504  intersectarray[cnt++] = array2[v2];
10505  k = v2 + 1;
10506  break;
10507  }
10508  }
10509  }
10510 
10511  /* store size of intersection array */
10512  *nintersectarray = cnt;
10513 }
10514 
10515 /** computes set intersection (duplicates removed) of two void-pointer arrays that are ordered ascendingly */
10517  void** array1, /**< pointer to first data array */
10518  int narray1, /**< number of entries of first array */
10519  void** array2, /**< pointer to second data array */
10520  int narray2, /**< number of entries of second array */
10521  SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
10522  void** intersectarray, /**< intersection of array1 and array2
10523  * (note: it is possible to use array1 for this input argument) */
10524  int* nintersectarray /**< pointer to store number of entries of intersection array
10525  * (note: it is possible to use narray1 for this input argument) */
10526  )
10527 {
10528  int cnt = 0;
10529  int k = 0;
10530  int v1;
10531  int v2;
10532 
10533  assert( array1 != NULL );
10534  assert( array2 != NULL );
10535  assert( ptrcomp != NULL );
10536  assert( intersectarray != NULL );
10537  assert( nintersectarray != NULL );
10538 
10539  /* determine intersection of array1 and array2 */
10540  for( v1 = 0; v1 < narray1; ++v1 )
10541  {
10542  assert( v1 == 0 || (*ptrcomp)(array1[v1], array1[v1-1]) >= 0 );
10543 
10544  /* skip duplicate entries */
10545  if( v1+1 < narray1 && array1[v1] == array1[v1+1] )
10546  continue;
10547 
10548  for( v2 = k; v2 < narray2; ++v2 )
10549  {
10550  assert( v2 == 0 || (*ptrcomp)(array2[v2], array2[v2-1]) > 0 || array2[v2] == array2[v2-1] );
10551 
10552  if( (*ptrcomp)(array2[v2], array1[v1]) > 0 )
10553  {
10554  k = v2;
10555  break;
10556  }
10557 
10558  if( array2[v2] == array1[v1] )
10559  {
10560  intersectarray[cnt++] = array2[v2];
10561  k = v2 + 1;
10562  break;
10563  }
10564  }
10565  }
10566 
10567  /* store size of intersection array */
10568  *nintersectarray = cnt;
10569 }
10570 
10571 
10572 /** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly
10573  *
10574  * @deprecated Switch to SCIPcomputeArraysSetminusInt().
10575  */
10577  int* array1, /**< first array (in ascending order) */
10578  int narray1, /**< number of entries of first array */
10579  int* array2, /**< second array (in ascending order) */
10580  int narray2, /**< number of entries of second array */
10581  int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10582  * (note: it is possible to use array1 for this input argument) */
10583  int* nsetminusarray /**< pointer to store number of entries of setminus array
10584  * (note: it is possible to use narray1 for this input argument) */
10585  )
10586 {
10587  SCIPcomputeArraysSetminusInt(array1, narray1, array2, narray2, setminusarray, nsetminusarray);
10588 
10589  return SCIP_OKAY;
10590 }
10591 
10592 /** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly */
10594  int* array1, /**< first array (in ascending order) */
10595  int narray1, /**< number of entries of first array */
10596  int* array2, /**< second array (in ascending order) */
10597  int narray2, /**< number of entries of second array */
10598  int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10599  * (note: it is possible to use array1 for this input argument) */
10600  int* nsetminusarray /**< pointer to store number of entries of setminus array
10601  * (note: it is possible to use narray1 for this input argument) */
10602  )
10603 {
10604  int cnt = 0;
10605  int v1 = 0;
10606  int v2 = 0;
10607 
10608  assert( array1 != NULL );
10609  assert( array2 != NULL );
10610  assert( setminusarray != NULL );
10611  assert( nsetminusarray != NULL );
10612 
10613  while ( v1 < narray1 )
10614  {
10615  int entry1;
10616 
10617  assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10618 
10619  /* skip duplicate entries */
10620  while ( v1 + 1 < narray1 && array1[v1] == array1[v1 + 1] )
10621  ++v1;
10622 
10623  entry1 = array1[v1];
10624 
10625  while ( v2 < narray2 && array2[v2] < entry1 )
10626  ++v2;
10627 
10628  if ( v2 >= narray2 || entry1 < array2[v2] )
10629  setminusarray[cnt++] = entry1;
10630  ++v1;
10631  }
10632 
10633  /* store size of setminus array */
10634  *nsetminusarray = cnt;
10635 }
10636 
10637 
10638 /*
10639  * Strings
10640  */
10641 
10642 
10643 /** copies characters from 'src' to 'dest', copying is stopped when either the 'stop' character is reached or after
10644  * 'cnt' characters have been copied, whichever comes first.
10645  *
10646  * @note undefined behavior on overlapping arrays
10647  */
10649  char* dest, /**< destination pointer to copy to */
10650  const char* src, /**< source pointer to copy from */
10651  char stop, /**< character when found stop copying */
10652  unsigned int cnt /**< maximal number of characters to copy */
10653  )
10654 {
10655  if( dest == NULL || src == NULL || cnt == 0 )
10656  return -1;
10657  else
10658  {
10659  char* destination = dest;
10660 
10661  while( cnt-- && (*destination++ = *src++) != stop ); /*lint !e722*/
10662 
10663  return (int)(destination - dest);
10664  }
10665 }
10666 
10667 /** prints an error message containing of the given string followed by a string describing the current system error
10668  *
10669  * Prefers to use the strerror_r method, which is threadsafe. On systems where this method does not exist,
10670  * NO_STRERROR_R should be defined (see INSTALL). In this case, strerror is used which is not guaranteed to be
10671  * threadsafe (on SUN-systems, it actually is).
10672  */
10674  const char* message /**< first part of the error message, e.g. the filename */
10675  )
10676 {
10677 #ifdef NO_STRERROR_R
10678  SCIPmessagePrintError("%s: %s\n", message, strerror(errno));
10679 #else
10680  char buf[SCIP_MAXSTRLEN];
10681 
10682 #if defined(_WIN32) || defined(_WIN64)
10683  /* strerror_s returns 0 on success; the string is \0 terminated. */
10684  if ( strerror_s(buf, SCIP_MAXSTRLEN, errno) != 0 )
10685  SCIPmessagePrintError("Unknown error number %d or error message too long.\n", errno);
10686  SCIPmessagePrintError("%s: %s\n", message, buf);
10687 #elif (_POSIX_C_SOURCE >= 200112L || __DARWIN_C_LEVEL > 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
10688  /* We are in the POSIX/XSI case, where strerror_r returns 0 on success; \0 termination is unclear. */
10689  if ( strerror_r(errno, buf, SCIP_MAXSTRLEN) != 0 )
10690  SCIPmessagePrintError("Unknown error number %d.\n", errno);
10691  buf[SCIP_MAXSTRLEN - 1] = '\0';
10692  SCIPmessagePrintError("%s: %s\n", message, buf);
10693 #else
10694  /* We are in the GNU case, where strerror_r returns a pointer to the error string. This string is possibly stored
10695  * in buf and is always \0 terminated.
10696  * However, if compiling on one system and executing on another system, we might actually call a different
10697  * variant of the strerror_r function than we had at compile time.
10698  */
10699  char* errordescr;
10700  *buf = '\0';
10701  errordescr = strerror_r(errno, buf, SCIP_MAXSTRLEN);
10702  if( *buf != '\0' )
10703  {
10704  /* strerror_r wrote into buf */
10705  SCIPmessagePrintError("%s: %s\n", message, buf);
10706  }
10707  else if( errordescr != NULL )
10708  {
10709  /* strerror_r returned something non-NULL */
10710  SCIPmessagePrintError("%s: %s\n", message, errordescr);
10711  }
10712  else
10713  {
10714  /* strerror_r did return NULL and did not write into buf */
10715  SCIPmessagePrintError("Could not obtain description for error %d.\n", errno);
10716  }
10717 #endif
10718 #endif
10719 }
10720 
10721 /** extracts tokens from strings - wrapper method for strtok_r() */
10723  char* s, /**< string to parse */
10724  const char* delim, /**< delimiters for parsing */
10725  char** ptrptr /**< pointer to working char pointer - must stay the same while parsing */
10726  )
10727 {
10728 #ifdef SCIP_NO_STRTOK_R
10729  return strtok(s, delim);
10730 #else
10731  return strtok_r(s, delim, ptrptr);
10732 #endif
10733 }
10734 
10735 /** translates the given string into a string where symbols ", ', and spaces are escaped with a \ prefix */
10737  char* t, /**< target buffer to store escaped string */
10738  int bufsize, /**< size of buffer t */
10739  const char* s /**< string to transform into escaped string */
10740  )
10741 {
10742  int len;
10743  int i;
10744  int p;
10745 
10746  assert(t != NULL);
10747  assert(bufsize > 0);
10748 
10749  len = (int)strlen(s);
10750  for( p = 0, i = 0; i <= len && p < bufsize; ++i, ++p )
10751  {
10752  if( s[i] == ' ' || s[i] == '"' || s[i] == '\'' )
10753  {
10754  t[p] = '\\';
10755  p++;
10756  }
10757  if( p < bufsize )
10758  t[p] = s[i];
10759  }
10760  t[bufsize-1] = '\0';
10761 }
10762 
10763 /* safe version of snprintf */
10765  char* t, /**< target string */
10766  int len, /**< length of the string to copy */
10767  const char* s, /**< source string */
10768  ... /**< further parameters */
10769  )
10770 {
10771  va_list ap;
10772  int n;
10773 
10774  assert(t != NULL);
10775  assert(len > 0);
10776 
10777  va_start(ap, s); /*lint !e826*/
10778 
10779 #if defined(_WIN32) || defined(_WIN64)
10780  n = _vsnprintf(t, (size_t) len, s, ap);
10781 #else
10782  n = vsnprintf(t, (size_t) len, s, ap); /*lint !e571*/
10783 #endif
10784  va_end(ap);
10785 
10786  if( n < 0 || n >= len )
10787  {
10788 #ifndef NDEBUG
10789  if( n < 0 )
10790  {
10791  SCIPerrorMessage("vsnprintf returned %d\n",n);
10792  }
10793 #endif
10794  t[len-1] = '\0';
10795  n = len-1;
10796  }
10797  return n;
10798 }
10799 
10800 /** safe version of strncpy
10801  *
10802  * Copies string in s to t using at most @a size-1 nonzero characters (strncpy copies size characters). It always adds
10803  * a terminating zero char. Does not pad the remaining string with zero characters (unlike strncpy). Returns the number
10804  * of copied nonzero characters, if the length of s is at most size - 1, and returns size otherwise. Thus, the original
10805  * string was truncated if the return value is size.
10806  */
10808  char* t, /**< target string */
10809  const char* s, /**< source string */
10810  int size /**< maximal size of t */
10811  )
10812 {
10813  int n;
10814 
10815  if( size <= 0 )
10816  return 0;
10817 
10818  /* decrease size by 1 to create space for terminating zero char */
10819  --size;
10820  for( n = 0; n < size && *s != '\0'; n++ )
10821  *(t++) = *(s++);
10822  *t = '\0';
10823 
10824  if( *s != '\0' )
10825  ++n;
10826 
10827  return n;
10828 }
10829 
10830 /** extract the next token as a integer value if it is one; in case no value is parsed the endptr is set to @p str
10831  *
10832  * @return Returns TRUE if a value could be extracted, otherwise FALSE
10833  */
10835  const char* str, /**< string to search */
10836  int* value, /**< pointer to store the parsed value */
10837  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10838  )
10839 {
10840  assert(str != NULL);
10841  assert(value != NULL);
10842  assert(endptr != NULL);
10843 
10844  /* init errno to detect possible errors */
10845  errno = 0;
10846 
10847  *value = (int) strtol(str, endptr, 10);
10848 
10849  if( *endptr != str && *endptr != NULL )
10850  {
10851  SCIPdebugMessage("parsed integer value <%d>\n", *value);
10852  return TRUE;
10853  }
10854  *endptr = (char*)str;
10855 
10856  SCIPdebugMessage("failed parsing integer value <%s>\n", str);
10857 
10858  return FALSE;
10859 }
10860 
10861 /** extract the next token as a double value if it is one; in case no value is parsed the endptr is set to @p str
10862  *
10863  * @return Returns TRUE if a value could be extracted, otherwise FALSE
10864  */
10866  const char* str, /**< string to search */
10867  SCIP_Real* value, /**< pointer to store the parsed value */
10868  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10869  )
10870 {
10871  assert(str != NULL);
10872  assert(value != NULL);
10873  assert(endptr != NULL);
10874 
10875  /* init errno to detect possible errors */
10876  errno = 0;
10877 
10878  *value = strtod(str, endptr);
10879 
10880  if( *endptr != str && *endptr != NULL )
10881  {
10882  SCIPdebugMessage("parsed real value <%g>\n", *value);
10883  return TRUE;
10884  }
10885  *endptr = (char*)str;
10886 
10887  SCIPdebugMessage("failed parsing real value <%s>\n", str);
10888 
10889  return FALSE;
10890 }
10891 
10892 /** copies the first size characters between a start and end character of str into token, if no error occurred endptr
10893  * will point to the position after the read part, otherwise it will point to @p str
10894  */
10896  const char* str, /**< string to search */
10897  char startchar, /**< character which defines the beginning */
10898  char endchar, /**< character which defines the ending */
10899  char* token, /**< string to store the copy */
10900  int size, /**< size of the token char array */
10901  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10902  )
10903 {
10904  const char* copystr;
10905  int nchars;
10906 
10907  assert(str != NULL);
10908  assert(token != NULL);
10909  assert(size > 0);
10910  assert(endptr != NULL);
10911 
10912  nchars = 0;
10913 
10914  copystr = str;
10915 
10916  /* find starting character */
10917  while( *str != '\0' && *str != startchar )
10918  ++str;
10919 
10920  /* did not find start character */
10921  if( *str == '\0' )
10922  {
10923  *endptr = (char*)copystr;
10924  return;
10925  }
10926 
10927  /* skip start character */
10928  ++str;
10929 
10930  /* copy string */
10931  while( *str != '\0' && *str != endchar && nchars < size-1 )
10932  {
10933  assert(nchars < SCIP_MAXSTRLEN);
10934  token[nchars] = *str;
10935  nchars++;
10936  ++str;
10937  }
10938 
10939  /* add end to token */
10940  token[nchars] = '\0';
10941 
10942  /* if section was longer than size, we want to reach the end of the parsing section anyway */
10943  if( nchars == (size-1) )
10944  while( *str != '\0' && *str != endchar )
10945  ++str;
10946 
10947  /* did not find end character */
10948  if( *str == '\0' )
10949  {
10950  *endptr = (char*)copystr;
10951  return;
10952  }
10953 
10954  /* skip end character */
10955  ++str;
10956 
10957  SCIPdebugMessage("parsed section <%s>\n", token);
10958 
10959  *endptr = (char*) str;
10960 }
10961 
10962 /*
10963  * File methods
10964  */
10965 
10966 /** returns, whether the given file exists */
10968  const char* filename /**< file name */
10969  )
10970 {
10971  FILE* f;
10972 
10973  f = fopen(filename, "r");
10974  if( f == NULL )
10975  return FALSE;
10976 
10977  fclose(f);
10978 
10979  return TRUE;
10980 }
10981 
10982 /** splits filename into path, name, and extension */
10984  char* filename, /**< filename to split; is destroyed (but not freed) during process */
10985  char** path, /**< pointer to store path, or NULL if not needed */
10986  char** name, /**< pointer to store name, or NULL if not needed */
10987  char** extension, /**< pointer to store extension, or NULL if not needed */
10988  char** compression /**< pointer to store compression extension, or NULL if not needed */
10989  )
10990 {
10991  char* lastslash;
10992  char* lastbackslash;
10993  char* lastdot;
10994 
10995  assert(filename != NULL);
10996 
10997  if( path != NULL )
10998  *path = NULL;
10999  if( name != NULL )
11000  *name = NULL;
11001  if( extension != NULL )
11002  *extension = NULL;
11003  if( compression != NULL )
11004  *compression = NULL;
11005 
11006  /* treat both slashes '/' and '\' as directory delimiters */
11007  lastslash = strrchr(filename, '/');
11008  lastbackslash = strrchr(filename, '\\');
11009  lastslash = MAX(lastslash, lastbackslash); /*lint !e613*/
11010  lastdot = strrchr(filename, '.');
11011  if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11012  lastdot = NULL;
11013 
11014  /* detect known compression extensions */
11015 #ifdef SCIP_WITH_ZLIB
11016  if( lastdot != NULL )
11017  {
11018  char* compext;
11019 
11020  compext = lastdot+1;
11021  if( strcmp(compext, "gz") == 0
11022  || strcmp(compext, "z") == 0
11023  || strcmp(compext, "Z") == 0 )
11024  {
11025  if( compression != NULL )
11026  *compression = compext;
11027  *lastdot = '\0';
11028  }
11029 
11030  /* find again the last dot in the filename without compression extension */
11031  lastdot = strrchr(filename, '.');
11032  if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11033  lastdot = NULL;
11034  }
11035 #endif
11036 
11037  if( lastslash == NULL )
11038  {
11039  if( name != NULL )
11040  *name = filename;
11041  }
11042  else
11043  {
11044  if( path != NULL )
11045  *path = filename;
11046  if( name != NULL )
11047  *name = lastslash+1;
11048  *lastslash = '\0';
11049  }
11050 
11051  if( lastdot != NULL )
11052  {
11053  if( extension != NULL )
11054  *extension = lastdot+1;
11055  *lastdot = '\0';
11056  }
11057 }
11058 
11059 /*
11060  * simple functions implemented as defines
11061  */
11062 
11063 /* In debug mode, the following methods are implemented as function calls to ensure
11064  * type validity.
11065  * In optimized mode, the methods are implemented as defines to improve performance.
11066  * However, we want to have them in the library anyways, so we have to undef the defines.
11067  */
11068 
11069 #undef SCIPrelDiff
11070 
11071 /** returns the relative difference: (val1-val2)/max(|val1|,|val2|,1.0) */
11073  SCIP_Real val1, /**< first value to be compared */
11074  SCIP_Real val2 /**< second value to be compared */
11075  )
11076 {
11077  SCIP_Real absval1;
11078  SCIP_Real absval2;
11079  SCIP_Real quot;
11080 
11081  absval1 = REALABS(val1);
11082  absval2 = REALABS(val2);
11083  quot = MAX3(1.0, absval1, absval2);
11084 
11085  return (val1-val2)/quot;
11086 }
11087 
11088 
11089 /** computes the gap from the primal and the dual bound */
11091  SCIP_Real eps, /**< the value treated as zero */
11092  SCIP_Real inf, /**< the value treated as infinity */
11093  SCIP_Real primalbound, /**< the primal bound */
11094  SCIP_Real dualbound /**< the dual bound */
11095  )
11096 {
11097  if( EPSEQ(primalbound, dualbound, eps) )
11098  return 0.0;
11099  else
11100  {
11101  SCIP_Real absdual = REALABS(dualbound);
11102  SCIP_Real absprimal = REALABS(primalbound);
11103 
11104  if( EPSZ(dualbound, eps) || EPSZ(primalbound, eps) || absprimal >= inf || absdual >= inf ||
11105  primalbound * dualbound < 0.0 )
11106  return inf;
11107  else
11108  return REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
11109  }
11110 }
11111 
11112 /*
11113  * disjoint set (union-find) data structure
11114  */
11115 
11116 /** creates a disjoint set (union find) structure \p djset for \p ncomponents many components (of size one) */
11118  SCIP_DISJOINTSET** djset, /**< disjoint set (union find) data structure */
11119  BMS_BLKMEM* blkmem, /**< block memory */
11120  int ncomponents /**< number of components */
11121  )
11122 {
11123  assert(djset != NULL);
11124  assert(blkmem != NULL);
11125 
11126  /* allocate the necessary memory */
11127  assert(ncomponents > 0);
11128  SCIP_ALLOC( BMSallocBlockMemory(blkmem, djset) );
11129  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->parents), ncomponents) );
11130  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->sizes), ncomponents) );
11131  (*djset)->size = ncomponents;
11132 
11133  /* clear the data structure */
11134  SCIPdisjointsetClear(*djset);
11135 
11136  return SCIP_OKAY;
11137 }
11138 
11139 /** clears the disjoint set (union find) structure \p djset */
11141  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11142  )
11143 {
11144  int i;
11145 
11146  djset->componentcount = djset->size;
11147 
11148  /* reset all components to be unconnected */
11149  for( i = 0; i < djset->componentcount; i++ )
11150  {
11151  djset->parents[i] = i;
11152  djset->sizes[i] = 1;
11153  }
11154 }
11155 
11156 /** finds and returns the component identifier of this \p element */
11158  SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11159  int element /**< element to be found */
11160  )
11161 {
11162  int newelement;
11163  int root = element;
11164  int* parents = djset->parents;
11165 
11166  /* find root of this element */
11167  while( root != parents[root] )
11168  {
11169  root = parents[root];
11170  }
11171 
11172  /* compress the path to make future queries faster */
11173  while( element != root )
11174  {
11175  newelement = parents[element];
11176  parents[element] = root;
11177  element = newelement;
11178  }
11179 
11180  return root;
11181 }
11182 
11183 /** merges the components containing the elements \p p and \p q */
11185  SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11186  int p, /**< first element */
11187  int q, /**< second element */
11188  SCIP_Bool forcerepofp /**< force representative of p to be new representative */
11189  )
11190 {
11191  int idp;
11192  int idq;
11193  int* sizes;
11194  int* parents;
11195 
11196  assert(djset != NULL);
11197  assert(0 <= p);
11198  assert(0 <= q);
11199  assert(djset->size > p);
11200  assert(djset->size > q);
11201 
11202  idp = SCIPdisjointsetFind(djset, p);
11203  idq = SCIPdisjointsetFind(djset, q);
11204 
11205  /* if p and q lie in the same component, there is nothing to be done */
11206  if( idp == idq )
11207  return;
11208 
11209  sizes = djset->sizes;
11210  parents = djset->parents;
11211 
11212  if( forcerepofp )
11213  {
11214  parents[idq] = idp;
11215  sizes[idp] += sizes[idq];
11216  }
11217  else
11218  {
11219  if( sizes[idp] < sizes[idq] )
11220  {
11221  parents[idp] = idq;
11222  sizes[idq] += sizes[idp];
11223  }
11224  else
11225  {
11226  parents[idq] = idp;
11227  sizes[idp] += sizes[idq];
11228  }
11229  }
11230  /* one less component */
11231  djset->componentcount--;
11232 }
11233 
11234 /** frees the disjoint set (union find) data structure */
11236  SCIP_DISJOINTSET** djset, /**< pointer to disjoint set (union find) data structure */
11237  BMS_BLKMEM* blkmem /**< block memory */
11238  )
11239 {
11240  SCIP_DISJOINTSET* dsptr;
11241 
11242  assert(djset != NULL);
11243  assert(*djset != NULL);
11244 
11245  dsptr = *djset;
11246 
11247  BMSfreeBlockMemoryArray(blkmem, &dsptr->sizes, dsptr->size);
11248  BMSfreeBlockMemoryArray(blkmem, &dsptr->parents, dsptr->size);
11249 
11250  BMSfreeBlockMemory(blkmem, djset);
11251 }
11252 
11253 /** returns the number of independent components in this disjoint set (union find) data structure */
11255  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11256  )
11257 {
11258  assert(djset != NULL);
11259 
11260  return djset->componentcount;
11261 }
11262 
11263 /** returns the size (number of nodes) of this disjoint set (union find) data structure */
11265  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11266  )
11267 {
11268  assert(djset != NULL);
11269 
11270  return djset->size;
11271 }
11272 
11273 /** checks whether a given string t appears at the beginning of the string s (up to spaces at beginning) */
11275  const char* s, /**< string to search in */
11276  const char* t, /**< string to search for */
11277  size_t tlen /**< length of t */
11278  )
11279 {
11280  int idxctr = 0;
11281 
11282  assert(s != NULL);
11283  assert(t != NULL);
11284 
11285  /* skip whitespace at beginning */
11286  while( idxctr < SCIP_MAXSTRLEN && isspace((unsigned char)s[idxctr]) )
11287  ++idxctr;
11288  if( strncmp(&s[idxctr], t, tlen) == 0 )
11289  return TRUE;
11290  return FALSE;
11291 }
void SCIPmultihashFree(SCIP_MULTIHASH **multihash)
Definition: misc.c:1943
void SCIPpermuteArray(void **array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10350
uint32_t * hashes
Definition: struct_misc.h:141
SCIP_BTNODE * parent
Definition: struct_misc.h:240
SCIP_RETCODE SCIPbtnodeCreate(SCIP_BT *tree, SCIP_BTNODE **node, void *dataptr)
Definition: misc.c:8587
int SCIPrealarrayGetMaxIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4341
void ** slots
Definition: struct_misc.h:96
void ** SCIPdigraphGetSuccessorsData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7748
int SCIPpqueueNElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1477
static void regressionRecompute(SCIP_REGRESSION *regression)
Definition: misc.c:284
void SCIPbtnodeFree(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8651
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3519
SCIP_Real SCIPnormalGetCriticalValue(SCIP_CONFIDENCELEVEL clevel)
Definition: misc.c:182
SCIP_Real * vals
Definition: struct_misc.h:160
static void * multihashlistRetrieveNext(SCIP_MULTIHASHLIST **multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1728
BMS_BLKMEM * blkmem
Definition: struct_misc.h:94
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:470
SCIP_QUEUEELEMENT * slots
Definition: struct_misc.h:63
static SCIP_Bool hashmapLookup(SCIP_HASHMAP *hashmap, void *origin, uint32_t *pos)
Definition: misc.c:2927
int SCIP_ROUNDMODE
Definition: intervalarith.h:64
#define narcs
Definition: gastrans.c:77
int SCIPmemccpy(char *dest, const char *src, char stop, unsigned int cnt)
Definition: misc.c:10648
SCIP_Real SCIPerf(SCIP_Real x)
Definition: misc.c:155
static SCIP_Bool multihashlistRemove(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1761
void SCIPhashmapEntrySetImageReal(SCIP_HASHMAPENTRY *entry, SCIP_Real image)
Definition: misc.c:3571
static SCIP_RETCODE hashmapCheckLoad(SCIP_HASHMAP *hashmap)
Definition: misc.c:2972
void *** arcdata
Definition: struct_misc.h:223
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:150
SCIP_RETCODE SCIPhashsetRemove(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3807
static const int nscalars
Definition: misc.c:9462
static SCIP_RETCODE hashmapInsert(SCIP_HASHMAP *hashmap, void *origin, SCIP_HASHMAPIMAGE image, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2851
BMS_BLKMEM * blkmem
Definition: struct_misc.h:221
void SCIPdisjointsetUnion(SCIP_DISJOINTSET *djset, int p, int q, SCIP_Bool forcerepofp)
Definition: misc.c:11184
void * SCIPhashtableGetEntry(SCIP_HASHTABLE *hashtable, int entryidx)
Definition: misc.c:2734
void SCIPsparseSolGetFirstSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:819
SCIP_BTNODE * SCIPbtnodeGetSibling(SCIP_BTNODE *node)
Definition: misc.c:8736
SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3306
uint32_t shift
Definition: struct_misc.h:142
SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
Definition: misc.c:6961
void * SCIPbtnodeGetData(SCIP_BTNODE *node)
Definition: misc.c:8696
void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2496
BMS_BLKMEM * blkmem
Definition: struct_misc.h:250
SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
Definition: misc.c:2800
SCIP_Real intercept
Definition: struct_misc.h:256
void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8428
int SCIPhashsetGetNElements(SCIP_HASHSET *hashset)
Definition: misc.c:3941
SCIP_RETCODE SCIPintarrayIncVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int incval)
Definition: misc.c:4683
void SCIPhashmapEntrySetImageInt(SCIP_HASHMAPENTRY *entry, int image)
Definition: misc.c:3560
static SCIP_RETCODE multihashlistAppend(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1601
void ** SCIPhashsetGetSlots(SCIP_HASHSET *hashset)
Definition: misc.c:3957
#define SCIP_MAXSTRLEN
Definition: def.h:302
static uint32_t hashSetDesiredPos(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3607
void ** nodedata
Definition: struct_misc.h:224
static SCIP_RETCODE hashtableCheckLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2443
void SCIPgmlWriteArc(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:638
SCIP_RETCODE SCIPdigraphComputeUndirectedComponents(SCIP_DIGRAPH *digraph, int minsize, int *components, int *ncomponents)
Definition: misc.c:8000
int SCIPintarrayGetMinIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4695
SCIP_RETCODE SCIPrealarrayCreate(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem)
Definition: misc.c:3979
static SCIP_RETCODE btnodeCreateEmpty(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8571
SCIP_RETCODE SCIPintarrayCopy(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem, SCIP_INTARRAY *sourceintarray)
Definition: misc.c:4371
void SCIPcomputeArraysSetminusInt(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10593
SCIP_Bool SCIPboolarrayGetVal(SCIP_BOOLARRAY *boolarray, int idx)
Definition: misc.c:4962
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:435
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7730
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
static SCIP_RETCODE ensureSuccessorsSize(SCIP_DIGRAPH *digraph, int idx, int newsize)
Definition: misc.c:7526
int firstfree
Definition: struct_misc.h:64
SCIP_RETCODE SCIPqueueInsert(SCIP_QUEUE *queue, void *elem)
Definition: misc.c:1029
static SCIP_RETCODE doProfileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6644
void SCIPgmlWriteNode(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor)
Definition: misc.c:496
void SCIPsplitFilename(char *filename, char **path, char **name, char **extension, char **compression)
Definition: misc.c:10983
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3509
SCIP_Bool SCIPsparseSolGetNextSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:842
int SCIPprofileGetTime(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6758
SCIP_RETCODE SCIPmultihashCreate(SCIP_MULTIHASH **multihash, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1910
int SCIPintarrayGetVal(SCIP_INTARRAY *intarray, int idx)
Definition: misc.c:4594
int * componentstarts
Definition: struct_misc.h:228
void SCIPgmlWriteClosing(FILE *file)
Definition: misc.c:698
uint32_t * hashes
Definition: struct_misc.h:97
uint32_t shift
Definition: struct_misc.h:152
static int calcGrowSize(int initsize, SCIP_Real growfac, int num)
Definition: misc.c:440
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:10300
void SCIPbtnodeSetRightchild(SCIP_BTNODE *node, SCIP_BTNODE *right)
Definition: misc.c:8857
#define DEFAULT_MWC
Definition: misc.c:9921
#define SCIP_RAND_MAX
Definition: misc.c:9838
void * SCIPptrarrayGetVal(SCIP_PTRARRAY *ptrarray, int idx)
Definition: misc.c:5315
#define FALSE
Definition: def.h:96
static SCIP_RETCODE hashtableInsert(SCIP_HASHTABLE *hashtable, void *element, void *key, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2359
#define GMLNODEWIDTH
Definition: misc.c:486
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3023
#define EPSEQ(x, y, eps)
Definition: def.h:211
static const SCIP_Real studentt_quartilesabove[]
Definition: misc.c:97
int SCIPboolarrayGetMaxIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5061
uint32_t mwc_seed
Definition: struct_misc.h:272
uint32_t mask
Definition: struct_misc.h:99
SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
Definition: misc.c:11072
void ** slots
Definition: struct_misc.h:151
int SCIPprofileGetEarliestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7051
#define SCIP_MULTIHASH_MAXSIZE
Definition: misc.c:1788
miscellaneous datastructures
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10764
void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
Definition: misc.c:10083
#define TRUE
Definition: def.h:95
SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
Definition: misc.c:3708
uint32_t cst_seed
Definition: struct_misc.h:273
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
SCIP_RETCODE SCIPdigraphSetSizes(SCIP_DIGRAPH *digraph, int *sizes)
Definition: misc.c:7455
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3141
void SCIPdigraphPrintComponents(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8534
SCIP_VAR * SCIPactivityGetVar(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6597
SCIP_RETCODE SCIPptrarrayExtend(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:5129
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1463
SCIP_RETCODE SCIPboolarrayCopy(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem, SCIP_BOOLARRAY *sourceboolarray)
Definition: misc.c:4736
SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3766
SCIP_Real SCIPregressionGetIntercept(SCIP_REGRESSION *regression)
Definition: misc.c:273
uint32_t nelements
Definition: struct_misc.h:100
void SCIPhashtableClear(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2347
SCIP_RETCODE SCIPcomputeArraysIntersection(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10446
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:125
void SCIPregressionAddObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:380
void SCIPswapReals(SCIP_Real *value1, SCIP_Real *value2)
Definition: misc.c:10287
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8195
static SCIP_MULTIHASHLIST * multihashlistFind(SCIP_MULTIHASHLIST *multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1647
SCIP_Bool SCIPstrToIntValue(const char *str, int *value, char **endptr)
Definition: misc.c:10834
#define SCIP_MULTIHASH_RESIZE_PERCENTAGE
Definition: misc.c:1789
void SCIPpqueueFree(SCIP_PQUEUE **pqueue)
Definition: misc.c:1272
SCIP_RETCODE SCIPprofileInsertCore(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:6931
#define SCIPdebugMessage
Definition: pub_message.h:96
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10012
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9728
#define DEFAULT_XOR
Definition: misc.c:9920
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:8208
SCIP_VAR ** vars
Definition: struct_misc.h:48
SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
Definition: misc.c:3472
int SCIPdisjointsetGetSize(SCIP_DISJOINTSET *djset)
Definition: misc.c:11264
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3210
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
#define SCIP_LONGINT_MAX
Definition: def.h:172
int SCIPptrarrayGetMinIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5404
SCIP_Bool SCIPqueueIsEmpty(SCIP_QUEUE *queue)
Definition: misc.c:1184
#define BMSfreeMemory(ptr)
Definition: memory.h:147
SCIP_Real SCIPnegateReal(SCIP_Real x)
Definition: misc.c:10262
void SCIPsortDown(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5988
void SCIPpqueueDelPos(SCIP_PQUEUE *pqueue, int pos)
Definition: misc.c:1383
static void queueCheckMarker(SCIP_QUEUE *queue)
Definition: misc.c:1015
SCIP_MULTIHASHLIST ** lists
Definition: struct_misc.h:117
template functions for sorting
int SCIPprofileGetLoad(SCIP_PROFILE *profile, int pos)
Definition: misc.c:6770
SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3250
void * dataptr
Definition: struct_misc.h:243
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10807
int SCIPhashsetGetNSlots(SCIP_HASHSET *hashset)
Definition: misc.c:3949
SCIP_VAR ** x
Definition: circlepacking.c:63
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8129
#define SCIP_MULTIHASH_GROW_FACTOR
Definition: misc.c:1790
int SCIPrealarrayGetMinIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4331
SCIP_Bool SCIPbtnodeIsRoot(SCIP_BTNODE *node)
Definition: misc.c:8756
real eps
void SCIPmultihashRemoveAll(SCIP_MULTIHASH *multihash)
Definition: misc.c:2160
unsigned int uinteger
Definition: struct_misc.h:56
SCIP_Real corrcoef
Definition: struct_misc.h:263
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:2245
SCIP_RETCODE SCIPboolarraySetVal(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Bool val)
Definition: misc.c:4983
SCIP_Real SCIPcalcRootNewton(SCIP_DECL_NEWTONEVAL((*function)), SCIP_DECL_NEWTONEVAL((*derivative)), SCIP_Real *params, int nparams, SCIP_Real x, SCIP_Real eps, int k)
Definition: misc.c:9769
#define SCIP_DEFAULT_EPSILON
Definition: def.h:192
BMS_BLKMEM * blkmem
Definition: struct_misc.h:139
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3372
void * userptr
Definition: struct_misc.h:95
SCIP_BTNODE * root
Definition: struct_misc.h:249
SCIP_Longint SCIPmultihashGetNElements(SCIP_MULTIHASH *multihash)
Definition: misc.c:2181
SCIP_Bool SCIPhashsetIsEmpty(SCIP_HASHSET *hashset)
Definition: misc.c:3933
SCIP_Bool SCIPfileExists(const char *filename)
Definition: misc.c:10967
void SCIPqueueClear(SCIP_QUEUE *queue)
Definition: misc.c:978
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:7657
int SCIPprofileGetCapacity(SCIP_PROFILE *profile)
Definition: misc.c:6718
SCIP_RETCODE SCIPintarrayFree(SCIP_INTARRAY **intarray)
Definition: misc.c:4394
int ** successors
Definition: struct_misc.h:222
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9304
void SCIPsortedvecInsertIntInt(int *intarray1, int *intarray2, int keyval, int field1val, int *len, int *pos)
SCIP_RETCODE SCIPrealarrayIncVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real incval)
Definition: misc.c:4313
void ** slots
Definition: struct_misc.h:83
SCIP_RETCODE SCIPactivityCreate(SCIP_RESOURCEACTIVITY **activity, SCIP_VAR *var, int duration, int demand)
Definition: misc.c:6552
void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:348
SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
Definition: misc.c:2791
SCIP_VAR * w
Definition: circlepacking.c:67
void SCIPsortDownInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
static const int studentt_maxdf
Definition: misc.c:102
SCIP_Real inf
Definition: intervalarith.h:55
void SCIPhashsetRemoveAll(SCIP_HASHSET *hashset)
Definition: misc.c:3965
SCIP_Real meany
Definition: struct_misc.h:259
#define SCIP_DECL_NEWTONEVAL(x)
Definition: type_misc.h:205
void SCIPdisjointsetClear(SCIP_DISJOINTSET *djset)
Definition: misc.c:11140
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:53
SCIP_Bool SCIPstrAtStart(const char *s, const char *t, size_t tlen)
Definition: misc.c:11274
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:464
SCIP_RETCODE SCIPrealarrayCopy(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem, SCIP_REALARRAY *sourcerealarray)
Definition: misc.c:3999
SCIP_Longint * SCIPsparseSolGetLbs(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:799
int SCIPqueueNElems(SCIP_QUEUE *queue)
Definition: misc.c:1197
SCIP_BTNODE * left
Definition: struct_misc.h:241
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:149
SCIP_Bool SCIPmultihashExists(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2099
SCIP_BTNODE * SCIPbtnodeGetParent(SCIP_BTNODE *node)
Definition: misc.c:8706
#define GMLNODEHEIGTH
Definition: misc.c:487
SCIP_RETCODE SCIPdigraphSetNSuccessors(SCIP_DIGRAPH *digraph, int node, int nsuccessors)
Definition: misc.c:7641
void SCIPmessagePrintError(const char *formatstr,...)
Definition: message.c:791
#define SCIPerrorMessage
Definition: pub_message.h:64
void SCIPhashmapPrintStatistics(SCIP_HASHMAP *hashmap, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3434
int SCIPactivityGetEnergy(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6627
interval arithmetics for provable bounds
#define SCIPdebugPrintf
Definition: pub_message.h:99
static SCIP_RETCODE multihashResize(SCIP_MULTIHASH *multihash)
Definition: misc.c:1794
int SCIPhashmapGetNEntries(SCIP_HASHMAP *hashmap)
Definition: misc.c:3490
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3498
void SCIPdisjointsetFree(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem)
Definition: misc.c:11235
#define GMLNODETYPE
Definition: misc.c:489
void SCIPbtnodeSetLeftchild(SCIP_BTNODE *node, SCIP_BTNODE *left)
Definition: misc.c:8843
SCIP_RETCODE SCIPboolarrayCreate(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4716
void * SCIPdigraphGetNodeData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7667
int * timepoints
Definition: struct_misc.h:211
uint32_t mask
Definition: struct_misc.h:143
SCIP_Real variancesumx
Definition: struct_misc.h:261
void SCIPhashsetFree(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3739
#define BMSmoveMemoryArray(ptr, source, num)
Definition: memory.h:140
Definition: pqueue.h:37
SCIP_Real SCIPrealarrayGetVal(SCIP_REALARRAY *realarray, int idx)
Definition: misc.c:4223
void SCIPdigraphSetNodeData(SCIP_DIGRAPH *digraph, void *dataptr, int node)
Definition: misc.c:7683
#define SQRTOFTWO
Definition: misc.c:60
void SCIPescapeString(char *t, int bufsize, const char *s)
Definition: misc.c:10736
void SCIPhashmapEntrySetImage(SCIP_HASHMAPENTRY *entry, void *image)
Definition: misc.c:3549
int SCIPintarrayGetMaxIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4705
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10895
SCIP_Real sizefac
Definition: struct_misc.h:80
SCIP_RETCODE SCIPdigraphCreate(SCIP_DIGRAPH **digraph, BMS_BLKMEM *blkmem, int nnodes)
Definition: misc.c:7288
SCIP_RETCODE SCIPmultihashSafeInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2015
static int profileFindFeasibleStart(SCIP_PROFILE *profile, int pos, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:6993
void SCIPcomputeArraysIntersectionInt(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10463
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3057
void SCIPdigraphPrint(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8460
#define BMSallocClearBlockMemoryArray(mem, ptr, num)
Definition: memory.h:457
internal miscellaneous methods
SCIP_RETCODE SCIPboolarrayClear(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:4931
#define NULL
Definition: lpi_spx1.cpp:164
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
Definition: misc.c:9996
SCIP_Longint * lbvalues
Definition: struct_misc.h:49
uint32_t shift
Definition: struct_misc.h:98
#define REALABS(x)
Definition: def.h:210
void SCIPactivityFree(SCIP_RESOURCEACTIVITY **activity)
Definition: misc.c:6571
void SCIPrandomSetSeed(SCIP_RANDNUMGEN *randnumgen, unsigned int initseed)
Definition: misc.c:9926
int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
Definition: misc.c:11157
#define DEFAULT_SEED
Definition: misc.c:9919
int narticulations
Definition: struct_misc.h:233
void SCIPgmlWriteEdge(FILE *file, unsigned int source, unsigned int target, const char *label, const char *color)
Definition: misc.c:594
int SCIPptrarrayGetMaxIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5414
#define SCIP_CALL(x)
Definition: def.h:393
#define SCIPhashTwo(a, b)
Definition: pub_misc.h:519
#define PQ_LEFTCHILD(p)
Definition: misc.c:1222
#define GMLNODEFILLCOLOR
Definition: misc.c:490
static SCIP_RETCODE profileUpdate(SCIP_PROFILE *profile, int left, int right, int demand, int *pos, SCIP_Bool *infeasible)
Definition: misc.c:6871
SCIP_VAR * h
Definition: circlepacking.c:68
unsigned int SCIPqueueRemoveUInt(SCIP_QUEUE *queue)
Definition: misc.c:1114
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:594
void SCIPhashtableRemoveAll(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2704
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2626
SCIP_RETCODE SCIPintarraySetVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int val)
Definition: misc.c:4615
SCIP_RETCODE SCIPprofileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6666
static SCIP_RETCODE ensureProfileSize(SCIP_PROFILE *profile, int neededsize)
Definition: misc.c:6807
SCIP_Real slope
Definition: struct_misc.h:257
void SCIPqueueFree(SCIP_QUEUE **queue)
Definition: misc.c:967
SCIP_RETCODE SCIPdigraphAddArc(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7573
SCIP_Bool SCIPbtnodeIsRightchild(SCIP_BTNODE *node)
Definition: misc.c:8794
SCIP_Real SCIPmultihashGetLoad(SCIP_MULTIHASH *multihash)
Definition: misc.c:2191
void * SCIPpqueueRemove(SCIP_PQUEUE *pqueue)
Definition: misc.c:1443
int SCIPdisjointsetGetComponentCount(SCIP_DISJOINTSET *djset)
Definition: misc.c:11254
SCIP_RETCODE SCIPgetRandomSubset(void **set, int nelems, void **subset, int nsubelems, unsigned int randseed)
Definition: misc.c:10384
uint32_t xor_seed
Definition: struct_misc.h:271
SCIP_Bool SCIPsortedvecFindInt(int *intarray, int val, int len, int *pos)
SCIP_BTNODE * SCIPbtGetRoot(SCIP_BT *tree)
Definition: misc.c:8979
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:145
SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3177
void SCIPregressionFree(SCIP_REGRESSION **regression)
Definition: misc.c:431
SCIP_RETCODE SCIPcomputeArraysSetminus(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10576
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:467
SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
Definition: misc.c:2819
static int getRand(unsigned int *seedp)
Definition: misc.c:9842
SCIP_Bool * vals
Definition: struct_misc.h:182
static SCIP_RETCODE pqueueResize(SCIP_PQUEUE *pqueue, int minsize)
Definition: misc.c:1228
int * components
Definition: struct_misc.h:227
void SCIPhashtablePrintStatistics(SCIP_HASHTABLE *hashtable, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2753
SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
Definition: misc.c:5429
#define PQ_PARENT(q)
Definition: misc.c:1221
SCIP_BTNODE * SCIPbtnodeGetRightchild(SCIP_BTNODE *node)
Definition: misc.c:8726
void SCIPintervalSetRoundingModeDownwards(void)
public data structures and miscellaneous methods
SCIP_RETCODE SCIPdigraphAddArcSafe(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7604
static const int primetablesize
Definition: misc.c:1575
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7715
#define SCIP_Bool
Definition: def.h:93
#define GMLFONTSIZE
Definition: misc.c:488
#define BMSallocBlockMemoryArray(mem, ptr, num)
Definition: memory.h:456
SCIP_Longint * SCIPsparseSolGetUbs(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:809
SCIP_Real variancesumy
Definition: struct_misc.h:262
void SCIPprintSysError(const char *message)
Definition: misc.c:10673
SCIP_RETCODE SCIPsparseSolCreate(SCIP_SPARSESOL **sparsesol, SCIP_VAR **vars, int nvars, SCIP_Bool cleared)
Definition: misc.c:713
SCIP_RETCODE SCIPhashmapRemoveAll(SCIP_HASHMAP *hashmap)
Definition: misc.c:3582
static const SCIP_Real studentt_quartiles[]
Definition: misc.c:76
#define ELEM_DISTANCE(pos)
Definition: misc.c:3603
SCIP_RETCODE SCIPmultihashInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:1974
static uint32_t randomGetRand(SCIP_RANDNUMGEN *randnumgen)
Definition: misc.c:9957
SCIP_Bool SCIPprofileFindLeft(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6784
SCIP_RETCODE SCIPrealarrayFree(SCIP_REALARRAY **realarray)
Definition: misc.c:4023
SCIP_RETCODE SCIPdigraphResize(SCIP_DIGRAPH *digraph, int nnodes)
Definition: misc.c:7325
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:469
unsigned int SCIPqueueFirstUInt(SCIP_QUEUE *queue)
Definition: misc.c:1166
void SCIPrandomPermuteIntArray(SCIP_RANDNUMGEN *randnumgen, int *array, int begin, int end)
Definition: misc.c:10053
static const SCIP_Real simplednoms[]
Definition: misc.c:9298
#define MAX(x, y)
Definition: tclique_def.h:92
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10865
static int getRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9853
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:7697
void SCIPbtFree(SCIP_BT **tree)
Definition: misc.c:8887
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2528
SCIP_Bool SCIPbtnodeIsLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8776
SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
Definition: misc.c:9274
#define DEFAULT_CST
Definition: misc.c:9922
SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
Definition: misc.c:8340
int SCIPboolarrayGetMinIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5051
void * SCIPmultihashRetrieveNext(SCIP_MULTIHASH *multihash, SCIP_MULTIHASHLIST **multihashlist, void *key)
Definition: misc.c:2063
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:122
int * successorssize
Definition: struct_misc.h:225
void ** SCIPpqueueElems(SCIP_PQUEUE *pqueue)
Definition: misc.c:1488
#define SCIP_DECL_PQUEUEELEMCHGPOS(x)
Definition: type_misc.h:208
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:136
void SCIPprofilePrint(SCIP_PROFILE *profile, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:6696
void SCIPgmlWriteNodeWeight(FILE *file, unsigned int id, const char *label, const char *nodetype, const char *fillcolor, const char *bordercolor, SCIP_Real weight)
Definition: misc.c:544
SCIP_Bool SCIPfindSimpleRational(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9681
int * articulations
Definition: struct_misc.h:229
SCIP_RETCODE SCIPdigraphGetArticulationPoints(SCIP_DIGRAPH *digraph, int **articulations, int *narticulations)
Definition: misc.c:7911
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2557
static SCIP_Real getRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9873
SCIP_Longint * ubvalues
Definition: struct_misc.h:50
static SCIP_Bool isIntegralScalar(SCIP_Real val, SCIP_Real scalar, SCIP_Real mindelta, SCIP_Real maxdelta)
Definition: misc.c:9439
#define BMSclearMemory(ptr)
Definition: memory.h:131
int * SCIPprofileGetTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6738
SCIP_Real sumxy
Definition: struct_misc.h:260
SCIP_VAR ** SCIPsparseSolGetVars(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:779
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:10034
int * SCIPprofileGetLoads(SCIP_PROFILE *profile)
Definition: misc.c:6748
static void depthFirstSearch(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *dfsstack, int *stackadjvisited, int *dfsnodes, int *ndfsnodes)
Definition: misc.c:7765
#define BMSallocClearMemoryArray(ptr, num)
Definition: memory.h:127
static void incrementalStatsUpdate(SCIP_Real value, SCIP_Real *meanptr, SCIP_Real *sumvarptr, int nobservations, SCIP_Bool add)
Definition: misc.c:322
int SCIPgetRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9895
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2295
SCIP_Bool SCIPbtIsEmpty(SCIP_BT *tree)
Definition: misc.c:8969
SCIP_RETCODE SCIPptrarrayClear(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5284
#define GMLEDGECOLOR
Definition: misc.c:491
uint32_t nelements
Definition: struct_misc.h:153
static void tarjan(SCIP_DIGRAPH *digraph, int v, int *lowlink, int *dfsidx, int *stack, int *stacksize, SCIP_Bool *unprocessed, SCIP_Bool *nodeinstack, int *maxdfs, int *strongcomponents, int *nstrongcomponents, int *strongcompstartidx, int *nstorednodes)
Definition: misc.c:8231
#define SCIP_REAL_MAX
Definition: def.h:187
SCIP_Real SCIPgetRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9908
static SCIP_RETCODE queueCheckSize(SCIP_QUEUE *queue)
Definition: misc.c:990
SCIP_BTNODE * SCIPbtnodeGetLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8716
SCIP_Bool articulationscheck
Definition: struct_misc.h:234
static uint32_t hashvalue(uint64_t input)
Definition: misc.c:1579
SCIP_RETCODE SCIPpqueueCreate(SCIP_PQUEUE **pqueue, int initsize, SCIP_Real sizefac, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), SCIP_DECL_PQUEUEELEMCHGPOS((*elemchgpos)))
Definition: misc.c:1245
SCIP_Real * r
Definition: circlepacking.c:59
#define EPSGT(x, y, eps)
Definition: def.h:214
#define SCIP_DECL_SORTINDCOMP(x)
Definition: type_misc.h:180
int SCIPsparseSolGetNVars(SCIP_SPARSESOL *sparsesol)
Definition: misc.c:789
SCIP_Real meanx
Definition: struct_misc.h:258
SCIP_VAR ** b
Definition: circlepacking.c:65
void SCIPbtSetRoot(SCIP_BT *tree, SCIP_BTNODE *root)
Definition: misc.c:8992
SCIP_RETCODE SCIPhashmapSetImageReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3340
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3388
int SCIPpqueueFind(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1499
void SCIPbtnodeSetParent(SCIP_BTNODE *node, SCIP_BTNODE *parent)
Definition: misc.c:8829
int SCIPhashmapGetNElements(SCIP_HASHMAP *hashmap)
Definition: misc.c:3482
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:105
void SCIPsort(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5449
SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
Definition: misc.c:943
SCIP_RETCODE SCIPptrarrayFree(SCIP_PTRARRAY **ptrarray)
Definition: misc.c:5115
#define GMLNODEBORDERCOLOR
Definition: misc.c:492
SCIP_RETCODE SCIPpqueueInsert(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1344
static SCIP_RETCODE hashsetCheckLoad(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem)
Definition: misc.c:3667
SCIP_Real SCIPcalcMachineEpsilon(void)
Definition: misc.c:9008
SCIP_Real SCIPhashmapEntryGetImageReal(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3539
void * SCIPmultihashRetrieve(SCIP_MULTIHASH *multihash, void *key)
Definition: misc.c:2034
SCIP_HASHMAPTYPE hashmaptype
Definition: struct_misc.h:145
SCIP_RETCODE SCIPintarrayExtend(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4408
SCIP_RETCODE SCIPptrarraySetVal(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, void *val)
Definition: misc.c:5336
SCIP_HASHMAPENTRY * slots
Definition: struct_misc.h:140
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:195
SCIP_Real SCIPregressionGetSlope(SCIP_REGRESSION *regression)
Definition: misc.c:263
static int profileFindDownFeasibleStart(SCIP_PROFILE *profile, int pos, int ect, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7143
int SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6607
SCIP_BTNODE * right
Definition: struct_misc.h:242
SCIP_RETCODE SCIPdigraphCopy(SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph, BMS_BLKMEM *targetblkmem)
Definition: misc.c:7365
SCIP_RETCODE SCIPboolarrayFree(SCIP_BOOLARRAY **boolarray)
Definition: misc.c:4760
public methods for message output
SCIP_RETCODE SCIPqueueInsertUInt(SCIP_QUEUE *queue, unsigned int elem)
Definition: misc.c:1055
SCIP_VAR * a
Definition: circlepacking.c:66
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:618
void SCIPhashsetPrintStatistics(SCIP_HASHSET *hashset, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:3882
static const SCIP_Real scalars[]
Definition: misc.c:9461
SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:3749
SCIP_Bool SCIPintervalHasRoundingControl(void)
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3272
static SCIP_RETCODE profileInsertTimepoint(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6830
#define SCIP_Real
Definition: def.h:186
void SCIPmultihashPrintStatistics(SCIP_MULTIHASH *multihash, SCIP_MESSAGEHDLR *messagehdlr)
Definition: misc.c:2201
void SCIPpermuteIntArray(int *array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10316
int componentstartsize
Definition: struct_misc.h:231
uint32_t nelements
Definition: struct_misc.h:144
BMS_BLKMEM * blkmem
Definition: struct_misc.h:116
#define SCIP_CALL_TERMINATE(retcode, x, TERM)
Definition: def.h:414
SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4037
SCIP_VAR ** y
Definition: circlepacking.c:64
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:9980
SCIP_RETCODE SCIPrandomGetSubset(SCIP_RANDNUMGEN *randnumgen, void **set, int nelems, void **subset, int nsubelems)
Definition: misc.c:10115
SCIP_Longint SCIPcalcBinomCoef(int n, int m)
Definition: misc.c:10176
#define BMSallocMemory(ptr)
Definition: memory.h:120
#define SCIP_INVALID
Definition: def.h:206
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:129
int SCIPhashmapEntryGetImageInt(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3529
static int primetable[]
Definition: misc.c:1523
static void hashsetInsert(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3616
int SCIPhashtableGetNEntries(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2726
static void multihashlistFree(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem)
Definition: misc.c:1623
static void btnodeFreeLeaf(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8610
#define SCIP_Longint
Definition: def.h:171
SCIP_RETCODE SCIPcalcIntegralScalar(SCIP_Real *vals, int nvals, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Real *intscalar, SCIP_Bool *success)
Definition: misc.c:9467
static void btPrintSubtree(SCIP_BTNODE *node, FILE *file, int *nnodes)
Definition: misc.c:8903
void SCIPregressionReset(SCIP_REGRESSION *regression)
Definition: misc.c:399
SCIP_RETCODE SCIPdisjointsetCreate(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem, int ncomponents)
Definition: misc.c:11117
SCIP_RETCODE SCIPrealarraySetVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real val)
Definition: misc.c:4244
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2608
void * SCIPqueueRemove(SCIP_QUEUE *queue)
Definition: misc.c:1080
SCIP_RETCODE SCIPintarrayClear(SCIP_INTARRAY *intarray)
Definition: misc.c:4563
unsigned int SCIPcalcFibHash(SCIP_Real v)
Definition: misc.c:10251
void ** vals
Definition: struct_misc.h:193
SCIP_RETCODE SCIPmultihashRemove(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2126
#define STARTSUCCESSORSSIZE
Definition: misc.c:7522
#define nnodes
Definition: gastrans.c:74
int SCIPprofileGetLatestFeasibleStart(SCIP_PROFILE *profile, int est, int lst, int duration, int demand, SCIP_Bool *infeasible)
Definition: misc.c:7200
SCIP_MULTIHASHLIST * next
Definition: struct_misc.h:107
void SCIPgmlWriteOpening(FILE *file, SCIP_Bool directed)
Definition: misc.c:682
int SCIPcalcMultihashSize(int minsize)
Definition: misc.c:1587
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:453
SCIP_RETCODE SCIPregressionCreate(SCIP_REGRESSION **regression)
Definition: misc.c:415
SCIP_RETCODE SCIPboolarrayExtend(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4774
static void pqueueElemChgPos(SCIP_PQUEUE *pqueue, void *elem, int oldpos, int newpos)
Definition: misc.c:1294
int * nsuccessors
Definition: struct_misc.h:226
#define EPSFLOOR(x, eps)
Definition: def.h:219
SCIP_Longint nelements
Definition: struct_misc.h:120
SCIP_Real sizefac
Definition: struct_misc.h:62
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3105
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:132
SCIP_Real SCIPhashtableGetLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2743
common defines and data types used in all packages of SCIP
void * SCIPqueueFirst(SCIP_QUEUE *queue)
Definition: misc.c:1148
void SCIPswapInts(int *value1, int *value2)
Definition: misc.c:10274
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:439
SCIP_RETCODE SCIPbtCreate(SCIP_BT **tree, BMS_BLKMEM *blkmem)
Definition: misc.c:8868
#define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
Definition: def.h:424
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3230
static SCIP_RETCODE queueResize(SCIP_QUEUE *queue, int minsize)
Definition: misc.c:924
#define SCIP_CALL_ABORT(x)
Definition: def.h:372
void SCIPcomputeArraysIntersectionPtr(void **array1, int narray1, void **array2, int narray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void **intersectarray, int *nintersectarray)
Definition: misc.c:10516
static void findArticulationPointsUtil(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *tdisc, int *mindisc, int *parent, SCIP_Bool *articulationflag, int time)
Definition: misc.c:7844
int SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6617
void SCIPbtnodeSetData(SCIP_BTNODE *node, void *dataptr)
Definition: misc.c:8815
static void * multihashlistRetrieve(SCIP_MULTIHASHLIST *multihashlist, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr, uint64_t keyval, void *key)
Definition: misc.c:1678
SCIP_RETCODE SCIPptrarrayCreate(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem)
Definition: misc.c:5072
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
Definition: misc.c:7479
int SCIPprofileGetNTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6728
void SCIPpqueueClear(SCIP_PQUEUE *pqueue)
Definition: misc.c:1283
int SCIPregressionGetNObservations(SCIP_REGRESSION *regression)
Definition: misc.c:253
#define SCIP_ALLOC(x)
Definition: def.h:404
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10722
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9031
void SCIPdigraphPrintGml(SCIP_DIGRAPH *digraph, FILE *file)
Definition: misc.c:8495
SCIP_HASHMAPIMAGE image
Definition: struct_misc.h:133
SCIP_RETCODE SCIPintarrayCreate(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4351
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:460
void SCIPbtPrintGml(SCIP_BT *tree, FILE *file)
Definition: misc.c:8939
SCIP_Longint SCIPhashtableGetNElements(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2716
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9283
#define EPSZ(x, eps)
Definition: def.h:216
int firstused
Definition: struct_misc.h:65
SCIP_RETCODE SCIPptrarrayCopy(SCIP_PTRARRAY **ptrarray, BMS_BLKMEM *blkmem, SCIP_PTRARRAY *sourceptrarray)
Definition: misc.c:5092
#define PQ_RIGHTCHILD(p)
Definition: misc.c:1223
SCIP_Bool SCIPbtnodeIsLeaf(SCIP_BTNODE *node)
Definition: misc.c:8766
void SCIPsparseSolFree(SCIP_SPARSESOL **sparsesol)
Definition: misc.c:765
SCIP_Real SCIPcomputeGap(SCIP_Real eps, SCIP_Real inf, SCIP_Real primalbound, SCIP_Real dualbound)
Definition: misc.c:11090
void SCIPprofileFree(SCIP_PROFILE **profile)
Definition: misc.c:6680
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:4192