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