Scippy

SCIP

Solving Constraint Integer Programs

misc.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB) */
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  SCIP_UNUSED(sumslotsize);
2236 
2237  SCIPmessagePrintInfo(messagehdlr, "%" SCIP_LONGINT_FORMAT " multihash entries, used %d/%d slots (%.1f%%)",
2238  multihash->nelements, usedslots, multihash->nlists, 100.0*(SCIP_Real)usedslots/(SCIP_Real)(multihash->nlists));
2239  if( usedslots > 0 )
2240  SCIPmessagePrintInfo(messagehdlr, ", avg. %.1f entries/used slot, max. %d entries in slot",
2241  (SCIP_Real)(multihash->nelements)/(SCIP_Real)usedslots, maxslotsize);
2242  SCIPmessagePrintInfo(messagehdlr, "\n");
2243 }
2244 
2245 /** creates a hash table */
2247  SCIP_HASHTABLE** hashtable, /**< pointer to store the created hash table */
2248  BMS_BLKMEM* blkmem, /**< block memory used to store hash table entries */
2249  int tablesize, /**< size of the hash table */
2250  SCIP_DECL_HASHGETKEY((*hashgetkey)), /**< gets the key of the given element */
2251  SCIP_DECL_HASHKEYEQ ((*hashkeyeq)), /**< returns TRUE iff both keys are equal */
2252  SCIP_DECL_HASHKEYVAL((*hashkeyval)), /**< returns the hash value of the key */
2253  void* userptr /**< user pointer */
2254  )
2255 {
2256  unsigned int nslots;
2257 
2258  /* only assert non negative to catch overflow errors
2259  * but not zeros due to integer divison
2260  */
2261  assert(tablesize >= 0);
2262  assert(hashtable != NULL);
2263  assert(hashgetkey != NULL);
2264  assert(hashkeyeq != NULL);
2265  assert(hashkeyval != NULL);
2266  assert(blkmem != NULL);
2267 
2268  SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashtable) );
2269 
2270  /* dont create too small hashtables, i.e. at least size 32, and increase
2271  * the given size by divinding it by 0.9, since then no rebuilding will
2272  * be necessary if the given number of elements are inserted. Finally round
2273  * to the next power of two.
2274  */
2275  (*hashtable)->shift = 32;
2276  (*hashtable)->shift -= (unsigned int)ceil(LOG2(MAX(32.0, tablesize / 0.9)));
2277 
2278  /* compute size from shift */
2279  nslots = 1u << (32 - (*hashtable)->shift);
2280 
2281  /* compute mask to do a fast modulo by nslots using bitwise and */
2282  (*hashtable)->mask = nslots - 1;
2283  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*hashtable)->slots, nslots) );
2284  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashtable)->hashes, nslots) );
2285  (*hashtable)->blkmem = blkmem;
2286  (*hashtable)->hashgetkey = hashgetkey;
2287  (*hashtable)->hashkeyeq = hashkeyeq;
2288  (*hashtable)->hashkeyval = hashkeyval;
2289  (*hashtable)->userptr = userptr;
2290  (*hashtable)->nelements = 0;
2291 
2292  return SCIP_OKAY;
2293 }
2294 
2295 /** frees the hash table */
2297  SCIP_HASHTABLE** hashtable /**< pointer to the hash table */
2298  )
2299 {
2300  uint32_t nslots;
2301  SCIP_HASHTABLE* table;
2302 
2303  assert(hashtable != NULL);
2304  assert(*hashtable != NULL);
2305  table = *hashtable;
2306  nslots = (*hashtable)->mask + 1;
2307 #ifdef SCIP_DEBUG
2308  {
2309  uint32_t maxprobelen = 0;
2310  uint64_t probelensum = 0;
2311  uint32_t i;
2312 
2313  assert(table != NULL);
2314 
2315  for( i = 0; i < nslots; ++i )
2316  {
2317  if( table->hashes[i] != 0 )
2318  {
2319  uint32_t probelen = ((i + table->mask + 1 - (table->hashes[i]>>(table->shift))) & table->mask) + 1;
2320  probelensum += probelen;
2321  maxprobelen = MAX(probelen, maxprobelen);
2322  }
2323  }
2324 
2325  SCIPdebugMessage("%u hash table entries, used %u/%u slots (%.1f%%)",
2326  (unsigned int)table->nelements, (unsigned int)table->nelements, (unsigned int)nslots,
2327  100.0*(SCIP_Real)table->nelements/(SCIP_Real)(nslots));
2328  if( table->nelements > 0 )
2329  SCIPdebugMessage(", avg. probe length is %.1f, max. probe length is %u",
2330  (SCIP_Real)(probelensum)/(SCIP_Real)table->nelements, (unsigned int)maxprobelen);
2331  SCIPdebugMessage("\n");
2332  }
2333 #endif
2334 
2335  /* free main hash table data structure */
2336  BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->hashes, nslots);
2337  BMSfreeBlockMemoryArray((*hashtable)->blkmem, &table->slots, nslots);
2338  BMSfreeBlockMemory((*hashtable)->blkmem, hashtable);
2339 }
2340 
2341 /** removes all elements of the hash table
2342  *
2343  * @note From a performance point of view you should not fill and clear a hash table too often since the clearing can
2344  * be expensive. Clearing is done by looping over all buckets and removing the hash table lists one-by-one.
2345  *
2346  * @deprecated Please use SCIPhashtableRemoveAll()
2347  */
2349  SCIP_HASHTABLE* hashtable /**< hash table */
2350  )
2351 {
2352  SCIPhashtableRemoveAll(hashtable);
2353 }
2354 
2355 /* computes the distance from it's desired position for the element stored at pos */
2356 #define ELEM_DISTANCE(pos) (((pos) + hashtable->mask + 1 - (hashtable->hashes[(pos)]>>(hashtable->shift))) & hashtable->mask)
2357 
2358 /** inserts element in hash table (multiple inserts of same element overrides previous one) */
2359 static
2361  SCIP_HASHTABLE* hashtable, /**< hash table */
2362  void* element, /**< element to insert into the table */
2363  void* key, /**< key of element */
2364  uint32_t hashval, /**< hash value of element */
2365  SCIP_Bool override /**< should element be overridden or an error be returned if already existing */
2366  )
2367 {
2368  uint32_t elemdistance;
2369  uint32_t pos;
2370 #ifndef NDEBUG
2371  SCIP_Bool swapped = FALSE;
2372 #endif
2373 
2374  assert(hashtable != NULL);
2375  assert(hashtable->slots != NULL);
2376  assert(hashtable->hashes != NULL);
2377  assert(hashtable->mask > 0);
2378  assert(hashtable->hashgetkey != NULL);
2379  assert(hashtable->hashkeyeq != NULL);
2380  assert(hashtable->hashkeyval != NULL);
2381  assert(element != NULL);
2382 
2383  pos = hashval>>(hashtable->shift);
2384  elemdistance = 0;
2385  while( TRUE ) /*lint !e716*/
2386  {
2387  uint32_t distance;
2388 
2389  /* if position is empty or key equal insert element */
2390  if( hashtable->hashes[pos] == 0 )
2391  {
2392  hashtable->slots[pos] = element;
2393  hashtable->hashes[pos] = hashval;
2394  ++hashtable->nelements;
2395  return SCIP_OKAY;
2396  }
2397 
2398  if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2399  hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2400  {
2401  if( override )
2402  {
2403 #ifndef NDEBUG
2404  assert(! swapped);
2405 #endif
2406  hashtable->slots[pos] = element;
2407  hashtable->hashes[pos] = hashval;
2408  return SCIP_OKAY;
2409  }
2410  else
2411  {
2412  return SCIP_KEYALREADYEXISTING;
2413  }
2414  }
2415 
2416  /* otherwise check if the current element at this position is closer to its hashvalue */
2417  distance = ELEM_DISTANCE(pos);
2418  if( distance < elemdistance )
2419  {
2420  uint32_t tmp;
2421 
2422  /* if this is the case we insert the new element here and find a new position for the old one */
2423  elemdistance = distance;
2424  SCIPswapPointers(&hashtable->slots[pos], &element);
2425  tmp = hashval;
2426  hashval = hashtable->hashes[pos];
2427  hashtable->hashes[pos] = tmp;
2428  key = hashtable->hashgetkey(hashtable->userptr, element);
2429 
2430  /* after doing a swap the case that other elements are replaced must not happen anymore */
2431 #ifndef NDEBUG
2432  swapped = TRUE;
2433 #endif
2434  }
2435 
2436  /* continue until we have found an empty position */
2437  pos = (pos + 1) & hashtable->mask;
2438  ++elemdistance;
2439  }
2440 }
2441 
2442 /** check if the load factor of the hashtable is too high and rebuild if necessary */
2443 static
2445  SCIP_HASHTABLE* hashtable /**< hash table */
2446  )
2447 {
2448  assert(hashtable != NULL);
2449  assert(hashtable->shift < 32);
2450 
2451  /* use integer arithmetic to approximately check if load factor is above 90% */
2452  if( ((((uint64_t)hashtable->nelements)<<10)>>(32-hashtable->shift) > 921) )
2453  {
2454  void** slots;
2455  uint32_t* hashes;
2456  uint32_t nslots;
2457  uint32_t newnslots;
2458  uint32_t i;
2459 
2460  /* calculate new size (always power of two) */
2461  nslots = hashtable->mask + 1;
2462  newnslots = 2*nslots;
2463  hashtable->mask = newnslots-1;
2464  --hashtable->shift;
2465 
2466  /* reallocate array */
2467  SCIP_ALLOC( BMSallocBlockMemoryArray(hashtable->blkmem, &slots, newnslots) );
2468  SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashtable->blkmem, &hashes, newnslots) );
2469 
2470  SCIPswapPointers((void**) &slots, (void**) &hashtable->slots);
2471  SCIPswapPointers((void**) &hashes, (void**) &hashtable->hashes);
2472  hashtable->nelements = 0;
2473 
2474  /* reinsert all elements */
2475  for( i = 0; i < nslots; ++i )
2476  {
2477  /* using SCIP_CALL_ABORT since there are no allocations or duplicates
2478  * and thus no bad return codes when inserting the elements
2479  */
2480  if( hashes[i] != 0 )
2481  {
2482  SCIP_CALL_ABORT( hashtableInsert(hashtable, slots[i], hashtable->hashgetkey(hashtable->userptr, slots[i]), hashes[i], FALSE) );
2483  }
2484  }
2485  BMSfreeBlockMemoryArray(hashtable->blkmem, &hashes, nslots);
2486  BMSfreeBlockMemoryArray(hashtable->blkmem, &slots, nslots);
2487  }
2488 
2489  return SCIP_OKAY;
2490 }
2491 
2492 
2493 /** inserts element in hash table
2494  *
2495  * @note multiple inserts of same element overrides previous one
2496  */
2498  SCIP_HASHTABLE* hashtable, /**< hash table */
2499  void* element /**< element to insert into the table */
2500  )
2501 {
2502  void* key;
2503  uint64_t keyval;
2504  uint32_t hashval;
2505 
2506  assert(hashtable != NULL);
2507  assert(hashtable->slots != NULL);
2508  assert(hashtable->hashes != NULL);
2509  assert(hashtable->mask > 0);
2510  assert(hashtable->hashgetkey != NULL);
2511  assert(hashtable->hashkeyeq != NULL);
2512  assert(hashtable->hashkeyval != NULL);
2513  assert(element != NULL);
2514 
2515  SCIP_CALL( hashtableCheckLoad(hashtable) );
2516 
2517  /* get the hash key and its hash value */
2518  key = hashtable->hashgetkey(hashtable->userptr, element);
2519  keyval = hashtable->hashkeyval(hashtable->userptr, key);
2520  hashval = hashvalue(keyval);
2521 
2522  return hashtableInsert(hashtable, element, key, hashval, TRUE);
2523 }
2524 
2525 /** inserts element in hash table
2526  *
2527  * @note multiple insertion of same element is checked and results in an error
2528  */
2530  SCIP_HASHTABLE* hashtable, /**< hash table */
2531  void* element /**< element to insert into the table */
2532  )
2533 {
2534  void* key;
2535  uint64_t keyval;
2536  uint32_t hashval;
2537 
2538  assert(hashtable != NULL);
2539  assert(hashtable->slots != NULL);
2540  assert(hashtable->hashes != NULL);
2541  assert(hashtable->mask > 0);
2542  assert(hashtable->hashgetkey != NULL);
2543  assert(hashtable->hashkeyeq != NULL);
2544  assert(hashtable->hashkeyval != NULL);
2545  assert(element != NULL);
2546 
2547  SCIP_CALL( hashtableCheckLoad(hashtable) );
2548 
2549  /* get the hash key and its hash value */
2550  key = hashtable->hashgetkey(hashtable->userptr, element);
2551  keyval = hashtable->hashkeyval(hashtable->userptr, key);
2552  hashval = hashvalue(keyval);
2553 
2554  return hashtableInsert(hashtable, element, key, hashval, FALSE);
2555 }
2556 
2557 /** retrieve element with key from hash table, returns NULL if not existing */
2559  SCIP_HASHTABLE* hashtable, /**< hash table */
2560  void* key /**< key to retrieve */
2561  )
2562 {
2563  uint64_t keyval;
2564  uint32_t hashval;
2565  uint32_t pos;
2566  uint32_t elemdistance;
2567 
2568  assert(hashtable != NULL);
2569  assert(hashtable->slots != NULL);
2570  assert(hashtable->hashes != NULL);
2571  assert(hashtable->mask > 0);
2572  assert(hashtable->hashgetkey != NULL);
2573  assert(hashtable->hashkeyeq != NULL);
2574  assert(hashtable->hashkeyval != NULL);
2575  assert(key != NULL);
2576 
2577  /* get the hash value of the key */
2578  keyval = hashtable->hashkeyval(hashtable->userptr, key);
2579  hashval = hashvalue(keyval);
2580 
2581  pos = hashval>>(hashtable->shift);
2582  elemdistance = 0;
2583 
2584  while( TRUE ) /*lint !e716*/
2585  {
2586  uint32_t distance;
2587 
2588  /* slots is empty so element cannot be contained */
2589  if( hashtable->hashes[pos] == 0 )
2590  return NULL;
2591 
2592  distance = ELEM_DISTANCE(pos);
2593 
2594  /* element cannot be contained since otherwise we would have swapped it with this one during insert */
2595  if( elemdistance > distance )
2596  return NULL;
2597 
2598  /* found element */
2599  if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2600  hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2601  return hashtable->slots[pos];
2602 
2603  pos = (pos + 1) & hashtable->mask;
2604  ++elemdistance;
2605  }
2606 }
2607 
2608 /** returns whether the given element exists in the table */
2610  SCIP_HASHTABLE* hashtable, /**< hash table */
2611  void* element /**< element to search in the table */
2612  )
2613 {
2614  assert(hashtable != NULL);
2615  assert(hashtable->slots != NULL);
2616  assert(hashtable->hashes != NULL);
2617  assert(hashtable->mask > 0);
2618  assert(hashtable->hashgetkey != NULL);
2619  assert(hashtable->hashkeyeq != NULL);
2620  assert(hashtable->hashkeyval != NULL);
2621  assert(element != NULL);
2622 
2623  return (SCIPhashtableRetrieve(hashtable, hashtable->hashgetkey(hashtable->userptr, element)) != NULL);
2624 }
2625 
2626 /** removes element from the hash table, if it exists */
2628  SCIP_HASHTABLE* hashtable, /**< hash table */
2629  void* element /**< element to remove from the table */
2630  )
2631 {
2632  void* key;
2633  uint64_t keyval;
2634  uint32_t hashval;
2635  uint32_t elemdistance;
2636  uint32_t distance;
2637  uint32_t pos;
2638 
2639  assert(hashtable != NULL);
2640  assert(hashtable->slots != NULL);
2641  assert(hashtable->hashes != NULL);
2642  assert(hashtable->mask > 0);
2643  assert(hashtable->hashgetkey != NULL);
2644  assert(hashtable->hashkeyeq != NULL);
2645  assert(hashtable->hashkeyval != NULL);
2646  assert(element != NULL);
2647 
2648  /* get the hash key and its hash value */
2649  key = hashtable->hashgetkey(hashtable->userptr, element);
2650  keyval = hashtable->hashkeyval(hashtable->userptr, key);
2651  hashval = hashvalue(keyval);
2652 
2653  elemdistance = 0;
2654  pos = hashval>>(hashtable->shift);
2655  while( TRUE ) /*lint !e716*/
2656  {
2657  /* slots empty so element not contained */
2658  if( hashtable->hashes[pos] == 0 )
2659  return SCIP_OKAY;
2660 
2661  distance = ELEM_DISTANCE(pos);
2662 
2663  /* element can not be contained since otherwise we would have swapped it with this one */
2664  if( elemdistance > distance )
2665  return SCIP_OKAY;
2666 
2667  if( hashtable->hashes[pos] == hashval && hashtable->hashkeyeq(hashtable->userptr,
2668  hashtable->hashgetkey(hashtable->userptr, hashtable->slots[pos]), key) )
2669  {
2670  /* element exists at pos so break out of loop */
2671  break;
2672  }
2673 
2674  pos = (pos + 1) & hashtable->mask;
2675  ++elemdistance;
2676  }
2677 
2678  /* remove element */
2679  hashtable->hashes[pos] = 0;
2680  --hashtable->nelements;
2681  while( TRUE ) /*lint !e716*/
2682  {
2683  uint32_t nextpos = (pos + 1) & hashtable->mask;
2684 
2685  /* nothing to do since there is no chain that needs to be moved */
2686  if( hashtable->hashes[nextpos] == 0 )
2687  break;
2688 
2689  /* check if the element is the start of a new chain and return if that is the case */
2690  if( (hashtable->hashes[nextpos]>>(hashtable->shift)) == nextpos )
2691  break;
2692 
2693  /* element should be moved to the left and next element needs to be checked */
2694  hashtable->slots[pos] = hashtable->slots[nextpos];
2695  hashtable->hashes[pos] = hashtable->hashes[nextpos];
2696  hashtable->hashes[nextpos] = 0;
2697 
2698  pos = nextpos;
2699  }
2700 
2701  return SCIP_OKAY;
2702 }
2703 
2704 /** removes all elements of the hash table */
2706  SCIP_HASHTABLE* hashtable /**< hash table */
2707  )
2708 {
2709  assert(hashtable != NULL);
2710 
2711  BMSclearMemoryArray(hashtable->hashes, hashtable->mask + 1);
2712 
2713  hashtable->nelements = 0;
2714 }
2715 
2716 /** returns number of hash table elements */
2718  SCIP_HASHTABLE* hashtable /**< hash table */
2719  )
2720 {
2721  assert(hashtable != NULL);
2722 
2723  return hashtable->nelements;
2724 }
2725 
2726 /** gives the number of entries in the internal arrays of a hash table */
2728  SCIP_HASHTABLE* hashtable /**< hash table */
2729  )
2730 {
2731  return (int) hashtable->mask + 1;
2732 }
2733 
2734 /** gives the element at the given index or NULL if entry at that index has no element */
2736  SCIP_HASHTABLE* hashtable, /**< hash table */
2737  int entryidx /**< index of hash table entry */
2738  )
2739 {
2740  return hashtable->hashes[entryidx] == 0 ? NULL : hashtable->slots[entryidx];
2741 }
2742 
2743 /** returns the load of the given hash table in percentage */
2745  SCIP_HASHTABLE* hashtable /**< hash table */
2746  )
2747 {
2748  assert(hashtable != NULL);
2749 
2750  return ((SCIP_Real)(hashtable->nelements) / (hashtable->mask + 1) * 100.0);
2751 }
2752 
2753 /** prints statistics about hash table usage */
2755  SCIP_HASHTABLE* hashtable, /**< hash table */
2756  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
2757  )
2758 {
2759  uint32_t maxprobelen = 0;
2760  uint64_t probelensum = 0;
2761  uint32_t nslots;
2762  uint32_t i;
2763 
2764  assert(hashtable != NULL);
2765 
2766  nslots = hashtable->mask + 1;
2767 
2768  /* compute the maximum and average probe length */
2769  for( i = 0; i < nslots; ++i )
2770  {
2771  if( hashtable->hashes[i] != 0 )
2772  {
2773  uint32_t probelen = ELEM_DISTANCE(i) + 1;
2774  probelensum += probelen;
2775  maxprobelen = MAX(probelen, maxprobelen);
2776  }
2777  }
2778 
2779  /* print general hash table statistics */
2780  SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
2781  (unsigned int)hashtable->nelements, (unsigned int)hashtable->nelements,
2782  (unsigned int)nslots, 100.0*(SCIP_Real)hashtable->nelements/(SCIP_Real)(nslots));
2783 
2784  /* if not empty print average and maximum probe length */
2785  if( hashtable->nelements > 0 )
2786  SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
2787  (SCIP_Real)(probelensum)/(SCIP_Real)hashtable->nelements, (unsigned int)maxprobelen);
2788  SCIPmessagePrintInfo(messagehdlr, "\n");
2789 }
2790 
2791 /** returns TRUE iff both keys (i.e. strings) are equal */
2792 SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
2793 { /*lint --e{715}*/
2794  const char* string1 = (const char*)key1;
2795  const char* string2 = (const char*)key2;
2796 
2797  return (strcmp(string1, string2) == 0);
2798 }
2799 
2800 /** returns the hash value of the key (i.e. string) */
2801 SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
2802 { /*lint --e{715}*/
2803  const char* str;
2804  uint64_t hash;
2805 
2806  str = (const char*)key;
2807  hash = 37;
2808  while( *str != '\0' )
2809  {
2810  hash *= 11;
2811  hash += (unsigned int)(*str); /*lint !e571*/
2812  str++;
2813  }
2814 
2815  return hash;
2816 }
2817 
2818 
2819 /** gets the element as the key */
2820 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
2821 { /*lint --e{715}*/
2822  /* the key is the element itself */
2823  return elem;
2824 }
2825 
2826 /** returns TRUE iff both keys(pointer) are equal */
2827 SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqPtr)
2828 { /*lint --e{715}*/
2829  return (key1 == key2);
2830 }
2831 
2832 /** returns the hash value of the key */
2833 SCIP_DECL_HASHKEYVAL(SCIPhashKeyValPtr)
2834 { /*lint --e{715}*/
2835  /* the key is used as the keyvalue too */
2836  return (uint64_t) (uintptr_t) key;
2837 }
2838 
2839 
2840 
2841 /*
2842  * Hash Map
2843  */
2844 
2845 /* redefine ELEM_DISTANCE macro for hashmap */
2846 #undef ELEM_DISTANCE
2847 /* computes the distance from it's desired position for the element stored at pos */
2848 #define ELEM_DISTANCE(pos) (((pos) + hashmap->mask + 1 - (hashmap->hashes[(pos)]>>(hashmap->shift))) & hashmap->mask)
2849 
2850 /** inserts element in hash table */
2851 static
2853  SCIP_HASHMAP* hashmap, /**< hash map */
2854  void* origin, /**< element to insert into the table */
2855  SCIP_HASHMAPIMAGE image, /**< key of element */
2856  uint32_t hashval, /**< hash value of element */
2857  SCIP_Bool override /**< should element be overridden or error be returned if already existing */
2858  )
2859 {
2860  uint32_t elemdistance;
2861  uint32_t pos;
2862 
2863  assert(hashmap != NULL);
2864  assert(hashmap->slots != NULL);
2865  assert(hashmap->hashes != NULL);
2866  assert(hashmap->mask > 0);
2867  assert(hashval != 0);
2868 
2869  pos = hashval>>(hashmap->shift);
2870  elemdistance = 0;
2871  while( TRUE ) /*lint !e716*/
2872  {
2873  uint32_t distance;
2874 
2875  /* if position is empty or key equal insert element */
2876  if( hashmap->hashes[pos] == 0 )
2877  {
2878  hashmap->slots[pos].origin = origin;
2879  hashmap->slots[pos].image = image;
2880  hashmap->hashes[pos] = hashval;
2881  ++hashmap->nelements;
2882  return SCIP_OKAY;
2883  }
2884 
2885  if( hashval == hashmap->hashes[pos] && origin == hashmap->slots[pos].origin )
2886  {
2887  if( override )
2888  {
2889  hashmap->slots[pos].origin = origin;
2890  hashmap->slots[pos].image = image;
2891  hashmap->hashes[pos] = hashval;
2892  return SCIP_OKAY;
2893  }
2894  else
2895  {
2896  return SCIP_KEYALREADYEXISTING;
2897  }
2898  }
2899 
2900  /* otherwise check if the current element at this position is closer to its hashvalue */
2901  distance = ELEM_DISTANCE(pos);
2902  if( distance < elemdistance )
2903  {
2904  SCIP_HASHMAPIMAGE tmp;
2905  uint32_t tmphash;
2906 
2907  /* if this is the case we insert the new element here and find a new position for the old one */
2908  elemdistance = distance;
2909  tmphash = hashval;
2910  hashval = hashmap->hashes[pos];
2911  hashmap->hashes[pos] = tmphash;
2912  SCIPswapPointers(&hashmap->slots[pos].origin, &origin);
2913  tmp = image;
2914  image = hashmap->slots[pos].image;
2915  hashmap->slots[pos].image = tmp;
2916  }
2917 
2918  /* continue until we have found an empty position */
2919  pos = (pos + 1) & hashmap->mask;
2920  ++elemdistance;
2921  }
2922 }
2923 
2924 /** lookup origin in the hashmap. If element is found returns true and the position of the element,
2925  * otherwise returns FALSE.
2926  */
2927 static
2929  SCIP_HASHMAP* hashmap, /**< hash table */
2930  void* origin, /**< origin to lookup */
2931  uint32_t* pos /**< pointer to store position of element, if exists */
2932  )
2933 {
2934  uint32_t hashval;
2935  uint32_t elemdistance;
2936 
2937  assert(hashmap != NULL);
2938  assert(hashmap->slots != NULL);
2939  assert(hashmap->hashes != NULL);
2940  assert(hashmap->mask > 0);
2941 
2942  /* get the hash value */
2943  hashval = hashvalue((size_t)origin);
2944  assert(hashval != 0);
2945 
2946  *pos = hashval>>(hashmap->shift);
2947  elemdistance = 0;
2948 
2949  while( TRUE ) /*lint !e716*/
2950  {
2951  uint32_t distance;
2952 
2953  /* slots is empty so element cannot be contained */
2954  if( hashmap->hashes[*pos] == 0 )
2955  return FALSE;
2956 
2957  distance = ELEM_DISTANCE(*pos);
2958  /* element can not be contained since otherwise we would have swapped it with this one during insert */
2959  if( elemdistance > distance )
2960  return FALSE;
2961 
2962  /* found element */
2963  if( hashmap->hashes[*pos] == hashval && hashmap->slots[*pos].origin == origin )
2964  return TRUE;
2965 
2966  *pos = (*pos + 1) & hashmap->mask;
2967  ++elemdistance;
2968  }
2969 }
2970 
2971 /** check if the load factor of the hashmap is too high and rebuild if necessary */
2972 static
2974  SCIP_HASHMAP* hashmap /**< hash table */
2975  )
2976 {
2977  assert(hashmap != NULL);
2978  assert(hashmap->shift < 32);
2979 
2980  /* use integer arithmetic to approximately check if load factor is above 90% */
2981  if( ((((uint64_t)hashmap->nelements)<<10)>>(32-hashmap->shift) > 921) )
2982  {
2983  SCIP_HASHMAPENTRY* slots;
2984  uint32_t* hashes;
2985  uint32_t nslots;
2986  uint32_t newnslots;
2987  uint32_t i;
2988 
2989  /* calculate new size (always power of two) */
2990  nslots = hashmap->mask + 1;
2991  --hashmap->shift;
2992  newnslots = 2*nslots;
2993  hashmap->mask = newnslots-1;
2994 
2995  /* reallocate array */
2996  SCIP_ALLOC( BMSallocBlockMemoryArray(hashmap->blkmem, &slots, newnslots) );
2997  SCIP_ALLOC( BMSallocClearBlockMemoryArray(hashmap->blkmem, &hashes, newnslots) );
2998 
2999  SCIPswapPointers((void**) &slots, (void**) &hashmap->slots);
3000  SCIPswapPointers((void**) &hashes, (void**) &hashmap->hashes);
3001  hashmap->nelements = 0;
3002 
3003  /* reinsert all elements */
3004  for( i = 0; i < nslots; ++i )
3005  {
3006  /* using SCIP_CALL_ABORT since there are no allocations or duplicates
3007  * and thus no bad return codes when inserting the elements
3008  */
3009  if( hashes[i] != 0 )
3010  {
3011  SCIP_CALL_ABORT( hashmapInsert(hashmap, slots[i].origin, slots[i].image, hashes[i], FALSE) );
3012  }
3013  }
3014 
3015  /* free old arrays */
3016  BMSfreeBlockMemoryArray(hashmap->blkmem, &hashes, nslots);
3017  BMSfreeBlockMemoryArray(hashmap->blkmem, &slots, nslots);
3018  }
3019 
3020  return SCIP_OKAY;
3021 }
3022 
3023 /** creates a hash map mapping pointers to pointers */
3025  SCIP_HASHMAP** hashmap, /**< pointer to store the created hash map */
3026  BMS_BLKMEM* blkmem, /**< block memory used to store hash map entries */
3027  int mapsize /**< size of the hash map */
3028  )
3029 {
3030  uint32_t nslots;
3031 
3032  assert(hashmap != NULL);
3033  assert(mapsize >= 0);
3034  assert(blkmem != NULL);
3035 
3036  SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashmap) );
3037 
3038  /* dont create too small hashtables, i.e. at least size 32, and increase
3039  * the given size by divinding it by 0.9, since then no rebuilding will
3040  * be necessary if the given number of elements are inserted. Finally round
3041  * to the next power of two.
3042  */
3043  (*hashmap)->shift = 32;
3044  (*hashmap)->shift -= (unsigned int)ceil(log(MAX(32, mapsize / 0.9)) / log(2.0));
3045  nslots = 1u << (32 - (*hashmap)->shift);
3046  (*hashmap)->mask = nslots - 1;
3047  (*hashmap)->blkmem = blkmem;
3048  (*hashmap)->nelements = 0;
3049  (*hashmap)->hashmaptype = SCIP_HASHMAPTYPE_UNKNOWN;
3050 
3051  SCIP_ALLOC( BMSallocBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots) );
3052  SCIP_ALLOC( BMSallocClearBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots) );
3053 
3054  return SCIP_OKAY;
3055 }
3056 
3057 /** frees the hash map */
3059  SCIP_HASHMAP** hashmap /**< pointer to the hash map */
3060  )
3061 {
3062  uint32_t nslots;
3063 
3064  assert(hashmap != NULL);
3065  assert(*hashmap != NULL);
3066 
3067  nslots = (*hashmap)->mask + 1;
3068 #ifdef SCIP_DEBUG
3069  {
3070  uint32_t maxprobelen = 0;
3071  uint64_t probelensum = 0;
3072  uint32_t i;
3073 
3074  assert(hashmap != NULL);
3075 
3076  for( i = 0; i < nslots; ++i )
3077  {
3078  if( (*hashmap)->hashes[i] != 0 )
3079  {
3080  uint32_t probelen = ((i + (*hashmap)->mask + 1 - ((*hashmap)->hashes[i]>>((*hashmap)->shift))) & (*hashmap)->mask) + 1;
3081  probelensum += probelen;
3082  maxprobelen = MAX(probelen, maxprobelen);
3083  }
3084  }
3085 
3086  SCIPdebugMessage("%u hash map entries, used %u/%u slots (%.1f%%)",
3087  (unsigned int)(*hashmap)->nelements, (unsigned int)(*hashmap)->nelements, (unsigned int)nslots,
3088  100.0*(SCIP_Real)(*hashmap)->nelements/(SCIP_Real)(nslots));
3089  if( (*hashmap)->nelements > 0 )
3090  SCIPdebugPrintf(", avg. probe length is %.1f, max. probe length is %u",
3091  (SCIP_Real)(probelensum)/(SCIP_Real)(*hashmap)->nelements, (unsigned int)maxprobelen);
3092  SCIPdebugPrintf("\n");
3093  }
3094 #endif
3095 
3096  /* free main hash map data structure */
3097  BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->hashes, nslots);
3098  BMSfreeBlockMemoryArray((*hashmap)->blkmem, &(*hashmap)->slots, nslots);
3099  BMSfreeBlockMemory((*hashmap)->blkmem, hashmap);
3100 }
3101 
3102 /** inserts new origin->image pair in hash map
3103  *
3104  * @note multiple insertion of same element is checked and results in an error
3105  */
3107  SCIP_HASHMAP* hashmap, /**< hash map */
3108  void* origin, /**< origin to set image for */
3109  void* image /**< new image for origin */
3110  )
3111 {
3112  uint32_t hashval;
3113  SCIP_HASHMAPIMAGE img;
3114 
3115  assert(hashmap != NULL);
3116  assert(hashmap->slots != NULL);
3117  assert(hashmap->hashes != NULL);
3118  assert(hashmap->mask > 0);
3119  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3120 
3121 #ifndef NDEBUG
3122  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3124 #endif
3125 
3126  SCIP_CALL( hashmapCheckLoad(hashmap) );
3127 
3128  /* get the hash value */
3129  hashval = hashvalue((size_t)origin);
3130 
3131  /* append origin->image pair to hash map */
3132  img.ptr = image;
3133  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3134 
3135  return SCIP_OKAY;
3136 }
3137 
3138 /** inserts new origin->image pair in hash map
3139  *
3140  * @note multiple insertion of same element is checked and results in an error
3141  */
3143  SCIP_HASHMAP* hashmap, /**< hash map */
3144  void* origin, /**< origin to set image for */
3145  int image /**< new image for origin */
3146  )
3147 {
3148  uint32_t hashval;
3149  SCIP_HASHMAPIMAGE img;
3150 
3151  assert(hashmap != NULL);
3152  assert(hashmap->slots != NULL);
3153  assert(hashmap->hashes != NULL);
3154  assert(hashmap->mask > 0);
3155  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3156 
3157 #ifndef NDEBUG
3158  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3159  hashmap->hashmaptype = SCIP_HASHMAPTYPE_INT;
3160 #endif
3161 
3162  SCIP_CALL( hashmapCheckLoad(hashmap) );
3163 
3164  /* get the hash value */
3165  hashval = hashvalue((size_t)origin);
3166 
3167  /* append origin->image pair to hash map */
3168  img.integer = image;
3169  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3170 
3171  return SCIP_OKAY;
3172 }
3173 
3174 /** inserts new origin->image pair in hash map
3175  *
3176  * @note multiple insertion of same element is checked and results in an error
3177  */
3179  SCIP_HASHMAP* hashmap, /**< hash map */
3180  void* origin, /**< origin to set image for */
3181  SCIP_Real image /**< new image for origin */
3182  )
3183 {
3184  uint32_t hashval;
3185  SCIP_HASHMAPIMAGE img;
3186 
3187  assert(hashmap != NULL);
3188  assert(hashmap->slots != NULL);
3189  assert(hashmap->hashes != NULL);
3190  assert(hashmap->mask > 0);
3191  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3192 
3193 #ifndef NDEBUG
3194  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3196 #endif
3197 
3198  SCIP_CALL( hashmapCheckLoad(hashmap) );
3199 
3200  /* get the hash value */
3201  hashval = hashvalue((size_t)origin);
3202 
3203  /* append origin->image pair to hash map */
3204  img.real = image;
3205  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, FALSE) );
3206 
3207  return SCIP_OKAY;
3208 }
3209 
3210 /** retrieves image of given origin from the hash map, or NULL if no image exists */
3212  SCIP_HASHMAP* hashmap, /**< hash map */
3213  void* origin /**< origin to retrieve image for */
3214  )
3215 {
3216  uint32_t pos;
3217 
3218  assert(hashmap != NULL);
3219  assert(hashmap->slots != NULL);
3220  assert(hashmap->hashes != NULL);
3221  assert(hashmap->mask > 0);
3222  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3223 
3224  if( hashmapLookup(hashmap, origin, &pos) )
3225  return hashmap->slots[pos].image.ptr;
3226 
3227  return NULL;
3228 }
3229 
3230 /** retrieves image of given origin from the hash map, or INT_MAX if no image exists */
3232  SCIP_HASHMAP* hashmap, /**< hash map */
3233  void* origin /**< origin to retrieve image for */
3234  )
3235 {
3236  uint32_t pos;
3237 
3238  assert(hashmap != NULL);
3239  assert(hashmap->slots != NULL);
3240  assert(hashmap->hashes != NULL);
3241  assert(hashmap->mask > 0);
3242  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3243 
3244  if( hashmapLookup(hashmap, origin, &pos) )
3245  return hashmap->slots[pos].image.integer;
3246 
3247  return INT_MAX;
3248 }
3249 
3250 /** retrieves image of given origin from the hash map, or SCIP_INVALID if no image exists */
3252  SCIP_HASHMAP* hashmap, /**< hash map */
3253  void* origin /**< origin to retrieve image for */
3254  )
3255 {
3256  uint32_t pos;
3257 
3258  assert(hashmap != NULL);
3259  assert(hashmap->slots != NULL);
3260  assert(hashmap->hashes != NULL);
3261  assert(hashmap->mask > 0);
3262  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3263 
3264  if( hashmapLookup(hashmap, origin, &pos) )
3265  return hashmap->slots[pos].image.real;
3266 
3267  return SCIP_INVALID;
3268 }
3269 
3270 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3271  * or by appending a new origin->image pair
3272  */
3274  SCIP_HASHMAP* hashmap, /**< hash map */
3275  void* origin, /**< origin to set image for */
3276  void* image /**< new image for origin */
3277  )
3278 {
3279  uint32_t hashval;
3280  SCIP_HASHMAPIMAGE img;
3281 
3282  assert(hashmap != NULL);
3283  assert(hashmap->slots != NULL);
3284  assert(hashmap->mask > 0);
3285  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_POINTER);
3286 
3287 #ifndef NDEBUG
3288  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3290 #endif
3291 
3292  SCIP_CALL( hashmapCheckLoad(hashmap) );
3293 
3294  /* get the hash value */
3295  hashval = hashvalue((size_t)origin);
3296 
3297  /* append origin->image pair to hash map */
3298  img.ptr = image;
3299  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3300 
3301  return SCIP_OKAY;
3302 }
3303 
3304 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3305  * or by appending a new origin->image pair
3306  */
3308  SCIP_HASHMAP* hashmap, /**< hash map */
3309  void* origin, /**< origin to set image for */
3310  int image /**< new image for origin */
3311  )
3312 {
3313  uint32_t hashval;
3314  SCIP_HASHMAPIMAGE img;
3315 
3316  assert(hashmap != NULL);
3317  assert(hashmap->slots != NULL);
3318  assert(hashmap->mask > 0);
3319  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_INT);
3320 
3321 #ifndef NDEBUG
3322  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3323  hashmap->hashmaptype = SCIP_HASHMAPTYPE_INT;
3324 #endif
3325 
3326  SCIP_CALL( hashmapCheckLoad(hashmap) );
3327 
3328  /* get the hash value */
3329  hashval = hashvalue((size_t)origin);
3330 
3331  /* append origin->image pair to hash map */
3332  img.integer = image;
3333  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3334 
3335  return SCIP_OKAY;
3336 }
3337 
3338 /** sets image for given origin in the hash map, either by modifying existing origin->image pair
3339  * or by appending a new origin->image pair
3340  */
3342  SCIP_HASHMAP* hashmap, /**< hash map */
3343  void* origin, /**< origin to set image for */
3344  SCIP_Real image /**< new image for origin */
3345  )
3346 {
3347  uint32_t hashval;
3348  SCIP_HASHMAPIMAGE img;
3349 
3350  assert(hashmap != NULL);
3351  assert(hashmap->slots != NULL);
3352  assert(hashmap->mask > 0);
3353  assert(hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN || hashmap->hashmaptype == SCIP_HASHMAPTYPE_REAL);
3354 
3355 #ifndef NDEBUG
3356  if( hashmap->hashmaptype == SCIP_HASHMAPTYPE_UNKNOWN )
3358 #endif
3359 
3360  SCIP_CALL( hashmapCheckLoad(hashmap) );
3361 
3362  /* get the hash value */
3363  hashval = hashvalue((size_t)origin);
3364 
3365  /* append origin->image pair to hash map */
3366  img.real = image;
3367  SCIP_CALL( hashmapInsert(hashmap, origin, img, hashval, TRUE) );
3368 
3369  return SCIP_OKAY;
3370 }
3371 
3372 /** checks whether an image to the given origin exists in the hash map */
3374  SCIP_HASHMAP* hashmap, /**< hash map */
3375  void* origin /**< origin to search for */
3376  )
3377 {
3378  uint32_t pos;
3379 
3380  assert(hashmap != NULL);
3381  assert(hashmap->slots != NULL);
3382  assert(hashmap->hashes != NULL);
3383  assert(hashmap->mask > 0);
3384 
3385  return hashmapLookup(hashmap, origin, &pos);
3386 }
3387 
3388 /** removes origin->image pair from the hash map, if it exists */
3390  SCIP_HASHMAP* hashmap, /**< hash map */
3391  void* origin /**< origin to remove from the list */
3392  )
3393 {
3394  uint32_t pos;
3395 
3396  assert(hashmap != NULL);
3397  assert(hashmap->slots != NULL);
3398  assert(hashmap->mask > 0);
3399 
3400  assert(origin != NULL);
3401 
3402  if( hashmapLookup(hashmap, origin, &pos) )
3403  {
3404  /* remove element */
3405  hashmap->hashes[pos] = 0;
3406  --hashmap->nelements;
3407 
3408  /* move other elements if necessary */
3409  while( TRUE ) /*lint !e716*/
3410  {
3411  uint32_t nextpos = (pos + 1) & hashmap->mask;
3412 
3413  /* nothing to do since there is no chain that needs to be moved */
3414  if( hashmap->hashes[nextpos] == 0 )
3415  return SCIP_OKAY;
3416 
3417  /* check if the element is the start of a new chain and return if that is the case */
3418  if( (hashmap->hashes[nextpos]>>(hashmap->shift)) == nextpos )
3419  return SCIP_OKAY;
3420 
3421  /* element should be moved to the left and next element needs to be checked */
3422  hashmap->slots[pos].origin = hashmap->slots[nextpos].origin;
3423  hashmap->slots[pos].image = hashmap->slots[nextpos].image;
3424  hashmap->hashes[pos] = hashmap->hashes[nextpos];
3425  hashmap->hashes[nextpos] = 0;
3426 
3427  pos = nextpos;
3428  }
3429  }
3430 
3431  return SCIP_OKAY;
3432 }
3433 
3434 /** prints statistics about hash map usage */
3436  SCIP_HASHMAP* hashmap, /**< hash map */
3437  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3438  )
3439 {
3440  uint32_t maxprobelen = 0;
3441  uint64_t probelensum = 0;
3442  uint32_t nslots;
3443  uint32_t i;
3444 
3445  assert(hashmap != NULL);
3446 
3447  nslots = hashmap->mask + 1;
3448 
3449  /* compute the maximum and average probe length */
3450  for( i = 0; i < nslots; ++i )
3451  {
3452  if( hashmap->hashes[i] != 0 )
3453  {
3454  uint32_t probelen = ELEM_DISTANCE(i) + 1;
3455  probelensum += probelen;
3456  maxprobelen = MAX(probelen, maxprobelen);
3457  }
3458  }
3459 
3460  /* print general hash map statistics */
3461  SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3462  (unsigned int)hashmap->nelements, (unsigned int)hashmap->nelements,
3463  (unsigned int)nslots, 100.0*(SCIP_Real)hashmap->nelements/(SCIP_Real)(nslots));
3464 
3465  /* if not empty print average and maximum probe length */
3466  if( hashmap->nelements > 0 )
3467  SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3468  (SCIP_Real)(probelensum)/(SCIP_Real)hashmap->nelements, (unsigned int)maxprobelen);
3469  SCIPmessagePrintInfo(messagehdlr, "\n");
3470 }
3471 
3472 /** indicates whether a hash map has no entries */
3474  SCIP_HASHMAP* hashmap /**< hash map */
3475  )
3476 {
3477  assert(hashmap != NULL);
3478 
3479  return hashmap->nelements == 0;
3480 }
3481 
3482 /** gives the number of elements in a hash map */
3484  SCIP_HASHMAP* hashmap /**< hash map */
3485  )
3486 {
3487  return (int) hashmap->nelements;
3488 }
3489 
3490 /** gives the number of entries in the internal arrays of a hash map */
3492  SCIP_HASHMAP* hashmap /**< hash map */
3493  )
3494 {
3495  return (int) hashmap->mask + 1;
3496 }
3497 
3498 /** gives the hashmap entry at the given index or NULL if entry is empty */
3500  SCIP_HASHMAP* hashmap, /**< hash map */
3501  int entryidx /**< index of hash map entry */
3502  )
3503 {
3504  assert(hashmap != NULL);
3505 
3506  return hashmap->hashes[entryidx] == 0 ? NULL : &hashmap->slots[entryidx];
3507 }
3508 
3509 /** gives the origin of the hashmap entry */
3511  SCIP_HASHMAPENTRY* entry /**< hash map entry */
3512  )
3513 {
3514  assert(entry != NULL);
3515 
3516  return entry->origin;
3517 }
3518 
3519 /** gives the image of the hashmap entry */
3521  SCIP_HASHMAPENTRY* entry /**< hash map entry */
3522  )
3523 {
3524  assert(entry != NULL);
3525 
3526  return entry->image.ptr;
3527 }
3528 
3529 /** gives the image of the hashmap entry */
3531  SCIP_HASHMAPENTRY* entry /**< hash map entry */
3532  )
3533 {
3534  assert(entry != NULL);
3535 
3536  return entry->image.integer;
3537 }
3538 
3539 /** gives the image of the hashmap entry */
3541  SCIP_HASHMAPENTRY* entry /**< hash map entry */
3542  )
3543 {
3544  assert(entry != NULL);
3545 
3546  return entry->image.real;
3547 }
3548 
3549 /** sets pointer image of a hashmap entry */
3551  SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3552  void* image /**< new image */
3553  )
3554 {
3555  assert(entry != NULL);
3556 
3557  entry->image.ptr = image;
3558 }
3559 
3560 /** sets integer image of a hashmap entry */
3562  SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3563  int image /**< new image */
3564  )
3565 {
3566  assert(entry != NULL);
3567 
3568  entry->image.integer = image;
3569 }
3570 
3571 /** sets real image of a hashmap entry */
3573  SCIP_HASHMAPENTRY* entry, /**< hash map entry */
3574  SCIP_Real image /**< new image */
3575  )
3576 {
3577  assert(entry != NULL);
3578 
3579  entry->image.real = image;
3580 }
3581 
3582 /** removes all entries in a hash map. */
3584  SCIP_HASHMAP* hashmap /**< hash map */
3585  )
3586 {
3587  assert(hashmap != NULL);
3588 
3589  BMSclearMemoryArray(hashmap->hashes, hashmap->mask + 1);
3590 
3591  hashmap->nelements = 0;
3592 
3593  return SCIP_OKAY;
3594 }
3595 
3596 
3597 /*
3598  * Hash Set
3599  */
3600 
3601 /* redefine ELEM_DISTANCE macro for hashset */
3602 #undef ELEM_DISTANCE
3603 /* computes the distance from it's desired position for the element stored at pos */
3604 #define ELEM_DISTANCE(pos) (((pos) + nslots - hashSetDesiredPos(hashset, hashset->slots[(pos)])) & mask)
3605 
3606 /* calculate desired position of element in hash set */
3607 static
3609  SCIP_HASHSET* hashset, /**< the hash set */
3610  void* element /**< element to calculate position for */
3611  )
3612 {
3613  return (uint32_t)((UINT64_C(0x9e3779b97f4a7c15) * (uintptr_t)element)>>(hashset->shift));
3614 }
3615 
3616 static
3618  SCIP_HASHSET* hashset, /**< hash set */
3619  void* element /**< element to insert */
3620  )
3621 {
3622  uint32_t elemdistance;
3623  uint32_t pos;
3624  uint32_t nslots;
3625  uint32_t mask;
3626 
3627  assert(hashset != NULL);
3628  assert(hashset->slots != NULL);
3629  assert(element != NULL);
3630 
3631  pos = hashSetDesiredPos(hashset, element);
3632  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3633  mask = nslots - 1;
3634 
3635  elemdistance = 0;
3636  while( TRUE ) /*lint !e716*/
3637  {
3638  uint32_t distance;
3639 
3640  /* if position is empty or key equal insert element */
3641  if( hashset->slots[pos] == NULL )
3642  {
3643  hashset->slots[pos] = element;
3644  ++hashset->nelements;
3645  return;
3646  }
3647 
3648  if( hashset->slots[pos] == element )
3649  return;
3650 
3651  /* otherwise check if the current element at this position is closer to its hashvalue */
3652  distance = ELEM_DISTANCE(pos);
3653  if( distance < elemdistance )
3654  {
3655  /* if this is the case we insert the new element here and find a new position for the old one */
3656  elemdistance = distance;
3657  SCIPswapPointers(&hashset->slots[pos], &element);
3658  }
3659 
3660  /* continue until we have found an empty position */
3661  pos = (pos + 1) & mask;
3662  ++elemdistance;
3663  }
3664 }
3665 
3666 /** check if the load factor of the hash set is too high and rebuild if necessary */
3667 static
3669  SCIP_HASHSET* hashset, /**< hash set */
3670  BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3671  )
3672 {
3673  assert(hashset != NULL);
3674  assert(hashset->shift < 64);
3675 
3676  /* use integer arithmetic to approximately check if load factor is above 90% */
3677  if( ((((uint64_t)hashset->nelements)<<10)>>(64-hashset->shift) > 921) )
3678  {
3679  void** slots;
3680  uint32_t nslots;
3681  uint32_t newnslots;
3682  uint32_t i;
3683 
3684  /* calculate new size (always power of two) */
3685  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3686  newnslots = 2*nslots;
3687  --hashset->shift;
3688 
3689  /* reallocate array */
3690  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &slots, newnslots) );
3691 
3692  SCIPswapPointers((void**) &slots, (void**) &hashset->slots);
3693  hashset->nelements = 0;
3694 
3695  /* reinsert all elements */
3696  for( i = 0; i < nslots; ++i )
3697  {
3698  if( slots[i] != NULL )
3699  hashsetInsert(hashset, slots[i]);
3700  }
3701 
3702  BMSfreeBlockMemoryArray(blkmem, &slots, nslots);
3703  }
3704 
3705  return SCIP_OKAY;
3706 }
3707 
3708 /** creates a hash set of pointers */
3710  SCIP_HASHSET** hashset, /**< pointer to store the created hash set */
3711  BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3712  int size /**< initial size of the hash set; it is guaranteed that the set is not
3713  * resized if at most that many elements are inserted */
3714  )
3715 {
3716  uint32_t nslots;
3717 
3718  assert(hashset != NULL);
3719  assert(size >= 0);
3720  assert(blkmem != NULL);
3721 
3722  SCIP_ALLOC( BMSallocBlockMemory(blkmem, hashset) );
3723 
3724  /* do not create too small hashtables, i.e. at least size 32, and increase
3725  * the given size by dividing it by 0.9, since then no rebuilding will
3726  * be necessary if the given number of elements are inserted. Finally round
3727  * to the next power of two.
3728  */
3729  (*hashset)->shift = 64;
3730  (*hashset)->shift -= (unsigned int)ceil(log(MAX(8.0, size / 0.9)) / log(2.0));
3731  nslots = (uint32_t)SCIPhashsetGetNSlots(*hashset);
3732  (*hashset)->nelements = 0;
3733 
3734  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*hashset)->slots, nslots) );
3735 
3736  return SCIP_OKAY;
3737 }
3738 
3739 /** frees the hash set */
3741  SCIP_HASHSET** hashset, /**< pointer to the hash set */
3742  BMS_BLKMEM* blkmem /**< block memory used to store hash set entries */
3743  )
3744 {
3745  BMSfreeBlockMemoryArray(blkmem, &(*hashset)->slots, SCIPhashsetGetNSlots(*hashset));
3746  BMSfreeBlockMemory(blkmem, hashset);
3747 }
3748 
3749 /** inserts new element into the hash set */
3751  SCIP_HASHSET* hashset, /**< hash set */
3752  BMS_BLKMEM* blkmem, /**< block memory used to store hash set entries */
3753  void* element /**< element to insert */
3754  )
3755 {
3756  assert(hashset != NULL);
3757  assert(hashset->slots != NULL);
3758 
3759  SCIP_CALL( hashsetCheckLoad(hashset, blkmem) );
3760 
3761  hashsetInsert(hashset, element);
3762 
3763  return SCIP_OKAY;
3764 }
3765 
3766 /** checks whether an element exists in the hash set */
3768  SCIP_HASHSET* hashset, /**< hash set */
3769  void* element /**< element to search for */
3770  )
3771 {
3772  uint32_t pos;
3773  uint32_t nslots;
3774  uint32_t mask;
3775  uint32_t elemdistance;
3776 
3777  assert(hashset != NULL);
3778  assert(hashset->slots != NULL);
3779 
3780  pos = hashSetDesiredPos(hashset, element);
3781  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3782  mask = nslots - 1;
3783  elemdistance = 0;
3784 
3785  while( TRUE ) /*lint !e716*/
3786  {
3787  uint32_t distance;
3788 
3789  /* found element */
3790  if( hashset->slots[pos] == element )
3791  return TRUE;
3792 
3793  /* slots is empty so element cannot be contained */
3794  if( hashset->slots[pos] == NULL )
3795  return FALSE;
3796 
3797  distance = ELEM_DISTANCE(pos);
3798  /* element can not be contained since otherwise we would have swapped it with this one during insert */
3799  if( elemdistance > distance )
3800  return FALSE;
3801 
3802  pos = (pos + 1) & mask;
3803  ++elemdistance;
3804  }
3805 }
3806 
3807 /** removes an element from the hash set, if it exists */
3809  SCIP_HASHSET* hashset, /**< hash set */
3810  void* element /**< origin to remove from the list */
3811  )
3812 {
3813  uint32_t pos;
3814  uint32_t nslots;
3815  uint32_t mask;
3816  uint32_t elemdistance;
3817 
3818  assert(hashset != NULL);
3819  assert(hashset->slots != NULL);
3820  assert(element != NULL);
3821 
3822  pos = hashSetDesiredPos(hashset, element);
3823  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3824  mask = nslots - 1;
3825  elemdistance = 0;
3826 
3827  while( TRUE ) /*lint !e716*/
3828  {
3829  uint32_t distance;
3830 
3831  /* found element */
3832  if( hashset->slots[pos] == element )
3833  break;
3834 
3835  /* slots is empty so element cannot be contained */
3836  if( hashset->slots[pos] == NULL )
3837  return SCIP_OKAY;
3838 
3839  distance = ELEM_DISTANCE(pos);
3840  /* element can not be contained since otherwise we would have swapped it with this one during insert */
3841  if( elemdistance > distance )
3842  return SCIP_OKAY;
3843 
3844  pos = (pos + 1) & mask;
3845  ++elemdistance;
3846  }
3847 
3848  assert(hashset->slots[pos] == element);
3849  assert(SCIPhashsetExists(hashset, element));
3850 
3851  /* remove element */
3852  --hashset->nelements;
3853 
3854  /* move other elements if necessary */
3855  while( TRUE ) /*lint !e716*/
3856  {
3857  uint32_t nextpos = (pos + 1) & mask;
3858 
3859  /* nothing to do since there is no chain that needs to be moved */
3860  if( hashset->slots[nextpos] == NULL )
3861  {
3862  hashset->slots[pos] = NULL;
3863  assert(!SCIPhashsetExists(hashset, element));
3864  return SCIP_OKAY;
3865  }
3866 
3867  /* check if the element is the start of a new chain and return if that is the case */
3868  if( hashSetDesiredPos(hashset, hashset->slots[nextpos]) == nextpos )
3869  {
3870  hashset->slots[pos] = NULL;
3871  assert(!SCIPhashsetExists(hashset, element));
3872  return SCIP_OKAY;
3873  }
3874 
3875  /* element should be moved to the left and next element needs to be checked */
3876  hashset->slots[pos] = hashset->slots[nextpos];
3877 
3878  pos = nextpos;
3879  }
3880 }
3881 
3882 /** prints statistics about hash set usage */
3884  SCIP_HASHSET* hashset, /**< hash set */
3885  SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
3886  )
3887 {
3888  uint32_t maxprobelen = 0;
3889  uint64_t probelensum = 0;
3890  uint32_t nslots;
3891  uint32_t mask;
3892  uint32_t i;
3893 
3894  assert(hashset != NULL);
3895 
3896  nslots = (uint32_t)SCIPhashsetGetNSlots(hashset);
3897  mask = nslots - 1;
3898 
3899  /* compute the maximum and average probe length */
3900  for( i = 0; i < nslots; ++i )
3901  {
3902  if( hashset->slots[i] != NULL )
3903  {
3904  uint32_t probelen = ((hashSetDesiredPos(hashset, hashset->slots[i]) + nslots - i) & mask) + 1;
3905  probelensum += probelen;
3906  maxprobelen = MAX(probelen, maxprobelen);
3907  }
3908  }
3909 
3910  /* print general hash set statistics */
3911  SCIPmessagePrintInfo(messagehdlr, "%u hash entries, used %u/%u slots (%.1f%%)",
3912  (unsigned int)hashset->nelements, (unsigned int)hashset->nelements,
3913  (unsigned int)nslots, 100.0*(SCIP_Real)hashset->nelements/(SCIP_Real)(nslots));
3914 
3915  /* if not empty print average and maximum probe length */
3916  if( hashset->nelements > 0 )
3917  SCIPmessagePrintInfo(messagehdlr, ", avg. probe length is %.1f, max. probe length is %u",
3918  (SCIP_Real)(probelensum)/(SCIP_Real)hashset->nelements, (unsigned int)maxprobelen);
3919  SCIPmessagePrintInfo(messagehdlr, "\n");
3920 }
3921 
3922 /* In debug mode, the following methods are implemented as function calls to ensure
3923  * type validity.
3924  * In optimized mode, the methods are implemented as defines to improve performance.
3925  * However, we want to have them in the library anyways, so we have to undef the defines.
3926  */
3927 
3928 #undef SCIPhashsetIsEmpty
3929 #undef SCIPhashsetGetNElements
3930 #undef SCIPhashsetGetNSlots
3931 #undef SCIPhashsetGetSlots
3932 
3933 /** indicates whether a hash set has no entries */
3935  SCIP_HASHSET* hashset /**< hash set */
3936  )
3937 {
3938  return hashset->nelements == 0;
3939 }
3940 
3941 /** gives the number of elements in a hash set */
3943  SCIP_HASHSET* hashset /**< hash set */
3944  )
3945 {
3946  return (int)hashset->nelements;
3947 }
3948 
3949 /** gives the number of slots of a hash set */
3951  SCIP_HASHSET* hashset /**< hash set */
3952  )
3953 {
3954  return (int) (1u << (64 - hashset->shift));
3955 }
3956 
3957 /** gives the array of hash set slots; contains all elements in indetermined order and may contain NULL values */
3959  SCIP_HASHSET* hashset /**< hash set */
3960  )
3961 {
3962  return hashset->slots;
3963 }
3964 
3965 /** removes all entries in a hash set. */
3967  SCIP_HASHSET* hashset /**< hash set */
3968  )
3969 {
3970  BMSclearMemoryArray(hashset->slots, SCIPhashsetGetNSlots(hashset));
3971 
3972  hashset->nelements = 0;
3973 }
3974 
3975 /*
3976  * Dynamic Arrays
3977  */
3978 
3979 /** creates a dynamic array of real values */
3981  SCIP_REALARRAY** realarray, /**< pointer to store the real array */
3982  BMS_BLKMEM* blkmem /**< block memory */
3983  )
3984 {
3985  assert(realarray != NULL);
3986  assert(blkmem != NULL);
3987 
3988  SCIP_ALLOC( BMSallocBlockMemory(blkmem, realarray) );
3989  (*realarray)->blkmem = blkmem;
3990  (*realarray)->vals = NULL;
3991  (*realarray)->valssize = 0;
3992  (*realarray)->firstidx = -1;
3993  (*realarray)->minusedidx = INT_MAX;
3994  (*realarray)->maxusedidx = INT_MIN;
3995 
3996  return SCIP_OKAY;
3997 }
3998 
3999 /** creates a copy of a dynamic array of real values */
4001  SCIP_REALARRAY** realarray, /**< pointer to store the copied real array */
4002  BMS_BLKMEM* blkmem, /**< block memory */
4003  SCIP_REALARRAY* sourcerealarray /**< dynamic real array to copy */
4004  )
4005 {
4006  assert(realarray != NULL);
4007  assert(sourcerealarray != NULL);
4008 
4009  SCIP_CALL( SCIPrealarrayCreate(realarray, blkmem) );
4010  if( sourcerealarray->valssize > 0 )
4011  {
4012  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*realarray)->vals, sourcerealarray->vals, \
4013  sourcerealarray->valssize) );
4014  }
4015  (*realarray)->valssize = sourcerealarray->valssize;
4016  (*realarray)->firstidx = sourcerealarray->firstidx;
4017  (*realarray)->minusedidx = sourcerealarray->minusedidx;
4018  (*realarray)->maxusedidx = sourcerealarray->maxusedidx;
4019 
4020  return SCIP_OKAY;
4021 }
4022 
4023 /** frees a dynamic array of real values */
4025  SCIP_REALARRAY** realarray /**< pointer to the real array */
4026  )
4027 {
4028  assert(realarray != NULL);
4029  assert(*realarray != NULL);
4030 
4031  BMSfreeBlockMemoryArrayNull((*realarray)->blkmem, &(*realarray)->vals, (*realarray)->valssize);
4032  BMSfreeBlockMemory((*realarray)->blkmem, realarray);
4033 
4034  return SCIP_OKAY;
4035 }
4036 
4037 /** extends dynamic array to be able to store indices from minidx to maxidx */
4039  SCIP_REALARRAY* realarray, /**< dynamic real array */
4040  int arraygrowinit, /**< initial size of array */
4041  SCIP_Real arraygrowfac, /**< growing factor of array */
4042  int minidx, /**< smallest index to allocate storage for */
4043  int maxidx /**< largest index to allocate storage for */
4044  )
4045 {
4046  int nused;
4047  int nfree;
4048  int newfirstidx;
4049  int i;
4050 
4051  assert(realarray != NULL);
4052  assert(realarray->minusedidx == INT_MAX || realarray->firstidx >= 0);
4053  assert(realarray->maxusedidx == INT_MIN || realarray->firstidx >= 0);
4054  assert(realarray->minusedidx == INT_MAX || realarray->minusedidx >= realarray->firstidx);
4055  assert(realarray->maxusedidx == INT_MIN || realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4056  assert(0 <= minidx);
4057  assert(minidx <= maxidx);
4058 
4059  minidx = MIN(minidx, realarray->minusedidx);
4060  maxidx = MAX(maxidx, realarray->maxusedidx);
4061  assert(0 <= minidx);
4062  assert(minidx <= maxidx);
4063 
4064  SCIPdebugMessage("extending realarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4065  (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, minidx, maxidx);
4066 
4067  /* check, whether we have to allocate additional memory, or shift the array */
4068  nused = maxidx - minidx + 1;
4069  if( nused > realarray->valssize )
4070  {
4071  SCIP_Real* newvals;
4072  int newvalssize;
4073 
4074  /* allocate new memory storage */
4075  newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4076  SCIP_ALLOC( BMSallocBlockMemoryArray(realarray->blkmem, &newvals, newvalssize) );
4077  nfree = newvalssize - nused;
4078  newfirstidx = minidx - nfree/2;
4079  newfirstidx = MAX(newfirstidx, 0);
4080  assert(newfirstidx <= minidx);
4081  assert(maxidx < newfirstidx + newvalssize);
4082 
4083  /* initialize memory array by copying old values and setting new values to zero */
4084  if( realarray->firstidx != -1 )
4085  {
4086  for( i = 0; i < realarray->minusedidx - newfirstidx; ++i )
4087  newvals[i] = 0.0;
4088 
4089  /* check for possible overflow or negative value */
4090  assert(realarray->maxusedidx - realarray->minusedidx + 1 > 0);
4091 
4092  BMScopyMemoryArray(&newvals[realarray->minusedidx - newfirstidx],
4093  &(realarray->vals[realarray->minusedidx - realarray->firstidx]),
4094  realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866 !e776*/
4095  for( i = realarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4096  newvals[i] = 0.0;
4097  }
4098  else
4099  {
4100  for( i = 0; i < newvalssize; ++i )
4101  newvals[i] = 0.0;
4102  }
4103 
4104  /* free old memory storage, and set the new array parameters */
4105  BMSfreeBlockMemoryArrayNull(realarray->blkmem, &realarray->vals, realarray->valssize);
4106  realarray->vals = newvals;
4107  realarray->valssize = newvalssize;
4108  realarray->firstidx = newfirstidx;
4109  }
4110  else if( realarray->firstidx == -1 )
4111  {
4112  /* a sufficiently large memory storage exists, but it was cleared */
4113  nfree = realarray->valssize - nused;
4114  assert(nfree >= 0);
4115  realarray->firstidx = minidx - nfree/2;
4116  assert(realarray->firstidx <= minidx);
4117  assert(maxidx < realarray->firstidx + realarray->valssize);
4118 #ifndef NDEBUG
4119  for( i = 0; i < realarray->valssize; ++i )
4120  assert(realarray->vals[i] == 0.0);
4121 #endif
4122  }
4123  else if( minidx < realarray->firstidx )
4124  {
4125  /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4126  nfree = realarray->valssize - nused;
4127  assert(nfree >= 0);
4128  newfirstidx = minidx - nfree/2;
4129  newfirstidx = MAX(newfirstidx, 0);
4130  assert(newfirstidx <= minidx);
4131  assert(maxidx < newfirstidx + realarray->valssize);
4132 
4133  if( realarray->minusedidx <= realarray->maxusedidx )
4134  {
4135  int shift;
4136 
4137  assert(realarray->firstidx <= realarray->minusedidx);
4138  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4139 
4140  /* shift used part of array to the right */
4141  shift = realarray->firstidx - newfirstidx;
4142  assert(shift > 0);
4143  for( i = realarray->maxusedidx - realarray->firstidx; i >= realarray->minusedidx - realarray->firstidx; --i )
4144  {
4145  assert(0 <= i + shift && i + shift < realarray->valssize);
4146  realarray->vals[i + shift] = realarray->vals[i];
4147  }
4148  /* clear the formerly used head of the array */
4149  for( i = 0; i < shift; ++i )
4150  realarray->vals[realarray->minusedidx - realarray->firstidx + i] = 0.0;
4151  }
4152  realarray->firstidx = newfirstidx;
4153  }
4154  else if( maxidx >= realarray->firstidx + realarray->valssize )
4155  {
4156  /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4157  nfree = realarray->valssize - nused;
4158  assert(nfree >= 0);
4159  newfirstidx = minidx - nfree/2;
4160  newfirstidx = MAX(newfirstidx, 0);
4161  assert(newfirstidx <= minidx);
4162  assert(maxidx < newfirstidx + realarray->valssize);
4163 
4164  if( realarray->minusedidx <= realarray->maxusedidx )
4165  {
4166  int shift;
4167 
4168  assert(realarray->firstidx <= realarray->minusedidx);
4169  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4170 
4171  /* shift used part of array to the left */
4172  shift = newfirstidx - realarray->firstidx;
4173  assert(shift > 0);
4174  for( i = realarray->minusedidx - realarray->firstidx; i <= realarray->maxusedidx - realarray->firstidx; ++i )
4175  {
4176  assert(0 <= i - shift && i - shift < realarray->valssize);
4177  realarray->vals[i - shift] = realarray->vals[i];
4178  }
4179  /* clear the formerly used tail of the array */
4180  for( i = 0; i < shift; ++i )
4181  realarray->vals[realarray->maxusedidx - realarray->firstidx - i] = 0.0;
4182  }
4183  realarray->firstidx = newfirstidx;
4184  }
4185 
4186  assert(minidx >= realarray->firstidx);
4187  assert(maxidx < realarray->firstidx + realarray->valssize);
4188 
4189  return SCIP_OKAY;
4190 }
4191 
4192 /** clears a dynamic real array */
4194  SCIP_REALARRAY* realarray /**< dynamic real array */
4195  )
4196 {
4197  assert(realarray != NULL);
4198 
4199  SCIPdebugMessage("clearing realarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4200  (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx);
4201 
4202  if( realarray->minusedidx <= realarray->maxusedidx )
4203  {
4204  assert(realarray->firstidx <= realarray->minusedidx);
4205  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4206  assert(realarray->firstidx != -1);
4207  assert(realarray->valssize > 0);
4208 
4209  /* clear the used part of array */
4210  BMSclearMemoryArray(&realarray->vals[realarray->minusedidx - realarray->firstidx],
4211  realarray->maxusedidx - realarray->minusedidx + 1); /*lint !e866*/
4212 
4213  /* mark the array cleared */
4214  realarray->minusedidx = INT_MAX;
4215  realarray->maxusedidx = INT_MIN;
4216  }
4217  assert(realarray->minusedidx == INT_MAX);
4218  assert(realarray->maxusedidx == INT_MIN);
4219 
4220  return SCIP_OKAY;
4221 }
4222 
4223 /** gets value of entry in dynamic array */
4225  SCIP_REALARRAY* realarray, /**< dynamic real array */
4226  int idx /**< array index to get value for */
4227  )
4228 {
4229  assert(realarray != NULL);
4230  assert(idx >= 0);
4231 
4232  if( idx < realarray->minusedidx || idx > realarray->maxusedidx )
4233  return 0.0;
4234  else
4235  {
4236  assert(realarray->vals != NULL);
4237  assert(idx - realarray->firstidx >= 0);
4238  assert(idx - realarray->firstidx < realarray->valssize);
4239 
4240  return realarray->vals[idx - realarray->firstidx];
4241  }
4242 }
4243 
4244 /** sets value of entry in dynamic array */
4246  SCIP_REALARRAY* realarray, /**< dynamic real array */
4247  int arraygrowinit, /**< initial size of array */
4248  SCIP_Real arraygrowfac, /**< growing factor of array */
4249  int idx, /**< array index to set value for */
4250  SCIP_Real val /**< value to set array index to */
4251  )
4252 {
4253  assert(realarray != NULL);
4254  assert(idx >= 0);
4255 
4256  SCIPdebugMessage("setting realarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %g\n",
4257  (void*)realarray, realarray->firstidx, realarray->valssize, realarray->minusedidx, realarray->maxusedidx, idx, val);
4258 
4259  if( val != 0.0 )
4260  {
4261  /* extend array to be able to store the index */
4262  SCIP_CALL( SCIPrealarrayExtend(realarray, arraygrowinit, arraygrowfac, idx, idx) );
4263  assert(idx >= realarray->firstidx);
4264  assert(idx < realarray->firstidx + realarray->valssize);
4265 
4266  /* set the array value of the index */
4267  realarray->vals[idx - realarray->firstidx] = val;
4268 
4269  /* update min/maxusedidx */
4270  realarray->minusedidx = MIN(realarray->minusedidx, idx);
4271  realarray->maxusedidx = MAX(realarray->maxusedidx, idx);
4272  }
4273  else if( idx >= realarray->firstidx && idx < realarray->firstidx + realarray->valssize )
4274  {
4275  /* set the array value of the index to zero */
4276  realarray->vals[idx - realarray->firstidx] = 0.0;
4277 
4278  /* check, if we can tighten the min/maxusedidx */
4279  if( idx == realarray->minusedidx )
4280  {
4281  assert(realarray->maxusedidx >= 0);
4282  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4283  do
4284  {
4285  realarray->minusedidx++;
4286  }
4287  while( realarray->minusedidx <= realarray->maxusedidx
4288  && realarray->vals[realarray->minusedidx - realarray->firstidx] == 0.0 );
4289 
4290  if( realarray->minusedidx > realarray->maxusedidx )
4291  {
4292  realarray->minusedidx = INT_MAX;
4293  realarray->maxusedidx = INT_MIN;
4294  }
4295  }
4296  else if( idx == realarray->maxusedidx )
4297  {
4298  assert(realarray->minusedidx >= 0);
4299  assert(realarray->minusedidx < realarray->maxusedidx);
4300  assert(realarray->maxusedidx < realarray->firstidx + realarray->valssize);
4301  do
4302  {
4303  realarray->maxusedidx--;
4304  assert(realarray->minusedidx <= realarray->maxusedidx);
4305  }
4306  while( realarray->vals[realarray->maxusedidx - realarray->firstidx] == 0.0 );
4307  }
4308  }
4309 
4310  return SCIP_OKAY;
4311 }
4312 
4313 /** increases value of entry in dynamic array */
4315  SCIP_REALARRAY* realarray, /**< dynamic real array */
4316  int arraygrowinit, /**< initial size of array */
4317  SCIP_Real arraygrowfac, /**< growing factor of array */
4318  int idx, /**< array index to increase value for */
4319  SCIP_Real incval /**< value to increase array index */
4320  )
4321 {
4322  SCIP_Real oldval;
4323 
4324  oldval = SCIPrealarrayGetVal(realarray, idx);
4325  if( oldval != SCIP_INVALID ) /*lint !e777*/
4326  return SCIPrealarraySetVal(realarray, arraygrowinit, arraygrowfac, idx, oldval + incval);
4327  else
4328  return SCIP_OKAY;
4329 }
4330 
4331 /** returns the minimal index of all stored non-zero elements */
4333  SCIP_REALARRAY* realarray /**< dynamic real array */
4334  )
4335 {
4336  assert(realarray != NULL);
4337 
4338  return realarray->minusedidx;
4339 }
4340 
4341 /** returns the maximal index of all stored non-zero elements */
4343  SCIP_REALARRAY* realarray /**< dynamic real array */
4344  )
4345 {
4346  assert(realarray != NULL);
4347 
4348  return realarray->maxusedidx;
4349 }
4350 
4351 /** creates a dynamic array of int values */
4353  SCIP_INTARRAY** intarray, /**< pointer to store the int array */
4354  BMS_BLKMEM* blkmem /**< block memory */
4355  )
4356 {
4357  assert(intarray != NULL);
4358  assert(blkmem != NULL);
4359 
4360  SCIP_ALLOC( BMSallocBlockMemory(blkmem, intarray) );
4361  (*intarray)->blkmem = blkmem;
4362  (*intarray)->vals = NULL;
4363  (*intarray)->valssize = 0;
4364  (*intarray)->firstidx = -1;
4365  (*intarray)->minusedidx = INT_MAX;
4366  (*intarray)->maxusedidx = INT_MIN;
4367 
4368  return SCIP_OKAY;
4369 }
4370 
4371 /** creates a copy of a dynamic array of int values */
4373  SCIP_INTARRAY** intarray, /**< pointer to store the copied int array */
4374  BMS_BLKMEM* blkmem, /**< block memory */
4375  SCIP_INTARRAY* sourceintarray /**< dynamic int array to copy */
4376  )
4377 {
4378  assert(intarray != NULL);
4379  assert(sourceintarray != NULL);
4380 
4381  SCIP_CALL( SCIPintarrayCreate(intarray, blkmem) );
4382  if( sourceintarray->valssize > 0 )
4383  {
4384  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*intarray)->vals, sourceintarray->vals, sourceintarray->valssize) );
4385  }
4386  (*intarray)->valssize = sourceintarray->valssize;
4387  (*intarray)->firstidx = sourceintarray->firstidx;
4388  (*intarray)->minusedidx = sourceintarray->minusedidx;
4389  (*intarray)->maxusedidx = sourceintarray->maxusedidx;
4390 
4391  return SCIP_OKAY;
4392 }
4393 
4394 /** frees a dynamic array of int values */
4396  SCIP_INTARRAY** intarray /**< pointer to the int array */
4397  )
4398 {
4399  assert(intarray != NULL);
4400  assert(*intarray != NULL);
4401 
4402  BMSfreeBlockMemoryArrayNull((*intarray)->blkmem, &(*intarray)->vals, (*intarray)->valssize);
4403  BMSfreeBlockMemory((*intarray)->blkmem, intarray);
4404 
4405  return SCIP_OKAY;
4406 }
4407 
4408 /** extends dynamic array to be able to store indices from minidx to maxidx */
4410  SCIP_INTARRAY* intarray, /**< dynamic int array */
4411  int arraygrowinit, /**< initial size of array */
4412  SCIP_Real arraygrowfac, /**< growing factor of array */
4413  int minidx, /**< smallest index to allocate storage for */
4414  int maxidx /**< largest index to allocate storage for */
4415  )
4416 {
4417  int nused;
4418  int nfree;
4419  int newfirstidx;
4420  int i;
4421 
4422  assert(intarray != NULL);
4423  assert(intarray->minusedidx == INT_MAX || intarray->firstidx >= 0);
4424  assert(intarray->maxusedidx == INT_MIN || intarray->firstidx >= 0);
4425  assert(intarray->minusedidx == INT_MAX || intarray->minusedidx >= intarray->firstidx);
4426  assert(intarray->maxusedidx == INT_MIN || intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4427  assert(0 <= minidx);
4428  assert(minidx <= maxidx);
4429 
4430  minidx = MIN(minidx, intarray->minusedidx);
4431  maxidx = MAX(maxidx, intarray->maxusedidx);
4432  assert(0 <= minidx);
4433  assert(minidx <= maxidx);
4434 
4435  SCIPdebugMessage("extending intarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4436  (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, minidx, maxidx);
4437 
4438  /* check, whether we have to allocate additional memory, or shift the array */
4439  nused = maxidx - minidx + 1;
4440  if( nused > intarray->valssize )
4441  {
4442  int* newvals;
4443  int newvalssize;
4444 
4445  /* allocate new memory storage */
4446  newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4447  SCIP_ALLOC( BMSallocBlockMemoryArray(intarray->blkmem, &newvals, newvalssize) );
4448  nfree = newvalssize - nused;
4449  newfirstidx = minidx - nfree/2;
4450  newfirstidx = MAX(newfirstidx, 0);
4451  assert(newfirstidx <= minidx);
4452  assert(maxidx < newfirstidx + newvalssize);
4453 
4454  /* initialize memory array by copying old values and setting new values to zero */
4455  if( intarray->firstidx != -1 )
4456  {
4457  for( i = 0; i < intarray->minusedidx - newfirstidx; ++i )
4458  newvals[i] = 0;
4459 
4460  /* check for possible overflow or negative value */
4461  assert(intarray->maxusedidx - intarray->minusedidx + 1 > 0);
4462 
4463  BMScopyMemoryArray(&newvals[intarray->minusedidx - newfirstidx],
4464  &intarray->vals[intarray->minusedidx - intarray->firstidx],
4465  intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866 !e776*/
4466  for( i = intarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4467  newvals[i] = 0;
4468  }
4469  else
4470  {
4471  for( i = 0; i < newvalssize; ++i )
4472  newvals[i] = 0;
4473  }
4474 
4475  /* free old memory storage, and set the new array parameters */
4476  BMSfreeBlockMemoryArrayNull(intarray->blkmem, &intarray->vals, intarray->valssize);
4477  intarray->vals = newvals;
4478  intarray->valssize = newvalssize;
4479  intarray->firstidx = newfirstidx;
4480  }
4481  else if( intarray->firstidx == -1 )
4482  {
4483  /* a sufficiently large memory storage exists, but it was cleared */
4484  nfree = intarray->valssize - nused;
4485  assert(nfree >= 0);
4486  intarray->firstidx = minidx - nfree/2;
4487  assert(intarray->firstidx <= minidx);
4488  assert(maxidx < intarray->firstidx + intarray->valssize);
4489 #ifndef NDEBUG
4490  for( i = 0; i < intarray->valssize; ++i )
4491  assert(intarray->vals[i] == 0);
4492 #endif
4493  }
4494  else if( minidx < intarray->firstidx )
4495  {
4496  /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4497  nfree = intarray->valssize - nused;
4498  assert(nfree >= 0);
4499  newfirstidx = minidx - nfree/2;
4500  newfirstidx = MAX(newfirstidx, 0);
4501  assert(newfirstidx <= minidx);
4502  assert(maxidx < newfirstidx + intarray->valssize);
4503 
4504  if( intarray->minusedidx <= intarray->maxusedidx )
4505  {
4506  int shift;
4507 
4508  assert(intarray->firstidx <= intarray->minusedidx);
4509  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4510 
4511  /* shift used part of array to the right */
4512  shift = intarray->firstidx - newfirstidx;
4513  assert(shift > 0);
4514  for( i = intarray->maxusedidx - intarray->firstidx; i >= intarray->minusedidx - intarray->firstidx; --i )
4515  {
4516  assert(0 <= i + shift && i + shift < intarray->valssize);
4517  intarray->vals[i + shift] = intarray->vals[i];
4518  }
4519  /* clear the formerly used head of the array */
4520  for( i = 0; i < shift; ++i )
4521  intarray->vals[intarray->minusedidx - intarray->firstidx + i] = 0;
4522  }
4523  intarray->firstidx = newfirstidx;
4524  }
4525  else if( maxidx >= intarray->firstidx + intarray->valssize )
4526  {
4527  /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4528  nfree = intarray->valssize - nused;
4529  assert(nfree >= 0);
4530  newfirstidx = minidx - nfree/2;
4531  newfirstidx = MAX(newfirstidx, 0);
4532  assert(newfirstidx <= minidx);
4533  assert(maxidx < newfirstidx + intarray->valssize);
4534 
4535  if( intarray->minusedidx <= intarray->maxusedidx )
4536  {
4537  int shift;
4538 
4539  assert(intarray->firstidx <= intarray->minusedidx);
4540  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4541 
4542  /* shift used part of array to the left */
4543  shift = newfirstidx - intarray->firstidx;
4544  assert(shift > 0);
4545  for( i = intarray->minusedidx - intarray->firstidx; i <= intarray->maxusedidx - intarray->firstidx; ++i )
4546  {
4547  assert(0 <= i - shift && i - shift < intarray->valssize);
4548  intarray->vals[i - shift] = intarray->vals[i];
4549  }
4550  /* clear the formerly used tail of the array */
4551  for( i = 0; i < shift; ++i )
4552  intarray->vals[intarray->maxusedidx - intarray->firstidx - i] = 0;
4553  }
4554  intarray->firstidx = newfirstidx;
4555  }
4556 
4557  assert(minidx >= intarray->firstidx);
4558  assert(maxidx < intarray->firstidx + intarray->valssize);
4559 
4560  return SCIP_OKAY;
4561 }
4562 
4563 /** clears a dynamic int array */
4565  SCIP_INTARRAY* intarray /**< dynamic int array */
4566  )
4567 {
4568  assert(intarray != NULL);
4569 
4570  SCIPdebugMessage("clearing intarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4571  (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx);
4572 
4573  if( intarray->minusedidx <= intarray->maxusedidx )
4574  {
4575  assert(intarray->firstidx <= intarray->minusedidx);
4576  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4577  assert(intarray->firstidx != -1);
4578  assert(intarray->valssize > 0);
4579 
4580  /* clear the used part of array */
4581  BMSclearMemoryArray(&intarray->vals[intarray->minusedidx - intarray->firstidx],
4582  intarray->maxusedidx - intarray->minusedidx + 1); /*lint !e866*/
4583 
4584  /* mark the array cleared */
4585  intarray->minusedidx = INT_MAX;
4586  intarray->maxusedidx = INT_MIN;
4587  }
4588  assert(intarray->minusedidx == INT_MAX);
4589  assert(intarray->maxusedidx == INT_MIN);
4590 
4591  return SCIP_OKAY;
4592 }
4593 
4594 /** gets value of entry in dynamic array */
4596  SCIP_INTARRAY* intarray, /**< dynamic int array */
4597  int idx /**< array index to get value for */
4598  )
4599 {
4600  assert(intarray != NULL);
4601  assert(idx >= 0);
4602 
4603  if( idx < intarray->minusedidx || idx > intarray->maxusedidx )
4604  return 0;
4605  else
4606  {
4607  assert(intarray->vals != NULL);
4608  assert(idx - intarray->firstidx >= 0);
4609  assert(idx - intarray->firstidx < intarray->valssize);
4610 
4611  return intarray->vals[idx - intarray->firstidx];
4612  }
4613 }
4614 
4615 /** sets value of entry in dynamic array */
4617  SCIP_INTARRAY* intarray, /**< dynamic int array */
4618  int arraygrowinit, /**< initial size of array */
4619  SCIP_Real arraygrowfac, /**< growing factor of array */
4620  int idx, /**< array index to set value for */
4621  int val /**< value to set array index to */
4622  )
4623 {
4624  assert(intarray != NULL);
4625  assert(idx >= 0);
4626 
4627  SCIPdebugMessage("setting intarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %d\n",
4628  (void*)intarray, intarray->firstidx, intarray->valssize, intarray->minusedidx, intarray->maxusedidx, idx, val);
4629 
4630  if( val != 0 )
4631  {
4632  /* extend array to be able to store the index */
4633  SCIP_CALL( SCIPintarrayExtend(intarray, arraygrowinit, arraygrowfac, idx, idx) );
4634  assert(idx >= intarray->firstidx);
4635  assert(idx < intarray->firstidx + intarray->valssize);
4636 
4637  /* set the array value of the index */
4638  intarray->vals[idx - intarray->firstidx] = val;
4639 
4640  /* update min/maxusedidx */
4641  intarray->minusedidx = MIN(intarray->minusedidx, idx);
4642  intarray->maxusedidx = MAX(intarray->maxusedidx, idx);
4643  }
4644  else if( idx >= intarray->firstidx && idx < intarray->firstidx + intarray->valssize )
4645  {
4646  /* set the array value of the index to zero */
4647  intarray->vals[idx - intarray->firstidx] = 0;
4648 
4649  /* check, if we can tighten the min/maxusedidx */
4650  if( idx == intarray->minusedidx )
4651  {
4652  assert(intarray->maxusedidx >= 0);
4653  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4654  do
4655  {
4656  intarray->minusedidx++;
4657  }
4658  while( intarray->minusedidx <= intarray->maxusedidx
4659  && intarray->vals[intarray->minusedidx - intarray->firstidx] == 0 );
4660  if( intarray->minusedidx > intarray->maxusedidx )
4661  {
4662  intarray->minusedidx = INT_MAX;
4663  intarray->maxusedidx = INT_MIN;
4664  }
4665  }
4666  else if( idx == intarray->maxusedidx )
4667  {
4668  assert(intarray->minusedidx >= 0);
4669  assert(intarray->minusedidx < intarray->maxusedidx);
4670  assert(intarray->maxusedidx < intarray->firstidx + intarray->valssize);
4671  do
4672  {
4673  intarray->maxusedidx--;
4674  assert(intarray->minusedidx <= intarray->maxusedidx);
4675  }
4676  while( intarray->vals[intarray->maxusedidx - intarray->firstidx] == 0 );
4677  }
4678  }
4679 
4680  return SCIP_OKAY;
4681 }
4682 
4683 /** increases value of entry in dynamic array */
4685  SCIP_INTARRAY* intarray, /**< dynamic int array */
4686  int arraygrowinit, /**< initial size of array */
4687  SCIP_Real arraygrowfac, /**< growing factor of array */
4688  int idx, /**< array index to increase value for */
4689  int incval /**< value to increase array index */
4690  )
4691 {
4692  return SCIPintarraySetVal(intarray, arraygrowinit, arraygrowfac, idx, SCIPintarrayGetVal(intarray, idx) + incval);
4693 }
4694 
4695 /** returns the minimal index of all stored non-zero elements */
4697  SCIP_INTARRAY* intarray /**< dynamic int array */
4698  )
4699 {
4700  assert(intarray != NULL);
4701 
4702  return intarray->minusedidx;
4703 }
4704 
4705 /** returns the maximal index of all stored non-zero elements */
4707  SCIP_INTARRAY* intarray /**< dynamic int array */
4708  )
4709 {
4710  assert(intarray != NULL);
4711 
4712  return intarray->maxusedidx;
4713 }
4714 
4715 
4716 /** creates a dynamic array of bool values */
4718  SCIP_BOOLARRAY** boolarray, /**< pointer to store the bool array */
4719  BMS_BLKMEM* blkmem /**< block memory */
4720  )
4721 {
4722  assert(boolarray != NULL);
4723  assert(blkmem != NULL);
4724 
4725  SCIP_ALLOC( BMSallocBlockMemory(blkmem, boolarray) );
4726  (*boolarray)->blkmem = blkmem;
4727  (*boolarray)->vals = NULL;
4728  (*boolarray)->valssize = 0;
4729  (*boolarray)->firstidx = -1;
4730  (*boolarray)->minusedidx = INT_MAX;
4731  (*boolarray)->maxusedidx = INT_MIN;
4732 
4733  return SCIP_OKAY;
4734 }
4735 
4736 /** creates a copy of a dynamic array of bool values */
4738  SCIP_BOOLARRAY** boolarray, /**< pointer to store the copied bool array */
4739  BMS_BLKMEM* blkmem, /**< block memory */
4740  SCIP_BOOLARRAY* sourceboolarray /**< dynamic bool array to copy */
4741  )
4742 {
4743  assert(boolarray != NULL);
4744  assert(sourceboolarray != NULL);
4745 
4746  SCIP_CALL( SCIPboolarrayCreate(boolarray, blkmem) );
4747  if( sourceboolarray->valssize > 0 )
4748  {
4749  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*boolarray)->vals, sourceboolarray->vals, \
4750  sourceboolarray->valssize) );
4751  }
4752  (*boolarray)->valssize = sourceboolarray->valssize;
4753  (*boolarray)->firstidx = sourceboolarray->firstidx;
4754  (*boolarray)->minusedidx = sourceboolarray->minusedidx;
4755  (*boolarray)->maxusedidx = sourceboolarray->maxusedidx;
4756 
4757  return SCIP_OKAY;
4758 }
4759 
4760 /** frees a dynamic array of bool values */
4762  SCIP_BOOLARRAY** boolarray /**< pointer to the bool array */
4763  )
4764 {
4765  assert(boolarray != NULL);
4766  assert(*boolarray != NULL);
4767 
4768  BMSfreeBlockMemoryArrayNull((*boolarray)->blkmem, &(*boolarray)->vals, (*boolarray)->valssize);
4769  BMSfreeBlockMemory((*boolarray)->blkmem, boolarray);
4770 
4771  return SCIP_OKAY;
4772 }
4773 
4774 /** extends dynamic array to be able to store indices from minidx to maxidx */
4776  SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4777  int arraygrowinit, /**< initial size of array */
4778  SCIP_Real arraygrowfac, /**< growing factor of array */
4779  int minidx, /**< smallest index to allocate storage for */
4780  int maxidx /**< largest index to allocate storage for */
4781  )
4782 {
4783  int nused;
4784  int nfree;
4785  int newfirstidx;
4786  int i;
4787 
4788  assert(boolarray != NULL);
4789  assert(boolarray->minusedidx == INT_MAX || boolarray->firstidx >= 0);
4790  assert(boolarray->maxusedidx == INT_MIN || boolarray->firstidx >= 0);
4791  assert(boolarray->minusedidx == INT_MAX || boolarray->minusedidx >= boolarray->firstidx);
4792  assert(boolarray->maxusedidx == INT_MIN || boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4793  assert(0 <= minidx);
4794  assert(minidx <= maxidx);
4795 
4796  minidx = MIN(minidx, boolarray->minusedidx);
4797  maxidx = MAX(maxidx, boolarray->maxusedidx);
4798  assert(0 <= minidx);
4799  assert(minidx <= maxidx);
4800 
4801  SCIPdebugMessage("extending boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
4802  (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, minidx, maxidx);
4803 
4804  /* check, whether we have to allocate additional memory, or shift the array */
4805  nused = maxidx - minidx + 1;
4806  if( nused > boolarray->valssize )
4807  {
4808  SCIP_Bool* newvals;
4809  int newvalssize;
4810 
4811  /* allocate new memory storage */
4812  newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
4813  SCIP_ALLOC( BMSallocBlockMemoryArray(boolarray->blkmem, &newvals, newvalssize) );
4814  nfree = newvalssize - nused;
4815  newfirstidx = minidx - nfree/2;
4816  newfirstidx = MAX(newfirstidx, 0);
4817  assert(newfirstidx <= minidx);
4818  assert(maxidx < newfirstidx + newvalssize);
4819 
4820  /* initialize memory array by copying old values and setting new values to zero */
4821  if( boolarray->firstidx != -1 )
4822  {
4823  for( i = 0; i < boolarray->minusedidx - newfirstidx; ++i )
4824  newvals[i] = FALSE;
4825 
4826  /* check for possible overflow or negative value */
4827  assert(boolarray->maxusedidx - boolarray->minusedidx + 1 > 0);
4828 
4829  BMScopyMemoryArray(&newvals[boolarray->minusedidx - newfirstidx],
4830  &boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4831  boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866 !e776*/
4832  for( i = boolarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
4833  newvals[i] = FALSE;
4834  }
4835  else
4836  {
4837  for( i = 0; i < newvalssize; ++i )
4838  newvals[i] = FALSE;
4839  }
4840 
4841  /* free old memory storage, and set the new array parameters */
4842  BMSfreeBlockMemoryArrayNull(boolarray->blkmem, &boolarray->vals, boolarray->valssize);
4843  boolarray->vals = newvals;
4844  boolarray->valssize = newvalssize;
4845  boolarray->firstidx = newfirstidx;
4846  }
4847  else if( boolarray->firstidx == -1 )
4848  {
4849  /* a sufficiently large memory storage exists, but it was cleared */
4850  nfree = boolarray->valssize - nused;
4851  assert(nfree >= 0);
4852  boolarray->firstidx = minidx - nfree/2;
4853  assert(boolarray->firstidx <= minidx);
4854  assert(maxidx < boolarray->firstidx + boolarray->valssize);
4855 #ifndef NDEBUG
4856  for( i = 0; i < boolarray->valssize; ++i )
4857  assert(boolarray->vals[i] == FALSE);
4858 #endif
4859  }
4860  else if( minidx < boolarray->firstidx )
4861  {
4862  /* a sufficiently large memory storage exists, but it has to be shifted to the right */
4863  nfree = boolarray->valssize - nused;
4864  assert(nfree >= 0);
4865  newfirstidx = minidx - nfree/2;
4866  newfirstidx = MAX(newfirstidx, 0);
4867  assert(newfirstidx <= minidx);
4868  assert(maxidx < newfirstidx + boolarray->valssize);
4869 
4870  if( boolarray->minusedidx <= boolarray->maxusedidx )
4871  {
4872  int shift;
4873 
4874  assert(boolarray->firstidx <= boolarray->minusedidx);
4875  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4876 
4877  /* shift used part of array to the right */
4878  shift = boolarray->firstidx - newfirstidx;
4879  assert(shift > 0);
4880  for( i = boolarray->maxusedidx - boolarray->firstidx; i >= boolarray->minusedidx - boolarray->firstidx; --i )
4881  {
4882  assert(0 <= i + shift && i + shift < boolarray->valssize);
4883  boolarray->vals[i + shift] = boolarray->vals[i];
4884  }
4885  /* clear the formerly used head of the array */
4886  for( i = 0; i < shift; ++i )
4887  boolarray->vals[boolarray->minusedidx - boolarray->firstidx + i] = FALSE;
4888  }
4889  boolarray->firstidx = newfirstidx;
4890  }
4891  else if( maxidx >= boolarray->firstidx + boolarray->valssize )
4892  {
4893  /* a sufficiently large memory storage exists, but it has to be shifted to the left */
4894  nfree = boolarray->valssize - nused;
4895  assert(nfree >= 0);
4896  newfirstidx = minidx - nfree/2;
4897  newfirstidx = MAX(newfirstidx, 0);
4898  assert(newfirstidx <= minidx);
4899  assert(maxidx < newfirstidx + boolarray->valssize);
4900 
4901  if( boolarray->minusedidx <= boolarray->maxusedidx )
4902  {
4903  int shift;
4904 
4905  assert(boolarray->firstidx <= boolarray->minusedidx);
4906  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4907 
4908  /* shift used part of array to the left */
4909  shift = newfirstidx - boolarray->firstidx;
4910  assert(shift > 0);
4911 
4912  assert(0 <= boolarray->minusedidx - boolarray->firstidx - shift);
4913  assert(boolarray->maxusedidx - boolarray->firstidx - shift < boolarray->valssize);
4914  BMSmoveMemoryArray(&(boolarray->vals[boolarray->minusedidx - boolarray->firstidx - shift]),
4915  &(boolarray->vals[boolarray->minusedidx - boolarray->firstidx]),
4916  boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
4917 
4918  /* clear the formerly used tail of the array */
4919  for( i = 0; i < shift; ++i )
4920  boolarray->vals[boolarray->maxusedidx - boolarray->firstidx - i] = FALSE;
4921  }
4922  boolarray->firstidx = newfirstidx;
4923  }
4924 
4925  assert(minidx >= boolarray->firstidx);
4926  assert(maxidx < boolarray->firstidx + boolarray->valssize);
4927 
4928  return SCIP_OKAY;
4929 }
4930 
4931 /** clears a dynamic bool array */
4933  SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
4934  )
4935 {
4936  assert(boolarray != NULL);
4937 
4938  SCIPdebugMessage("clearing boolarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
4939  (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx);
4940 
4941  if( boolarray->minusedidx <= boolarray->maxusedidx )
4942  {
4943  assert(boolarray->firstidx <= boolarray->minusedidx);
4944  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
4945  assert(boolarray->firstidx != -1);
4946  assert(boolarray->valssize > 0);
4947 
4948  /* clear the used part of array */
4949  BMSclearMemoryArray(&boolarray->vals[boolarray->minusedidx - boolarray->firstidx],
4950  boolarray->maxusedidx - boolarray->minusedidx + 1); /*lint !e866*/
4951 
4952  /* mark the array cleared */
4953  boolarray->minusedidx = INT_MAX;
4954  boolarray->maxusedidx = INT_MIN;
4955  }
4956  assert(boolarray->minusedidx == INT_MAX);
4957  assert(boolarray->maxusedidx == INT_MIN);
4958 
4959  return SCIP_OKAY;
4960 }
4961 
4962 /** gets value of entry in dynamic array */
4964  SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4965  int idx /**< array index to get value for */
4966  )
4967 {
4968  assert(boolarray != NULL);
4969  assert(idx >= 0);
4970 
4971  if( idx < boolarray->minusedidx || idx > boolarray->maxusedidx )
4972  return FALSE;
4973  else
4974  {
4975  assert(boolarray->vals != NULL);
4976  assert(idx - boolarray->firstidx >= 0);
4977  assert(idx - boolarray->firstidx < boolarray->valssize);
4978 
4979  return boolarray->vals[idx - boolarray->firstidx];
4980  }
4981 }
4982 
4983 /** sets value of entry in dynamic array */
4985  SCIP_BOOLARRAY* boolarray, /**< dynamic bool array */
4986  int arraygrowinit, /**< initial size of array */
4987  SCIP_Real arraygrowfac, /**< growing factor of array */
4988  int idx, /**< array index to set value for */
4989  SCIP_Bool val /**< value to set array index to */
4990  )
4991 {
4992  assert(boolarray != NULL);
4993  assert(idx >= 0);
4994 
4995  SCIPdebugMessage("setting boolarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %u\n",
4996  (void*)boolarray, boolarray->firstidx, boolarray->valssize, boolarray->minusedidx, boolarray->maxusedidx, idx, val);
4997 
4998  if( val != FALSE )
4999  {
5000  /* extend array to be able to store the index */
5001  SCIP_CALL( SCIPboolarrayExtend(boolarray, arraygrowinit, arraygrowfac, idx, idx) );
5002  assert(idx >= boolarray->firstidx);
5003  assert(idx < boolarray->firstidx + boolarray->valssize);
5004 
5005  /* set the array value of the index */
5006  boolarray->vals[idx - boolarray->firstidx] = val;
5007 
5008  /* update min/maxusedidx */
5009  boolarray->minusedidx = MIN(boolarray->minusedidx, idx);
5010  boolarray->maxusedidx = MAX(boolarray->maxusedidx, idx);
5011  }
5012  else if( idx >= boolarray->firstidx && idx < boolarray->firstidx + boolarray->valssize )
5013  {
5014  /* set the array value of the index to zero */
5015  boolarray->vals[idx - boolarray->firstidx] = FALSE;
5016 
5017  /* check, if we can tighten the min/maxusedidx */
5018  if( idx == boolarray->minusedidx )
5019  {
5020  assert(boolarray->maxusedidx >= 0);
5021  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5022  do
5023  {
5024  boolarray->minusedidx++;
5025  }
5026  while( boolarray->minusedidx <= boolarray->maxusedidx
5027  && boolarray->vals[boolarray->minusedidx - boolarray->firstidx] == FALSE );
5028  if( boolarray->minusedidx > boolarray->maxusedidx )
5029  {
5030  boolarray->minusedidx = INT_MAX;
5031  boolarray->maxusedidx = INT_MIN;
5032  }
5033  }
5034  else if( idx == boolarray->maxusedidx )
5035  {
5036  assert(boolarray->minusedidx >= 0);
5037  assert(boolarray->minusedidx < boolarray->maxusedidx);
5038  assert(boolarray->maxusedidx < boolarray->firstidx + boolarray->valssize);
5039  do
5040  {
5041  boolarray->maxusedidx--;
5042  assert(boolarray->minusedidx <= boolarray->maxusedidx);
5043  }
5044  while( boolarray->vals[boolarray->maxusedidx - boolarray->firstidx] == FALSE );
5045  }
5046  }
5047 
5048  return SCIP_OKAY;
5049 }
5050 
5051 /** returns the minimal index of all stored non-zero elements */
5053  SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5054  )
5055 {
5056  assert(boolarray != NULL);
5057 
5058  return boolarray->minusedidx;
5059 }
5060 
5061 /** returns the maximal index of all stored non-zero elements */
5063  SCIP_BOOLARRAY* boolarray /**< dynamic bool array */
5064  )
5065 {
5066  assert(boolarray != NULL);
5067 
5068  return boolarray->maxusedidx;
5069 }
5070 
5071 
5072 /** creates a dynamic array of pointer values */
5074  SCIP_PTRARRAY** ptrarray, /**< pointer to store the ptr array */
5075  BMS_BLKMEM* blkmem /**< block memory */
5076  )
5077 {
5078  assert(ptrarray != NULL);
5079  assert(blkmem != NULL);
5080 
5081  SCIP_ALLOC( BMSallocBlockMemory(blkmem, ptrarray) );
5082  (*ptrarray)->blkmem = blkmem;
5083  (*ptrarray)->vals = NULL;
5084  (*ptrarray)->valssize = 0;
5085  (*ptrarray)->firstidx = -1;
5086  (*ptrarray)->minusedidx = INT_MAX;
5087  (*ptrarray)->maxusedidx = INT_MIN;
5088 
5089  return SCIP_OKAY;
5090 }
5091 
5092 /** creates a copy of a dynamic array of pointer values */
5094  SCIP_PTRARRAY** ptrarray, /**< pointer to store the copied ptr array */
5095  BMS_BLKMEM* blkmem, /**< block memory */
5096  SCIP_PTRARRAY* sourceptrarray /**< dynamic ptr array to copy */
5097  )
5098 {
5099  assert(ptrarray != NULL);
5100  assert(sourceptrarray != NULL);
5101 
5102  SCIP_CALL( SCIPptrarrayCreate(ptrarray, blkmem) );
5103  if( sourceptrarray->valssize > 0 )
5104  {
5105  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*ptrarray)->vals, sourceptrarray->vals, sourceptrarray->valssize) );
5106  }
5107  (*ptrarray)->valssize = sourceptrarray->valssize;
5108  (*ptrarray)->firstidx = sourceptrarray->firstidx;
5109  (*ptrarray)->minusedidx = sourceptrarray->minusedidx;
5110  (*ptrarray)->maxusedidx = sourceptrarray->maxusedidx;
5111 
5112  return SCIP_OKAY;
5113 }
5114 
5115 /** frees a dynamic array of pointer values */
5117  SCIP_PTRARRAY** ptrarray /**< pointer to the ptr array */
5118  )
5119 {
5120  assert(ptrarray != NULL);
5121  assert(*ptrarray != NULL);
5122 
5123  BMSfreeBlockMemoryArrayNull((*ptrarray)->blkmem, &(*ptrarray)->vals, (*ptrarray)->valssize);
5124  BMSfreeBlockMemory((*ptrarray)->blkmem, ptrarray);
5125 
5126  return SCIP_OKAY;
5127 }
5128 
5129 /** extends dynamic array to be able to store indices from minidx to maxidx */
5131  SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5132  int arraygrowinit, /**< initial size of array */
5133  SCIP_Real arraygrowfac, /**< growing factor of array */
5134  int minidx, /**< smallest index to allocate storage for */
5135  int maxidx /**< largest index to allocate storage for */
5136  )
5137 {
5138  int nused;
5139  int nfree;
5140  int newfirstidx;
5141  int i;
5142 
5143  assert(ptrarray != NULL);
5144  assert(ptrarray->minusedidx == INT_MAX || ptrarray->firstidx >= 0);
5145  assert(ptrarray->maxusedidx == INT_MIN || ptrarray->firstidx >= 0);
5146  assert(ptrarray->minusedidx == INT_MAX || ptrarray->minusedidx >= ptrarray->firstidx);
5147  assert(ptrarray->maxusedidx == INT_MIN || ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5148  assert(0 <= minidx);
5149  assert(minidx <= maxidx);
5150 
5151  minidx = MIN(minidx, ptrarray->minusedidx);
5152  maxidx = MAX(maxidx, ptrarray->maxusedidx);
5153  assert(0 <= minidx);
5154  assert(minidx <= maxidx);
5155 
5156  SCIPdebugMessage("extending ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) to range [%d,%d]\n",
5157  (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, minidx, maxidx);
5158 
5159  /* check, whether we have to allocate additional memory, or shift the array */
5160  nused = maxidx - minidx + 1;
5161  if( nused > ptrarray->valssize )
5162  {
5163  void** newvals;
5164  int newvalssize;
5165 
5166  /* allocate new memory storage */
5167  newvalssize = calcGrowSize(arraygrowinit, arraygrowfac, nused);
5168  SCIP_ALLOC( BMSallocBlockMemoryArray(ptrarray->blkmem, &newvals, newvalssize) );
5169  nfree = newvalssize - nused;
5170  newfirstidx = minidx - nfree/2;
5171  newfirstidx = MAX(newfirstidx, 0);
5172  assert(newfirstidx <= minidx);
5173  assert(maxidx < newfirstidx + newvalssize);
5174 
5175  /* initialize memory array by copying old values and setting new values to zero */
5176  if( ptrarray->firstidx != -1 )
5177  {
5178  for( i = 0; i < ptrarray->minusedidx - newfirstidx; ++i )
5179  newvals[i] = NULL;
5180 
5181  /* check for possible overflow or negative value */
5182  assert(ptrarray->maxusedidx - ptrarray->minusedidx + 1 > 0);
5183 
5184  BMScopyMemoryArray(&newvals[ptrarray->minusedidx - newfirstidx],
5185  &(ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx]),
5186  ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866 !e776*/
5187  for( i = ptrarray->maxusedidx - newfirstidx + 1; i < newvalssize; ++i )
5188  newvals[i] = NULL;
5189  }
5190  else
5191  {
5192  for( i = 0; i < newvalssize; ++i )
5193  newvals[i] = NULL;
5194  }
5195 
5196  /* free old memory storage, and set the new array parameters */
5197  BMSfreeBlockMemoryArrayNull(ptrarray->blkmem, &ptrarray->vals, ptrarray->valssize);
5198  ptrarray->vals = newvals;
5199  ptrarray->valssize = newvalssize;
5200  ptrarray->firstidx = newfirstidx;
5201  }
5202  else if( ptrarray->firstidx == -1 )
5203  {
5204  /* a sufficiently large memory storage exists, but it was cleared */
5205  nfree = ptrarray->valssize - nused;
5206  assert(nfree >= 0);
5207  ptrarray->firstidx = minidx - nfree/2;
5208  assert(ptrarray->firstidx <= minidx);
5209  assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5210 #ifndef NDEBUG
5211  for( i = 0; i < ptrarray->valssize; ++i )
5212  assert(ptrarray->vals[i] == NULL);
5213 #endif
5214  }
5215  else if( minidx < ptrarray->firstidx )
5216  {
5217  /* a sufficiently large memory storage exists, but it has to be shifted to the right */
5218  nfree = ptrarray->valssize - nused;
5219  assert(nfree >= 0);
5220  newfirstidx = minidx - nfree/2;
5221  newfirstidx = MAX(newfirstidx, 0);
5222  assert(newfirstidx <= minidx);
5223  assert(maxidx < newfirstidx + ptrarray->valssize);
5224 
5225  if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5226  {
5227  int shift;
5228 
5229  assert(ptrarray->firstidx <= ptrarray->minusedidx);
5230  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5231 
5232  /* shift used part of array to the right */
5233  shift = ptrarray->firstidx - newfirstidx;
5234  assert(shift > 0);
5235  for( i = ptrarray->maxusedidx - ptrarray->firstidx; i >= ptrarray->minusedidx - ptrarray->firstidx; --i )
5236  {
5237  assert(0 <= i + shift && i + shift < ptrarray->valssize);
5238  ptrarray->vals[i + shift] = ptrarray->vals[i];
5239  }
5240  /* clear the formerly used head of the array */
5241  for( i = 0; i < shift; ++i )
5242  ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx + i] = NULL;
5243  }
5244  ptrarray->firstidx = newfirstidx;
5245  }
5246  else if( maxidx >= ptrarray->firstidx + ptrarray->valssize )
5247  {
5248  /* a sufficiently large memory storage exists, but it has to be shifted to the left */
5249  nfree = ptrarray->valssize - nused;
5250  assert(nfree >= 0);
5251  newfirstidx = minidx - nfree/2;
5252  newfirstidx = MAX(newfirstidx, 0);
5253  assert(newfirstidx <= minidx);
5254  assert(maxidx < newfirstidx + ptrarray->valssize);
5255 
5256  if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5257  {
5258  int shift;
5259 
5260  assert(ptrarray->firstidx <= ptrarray->minusedidx);
5261  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5262 
5263  /* shift used part of array to the left */
5264  shift = newfirstidx - ptrarray->firstidx;
5265  assert(shift > 0);
5266  for( i = ptrarray->minusedidx - ptrarray->firstidx; i <= ptrarray->maxusedidx - ptrarray->firstidx; ++i )
5267  {
5268  assert(0 <= i - shift && i - shift < ptrarray->valssize);
5269  ptrarray->vals[i - shift] = ptrarray->vals[i];
5270  }
5271  /* clear the formerly used tail of the array */
5272  for( i = 0; i < shift; ++i )
5273  ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx - i] = NULL;
5274  }
5275  ptrarray->firstidx = newfirstidx;
5276  }
5277 
5278  assert(minidx >= ptrarray->firstidx);
5279  assert(maxidx < ptrarray->firstidx + ptrarray->valssize);
5280 
5281  return SCIP_OKAY;
5282 }
5283 
5284 /** clears a dynamic pointer array */
5286  SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5287  )
5288 {
5289  assert(ptrarray != NULL);
5290 
5291  SCIPdebugMessage("clearing ptrarray %p (firstidx=%d, size=%d, range=[%d,%d])\n",
5292  (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx);
5293 
5294  if( ptrarray->minusedidx <= ptrarray->maxusedidx )
5295  {
5296  assert(ptrarray->firstidx <= ptrarray->minusedidx);
5297  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5298  assert(ptrarray->firstidx != -1);
5299  assert(ptrarray->valssize > 0);
5300 
5301  /* clear the used part of array */
5302  BMSclearMemoryArray(&ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx],
5303  ptrarray->maxusedidx - ptrarray->minusedidx + 1); /*lint !e866*/
5304 
5305  /* mark the array cleared */
5306  ptrarray->minusedidx = INT_MAX;
5307  ptrarray->maxusedidx = INT_MIN;
5308  }
5309  assert(ptrarray->minusedidx == INT_MAX);
5310  assert(ptrarray->maxusedidx == INT_MIN);
5311 
5312  return SCIP_OKAY;
5313 }
5314 
5315 /** gets value of entry in dynamic array */
5317  SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5318  int idx /**< array index to get value for */
5319  )
5320 {
5321  assert(ptrarray != NULL);
5322  assert(idx >= 0);
5323 
5324  if( idx < ptrarray->minusedidx || idx > ptrarray->maxusedidx )
5325  return NULL;
5326  else
5327  {
5328  assert(ptrarray->vals != NULL);
5329  assert(idx - ptrarray->firstidx >= 0);
5330  assert(idx - ptrarray->firstidx < ptrarray->valssize);
5331 
5332  return ptrarray->vals[idx - ptrarray->firstidx];
5333  }
5334 }
5335 
5336 /** sets value of entry in dynamic array */
5338  SCIP_PTRARRAY* ptrarray, /**< dynamic ptr array */
5339  int arraygrowinit, /**< initial size of array */
5340  SCIP_Real arraygrowfac, /**< growing factor of array */
5341  int idx, /**< array index to set value for */
5342  void* val /**< value to set array index to */
5343  )
5344 {
5345  assert(ptrarray != NULL);
5346  assert(idx >= 0);
5347 
5348  SCIPdebugMessage("setting ptrarray %p (firstidx=%d, size=%d, range=[%d,%d]) index %d to %p\n",
5349  (void*)ptrarray, ptrarray->firstidx, ptrarray->valssize, ptrarray->minusedidx, ptrarray->maxusedidx, idx, val);
5350 
5351  if( val != NULL )
5352  {
5353  /* extend array to be able to store the index */
5354  SCIP_CALL( SCIPptrarrayExtend(ptrarray, arraygrowinit, arraygrowfac, idx, idx) );
5355  assert(idx >= ptrarray->firstidx);
5356  assert(idx < ptrarray->firstidx + ptrarray->valssize);
5357 
5358  /* set the array value of the index */
5359  ptrarray->vals[idx - ptrarray->firstidx] = val;
5360 
5361  /* update min/maxusedidx */
5362  ptrarray->minusedidx = MIN(ptrarray->minusedidx, idx);
5363  ptrarray->maxusedidx = MAX(ptrarray->maxusedidx, idx);
5364  }
5365  else if( idx >= ptrarray->firstidx && idx < ptrarray->firstidx + ptrarray->valssize )
5366  {
5367  /* set the array value of the index to zero */
5368  ptrarray->vals[idx - ptrarray->firstidx] = NULL;
5369 
5370  /* check, if we can tighten the min/maxusedidx */
5371  if( idx == ptrarray->minusedidx )
5372  {
5373  assert(ptrarray->maxusedidx >= 0);
5374  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5375  do
5376  {
5377  ptrarray->minusedidx++;
5378  }
5379  while( ptrarray->minusedidx <= ptrarray->maxusedidx
5380  && ptrarray->vals[ptrarray->minusedidx - ptrarray->firstidx] == NULL );
5381  if( ptrarray->minusedidx > ptrarray->maxusedidx )
5382  {
5383  ptrarray->minusedidx = INT_MAX;
5384  ptrarray->maxusedidx = INT_MIN;
5385  }
5386  }
5387  else if( idx == ptrarray->maxusedidx )
5388  {
5389  assert(ptrarray->minusedidx >= 0);
5390  assert(ptrarray->minusedidx < ptrarray->maxusedidx);
5391  assert(ptrarray->maxusedidx < ptrarray->firstidx + ptrarray->valssize);
5392  do
5393  {
5394  ptrarray->maxusedidx--;
5395  assert(ptrarray->minusedidx <= ptrarray->maxusedidx);
5396  }
5397  while( ptrarray->vals[ptrarray->maxusedidx - ptrarray->firstidx] == NULL );
5398  }
5399  }
5400 
5401  return SCIP_OKAY;
5402 }
5403 
5404 /** returns the minimal index of all stored non-zero elements */
5406  SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5407  )
5408 {
5409  assert(ptrarray != NULL);
5410 
5411  return ptrarray->minusedidx;
5412 }
5413 
5414 /** returns the maximal index of all stored non-zero elements */
5416  SCIP_PTRARRAY* ptrarray /**< dynamic ptr array */
5417  )
5418 {
5419  assert(ptrarray != NULL);
5420 
5421  return ptrarray->maxusedidx;
5422 }
5423 
5424 
5425 /*
5426  * Sorting algorithms
5427  */
5428 
5429 /** default comparer for integers */
5430 SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
5431 {
5432  int value1;
5433  int value2;
5434 
5435  value1 = (int)(size_t)elem1;
5436  value2 = (int)(size_t)elem2;
5437 
5438  if( value1 < value2 )
5439  return -1;
5440 
5441  if( value2 < value1 )
5442  return 1;
5443 
5444  return 0;
5445 }
5446 
5447 /* first all upwards-sorting methods */
5448 
5449 /** sort an indexed element set in non-decreasing order, resulting in a permutation index array */
5451  int* perm, /**< pointer to store the resulting permutation */
5452  SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
5453  void* dataptr, /**< pointer to data field that is given to the external compare method */
5454  int len /**< number of elements to be sorted (valid index range) */
5455  )
5456 {
5457  int pos;
5458 
5459  assert(indcomp != NULL);
5460  assert(len == 0 || perm != NULL);
5461 
5462  /* create identity permutation */
5463  for( pos = 0; pos < len; ++pos )
5464  perm[pos] = pos;
5465 
5466  SCIPsortInd(perm, indcomp, dataptr, len);
5467 }
5468 
5469 /* SCIPsortInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5470 #define SORTTPL_NAMEEXT Ind
5471 #define SORTTPL_KEYTYPE int
5472 #define SORTTPL_INDCOMP
5473 #include "scip/sorttpl.c" /*lint !e451*/
5474 
5475 
5476 /* SCIPsortPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5477 #define SORTTPL_NAMEEXT Ptr
5478 #define SORTTPL_KEYTYPE void*
5479 #define SORTTPL_PTRCOMP
5480 #include "scip/sorttpl.c" /*lint !e451*/
5481 
5482 
5483 /* SCIPsortPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5484 #define SORTTPL_NAMEEXT PtrPtr
5485 #define SORTTPL_KEYTYPE void*
5486 #define SORTTPL_FIELD1TYPE void*
5487 #define SORTTPL_PTRCOMP
5488 #include "scip/sorttpl.c" /*lint !e451*/
5489 
5490 
5491 /* SCIPsortPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5492 #define SORTTPL_NAMEEXT PtrReal
5493 #define SORTTPL_KEYTYPE void*
5494 #define SORTTPL_FIELD1TYPE SCIP_Real
5495 #define SORTTPL_PTRCOMP
5496 #include "scip/sorttpl.c" /*lint !e451*/
5497 
5498 
5499 /* SCIPsortPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5500 #define SORTTPL_NAMEEXT PtrInt
5501 #define SORTTPL_KEYTYPE void*
5502 #define SORTTPL_FIELD1TYPE int
5503 #define SORTTPL_PTRCOMP
5504 #include "scip/sorttpl.c" /*lint !e451*/
5505 
5506 
5507 /* SCIPsortPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5508 #define SORTTPL_NAMEEXT PtrBool
5509 #define SORTTPL_KEYTYPE void*
5510 #define SORTTPL_FIELD1TYPE SCIP_Bool
5511 #define SORTTPL_PTRCOMP
5512 #include "scip/sorttpl.c" /*lint !e451*/
5513 
5514 
5515 /* SCIPsortPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5516 #define SORTTPL_NAMEEXT PtrIntInt
5517 #define SORTTPL_KEYTYPE void*
5518 #define SORTTPL_FIELD1TYPE int
5519 #define SORTTPL_FIELD2TYPE int
5520 #define SORTTPL_PTRCOMP
5521 #include "scip/sorttpl.c" /*lint !e451*/
5522 
5523 
5524 /* SCIPsortPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5525 #define SORTTPL_NAMEEXT PtrRealInt
5526 #define SORTTPL_KEYTYPE void*
5527 #define SORTTPL_FIELD1TYPE SCIP_Real
5528 #define SORTTPL_FIELD2TYPE int
5529 #define SORTTPL_PTRCOMP
5530 #include "scip/sorttpl.c" /*lint !e451*/
5531 
5532 /* SCIPsortPtrRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5533 #define SORTTPL_NAMEEXT PtrRealRealInt
5534 #define SORTTPL_KEYTYPE void*
5535 #define SORTTPL_FIELD1TYPE SCIP_Real
5536 #define SORTTPL_FIELD2TYPE SCIP_Real
5537 #define SORTTPL_FIELD3TYPE int
5538 #define SORTTPL_PTRCOMP
5539 #include "scip/sorttpl.c" /*lint !e451*/
5540 
5541 /* SCIPsortPtrRealRealBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5542 #define SORTTPL_NAMEEXT PtrRealRealBoolBool
5543 #define SORTTPL_KEYTYPE void*
5544 #define SORTTPL_FIELD1TYPE SCIP_Real
5545 #define SORTTPL_FIELD2TYPE SCIP_Real
5546 #define SORTTPL_FIELD3TYPE SCIP_Bool
5547 #define SORTTPL_FIELD4TYPE SCIP_Bool
5548 #define SORTTPL_PTRCOMP
5549 #include "scip/sorttpl.c" /*lint !e451*/
5550 
5551 /* SCIPsortPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5552 #define SORTTPL_NAMEEXT PtrRealRealIntBool
5553 #define SORTTPL_KEYTYPE void*
5554 #define SORTTPL_FIELD1TYPE SCIP_Real
5555 #define SORTTPL_FIELD2TYPE SCIP_Real
5556 #define SORTTPL_FIELD3TYPE int
5557 #define SORTTPL_FIELD4TYPE SCIP_Bool
5558 #define SORTTPL_PTRCOMP
5559 #include "scip/sorttpl.c" /*lint !e451*/
5560 
5561 /* SCIPsortPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5562 #define SORTTPL_NAMEEXT PtrRealBool
5563 #define SORTTPL_KEYTYPE void*
5564 #define SORTTPL_FIELD1TYPE SCIP_Real
5565 #define SORTTPL_FIELD2TYPE SCIP_Bool
5566 #define SORTTPL_PTRCOMP
5567 #include "scip/sorttpl.c" /*lint !e451*/
5568 
5569 
5570 /* SCIPsortPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5571 #define SORTTPL_NAMEEXT PtrPtrInt
5572 #define SORTTPL_KEYTYPE void*
5573 #define SORTTPL_FIELD1TYPE void*
5574 #define SORTTPL_FIELD2TYPE int
5575 #define SORTTPL_PTRCOMP
5576 #include "scip/sorttpl.c" /*lint !e451*/
5577 
5578 
5579 /* SCIPsortPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5580 #define SORTTPL_NAMEEXT PtrPtrReal
5581 #define SORTTPL_KEYTYPE void*
5582 #define SORTTPL_FIELD1TYPE void*
5583 #define SORTTPL_FIELD2TYPE SCIP_Real
5584 #define SORTTPL_PTRCOMP
5585 #include "scip/sorttpl.c" /*lint !e451*/
5586 
5587 
5588 /* SCIPsortPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5589 #define SORTTPL_NAMEEXT PtrRealIntInt
5590 #define SORTTPL_KEYTYPE void*
5591 #define SORTTPL_FIELD1TYPE SCIP_Real
5592 #define SORTTPL_FIELD2TYPE int
5593 #define SORTTPL_FIELD3TYPE int
5594 #define SORTTPL_PTRCOMP
5595 #include "scip/sorttpl.c" /*lint !e451*/
5596 
5597 
5598 /* SCIPsortPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5599 #define SORTTPL_NAMEEXT PtrPtrIntInt
5600 #define SORTTPL_KEYTYPE void*
5601 #define SORTTPL_FIELD1TYPE void*
5602 #define SORTTPL_FIELD2TYPE int
5603 #define SORTTPL_FIELD3TYPE int
5604 #define SORTTPL_PTRCOMP
5605 #include "scip/sorttpl.c" /*lint !e451*/
5606 
5607 
5608 /* SCIPsortPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5609 #define SORTTPL_NAMEEXT PtrPtrRealInt
5610 #define SORTTPL_KEYTYPE void*
5611 #define SORTTPL_FIELD1TYPE void*
5612 #define SORTTPL_FIELD2TYPE SCIP_Real
5613 #define SORTTPL_FIELD3TYPE int
5614 #define SORTTPL_PTRCOMP
5615 #include "scip/sorttpl.c" /*lint !e451*/
5616 
5617 
5618 /* SCIPsortPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5619 #define SORTTPL_NAMEEXT PtrPtrRealBool
5620 #define SORTTPL_KEYTYPE void*
5621 #define SORTTPL_FIELD1TYPE void*
5622 #define SORTTPL_FIELD2TYPE SCIP_Real
5623 #define SORTTPL_FIELD3TYPE SCIP_Bool
5624 #define SORTTPL_PTRCOMP
5625 #include "scip/sorttpl.c" /*lint !e451*/
5626 
5627 
5628 /* SCIPsortPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5629 #define SORTTPL_NAMEEXT PtrPtrLongInt
5630 #define SORTTPL_KEYTYPE void*
5631 #define SORTTPL_FIELD1TYPE void*
5632 #define SORTTPL_FIELD2TYPE SCIP_Longint
5633 #define SORTTPL_FIELD3TYPE int
5634 #define SORTTPL_PTRCOMP
5635 #include "scip/sorttpl.c" /*lint !e451*/
5636 
5637 
5638 /* SCIPsortPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5639 #define SORTTPL_NAMEEXT PtrPtrLongIntInt
5640 #define SORTTPL_KEYTYPE void*
5641 #define SORTTPL_FIELD1TYPE void*
5642 #define SORTTPL_FIELD2TYPE SCIP_Longint
5643 #define SORTTPL_FIELD3TYPE int
5644 #define SORTTPL_FIELD4TYPE int
5645 #define SORTTPL_PTRCOMP
5646 #include "scip/sorttpl.c" /*lint !e451*/
5647 
5648 
5649 /* SCIPsortReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5650 #define SORTTPL_NAMEEXT Real
5651 #define SORTTPL_KEYTYPE SCIP_Real
5652 #include "scip/sorttpl.c" /*lint !e451*/
5653 
5654 
5655 /* SCIPsortRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5656 #define SORTTPL_NAMEEXT RealBoolPtr
5657 #define SORTTPL_KEYTYPE SCIP_Real
5658 #define SORTTPL_FIELD1TYPE SCIP_Bool
5659 #define SORTTPL_FIELD2TYPE void*
5660 #include "scip/sorttpl.c" /*lint !e451*/
5661 
5662 
5663 /* SCIPsortRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5664 #define SORTTPL_NAMEEXT RealPtr
5665 #define SORTTPL_KEYTYPE SCIP_Real
5666 #define SORTTPL_FIELD1TYPE void*
5667 #include "scip/sorttpl.c" /*lint !e451*/
5668 
5669 
5670 /* SCIPsortRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5671 #define SORTTPL_NAMEEXT RealInt
5672 #define SORTTPL_KEYTYPE SCIP_Real
5673 #define SORTTPL_FIELD1TYPE int
5674 #include "scip/sorttpl.c" /*lint !e451*/
5675 
5676 
5677 /* SCIPsortRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5678 #define SORTTPL_NAMEEXT RealIntInt
5679 #define SORTTPL_KEYTYPE SCIP_Real
5680 #define SORTTPL_FIELD1TYPE int
5681 #define SORTTPL_FIELD2TYPE int
5682 #include "scip/sorttpl.c" /*lint !e451*/
5683 
5684 
5685 /* SCIPsortRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5686 #define SORTTPL_NAMEEXT RealIntLong
5687 #define SORTTPL_KEYTYPE SCIP_Real
5688 #define SORTTPL_FIELD1TYPE int
5689 #define SORTTPL_FIELD2TYPE SCIP_Longint
5690 #include "scip/sorttpl.c" /*lint !e451*/
5691 
5692 
5693 /* SCIPsortRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5694 #define SORTTPL_NAMEEXT RealIntPtr
5695 #define SORTTPL_KEYTYPE SCIP_Real
5696 #define SORTTPL_FIELD1TYPE int
5697 #define SORTTPL_FIELD2TYPE void*
5698 #include "scip/sorttpl.c" /*lint !e451*/
5699 
5700 
5701 /* SCIPsortRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5702 #define SORTTPL_NAMEEXT RealRealPtr
5703 #define SORTTPL_KEYTYPE SCIP_Real
5704 #define SORTTPL_FIELD1TYPE SCIP_Real
5705 #define SORTTPL_FIELD2TYPE void*
5706 #include "scip/sorttpl.c" /*lint !e451*/
5707 
5708 
5709 /* SCIPsortRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5710 #define SORTTPL_NAMEEXT RealLongRealInt
5711 #define SORTTPL_KEYTYPE SCIP_Real
5712 #define SORTTPL_FIELD1TYPE SCIP_Longint
5713 #define SORTTPL_FIELD2TYPE SCIP_Real
5714 #define SORTTPL_FIELD3TYPE int
5715 #include "scip/sorttpl.c" /*lint !e451*/
5716 
5717 /* SCIPsortRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5718 #define SORTTPL_NAMEEXT RealRealIntInt
5719 #define SORTTPL_KEYTYPE SCIP_Real
5720 #define SORTTPL_FIELD1TYPE SCIP_Real
5721 #define SORTTPL_FIELD2TYPE int
5722 #define SORTTPL_FIELD3TYPE int
5723 #include "scip/sorttpl.c" /*lint !e451*/
5724 
5725 
5726 /* SCIPsortRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5727 #define SORTTPL_NAMEEXT RealRealRealInt
5728 #define SORTTPL_KEYTYPE SCIP_Real
5729 #define SORTTPL_FIELD1TYPE SCIP_Real
5730 #define SORTTPL_FIELD2TYPE SCIP_Real
5731 #define SORTTPL_FIELD3TYPE int
5732 #include "scip/sorttpl.c" /*lint !e451*/
5733 
5734 
5735 /* SCIPsortRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5736 #define SORTTPL_NAMEEXT RealRealRealPtr
5737 #define SORTTPL_KEYTYPE SCIP_Real
5738 #define SORTTPL_FIELD1TYPE SCIP_Real
5739 #define SORTTPL_FIELD2TYPE SCIP_Real
5740 #define SORTTPL_FIELD3TYPE void*
5741 #include "scip/sorttpl.c" /*lint !e451*/
5742 
5743 
5744 /* SCIPsortRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5745 #define SORTTPL_NAMEEXT RealPtrPtrInt
5746 #define SORTTPL_KEYTYPE SCIP_Real
5747 #define SORTTPL_FIELD1TYPE void*
5748 #define SORTTPL_FIELD2TYPE void*
5749 #define SORTTPL_FIELD3TYPE int
5750 #include "scip/sorttpl.c" /*lint !e451*/
5751 
5752 
5753 /* SCIPsortRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5754 #define SORTTPL_NAMEEXT RealPtrPtrIntInt
5755 #define SORTTPL_KEYTYPE SCIP_Real
5756 #define SORTTPL_FIELD1TYPE void*
5757 #define SORTTPL_FIELD2TYPE void*
5758 #define SORTTPL_FIELD3TYPE int
5759 #define SORTTPL_FIELD4TYPE int
5760 #include "scip/sorttpl.c" /*lint !e451*/
5761 
5762 
5763 /* SCIPsortRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5764 #define SORTTPL_NAMEEXT RealRealRealBoolPtr
5765 #define SORTTPL_KEYTYPE SCIP_Real
5766 #define SORTTPL_FIELD1TYPE SCIP_Real
5767 #define SORTTPL_FIELD2TYPE SCIP_Real
5768 #define SORTTPL_FIELD3TYPE SCIP_Bool
5769 #define SORTTPL_FIELD4TYPE void*
5770 #include "scip/sorttpl.c" /*lint !e451*/
5771 
5772 
5773 /* SCIPsortRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5774 #define SORTTPL_NAMEEXT RealRealRealBoolBoolPtr
5775 #define SORTTPL_KEYTYPE SCIP_Real
5776 #define SORTTPL_FIELD1TYPE SCIP_Real
5777 #define SORTTPL_FIELD2TYPE SCIP_Real
5778 #define SORTTPL_FIELD3TYPE SCIP_Bool
5779 #define SORTTPL_FIELD4TYPE SCIP_Bool
5780 #define SORTTPL_FIELD5TYPE void*
5781 #include "scip/sorttpl.c" /*lint !e451*/
5782 
5783 
5784 /* SCIPsortInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5785 #define SORTTPL_NAMEEXT Int
5786 #define SORTTPL_KEYTYPE int
5787 #include "scip/sorttpl.c" /*lint !e451*/
5788 
5789 
5790 /* SCIPsortIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5791 #define SORTTPL_NAMEEXT IntInt
5792 #define SORTTPL_KEYTYPE int
5793 #define SORTTPL_FIELD1TYPE int
5794 #include "scip/sorttpl.c" /*lint !e451*/
5795 
5796 
5797 /* SCIPsortIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5798 #define SORTTPL_NAMEEXT IntReal
5799 #define SORTTPL_KEYTYPE int
5800 #define SORTTPL_FIELD1TYPE SCIP_Real
5801 #include "scip/sorttpl.c" /*lint !e451*/
5802 
5803 
5804 /* SCIPsortIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5805 #define SORTTPL_NAMEEXT IntPtr
5806 #define SORTTPL_KEYTYPE int
5807 #define SORTTPL_FIELD1TYPE void*
5808 #include "scip/sorttpl.c" /*lint !e451*/
5809 
5810 
5811 /* SCIPsortIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5812 #define SORTTPL_NAMEEXT IntIntInt
5813 #define SORTTPL_KEYTYPE int
5814 #define SORTTPL_FIELD1TYPE int
5815 #define SORTTPL_FIELD2TYPE int
5816 #include "scip/sorttpl.c" /*lint !e451*/
5817 
5818 
5819 /* SCIPsortIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5820 #define SORTTPL_NAMEEXT IntIntLong
5821 #define SORTTPL_KEYTYPE int
5822 #define SORTTPL_FIELD1TYPE int
5823 #define SORTTPL_FIELD2TYPE SCIP_Longint
5824 #include "scip/sorttpl.c" /*lint !e451*/
5825 
5826 /* SCIPsortIntRealLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5827 #define SORTTPL_NAMEEXT IntRealLong
5828 #define SORTTPL_KEYTYPE int
5829 #define SORTTPL_FIELD1TYPE SCIP_Real
5830 #define SORTTPL_FIELD2TYPE SCIP_Longint
5831 #include "scip/sorttpl.c" /*lint !e451*/
5832 
5833 
5834 /* SCIPsortIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5835 #define SORTTPL_NAMEEXT IntIntPtr
5836 #define SORTTPL_KEYTYPE int
5837 #define SORTTPL_FIELD1TYPE int
5838 #define SORTTPL_FIELD2TYPE void*
5839 #include "scip/sorttpl.c" /*lint !e451*/
5840 
5841 
5842 /* SCIPsortIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5843 #define SORTTPL_NAMEEXT IntIntReal
5844 #define SORTTPL_KEYTYPE int
5845 #define SORTTPL_FIELD1TYPE int
5846 #define SORTTPL_FIELD2TYPE SCIP_Real
5847 #include "scip/sorttpl.c" /*lint !e451*/
5848 
5849 
5850 /* SCIPsortIntPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5851 #define SORTTPL_NAMEEXT IntPtrReal
5852 #define SORTTPL_KEYTYPE int
5853 #define SORTTPL_FIELD1TYPE void*
5854 #define SORTTPL_FIELD2TYPE SCIP_Real
5855 #include "scip/sorttpl.c" /*lint !e451*/
5856 
5857 
5858 /* SCIPsortIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5859 #define SORTTPL_NAMEEXT IntIntIntPtr
5860 #define SORTTPL_KEYTYPE int
5861 #define SORTTPL_FIELD1TYPE int
5862 #define SORTTPL_FIELD2TYPE int
5863 #define SORTTPL_FIELD3TYPE void*
5864 #include "scip/sorttpl.c" /*lint !e451*/
5865 
5866 /* SCIPsortIntIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5867 #define SORTTPL_NAMEEXT IntIntIntReal
5868 #define SORTTPL_KEYTYPE int
5869 #define SORTTPL_FIELD1TYPE int
5870 #define SORTTPL_FIELD2TYPE int
5871 #define SORTTPL_FIELD3TYPE SCIP_Real
5872 #include "scip/sorttpl.c" /*lint !e451*/
5873 
5874 /* SCIPsortIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5875 #define SORTTPL_NAMEEXT IntPtrIntReal
5876 #define SORTTPL_KEYTYPE int
5877 #define SORTTPL_FIELD1TYPE void*
5878 #define SORTTPL_FIELD2TYPE int
5879 #define SORTTPL_FIELD3TYPE SCIP_Real
5880 #include "scip/sorttpl.c" /*lint !e451*/
5881 
5882 
5883 /* SCIPsortLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5884 #define SORTTPL_NAMEEXT Long
5885 #define SORTTPL_KEYTYPE SCIP_Longint
5886 #include "scip/sorttpl.c" /*lint !e451*/
5887 
5888 
5889 /* SCIPsortLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5890 #define SORTTPL_NAMEEXT LongPtr
5891 #define SORTTPL_KEYTYPE SCIP_Longint
5892 #define SORTTPL_FIELD1TYPE void*
5893 #include "scip/sorttpl.c" /*lint !e451*/
5894 
5895 
5896 /* SCIPsortLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5897 #define SORTTPL_NAMEEXT LongPtrInt
5898 #define SORTTPL_KEYTYPE SCIP_Longint
5899 #define SORTTPL_FIELD1TYPE void*
5900 #define SORTTPL_FIELD2TYPE int
5901 #include "scip/sorttpl.c" /*lint !e451*/
5902 
5903 
5904 /* SCIPsortLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5905 #define SORTTPL_NAMEEXT LongPtrRealBool
5906 #define SORTTPL_KEYTYPE SCIP_Longint
5907 #define SORTTPL_FIELD1TYPE void*
5908 #define SORTTPL_FIELD2TYPE SCIP_Real
5909 #define SORTTPL_FIELD3TYPE SCIP_Bool
5910 #include "scip/sorttpl.c" /*lint !e451*/
5911 
5912 
5913 /* SCIPsortLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5914 #define SORTTPL_NAMEEXT LongPtrRealRealBool
5915 #define SORTTPL_KEYTYPE SCIP_Longint
5916 #define SORTTPL_FIELD1TYPE void*
5917 #define SORTTPL_FIELD2TYPE SCIP_Real
5918 #define SORTTPL_FIELD3TYPE SCIP_Real
5919 #define SORTTPL_FIELD4TYPE SCIP_Bool
5920 #include "scip/sorttpl.c" /*lint !e451*/
5921 
5922 
5923 /* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5924 #define SORTTPL_NAMEEXT LongPtrRealRealIntBool
5925 #define SORTTPL_KEYTYPE SCIP_Longint
5926 #define SORTTPL_FIELD1TYPE void*
5927 #define SORTTPL_FIELD2TYPE SCIP_Real
5928 #define SORTTPL_FIELD3TYPE SCIP_Real
5929 #define SORTTPL_FIELD4TYPE int
5930 #define SORTTPL_FIELD5TYPE SCIP_Bool
5931 #include "scip/sorttpl.c" /*lint !e451*/
5932 
5933 
5934 /* SCIPsortLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5935 #define SORTTPL_NAMEEXT LongPtrPtrInt
5936 #define SORTTPL_KEYTYPE SCIP_Longint
5937 #define SORTTPL_FIELD1TYPE void*
5938 #define SORTTPL_FIELD2TYPE void*
5939 #define SORTTPL_FIELD3TYPE int
5940 #include "scip/sorttpl.c" /*lint !e451*/
5941 
5942 
5943 /* SCIPsortLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5944 #define SORTTPL_NAMEEXT LongPtrPtrIntInt
5945 #define SORTTPL_KEYTYPE SCIP_Longint
5946 #define SORTTPL_FIELD1TYPE void*
5947 #define SORTTPL_FIELD2TYPE void*
5948 #define SORTTPL_FIELD3TYPE int
5949 #define SORTTPL_FIELD4TYPE int
5950 #include "scip/sorttpl.c" /*lint !e451*/
5951 
5952 
5953 /* SCIPsortLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5954 #define SORTTPL_NAMEEXT LongPtrPtrBoolInt
5955 #define SORTTPL_KEYTYPE SCIP_Longint
5956 #define SORTTPL_FIELD1TYPE void*
5957 #define SORTTPL_FIELD2TYPE void*
5958 #define SORTTPL_FIELD3TYPE SCIP_Bool
5959 #define SORTTPL_FIELD4TYPE int
5960 #include "scip/sorttpl.c" /*lint !e451*/
5961 
5962 
5963 /* SCIPsortPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5964 #define SORTTPL_NAMEEXT PtrIntIntBoolBool
5965 #define SORTTPL_KEYTYPE void*
5966 #define SORTTPL_FIELD1TYPE int
5967 #define SORTTPL_FIELD2TYPE int
5968 #define SORTTPL_FIELD3TYPE SCIP_Bool
5969 #define SORTTPL_FIELD4TYPE SCIP_Bool
5970 #define SORTTPL_PTRCOMP
5971 #include "scip/sorttpl.c" /*lint !e451*/
5972 
5973 
5974 /* SCIPsortIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
5975 #define SORTTPL_NAMEEXT IntPtrIntIntBoolBool
5976 #define SORTTPL_KEYTYPE int
5977 #define SORTTPL_FIELD1TYPE void*
5978 #define SORTTPL_FIELD2TYPE int
5979 #define SORTTPL_FIELD3TYPE int
5980 #define SORTTPL_FIELD4TYPE SCIP_Bool
5981 #define SORTTPL_FIELD5TYPE SCIP_Bool
5982 #include "scip/sorttpl.c" /*lint !e451*/
5983 
5984 
5985 /* now all downwards-sorting methods */
5986 
5987 
5988 /** sort an indexed element set in non-increasing order, resulting in a permutation index array */
5990  int* perm, /**< pointer to store the resulting permutation */
5991  SCIP_DECL_SORTINDCOMP((*indcomp)), /**< data element comparator */
5992  void* dataptr, /**< pointer to data field that is given to the external compare method */
5993  int len /**< number of elements to be sorted (valid index range) */
5994  )
5995 {
5996  int pos;
5997 
5998  assert(indcomp != NULL);
5999  assert(len == 0 || perm != NULL);
6000 
6001  /* create identity permutation */
6002  for( pos = 0; pos < len; ++pos )
6003  perm[pos] = pos;
6004 
6005  SCIPsortDownInd(perm, indcomp, dataptr, len);
6006 }
6007 
6008 
6009 /* SCIPsortDownInd(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6010 #define SORTTPL_NAMEEXT DownInd
6011 #define SORTTPL_KEYTYPE int
6012 #define SORTTPL_INDCOMP
6013 #define SORTTPL_BACKWARDS
6014 #include "scip/sorttpl.c" /*lint !e451*/
6015 
6016 
6017 /* SCIPsortDownPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6018 #define SORTTPL_NAMEEXT DownPtr
6019 #define SORTTPL_KEYTYPE void*
6020 #define SORTTPL_PTRCOMP
6021 #define SORTTPL_BACKWARDS
6022 #include "scip/sorttpl.c" /*lint !e451*/
6023 
6024 
6025 /* SCIPsortDownPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6026 #define SORTTPL_NAMEEXT DownPtrPtr
6027 #define SORTTPL_KEYTYPE void*
6028 #define SORTTPL_FIELD1TYPE void*
6029 #define SORTTPL_PTRCOMP
6030 #define SORTTPL_BACKWARDS
6031 #include "scip/sorttpl.c" /*lint !e451*/
6032 
6033 
6034 /* SCIPsortDownPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6035 #define SORTTPL_NAMEEXT DownPtrReal
6036 #define SORTTPL_KEYTYPE void*
6037 #define SORTTPL_FIELD1TYPE SCIP_Real
6038 #define SORTTPL_PTRCOMP
6039 #define SORTTPL_BACKWARDS
6040 #include "scip/sorttpl.c" /*lint !e451*/
6041 
6042 
6043 /* SCIPsortDownPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6044 #define SORTTPL_NAMEEXT DownPtrInt
6045 #define SORTTPL_KEYTYPE void*
6046 #define SORTTPL_FIELD1TYPE int
6047 #define SORTTPL_PTRCOMP
6048 #define SORTTPL_BACKWARDS
6049 #include "scip/sorttpl.c" /*lint !e451*/
6050 
6051 /* SCIPsortDownPtrBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6052 #define SORTTPL_NAMEEXT DownPtrBool
6053 #define SORTTPL_KEYTYPE void*
6054 #define SORTTPL_FIELD1TYPE SCIP_Bool
6055 #define SORTTPL_PTRCOMP
6056 #define SORTTPL_BACKWARDS
6057 #include "scip/sorttpl.c" /*lint !e451*/
6058 
6059 /* SCIPsortDownPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6060 #define SORTTPL_NAMEEXT DownPtrIntInt
6061 #define SORTTPL_KEYTYPE void*
6062 #define SORTTPL_FIELD1TYPE int
6063 #define SORTTPL_FIELD2TYPE int
6064 #define SORTTPL_PTRCOMP
6065 #define SORTTPL_BACKWARDS
6066 #include "scip/sorttpl.c" /*lint !e451*/
6067 
6068 
6069 /* SCIPsortDownPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6070 #define SORTTPL_NAMEEXT DownPtrRealInt
6071 #define SORTTPL_KEYTYPE void*
6072 #define SORTTPL_FIELD1TYPE SCIP_Real
6073 #define SORTTPL_FIELD2TYPE int
6074 #define SORTTPL_PTRCOMP
6075 #define SORTTPL_BACKWARDS
6076 #include "scip/sorttpl.c" /*lint !e451*/
6077 
6078 
6079 /* SCIPsortDownPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6080 #define SORTTPL_NAMEEXT DownPtrRealBool
6081 #define SORTTPL_KEYTYPE void*
6082 #define SORTTPL_FIELD1TYPE SCIP_Real
6083 #define SORTTPL_FIELD2TYPE SCIP_Bool
6084 #define SORTTPL_PTRCOMP
6085 #define SORTTPL_BACKWARDS
6086 #include "scip/sorttpl.c" /*lint !e451*/
6087 
6088 
6089 /* SCIPsortDownPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6090 #define SORTTPL_NAMEEXT DownPtrPtrInt
6091 #define SORTTPL_KEYTYPE void*
6092 #define SORTTPL_FIELD1TYPE void*
6093 #define SORTTPL_FIELD2TYPE int
6094 #define SORTTPL_PTRCOMP
6095 #define SORTTPL_BACKWARDS
6096 #include "scip/sorttpl.c" /*lint !e451*/
6097 
6098 
6099 /* SCIPsortDownPtrPtrReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6100 #define SORTTPL_NAMEEXT DownPtrPtrReal
6101 #define SORTTPL_KEYTYPE void*
6102 #define SORTTPL_FIELD1TYPE void*
6103 #define SORTTPL_FIELD2TYPE SCIP_Real
6104 #define SORTTPL_PTRCOMP
6105 #define SORTTPL_BACKWARDS
6106 #include "scip/sorttpl.c" /*lint !e451*/
6107 
6108 
6109 /* SCIPsortDownPtrRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6110 #define SORTTPL_NAMEEXT DownPtrRealIntInt
6111 #define SORTTPL_KEYTYPE void*
6112 #define SORTTPL_FIELD1TYPE SCIP_Real
6113 #define SORTTPL_FIELD2TYPE int
6114 #define SORTTPL_FIELD3TYPE int
6115 #define SORTTPL_PTRCOMP
6116 #define SORTTPL_BACKWARDS
6117 #include "scip/sorttpl.c" /*lint !e451*/
6118 
6119 
6120 /* SCIPsortDownPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6121 #define SORTTPL_NAMEEXT DownPtrPtrIntInt
6122 #define SORTTPL_KEYTYPE void*
6123 #define SORTTPL_FIELD1TYPE void*
6124 #define SORTTPL_FIELD2TYPE int
6125 #define SORTTPL_FIELD3TYPE int
6126 #define SORTTPL_PTRCOMP
6127 #define SORTTPL_BACKWARDS
6128 #include "scip/sorttpl.c" /*lint !e451*/
6129 
6130 
6131 /* SCIPsortDownPtrPtrRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6132 #define SORTTPL_NAMEEXT DownPtrPtrRealInt
6133 #define SORTTPL_KEYTYPE void*
6134 #define SORTTPL_FIELD1TYPE void*
6135 #define SORTTPL_FIELD2TYPE SCIP_Real
6136 #define SORTTPL_FIELD3TYPE int
6137 #define SORTTPL_PTRCOMP
6138 #define SORTTPL_BACKWARDS
6139 #include "scip/sorttpl.c" /*lint !e451*/
6140 
6141 
6142 /* SCIPsortDownPtrPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6143 #define SORTTPL_NAMEEXT DownPtrPtrRealBool
6144 #define SORTTPL_KEYTYPE void*
6145 #define SORTTPL_FIELD1TYPE void*
6146 #define SORTTPL_FIELD2TYPE SCIP_Real
6147 #define SORTTPL_FIELD3TYPE SCIP_Bool
6148 #define SORTTPL_PTRCOMP
6149 #define SORTTPL_BACKWARDS
6150 #include "scip/sorttpl.c" /*lint !e451*/
6151 
6152 
6153 /* SCIPsortDownPtrPtrLongInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6154 #define SORTTPL_NAMEEXT DownPtrPtrLongInt
6155 #define SORTTPL_KEYTYPE void*
6156 #define SORTTPL_FIELD1TYPE void*
6157 #define SORTTPL_FIELD2TYPE SCIP_Longint
6158 #define SORTTPL_FIELD3TYPE int
6159 #define SORTTPL_PTRCOMP
6160 #define SORTTPL_BACKWARDS
6161 #include "scip/sorttpl.c" /*lint !e451*/
6162 
6163 
6164 /* SCIPsortDownPtrPtrLongIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6165 #define SORTTPL_NAMEEXT DownPtrPtrLongIntInt
6166 #define SORTTPL_KEYTYPE void*
6167 #define SORTTPL_FIELD1TYPE void*
6168 #define SORTTPL_FIELD2TYPE SCIP_Longint
6169 #define SORTTPL_FIELD3TYPE int
6170 #define SORTTPL_FIELD4TYPE int
6171 #define SORTTPL_PTRCOMP
6172 #define SORTTPL_BACKWARDS
6173 #include "scip/sorttpl.c" /*lint !e451*/
6174 
6175 
6176 /* SCIPsortDownReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6177 #define SORTTPL_NAMEEXT DownReal
6178 #define SORTTPL_KEYTYPE SCIP_Real
6179 #define SORTTPL_BACKWARDS
6180 #include "scip/sorttpl.c" /*lint !e451*/
6181 
6182 
6183 /* SCIPsortDownRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6184 #define SORTTPL_NAMEEXT DownRealBoolPtr
6185 #define SORTTPL_KEYTYPE SCIP_Real
6186 #define SORTTPL_FIELD1TYPE SCIP_Bool
6187 #define SORTTPL_FIELD2TYPE void*
6188 #define SORTTPL_BACKWARDS
6189 #include "scip/sorttpl.c" /*lint !e451*/
6190 
6191 
6192 /* SCIPsortDownRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6193 #define SORTTPL_NAMEEXT DownRealPtr
6194 #define SORTTPL_KEYTYPE SCIP_Real
6195 #define SORTTPL_FIELD1TYPE void*
6196 #define SORTTPL_BACKWARDS
6197 #include "scip/sorttpl.c" /*lint !e451*/
6198 
6199 
6200 /* SCIPsortDownRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6201 #define SORTTPL_NAMEEXT DownRealInt
6202 #define SORTTPL_KEYTYPE SCIP_Real
6203 #define SORTTPL_FIELD1TYPE int
6204 #define SORTTPL_BACKWARDS
6205 #include "scip/sorttpl.c" /*lint !e451*/
6206 
6207 /* SCIPsortDownRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6208 #define SORTTPL_NAMEEXT DownRealIntInt
6209 #define SORTTPL_KEYTYPE SCIP_Real
6210 #define SORTTPL_FIELD1TYPE int
6211 #define SORTTPL_FIELD2TYPE int
6212 #define SORTTPL_BACKWARDS
6213 #include "scip/sorttpl.c" /*lint !e451*/
6214 
6215 /* SCIPsortDownRealIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6216 #define SORTTPL_NAMEEXT DownRealIntLong
6217 #define SORTTPL_KEYTYPE SCIP_Real
6218 #define SORTTPL_FIELD1TYPE int
6219 #define SORTTPL_FIELD2TYPE SCIP_Longint
6220 #define SORTTPL_BACKWARDS
6221 #include "scip/sorttpl.c" /*lint !e451*/
6222 
6223 
6224 /* SCIPsortDownRealIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6225 #define SORTTPL_NAMEEXT DownRealIntPtr
6226 #define SORTTPL_KEYTYPE SCIP_Real
6227 #define SORTTPL_FIELD1TYPE int
6228 #define SORTTPL_FIELD2TYPE void*
6229 #define SORTTPL_BACKWARDS
6230 #include "scip/sorttpl.c" /*lint !e451*/
6231 
6232 
6233 /* SCIPsortDownRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6234 #define SORTTPL_NAMEEXT DownRealPtrPtr
6235 #define SORTTPL_KEYTYPE SCIP_Real
6236 #define SORTTPL_FIELD1TYPE void*
6237 #define SORTTPL_FIELD2TYPE void*
6238 #define SORTTPL_BACKWARDS
6239 #include "scip/sorttpl.c" /*lint !e451*/
6240 
6241 /* SCIPsortDownRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6242 #define SORTTPL_NAMEEXT DownRealRealInt
6243 #define SORTTPL_KEYTYPE SCIP_Real
6244 #define SORTTPL_FIELD1TYPE SCIP_Real
6245 #define SORTTPL_FIELD2TYPE int
6246 #define SORTTPL_BACKWARDS
6247 #include "scip/sorttpl.c" /*lint !e451*/
6248 
6249 /* SCIPsortDownRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6250 #define SORTTPL_NAMEEXT DownRealRealPtr
6251 #define SORTTPL_KEYTYPE SCIP_Real
6252 #define SORTTPL_FIELD1TYPE SCIP_Real
6253 #define SORTTPL_FIELD2TYPE void*
6254 #define SORTTPL_BACKWARDS
6255 #include "scip/sorttpl.c" /*lint !e451*/
6256 
6257 /* SCIPsortDownRealRealPtrPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6258 #define SORTTPL_NAMEEXT DownRealRealPtrPtr
6259 #define SORTTPL_KEYTYPE SCIP_Real
6260 #define SORTTPL_FIELD1TYPE SCIP_Real
6261 #define SORTTPL_FIELD2TYPE void*
6262 #define SORTTPL_FIELD3TYPE void*
6263 #define SORTTPL_BACKWARDS
6264 #include "scip/sorttpl.c" /*lint !e451*/
6265 
6266 
6267 /* SCIPsortDownRealLongRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6268 #define SORTTPL_NAMEEXT DownRealLongRealInt
6269 #define SORTTPL_KEYTYPE SCIP_Real
6270 #define SORTTPL_FIELD1TYPE SCIP_Longint
6271 #define SORTTPL_FIELD2TYPE SCIP_Real
6272 #define SORTTPL_FIELD3TYPE int
6273 #define SORTTPL_BACKWARDS
6274 #include "scip/sorttpl.c" /*lint !e451*/
6275 
6276 
6277 /* SCIPsortDownRealRealIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6278 #define SORTTPL_NAMEEXT DownRealRealIntInt
6279 #define SORTTPL_KEYTYPE SCIP_Real
6280 #define SORTTPL_FIELD1TYPE SCIP_Real
6281 #define SORTTPL_FIELD2TYPE int
6282 #define SORTTPL_FIELD3TYPE int
6283 #define SORTTPL_BACKWARDS
6284 #include "scip/sorttpl.c" /*lint !e451*/
6285 
6286 
6287 /* SCIPsortDownRealRealRealInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6288 #define SORTTPL_NAMEEXT DownRealRealRealInt
6289 #define SORTTPL_KEYTYPE SCIP_Real
6290 #define SORTTPL_FIELD1TYPE SCIP_Real
6291 #define SORTTPL_FIELD2TYPE SCIP_Real
6292 #define SORTTPL_FIELD3TYPE int
6293 #define SORTTPL_BACKWARDS
6294 #include "scip/sorttpl.c" /*lint !e451*/
6295 
6296 
6297 /* SCIPsortDownRealRealRealPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6298 #define SORTTPL_NAMEEXT DownRealRealRealPtr
6299 #define SORTTPL_KEYTYPE SCIP_Real
6300 #define SORTTPL_FIELD1TYPE SCIP_Real
6301 #define SORTTPL_FIELD2TYPE SCIP_Real
6302 #define SORTTPL_FIELD3TYPE void*
6303 #define SORTTPL_BACKWARDS
6304 #include "scip/sorttpl.c" /*lint !e451*/
6305 
6306 
6307 /* SCIPsortDownRealPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6308 #define SORTTPL_NAMEEXT DownRealPtrPtrInt
6309 #define SORTTPL_KEYTYPE SCIP_Real
6310 #define SORTTPL_FIELD1TYPE void*
6311 #define SORTTPL_FIELD2TYPE void*
6312 #define SORTTPL_FIELD3TYPE int
6313 #define SORTTPL_BACKWARDS
6314 #include "scip/sorttpl.c" /*lint !e451*/
6315 
6316 /* SCIPsortDownRealPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6317 #define SORTTPL_NAMEEXT DownRealPtrPtrIntInt
6318 #define SORTTPL_KEYTYPE SCIP_Real
6319 #define SORTTPL_FIELD1TYPE void*
6320 #define SORTTPL_FIELD2TYPE void*
6321 #define SORTTPL_FIELD3TYPE int
6322 #define SORTTPL_FIELD4TYPE int
6323 #define SORTTPL_BACKWARDS
6324 #include "scip/sorttpl.c" /*lint !e451*/
6325 
6326 
6327 /* SCIPsortDownRealRealRealBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6328 #define SORTTPL_NAMEEXT DownRealRealRealBoolPtr
6329 #define SORTTPL_KEYTYPE SCIP_Real
6330 #define SORTTPL_FIELD1TYPE SCIP_Real
6331 #define SORTTPL_FIELD2TYPE SCIP_Real
6332 #define SORTTPL_FIELD3TYPE SCIP_Bool
6333 #define SORTTPL_FIELD4TYPE void*
6334 #define SORTTPL_BACKWARDS
6335 #include "scip/sorttpl.c" /*lint !e451*/
6336 
6337 
6338 /* SCIPsortDownRealRealRealBoolBoolPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6339 #define SORTTPL_NAMEEXT DownRealRealRealBoolBoolPtr
6340 #define SORTTPL_KEYTYPE SCIP_Real
6341 #define SORTTPL_FIELD1TYPE SCIP_Real
6342 #define SORTTPL_FIELD2TYPE SCIP_Real
6343 #define SORTTPL_FIELD3TYPE SCIP_Bool
6344 #define SORTTPL_FIELD4TYPE SCIP_Bool
6345 #define SORTTPL_FIELD5TYPE void*
6346 #include "scip/sorttpl.c" /*lint !e451*/
6347 
6348 
6349 /* SCIPsortDownInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6350 #define SORTTPL_NAMEEXT DownInt
6351 #define SORTTPL_KEYTYPE int
6352 #define SORTTPL_BACKWARDS
6353 #include "scip/sorttpl.c" /*lint !e451*/
6354 
6355 
6356 /* SCIPsortDownIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6357 #define SORTTPL_NAMEEXT DownIntInt
6358 #define SORTTPL_KEYTYPE int
6359 #define SORTTPL_FIELD1TYPE int
6360 #define SORTTPL_BACKWARDS
6361 #include "scip/sorttpl.c" /*lint !e451*/
6362 
6363 
6364 /* SCIPsortDownIntIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6365 #define SORTTPL_NAMEEXT DownIntIntReal
6366 #define SORTTPL_KEYTYPE int
6367 #define SORTTPL_FIELD1TYPE int
6368 #define SORTTPL_FIELD2TYPE SCIP_Real
6369 #define SORTTPL_BACKWARDS
6370 #include "scip/sorttpl.c" /*lint !e451*/
6371 
6372 
6373 /* SCIPsortDownIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6374 #define SORTTPL_NAMEEXT DownIntReal
6375 #define SORTTPL_KEYTYPE int
6376 #define SORTTPL_FIELD1TYPE SCIP_Real
6377 #define SORTTPL_BACKWARDS
6378 #include "scip/sorttpl.c" /*lint !e451*/
6379 
6380 
6381 /* SCIPsortDownIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6382 #define SORTTPL_NAMEEXT DownIntPtr
6383 #define SORTTPL_KEYTYPE int
6384 #define SORTTPL_FIELD1TYPE void*
6385 #define SORTTPL_BACKWARDS
6386 #include "scip/sorttpl.c" /*lint !e451*/
6387 
6388 
6389 /* SCIPsortDownIntIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6390 #define SORTTPL_NAMEEXT DownIntIntInt
6391 #define SORTTPL_KEYTYPE int
6392 #define SORTTPL_FIELD1TYPE int
6393 #define SORTTPL_FIELD2TYPE int
6394 #define SORTTPL_BACKWARDS
6395 #include "scip/sorttpl.c" /*lint !e451*/
6396 
6397 
6398 /* SCIPsortDownIntIntLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6399 #define SORTTPL_NAMEEXT DownIntIntLong
6400 #define SORTTPL_KEYTYPE int
6401 #define SORTTPL_FIELD1TYPE int
6402 #define SORTTPL_FIELD2TYPE SCIP_Longint
6403 #define SORTTPL_BACKWARDS
6404 #include "scip/sorttpl.c" /*lint !e451*/
6405 
6406 
6407 /* SCIPsortDownIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6408 #define SORTTPL_NAMEEXT DownIntIntPtr
6409 #define SORTTPL_KEYTYPE int
6410 #define SORTTPL_FIELD1TYPE int
6411 #define SORTTPL_FIELD2TYPE void*
6412 #define SORTTPL_BACKWARDS
6413 #include "scip/sorttpl.c" /*lint !e451*/
6414 
6415 
6416 /* SCIPsortDownIntIntIntPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6417 #define SORTTPL_NAMEEXT DownIntIntIntPtr
6418 #define SORTTPL_KEYTYPE int
6419 #define SORTTPL_FIELD1TYPE int
6420 #define SORTTPL_FIELD2TYPE int
6421 #define SORTTPL_FIELD3TYPE void*
6422 #define SORTTPL_BACKWARDS
6423 #include "scip/sorttpl.c" /*lint !e451*/
6424 
6425 
6426 /* SCIPsortDownIntPtrIntReal(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6427 #define SORTTPL_NAMEEXT DownIntPtrIntReal
6428 #define SORTTPL_KEYTYPE int
6429 #define SORTTPL_FIELD1TYPE void*
6430 #define SORTTPL_FIELD2TYPE int
6431 #define SORTTPL_FIELD3TYPE SCIP_Real
6432 #define SORTTPL_BACKWARDS
6433 #include "scip/sorttpl.c" /*lint !e451*/
6434 
6435 
6436 /* SCIPsortDownLong(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6437 #define SORTTPL_NAMEEXT DownLong
6438 #define SORTTPL_KEYTYPE SCIP_Longint
6439 #define SORTTPL_BACKWARDS
6440 #include "scip/sorttpl.c" /*lint !e451*/
6441 
6442 
6443 /* SCIPsortDownLongPtr(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6444 #define SORTTPL_NAMEEXT DownLongPtr
6445 #define SORTTPL_KEYTYPE SCIP_Longint
6446 #define SORTTPL_FIELD1TYPE void*
6447 #define SORTTPL_BACKWARDS
6448 #include "scip/sorttpl.c" /*lint !e451*/
6449 
6450 
6451 /* SCIPsortDownLongPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6452 #define SORTTPL_NAMEEXT DownLongPtrInt
6453 #define SORTTPL_KEYTYPE SCIP_Longint
6454 #define SORTTPL_FIELD1TYPE void*
6455 #define SORTTPL_FIELD2TYPE int
6456 #define SORTTPL_BACKWARDS
6457 #include "scip/sorttpl.c" /*lint !e451*/
6458 
6459 
6460 /* SCIPsortDownLongPtrRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6461 #define SORTTPL_NAMEEXT DownLongPtrRealBool
6462 #define SORTTPL_KEYTYPE SCIP_Longint
6463 #define SORTTPL_FIELD1TYPE void*
6464 #define SORTTPL_FIELD2TYPE SCIP_Real
6465 #define SORTTPL_FIELD3TYPE SCIP_Bool
6466 #define SORTTPL_BACKWARDS
6467 #include "scip/sorttpl.c" /*lint !e451*/
6468 
6469 
6470 /* SCIPsortDownLongPtrRealRealBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6471 #define SORTTPL_NAMEEXT DownLongPtrRealRealBool
6472 #define SORTTPL_KEYTYPE SCIP_Longint
6473 #define SORTTPL_FIELD1TYPE void*
6474 #define SORTTPL_FIELD2TYPE SCIP_Real
6475 #define SORTTPL_FIELD3TYPE SCIP_Real
6476 #define SORTTPL_FIELD4TYPE SCIP_Bool
6477 #define SORTTPL_BACKWARDS
6478 #include "scip/sorttpl.c" /*lint !e451*/
6479 
6480 
6481 /* SCIPsortLongPtrRealRealIntBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6482 #define SORTTPL_NAMEEXT DownLongPtrRealRealIntBool
6483 #define SORTTPL_KEYTYPE SCIP_Longint
6484 #define SORTTPL_FIELD1TYPE void*
6485 #define SORTTPL_FIELD2TYPE SCIP_Real
6486 #define SORTTPL_FIELD3TYPE SCIP_Real
6487 #define SORTTPL_FIELD4TYPE int
6488 #define SORTTPL_FIELD5TYPE SCIP_Bool
6489 #define SORTTPL_BACKWARDS
6490 #include "scip/sorttpl.c" /*lint !e451*/
6491 
6492 
6493 /* SCIPsortDownLongPtrPtrInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6494 #define SORTTPL_NAMEEXT DownLongPtrPtrInt
6495 #define SORTTPL_KEYTYPE SCIP_Longint
6496 #define SORTTPL_FIELD1TYPE void*
6497 #define SORTTPL_FIELD2TYPE void*
6498 #define SORTTPL_FIELD3TYPE int
6499 #define SORTTPL_BACKWARDS
6500 #include "scip/sorttpl.c" /*lint !e451*/
6501 
6502 
6503 /* SCIPsortDownLongPtrPtrIntInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6504 #define SORTTPL_NAMEEXT DownLongPtrPtrIntInt
6505 #define SORTTPL_KEYTYPE SCIP_Longint
6506 #define SORTTPL_FIELD1TYPE void*
6507 #define SORTTPL_FIELD2TYPE void*
6508 #define SORTTPL_FIELD3TYPE int
6509 #define SORTTPL_FIELD4TYPE int
6510 #define SORTTPL_BACKWARDS
6511 #include "scip/sorttpl.c" /*lint !e451*/
6512 
6513 
6514 /* SCIPsortDownLongPtrPtrBoolInt(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6515 #define SORTTPL_NAMEEXT DownLongPtrPtrBoolInt
6516 #define SORTTPL_KEYTYPE SCIP_Longint
6517 #define SORTTPL_FIELD1TYPE void*
6518 #define SORTTPL_FIELD2TYPE void*
6519 #define SORTTPL_FIELD3TYPE SCIP_Bool
6520 #define SORTTPL_FIELD4TYPE int
6521 #define SORTTPL_BACKWARDS
6522 #include "scip/sorttpl.c" /*lint !e451*/
6523 
6524 
6525 /* SCIPsortDownPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6526 #define SORTTPL_NAMEEXT DownPtrIntIntBoolBool
6527 #define SORTTPL_KEYTYPE void*
6528 #define SORTTPL_FIELD1TYPE int
6529 #define SORTTPL_FIELD2TYPE int
6530 #define SORTTPL_FIELD3TYPE SCIP_Bool
6531 #define SORTTPL_FIELD4TYPE SCIP_Bool
6532 #define SORTTPL_PTRCOMP
6533 #define SORTTPL_BACKWARDS
6534 #include "scip/sorttpl.c" /*lint !e451*/
6535 
6536 
6537 /* SCIPsortDownIntPtrIntIntBoolBool(), SCIPsortedvecInsert...(), SCIPsortedvecDelPos...(), SCIPsortedvecFind...() via sort template */
6538 #define SORTTPL_NAMEEXT DownIntPtrIntIntBoolBool
6539 #define SORTTPL_KEYTYPE int
6540 #define SORTTPL_FIELD1TYPE void*
6541 #define SORTTPL_FIELD2TYPE int
6542 #define SORTTPL_FIELD3TYPE int
6543 #define SORTTPL_FIELD4TYPE SCIP_Bool
6544 #define SORTTPL_FIELD5TYPE SCIP_Bool
6545 #define SORTTPL_BACKWARDS
6546 #include "scip/sorttpl.c" /*lint !e451*/
6547 
6548 /*
6549  * Resulting activity
6550  */
6551 
6552 /** create a resource activity */
6554  SCIP_RESOURCEACTIVITY** activity, /**< pointer to store the resource activity */
6555  SCIP_VAR* var, /**< start time variable of the activity */
6556  int duration, /**< duration of the activity */
6557  int demand /**< demand of the activity */
6558  )
6559 {
6560  assert(activity != NULL);
6561 
6562  SCIP_ALLOC( BMSallocMemory(activity) );
6563 
6564  (*activity)->var = var;
6565  (*activity)->duration = duration;
6566  (*activity)->demand = demand;
6567 
6568  return SCIP_OKAY;
6569 }
6570 
6571 /** frees a resource activity */
6573  SCIP_RESOURCEACTIVITY** activity /**< pointer to the resource activity */
6574  )
6575 {
6576  assert(activity != NULL);
6577  assert(*activity != NULL);
6578 
6579  BMSfreeMemory(activity);
6580 }
6581 
6582 /* some simple variable functions implemented as defines */
6583 
6584 #ifndef NDEBUG
6585 
6586 /* In debug mode, the following methods are implemented as function calls to ensure
6587  * type validity.
6588  * In optimized mode, the methods are implemented as defines to improve performance.
6589  * However, we want to have them in the library anyways, so we have to undef the defines.
6590  */
6591 
6592 #undef SCIPactivityGetVar
6593 #undef SCIPactivityGetDuration
6594 #undef SCIPactivityGetDemand
6595 #undef SCIPactivityGetEnergy
6596 
6597 /** returns the start time variable of the resource activity */
6599  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6600  )
6601 {
6602  assert(activity != NULL);
6603 
6604  return activity->var;
6605 }
6606 
6607 /** returns the duration of the resource activity */
6609  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6610  )
6611 {
6612  assert(activity != NULL);
6613 
6614  return activity->duration;
6615 }
6616 
6617 /** returns the demand of the resource activity */
6619  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6620  )
6621 {
6622  assert(activity != NULL);
6623 
6624  return activity->demand;
6625 }
6626 
6627 /** returns the energy of the resource activity */
6629  SCIP_RESOURCEACTIVITY* activity /**< resource activity */
6630  )
6631 {
6632  assert(activity != NULL);
6633 
6634  return activity->duration * activity->demand ;
6635 }
6636 
6637 #endif
6638 
6639 /*
6640  * Resource Profile
6641  */
6642 
6643 /** helper method to create a profile */
6644 static
6646  SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6647  int capacity /**< resource capacity */
6648  )
6649 {
6650  SCIP_ALLOC( BMSallocMemory(profile) );
6651  BMSclearMemory(*profile);
6652 
6653  (*profile)->arraysize = 10;
6654  SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->timepoints, (*profile)->arraysize) );
6655  SCIP_ALLOC( BMSallocMemoryArray(&(*profile)->loads, (*profile)->arraysize) );
6656 
6657  /* setup resource profile for use */
6658  (*profile)->ntimepoints = 1;
6659  (*profile)->timepoints[0] = 0;
6660  (*profile)->loads[0] = 0;
6661  (*profile)->capacity = capacity;
6662 
6663  return SCIP_OKAY;
6664 }
6665 
6666 /** creates resource profile */
6668  SCIP_PROFILE** profile, /**< pointer to store the resource profile */
6669  int capacity /**< resource capacity */
6670  )
6671 {
6672  assert(profile != NULL);
6673  assert(capacity > 0);
6674 
6675  SCIP_CALL_FINALLY( doProfileCreate(profile, capacity), SCIPprofileFree(profile) );
6676 
6677  return SCIP_OKAY;
6678 }
6679 
6680 /** frees given resource profile */
6682  SCIP_PROFILE** profile /**< pointer to the resource profile */
6683  )
6684 {
6685  assert(profile != NULL);
6686 
6687  /* free resource profile */
6688  if( *profile != NULL )
6689  {
6690  BMSfreeMemoryArrayNull(&(*profile)->loads);
6691  BMSfreeMemoryArrayNull(&(*profile)->timepoints);
6692  BMSfreeMemory(profile);
6693  }
6694 }
6695 
6696 /** output of the given resource profile */
6698  SCIP_PROFILE* profile, /**< resource profile to output */
6699  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
6700  FILE* file /**< output file (or NULL for standard output) */
6701  )
6702 {
6703  int t;
6704 
6705  SCIPmessageFPrintInfo(messagehdlr, file, "Profile <%p> (capacity %d) --> ", (void*)profile, profile->capacity);
6706 
6707  for( t = 0; t < profile->ntimepoints; ++t )
6708  {
6709  if( t == 0 )
6710  SCIPmessageFPrintInfo(messagehdlr, file, "%d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6711  else
6712  SCIPmessageFPrintInfo(messagehdlr, file, ", %d:(%d,%d)", t, profile->timepoints[t], profile->loads[t]);
6713  }
6714 
6715  SCIPmessageFPrintInfo(messagehdlr, file,"\n");
6716 }
6717 
6718 /** returns the capacity of the resource profile */
6720  SCIP_PROFILE* profile /**< resource profile to use */
6721  )
6722 {
6723  assert(profile != NULL);
6724 
6725  return profile->capacity;
6726 }
6727 
6728 /** returns the number time points of the resource profile */
6730  SCIP_PROFILE* profile /**< resource profile to use */
6731  )
6732 {
6733  assert(profile != NULL);
6734 
6735  return profile->ntimepoints;
6736 }
6737 
6738 /** returns the time points of the resource profile */
6740  SCIP_PROFILE* profile /**< resource profile to use */
6741  )
6742 {
6743  assert(profile != NULL);
6744 
6745  return profile->timepoints;
6746 }
6747 
6748 /** returns the loads of the resource profile */
6750  SCIP_PROFILE* profile /**< resource profile to use */
6751  )
6752 {
6753  assert(profile != NULL);
6754 
6755  return profile->loads;
6756 }
6757 
6758 /** returns the time point for given position of the resource profile */
6760  SCIP_PROFILE* profile, /**< resource profile to use */
6761  int pos /**< position */
6762  )
6763 {
6764  assert(profile != NULL);
6765  assert(pos >= 0 && pos < profile->ntimepoints);
6766 
6767  return profile->timepoints[pos];
6768 }
6769 
6770 /** returns the loads of the resource profile at the given position */
6772  SCIP_PROFILE* profile, /**< resource profile */
6773  int pos /**< position */
6774  )
6775 {
6776  assert(profile != NULL);
6777  assert(pos >= 0 && pos < profile->ntimepoints);
6778 
6779  return profile->loads[pos];
6780 }
6781 
6782 /** returns if the given time point exists in the resource profile and stores the position of the given time point if it
6783  * exists; otherwise the position of the next smaller existing time point is stored
6784  */
6786  SCIP_PROFILE* profile, /**< resource profile to search */
6787  int timepoint, /**< time point to search for */
6788  int* pos /**< pointer to store the position */
6789  )
6790 {
6791  assert(profile != NULL);
6792  assert(timepoint >= 0);
6793  assert(profile->ntimepoints > 0);
6794  assert(profile->timepoints[0] == 0);
6795 
6796  /* find the position of time point in the time points array via binary search */
6797  if( SCIPsortedvecFindInt(profile->timepoints, timepoint, profile->ntimepoints, pos) )
6798  return TRUE;
6799 
6800  assert(*pos > 0);
6801  (*pos)--;
6802 
6803  return FALSE;
6804 }
6805 
6806 /* ensures that resource profile arrays is big enough */
6807 static
6809  SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6810  int neededsize /**< needed size */
6811  )
6812 {
6813  assert(profile->arraysize > 0);
6814 
6815  /* check whether the arrays are big enough */
6816  if( neededsize <= profile->arraysize )
6817  return SCIP_OKAY;
6818 
6819  profile->arraysize *= 2;
6820 
6821  SCIP_ALLOC( BMSreallocMemoryArray(&profile->timepoints, profile->arraysize) );
6822  SCIP_ALLOC( BMSreallocMemoryArray(&profile->loads, profile->arraysize) );
6823 
6824  return SCIP_OKAY;
6825 }
6826 
6827 /** inserts the given time point into the resource profile if it this time point does not exists yet; returns its
6828  * position in the time point array
6829  */
6830 static
6832  SCIP_PROFILE* profile, /**< resource profile to insert the time point */
6833  int timepoint, /**< time point to insert */
6834  int* pos /**< pointer to store the insert position */
6835  )
6836 {
6837  assert(profile != NULL);
6838  assert(timepoint >= 0);
6839  assert(profile->arraysize >= profile->ntimepoints);
6840 
6841  /* get the position of the given time point in the resource profile array if it exists; otherwise the position of the
6842  * next smaller existing time point
6843  */
6844  if( !SCIPprofileFindLeft(profile, timepoint, pos) )
6845  {
6846  assert(*pos >= 0 && *pos < profile->ntimepoints);
6847  assert(timepoint >= profile->timepoints[*pos]);
6848 
6849  /* ensure that the arrays are big enough */
6850  SCIP_CALL( ensureProfileSize(profile, profile->ntimepoints + 1) );
6851  assert(profile->arraysize > profile->ntimepoints);
6852 
6853  /* insert new time point into the (sorted) resource profile */
6854  SCIPsortedvecInsertIntInt(profile->timepoints, profile->loads, timepoint, profile->loads[*pos],
6855  &profile->ntimepoints, pos);
6856  }
6857 
6858 #ifndef NDEBUG
6859  /* check if the time points are sorted */
6860  {
6861  int i;
6862  for( i = 1; i < profile->ntimepoints; ++i )
6863  assert(profile->timepoints[i-1] < profile->timepoints[i]);
6864  }
6865 #endif
6866 
6867  return SCIP_OKAY;
6868 }
6869 
6870 /** updates the resource profile due to inserting of a core */
6871 static
6873  SCIP_PROFILE* profile, /**< resource profile to update */
6874  int left, /**< left side of core interval */
6875  int right, /**< right side of core interval */
6876  int demand, /**< demand of the core */
6877  int* pos, /**< pointer to store the first position were it gets infeasible */
6878  SCIP_Bool* infeasible /**< pointer to store if the update is infeasible */
6879  )
6880 {
6881  int startpos;
6882  int endpos;
6883  int i;
6884 
6885  assert(profile != NULL);
6886  assert(profile->arraysize >= profile->ntimepoints);
6887  assert(left >= 0);
6888  assert(left < right);
6889  assert(infeasible != NULL);
6890 
6891  (*infeasible) = FALSE;
6892  (*pos) = -1;
6893 
6894  /* get position of the starttime in profile */
6895  SCIP_CALL( profileInsertTimepoint(profile, left, &startpos) );
6896  assert(profile->timepoints[startpos] == left);
6897 
6898  /* get position of the endtime in profile */
6899  SCIP_CALL( profileInsertTimepoint(profile, right, &endpos) );
6900  assert(profile->timepoints[endpos] == right);
6901 
6902  assert(startpos < endpos);
6903  assert(profile->arraysize >= profile->ntimepoints);
6904 
6905  /* remove/add the given demand from the core */
6906  for( i = startpos; i < endpos; ++i )
6907  {
6908  profile->loads[i] += demand;
6909 
6910  /* check if the core fits */
6911  if( profile->loads[i] > profile->capacity )
6912  {
6913  SCIPdebugMessage("core insertion detected infeasibility (pos %d)\n", i);
6914 
6915  (*infeasible) = TRUE;
6916  (*pos) = i;
6917 
6918  /* remove the partly inserted core since it does fit completely */
6919  for( ; i >= startpos; --i ) /*lint !e445*/
6920  profile->loads[i] -= demand;
6921 
6922  break;
6923  }
6924  }
6925 
6926  return SCIP_OKAY;
6927 }
6928 
6929 /** insert a core into resource profile; if the core is non-empty the resource profile will be updated otherwise nothing
6930  * happens
6931  */
6933  SCIP_PROFILE* profile, /**< resource profile */
6934  int left, /**< left side of the core */
6935  int right, /**< right side of the core */
6936  int demand, /**< demand of the core */
6937  int* pos, /**< pointer to store the first position were it gets infeasible */
6938  SCIP_Bool* infeasible /**< pointer to store if the core does not fit due to capacity */
6939  )
6940 {
6941  assert(profile != NULL);
6942  assert(left < right);
6943  assert(demand >= 0);
6944  assert(infeasible != NULL);
6945 
6946  (*infeasible) = FALSE;
6947  (*pos) = -1;
6948 
6949  /* insert core into the resource profile */
6950  SCIPdebugMessage("insert core [%d,%d] with demand %d\n", left, right, demand);
6951 
6952  if( demand > 0 )
6953  {
6954  /* try to insert core into the resource profile */
6955  SCIP_CALL( profileUpdate(profile, left, right, demand, pos, infeasible) );
6956  }
6957 
6958  return SCIP_OKAY;
6959 }
6960 
6961 /** subtracts the demand from the resource profile during core time */
6963  SCIP_PROFILE* profile, /**< resource profile to use */
6964  int left, /**< left side of the core */
6965  int right, /**< right side of the core */
6966  int demand /**< demand of the core */
6967  )
6968 {
6969  SCIP_Bool infeasible;
6970  int pos;
6971 
6972  assert(left < right);
6973 #ifndef NDEBUG
6974  {
6975  /* check if the left and right time points of the core correspond to a time point in the resource profile; this
6976  * should be the case since we added the core before to the resource profile
6977  */
6978  assert(SCIPprofileFindLeft(profile, left, &pos));
6979  assert(SCIPprofileFindLeft(profile, right, &pos));
6980  }
6981 #endif
6982 
6983  /* remove the core from the resource profile */
6984  SCIPdebugMessage("delete core [%d,%d] with demand %d\n", left, right, demand);
6985 
6986  SCIP_CALL( profileUpdate(profile, left, right, -demand, &pos, &infeasible) );
6987  assert(!infeasible);
6988 
6989  return SCIP_OKAY; /*lint !e438*/
6990 }
6991 
6992 /** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
6993 static
6995  SCIP_PROFILE* profile, /**< resource profile to use */
6996  int pos, /**< pointer to store the position in the profile to start the serch */
6997  int lst, /**< latest start time */
6998  int duration, /**< duration of the core */
6999  int demand, /**< demand of the core */
7000  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7001  )
7002 {
7003  int remainingduration;
7004  int startpos;
7005 
7006  assert(profile != NULL);
7007  assert(pos >= 0);
7008  assert(pos < profile->ntimepoints);
7009  assert(duration > 0);
7010  assert(demand > 0);
7011  assert(profile->loads[profile->ntimepoints-1] == 0);
7012 
7013  remainingduration = duration;
7014  startpos = pos;
7015  (*infeasible) = FALSE;
7016 
7017  if( profile->timepoints[startpos] > lst )
7018  {
7019  (*infeasible) = TRUE;
7020  return pos;
7021  }
7022 
7023  while( pos < profile->ntimepoints - 1 )
7024  {
7025  if( profile->loads[pos] + demand > profile->capacity )
7026  {
7027  SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos], pos);
7028  startpos = pos + 1;
7029  remainingduration = duration;
7030 
7031  if( profile->timepoints[startpos] > lst )
7032  {
7033  (*infeasible) = TRUE;
7034  return pos;
7035  }
7036  }
7037  else
7038  remainingduration -= profile->timepoints[pos+1] - profile->timepoints[pos];
7039 
7040  if( remainingduration <= 0 )
7041  break;
7042 
7043  pos++;
7044  }
7045 
7046  return startpos;
7047 }
7048 
7049 /** return the earliest possible starting point within the time interval [lb,ub] for a given core (given by its demand
7050  * and duration)
7051  */
7053  SCIP_PROFILE* profile, /**< resource profile to use */
7054  int est, /**< earliest starting time of the given core */
7055  int lst, /**< latest starting time of the given core */
7056  int duration, /**< duration of the core */
7057  int demand, /**< demand of the core */
7058  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7059  )
7060 {
7061  SCIP_Bool found;
7062  int pos;
7063 
7064  assert(profile != NULL);
7065  assert(est >= 0);
7066  assert(est <= lst);
7067  assert(duration >= 0);
7068  assert(demand >= 0);
7069  assert(infeasible != NULL);
7070  assert(profile->ntimepoints > 0);
7071  assert(profile->loads[profile->ntimepoints-1] == 0);
7072 
7073  SCIPdebugMessage("profile <%p>: find earliest start time (demad %d, duration %d) [%d,%d]\n", (void*)profile, demand, duration, est, lst);
7074 
7075  if( duration == 0 || demand == 0 )
7076  {
7077  *infeasible = FALSE;
7078  return est;
7079  }
7080 
7081  found = SCIPprofileFindLeft(profile, est, &pos);
7082  SCIPdebugMessage("profile <%p>: earliest start time does %s exist as time point (pos %d)\n", (void*)profile, found ? "" : "not", pos);
7083 
7084  /* if the position is the last time point in the profile, the core can be inserted at its earliest start time */
7085  if( pos == profile->ntimepoints - 1 )
7086  {
7087  (*infeasible) = FALSE;
7088  return est;
7089  }
7090 
7091  if( found )
7092  {
7093  /* if the start time matches a time point in the profile we can just search */
7094  assert(profile->timepoints[pos] == est);
7095  pos = profileFindFeasibleStart(profile, pos, lst, duration, demand, infeasible);
7096 
7097  assert(pos < profile->ntimepoints);
7098  est = profile->timepoints[pos];
7099  }
7100  else if( profile->loads[pos] + demand > profile->capacity )
7101  {
7102  /* if the the time point left to the start time has not enough free capacity we can just search the profile
7103  * starting from the next time point
7104  */
7105  assert(profile->timepoints[pos] <= est);
7106  pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7107 
7108  assert(pos < profile->ntimepoints);
7109  est = profile->timepoints[pos];
7110  }
7111  else
7112  {
7113  int remainingduration;
7114 
7115  /* check if the core can be placed at its earliest start time */
7116 
7117  assert(pos < profile->ntimepoints - 1);
7118 
7119  remainingduration = duration - (profile->timepoints[pos+1] - est);
7120  SCIPdebugMessage("remaining duration %d\n", remainingduration);
7121 
7122  if( remainingduration <= 0 )
7123  (*infeasible) = FALSE;
7124  else
7125  {
7126  pos = profileFindFeasibleStart(profile, pos+1, profile->timepoints[pos+1], remainingduration, demand, infeasible);
7127  SCIPdebugMessage("remaining duration can%s be processed\n", *infeasible ? "not" : "");
7128 
7129  if( *infeasible )
7130  {
7131  pos = profileFindFeasibleStart(profile, pos+1, lst, duration, demand, infeasible);
7132 
7133  assert(pos < profile->ntimepoints);
7134  est = profile->timepoints[pos];
7135  }
7136  }
7137  }
7138 
7139  return est;
7140 }
7141 
7142 /** returns TRUE if the core (given by its demand and during) can be inserted at the given time point; otherwise FALSE */
7143 static
7145  SCIP_PROFILE* profile, /**< resource profile to use */
7146  int pos, /**< pointer to store the position in the profile to start the search */
7147  int ect, /**< earliest completion time */
7148  int duration, /**< duration of the core */
7149  int demand, /**< demand of the core */
7150  SCIP_Bool* infeasible /**< pointer store if the corer cannot be inserted */
7151  )
7152 {
7153  int remainingduration;
7154  int endpos;
7155 
7156  assert(profile != NULL);
7157  assert(pos >= 0);
7158  assert(pos < profile->ntimepoints);
7159  assert(duration > 0);
7160  assert(demand > 0);
7161  assert(profile->ntimepoints > 0);
7162  assert(profile->loads[profile->ntimepoints-1] == 0);
7163 
7164  remainingduration = duration;
7165  endpos = pos;
7166  (*infeasible) = TRUE;
7167 
7168  if( profile->timepoints[endpos] < ect - duration )
7169  return pos;
7170 
7171  while( pos > 0 )
7172  {
7173  if( profile->loads[pos-1] + demand > profile->capacity )
7174  {
7175  SCIPdebugMessage("profile <%p>: core does not fit at time point %d (pos %d)\n", (void*)profile, profile->timepoints[pos-1], pos-1);
7176 
7177  endpos = pos - 1;
7178  remainingduration = duration;
7179 
7180  if( profile->timepoints[endpos] < ect - duration )
7181  return pos;
7182  }
7183  else
7184  remainingduration -= profile->timepoints[pos] - profile->timepoints[pos-1];
7185 
7186  if( remainingduration <= 0 )
7187  {
7188  *infeasible = FALSE;
7189  break;
7190  }
7191 
7192  pos--;
7193  }
7194 
7195  return endpos;
7196 }
7197 
7198 /** return the latest possible starting point within the time interval [lb,ub] for a given core (given by its demand and
7199  * duration)
7200  */
7202  SCIP_PROFILE* profile, /**< resource profile to use */
7203  int est, /**< earliest possible start point */
7204  int lst, /**< latest possible start point */
7205  int duration, /**< duration of the core */
7206  int demand, /**< demand of the core */
7207  SCIP_Bool* infeasible /**< pointer store if the core cannot be inserted */
7208  )
7209 {
7210  SCIP_Bool found;
7211  int ect;
7212  int lct;
7213  int pos;
7214 
7215  assert(profile != NULL);
7216  assert(est >= 0);
7217  assert(est <= lst);
7218  assert(duration >= 0);
7219  assert(demand >= 0);
7220  assert(infeasible != NULL);
7221  assert(profile->ntimepoints > 0);
7222  assert(profile->loads[profile->ntimepoints-1] == 0);
7223 
7224  if( duration == 0 || demand == 0 )
7225  {
7226  *infeasible = FALSE;
7227  return lst;
7228  }
7229 
7230  ect = est + duration;
7231  lct = lst + duration;
7232 
7233  found = SCIPprofileFindLeft(profile, lct, &pos);
7234  SCIPdebugMessage("profile <%p>: latest completion time %d does %s exist as time point (pos %d)\n", (void*)profile, lct, found ? "" : "not", pos);
7235 
7236  if( found )
7237  {
7238  /* if the start time matches a time point in the profile we can just search */
7239  assert(profile->timepoints[pos] == lct);
7240  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7241 
7242  assert(pos < profile->ntimepoints && pos >= 0);
7243  lct = profile->timepoints[pos];
7244  }
7245  else if( profile->loads[pos] + demand > profile->capacity )
7246  {
7247  /* if the time point left to the start time has not enough free capacity we can just search the profile starting
7248  * from the next time point
7249  */
7250  assert(profile->timepoints[pos] < lct);
7251  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7252 
7253  assert(pos < profile->ntimepoints && pos >= 0);
7254  lct = profile->timepoints[pos];
7255  }
7256  else
7257  {
7258  int remainingduration;
7259 
7260  /* check if the core can be placed at its latest start time */
7261  assert(profile->timepoints[pos] < lct);
7262 
7263  remainingduration = duration - (lct - profile->timepoints[pos]);
7264 
7265  if( remainingduration <= 0 )
7266  (*infeasible) = FALSE;
7267  else
7268  {
7269  pos = profileFindDownFeasibleStart(profile, pos, profile->timepoints[pos], remainingduration, demand, infeasible);
7270 
7271  if( *infeasible )
7272  {
7273  pos = profileFindDownFeasibleStart(profile, pos, ect, duration, demand, infeasible);
7274 
7275  assert(pos < profile->ntimepoints && pos >= 0);
7276  lct = profile->timepoints[pos];
7277  }
7278  }
7279  }
7280 
7281  return lct - duration;
7282 }
7283 
7284 /*
7285  * Directed graph
7286  */
7287 
7288 /** creates directed graph structure */
7290  SCIP_DIGRAPH** digraph, /**< pointer to store the created directed graph */
7291  BMS_BLKMEM* blkmem, /**< block memory to store the data */
7292  int nnodes /**< number of nodes */
7293  )
7294 {
7295  assert(digraph != NULL);
7296  assert(blkmem != NULL);
7297  assert(nnodes > 0);
7298 
7299  /* allocate memory for the graph and the arrays storing arcs and data */
7300  SCIP_ALLOC( BMSallocBlockMemory(blkmem, digraph) );
7301  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successors, nnodes) );
7302  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->arcdata, nnodes) );
7303  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->successorssize, nnodes) );
7304  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nsuccessors, nnodes) );
7305  SCIP_ALLOC( BMSallocClearBlockMemoryArray(blkmem, &(*digraph)->nodedata, nnodes) );
7306 
7307  /* store number of nodes */
7308  (*digraph)->nnodes = nnodes;
7309 
7310  /* at the beginning, no components are stored */
7311  (*digraph)->blkmem = blkmem;
7312  (*digraph)->ncomponents = 0;
7313  (*digraph)->componentstartsize = 0;
7314  (*digraph)->components = NULL;
7315  (*digraph)->componentstarts = NULL;
7316 
7317  /* all nodes are initially considered as non-articulation points */
7318  (*digraph)->narticulations = -1;
7319  (*digraph)->articulations = NULL;
7320  (*digraph)->articulationscheck = FALSE;
7321 
7322  return SCIP_OKAY;
7323 }
7324 
7325 /** resize directed graph structure */
7327  SCIP_DIGRAPH* digraph, /**< directed graph */
7328  int nnodes /**< new number of nodes */
7329  )
7330 {
7331  int n;
7332  assert(digraph != NULL);
7333  assert(digraph->blkmem != NULL);
7334 
7335  /* check if the digraph has already a proper size */
7336  if( nnodes <= digraph->nnodes )
7337  return SCIP_OKAY;
7338 
7339  /* reallocate memory for increasing the arrays storing arcs and data */
7340  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successors, digraph->nnodes, nnodes) );
7341  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->arcdata, digraph->nnodes, nnodes) );
7342  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->successorssize, digraph->nnodes, nnodes) );
7343  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nsuccessors, digraph->nnodes, nnodes) );
7344  SCIP_ALLOC( BMSreallocBlockMemoryArray(digraph->blkmem, &digraph->nodedata, digraph->nnodes, nnodes) );
7345 
7346  /* initialize the new node data structures */
7347  for( n = digraph->nnodes; n < nnodes; ++n )
7348  {
7349  digraph->nodedata[n] = NULL;
7350  digraph->arcdata[n] = NULL;
7351  digraph->successors[n] = NULL;
7352  digraph->successorssize[n] = 0;
7353  digraph->nsuccessors[n] = 0;
7354  }
7355 
7356  /* store the new number of nodes */
7357  digraph->nnodes = nnodes;
7358 
7359  return SCIP_OKAY;
7360 }
7361 
7362 /** copies directed graph structure
7363  *
7364  * @note The data in nodedata is copied verbatim. This possibly has to be adapted by the user.
7365  */
7367  SCIP_DIGRAPH** targetdigraph, /**< pointer to store the copied directed graph */
7368  SCIP_DIGRAPH* sourcedigraph, /**< source directed graph */
7369  BMS_BLKMEM* targetblkmem /**< block memory to store the target block memory, or NULL to use the same
7370  * the same block memory as used for the \p sourcedigraph */
7371  )
7372 {
7373  int ncomponents;
7374  int nnodes;
7375  int i;
7376  SCIP_Bool articulationscheck;
7377 
7378  assert(sourcedigraph != NULL);
7379  assert(targetdigraph != NULL);
7380 
7381  /* use the source digraph block memory if not specified otherwise */
7382  if( targetblkmem == NULL )
7383  targetblkmem = sourcedigraph->blkmem;
7384 
7385  assert(targetblkmem != NULL);
7386 
7387  SCIP_ALLOC( BMSallocBlockMemory(targetblkmem, targetdigraph) );
7388 
7389  nnodes = sourcedigraph->nnodes;
7390  ncomponents = sourcedigraph->ncomponents;
7391  articulationscheck = sourcedigraph->articulationscheck;
7392  (*targetdigraph)->nnodes = nnodes;
7393  (*targetdigraph)->ncomponents = ncomponents;
7394  (*targetdigraph)->blkmem = targetblkmem;
7395 
7396  /* copy arcs and data */
7397  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->successors, nnodes) );
7398  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->arcdata, nnodes) );
7399  SCIP_ALLOC( BMSallocClearBlockMemoryArray(targetblkmem, &(*targetdigraph)->nodedata, nnodes) );
7400 
7401  /* copy lists of successors and arc data */
7402  for( i = 0; i < nnodes; ++i )
7403  {
7404  if( sourcedigraph->nsuccessors[i] > 0 )
7405  {
7406  assert(sourcedigraph->successors[i] != NULL);
7407  assert(sourcedigraph->arcdata[i] != NULL);
7408 
7409  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->successors[i]),
7410  sourcedigraph->successors[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7411  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &((*targetdigraph)->arcdata[i]),
7412  sourcedigraph->arcdata[i], sourcedigraph->nsuccessors[i]) ); /*lint !e866*/
7413  }
7414  /* copy node data - careful if these are pointers to some information -> need to be copied by hand */
7415  (*targetdigraph)->nodedata[i] = sourcedigraph->nodedata[i];
7416  }
7417 
7418  /* use nsuccessors as size to save memory */
7419  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->successorssize, sourcedigraph->nsuccessors, nnodes) );
7420  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->nsuccessors, sourcedigraph->nsuccessors, nnodes) );
7421 
7422  /* copy component data */
7423  if( ncomponents > 0 )
7424  {
7425  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->components, sourcedigraph->components,
7426  sourcedigraph->componentstarts[ncomponents]) );
7427  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->componentstarts,
7428  sourcedigraph->componentstarts,ncomponents + 1) ); /*lint !e776*/
7429  (*targetdigraph)->componentstartsize = ncomponents + 1;
7430  }
7431  else
7432  {
7433  (*targetdigraph)->components = NULL;
7434  (*targetdigraph)->componentstarts = NULL;
7435  (*targetdigraph)->componentstartsize = 0;
7436  }
7437 
7438  /* copy the articulation point information if it has been computed and is up-to-date */
7439  if( articulationscheck )
7440  {
7441  SCIP_ALLOC( BMSduplicateBlockMemoryArray(targetblkmem, &(*targetdigraph)->articulations, sourcedigraph->articulations, sourcedigraph->narticulations) );
7442  (*targetdigraph)->narticulations = sourcedigraph->narticulations;
7443  (*targetdigraph)->articulationscheck = TRUE;
7444  }
7445  else
7446  {
7447  (*targetdigraph)->narticulations = -1;
7448  (*targetdigraph)->articulations = NULL;
7449  (*targetdigraph)->articulationscheck = FALSE;
7450  }
7451 
7452  return SCIP_OKAY;
7453 }
7454 
7455 /** sets the sizes of the successor lists for the nodes in a directed graph and allocates memory for the lists */
7457  SCIP_DIGRAPH* digraph, /**< directed graph */
7458  int* sizes /**< sizes of the successor lists */
7459  )
7460 {
7461  int i;
7462  BMS_BLKMEM* blkmem;
7463 
7464  assert(digraph != NULL);
7465  assert(digraph->nnodes > 0);
7466  blkmem = digraph->blkmem;
7467 
7468  for( i = 0; i < digraph->nnodes; ++i )
7469  {
7470  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[i], sizes[i]) ); /*lint !e866*/
7471  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[i], sizes[i]) ); /*lint !e866*/
7472  digraph->successorssize[i] = sizes[i];
7473  digraph->nsuccessors[i] = 0;
7474  }
7475 
7476  return SCIP_OKAY;
7477 }
7478 
7479 /** frees given directed graph structure */
7481  SCIP_DIGRAPH** digraph /**< pointer to the directed graph */
7482  )
7483 {
7484  int i;
7485  BMS_BLKMEM* blkmem;
7486  SCIP_DIGRAPH* digraphptr;
7487 
7488  assert(digraph != NULL);
7489  assert(*digraph != NULL);
7490  assert((*digraph)->blkmem != NULL);
7491 
7492  blkmem = (*digraph)->blkmem;
7493  digraphptr = *digraph;
7494 
7495  /* free arrays storing the successor nodes and arc data */
7496  for( i = digraphptr->nnodes - 1; i >= 0; --i )
7497  {
7498  BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->successors[i], digraphptr->successorssize[i]);
7499  BMSfreeBlockMemoryArrayNull(blkmem, &digraphptr->arcdata[i], digraphptr->successorssize[i]);
7500  }
7501 
7502  /* free components structure */
7503  SCIPdigraphFreeComponents(digraphptr);
7504  assert(digraphptr->ncomponents == 0);
7505  assert(digraphptr->componentstartsize == 0);
7506  assert(digraphptr->components == NULL);
7507  assert(digraphptr->componentstarts == NULL);
7508 
7509  /* free the articulation points structure if it has been computed*/
7510  if( digraphptr->articulationscheck )
7511  BMSfreeBlockMemoryArray(blkmem, &digraphptr->articulations, digraphptr->narticulations);
7512 
7513  /* free directed graph data structure */
7514  BMSfreeBlockMemoryArray(blkmem, &digraphptr->nodedata, digraphptr->nnodes);
7515  BMSfreeBlockMemoryArray(blkmem, &digraphptr->successorssize, digraphptr->nnodes);
7516  BMSfreeBlockMemoryArray(blkmem, &digraphptr->nsuccessors, digraphptr->nnodes);
7517  BMSfreeBlockMemoryArray(blkmem, &digraphptr->successors, digraphptr->nnodes);
7518  BMSfreeBlockMemoryArray(blkmem, &digraphptr->arcdata, digraphptr->nnodes);
7519 
7520  BMSfreeBlockMemory(blkmem, digraph);
7521 }
7522 
7523 #define STARTSUCCESSORSSIZE 5
7524 
7525 /** ensures that successors array of one node in a directed graph is big enough */
7526 static
7528  SCIP_DIGRAPH* digraph, /**< directed graph */
7529  int idx, /**< index for which the size is ensured */
7530  int newsize /**< needed size */
7531  )
7532 {
7533  BMS_BLKMEM* blkmem;
7534 
7535  assert(digraph != NULL);
7536  assert(digraph->blkmem != NULL);
7537  assert(idx >= 0);
7538  assert(idx < digraph->nnodes);
7539  assert(newsize > 0);
7540  assert(digraph->successorssize[idx] == 0 || digraph->successors[idx] != NULL);
7541  assert(digraph->successorssize[idx] == 0 || digraph->arcdata[idx] != NULL);
7542 
7543  blkmem = digraph->blkmem;
7544 
7545  /* check whether array is big enough, and realloc, if needed */
7546  if( newsize > digraph->successorssize[idx] )
7547  {
7548  if( digraph->successors[idx] == NULL )
7549  {
7550  assert(digraph->arcdata[idx] == NULL);
7551  digraph->successorssize[idx] = STARTSUCCESSORSSIZE;
7552  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7553  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx]) ); /*lint !e866*/
7554  }
7555  else
7556  {
7557  newsize = MAX(newsize, 2 * digraph->successorssize[idx]);
7558  assert(digraph->arcdata[idx] != NULL);
7559  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->successors[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7560  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &digraph->arcdata[idx], digraph->successorssize[idx], newsize) ); /*lint !e866*/
7561  digraph->successorssize[idx] = newsize;
7562  }
7563  }
7564 
7565  assert(newsize <= digraph->successorssize[idx]);
7566 
7567  return SCIP_OKAY;
7568 }
7569 
7570 /** add (directed) arc and a related data to the directed graph structure
7571  *
7572  * @note if the arc is already contained, it is added a second time
7573  */
7575  SCIP_DIGRAPH* digraph, /**< directed graph */
7576  int startnode, /**< start node of the arc */
7577  int endnode, /**< start node of the arc */
7578  void* data /**< data that should be stored for the arc; or NULL */
7579  )
7580 {
7581  assert(digraph != NULL);
7582  assert(startnode >= 0);
7583  assert(endnode >= 0);
7584  assert(startnode < digraph->nnodes);
7585  assert(endnode < digraph->nnodes);
7586 
7587  SCIP_CALL( ensureSuccessorsSize(digraph, startnode, digraph->nsuccessors[startnode] + 1) );
7588 
7589  /* add arc */
7590  digraph->successors[startnode][digraph->nsuccessors[startnode]] = endnode;
7591  digraph->arcdata[startnode][digraph->nsuccessors[startnode]] = data;
7592  digraph->nsuccessors[startnode]++;
7593 
7594  /* the articulation points are not up-to-date */
7595  digraph->articulationscheck = FALSE;
7596 
7597  return SCIP_OKAY;
7598 }
7599 
7600 /** add (directed) arc to the directed graph structure, if it is not contained, yet
7601  *
7602  * @note if there already exists an arc from startnode to endnode, the new arc is not added,
7603  * even if its data is different
7604  */
7606  SCIP_DIGRAPH* digraph, /**< directed graph */
7607  int startnode, /**< start node of the arc */
7608  int endnode, /**< start node of the arc */
7609  void* data /**< data that should be stored for the arc; or NULL */
7610  )
7611 {
7612  int nsuccessors;
7613  int i;
7614 
7615  assert(digraph != NULL);
7616  assert(startnode >= 0);
7617  assert(endnode >= 0);
7618  assert(startnode < digraph->nnodes);
7619  assert(endnode < digraph->nnodes);
7620 
7621  nsuccessors = digraph->nsuccessors[startnode];
7622 
7623  /* search for the arc in existing arcs */
7624  for( i = 0; i < nsuccessors; ++i )
7625  if( digraph->successors[startnode][i] == endnode )
7626  return SCIP_OKAY;
7627 
7628  SCIP_CALL( ensureSuccessorsSize(digraph, startnode, nsuccessors + 1) );
7629 
7630  /* add arc */
7631  digraph->successors[startnode][nsuccessors] = endnode;
7632  digraph->arcdata[startnode][nsuccessors] = data;
7633  ++(digraph->nsuccessors[startnode]);
7634 
7635  /* the articulation points are not up-to-date */
7636  digraph->articulationscheck = FALSE;
7637 
7638  return SCIP_OKAY;
7639 }
7640 
7641 /** sets the number of successors to a given value */
7643  SCIP_DIGRAPH* digraph, /**< directed graph */
7644  int node, /**< node for which the number of successors has to be changed */
7645  int nsuccessors /**< new number of successors */
7646  )
7647 {
7648  assert(digraph != NULL);
7649  assert(node >= 0);
7650  assert(node < digraph->nnodes);
7651 
7652  digraph->nsuccessors[node] = nsuccessors;
7653 
7654  return SCIP_OKAY;
7655 }
7656 
7657 /** returns the number of nodes of the given digraph */
7659  SCIP_DIGRAPH* digraph /**< directed graph */
7660  )
7661 {
7662  assert(digraph != NULL);
7663 
7664  return digraph->nnodes;
7665 }
7666 
7667 /** returns the node data, or NULL if no data exist */
7669  SCIP_DIGRAPH* digraph, /**< directed graph */
7670  int node /**< node for which the node data is returned */
7671  )
7672 {
7673  assert(digraph != NULL);
7674  assert(node >= 0);
7675  assert(node < digraph->nnodes);
7676 
7677  return digraph->nodedata[node];
7678 }
7679 
7680 /** sets the node data
7681  *
7682  * @note The old user pointer is not freed. This has to be done by the user
7683  */
7685  SCIP_DIGRAPH* digraph, /**< directed graph */
7686  void* dataptr, /**< user node data pointer, or NULL */
7687  int node /**< node for which the node data is returned */
7688  )
7689 {
7690  assert(digraph != NULL);
7691  assert(node >= 0);
7692  assert(node < digraph->nnodes);
7693 
7694  digraph->nodedata[node] = dataptr;
7695 }
7696 
7697 /** returns the total number of arcs in the given digraph */
7699  SCIP_DIGRAPH* digraph /**< directed graph */
7700  )
7701 {
7702  int i;
7703  int narcs;
7704 
7705  assert(digraph != NULL);
7706 
7707  /* count number of arcs */
7708  narcs = 0;
7709  for( i = 0; i < digraph->nnodes; ++i )
7710  narcs += digraph->nsuccessors[i];
7711 
7712  return narcs;
7713 }
7714 
7715 /** returns the number of successor nodes of the given node */
7717  SCIP_DIGRAPH* digraph, /**< directed graph */
7718  int node /**< node for which the number of outgoing arcs is returned */
7719  )
7720 {
7721  assert(digraph != NULL);
7722  assert(node >= 0);
7723  assert(node < digraph->nnodes);
7724  assert(digraph->nsuccessors[node] >= 0);
7725  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7726 
7727  return digraph->nsuccessors[node];
7728 }
7729 
7730 /** returns the array of indices of the successor nodes; this array must not be changed from outside */
7732  SCIP_DIGRAPH* digraph, /**< directed graph */
7733  int node /**< node for which the array of outgoing arcs is returned */
7734  )
7735 {
7736  assert(digraph != NULL);
7737  assert(node >= 0);
7738  assert(node < digraph->nnodes);
7739  assert(digraph->nsuccessors[node] >= 0);
7740  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7741  assert((digraph->nsuccessors[node] == 0) || (digraph->successors[node] != NULL));
7742 
7743  return digraph->successors[node];
7744 }
7745 
7746 /** returns the array of data corresponding to the arcs originating at the given node, or NULL if no data exist; this
7747  * array must not be changed from outside
7748  */
7750  SCIP_DIGRAPH* digraph, /**< directed graph */
7751  int node /**< node for which the data corresponding to the outgoing arcs is returned */
7752  )
7753 {
7754  assert(digraph != NULL);
7755  assert(node >= 0);
7756  assert(node < digraph->nnodes);
7757  assert(digraph->nsuccessors[node] >= 0);
7758  assert(digraph->nsuccessors[node] <= digraph->successorssize[node]);
7759  assert(digraph->arcdata != NULL);
7760 
7761  return digraph->arcdata[node];
7762 }
7763 
7764 /** performs depth-first-search in the given directed graph from the given start node */
7765 static
7767  SCIP_DIGRAPH* digraph, /**< directed graph */
7768  int startnode, /**< node to start the depth-first-search */
7769  SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7770  int* dfsstack, /**< array of size number of nodes to store the stack;
7771  * only needed for performance reasons */
7772  int* stackadjvisited, /**< array of size number of nodes to store the number of adjacent nodes already visited
7773  * for each node on the stack; only needed for performance reasons */
7774  int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse dfs order */
7775  int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at startnode */
7776  )
7777 {
7778  int stackidx;
7779 
7780  assert(digraph != NULL);
7781  assert(startnode >= 0);
7782  assert(startnode < digraph->nnodes);
7783  assert(visited != NULL);
7784  assert(visited[startnode] == FALSE);
7785  assert(dfsstack != NULL);
7786  assert(dfsnodes != NULL);
7787  assert(ndfsnodes != NULL);
7788 
7789  /* put start node on the stack */
7790  dfsstack[0] = startnode;
7791  stackadjvisited[0] = 0;
7792  stackidx = 0;
7793 
7794  while( stackidx >= 0 )
7795  {
7796  int currnode;
7797  int sadv;
7798 
7799  /* get next node from stack */
7800  currnode = dfsstack[stackidx];
7801 
7802  sadv = stackadjvisited[stackidx];
7803  assert( 0 <= sadv && sadv <= digraph->nsuccessors[currnode] );
7804 
7805  /* mark current node as visited */
7806  assert( visited[currnode] == (sadv > 0) );
7807  visited[currnode] = TRUE;
7808 
7809  /* iterate through the successor list until we reach unhandled node */
7810  while( sadv < digraph->nsuccessors[currnode] && visited[digraph->successors[currnode][sadv]] )
7811  ++sadv;
7812 
7813  /* the current node was completely handled, remove it from stack */
7814  if( sadv == digraph->nsuccessors[currnode] )
7815  {
7816  --stackidx;
7817 
7818  /* store node in the sorted nodes array */
7819  dfsnodes[(*ndfsnodes)++] = currnode;
7820  }
7821  /* handle next unhandled successor node */
7822  else
7823  {
7824  assert( ! visited[digraph->successors[currnode][sadv]] );
7825 
7826  /* store current stackadjvisted index */
7827  stackadjvisited[stackidx] = sadv + 1;
7828 
7829  /* put the successor node onto the stack */
7830  ++stackidx;
7831  dfsstack[stackidx] = digraph->successors[currnode][sadv];
7832  stackadjvisited[stackidx] = 0;
7833  assert( stackidx < digraph->nnodes );
7834  }
7835  }
7836 }
7837 
7838 /** checks for articulation points in a given directed graph through a recursive depth-first-search.
7839  * starts from a given start node and keeps track of the nodes' discovery time in search for back edges.
7840  *
7841  * @note an articulation point is a node whose removal disconnects a connected graph or increases
7842  * the number of connected components in a disconnected graph
7843  */
7844 static
7846  SCIP_DIGRAPH* digraph, /**< directed graph */
7847  int startnode, /**< node to start the depth-first-search */
7848  SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
7849  int* tdisc, /**< array of size number of nodes to store each node's discovery time */
7850  int* mindisc, /**< array of size number of nodes to store the discovery time of the earliest discovered vertex
7851  * to which startnode (or any node in the subtree rooted at it) is having a back edge */
7852  int* parent, /**< array to store the parent of each node in the DFS tree */
7853  SCIP_Bool* articulationflag, /**< array to mark whether a node is identified as an articulation point */
7854  int time /**< current discovery time in the DFS */
7855  )
7856 {
7857  int n;
7858  int nchildren = 0;
7859  int nsucc;
7860  int* succnodes;
7861 
7862  assert(digraph != NULL);
7863  assert(startnode >= 0);
7864  assert(startnode < digraph->nnodes);
7865  assert(visited != NULL);
7866  assert(visited[startnode] == FALSE);
7867  assert(tdisc != NULL);
7868  assert(mindisc != NULL);
7869  assert(parent != NULL);
7870  assert(articulationflag != NULL);
7871  assert(time >= 0);
7872 
7873  nsucc = (int) SCIPdigraphGetNSuccessors(digraph, startnode);
7874  succnodes = (int*) SCIPdigraphGetSuccessors(digraph, startnode);
7875  visited[startnode] = TRUE;
7876  tdisc[startnode] = time + 1;
7877  mindisc[startnode] = time + 1;
7878 
7879  /* process all the adjacent nodes to startnode */
7880  for( n = 0; n < nsucc; ++n)
7881  {
7882  if( !visited[succnodes[n]] )
7883  {
7884  parent[succnodes[n]] = startnode;
7885  ++nchildren;
7886  findArticulationPointsUtil(digraph, succnodes[n], visited, tdisc, mindisc, parent, articulationflag, time + 1);
7887  /* updated the mindisc of startnode when the DFS concludes for node n*/
7888  mindisc[startnode] = MIN(mindisc[startnode], mindisc[succnodes[n]]);
7889 
7890  /* the root is an articulation point if it has more than 2 children*/
7891  if( parent[startnode] == -1 && nchildren > 1 )
7892  articulationflag[startnode] = TRUE;
7893  /* a vertex startnode is an articulation point if it is not the root and
7894  * there is no back edge from the subtree rooted at child n to any of the ancestors of startnode */
7895  if( parent[startnode] > -1 && mindisc[succnodes[n]] >= tdisc[startnode] )
7896  articulationflag[startnode] = TRUE;
7897  }
7898  else
7899  {
7900  if( parent[startnode] != succnodes[n] )
7901  mindisc[startnode] = MIN(mindisc[startnode], tdisc[succnodes[n]]);
7902  }
7903  }
7904 
7905  if( articulationflag[startnode] )
7906  ++digraph->narticulations;
7907 }
7908 
7909 /** identifies the articulation points in a given directed graph
7910  * uses the helper recursive function findArticulationPointsUtil
7911  */
7913  SCIP_DIGRAPH* digraph, /**< directed graph */
7914  int** articulations, /**< array to store the sorted node indices of the computed articulation points, or NULL */
7915  int* narticulations /**< number of the computed articulation points, or NULL */
7916  )
7917 {
7918  SCIP_RETCODE retcode = SCIP_OKAY;
7919  BMS_BLKMEM* blkmem;
7920  SCIP_Bool* visited = NULL;
7921  SCIP_Bool* articulationflag = NULL;
7922  int* tdisc = NULL;
7923  int* mindisc = NULL;
7924  int* parent = NULL;
7925  int n;
7926  int articulationidx = 0;
7927  int time = 0;
7928 
7929  assert(digraph != NULL);
7930  assert(digraph->nnodes > 0);
7931 
7932  /* Only perform the computation if the articulation points are NOT up-to-date */
7933  if( !digraph->articulationscheck )
7934  {
7935  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&visited, digraph->nnodes), TERMINATE );
7936  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&tdisc, digraph->nnodes), TERMINATE );
7937  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&mindisc, digraph->nnodes), TERMINATE );
7938  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&parent, digraph->nnodes), TERMINATE );
7939  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&articulationflag, digraph->nnodes), TERMINATE );
7940 
7941  assert(digraph->blkmem != NULL);
7942  blkmem = digraph->blkmem;
7943 
7944  if( digraph->narticulations >= 0 ) /* case: articulations have already been computed but not up-to-date */
7945  BMSfreeBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations);
7946 
7947  /* Initialize the no. of articulation points ahead of the recursive computation */
7948  digraph->narticulations = 0;
7949 
7950  for( n = 0; n < digraph->nnodes; ++n )
7951  {
7952  visited[n] = FALSE;
7953  parent[n] = -1;
7954  articulationflag[n] = FALSE;
7955  }
7956 
7957  /* the function is called on every unvisited node in the graph to cover the disconnected graph case */
7958  for( n = 0; n < digraph->nnodes; ++n )
7959  {
7960  if( !visited[n] )
7961  findArticulationPointsUtil(digraph, n, visited, tdisc, mindisc, parent, articulationflag, time);
7962  }
7963 
7964  /* allocation of the block memory for the node indices of the articulation points*/
7965  SCIP_ALLOC_TERMINATE( retcode, BMSallocBlockMemoryArray(blkmem, &digraph->articulations, digraph->narticulations), TERMINATE );
7966 
7967  for( n = 0; n < digraph->nnodes; ++n )
7968  {
7969  if( articulationflag[n] )
7970  {
7971  digraph->articulations[articulationidx] = n;
7972  ++articulationidx;
7973  }
7974  }
7975  }
7976 
7977  if( articulations != NULL )
7978  (*articulations) = digraph->articulations;
7979  if( narticulations != NULL )
7980  (*narticulations) = digraph->narticulations;
7981 
7982  /* the articulation points are now up-to-date */
7983  digraph->articulationscheck = TRUE;
7984 
7985 /* cppcheck-suppress unusedLabel */
7986 TERMINATE:
7987  BMSfreeMemoryArrayNull(&articulationflag);
7988  BMSfreeMemoryArrayNull(&parent);
7989  BMSfreeMemoryArrayNull(&mindisc);
7990  BMSfreeMemoryArrayNull(&tdisc);
7991  BMSfreeMemoryArrayNull(&visited);
7992 
7993  return retcode;
7994 }
7995 
7996 /** Compute undirected connected components on the given graph.
7997  *
7998  * @note For each arc, its reverse is added, so the graph does not need to be the directed representation of an
7999  * undirected graph.
8000  */
8002  SCIP_DIGRAPH* digraph, /**< directed graph */
8003  int minsize, /**< all components with less nodes are ignored */
8004  int* components, /**< array with as many slots as there are nodes in the directed graph
8005  * to store for each node the component to which it belongs
8006  * (components are numbered 0 to ncomponents - 1); or NULL, if components
8007  * are accessed one-by-one using SCIPdigraphGetComponent() */
8008  int* ncomponents /**< pointer to store the number of components; or NULL, if the
8009  * number of components is accessed by SCIPdigraphGetNComponents() */
8010  )
8011 {
8012  BMS_BLKMEM* blkmem;
8013  SCIP_Bool* visited;
8014  int* ndirectedsuccessors;
8015  int* stackadjvisited;
8016  int* dfsstack;
8017  int ndfsnodes;
8018  int compstart;
8019  int v;
8020  int i;
8021  int j;
8022 
8023  SCIP_RETCODE retcode = SCIP_OKAY;
8024 
8025  assert(digraph != NULL);
8026  assert(digraph->nnodes > 0);
8027  assert(digraph->blkmem != NULL);
8028 
8029  blkmem = digraph->blkmem;
8030 
8031  /* first free the old components */
8032  if( digraph->ncomponents > 0 )
8033  {
8034  SCIPdigraphFreeComponents(digraph);
8035  }
8036 
8037  digraph->ncomponents = 0;
8038  digraph->componentstartsize = 10;
8039 
8040  /* storage to hold components is stored in block memory */
8041  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes) );
8043 
8044  /* allocate temporary arrays */
8045  SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8046  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8047  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8048  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&ndirectedsuccessors, digraph->nnodes), TERMINATE );
8049 
8050  digraph->componentstarts[0] = 0;
8051 
8052  /* store the number of directed arcs per node */
8053  BMScopyMemoryArray(ndirectedsuccessors, digraph->nsuccessors, digraph->nnodes);
8054 
8055  /* add reverse arcs to the graph */
8056  for( i = digraph->nnodes - 1; i >= 0; --i )
8057  {
8058  for( j = 0; j < ndirectedsuccessors[i]; ++j )
8059  {
8060  SCIP_CALL_TERMINATE( retcode, SCIPdigraphAddArc(digraph, digraph->successors[i][j], i, NULL), TERMINATE );
8061  }
8062  }
8063 
8064  for( v = 0; v < digraph->nnodes; ++v )
8065  {
8066  if( visited[v] )
8067  continue;
8068 
8069  compstart = digraph->componentstarts[digraph->ncomponents];
8070  ndfsnodes = 0;
8071  depthFirstSearch(digraph, v, visited, dfsstack, stackadjvisited,
8072  &digraph->components[compstart], &ndfsnodes);
8073 
8074  /* forget about this component if it is too small */
8075  if( ndfsnodes >= minsize )
8076  {
8077  digraph->ncomponents++;
8078 
8079  /* enlarge componentstartsize array, if needed */
8080  if( digraph->ncomponents >= digraph->componentstartsize )
8081  {
8082  int newsize;
8083 
8084  newsize = 2 * digraph->componentstartsize;
8085  assert(digraph->ncomponents < newsize);
8086 
8087  SCIP_ALLOC_TERMINATE( retcode, BMSreallocBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize, newsize), TERMINATE );
8088  digraph->componentstartsize = newsize;
8089  }
8090  digraph->componentstarts[digraph->ncomponents] = compstart + ndfsnodes;
8091 
8092  /* store component number for contained nodes if array was given */
8093  if( components != NULL )
8094  {
8095  for( i = digraph->componentstarts[digraph->ncomponents] - 1; i >= compstart; --i )
8096  {
8097  components[digraph->components[i]] = digraph->ncomponents - 1;
8098  }
8099  }
8100  }
8101  }
8102 
8103  /* restore the number of directed arcs per node */
8104  BMScopyMemoryArray(digraph->nsuccessors, ndirectedsuccessors, digraph->nnodes);
8105  BMSclearMemoryArray(visited, digraph->nnodes);
8106 
8107  /* return number of components, if the pointer was given */
8108  if( ncomponents != NULL )
8109  (*ncomponents) = digraph->ncomponents;
8110 
8111 TERMINATE:
8112  if( retcode != SCIP_OKAY )
8113  {
8114  SCIPdigraphFreeComponents(digraph);
8115  }
8116  BMSfreeMemoryArrayNull(&ndirectedsuccessors);
8117  BMSfreeMemoryArrayNull(&stackadjvisited);
8118  BMSfreeMemoryArrayNull(&dfsstack);
8119  BMSfreeMemoryArrayNull(&visited);
8120 
8121  return retcode;
8122 }
8123 
8124 /** Performs an (almost) topological sort on the undirected components of the given directed graph. The undirected
8125  * components should be computed before using SCIPdigraphComputeUndirectedComponents().
8126  *
8127  * @note In general a topological sort is not unique. Note, that there might be directed cycles, that are randomly
8128  * broken, which is the reason for having only almost topologically sorted arrays.
8129  */
8131  SCIP_DIGRAPH* digraph /**< directed graph */
8132  )
8133 {
8134  SCIP_Bool* visited = NULL;
8135  int* comps;
8136  int* compstarts;
8137  int* stackadjvisited = NULL;
8138  int* dfsstack = NULL;
8139  int* dfsnodes = NULL;
8140  int ndfsnodes;
8141  int ncomps;
8142  int i;
8143  int j;
8144  int k;
8145  int endidx;
8146  SCIP_RETCODE retcode = SCIP_OKAY;
8147 
8148  assert(digraph != NULL);
8149 
8150  ncomps = digraph->ncomponents;
8151  comps = digraph->components;
8152  compstarts = digraph->componentstarts;
8153 
8154  SCIP_ALLOC_TERMINATE( retcode, BMSallocClearMemoryArray(&visited, digraph->nnodes), TERMINATE );
8155  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsnodes, digraph->nnodes), TERMINATE );
8156  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsstack, digraph->nnodes), TERMINATE );
8157  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stackadjvisited, digraph->nnodes), TERMINATE );
8158 
8159  /* sort the components (almost) topologically */
8160  for( i = 0; i < ncomps; ++i )
8161  {
8162  endidx = compstarts[i+1] - 1;
8163  ndfsnodes = 0;
8164  for( j = compstarts[i]; j < compstarts[i+1]; ++j )
8165  {
8166  if( visited[comps[j]] )
8167  continue;
8168 
8169  /* perform depth first search, nodes visited in this call are appended to the list dfsnodes in reverse
8170  * dfs order, after the nodes already contained;
8171  * so at every point in time, the nodes in dfsnode are in reverse (almost) topological order
8172  */
8173  depthFirstSearch(digraph, comps[j], visited, dfsstack, stackadjvisited, dfsnodes, &ndfsnodes);
8174  }
8175  assert(endidx - ndfsnodes == compstarts[i] - 1);
8176 
8177  /* copy reverse (almost) topologically sorted array of nodes reached by the dfs searches;
8178  * reverse their order to get an (almost) topologically sort
8179  */
8180  for( k = 0; k < ndfsnodes; ++k )
8181  {
8182  digraph->components[endidx - k] = dfsnodes[k];
8183  }
8184  }
8185 
8186 TERMINATE:
8187  BMSfreeMemoryArrayNull(&stackadjvisited);
8188  BMSfreeMemoryArrayNull(&dfsstack);
8189  BMSfreeMemoryArrayNull(&dfsnodes);
8190  BMSfreeMemoryArrayNull(&visited);
8191 
8192  return retcode;
8193 }
8194 
8195 /** returns the number of previously computed undirected components for the given directed graph */
8197  SCIP_DIGRAPH* digraph /**< directed graph */
8198  )
8199 {
8200  assert(digraph != NULL);
8201  assert(digraph->componentstartsize > 0); /* components should have been computed */
8202 
8203  return digraph->ncomponents;
8204 }
8205 
8206 /** Returns the previously computed undirected component of the given number for the given directed graph.
8207  * If the components were sorted using SCIPdigraphTopoSortComponents(), the component is (almost) topologically sorted.
8208  */
8210  SCIP_DIGRAPH* digraph, /**< directed graph */
8211  int compidx, /**< number of the component to return */
8212  int** nodes, /**< pointer to store the nodes in the component; or NULL, if not needed */
8213  int* nnodes /**< pointer to store the number of nodes in the component;
8214  * or NULL, if not needed */
8215  )
8216 {
8217  assert(digraph != NULL);
8218  assert(compidx >= 0);
8219  assert(compidx < digraph->ncomponents);
8220  assert(nodes != NULL || nnodes != NULL);
8221 
8222  if( nodes != NULL )
8223  (*nodes) = &(digraph->components[digraph->componentstarts[compidx]]);
8224  if( nnodes != NULL )
8225  (*nnodes) = digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx];
8226 }
8227 
8228 /* Performs Tarjan's algorithm for a given directed graph to obtain the strongly connected components
8229  * which are reachable from a given node.
8230  */
8231 static
8232 void tarjan(
8233  SCIP_DIGRAPH* digraph, /**< directed graph */
8234  int v, /**< node to start the algorithm */
8235  int* lowlink, /**< array to store lowlink values */
8236  int* dfsidx, /**< array to store dfs indices */
8237  int* stack, /**< array to store a stack */
8238  int* stacksize, /**< pointer to store the size of the stack */
8239  SCIP_Bool* unprocessed, /**< array to store which node is unprocessed yet */
8240  SCIP_Bool* nodeinstack, /**< array to store which nodes are in the stack */
8241  int* maxdfs, /**< pointer to store index for DFS */
8242  int* strongcomponents, /**< array to store for each node the strongly connected
8243  * component to which it belongs (components are
8244  * numbered 0 to nstrongcomponents - 1); */
8245  int* nstrongcomponents, /**< pointer to store the number of computed components so far */
8246  int* strongcompstartidx, /**< array to store the start index of the computed components */
8247  int* nstorednodes /**< pointer to store the number of already stored nodes */
8248  )
8249 {
8250  int i;
8251 
8252  assert(digraph != NULL);
8253  assert(v >= 0);
8254  assert(v < digraph->nnodes);
8255  assert(lowlink != NULL);
8256  assert(dfsidx != NULL);
8257  assert(stack != NULL);
8258  assert(stacksize != NULL);
8259  assert(*stacksize >= 0);
8260  assert(*stacksize < digraph->nnodes);
8261  assert(unprocessed != NULL);
8262  assert(nodeinstack != NULL);
8263  assert(maxdfs != NULL);
8264  assert(strongcomponents != NULL);
8265  assert(nstrongcomponents != NULL);
8266  assert(strongcompstartidx != NULL);
8267  assert(nstorednodes != NULL);
8268  assert(*nstorednodes >= 0 && *nstorednodes < digraph->nnodes);
8269 
8270  dfsidx[v] = *maxdfs;
8271  lowlink[v] = *maxdfs;
8272  *maxdfs += 1;
8273 
8274  /* add v to the stack */
8275  stack[*stacksize] = v;
8276  *stacksize += 1;
8277  nodeinstack[v] = TRUE;
8278 
8279  /* mark v as processed */
8280  unprocessed[v] = FALSE;
8281 
8282  for( i = 0; i < digraph->nsuccessors[v]; ++i )
8283  {
8284  int w;
8285 
8286  /* edge (v,w) */
8287  w = digraph->successors[v][i];
8288 
8289  if( unprocessed[w] )
8290  {
8291  tarjan(digraph, w, lowlink, dfsidx, stack, stacksize, unprocessed, nodeinstack, maxdfs, strongcomponents,
8292  nstrongcomponents, strongcompstartidx, nstorednodes);
8293 
8294  assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8295  assert(lowlink[w] >= 0 && lowlink[w] < digraph->nnodes);
8296 
8297  /* update lowlink */
8298  lowlink[v] = MIN(lowlink[v], lowlink[w]);
8299  }
8300  else if( nodeinstack[w] )
8301  {
8302  assert(lowlink[v] >= 0 && lowlink[v] < digraph->nnodes);
8303  assert(dfsidx[w] >= 0 && dfsidx[w] < digraph->nnodes);
8304 
8305  /* update lowlink */
8306  lowlink[v] = MIN(lowlink[v], dfsidx[w]);
8307  }
8308  }
8309 
8310  /* found a root of a strong component */
8311  if( lowlink[v] == dfsidx[v] )
8312  {
8313  int w;
8314 
8315  strongcompstartidx[*nstrongcomponents] = *nstorednodes;
8316  *nstrongcomponents += 1;
8317 
8318  do
8319  {
8320  assert(*stacksize > 0);
8321 
8322  /* stack.pop() */
8323  w = stack[*stacksize - 1];
8324  *stacksize -= 1;
8325  nodeinstack[w] = FALSE;
8326 
8327  /* store the node in the corresponding component */
8328  strongcomponents[*nstorednodes] = w;
8329  *nstorednodes += 1;
8330  }
8331  while( v != w );
8332  }
8333 }
8334 
8335 /** Computes all strongly connected components of an undirected connected component with Tarjan's Algorithm.
8336  * The resulting strongly connected components are sorted topologically (starting from the end of the
8337  * strongcomponents array).
8338  *
8339  * @note In general a topological sort of the strongly connected components is not unique.
8340  */
8342  SCIP_DIGRAPH* digraph, /**< directed graph */
8343  int compidx, /**< number of the undirected connected component */
8344  int* strongcomponents, /**< array to store the strongly connected components
8345  * (length >= size of the component) */
8346  int* strongcompstartidx, /**< array to store the start indices of the strongly connected
8347  * components (length >= size of the component) */
8348  int* nstrongcomponents /**< pointer to store the number of strongly connected
8349  * components */
8350  )
8351 {
8352  int* lowlink = NULL;
8353  int* dfsidx = NULL;
8354  int* stack = NULL;
8355  int stacksize;
8356  SCIP_Bool* unprocessed = NULL;
8357  SCIP_Bool* nodeinstack = NULL;
8358  int maxdfs;
8359  int nstorednodes;
8360  int i;
8361  SCIP_RETCODE retcode;
8362 
8363  assert(digraph != NULL);
8364  assert(compidx >= 0);
8365  assert(compidx < digraph->ncomponents);
8366  assert(strongcomponents != NULL);
8367  assert(strongcompstartidx != NULL);
8368  assert(nstrongcomponents != NULL);
8369 
8370  retcode = SCIP_OKAY;
8371 
8372  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&lowlink, digraph->nnodes), TERMINATE );
8373  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&dfsidx, digraph->nnodes), TERMINATE );
8374  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&stack, digraph->nnodes), TERMINATE );
8375  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&unprocessed, digraph->nnodes), TERMINATE );
8376  SCIP_ALLOC_TERMINATE( retcode, BMSallocMemoryArray(&nodeinstack, digraph->nnodes), TERMINATE );
8377 
8378  for( i = 0; i < digraph->nnodes; ++i )
8379  {
8380  lowlink[i] = -1;
8381  dfsidx[i] = -1;
8382  stack[i] = -1;
8383  unprocessed[i] = TRUE;
8384  nodeinstack[i] = FALSE;
8385  }
8386 
8387  nstorednodes = 0;
8388  stacksize = 0;
8389  maxdfs = 0;
8390  *nstrongcomponents = 0;
8391 
8392  /* iterate over all nodes in the undirected connected component */
8393  for( i = digraph->componentstarts[compidx]; i < digraph->componentstarts[compidx + 1]; ++i )
8394  {
8395  int v;
8396 
8397  v = digraph->components[i];
8398  assert(v >= 0 && v < digraph->nnodes);
8399 
8400  /* call Tarjan's algorithm for unprocessed nodes */
8401  if( unprocessed[v] )
8402  {
8403  SCIPdebugMessage("apply Tarjan's algorithm for node %d\n", v);
8404  tarjan(digraph, v, lowlink, dfsidx, stack, &stacksize, unprocessed, nodeinstack, &maxdfs,
8405  strongcomponents, nstrongcomponents, strongcompstartidx, &nstorednodes);
8406  }
8407  }
8408 
8409  /* we should have stored as many nodes as in the undirected connected component */
8410  assert(nstorednodes == digraph->componentstarts[compidx + 1] - digraph->componentstarts[compidx]);
8411 
8412  /* to simplify the iteration over all strongly connected components */
8413  assert(*nstrongcomponents < digraph->nnodes + 1);
8414  strongcompstartidx[*nstrongcomponents] = nstorednodes;
8415 
8416  assert(retcode == SCIP_OKAY);
8417 
8418 TERMINATE:
8419  BMSfreeMemoryArrayNull(&lowlink);
8420  BMSfreeMemoryArrayNull(&dfsidx);
8421  BMSfreeMemoryArrayNull(&stack);
8422  BMSfreeMemoryArrayNull(&unprocessed);
8423  BMSfreeMemoryArrayNull(&nodeinstack);
8424 
8425  return retcode;
8426 }
8427 
8428 /** frees the component information for the given directed graph */
8430  SCIP_DIGRAPH* digraph /**< directed graph */
8431  )
8432 {
8433  BMS_BLKMEM* blkmem;
8434 
8435  assert(digraph != NULL);
8436  assert(digraph->blkmem != NULL);
8437 
8438  blkmem = digraph->blkmem;
8439 
8440  /* free components structure */
8441  if( digraph->componentstartsize > 0 )
8442  {
8443  BMSfreeBlockMemoryArray(blkmem, &digraph->componentstarts, digraph->componentstartsize);
8444  BMSfreeBlockMemoryArray(blkmem, &digraph->components, digraph->nnodes);
8445  digraph->components = NULL;
8446  digraph->componentstarts = NULL;
8447  digraph->ncomponents = 0;
8448  digraph->componentstartsize = 0;
8449  }
8450 #ifndef NDEBUG
8451  else
8452  {
8453  assert(digraph->components == NULL);
8454  assert(digraph->componentstarts == NULL);
8455  assert(digraph->ncomponents == 0);
8456  }
8457 #endif
8458 }
8459 
8460 /** output of the given directed graph via the given message handler */
8462  SCIP_DIGRAPH* digraph, /**< directed graph */
8463  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8464  FILE* file /**< output file (or NULL for standard output) */
8465  )
8466 {
8467  int n;
8468 
8469  for( n = 0; n < digraph->nnodes; ++n )
8470  {
8471  int* successors;
8472  int nsuccessors;
8473  int m;
8474 
8475  nsuccessors = digraph->nsuccessors[n];
8476  successors = digraph->successors[n];
8477 
8478  SCIPmessageFPrintInfo(messagehdlr, file, "node %d --> ", n);
8479 
8480  for( m = 0; m < nsuccessors ; ++m )
8481  {
8482  if( m == 0 )
8483  {
8484  SCIPmessageFPrintInfo(messagehdlr, file, "%d", successors[m]);
8485  }
8486  else
8487  {
8488  SCIPmessageFPrintInfo(messagehdlr, file, ", %d", successors[m]);
8489  }
8490  }
8491  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8492  }
8493 }
8494 
8495 /** prints the given directed graph structure in GML format into the given file */
8497  SCIP_DIGRAPH* digraph, /**< directed graph */
8498  FILE* file /**< file to write to */
8499  )
8500 {
8501  int n;
8502 
8503  /* write GML format opening */
8504  SCIPgmlWriteOpening(file, TRUE);
8505 
8506  /* write all nodes of the graph */
8507  for( n = 0; n < digraph->nnodes; ++n )
8508  {
8509  char label[SCIP_MAXSTRLEN];
8510 
8511  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", n);
8512  SCIPgmlWriteNode(file, (unsigned int)n, label, "circle", NULL, NULL);
8513  }
8514 
8515  /* write all edges */
8516  for( n = 0; n < digraph->nnodes; ++n )
8517  {
8518  int* successors;
8519  int nsuccessors;
8520  int m;
8521 
8522  nsuccessors = digraph->nsuccessors[n];
8523  successors = digraph->successors[n];
8524 
8525  for( m = 0; m < nsuccessors; ++m )
8526  {
8527  SCIPgmlWriteArc(file, (unsigned int)n, (unsigned int)successors[m], NULL, NULL);
8528  }
8529  }
8530  /* write GML format closing */
8531  SCIPgmlWriteClosing(file);
8532 }
8533 
8534 /** output of the given directed graph via the given message handler */
8536  SCIP_DIGRAPH* digraph, /**< directed graph */
8537  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
8538  FILE* file /**< output file (or NULL for standard output) */
8539  )
8540 {
8541  int c;
8542  int i;
8543 
8544  for( c = 0; c < digraph->ncomponents; ++c )
8545  {
8546  int start = digraph->componentstarts[c];
8547  int end = digraph->componentstarts[c+1];
8548 
8549  SCIPmessageFPrintInfo(messagehdlr, file, "Components %d --> ", c);
8550 
8551  for( i = start; i < end; ++i )
8552  {
8553  if( i == start )
8554  {
8555  SCIPmessageFPrintInfo(messagehdlr, file, "%d", digraph->components[i]);
8556  }
8557  else
8558  {
8559  SCIPmessageFPrintInfo(messagehdlr, file, ", %d", digraph->components[i]);
8560  }
8561  }
8562  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
8563  }
8564 }
8565 
8566 /*
8567  * Binary tree
8568  */
8569 
8570 /** creates a node for a binary tree */
8571 static
8573  SCIP_BT* tree, /**< binary tree */
8574  SCIP_BTNODE** node /**< pointer to store the created node */
8575  )
8576 {
8577  SCIP_ALLOC( BMSallocBlockMemory(tree->blkmem, node) );
8578 
8579  (*node)->parent = NULL;
8580  (*node)->left = NULL;
8581  (*node)->right = NULL;
8582  (*node)->dataptr = NULL;
8583 
8584  return SCIP_OKAY;
8585 }
8586 
8587 /** creates a tree node with (optinal) user data */
8589  SCIP_BT* tree, /**< binary tree */
8590  SCIP_BTNODE** node, /**< pointer to store the created node */
8591  void* dataptr /**< user node data pointer, or NULL */
8592  )
8593 {
8594  assert(tree != NULL);
8595  assert(node != NULL);
8596 
8597  SCIP_CALL( btnodeCreateEmpty(tree, node) );
8598 
8599  assert((*node)->parent == NULL);
8600  assert((*node)->left == NULL);
8601  assert((*node)->right == NULL);
8602 
8603  /* initialize user data */
8604  (*node)->dataptr = dataptr;
8605 
8606  return SCIP_OKAY;
8607 }
8608 
8609 /** frees a tree leaf */
8610 static
8612  SCIP_BT* tree, /**< binary tree */
8613  SCIP_BTNODE** node /**< pointer to node which has to be freed */
8614  )
8615 {
8616  assert(tree != NULL);
8617  assert(node != NULL);
8618  assert(*node != NULL);
8619 
8620  assert((*node)->left == NULL);
8621  assert((*node)->right == NULL);
8622 
8623 #if 0
8624  /* remove reference from parent node */
8625  if( (*node)->parent != NULL )
8626  {
8627  assert(*node != NULL);
8628 
8629  assert((*node)->parent->left == *node || ((*node)->parent->right == *node));
8630 
8631  if( (*node)->parent->left == *node )
8632  {
8633  (*node)->parent->left = NULL;
8634  }
8635  else
8636  {
8637  assert((*node)->parent->right == *node);
8638  (*node)->parent->right = NULL;
8639  }
8640  }
8641 #endif
8642 
8643  assert(*node != NULL);
8644  BMSfreeBlockMemory(tree->blkmem, node);
8645  assert(*node == NULL);
8646 }
8647 
8648 /** frees the node including the rooted subtree
8649  *
8650  * @note The user pointer (object) is not freed. If needed, it has to be done by the user.
8651  */
8653  SCIP_BT* tree, /**< binary tree */
8654  SCIP_BTNODE** node /**< node to be freed */
8655  )
8656 {
8657  assert(tree != NULL);
8658  assert(node != NULL);
8659  assert(*node != NULL);
8660 
8661  if( (*node)->left != NULL )
8662  {
8663  SCIPbtnodeFree(tree, &(*node)->left);
8664  assert((*node)->left == NULL);
8665  }
8666 
8667  if( (*node)->right != NULL )
8668  {
8669  SCIPbtnodeFree(tree, &(*node)->right);
8670  assert((*node)->right == NULL);
8671  }
8672 
8673  btnodeFreeLeaf(tree, node);
8674  assert(*node == NULL);
8675 }
8676 
8677 /* some simple variable functions implemented as defines */
8678 
8679 /* In debug mode, the following methods are implemented as function calls to ensure
8680  * type validity.
8681  * In optimized mode, the methods are implemented as defines to improve performance.
8682  * However, we want to have them in the library anyways, so we have to undef the defines.
8683  */
8684 
8685 #undef SCIPbtnodeGetData
8686 #undef SCIPbtnodeGetKey
8687 #undef SCIPbtnodeGetParent
8688 #undef SCIPbtnodeGetLeftchild
8689 #undef SCIPbtnodeGetRightchild
8690 #undef SCIPbtnodeGetSibling
8691 #undef SCIPbtnodeIsRoot
8692 #undef SCIPbtnodeIsLeaf
8693 #undef SCIPbtnodeIsLeftchild
8694 #undef SCIPbtnodeIsRightchild
8695 
8696 /** returns the user data pointer stored in that node */
8698  SCIP_BTNODE* node /**< node */
8699  )
8700 {
8701  assert(node != NULL);
8702 
8703  return node->dataptr;
8704 }
8705 
8706 /** returns the parent which can be NULL if the given node is the root */
8708  SCIP_BTNODE* node /**< node */
8709  )
8710 {
8711  assert(node != NULL);
8712 
8713  return node->parent;
8714 }
8715 
8716 /** returns left child which can be NULL if the given node is a leaf */
8718  SCIP_BTNODE* node /**< node */
8719  )
8720 {
8721  assert(node != NULL);
8722 
8723  return node->left;
8724 }
8725 
8726 /** returns right child which can be NULL if the given node is a leaf */
8728  SCIP_BTNODE* node /**< node */
8729  )
8730 {
8731  assert(node != NULL);
8732 
8733  return node->right;
8734 }
8735 
8736 /** returns the sibling of the node or NULL if does not exist */
8738  SCIP_BTNODE* node /**< node */
8739  )
8740 {
8741  SCIP_BTNODE* parent;
8742 
8743  parent = SCIPbtnodeGetParent(node);
8744 
8745  if( parent == NULL )
8746  return NULL;
8747 
8748  if( SCIPbtnodeGetLeftchild(parent) == node )
8749  return SCIPbtnodeGetRightchild(parent);
8750 
8751  assert(SCIPbtnodeGetRightchild(parent) == node);
8752 
8753  return SCIPbtnodeGetLeftchild(parent);
8754 }
8755 
8756 /** returns whether the node is a root node */
8758  SCIP_BTNODE* node /**< node */
8759  )
8760 {
8761  assert(node != NULL);
8762 
8763  return (node->parent == NULL);
8764 }
8765 
8766 /** returns whether the node is a leaf */
8768  SCIP_BTNODE* node /**< node */
8769  )
8770 {
8771  assert(node != NULL);
8772 
8773  return (node->left == NULL && node->right == NULL);
8774 }
8775 
8776 /** returns TRUE if the given node is left child */
8778  SCIP_BTNODE* node /**< node */
8779  )
8780 {
8781  SCIP_BTNODE* parent;
8782 
8783  if( SCIPbtnodeIsRoot(node) )
8784  return FALSE;
8785 
8786  parent = SCIPbtnodeGetParent(node);
8787 
8788  if( SCIPbtnodeGetLeftchild(parent) == node )
8789  return TRUE;
8790 
8791  return FALSE;
8792 }
8793 
8794 /** returns TRUE if the given node is right child */
8796  SCIP_BTNODE* node /**< node */
8797  )
8798 {
8799  SCIP_BTNODE* parent;
8800 
8801  if( SCIPbtnodeIsRoot(node) )
8802  return FALSE;
8803 
8804  parent = SCIPbtnodeGetParent(node);
8805 
8806  if( SCIPbtnodeGetRightchild(parent) == node )
8807  return TRUE;
8808 
8809  return FALSE;
8810 }
8811 
8812 /** sets the give node data
8813  *
8814  * @note The old user pointer is not freed.
8815  */
8817  SCIP_BTNODE* node, /**< node */
8818  void* dataptr /**< node user data pointer */
8819  )
8820 {
8821  assert(node != NULL);
8822 
8823  node->dataptr = dataptr;
8824 }
8825 
8826 /** sets parent node
8827  *
8828  * @note The old parent including the rooted subtree is not delete.
8829  */
8831  SCIP_BTNODE* node, /**< node */
8832  SCIP_BTNODE* parent /**< new parent node, or NULL */
8833  )
8834 {
8835  assert(node != NULL);
8836 
8837  node->parent = parent;
8838 }
8839 
8840 /** sets left child
8841  *
8842  * @note The old left child including the rooted subtree is not delete.
8843  */
8845  SCIP_BTNODE* node, /**< node */
8846  SCIP_BTNODE* left /**< new left child, or NULL */
8847  )
8848 {
8849  assert(node != NULL);
8850 
8851  node->left = left;
8852 }
8853 
8854 /** sets right child
8855  *
8856  * @note The old right child including the rooted subtree is not delete.
8857  */
8859  SCIP_BTNODE* node, /**< node */
8860  SCIP_BTNODE* right /**< new right child, or NULL */
8861  )
8862 {
8863  assert(node != NULL);
8864 
8865  node->right = right;
8866 }
8867 
8868 /** creates an binary tree */
8870  SCIP_BT** tree, /**< pointer to store the created binary tree */
8871  BMS_BLKMEM* blkmem /**< block memory used to createnode */
8872  )
8873 {
8874  assert(tree != NULL);
8875  assert(blkmem != NULL);
8876 
8877  SCIP_ALLOC( BMSallocBlockMemory(blkmem, tree) );
8878  (*tree)->blkmem = blkmem;
8879  (*tree)->root = NULL;
8880 
8881  return SCIP_OKAY;
8882 }
8883 
8884 /** frees binary tree
8885  *
8886  * @note The user pointers (object) of the nodes are not freed. If needed, it has to be done by the user.
8887  */
8889  SCIP_BT** tree /**< pointer to binary tree */
8890  )
8891 {
8892  assert(tree != NULL);
8893 
8894  if( (*tree)->root != NULL )
8895  {
8896  SCIPbtnodeFree(*tree, &((*tree)->root));
8897  }
8898 
8899  BMSfreeBlockMemory((*tree)->blkmem, tree);
8900 }
8901 
8902 /** prints the rooted subtree of the given binary tree node in GML format into the given file */
8903 static
8905  SCIP_BTNODE* node, /**< binary tree node */
8906  FILE* file, /**< file to write to */
8907  int* nnodes /**< pointer to count the number of nodes */
8908  )
8909 {
8910  SCIP_BTNODE* left;
8911  SCIP_BTNODE* right;
8912  char label[SCIP_MAXSTRLEN];
8913 
8914  assert(node != NULL);
8915 
8916  (*nnodes)++;
8917  (void)SCIPsnprintf(label, SCIP_MAXSTRLEN, "%d", *nnodes);
8918 
8919  SCIPgmlWriteNode(file, (unsigned int)(size_t)node, label, "circle", NULL, NULL);
8920 
8921  left = SCIPbtnodeGetLeftchild(node);
8922  right = SCIPbtnodeGetRightchild(node);
8923 
8924  if( left != NULL )
8925  {
8926  btPrintSubtree(left, file, nnodes);
8927 
8928  SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)left, NULL, NULL);
8929  }
8930 
8931  if( right != NULL )
8932  {
8933  btPrintSubtree(right, file, nnodes);
8934 
8935  SCIPgmlWriteArc(file, (unsigned int)(size_t)node, (unsigned int)(size_t)right, NULL, NULL);
8936  }
8937 }
8938 
8939 /** prints the binary tree in GML format into the given file */
8941  SCIP_BT* tree, /**< binary tree */
8942  FILE* file /**< file to write to */
8943  )
8944 {
8945  /* write GML opening */
8946  SCIPgmlWriteOpening(file, TRUE);
8947 
8948  if( !SCIPbtIsEmpty(tree) )
8949  {
8950  SCIP_BTNODE* root;
8951  int nnodes;
8952 
8953  root = SCIPbtGetRoot(tree);
8954  assert(root != NULL);
8955 
8956  nnodes = 0;
8957 
8958  btPrintSubtree(root, file, &nnodes);
8959  }
8960 
8961  /* write GML closing */
8962  SCIPgmlWriteClosing(file);
8963 }
8964 
8965 /* some simple variable functions implemented as defines */
8966 #undef SCIPbtIsEmpty
8967 #undef SCIPbtGetRoot
8968 
8969 /** returns whether the binary tree is empty (has no nodes) */
8971  SCIP_BT* tree /**< binary tree */
8972  )
8973 {
8974  assert(tree != NULL);
8975 
8976  return (tree->root == NULL);
8977 }
8978 
8979 /** returns the the root node of the binary or NULL if the binary tree is empty */
8981  SCIP_BT* tree /**< tree to be evaluated */
8982  )
8983 {
8984  assert(tree != NULL);
8985 
8986  return tree->root;
8987 }
8988 
8989 /** sets root node
8990  *
8991  * @note The old root including the rooted subtree is not delete.
8992  */
8994  SCIP_BT* tree, /**< tree to be evaluated */
8995  SCIP_BTNODE* root /**< new root, or NULL */
8996  )
8997 {
8998  assert(tree != NULL);
8999 
9000  tree->root = root;
9001 }
9002 
9003 
9004 /*
9005  * Numerical methods
9006  */
9007 
9008 /** returns the machine epsilon: the smallest number eps > 0, for which 1.0 + eps > 1.0 */
9010  void
9011  )
9012 {
9013  SCIP_Real eps;
9014  SCIP_Real lasteps;
9015  SCIP_Real one;
9016  SCIP_Real onepluseps;
9017 
9018  one = 1.0;
9019  eps = 1.0;
9020  do
9021  {
9022  lasteps = eps;
9023  eps /= 2.0;
9024  onepluseps = one + eps;
9025  }
9026  while( onepluseps > one );
9027 
9028  return lasteps;
9029 }
9030 
9031 /** calculates the greatest common divisor of the two given values */
9033  SCIP_Longint val1, /**< first value of greatest common devisor calculation */
9034  SCIP_Longint val2 /**< second value of greatest common devisor calculation */
9035  )
9036 {
9037  int t;
9038 
9039  assert(val1 > 0);
9040  assert(val2 > 0);
9041 
9042  t = 0;
9043  /* if val1 is even, divide it by 2 */
9044  while( !(val1 & 1) )
9045  {
9046  val1 >>= 1; /*lint !e704*/
9047 
9048  /* if val2 is even too, divide it by 2 and increase t(=number of e) */
9049  if( !(val2 & 1) )
9050  {
9051  val2 >>= 1; /*lint !e704*/
9052  ++t;
9053  }
9054  /* only val1 can be odd */
9055  else
9056  {
9057  /* while val1 is even, divide it by 2 */
9058  while( !(val1 & 1) )
9059  val1 >>= 1; /*lint !e704*/
9060 
9061  break;
9062  }
9063  }
9064 
9065  /* while val2 is even, divide it by 2 */
9066  while( !(val2 & 1) )
9067  val2 >>= 1; /*lint !e704*/
9068 
9069  /* the following if/else condition is only to make sure that we do not overflow when adding up both values before
9070  * dividing them by 4 in the following while loop
9071  */
9072  if( t == 0 )
9073  {
9074  if( val1 > val2 )
9075  {
9076  val1 -= val2;
9077 
9078  /* divide val1 by 2 as long as possible */
9079  while( !(val1 & 1) )
9080  val1 >>= 1; /*lint !e704*/
9081  }
9082  else if( val1 < val2 )
9083  {
9084  val2 -= val1;
9085 
9086  /* divide val2 by 2 as long as possible */
9087  while( !(val2 & 1) )
9088  val2 >>= 1; /*lint !e704*/
9089  }
9090  }
9091 
9092  /* val1 and val2 are odd */
9093  while( val1 != val2 )
9094  {
9095  if( val1 > val2 )
9096  {
9097  /* we can stop if one value reached one */
9098  if( val2 == 1 )
9099  return (val2 << t); /*lint !e647 !e703*/
9100 
9101  /* if ((val1 xor val2) and 2) = 2, then gcd(val1, val2) = gcd((val1 + val2)/4, val2),
9102  * and otherwise gcd(val1, val2) = gcd((val1 − val2)/4, val2)
9103  */
9104  if( ((val1 ^ val2) & 2) == 2 )
9105  val1 += val2;
9106  else
9107  val1 -= val2;
9108 
9109  assert((val1 & 3) == 0);
9110  val1 >>= 2; /*lint !e704*/
9111 
9112  /* if val1 is still even, divide it by 2 */
9113  while( !(val1 & 1) )
9114  val1 >>= 1; /*lint !e704*/
9115  }
9116  else
9117  {
9118  /* we can stop if one value reached one */
9119  if( val1 == 1 )
9120  return (val1 << t); /*lint !e647 !e703*/
9121 
9122  /* if ((val2 xor val1) and 2) = 2, then gcd(val2, val1) = gcd((val2 + val1)/4, val1),
9123  * and otherwise gcd(val2, val1) = gcd((val2 − val1)/4, val1)
9124  */
9125  if( ((val2 ^ val1) & 2) == 2 )
9126  val2 += val1;
9127  else
9128  val2 -= val1;
9129 
9130  assert((val2 & 3) == 0);
9131  val2 >>= 2; /*lint !e704*/
9132 
9133  /* if val2 is still even, divide it by 2 */
9134  while( !(val2 & 1) )
9135  val2 >>= 1; /*lint !e704*/
9136  }
9137  }
9138 
9139  return (val1 << t); /*lint !e703*/
9140 }
9141 
9142 
9143 /* for the MS compiler, the function nextafter is named _nextafter */
9144 #if defined(_MSC_VER) && !defined(NO_NEXTAFTER)
9145 #define nextafter(x,y) _nextafter(x,y)
9146 #endif
9147 
9148 /* on systems where the function nextafter is not defined, we provide an implementation from Sun */
9149 #ifdef NO_NEXTAFTER
9150 /* The following implementation of the routine nextafter() comes with the following license:
9151  *
9152  * ====================================================
9153  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9154  *
9155  * Developed at SunSoft, a Sun Microsystems, Inc. business.
9156  * Permission to use, copy, modify, and distribute this
9157  * software is freely granted, provided that this notice
9158  * is preserved.
9159  * ====================================================
9160  */
9161 
9162 #define __HI(x) *(1+(int*)&x)
9163 #define __LO(x) *(int*)&x
9164 #define __HIp(x) *(1+(int*)x)
9165 #define __LOp(x) *(int*)x
9166 
9167 static
9168 double nextafter(double x, double y)
9169 {
9170  int hx;
9171  int hy;
9172  int ix;
9173  int iy;
9174  unsigned lx;
9175  unsigned ly;
9176 
9177  /* cppcheck-suppress invalidPointerCast */
9178  hx = __HI(x); /* high word of x */
9179  /* cppcheck-suppress invalidPointerCast */
9180  lx = __LO(x); /* low word of x */
9181  /* cppcheck-suppress invalidPointerCast */
9182  hy = __HI(y); /* high word of y */
9183  /* cppcheck-suppress invalidPointerCast */
9184  ly = __LO(y); /* low word of y */
9185  ix = hx&0x7fffffff; /* |x| */
9186  iy = hy&0x7fffffff; /* |y| */
9187 
9188  if( ((ix>=0x7ff00000) && ((ix-0x7ff00000)|lx) != 0 ) || /* x is nan */
9189  ( (iy>=0x7ff00000) && ((iy-0x7ff00000)|ly) != 0 )) /* y is nan */
9190  return x + y;
9191 
9192  /* x == y, return x */
9193  if( x == y )
9194  return x;
9195 
9196  /* x == 0 */
9197  if( (ix|lx) == 0 )
9198  {
9199  /* return +-minsubnormal */
9200  /* cppcheck-suppress invalidPointerCast */
9201  __HI(x) = hy&0x80000000;
9202  /* cppcheck-suppress invalidPointerCast */
9203  __LO(x) = 1;
9204  y = x * x;
9205  if ( y == x )
9206  return y;
9207  else
9208  return x; /* raise underflow flag */
9209  }
9210  /* x > 0 */
9211  if( hx >= 0 )
9212  {
9213  /* x > y, x -= ulp */
9214  if( hx > hy || ((hx == hy) && (lx > ly)) )
9215  {
9216  if ( lx == 0 )
9217  hx -= 1;
9218  lx -= 1;
9219  }
9220  else
9221  {
9222  /* x < y, x += ulp */
9223  lx += 1;
9224  if ( lx == 0 )
9225  hx += 1;
9226  }
9227  }
9228  else
9229  {
9230  /* x < 0 */
9231  if( hy >= 0 || hx > hy || ((hx == hy) && (lx > ly)) )
9232  {
9233  /* x < y, x -= ulp */
9234  if ( lx == 0 )
9235  hx -= 1;
9236  lx -= 1;
9237  }
9238  else
9239  {
9240  /* x > y, x += ulp */
9241  lx += 1;
9242  if( lx == 0 )
9243  hx += 1;
9244  }
9245  }
9246  hy = hx&0x7ff00000;
9247  /* overflow */
9248  if( hy >= 0x7ff00000 )
9249  return x + x;
9250  if( hy < 0x00100000 )
9251  {
9252  /* underflow */
9253  y = x*x;
9254  if( y != x )
9255  {
9256  /* raise underflow flag */
9257  /* cppcheck-suppress invalidPointerCast */
9258  __HI(y) = hx;
9259  /* cppcheck-suppress invalidPointerCast */
9260  __LO(y) = lx;
9261  return y;
9262  }
9263  }
9264 
9265  /* cppcheck-suppress invalidPointerCast */
9266  __HI(x) = hx;
9267  /* cppcheck-suppress invalidPointerCast */
9268  __LO(x) = lx;
9269  return x;
9270 }
9271 #endif
9272 
9273 
9274 /** returns the next representable value of from in the direction of to */
9276  SCIP_Real from, /**< value from which the next representable value should be returned */
9277  SCIP_Real to /**< direction in which the next representable value should be returned */
9278  )
9279 {
9280  return nextafter(from, to);
9281 }
9282 
9283 /** calculates the smallest common multiple of the two given values */
9285  SCIP_Longint val1, /**< first value of smallest common multiple calculation */
9286  SCIP_Longint val2 /**< second value of smallest common multiple calculation */
9287  )
9288 {
9289  SCIP_Longint gcd;
9290 
9291  assert(val1 > 0);
9292  assert(val2 > 0);
9293 
9294  gcd = SCIPcalcGreComDiv(val1, val2);
9295 
9296  return val1/gcd * val2;
9297 }
9298 
9299 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,
9300  17.0, 18.0, 19.0, 25.0, -1.0};
9301 
9302 /** converts a real number into a (approximate) rational representation, and returns TRUE iff the conversion was
9303  * successful
9304  */
9306  SCIP_Real val, /**< real value r to convert into rational number */
9307  SCIP_Real mindelta, /**< minimal allowed difference r - q of real r and rational q = n/d */
9308  SCIP_Real maxdelta, /**< maximal allowed difference r - q of real r and rational q = n/d */
9309  SCIP_Longint maxdnom, /**< maximal denominator allowed */
9310  SCIP_Longint* nominator, /**< pointer to store the nominator n of the rational number */
9311  SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9312  )
9313 {
9314  SCIP_Real a;
9315  SCIP_Real b;
9316  SCIP_Real g0;
9317  SCIP_Real g1;
9318  SCIP_Real gx;
9319  SCIP_Real h0;
9320  SCIP_Real h1;
9321  SCIP_Real hx;
9322  SCIP_Real delta0;
9323  SCIP_Real delta1;
9324  SCIP_Real epsilon;
9325  int i;
9326 
9327  assert(mindelta < 0.0);
9328  assert(maxdelta > 0.0);
9329  assert(nominator != NULL);
9330  assert(denominator != NULL);
9331 
9332  if( REALABS(val) >= ((SCIP_Real)SCIP_LONGINT_MAX) / maxdnom )
9333  return FALSE;
9334 
9335  /* try the simple denominators first: each value of the simpledenoms table multiplied by powers of 10
9336  * is tried as denominator
9337  */
9338  for( i = 0; simplednoms[i] > 0.0; ++i )
9339  {
9340  SCIP_Real nom;
9341  SCIP_Real dnom;
9342  SCIP_Real ratval0;
9343  SCIP_Real ratval1;
9344 
9345  /* try powers of 10 (including 10^0) */
9346  dnom = simplednoms[i];
9347  while( dnom <= maxdnom )
9348  {
9349  nom = floor(val * dnom);
9350  ratval0 = nom/dnom;
9351  ratval1 = (nom+1.0)/dnom;
9352  if( mindelta <= val - ratval0 && val - ratval1 <= maxdelta )
9353  {
9354  if( val - ratval0 <= maxdelta )
9355  {
9356  *nominator = (SCIP_Longint)nom;
9357  *denominator = (SCIP_Longint)dnom;
9358  return TRUE;
9359  }
9360  if( mindelta <= val - ratval1 )
9361  {
9362  *nominator = (SCIP_Longint)(nom+1.0);
9363  *denominator = (SCIP_Longint)dnom;
9364  return TRUE;
9365  }
9366  }
9367  dnom *= 10.0;
9368  }
9369  }
9370 
9371  /* the simple denominators didn't work: calculate rational representation with arbitrary denominator */
9372  epsilon = MIN(-mindelta, maxdelta)/2.0;
9373 
9374  b = val;
9375  a = EPSFLOOR(b, epsilon);
9376  g0 = a;
9377  h0 = 1.0;
9378  g1 = 1.0;
9379  h1 = 0.0;
9380  delta0 = val - g0/h0;
9381  delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9382 
9383  while( (delta0 < mindelta || delta0 > maxdelta) && (delta1 < mindelta || delta1 > maxdelta) )
9384  {
9385  assert(EPSGT(b, a, epsilon));
9386  assert(h0 >= 0.0);
9387  assert(h1 >= 0.0);
9388 
9389  b = 1.0 / (b - a);
9390  a = EPSFLOOR(b, epsilon);
9391 
9392  assert(a >= 0.0);
9393  gx = g0;
9394  hx = h0;
9395 
9396  g0 = a * g0 + g1;
9397  h0 = a * h0 + h1;
9398 
9399  g1 = gx;
9400  h1 = hx;
9401 
9402  if( h0 > maxdnom )
9403  return FALSE;
9404 
9405  delta0 = val - g0/h0;
9406  delta1 = (delta0 < 0.0 ? val - (g0-1.0)/h0 : val - (g0+1.0)/h0);
9407  }
9408 
9409  if( REALABS(g0) > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) || h0 > (SCIP_Real)(SCIP_LONGINT_MAX >> 4) )
9410  return FALSE;
9411 
9412  assert(h0 > 0.5);
9413 
9414  if( delta0 < mindelta )
9415  {
9416  assert(mindelta <= delta1 && delta1 <= maxdelta);
9417  *nominator = (SCIP_Longint)(g0 - 1.0);
9418  *denominator = (SCIP_Longint)h0;
9419  }
9420  else if( delta0 > maxdelta )
9421  {
9422  assert(mindelta <= delta1 && delta1 <= maxdelta);
9423  *nominator = (SCIP_Longint)(g0 + 1.0);
9424  *denominator = (SCIP_Longint)h0;
9425  }
9426  else
9427  {
9428  *nominator = (SCIP_Longint)g0;
9429  *denominator = (SCIP_Longint)h0;
9430  }
9431  assert(*denominator >= 1);
9432  assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) >= mindelta);
9433  assert(val - (SCIP_Real)(*nominator)/(SCIP_Real)(*denominator) <= maxdelta);
9434 
9435  return TRUE;
9436 }
9437 
9438 /** checks, whether the given scalar scales the given value to an integral number with error in the given bounds */
9439 static
9441  SCIP_Real val, /**< value that should be scaled to an integral value */
9442  SCIP_Real scalar, /**< scalar that should be tried */
9443  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9444  SCIP_Real maxdelta /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9445  )
9446 {
9447  SCIP_Real sval;
9448  SCIP_Real downval;
9449  SCIP_Real upval;
9450 
9451  assert(mindelta <= 0.0);
9452  assert(maxdelta >= 0.0);
9453 
9454  sval = val * scalar;
9455  downval = floor(sval);
9456  upval = ceil(sval);
9457 
9458  return (SCIPrelDiff(sval, downval) <= maxdelta || SCIPrelDiff(sval, upval) >= mindelta);
9459 }
9460 
9461 /** additional scalars that are tried in integrality scaling */
9462 static const SCIP_Real scalars[] = {3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0};
9463 static const int nscalars = 9;
9464 
9465 /** tries to find a value, such that all given values, if scaled with this value become integral in relative allowed
9466  * difference in between mindelta and maxdelta
9467  */
9469  SCIP_Real* vals, /**< values to scale */
9470  int nvals, /**< number of values to scale */
9471  SCIP_Real mindelta, /**< minimal relative allowed difference of scaled coefficient s*c and integral i */
9472  SCIP_Real maxdelta, /**< maximal relative allowed difference of scaled coefficient s*c and integral i */
9473  SCIP_Longint maxdnom, /**< maximal denominator allowed in rational numbers */
9474  SCIP_Real maxscale, /**< maximal allowed scalar */
9475  SCIP_Real* intscalar, /**< pointer to store scalar that would make the coefficients integral, or NULL */
9476  SCIP_Bool* success /**< stores whether returned value is valid */
9477  )
9478 {
9479  SCIP_Real bestscalar;
9480  SCIP_Longint gcd;
9481  SCIP_Longint scm;
9482  SCIP_Longint nominator;
9483  SCIP_Longint denominator;
9484  SCIP_Real val;
9485  SCIP_Real minval;
9486  SCIP_Real absval;
9487  SCIP_Real scaleval;
9488  SCIP_Bool scalable;
9489  SCIP_Bool rational;
9490  int c;
9491  int s;
9492  int i;
9493 
9494  assert(vals != NULL);
9495  assert(nvals >= 0);
9496  assert(maxdnom >= 1);
9497  assert(mindelta < 0.0);
9498  assert(maxdelta > 0.0);
9499  assert(success != NULL);
9500 
9501  SCIPdebugMessage("trying to find rational representation for given values\n");
9502 
9503  if( intscalar != NULL )
9504  *intscalar = SCIP_INVALID;
9505  *success = FALSE;
9506 
9507  /* get minimal absolute non-zero value */
9508  minval = SCIP_REAL_MAX;
9509  for( c = 0; c < nvals; ++c )
9510  {
9511  val = vals[c];
9512  if( val < mindelta || val > maxdelta )
9513  {
9514  absval = REALABS(val);
9515  minval = MIN(minval, absval);
9516  }
9517  }
9518 
9519  if( minval == SCIP_REAL_MAX ) /*lint !e777*/
9520  {
9521  /* all coefficients are zero (inside tolerances) */
9522  if( intscalar != NULL )
9523  *intscalar = 1.0;
9524  *success = TRUE;
9525  SCIPdebugMessage(" -> all values are zero (inside tolerances)\n");
9526 
9527  return SCIP_OKAY;
9528  }
9529  assert(minval > MIN(-mindelta, maxdelta));
9530 
9531  bestscalar = SCIP_INVALID;
9532 
9533  for( i = 0; i < 2; ++i )
9534  {
9535  scalable = TRUE;
9536 
9537  /* try, if values can be made integral multiplying them with the reciprocal of the smallest value and a power of 2 */
9538  if( i == 0 )
9539  scaleval = 1.0/minval;
9540  /* try, if values can be made integral by multiplying them by a power of 2 */
9541  else
9542  scaleval = 1.0;
9543 
9544  for( c = 0; c < nvals && scalable; ++c )
9545  {
9546  /* check, if the value can be scaled with a simple scalar */
9547  val = vals[c];
9548  if( val == 0.0 ) /* zeros are allowed in the vals array */
9549  continue;
9550 
9551  absval = REALABS(val);
9552  while( scaleval <= maxscale
9553  && (absval * scaleval < 0.5 || !isIntegralScalar(val, scaleval, mindelta, maxdelta)) )
9554  {
9555  for( s = 0; s < nscalars; ++s )
9556  {
9557  if( isIntegralScalar(val, scaleval * scalars[s], mindelta, maxdelta) )
9558  {
9559  scaleval *= scalars[s];
9560  break;
9561  }
9562  }
9563  if( s >= nscalars )
9564  scaleval *= 2.0;
9565  }
9566  scalable = (scaleval <= maxscale);
9567  SCIPdebugMessage(" -> val=%g, scaleval=%g, val*scaleval=%g, scalable=%u\n",
9568  val, scaleval, val*scaleval, scalable);
9569  }
9570  if( scalable )
9571  {
9572  /* make values integral by dividing them by the smallest value (and multiplying them with a power of 2) */
9573  assert(scaleval <= maxscale);
9574 
9575  /* check if we found a better scaling value */
9576  if( scaleval < bestscalar )
9577  bestscalar = scaleval;
9578 
9579  SCIPdebugMessage(" -> integrality could be achieved by scaling with %g\n", scaleval);
9580 
9581  /* if the scalar is still the reciprocal of the minimal value, all coeffcients are the same and we do not get a better scalar */
9582  if( i == 0 && EPSEQ(scaleval, 1.0/minval, SCIP_DEFAULT_EPSILON) )
9583  {
9584  if( intscalar != NULL )
9585  *intscalar = bestscalar;
9586  *success = TRUE;
9587 
9588  return SCIP_OKAY;
9589  }
9590  }
9591  }
9592 
9593  /* convert each value into a rational number, calculate the greatest common divisor of the nominators
9594  * and the smallest common multiple of the denominators
9595  */
9596  gcd = 1;
9597  scm = 1;
9598  rational = TRUE;
9599 
9600  /* first value (to initialize gcd) */
9601  for( c = 0; c < nvals && rational; ++c )
9602  {
9603  val = vals[c];
9604  if( val == 0.0 ) /* zeros are allowed in the vals array */
9605  continue;
9606 
9607  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9608  if( rational && nominator != 0 )
9609  {
9610  assert(denominator > 0);
9611  gcd = ABS(nominator);
9612  scm = denominator;
9613  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9614  SCIPdebugMessage(" -> c=%d first rational: val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9615  c, val, nominator, denominator, gcd, scm, rational);
9616  break;
9617  }
9618  }
9619 
9620  /* remaining values */
9621  for( ++c; c < nvals && rational; ++c )
9622  {
9623  val = vals[c];
9624  if( val == 0.0 ) /* zeros are allowed in the vals array */
9625  continue;
9626 
9627  rational = SCIPrealToRational(val, mindelta, maxdelta, maxdnom, &nominator, &denominator);
9628  if( rational && nominator != 0 )
9629  {
9630  assert(denominator > 0);
9631  gcd = SCIPcalcGreComDiv(gcd, ABS(nominator));
9632  scm *= denominator / SCIPcalcGreComDiv(scm, denominator);
9633  rational = ((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9634  SCIPdebugMessage(" -> c=%d next rational : val: %g == %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ", gcd=%" SCIP_LONGINT_FORMAT ", scm=%" SCIP_LONGINT_FORMAT ", rational=%u\n",
9635  c, val, nominator, denominator, gcd, scm, rational);
9636  }
9637  else
9638  {
9639  SCIPdebugMessage(" -> failed to convert %g into a rational representation\n", val);
9640  }
9641  }
9642 
9643  if( rational )
9644  {
9645  /* make values integral by multiplying them with the smallest common multiple of the denominators */
9646  assert((SCIP_Real)scm/(SCIP_Real)gcd <= maxscale);
9647 
9648  /* check if we found a better scaling value */
9649  if( (SCIP_Real)scm/(SCIP_Real)gcd < bestscalar )
9650  bestscalar = (SCIP_Real)scm/(SCIP_Real)gcd;
9651 
9652  SCIPdebugMessage(" -> integrality could be achieved by scaling with %g (rational:%" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ")\n",
9653  (SCIP_Real)scm/(SCIP_Real)gcd, scm, gcd);
9654  }
9655 
9656  if( bestscalar < SCIP_INVALID )
9657  {
9658  if( intscalar != NULL )
9659  *intscalar = bestscalar;
9660  *success = TRUE;
9661 
9662  SCIPdebugMessage(" -> smallest value to achieve integrality is %g \n", bestscalar);
9663  }
9664 
9665  return SCIP_OKAY;
9666 }
9667 
9668 /* Inform compiler that this code accesses the floating-point environment, so that
9669  * certain optimizations should be omitted (http://www.cplusplus.com/reference/cfenv/FENV_ACCESS/).
9670  * Not supported by Clang (gives warning) and GCC (silently), at the moment.
9671  */
9672 #if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9673 #pragma fenv_access (on)
9674 #elif defined(__GNUC__) && !defined(__clang__)
9675 #pragma STDC FENV_ACCESS ON
9676 #endif
9677 #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
9678 #if defined(__clang__)
9679 __attribute__((optnone))
9680 #else
9681 __attribute__((optimize(0)))
9682 #endif
9683 #endif
9684 /** given a (usually very small) interval, tries to find a rational number with simple denominator (i.e. a small
9685  * number, probably multiplied with powers of 10) out of this interval; returns TRUE iff a valid rational
9686  * number inside the interval was found
9687  */
9689  SCIP_Real lb, /**< lower bound of the interval */
9690  SCIP_Real ub, /**< upper bound of the interval */
9691  SCIP_Longint maxdnom, /**< maximal denominator allowed for resulting rational number */
9692  SCIP_Longint* nominator, /**< pointer to store the nominator n of the rational number */
9693  SCIP_Longint* denominator /**< pointer to store the denominator d of the rational number */
9694  )
9695 {
9696  SCIP_Real center;
9697  SCIP_Real delta;
9698 
9699  assert(lb <= ub);
9700 
9701  center = 0.5*(lb+ub);
9702 
9703  /* in order to compute a rational number that is exactly within the bounds (as the user expects),
9704  * we computed the allowed delta with downward rounding, if available
9705  */
9707  {
9708  SCIP_ROUNDMODE roundmode;
9709 
9710  roundmode = SCIPintervalGetRoundingMode();
9712 
9713  delta = 0.5*(ub-lb);
9714 
9715  SCIPintervalSetRoundingMode(roundmode);
9716  }
9717  else
9718  {
9719  delta = 0.5*(ub-lb);
9720  }
9721 
9722  return SCIPrealToRational(center, -delta, +delta, maxdnom, nominator, denominator);
9723 }
9724 
9725 #if defined(__INTEL_COMPILER) || defined(_MSC_VER)
9726 #pragma fenv_access (off)
9727 #elif defined(__GNUC__) && !defined(__clang__)
9728 #pragma STDC FENV_ACCESS OFF
9729 #endif
9730 
9731 /** given a (usually very small) interval, selects a value inside this interval; it is tried to select a rational number
9732  * with simple denominator (i.e. a small number, probably multiplied with powers of 10);
9733  * if no valid rational number inside the interval was found, selects the central value of the interval
9734  */
9736  SCIP_Real lb, /**< lower bound of the interval */
9737  SCIP_Real ub, /**< upper bound of the interval */
9738  SCIP_Longint maxdnom /**< maximal denominator allowed for resulting rational number */
9739  )
9740 {
9741  SCIP_Real val;
9742 
9743  val = 0.5*(lb+ub);
9744  if( lb < ub )
9745  {
9746  SCIP_Longint nominator;
9747  SCIP_Longint denominator;
9748  SCIP_Bool success;
9749 
9750  /* try to find a "simple" rational number inside the interval */
9751  SCIPdebugMessage("simple rational in [%.9f,%.9f]:", lb, ub);
9752  success = SCIPfindSimpleRational(lb, ub, maxdnom, &nominator, &denominator);
9753  if( success )
9754  {
9755  val = (SCIP_Real)nominator/(SCIP_Real)denominator;
9756  SCIPdebugPrintf(" %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT " == %.9f\n", nominator, denominator, val);
9757 
9758  if( val - lb < 0.0 || val - ub > 0.0 )
9759  {
9760  SCIPdebugPrintf(" value is out of interval bounds by %g -> failed\n", MAX(lb-val, val-ub));
9761  val = 0.5*(lb+ub);
9762  }
9763  }
9764  else
9765  {
9766  SCIPdebugPrintf(" failed\n");
9767  }
9768  }
9769 
9770  return val;
9771 }
9772 
9773 /** Performs the Newton Procedure from a given starting point to compute a root of the given function with
9774  * specified precision and maximum number of iterations. If the procedure fails, SCIP_INVALID is returned.
9775  */
9777  SCIP_DECL_NEWTONEVAL((*function)), /**< pointer to function for which roots are computed */
9778  SCIP_DECL_NEWTONEVAL((*derivative)), /**< pointer to derivative of above function */
9779  SCIP_Real* params, /**< parameters needed for function (can be NULL) */
9780  int nparams, /**< number of parameters (can be 0) */
9781  SCIP_Real x, /**< starting point */
9782  SCIP_Real eps, /**< tolerance */
9783  int k /**< iteration limit */
9784  )
9785 {
9786  SCIP_Real result = x;
9787  int iteration = 0;
9788 
9789  assert(function != NULL);
9790  assert(derivative != NULL);
9791  assert(params != NULL || nparams == 0);
9792  assert(eps > 0.0);
9793  assert(k >= 0);
9794  assert(x != SCIP_INVALID); /*lint !e777*/
9795 
9796  while( iteration < k )
9797  {
9798  SCIP_Real deriv = derivative(result, params, nparams);
9799 
9800  /* if we arrive at a stationary point, the procedure is aborted */
9801  if( REALABS(deriv) <= eps || deriv == SCIP_INVALID ) /*lint !e777*/
9802  return SCIP_INVALID;
9803 
9804  result = result - function(result, params, nparams) / deriv;
9805 
9806  /* if new point is within eps-range of 0, we are done */
9807  if( REALABS(function(result, params, nparams)) <= eps )
9808  break;
9809 
9810  ++iteration;
9811  }
9812 
9813  if( k == iteration )
9814  return SCIP_INVALID;
9815  else
9816  return result;
9817 }
9818 
9819 
9820 /*
9821  * Random Numbers
9822  */
9823 
9824 #if defined(NO_RAND_R) || defined(_WIN32) || defined(_WIN64)
9825 
9826 #define SCIP_RAND_MAX 32767
9827 /** returns a random number between 0 and SCIP_RAND_MAX */
9828 static
9829 int getRand(
9830  unsigned int* seedp /**< pointer to seed value */
9831  )
9832 {
9833  SCIP_Longint nextseed;
9834 
9835  assert(seedp != NULL);
9836 
9837  nextseed = (*seedp) * (SCIP_Longint)1103515245 + 12345;
9838  *seedp = (unsigned int)nextseed;
9839 
9840  return (int)((unsigned int)(nextseed/(2*(SCIP_RAND_MAX+1))) % (SCIP_RAND_MAX+1));
9841 }
9842 
9843 #else
9844 
9845 #define SCIP_RAND_MAX RAND_MAX
9846 
9847 /** returns a random number between 0 and SCIP_RAND_MAX */
9848 static
9850  unsigned int* seedp /**< pointer to seed value */
9851  )
9852 {
9853  return rand_r(seedp);
9854 }
9855 
9856 #endif
9857 
9858 /** returns a random integer between minrandval and maxrandval */
9859 static
9861  int minrandval, /**< minimal value to return */
9862  int maxrandval, /**< maximal value to return */
9863  unsigned int* seedp /**< pointer to seed value */
9864  )
9865 {
9866  SCIP_Real randnumber;
9867 
9868  randnumber = (SCIP_Real)getRand(seedp)/(SCIP_RAND_MAX+1.0);
9869  assert(randnumber >= 0.0);
9870  assert(randnumber < 1.0);
9871 
9872  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than INT_MAX
9873  * apart
9874  */
9875  return (int) (minrandval*(1.0 - randnumber) + maxrandval*randnumber + randnumber);
9876 }
9877 
9878 /** returns a random real between minrandval and maxrandval */
9879 static
9881  SCIP_Real minrandval, /**< minimal value to return */
9882  SCIP_Real maxrandval, /**< maximal value to return */
9883  unsigned int* seedp /**< pointer to seed value */
9884  )
9885 {
9886  SCIP_Real randnumber;
9887 
9888  randnumber = (SCIP_Real)getRand(seedp)/(SCIP_Real)SCIP_RAND_MAX;
9889  assert(randnumber >= 0.0);
9890  assert(randnumber <= 1.0);
9891 
9892  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
9893  * SCIP_REAL_MAX apart
9894  */
9895  return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
9896 }
9897 
9898 /** returns a random integer between minrandval and maxrandval
9899  *
9900  * @deprecated Please use SCIPrandomGetInt() to request a random integer.
9901  */
9903  int minrandval, /**< minimal value to return */
9904  int maxrandval, /**< maximal value to return */
9905  unsigned int* seedp /**< pointer to seed value */
9906  )
9907 {
9908  return getRandomInt(minrandval, maxrandval, seedp);
9909 }
9910 
9911 /** returns a random real between minrandval and maxrandval
9912  *
9913  * @deprecated Please use SCIPrandomGetReal() to request a random real.
9914  */
9916  SCIP_Real minrandval, /**< minimal value to return */
9917  SCIP_Real maxrandval, /**< maximal value to return */
9918  unsigned int* seedp /**< pointer to seed value */
9919  )
9920 {
9921  return getRandomReal(minrandval, maxrandval, seedp);
9922 }
9923 
9924 
9925 /* initial seeds for KISS random number generator */
9926 #define DEFAULT_SEED UINT32_C(123456789)
9927 #define DEFAULT_XOR UINT32_C(362436000)
9928 #define DEFAULT_MWC UINT32_C(521288629)
9929 #define DEFAULT_CST UINT32_C(7654321)
9930 
9931 
9932 /** initializes a random number generator with a given start seed */
9934  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
9935  unsigned int initseed /**< initial random seed */
9936  )
9937 {
9938  assert(randnumgen != NULL);
9939 
9940  /* use MAX() to avoid zero after over flowing */
9941  randnumgen->seed = MAX(SCIPhashTwo(DEFAULT_SEED, initseed), 1u);
9942  randnumgen->xor_seed = MAX(SCIPhashTwo(DEFAULT_XOR, initseed), 1u);
9943  randnumgen->mwc_seed = MAX(SCIPhashTwo(DEFAULT_MWC, initseed), 1u);
9944  randnumgen->cst_seed = SCIPhashTwo(DEFAULT_CST, initseed);
9945 
9946  assert(randnumgen->seed > 0);
9947  assert(randnumgen->xor_seed > 0);
9948  assert(randnumgen->mwc_seed > 0);
9949 }
9950 
9951 /** returns a random number between 0 and UINT32_MAX
9952  *
9953  * implementation of KISS random number generator developed by George Marsaglia.
9954  * KISS is combination of three different random number generators:
9955  * - Linear congruential generator
9956  * - Xorshift
9957  * - Lag-1 Multiply-with-carry
9958  *
9959  * KISS has a period of 2^123 and passes all statistical test part of BigCrush-Test of TestU01 [1].
9960  *
9961  * [1] http://dl.acm.org/citation.cfm?doid=1268776.1268777
9962  */
9963 static
9964 uint32_t randomGetRand(
9965  SCIP_RANDNUMGEN* randnumgen /**< random number generator */
9966  )
9967 {
9968  uint64_t t;
9969 
9970  /* linear congruential */
9971  randnumgen->seed = (uint32_t) (randnumgen->seed * UINT64_C(1103515245) + UINT64_C(12345));
9972 
9973  /* Xorshift */
9974  randnumgen->xor_seed ^= (randnumgen->xor_seed << 13);
9975  randnumgen->xor_seed ^= (randnumgen->xor_seed >> 17);
9976  randnumgen->xor_seed ^= (randnumgen->xor_seed << 5);
9977 
9978  /* Multiply-with-carry */
9979  t = UINT64_C(698769069) * randnumgen->mwc_seed + randnumgen->cst_seed;
9980  randnumgen->cst_seed = (uint32_t) (t >> 32);
9981  randnumgen->mwc_seed = (uint32_t) t;
9982 
9983  return randnumgen->seed + randnumgen->xor_seed + randnumgen->mwc_seed;
9984 }
9985 
9986 /** creates and initializes a random number generator */
9988  SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
9989  BMS_BLKMEM* blkmem, /**< block memory */
9990  unsigned int initialseed /**< initial random seed */
9991  )
9992 {
9993  assert(randnumgen != NULL);
9994 
9995  SCIP_ALLOC( BMSallocBlockMemory(blkmem, randnumgen) );
9996 
9997  SCIPrandomSetSeed((*randnumgen), initialseed);
9998 
9999  return SCIP_OKAY;
10000 }
10001 
10002 /** frees a random number generator */
10004  SCIP_RANDNUMGEN** randnumgen, /**< random number generator */
10005  BMS_BLKMEM* blkmem /**< block memory */
10006  )
10007 {
10008  assert(randnumgen != NULL);
10009  assert((*randnumgen) != NULL);
10010 
10011  BMSfreeBlockMemory(blkmem, randnumgen);
10012 
10013  return;
10014 }
10015 
10016 
10017 
10018 /** returns a random integer between minrandval and maxrandval */
10020  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10021  int minrandval, /**< minimal value to return */
10022  int maxrandval /**< maximal value to return */
10023  )
10024 {
10025  SCIP_Real randnumber;
10026  SCIP_Longint zeromax;
10027 
10028  randnumber = (SCIP_Real)randomGetRand(randnumgen)/(UINT32_MAX+1.0);
10029  assert(randnumber >= 0.0);
10030  assert(randnumber < 1.0);
10031 
10032  /* we need to shift the range to the non-negative integers to handle negative integer values correctly.
10033  * we use a long integer to avoid overflows.
10034  */
10035  zeromax = (SCIP_Longint)maxrandval - (SCIP_Longint)minrandval + 1;
10036 
10037  return (int) ((SCIP_Longint)(zeromax * randnumber) + (SCIP_Longint)minrandval);
10038 }
10039 
10040 /** returns a random real between minrandval and maxrandval */
10042  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10043  SCIP_Real minrandval, /**< minimal value to return */
10044  SCIP_Real maxrandval /**< maximal value to return */
10045  )
10046 {
10047  SCIP_Real randnumber;
10048 
10049  randnumber = (SCIP_Real)randomGetRand(randnumgen)/(SCIP_Real)UINT32_MAX;
10050  assert(randnumber >= 0.0);
10051  assert(randnumber <= 1.0);
10052 
10053  /* we multiply minrandval and maxrandval separately by randnumber in order to avoid overflow if they are more than
10054  * SCIP_REAL_MAX apart
10055  */
10056  return minrandval*(1.0 - randnumber) + maxrandval*randnumber;
10057 }
10058 
10059 /** randomly shuffles parts of an integer array using the Fisher-Yates algorithm */
10061  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10062  int* array, /**< array to be shuffled */
10063  int begin, /**< first included index that should be subject to shuffling
10064  * (0 for first array entry)
10065  */
10066  int end /**< first excluded index that should not be subject to shuffling
10067  * (array size for last array entry)
10068  */
10069  )
10070 {
10071  int tmp;
10072  int i;
10073 
10074  /* loop backwards through all elements and always swap the current last element to a random position */
10075  while( end > begin+1 )
10076  {
10077  --end;
10078 
10079  /* get a random position into which the last entry should be shuffled */
10080  i = SCIPrandomGetInt(randnumgen, begin, end);
10081 
10082  /* swap the last element and the random element */
10083  tmp = array[i];
10084  array[i] = array[end];
10085  array[end] = tmp;
10086  }
10087 }
10088 
10089 /** randomly shuffles parts of an array using the Fisher-Yates algorithm */
10091  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10092  void** array, /**< array to be shuffled */
10093  int begin, /**< first included index that should be subject to shuffling
10094  * (0 for first array entry)
10095  */
10096  int end /**< first excluded index that should not be subject to shuffling
10097  * (array size for last array entry)
10098  */
10099  )
10100 {
10101  void* tmp;
10102  int i;
10103 
10104  /* loop backwards through all elements and always swap the current last element to a random position */
10105  while( end > begin+1 )
10106  {
10107  end--;
10108 
10109  /* get a random position into which the last entry should be shuffled */
10110  i = SCIPrandomGetInt(randnumgen, begin, end);
10111 
10112  /* swap the last element and the random element */
10113  tmp = array[i];
10114  array[i] = array[end];
10115  array[end] = tmp;
10116  }
10117 }
10118 
10119 /** draws a random subset of disjoint elements from a given set of disjoint elements;
10120  * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10121  */
10123  SCIP_RANDNUMGEN* randnumgen, /**< random number generator */
10124  void** set, /**< original set, from which elements should be drawn */
10125  int nelems, /**< number of elements in original set */
10126  void** subset, /**< subset in which drawn elements should be stored */
10127  int nsubelems /**< number of elements that should be drawn and stored */
10128  )
10129 {
10130  int i;
10131  int j;
10132 
10133  /* if both sets are of equal size, we just copy the array */
10134  if( nelems == nsubelems)
10135  {
10136  BMScopyMemoryArray(subset,set,nelems);
10137  return SCIP_OKAY;
10138  }
10139 
10140  /* abort, if size of subset is too big */
10141  if( nsubelems > nelems )
10142  {
10143  SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10144  return SCIP_INVALIDDATA;
10145  }
10146 #ifndef NDEBUG
10147  for( i = 0; i < nsubelems; i++ )
10148  for( j = 0; j < i; j++ )
10149  assert(set[i] != set[j]);
10150 #endif
10151 
10152  /* draw each element individually */
10153  i = 0;
10154  while( i < nsubelems )
10155  {
10156  int r;
10157 
10158  r = SCIPrandomGetInt(randnumgen, 0, nelems-1);
10159  subset[i] = set[r];
10160 
10161  /* if we get an element that we already had, we will draw again */
10162  for( j = 0; j < i; j++ )
10163  {
10164  if( subset[i] == subset[j] )
10165  {
10166  --i;
10167  break;
10168  }
10169  }
10170  ++i;
10171  }
10172  return SCIP_OKAY;
10173 }
10174 
10175 /*
10176  * Additional math functions
10177  */
10178 
10179 /** calculates a binomial coefficient n over m, choose m elements out of n, maximal value will be 33 over 16 (because
10180  * 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
10181  * big numbers or an negative value m (and m < n) and -1 will be returned
10182  */
10184  int n, /**< number of different elements */
10185  int m /**< number to choose out of the above */
10186  )
10187 {
10188  if( m == 0 || m >= n )
10189  return 1;
10190 
10191  if( m < 0 )
10192  return -1;
10193 
10194  /* symmetry of the binomial coefficient, choose smaller m */
10195  if( m > n/2 )
10196  m = n - m;
10197 
10198  /* trivial case m == 1 */
10199  if( m == 1 )
10200  return n;
10201 
10202  /* simple case m == 2 */
10203  if( m == 2 )
10204  {
10205  if( ((SCIP_Real)SCIP_LONGINT_MAX) / n >= (n-1) * 2 ) /*lint !e790*/
10206  return ((SCIP_Longint)n*(n-1)/2); /*lint !e647*/
10207  else
10208  return -1;
10209  }
10210 
10211  /* abort on to big numbers */
10212  if( m > 16 || n > 33 )
10213  return -1;
10214 
10215  /* simple case m == 3 */
10216  if( m == 3 )
10217  return (n*(n-1)*(n-2)/6); /*lint !e647*/
10218  else
10219  {
10220  /* first half of Pascal's triangle numbers(without the symmetric part) backwards from (33,16) over (32,16),
10221  * (33,15), (32,15),(31,15, (30,15), (33,14) to (8,4) (rest is calculated directly)
10222  *
10223  * due to this order we can extract the right binomial coefficient by (16-m)^2+(16-m)+(33-n)
10224  */
10225  static const SCIP_Longint binoms[182] = {
10226  1166803110, 601080390, 1037158320, 565722720, 300540195, 155117520, 818809200, 471435600, 265182525, 145422675,
10227  77558760, 40116600, 573166440, 347373600, 206253075, 119759850, 67863915, 37442160, 20058300, 10400600,
10228  354817320, 225792840, 141120525, 86493225, 51895935, 30421755, 17383860, 9657700, 5200300, 2704156, 193536720,
10229  129024480, 84672315, 54627300, 34597290, 21474180, 13037895, 7726160, 4457400, 2496144, 1352078, 705432,
10230  92561040, 64512240, 44352165, 30045015, 20030010, 13123110, 8436285, 5311735, 3268760, 1961256, 1144066,
10231  646646, 352716, 184756, 38567100, 28048800, 20160075, 14307150, 10015005, 6906900, 4686825, 3124550, 2042975,
10232  1307504, 817190, 497420, 293930, 167960, 92378, 48620, 13884156, 10518300, 7888725, 5852925, 4292145, 3108105,
10233  2220075, 1562275, 1081575, 735471, 490314, 319770, 203490, 125970, 75582, 43758, 24310, 12870, 4272048, 3365856,
10234  2629575, 2035800, 1560780, 1184040, 888030, 657800, 480700, 346104, 245157, 170544, 116280, 77520, 50388, 31824,
10235  19448, 11440, 6435, 3432, 1107568, 906192, 736281, 593775, 475020, 376740, 296010, 230230, 177100, 134596,
10236  100947, 74613, 54264, 38760, 27132, 18564, 12376, 8008, 5005, 3003, 1716, 924, 237336, 201376, 169911, 142506,
10237  118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, 11628, 8568, 6188, 4368, 3003, 2002,
10238  1287, 792, 462, 252, 40920, 35960, 31465, 27405, 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985,
10239  4845, 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, 126, 70};
10240 
10241  /* m can at most be 16 */
10242  const int t = 16-m;
10243  assert(t >= 0);
10244  assert(n <= 33);
10245 
10246  /* binoms array hast exactly 182 elements */
10247  assert(t*(t+1)+(33-n) < 182);
10248 
10249  return binoms[t*(t+1)+(33-n)]; /*lint !e662 !e661*/
10250  }
10251 }
10252 
10253 #ifndef NDEBUG
10254 /** calculates hash for floating-point number by using Fibonacci hashing */
10255 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ * 10 >= 490 && !defined(__INTEL_COMPILER)
10256 __attribute__((no_sanitize_undefined))
10257 #endif
10258 unsigned int SCIPcalcFibHash(
10259  SCIP_Real v /**< number to hash */
10260  )
10261 {
10262  if( v >= 0 )
10263  return ((unsigned long long)(v * 2654435769)) % UINT_MAX;
10264  return ((unsigned long long)(-v * 683565275)) % UINT_MAX;
10265 }
10266 #endif
10267 
10268 /** negates a number */
10270  SCIP_Real x /**< value to negate */
10271  )
10272 {
10273  return -x;
10274 }
10275 
10276 /*
10277  * Permutations / Shuffling
10278  */
10279 
10280 /** swaps two ints */
10282  int* value1, /**< pointer to first integer */
10283  int* value2 /**< pointer to second integer */
10284  )
10285 {
10286  int tmp;
10287 
10288  tmp = *value1;
10289  *value1 = *value2;
10290  *value2 = tmp;
10291 }
10292 
10293 /** swaps two real values */
10295  SCIP_Real* value1, /**< pointer to first real value */
10296  SCIP_Real* value2 /**< pointer to second real value */
10297  )
10298 {
10299  SCIP_Real tmp;
10300 
10301  tmp = *value1;
10302  *value1 = *value2;
10303  *value2 = tmp;
10304 }
10305 
10306 /** swaps the addresses of two pointers */
10308  void** pointer1, /**< first pointer */
10309  void** pointer2 /**< second pointer */
10310  )
10311 {
10312  void* tmp;
10313 
10314  tmp = *pointer1;
10315  *pointer1 = *pointer2;
10316  *pointer2 = tmp;
10317 }
10318 
10319 /** randomly shuffles parts of an integer array using the Fisher-Yates algorithm
10320  *
10321  * @deprecated Please use SCIPrandomPermuteIntArray()
10322  */
10324  int* array, /**< array to be shuffled */
10325  int begin, /**< first included index that should be subject to shuffling
10326  * (0 for first array entry)
10327  */
10328  int end, /**< first excluded index that should not be subject to shuffling
10329  * (array size for last array entry)
10330  */
10331  unsigned int* randseed /**< seed value for the random generator */
10332  )
10333 {
10334  int tmp;
10335  int i;
10336 
10337  /* loop backwards through all elements and always swap the current last element to a random position */
10338  while( end > begin+1 )
10339  {
10340  --end;
10341 
10342  /* get a random position into which the last entry should be shuffled */
10343  i = getRandomInt(begin, end, randseed);
10344 
10345  /* swap the last element and the random element */
10346  tmp = array[i];
10347  array[i] = array[end];
10348  array[end] = tmp;
10349  }
10350 }
10351 
10352 
10353 /** randomly shuffles parts of an array using the Fisher-Yates algorithm
10354  *
10355  * @deprecated Please use SCIPrandomPermuteArray()
10356  */
10358  void** array, /**< array to be shuffled */
10359  int begin, /**< first included index that should be subject to shuffling
10360  * (0 for first array entry)
10361  */
10362  int end, /**< first excluded index that should not be subject to shuffling
10363  * (array size for last array entry)
10364  */
10365  unsigned int* randseed /**< seed value for the random generator */
10366  )
10367 {
10368  void* tmp;
10369  int i;
10370 
10371  /* loop backwards through all elements and always swap the current last element to a random position */
10372  while( end > begin+1 )
10373  {
10374  end--;
10375 
10376  /* get a random position into which the last entry should be shuffled */
10377  i = getRandomInt(begin, end, randseed);
10378 
10379  /* swap the last element and the random element */
10380  tmp = array[i];
10381  array[i] = array[end];
10382  array[end] = tmp;
10383  }
10384 }
10385 
10386 /** draws a random subset of disjoint elements from a given set of disjoint elements;
10387  * this implementation is suited for the case that nsubelems is considerably smaller then nelems
10388  *
10389  * @deprecated Please use SCIPrandomGetSubset()
10390  */
10392  void** set, /**< original set, from which elements should be drawn */
10393  int nelems, /**< number of elements in original set */
10394  void** subset, /**< subset in which drawn elements should be stored */
10395  int nsubelems, /**< number of elements that should be drawn and stored */
10396  unsigned int randseed /**< seed value for random generator */
10397  )
10398 {
10399  int i;
10400  int j;
10401 
10402  /* if both sets are of equal size, we just copy the array */
10403  if( nelems == nsubelems)
10404  {
10405  BMScopyMemoryArray(subset,set,nelems);
10406  return SCIP_OKAY;
10407  }
10408 
10409  /* abort, if size of subset is too big */
10410  if( nsubelems > nelems )
10411  {
10412  SCIPerrorMessage("Cannot create %d-elementary subset of %d-elementary set.\n", nsubelems, nelems);
10413  return SCIP_INVALIDDATA;
10414  }
10415 #ifndef NDEBUG
10416  for( i = 0; i < nsubelems; i++ )
10417  for( j = 0; j < i; j++ )
10418  assert(set[i] != set[j]);
10419 #endif
10420 
10421  /* draw each element individually */
10422  i = 0;
10423  while( i < nsubelems )
10424  {
10425  int r;
10426 
10427  r = getRandomInt(0, nelems-1, &randseed);
10428  subset[i] = set[r];
10429 
10430  /* if we get an element that we already had, we will draw again */
10431  for( j = 0; j < i; j++ )
10432  {
10433  if( subset[i] == subset[j] )
10434  {
10435  --i;
10436  break;
10437  }
10438  }
10439  ++i;
10440  }
10441  return SCIP_OKAY;
10442 }
10443 
10444 
10445 /*
10446  * Arrays
10447  */
10448 
10449 /** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly
10450  *
10451  * @deprecated Switch to SCIPcomputeArraysIntersectionInt().
10452  */
10454  int* array1, /**< first array (in ascending order) */
10455  int narray1, /**< number of entries of first array */
10456  int* array2, /**< second array (in ascending order) */
10457  int narray2, /**< number of entries of second array */
10458  int* intersectarray, /**< intersection of array1 and array2
10459  * (note: it is possible to use array1 for this input argument) */
10460  int* nintersectarray /**< pointer to store number of entries of intersection array
10461  * (note: it is possible to use narray1 for this input argument) */
10462  )
10463 {
10464  SCIPcomputeArraysIntersectionInt(array1, narray1, array2, narray2, intersectarray, nintersectarray);
10465 
10466  return SCIP_OKAY;
10467 }
10468 
10469 /** computes set intersection (duplicates removed) of two integer arrays that are ordered ascendingly */
10471  int* array1, /**< first array (in ascending order) */
10472  int narray1, /**< number of entries of first array */
10473  int* array2, /**< second array (in ascending order) */
10474  int narray2, /**< number of entries of second array */
10475  int* intersectarray, /**< intersection of array1 and array2
10476  * (note: it is possible to use array1 for this input argument) */
10477  int* nintersectarray /**< pointer to store number of entries of intersection array
10478  * (note: it is possible to use narray1 for this input argument) */
10479  )
10480 {
10481  int cnt = 0;
10482  int k = 0;
10483  int v1;
10484  int v2;
10485 
10486  assert( array1 != NULL );
10487  assert( array2 != NULL );
10488  assert( intersectarray != NULL );
10489  assert( nintersectarray != NULL );
10490 
10491  /* determine intersection of array1 and array2 */
10492  for (v1 = 0; v1 < narray1; ++v1)
10493  {
10494  assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10495 
10496  /* skip duplicate entries */
10497  if ( v1+1 < narray1 && array1[v1] == array1[v1+1])
10498  continue;
10499 
10500  for (v2 = k; v2 < narray2; ++v2)
10501  {
10502  assert( v2 == 0 || array2[v2] >= array2[v2-1] );
10503 
10504  if ( array2[v2] > array1[v1] )
10505  {
10506  k = v2;
10507  break;
10508  }
10509  else if ( array2[v2] == array1[v1] )
10510  {
10511  intersectarray[cnt++] = array2[v2];
10512  k = v2 + 1;
10513  break;
10514  }
10515  }
10516  }
10517 
10518  /* store size of intersection array */
10519  *nintersectarray = cnt;
10520 }
10521 
10522 /** computes set intersection (duplicates removed) of two void-pointer arrays that are ordered ascendingly */
10524  void** array1, /**< pointer to first data array */
10525  int narray1, /**< number of entries of first array */
10526  void** array2, /**< pointer to second data array */
10527  int narray2, /**< number of entries of second array */
10528  SCIP_DECL_SORTPTRCOMP((*ptrcomp)), /**< data element comparator */
10529  void** intersectarray, /**< intersection of array1 and array2
10530  * (note: it is possible to use array1 for this input argument) */
10531  int* nintersectarray /**< pointer to store number of entries of intersection array
10532  * (note: it is possible to use narray1 for this input argument) */
10533  )
10534 {
10535  int cnt = 0;
10536  int k = 0;
10537  int v1;
10538  int v2;
10539 
10540  assert( array1 != NULL );
10541  assert( array2 != NULL );
10542  assert( ptrcomp != NULL );
10543  assert( intersectarray != NULL );
10544  assert( nintersectarray != NULL );
10545 
10546  /* determine intersection of array1 and array2 */
10547  for( v1 = 0; v1 < narray1; ++v1 )
10548  {
10549  assert( v1 == 0 || (*ptrcomp)(array1[v1], array1[v1-1]) >= 0 );
10550 
10551  /* skip duplicate entries */
10552  if( v1+1 < narray1 && array1[v1] == array1[v1+1] )
10553  continue;
10554 
10555  for( v2 = k; v2 < narray2; ++v2 )
10556  {
10557  assert( v2 == 0 || (*ptrcomp)(array2[v2], array2[v2-1]) > 0 || array2[v2] == array2[v2-1] );
10558 
10559  if( (*ptrcomp)(array2[v2], array1[v1]) > 0 )
10560  {
10561  k = v2;
10562  break;
10563  }
10564 
10565  if( array2[v2] == array1[v1] )
10566  {
10567  intersectarray[cnt++] = array2[v2];
10568  k = v2 + 1;
10569  break;
10570  }
10571  }
10572  }
10573 
10574  /* store size of intersection array */
10575  *nintersectarray = cnt;
10576 }
10577 
10578 
10579 /** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly
10580  *
10581  * @deprecated Switch to SCIPcomputeArraysSetminusInt().
10582  */
10584  int* array1, /**< first array (in ascending order) */
10585  int narray1, /**< number of entries of first array */
10586  int* array2, /**< second array (in ascending order) */
10587  int narray2, /**< number of entries of second array */
10588  int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10589  * (note: it is possible to use array1 for this input argument) */
10590  int* nsetminusarray /**< pointer to store number of entries of setminus array
10591  * (note: it is possible to use narray1 for this input argument) */
10592  )
10593 {
10594  SCIPcomputeArraysSetminusInt(array1, narray1, array2, narray2, setminusarray, nsetminusarray);
10595 
10596  return SCIP_OKAY;
10597 }
10598 
10599 /** computes set difference (duplicates removed) of two integer arrays that are ordered ascendingly */
10601  int* array1, /**< first array (in ascending order) */
10602  int narray1, /**< number of entries of first array */
10603  int* array2, /**< second array (in ascending order) */
10604  int narray2, /**< number of entries of second array */
10605  int* setminusarray, /**< array to store entries of array1 that are not an entry of array2
10606  * (note: it is possible to use array1 for this input argument) */
10607  int* nsetminusarray /**< pointer to store number of entries of setminus array
10608  * (note: it is possible to use narray1 for this input argument) */
10609  )
10610 {
10611  int cnt = 0;
10612  int v1 = 0;
10613  int v2 = 0;
10614 
10615  assert( array1 != NULL );
10616  assert( array2 != NULL );
10617  assert( setminusarray != NULL );
10618  assert( nsetminusarray != NULL );
10619 
10620  while ( v1 < narray1 )
10621  {
10622  int entry1;
10623 
10624  assert( v1 == 0 || array1[v1] >= array1[v1-1] );
10625 
10626  /* skip duplicate entries */
10627  while ( v1 + 1 < narray1 && array1[v1] == array1[v1 + 1] )
10628  ++v1;
10629 
10630  entry1 = array1[v1];
10631 
10632  while ( v2 < narray2 && array2[v2] < entry1 )
10633  ++v2;
10634 
10635  if ( v2 >= narray2 || entry1 < array2[v2] )
10636  setminusarray[cnt++] = entry1;
10637  ++v1;
10638  }
10639 
10640  /* store size of setminus array */
10641  *nsetminusarray = cnt;
10642 }
10643 
10644 
10645 /*
10646  * Strings
10647  */
10648 
10649 
10650 /** copies characters from 'src' to 'dest', copying is stopped when either the 'stop' character is reached or after
10651  * 'cnt' characters have been copied, whichever comes first.
10652  *
10653  * @note undefined behavior on overlapping arrays
10654  */
10656  char* dest, /**< destination pointer to copy to */
10657  const char* src, /**< source pointer to copy from */
10658  char stop, /**< character when found stop copying */
10659  unsigned int cnt /**< maximal number of characters to copy */
10660  )
10661 {
10662  if( dest == NULL || src == NULL || cnt == 0 )
10663  return -1;
10664  else
10665  {
10666  char* destination = dest;
10667 
10668  while( cnt-- && (*destination++ = *src++) != stop ); /*lint !e722*/
10669 
10670  return (int)(destination - dest);
10671  }
10672 }
10673 
10674 /** prints an error message containing of the given string followed by a string describing the current system error
10675  *
10676  * Prefers to use the strerror_r method, which is threadsafe. On systems where this method does not exist,
10677  * NO_STRERROR_R should be defined (see INSTALL). In this case, strerror is used which is not guaranteed to be
10678  * threadsafe (on SUN-systems, it actually is).
10679  */
10681  const char* message /**< first part of the error message, e.g. the filename */
10682  )
10683 {
10684 #ifdef NO_STRERROR_R
10685  SCIPmessagePrintError("%s: %s\n", message, strerror(errno));
10686 #else
10687  char buf[SCIP_MAXSTRLEN];
10688 
10689 #if defined(_WIN32) || defined(_WIN64)
10690  /* strerror_s returns 0 on success; the string is \0 terminated. */
10691  if ( strerror_s(buf, SCIP_MAXSTRLEN, errno) != 0 )
10692  SCIPmessagePrintError("Unknown error number %d or error message too long.\n", errno);
10693  SCIPmessagePrintError("%s: %s\n", message, buf);
10694 #elif (_POSIX_C_SOURCE >= 200112L || __DARWIN_C_LEVEL > 200112L || _XOPEN_SOURCE >= 600) && ! defined(_GNU_SOURCE)
10695  /* We are in the POSIX/XSI case, where strerror_r returns 0 on success; \0 termination is unclear. */
10696  if ( strerror_r(errno, buf, SCIP_MAXSTRLEN) != 0 )
10697  SCIPmessagePrintError("Unknown error number %d.\n", errno);
10698  buf[SCIP_MAXSTRLEN - 1] = '\0';
10699  SCIPmessagePrintError("%s: %s\n", message, buf);
10700 #else
10701  /* We are in the GNU case, where strerror_r returns a pointer to the error string. This string is possibly stored
10702  * in buf and is always \0 terminated.
10703  * However, if compiling on one system and executing on another system, we might actually call a different
10704  * variant of the strerror_r function than we had at compile time.
10705  */
10706  char* errordescr;
10707  *buf = '\0';
10708  errordescr = strerror_r(errno, buf, SCIP_MAXSTRLEN);
10709  if( *buf != '\0' )
10710  {
10711  /* strerror_r wrote into buf */
10712  SCIPmessagePrintError("%s: %s\n", message, buf);
10713  }
10714  else if( errordescr != NULL )
10715  {
10716  /* strerror_r returned something non-NULL */
10717  SCIPmessagePrintError("%s: %s\n", message, errordescr);
10718  }
10719  else
10720  {
10721  /* strerror_r did return NULL and did not write into buf */
10722  SCIPmessagePrintError("Could not obtain description for error %d.\n", errno);
10723  }
10724 #endif
10725 #endif
10726 }
10727 
10728 /** extracts tokens from strings - wrapper method for strtok_r() */
10730  char* s, /**< string to parse */
10731  const char* delim, /**< delimiters for parsing */
10732  char** ptrptr /**< pointer to working char pointer - must stay the same while parsing */
10733  )
10734 {
10735 #ifdef SCIP_NO_STRTOK_R
10736  return strtok(s, delim);
10737 #else
10738  return strtok_r(s, delim, ptrptr);
10739 #endif
10740 }
10741 
10742 /** translates the given string into a string where unescaped symbols ", ', and spaces are escaped with a \ prefix */
10744  char* t, /**< target buffer to store escaped string */
10745  int bufsize, /**< size of buffer t */
10746  const char* s /**< string to transform into escaped string */
10747  )
10748 {
10749  int len;
10750  int i;
10751  int p;
10752 
10753  assert(t != NULL);
10754  assert(bufsize > 0);
10755 
10756  len = (int)strlen(s);
10757  for( p = 0, i = 0; i <= len && p < bufsize; ++i, ++p )
10758  {
10759  if( s[i] == '\\' )
10760  {
10761  t[p] = s[i];
10762  ++p;
10763  ++i;
10764  }
10765  else if( s[i] == ' ' || s[i] == '\"' || s[i] == '\'' )
10766  {
10767  t[p] = '\\';
10768  ++p;
10769  }
10770  if( i <= len && p < bufsize )
10771  t[p] = s[i];
10772  }
10773  t[bufsize-1] = '\0';
10774 }
10775 
10776 /** increases string pointer as long as it refers to a space character or an explicit space control sequence */
10778  char** s /**< pointer to string pointer */
10779  )
10780 {
10781  while( isspace(**s) || ( **s == '\\' && *(*s+1) != '\0' && strchr(SCIP_SPACECONTROL, *(*s+1)) ) )
10782  *s += **s == '\\' ? 2 : 1;
10783 
10784  return SCIP_OKAY;
10785 }
10786 
10787 /* safe version of snprintf */
10789  char* t, /**< target string */
10790  int len, /**< length of the string to copy */
10791  const char* s, /**< source string */
10792  ... /**< further parameters */
10793  )
10794 {
10795  va_list ap;
10796  int n;
10797 
10798  assert(t != NULL);
10799  assert(len > 0);
10800 
10801  va_start(ap, s); /*lint !e826*/
10802 
10803 #if defined(_WIN32) || defined(_WIN64)
10804  n = _vsnprintf(t, (size_t) len, s, ap);
10805 #else
10806  n = vsnprintf(t, (size_t) len, s, ap); /*lint !e571*/
10807 #endif
10808  va_end(ap);
10809 
10810  if( n < 0 || n >= len )
10811  {
10812 #ifndef NDEBUG
10813  if( n < 0 )
10814  {
10815  SCIPerrorMessage("vsnprintf returned %d\n",n);
10816  }
10817 #endif
10818  t[len-1] = '\0';
10819  n = len-1;
10820  }
10821  return n;
10822 }
10823 
10824 /** safe version of strncpy
10825  *
10826  * Copies string in s to t using at most @a size-1 nonzero characters (strncpy copies size characters). It always adds
10827  * a terminating zero char. Does not pad the remaining string with zero characters (unlike strncpy). Returns the number
10828  * of copied nonzero characters, if the length of s is at most size - 1, and returns size otherwise. Thus, the original
10829  * string was truncated if the return value is size.
10830  */
10832  char* t, /**< target string */
10833  const char* s, /**< source string */
10834  int size /**< maximal size of t */
10835  )
10836 {
10837  int n;
10838 
10839  if( size <= 0 )
10840  return 0;
10841 
10842  /* decrease size by 1 to create space for terminating zero char */
10843  --size;
10844  for( n = 0; n < size && *s != '\0'; n++ )
10845  *(t++) = *(s++);
10846  *t = '\0';
10847 
10848  if( *s != '\0' )
10849  ++n;
10850 
10851  return n;
10852 }
10853 
10854 /** 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
10855  *
10856  * @return Returns TRUE if a value could be extracted, otherwise FALSE
10857  */
10859  const char* str, /**< string to search */
10860  int* value, /**< pointer to store the parsed value */
10861  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10862  )
10863 {
10864  assert(str != NULL);
10865  assert(value != NULL);
10866  assert(endptr != NULL);
10867 
10868  /* init errno to detect possible errors */
10869  errno = 0;
10870 
10871  *value = (int) strtol(str, endptr, 10);
10872 
10873  if( *endptr != str && *endptr != NULL )
10874  {
10875  SCIPdebugMessage("parsed integer value <%d>\n", *value);
10876  return TRUE;
10877  }
10878  *endptr = (char*)str;
10879 
10880  SCIPdebugMessage("failed parsing integer value <%s>\n", str);
10881 
10882  return FALSE;
10883 }
10884 
10885 /** 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
10886  *
10887  * @return Returns TRUE if a value could be extracted, otherwise FALSE
10888  */
10890  const char* str, /**< string to search */
10891  SCIP_Real* value, /**< pointer to store the parsed value */
10892  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10893  )
10894 {
10895  assert(str != NULL);
10896  assert(value != NULL);
10897  assert(endptr != NULL);
10898 
10899  /* init errno to detect possible errors */
10900  errno = 0;
10901 
10902  *value = strtod(str, endptr);
10903 
10904  if( *endptr != str && *endptr != NULL )
10905  {
10906  SCIPdebugMessage("parsed real value <%g>\n", *value);
10907  return TRUE;
10908  }
10909  *endptr = (char*)str;
10910 
10911  SCIPdebugMessage("failed parsing real value <%s>\n", str);
10912 
10913  return FALSE;
10914 }
10915 
10916 /** copies the first size characters between a start and end character of str into token, if no error occurred endptr
10917  * will point to the position after the read part, otherwise it will point to @p str
10918  */
10920  const char* str, /**< string to search */
10921  char startchar, /**< character which defines the beginning */
10922  char endchar, /**< character which defines the ending */
10923  char* token, /**< string to store the copy */
10924  int size, /**< size of the token char array */
10925  char** endptr /**< pointer to store the final string position if successfully parsed, otherwise @p str */
10926  )
10927 {
10928  const char* copystr;
10929  int nchars;
10930 
10931  assert(str != NULL);
10932  assert(token != NULL);
10933  assert(size > 0);
10934  assert(endptr != NULL);
10935 
10936  nchars = 0;
10937 
10938  copystr = str;
10939 
10940  /* find starting character */
10941  while( *str != '\0' && *str != startchar )
10942  ++str;
10943 
10944  /* did not find start character */
10945  if( *str == '\0' )
10946  {
10947  *endptr = (char*)copystr;
10948  return;
10949  }
10950 
10951  /* skip start character */
10952  ++str;
10953 
10954  /* copy string */
10955  while( *str != '\0' && *str != endchar && nchars < size-1 )
10956  {
10957  assert(nchars < SCIP_MAXSTRLEN);
10958  token[nchars] = *str;
10959  nchars++;
10960  ++str;
10961  }
10962 
10963  /* add end to token */
10964  token[nchars] = '\0';
10965 
10966  /* if section was longer than size, we want to reach the end of the parsing section anyway */
10967  if( nchars == (size-1) )
10968  while( *str != '\0' && *str != endchar )
10969  ++str;
10970 
10971  /* did not find end character */
10972  if( *str == '\0' )
10973  {
10974  *endptr = (char*)copystr;
10975  return;
10976  }
10977 
10978  /* skip end character */
10979  ++str;
10980 
10981  SCIPdebugMessage("parsed section <%s>\n", token);
10982 
10983  *endptr = (char*) str;
10984 }
10985 
10986 /*
10987  * File methods
10988  */
10989 
10990 /** returns, whether the given file exists */
10992  const char* filename /**< file name */
10993  )
10994 {
10995  FILE* f;
10996 
10997  f = fopen(filename, "r");
10998  if( f == NULL )
10999  return FALSE;
11000 
11001  fclose(f);
11002 
11003  return TRUE;
11004 }
11005 
11006 /** splits filename into path, name, and extension */
11008  char* filename, /**< filename to split; is destroyed (but not freed) during process */
11009  char** path, /**< pointer to store path, or NULL if not needed */
11010  char** name, /**< pointer to store name, or NULL if not needed */
11011  char** extension, /**< pointer to store extension, or NULL if not needed */
11012  char** compression /**< pointer to store compression extension, or NULL if not needed */
11013  )
11014 {
11015  char* lastslash;
11016  char* lastbackslash;
11017  char* lastdot;
11018 
11019  assert(filename != NULL);
11020 
11021  if( path != NULL )
11022  *path = NULL;
11023  if( name != NULL )
11024  *name = NULL;
11025  if( extension != NULL )
11026  *extension = NULL;
11027  if( compression != NULL )
11028  *compression = NULL;
11029 
11030  /* treat both slashes '/' and '\' as directory delimiters */
11031  lastslash = strrchr(filename, '/');
11032  lastbackslash = strrchr(filename, '\\');
11033  lastslash = MAX(lastslash, lastbackslash); /*lint !e613*/
11034  lastdot = strrchr(filename, '.');
11035  if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11036  lastdot = NULL;
11037 
11038  /* detect known compression extensions */
11039 #ifdef SCIP_WITH_ZLIB
11040  if( lastdot != NULL )
11041  {
11042  char* compext;
11043 
11044  compext = lastdot+1;
11045  if( strcmp(compext, "gz") == 0
11046  || strcmp(compext, "z") == 0
11047  || strcmp(compext, "Z") == 0 )
11048  {
11049  if( compression != NULL )
11050  *compression = compext;
11051  *lastdot = '\0';
11052  }
11053 
11054  /* find again the last dot in the filename without compression extension */
11055  lastdot = strrchr(filename, '.');
11056  if( lastslash != NULL && lastdot != NULL && lastdot < lastslash ) /* is the last dot belonging to the path? */
11057  lastdot = NULL;
11058  }
11059 #endif
11060 
11061  if( lastslash == NULL )
11062  {
11063  if( name != NULL )
11064  *name = filename;
11065  }
11066  else
11067  {
11068  if( path != NULL )
11069  *path = filename;
11070  if( name != NULL )
11071  *name = lastslash+1;
11072  *lastslash = '\0';
11073  }
11074 
11075  if( lastdot != NULL )
11076  {
11077  if( extension != NULL )
11078  *extension = lastdot+1;
11079  *lastdot = '\0';
11080  }
11081 }
11082 
11083 /*
11084  * simple functions implemented as defines
11085  */
11086 
11087 /* In debug mode, the following methods are implemented as function calls to ensure
11088  * type validity.
11089  * In optimized mode, the methods are implemented as defines to improve performance.
11090  * However, we want to have them in the library anyways, so we have to undef the defines.
11091  */
11092 
11093 #undef SCIPrelDiff
11094 
11095 /** returns the relative difference: (val1-val2)/max(|val1|,|val2|,1.0) */
11097  SCIP_Real val1, /**< first value to be compared */
11098  SCIP_Real val2 /**< second value to be compared */
11099  )
11100 {
11101  SCIP_Real absval1;
11102  SCIP_Real absval2;
11103  SCIP_Real quot;
11104 
11105  absval1 = REALABS(val1);
11106  absval2 = REALABS(val2);
11107  quot = MAX3(1.0, absval1, absval2);
11108 
11109  return (val1-val2)/quot;
11110 }
11111 
11112 
11113 /** computes the gap from the primal and the dual bound */
11115  SCIP_Real eps, /**< the value treated as zero */
11116  SCIP_Real inf, /**< the value treated as infinity */
11117  SCIP_Real primalbound, /**< the primal bound */
11118  SCIP_Real dualbound /**< the dual bound */
11119  )
11120 {
11121  if( EPSEQ(primalbound, dualbound, eps) )
11122  return 0.0;
11123  else
11124  {
11125  SCIP_Real absdual = REALABS(dualbound);
11126  SCIP_Real absprimal = REALABS(primalbound);
11127 
11128  if( EPSZ(dualbound, eps) || EPSZ(primalbound, eps) || absprimal >= inf || absdual >= inf ||
11129  primalbound * dualbound < 0.0 )
11130  return inf;
11131  else
11132  return REALABS((primalbound - dualbound)/MIN(absdual, absprimal));
11133  }
11134 }
11135 
11136 /*
11137  * disjoint set (union-find) data structure
11138  */
11139 
11140 /** creates a disjoint set (union find) structure \p djset for \p ncomponents many components (of size one) */
11142  SCIP_DISJOINTSET** djset, /**< disjoint set (union find) data structure */
11143  BMS_BLKMEM* blkmem, /**< block memory */
11144  int ncomponents /**< number of components */
11145  )
11146 {
11147  assert(djset != NULL);
11148  assert(blkmem != NULL);
11149 
11150  /* allocate the necessary memory */
11151  assert(ncomponents > 0);
11152  SCIP_ALLOC( BMSallocBlockMemory(blkmem, djset) );
11153  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->parents), ncomponents) );
11154  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &((*djset)->sizes), ncomponents) );
11155  (*djset)->size = ncomponents;
11156 
11157  /* clear the data structure */
11158  SCIPdisjointsetClear(*djset);
11159 
11160  return SCIP_OKAY;
11161 }
11162 
11163 /** clears the disjoint set (union find) structure \p djset */
11165  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11166  )
11167 {
11168  int i;
11169 
11170  djset->componentcount = djset->size;
11171 
11172  /* reset all components to be unconnected */
11173  for( i = 0; i < djset->componentcount; i++ )
11174  {
11175  djset->parents[i] = i;
11176  djset->sizes[i] = 1;
11177  }
11178 }
11179 
11180 /** finds and returns the component identifier of this \p element */
11182  SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11183  int element /**< element to be found */
11184  )
11185 {
11186  int newelement;
11187  int root = element;
11188  int* parents = djset->parents;
11189 
11190  /* find root of this element */
11191  while( root != parents[root] )
11192  {
11193  root = parents[root];
11194  }
11195 
11196  /* compress the path to make future queries faster */
11197  while( element != root )
11198  {
11199  newelement = parents[element];
11200  parents[element] = root;
11201  element = newelement;
11202  }
11203 
11204  return root;
11205 }
11206 
11207 /** merges the components containing the elements \p p and \p q */
11209  SCIP_DISJOINTSET* djset, /**< disjoint set (union find) data structure */
11210  int p, /**< first element */
11211  int q, /**< second element */
11212  SCIP_Bool forcerepofp /**< force representative of p to be new representative */
11213  )
11214 {
11215  int idp;
11216  int idq;
11217  int* sizes;
11218  int* parents;
11219 
11220  assert(djset != NULL);
11221  assert(0 <= p);
11222  assert(0 <= q);
11223  assert(djset->size > p);
11224  assert(djset->size > q);
11225 
11226  idp = SCIPdisjointsetFind(djset, p);
11227  idq = SCIPdisjointsetFind(djset, q);
11228 
11229  /* if p and q lie in the same component, there is nothing to be done */
11230  if( idp == idq )
11231  return;
11232 
11233  sizes = djset->sizes;
11234  parents = djset->parents;
11235 
11236  if( forcerepofp )
11237  {
11238  parents[idq] = idp;
11239  sizes[idp] += sizes[idq];
11240  }
11241  else
11242  {
11243  if( sizes[idp] < sizes[idq] )
11244  {
11245  parents[idp] = idq;
11246  sizes[idq] += sizes[idp];
11247  }
11248  else
11249  {
11250  parents[idq] = idp;
11251  sizes[idp] += sizes[idq];
11252  }
11253  }
11254  /* one less component */
11255  djset->componentcount--;
11256 }
11257 
11258 /** frees the disjoint set (union find) data structure */
11260  SCIP_DISJOINTSET** djset, /**< pointer to disjoint set (union find) data structure */
11261  BMS_BLKMEM* blkmem /**< block memory */
11262  )
11263 {
11264  SCIP_DISJOINTSET* dsptr;
11265 
11266  assert(djset != NULL);
11267  assert(*djset != NULL);
11268 
11269  dsptr = *djset;
11270 
11271  BMSfreeBlockMemoryArray(blkmem, &dsptr->sizes, dsptr->size);
11272  BMSfreeBlockMemoryArray(blkmem, &dsptr->parents, dsptr->size);
11273 
11274  BMSfreeBlockMemory(blkmem, djset);
11275 }
11276 
11277 /** returns the number of independent components in this disjoint set (union find) data structure */
11279  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11280  )
11281 {
11282  assert(djset != NULL);
11283 
11284  return djset->componentcount;
11285 }
11286 
11287 /** returns the size (number of nodes) of this disjoint set (union find) data structure */
11289  SCIP_DISJOINTSET* djset /**< disjoint set (union find) data structure */
11290  )
11291 {
11292  assert(djset != NULL);
11293 
11294  return djset->size;
11295 }
11296 
11297 /** checks whether a given string t appears at the beginning of the string s (up to spaces at beginning) */
11299  const char* s, /**< string to search in */
11300  const char* t, /**< string to search for */
11301  size_t tlen /**< length of t */
11302  )
11303 {
11304  int idxctr = 0;
11305 
11306  assert(s != NULL);
11307  assert(t != NULL);
11308 
11309  /* skip whitespace at beginning */
11310  while( idxctr < SCIP_MAXSTRLEN && isspace((unsigned char)s[idxctr]) )
11311  ++idxctr;
11312  if( strncmp(&s[idxctr], t, tlen) == 0 )
11313  return TRUE;
11314  return FALSE;
11315 }
void SCIPmultihashFree(SCIP_MULTIHASH **multihash)
Definition: misc.c:1943
void SCIPpermuteArray(void **array, int begin, int end, unsigned int *randseed)
Definition: misc.c:10357
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:8588
int SCIPrealarrayGetMaxIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4342
void ** slots
Definition: struct_misc.h:96
void ** SCIPdigraphGetSuccessorsData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7749
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:8652
void * SCIPhashmapEntryGetImage(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3520
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:2928
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:10655
SCIP_RETCODE SCIPskipSpace(char **s)
Definition: misc.c:10777
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:3572
static SCIP_RETCODE hashmapCheckLoad(SCIP_HASHMAP *hashmap)
Definition: misc.c:2973
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:3808
static const int nscalars
Definition: misc.c:9463
static SCIP_RETCODE hashmapInsert(SCIP_HASHMAP *hashmap, void *origin, SCIP_HASHMAPIMAGE image, uint32_t hashval, SCIP_Bool override)
Definition: misc.c:2852
BMS_BLKMEM * blkmem
Definition: struct_misc.h:221
void SCIPdisjointsetUnion(SCIP_DISJOINTSET *djset, int p, int q, SCIP_Bool forcerepofp)
Definition: misc.c:11208
void * SCIPhashtableGetEntry(SCIP_HASHTABLE *hashtable, int entryidx)
Definition: misc.c:2735
void SCIPsparseSolGetFirstSol(SCIP_SPARSESOL *sparsesol, SCIP_Longint *sol, int nvars)
Definition: misc.c:819
SCIP_BTNODE * SCIPbtnodeGetSibling(SCIP_BTNODE *node)
Definition: misc.c:8737
SCIP_RETCODE SCIPhashmapSetImageInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3307
uint32_t shift
Definition: struct_misc.h:142
SCIP_RETCODE SCIPprofileDeleteCore(SCIP_PROFILE *profile, int left, int right, int demand)
Definition: misc.c:6962
void * SCIPbtnodeGetData(SCIP_BTNODE *node)
Definition: misc.c:8697
void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2497
BMS_BLKMEM * blkmem
Definition: struct_misc.h:250
SCIP_DECL_HASHKEYVAL(SCIPhashKeyValString)
Definition: misc.c:2801
SCIP_Real intercept
Definition: struct_misc.h:256
void SCIPdigraphFreeComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8429
int SCIPhashsetGetNElements(SCIP_HASHSET *hashset)
Definition: misc.c:3942
SCIP_RETCODE SCIPintarrayIncVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int incval)
Definition: misc.c:4684
void SCIPhashmapEntrySetImageInt(SCIP_HASHMAPENTRY *entry, int image)
Definition: misc.c:3561
static SCIP_RETCODE multihashlistAppend(SCIP_MULTIHASHLIST **multihashlist, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:1601
void ** SCIPhashsetGetSlots(SCIP_HASHSET *hashset)
Definition: misc.c:3958
#define SCIP_MAXSTRLEN
Definition: def.h:302
static uint32_t hashSetDesiredPos(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3608
void ** nodedata
Definition: struct_misc.h:224
static SCIP_RETCODE hashtableCheckLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2444
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:8001
int SCIPintarrayGetMinIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4696
SCIP_RETCODE SCIPrealarrayCreate(SCIP_REALARRAY **realarray, BMS_BLKMEM *blkmem)
Definition: misc.c:3980
static SCIP_RETCODE btnodeCreateEmpty(SCIP_BT *tree, SCIP_BTNODE **node)
Definition: misc.c:8572
SCIP_RETCODE SCIPintarrayCopy(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem, SCIP_INTARRAY *sourceintarray)
Definition: misc.c:4372
void SCIPcomputeArraysSetminusInt(int *array1, int narray1, int *array2, int narray2, int *setminusarray, int *nsetminusarray)
Definition: misc.c:10600
SCIP_Bool SCIPboolarrayGetVal(SCIP_BOOLARRAY *boolarray, int idx)
Definition: misc.c:4963
#define SCIP_CALL_FINALLY(x, y)
Definition: def.h:436
int * SCIPdigraphGetSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7731
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
static SCIP_RETCODE ensureSuccessorsSize(SCIP_DIGRAPH *digraph, int idx, int newsize)
Definition: misc.c:7527
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:6645
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:11007
void * SCIPhashmapEntryGetOrigin(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3510
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:6759
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:4595
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:10307
void SCIPbtnodeSetRightchild(SCIP_BTNODE *node, SCIP_BTNODE *right)
Definition: misc.c:8858
#define DEFAULT_MWC
Definition: misc.c:9928
#define SCIP_RAND_MAX
Definition: misc.c:9845
void * SCIPptrarrayGetVal(SCIP_PTRARRAY *ptrarray, int idx)
Definition: misc.c:5316
#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:2360
#define GMLNODEWIDTH
Definition: misc.c:486
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3024
#define EPSEQ(x, y, eps)
Definition: def.h:211
static const SCIP_Real studentt_quartilesabove[]
Definition: misc.c:97
static SCIP_RETCODE optimize(SCIP *scip, SCIP_SOL *worksol, SCIP_VAR **vars, int *blockstart, int *blockend, int nblocks, OPTTYPE opttype, SCIP_Real *activities, int nrows, SCIP_Bool *improvement, SCIP_Bool *varboundserr, SCIP_HEURDATA *heurdata)
Definition: heur_twoopt.c:931
int SCIPboolarrayGetMaxIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5062
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:11096
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:7052
#define SCIP_MULTIHASH_MAXSIZE
Definition: misc.c:1788
miscellaneous datastructures
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10788
void SCIPrandomPermuteArray(SCIP_RANDNUMGEN *randnumgen, void **array, int begin, int end)
Definition: misc.c:10090
#define TRUE
Definition: def.h:95
SCIP_RETCODE SCIPhashsetCreate(SCIP_HASHSET **hashset, BMS_BLKMEM *blkmem, int size)
Definition: misc.c:3709
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:7456
SCIP_RETCODE SCIPhashmapInsertInt(SCIP_HASHMAP *hashmap, void *origin, int image)
Definition: misc.c:3142
void SCIPdigraphPrintComponents(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8535
SCIP_VAR * SCIPactivityGetVar(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6598
SCIP_RETCODE SCIPptrarrayExtend(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:5130
void * SCIPpqueueFirst(SCIP_PQUEUE *pqueue)
Definition: misc.c:1463
SCIP_RETCODE SCIPboolarrayCopy(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem, SCIP_BOOLARRAY *sourceboolarray)
Definition: misc.c:4737
SCIP_Bool SCIPhashsetExists(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3767
#define SCIP_UNUSED(x)
Definition: def.h:448
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:2348
SCIP_RETCODE SCIPcomputeArraysIntersection(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10453
#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:10294
int SCIPdigraphGetNComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8196
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:10858
#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:6932
#define SCIPdebugMessage
Definition: pub_message.h:96
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10019
SCIP_Real SCIPselectSimpleValue(SCIP_Real lb, SCIP_Real ub, SCIP_Longint maxdnom)
Definition: misc.c:9735
#define DEFAULT_XOR
Definition: misc.c:9927
#define SCIP_SPACECONTROL
Definition: def.h:303
void SCIPdigraphGetComponent(SCIP_DIGRAPH *digraph, int compidx, int **nodes, int *nnodes)
Definition: misc.c:8209
SCIP_VAR ** vars
Definition: struct_misc.h:48
SCIP_Bool SCIPhashmapIsEmpty(SCIP_HASHMAP *hashmap)
Definition: misc.c:3473
int SCIPdisjointsetGetSize(SCIP_DISJOINTSET *djset)
Definition: misc.c:11288
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3211
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
#define SCIP_LONGINT_MAX
Definition: def.h:172
int SCIPptrarrayGetMinIdx(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5405
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:10269
void SCIPsortDown(int *perm, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
Definition: misc.c:5989
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:6771
SCIP_Real SCIPhashmapGetImageReal(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3251
void * dataptr
Definition: struct_misc.h:243
int SCIPstrncpy(char *t, const char *s, int size)
Definition: misc.c:10831
int SCIPhashsetGetNSlots(SCIP_HASHSET *hashset)
Definition: misc.c:3950
SCIP_VAR ** x
Definition: circlepacking.c:63
SCIP_RETCODE SCIPdigraphTopoSortComponents(SCIP_DIGRAPH *digraph)
Definition: misc.c:8130
#define SCIP_MULTIHASH_GROW_FACTOR
Definition: misc.c:1790
int SCIPrealarrayGetMinIdx(SCIP_REALARRAY *realarray)
Definition: misc.c:4332
SCIP_Bool SCIPbtnodeIsRoot(SCIP_BTNODE *node)
Definition: misc.c:8757
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:2246
SCIP_RETCODE SCIPboolarraySetVal(SCIP_BOOLARRAY *boolarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Bool val)
Definition: misc.c:4984
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:9776
#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:3373
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:3934
SCIP_Bool SCIPfileExists(const char *filename)
Definition: misc.c:10991
void SCIPqueueClear(SCIP_QUEUE *queue)
Definition: misc.c:978
int SCIPdigraphGetNNodes(SCIP_DIGRAPH *digraph)
Definition: misc.c:7658
int SCIPprofileGetCapacity(SCIP_PROFILE *profile)
Definition: misc.c:6719
SCIP_RETCODE SCIPintarrayFree(SCIP_INTARRAY **intarray)
Definition: misc.c:4395
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:9305
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:4314
void ** slots
Definition: struct_misc.h:83
SCIP_RETCODE SCIPactivityCreate(SCIP_RESOURCEACTIVITY **activity, SCIP_VAR *var, int duration, int demand)
Definition: misc.c:6553
void SCIPregressionRemoveObservation(SCIP_REGRESSION *regression, SCIP_Real x, SCIP_Real y)
Definition: misc.c:348
SCIP_DECL_HASHKEYEQ(SCIPhashKeyEqString)
Definition: misc.c:2792
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:3966
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:11164
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:11298
#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:4000
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:8707
#define GMLNODEHEIGTH
Definition: misc.c:487
SCIP_RETCODE SCIPdigraphSetNSuccessors(SCIP_DIGRAPH *digraph, int node, int nsuccessors)
Definition: misc.c:7642
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:3435
int SCIPactivityGetEnergy(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6628
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:3491
SCIP_HASHMAPENTRY * SCIPhashmapGetEntry(SCIP_HASHMAP *hashmap, int entryidx)
Definition: misc.c:3499
void SCIPdisjointsetFree(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem)
Definition: misc.c:11259
#define GMLNODETYPE
Definition: misc.c:489
void SCIPbtnodeSetLeftchild(SCIP_BTNODE *node, SCIP_BTNODE *left)
Definition: misc.c:8844
SCIP_RETCODE SCIPboolarrayCreate(SCIP_BOOLARRAY **boolarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4717
void * SCIPdigraphGetNodeData(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7668
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:3740
#define BMSmoveMemoryArray(ptr, source, num)
Definition: memory.h:140
Definition: pqueue.h:37
SCIP_Real SCIPrealarrayGetVal(SCIP_REALARRAY *realarray, int idx)
Definition: misc.c:4224
void SCIPdigraphSetNodeData(SCIP_DIGRAPH *digraph, void *dataptr, int node)
Definition: misc.c:7684
#define SQRTOFTWO
Definition: misc.c:60
void SCIPescapeString(char *t, int bufsize, const char *s)
Definition: misc.c:10743
void SCIPhashmapEntrySetImage(SCIP_HASHMAPENTRY *entry, void *image)
Definition: misc.c:3550
int SCIPintarrayGetMaxIdx(SCIP_INTARRAY *intarray)
Definition: misc.c:4706
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10919
SCIP_Real sizefac
Definition: struct_misc.h:80
SCIP_RETCODE SCIPdigraphCreate(SCIP_DIGRAPH **digraph, BMS_BLKMEM *blkmem, int nnodes)
Definition: misc.c:7289
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:6994
void SCIPcomputeArraysIntersectionInt(int *array1, int narray1, int *array2, int narray2, int *intersectarray, int *nintersectarray)
Definition: misc.c:10470
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3058
void SCIPdigraphPrint(SCIP_DIGRAPH *digraph, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: misc.c:8461
#define BMSallocClearBlockMemoryArray(mem, ptr, num)
Definition: memory.h:457
internal miscellaneous methods
SCIP_RETCODE SCIPboolarrayClear(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:4932
#define NULL
Definition: lpi_spx1.cpp:164
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem)
Definition: misc.c:10003
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:6572
void SCIPrandomSetSeed(SCIP_RANDNUMGEN *randnumgen, unsigned int initseed)
Definition: misc.c:9933
int SCIPdisjointsetFind(SCIP_DISJOINTSET *djset, int element)
Definition: misc.c:11181
#define DEFAULT_SEED
Definition: misc.c:9926
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:5415
#define SCIP_CALL(x)
Definition: def.h:394
#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:6872
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:2705
SCIP_RETCODE SCIPhashtableRemove(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2627
SCIP_RETCODE SCIPintarraySetVal(SCIP_INTARRAY *intarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, int val)
Definition: misc.c:4616
SCIP_RETCODE SCIPprofileCreate(SCIP_PROFILE **profile, int capacity)
Definition: misc.c:6667
static SCIP_RETCODE ensureProfileSize(SCIP_PROFILE *profile, int neededsize)
Definition: misc.c:6808
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:7574
SCIP_Bool SCIPbtnodeIsRightchild(SCIP_BTNODE *node)
Definition: misc.c:8795
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:11278
SCIP_RETCODE SCIPgetRandomSubset(void **set, int nelems, void **subset, int nsubelems, unsigned int randseed)
Definition: misc.c:10391
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:8980
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:145
SCIP_RETCODE SCIPhashmapInsertReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3178
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:10583
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:467
SCIP_DECL_HASHGETKEY(SCIPhashGetKeyStandard)
Definition: misc.c:2820
static int getRand(unsigned int *seedp)
Definition: misc.c:9849
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:2754
SCIP_DECL_SORTPTRCOMP(SCIPsortCompInt)
Definition: misc.c:5430
#define PQ_PARENT(q)
Definition: misc.c:1221
SCIP_BTNODE * SCIPbtnodeGetRightchild(SCIP_BTNODE *node)
Definition: misc.c:8727
void SCIPintervalSetRoundingModeDownwards(void)
public data structures and miscellaneous methods
SCIP_RETCODE SCIPdigraphAddArcSafe(SCIP_DIGRAPH *digraph, int startnode, int endnode, void *data)
Definition: misc.c:7605
static const int primetablesize
Definition: misc.c:1575
int SCIPdigraphGetNSuccessors(SCIP_DIGRAPH *digraph, int node)
Definition: misc.c:7716
#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:10680
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:3583
static const SCIP_Real studentt_quartiles[]
Definition: misc.c:76
#define ELEM_DISTANCE(pos)
Definition: misc.c:3604
SCIP_RETCODE SCIPmultihashInsert(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:1974
static uint32_t randomGetRand(SCIP_RANDNUMGEN *randnumgen)
Definition: misc.c:9964
SCIP_Bool SCIPprofileFindLeft(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6785
SCIP_RETCODE SCIPrealarrayFree(SCIP_REALARRAY **realarray)
Definition: misc.c:4024
SCIP_RETCODE SCIPdigraphResize(SCIP_DIGRAPH *digraph, int nnodes)
Definition: misc.c:7326
#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:10060
static const SCIP_Real simplednoms[]
Definition: misc.c:9299
#define MAX(x, y)
Definition: tclique_def.h:92
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10889
static int getRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:9860
int SCIPdigraphGetNArcs(SCIP_DIGRAPH *digraph)
Definition: misc.c:7698
void SCIPbtFree(SCIP_BT **tree)
Definition: misc.c:8888
SCIP_RETCODE SCIPhashtableSafeInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2529
SCIP_Bool SCIPbtnodeIsLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8777
SCIP_Real SCIPnextafter(SCIP_Real from, SCIP_Real to)
Definition: misc.c:9275
#define DEFAULT_CST
Definition: misc.c:9929
SCIP_RETCODE SCIPdigraphComputeDirectedComponents(SCIP_DIGRAPH *digraph, int compidx, int *strongcomponents, int *strongcompstartidx, int *nstrongcomponents)
Definition: misc.c:8341
int SCIPboolarrayGetMinIdx(SCIP_BOOLARRAY *boolarray)
Definition: misc.c:5052
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:6697
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:9688
int * articulations
Definition: struct_misc.h:229
SCIP_RETCODE SCIPdigraphGetArticulationPoints(SCIP_DIGRAPH *digraph, int **articulations, int *narticulations)
Definition: misc.c:7912
void * SCIPhashtableRetrieve(SCIP_HASHTABLE *hashtable, void *key)
Definition: misc.c:2558
static SCIP_Real getRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9880
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:9440
#define BMSclearMemory(ptr)
Definition: memory.h:131
int * SCIPprofileGetTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6739
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:10041
int * SCIPprofileGetLoads(SCIP_PROFILE *profile)
Definition: misc.c:6749
static void depthFirstSearch(SCIP_DIGRAPH *digraph, int startnode, SCIP_Bool *visited, int *dfsstack, int *stackadjvisited, int *dfsnodes, int *ndfsnodes)
Definition: misc.c:7766
#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:9902
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2296
SCIP_Bool SCIPbtIsEmpty(SCIP_BT *tree)
Definition: misc.c:8970
SCIP_RETCODE SCIPptrarrayClear(SCIP_PTRARRAY *ptrarray)
Definition: misc.c:5285
#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:8232
#define SCIP_REAL_MAX
Definition: def.h:187
SCIP_Real SCIPgetRandomReal(SCIP_Real minrandval, SCIP_Real maxrandval, unsigned int *seedp)
Definition: misc.c:9915
static SCIP_RETCODE queueCheckSize(SCIP_QUEUE *queue)
Definition: misc.c:990
SCIP_BTNODE * SCIPbtnodeGetLeftchild(SCIP_BTNODE *node)
Definition: misc.c:8717
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:8993
SCIP_RETCODE SCIPhashmapSetImageReal(SCIP_HASHMAP *hashmap, void *origin, SCIP_Real image)
Definition: misc.c:3341
SCIP_RETCODE SCIPhashmapRemove(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3389
int SCIPpqueueFind(SCIP_PQUEUE *pqueue, void *elem)
Definition: misc.c:1499
void SCIPbtnodeSetParent(SCIP_BTNODE *node, SCIP_BTNODE *parent)
Definition: misc.c:8830
int SCIPhashmapGetNElements(SCIP_HASHMAP *hashmap)
Definition: misc.c:3483
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:5450
SCIP_RETCODE SCIPqueueCreate(SCIP_QUEUE **queue, int initsize, SCIP_Real sizefac)
Definition: misc.c:943
SCIP_RETCODE SCIPptrarrayFree(SCIP_PTRARRAY **ptrarray)
Definition: misc.c:5116
#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:3668
SCIP_Real SCIPcalcMachineEpsilon(void)
Definition: misc.c:9009
SCIP_Real SCIPhashmapEntryGetImageReal(SCIP_HASHMAPENTRY *entry)
Definition: misc.c:3540
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:4409
SCIP_RETCODE SCIPptrarraySetVal(SCIP_PTRARRAY *ptrarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, void *val)
Definition: misc.c:5337
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:7144
int SCIPactivityGetDuration(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6608
SCIP_BTNODE * right
Definition: struct_misc.h:242
SCIP_RETCODE SCIPdigraphCopy(SCIP_DIGRAPH **targetdigraph, SCIP_DIGRAPH *sourcedigraph, BMS_BLKMEM *targetblkmem)
Definition: misc.c:7366
SCIP_RETCODE SCIPboolarrayFree(SCIP_BOOLARRAY **boolarray)
Definition: misc.c:4761
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:3883
static const SCIP_Real scalars[]
Definition: misc.c:9462
SCIP_RETCODE SCIPhashsetInsert(SCIP_HASHSET *hashset, BMS_BLKMEM *blkmem, void *element)
Definition: misc.c:3750
SCIP_Bool SCIPintervalHasRoundingControl(void)
SCIP_RETCODE SCIPhashmapSetImage(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3273
static SCIP_RETCODE profileInsertTimepoint(SCIP_PROFILE *profile, int timepoint, int *pos)
Definition: misc.c:6831
#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:10323
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:415
SCIP_RETCODE SCIPrealarrayExtend(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int minidx, int maxidx)
Definition: misc.c:4038
SCIP_VAR ** y
Definition: circlepacking.c:64
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:9987
SCIP_RETCODE SCIPrandomGetSubset(SCIP_RANDNUMGEN *randnumgen, void **set, int nelems, void **subset, int nsubelems)
Definition: misc.c:10122
SCIP_Longint SCIPcalcBinomCoef(int n, int m)
Definition: misc.c:10183
#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:3530
static int primetable[]
Definition: misc.c:1523
static void hashsetInsert(SCIP_HASHSET *hashset, void *element)
Definition: misc.c:3617
int SCIPhashtableGetNEntries(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2727
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:8611
#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:9468
static void btPrintSubtree(SCIP_BTNODE *node, FILE *file, int *nnodes)
Definition: misc.c:8904
void SCIPregressionReset(SCIP_REGRESSION *regression)
Definition: misc.c:399
SCIP_RETCODE SCIPdisjointsetCreate(SCIP_DISJOINTSET **djset, BMS_BLKMEM *blkmem, int ncomponents)
Definition: misc.c:11141
SCIP_RETCODE SCIPrealarraySetVal(SCIP_REALARRAY *realarray, int arraygrowinit, SCIP_Real arraygrowfac, int idx, SCIP_Real val)
Definition: misc.c:4245
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2609
void * SCIPqueueRemove(SCIP_QUEUE *queue)
Definition: misc.c:1080
SCIP_RETCODE SCIPintarrayClear(SCIP_INTARRAY *intarray)
Definition: misc.c:4564
unsigned int SCIPcalcFibHash(SCIP_Real v)
Definition: misc.c:10258
void ** vals
Definition: struct_misc.h:193
SCIP_RETCODE SCIPmultihashRemove(SCIP_MULTIHASH *multihash, void *element)
Definition: misc.c:2126
#define STARTSUCCESSORSSIZE
Definition: misc.c:7523
#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:7201
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:4775
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:3106
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:132
SCIP_Real SCIPhashtableGetLoad(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2744
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:10281
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:439
SCIP_RETCODE SCIPbtCreate(SCIP_BT **tree, BMS_BLKMEM *blkmem)
Definition: misc.c:8869
#define SCIP_ALLOC_TERMINATE(retcode, x, TERM)
Definition: def.h:425
int SCIPhashmapGetImageInt(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3231
static SCIP_RETCODE queueResize(SCIP_QUEUE *queue, int minsize)
Definition: misc.c:924
#define SCIP_CALL_ABORT(x)
Definition: def.h:373
void SCIPcomputeArraysIntersectionPtr(void **array1, int narray1, void **array2, int narray2, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void **intersectarray, int *nintersectarray)
Definition: misc.c:10523
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:7845
int SCIPactivityGetDemand(SCIP_RESOURCEACTIVITY *activity)
Definition: misc.c:6618
void SCIPbtnodeSetData(SCIP_BTNODE *node, void *dataptr)
Definition: misc.c:8816
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:5073
void SCIPdigraphFree(SCIP_DIGRAPH **digraph)
Definition: misc.c:7480
int SCIPprofileGetNTimepoints(SCIP_PROFILE *profile)
Definition: misc.c:6729
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:405
char * SCIPstrtok(char *s, const char *delim, char **ptrptr)
Definition: misc.c:10729
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9032
void SCIPdigraphPrintGml(SCIP_DIGRAPH *digraph, FILE *file)
Definition: misc.c:8496
SCIP_HASHMAPIMAGE image
Definition: struct_misc.h:133
SCIP_RETCODE SCIPintarrayCreate(SCIP_INTARRAY **intarray, BMS_BLKMEM *blkmem)
Definition: misc.c:4352
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:460
void SCIPbtPrintGml(SCIP_BT *tree, FILE *file)
Definition: misc.c:8940
SCIP_Longint SCIPhashtableGetNElements(SCIP_HASHTABLE *hashtable)
Definition: misc.c:2717
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9284
#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:5093
#define PQ_RIGHTCHILD(p)
Definition: misc.c:1223
SCIP_Bool SCIPbtnodeIsLeaf(SCIP_BTNODE *node)
Definition: misc.c:8767
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:11114
void SCIPprofileFree(SCIP_PROFILE **profile)
Definition: misc.c:6681
SCIP_RETCODE SCIPrealarrayClear(SCIP_REALARRAY *realarray)
Definition: misc.c:4193