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