1 /* $Id: CoinHelperFunctions.hpp 1448 2011-06-19 15:34:41Z stefan $ */
2 // Copyright (C) 2000, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #ifndef CoinHelperFunctions_H
7 #define CoinHelperFunctions_H
8 
9 #include "CoinUtilsConfig.h"
10 
11 #if defined(_MSC_VER)
12 #  include <direct.h>
13 #  define getcwd _getcwd
14 #else
15 #  include <unistd.h>
16 #endif
17 //#define USE_MEMCPY
18 
19 #include <cstdlib>
20 #include <cstdio>
21 #include <algorithm>
22 #include "CoinTypes.hpp"
23 #include "CoinError.hpp"
24 
25 // Compilers can produce better code if they know about __restrict
26 #ifndef COIN_RESTRICT
27 #ifdef COIN_USE_RESTRICT
28 #define COIN_RESTRICT __restrict
29 #else
30 #define COIN_RESTRICT
31 #endif
32 #endif
33 
34 //#############################################################################
35 
36 /** This helper function copies an array to another location using Duff's
37 	device (for a speedup of ~2). The arrays are given by pointers to their
38 	first entries and by the size of the source array. Overlapping arrays are
39 	handled correctly. */
40 
41 template <class T> inline void
CoinCopyN(const T * from,const int size,T * to)42 CoinCopyN(const T* from, const int size, T* to)
43 {
44 	if (size == 0 || from == to)
45 	return;
46 
47 #ifndef NDEBUG
48 	if (size < 0)
49 	throw CoinError("trying to copy negative number of entries",
50 			"CoinCopyN", "");
51 #endif
52 
53 	int n = (size + 7) / 8;
54 	if (to > from) {
55 	const T* downfrom = from + size;
56 	T* downto = to + size;
57 	// Use Duff's device to copy
58 	switch (size % 8) {
59 	case 0: do{     *--downto = *--downfrom;
60 	case 7:         *--downto = *--downfrom;
61 	case 6:         *--downto = *--downfrom;
62 	case 5:         *--downto = *--downfrom;
63 	case 4:         *--downto = *--downfrom;
64 	case 3:         *--downto = *--downfrom;
65 	case 2:         *--downto = *--downfrom;
66 	case 1:         *--downto = *--downfrom;
67 	}while(--n>0);
68 	}
69 	} else {
70 	// Use Duff's device to copy
71 	--from;
72 	--to;
73 	switch (size % 8) {
74 	case 0: do{     *++to = *++from;
75 	case 7:         *++to = *++from;
76 	case 6:         *++to = *++from;
77 	case 5:         *++to = *++from;
78 	case 4:         *++to = *++from;
79 	case 3:         *++to = *++from;
80 	case 2:         *++to = *++from;
81 	case 1:         *++to = *++from;
82 	}while(--n>0);
83 	}
84 	}
85 }
86 
87 //-----------------------------------------------------------------------------
88 
89 /** This helper function copies an array to another location using Duff's
90 	device (for a speedup of ~2). The source array is given by its first and
91 	"after last" entry; the target array is given by its first entry.
92 	Overlapping arrays are handled correctly.
93 
94 	All of the various CoinCopyN variants use an int for size. On 64-bit
95 	architectures, the address diff last-first will be a 64-bit quantity.
96 	Given that everything else uses an int, I'm going to choose to kick
97 	the difference down to int.  -- lh, 100823 --
98 */
99 template <class T> inline void
CoinCopy(const T * first,const T * last,T * to)100 CoinCopy(const T* first, const T* last, T* to)
101 {
102 	CoinCopyN(first, static_cast<int>(last-first), to);
103 }
104 
105 //-----------------------------------------------------------------------------
106 
107 /** This helper function copies an array to another location. The two arrays
108 	must not overlap (otherwise an exception is thrown). For speed 8 entries
109 	are copied at a time. The arrays are given by pointers to their first
110 	entries and by the size of the source array.
111 
112 	Note JJF - the speed claim seems to be false on IA32 so I have added
113 	CoinMemcpyN which can be used for atomic data */
114 template <class T> inline void
CoinDisjointCopyN(const T * from,const int size,T * to)115 CoinDisjointCopyN(const T* from, const int size, T* to)
116 {
117 #ifndef _MSC_VER
118 	if (size == 0 || from == to)
119 	return;
120 
121 #ifndef NDEBUG
122 	if (size < 0)
123 	throw CoinError("trying to copy negative number of entries",
124 			"CoinDisjointCopyN", "");
125 #endif
126 
127 #if 0
128 	/* There is no point to do this test. If to and from are from different
129 	   blocks then dist is undefined, so this can crash correct code. It's
130 	   better to trust the user that the arrays are really disjoint. */
131 	const long dist = to - from;
132 	if (-size < dist && dist < size)
133 	throw CoinError("overlapping arrays", "CoinDisjointCopyN", "");
134 #endif
135 
136 	for (int n = size / 8; n > 0; --n, from += 8, to += 8) {
137 	to[0] = from[0];
138 	to[1] = from[1];
139 	to[2] = from[2];
140 	to[3] = from[3];
141 	to[4] = from[4];
142 	to[5] = from[5];
143 	to[6] = from[6];
144 	to[7] = from[7];
145 	}
146 	switch (size % 8) {
147 	case 7: to[6] = from[6];
148 	case 6: to[5] = from[5];
149 	case 5: to[4] = from[4];
150 	case 4: to[3] = from[3];
151 	case 3: to[2] = from[2];
152 	case 2: to[1] = from[1];
153 	case 1: to[0] = from[0];
154 	case 0: break;
155 	}
156 #else
157 	CoinCopyN(from, size, to);
158 #endif
159 }
160 
161 //-----------------------------------------------------------------------------
162 
163 /** This helper function copies an array to another location. The two arrays
164 	must not overlap (otherwise an exception is thrown). For speed 8 entries
165 	are copied at a time. The source array is given by its first and "after
166 	last" entry; the target array is given by its first entry. */
167 template <class T> inline void
CoinDisjointCopy(const T * first,const T * last,T * to)168 CoinDisjointCopy(const T* first, const T* last,
169 		 T* to)
170 {
171 	CoinDisjointCopyN(first, static_cast<int>(last - first), to);
172 }
173 
174 //-----------------------------------------------------------------------------
175 
176 /*! \brief Return an array of length \p size filled with input from \p array,
177   or null if \p array is null.
178 */
179 
180 template <class T> inline T*
CoinCopyOfArray(const T * array,const int size)181 CoinCopyOfArray( const T * array, const int size)
182 {
183 	if (array) {
184 	T * arrayNew = new T[size];
185 	std::memcpy(arrayNew,array,size*sizeof(T));
186 	return arrayNew;
187 	} else {
188 	return NULL;
189 	}
190 }
191 
192 
193 /*! \brief Return an array of length \p size filled with first copySize from \p array,
194   or null if \p array is null.
195 */
196 
197 template <class T> inline T*
CoinCopyOfArrayPartial(const T * array,const int size,const int copySize)198 CoinCopyOfArrayPartial( const T * array, const int size,const int copySize)
199 {
200 	if (array||size) {
201 	T * arrayNew = new T[size];
202 	assert (copySize<=size);
203 	std::memcpy(arrayNew,array,copySize*sizeof(T));
204 	return arrayNew;
205 	} else {
206 	return NULL;
207 	}
208 }
209 
210 /*! \brief Return an array of length \p size filled with input from \p array,
211   or filled with (scalar) \p value if \p array is null
212 */
213 
214 template <class T> inline T*
CoinCopyOfArray(const T * array,const int size,T value)215 CoinCopyOfArray( const T * array, const int size, T value)
216 {
217 	T * arrayNew = new T[size];
218 	if (array) {
219 		std::memcpy(arrayNew,array,size*sizeof(T));
220 	} else {
221 	int i;
222 	for (i=0;i<size;i++)
223 		arrayNew[i] = value;
224 	}
225 	return arrayNew;
226 }
227 
228 
229 /*! \brief Return an array of length \p size filled with input from \p array,
230   or filled with zero if \p array is null
231 */
232 
233 template <class T> inline T*
CoinCopyOfArrayOrZero(const T * array,const int size)234 CoinCopyOfArrayOrZero( const T * array , const int size)
235 {
236 	T * arrayNew = new T[size];
237 	if (array) {
238 	  std::memcpy(arrayNew,array,size*sizeof(T));
239 	} else {
240 	  std::memset(arrayNew,0,size*sizeof(T));
241 	}
242 	return arrayNew;
243 }
244 
245 
246 //-----------------------------------------------------------------------------
247 
248 /** This helper function copies an array to another location. The two arrays
249 	must not overlap (otherwise an exception is thrown). For speed 8 entries
250 	are copied at a time. The arrays are given by pointers to their first
251 	entries and by the size of the source array.
252 
253 	Note JJF - the speed claim seems to be false on IA32 so I have added
254 	alternative coding if USE_MEMCPY defined*/
255 #ifndef COIN_USE_RESTRICT
256 template <class T> inline void
CoinMemcpyN(const T * from,const int size,T * to)257 CoinMemcpyN(const T* from, const int size, T* to)
258 {
259 #ifndef _MSC_VER
260 #ifdef USE_MEMCPY
261 	// Use memcpy - seems a lot faster on Intel with gcc
262 #ifndef NDEBUG
263 	// Some debug so check
264 	if (size < 0)
265 	throw CoinError("trying to copy negative number of entries",
266 			"CoinMemcpyN", "");
267 
268 #if 0
269 	/* There is no point to do this test. If to and from are from different
270 	   blocks then dist is undefined, so this can crash correct code. It's
271 	   better to trust the user that the arrays are really disjoint. */
272 	const long dist = to - from;
273 	if (-size < dist && dist < size)
274 	throw CoinError("overlapping arrays", "CoinMemcpyN", "");
275 #endif
276 #endif
277 	std::memcpy(to,from,size*sizeof(T));
278 #else
279 	if (size == 0 || from == to)
280 	return;
281 
282 #ifndef NDEBUG
283 	if (size < 0)
284 	throw CoinError("trying to copy negative number of entries",
285 			"CoinMemcpyN", "");
286 #endif
287 
288 #if 0
289 	/* There is no point to do this test. If to and from are from different
290 	   blocks then dist is undefined, so this can crash correct code. It's
291 	   better to trust the user that the arrays are really disjoint. */
292 	const long dist = to - from;
293 	if (-size < dist && dist < size)
294 	throw CoinError("overlapping arrays", "CoinMemcpyN", "");
295 #endif
296 
297 	for (int n = size / 8; n > 0; --n, from += 8, to += 8) {
298 	to[0] = from[0];
299 	to[1] = from[1];
300 	to[2] = from[2];
301 	to[3] = from[3];
302 	to[4] = from[4];
303 	to[5] = from[5];
304 	to[6] = from[6];
305 	to[7] = from[7];
306 	}
307 	switch (size % 8) {
308 	case 7: to[6] = from[6];
309 	case 6: to[5] = from[5];
310 	case 5: to[4] = from[4];
311 	case 4: to[3] = from[3];
312 	case 3: to[2] = from[2];
313 	case 2: to[1] = from[1];
314 	case 1: to[0] = from[0];
315 	case 0: break;
316 	}
317 #endif
318 #else
319 	CoinCopyN(from, size, to);
320 #endif
321 }
322 #else
323 template <class T> inline void
CoinMemcpyN(const T * COIN_RESTRICT from,int size,T * COIN_RESTRICT to)324 CoinMemcpyN(const T * COIN_RESTRICT from, int size, T* COIN_RESTRICT to)
325 {
326 #ifdef USE_MEMCPY
327   std::memcpy(to,from,size*sizeof(T));
328 #else
329   T * COIN_RESTRICT put =  to;
330   const T * COIN_RESTRICT get = from;
331   for ( ; 0<size ; --size)
332 	*put++ = *get++;
333 #endif
334 }
335 #endif
336 
337 //-----------------------------------------------------------------------------
338 
339 /** This helper function copies an array to another location. The two arrays
340 	must not overlap (otherwise an exception is thrown). For speed 8 entries
341 	are copied at a time. The source array is given by its first and "after
342 	last" entry; the target array is given by its first entry. */
343 template <class T> inline void
CoinMemcpy(const T * first,const T * last,T * to)344 CoinMemcpy(const T* first, const T* last,
345 	   T* to)
346 {
347 	CoinMemcpyN(first, static_cast<int>(last - first), to);
348 }
349 
350 //#############################################################################
351 
352 /** This helper function fills an array with a given value. For speed 8 entries
353 	are filled at a time. The array is given by a pointer to its first entry
354 	and its size.
355 
356 	Note JJF - the speed claim seems to be false on IA32 so I have added
357 	CoinZero to allow for memset. */
358 template <class T> inline void
CoinFillN(T * to,const int size,const T value)359 CoinFillN(T* to, const int size, const T value)
360 {
361 	if (size == 0)
362 	return;
363 
364 #ifndef NDEBUG
365 	if (size < 0)
366 	throw CoinError("trying to fill negative number of entries",
367 			"CoinFillN", "");
368 #endif
369 #if 1
370 	for (int n = size / 8; n > 0; --n, to += 8) {
371 	to[0] = value;
372 	to[1] = value;
373 	to[2] = value;
374 	to[3] = value;
375 	to[4] = value;
376 	to[5] = value;
377 	to[6] = value;
378 	to[7] = value;
379 	}
380 	switch (size % 8) {
381 	case 7: to[6] = value;
382 	case 6: to[5] = value;
383 	case 5: to[4] = value;
384 	case 4: to[3] = value;
385 	case 3: to[2] = value;
386 	case 2: to[1] = value;
387 	case 1: to[0] = value;
388 	case 0: break;
389 	}
390 #else
391 	// Use Duff's device to fill
392 	int n = (size + 7) / 8;
393 	--to;
394 	switch (size % 8) {
395 	case 0: do{     *++to = value;
396 	case 7:         *++to = value;
397 	case 6:         *++to = value;
398 	case 5:         *++to = value;
399 	case 4:         *++to = value;
400 	case 3:         *++to = value;
401 	case 2:         *++to = value;
402 	case 1:         *++to = value;
403 	}while(--n>0);
404 	}
405 #endif
406 }
407 
408 //-----------------------------------------------------------------------------
409 
410 /** This helper function fills an array with a given value. For speed 8
411 	entries are filled at a time. The array is given by its first and "after
412 	last" entry. */
413 template <class T> inline void
CoinFill(T * first,T * last,const T value)414 CoinFill(T* first, T* last, const T value)
415 {
416 	CoinFillN(first, last - first, value);
417 }
418 
419 //#############################################################################
420 
421 /** This helper function fills an array with zero. For speed 8 entries
422 	are filled at a time. The array is given by a pointer to its first entry
423 	and its size.
424 
425 	Note JJF - the speed claim seems to be false on IA32 so I have allowed
426 	for memset as an alternative */
427 template <class T> inline void
CoinZeroN(T * to,const int size)428 CoinZeroN(T* to, const int size)
429 {
430 #ifdef USE_MEMCPY
431 	// Use memset - seems faster on Intel with gcc
432 #ifndef NDEBUG
433 	// Some debug so check
434 	if (size < 0)
435 	throw CoinError("trying to fill negative number of entries",
436 			"CoinZeroN", "");
437 #endif
438 	memset(to,0,size*sizeof(T));
439 #else
440 	if (size == 0)
441 	return;
442 
443 #ifndef NDEBUG
444 	if (size < 0)
445 	throw CoinError("trying to fill negative number of entries",
446 			"CoinZeroN", "");
447 #endif
448 #if 1
449 	for (int n = size / 8; n > 0; --n, to += 8) {
450 	to[0] = 0;
451 	to[1] = 0;
452 	to[2] = 0;
453 	to[3] = 0;
454 	to[4] = 0;
455 	to[5] = 0;
456 	to[6] = 0;
457 	to[7] = 0;
458 	}
459 	switch (size % 8) {
460 	case 7: to[6] = 0;
461 	case 6: to[5] = 0;
462 	case 5: to[4] = 0;
463 	case 4: to[3] = 0;
464 	case 3: to[2] = 0;
465 	case 2: to[1] = 0;
466 	case 1: to[0] = 0;
467 	case 0: break;
468 	}
469 #else
470 	// Use Duff's device to fill
471 	int n = (size + 7) / 8;
472 	--to;
473 	switch (size % 8) {
474 	case 0: do{     *++to = 0;
475 	case 7:         *++to = 0;
476 	case 6:         *++to = 0;
477 	case 5:         *++to = 0;
478 	case 4:         *++to = 0;
479 	case 3:         *++to = 0;
480 	case 2:         *++to = 0;
481 	case 1:         *++to = 0;
482 	}while(--n>0);
483 	}
484 #endif
485 #endif
486 }
487 /// This Debug helper function checks an array is all zero
488 inline void
CoinCheckDoubleZero(double * to,const int size)489 CoinCheckDoubleZero(double * to, const int size)
490 {
491 	int n=0;
492 	for (int j=0;j<size;j++) {
493 	if (to[j])
494 		n++;
495 	}
496 	if (n) {
497 	printf("array of length %d should be zero has %d nonzero\n",size,n);
498 	}
499 }
500 /// This Debug helper function checks an array is all zero
501 inline void
CoinCheckIntZero(int * to,const int size)502 CoinCheckIntZero(int * to, const int size)
503 {
504 	int n=0;
505 	for (int j=0;j<size;j++) {
506 	if (to[j])
507 		n++;
508 	}
509 	if (n) {
510 	printf("array of length %d should be zero has %d nonzero\n",size,n);
511 	}
512 }
513 
514 //-----------------------------------------------------------------------------
515 
516 /** This helper function fills an array with a given value. For speed 8
517 	entries are filled at a time. The array is given by its first and "after
518 	last" entry. */
519 template <class T> inline void
CoinZero(T * first,T * last)520 CoinZero(T* first, T* last)
521 {
522 	CoinZeroN(first, last - first);
523 }
524 
525 //#############################################################################
526 
527 /** Returns strdup or NULL if original NULL */
CoinStrdup(const char * name)528 inline char * CoinStrdup(const char * name)
529 {
530   char* dup = nullptr;
531   if (name) {
532 	const int len = static_cast<int>(strlen(name));
533 	dup = static_cast<char*>(malloc(len+1));
534 	CoinMemcpyN(name, len, dup);
535 	dup[len] = 0;
536   }
537   return dup;
538 }
539 
540 //#############################################################################
541 
542 /** Return the larger (according to <code>operator<()</code> of the arguments.
543 	This function was introduced because for some reason compiler tend to
544 	handle the <code>max()</code> function differently. */
545 template <class T> inline T
CoinMax(const T x1,const T x2)546 CoinMax(const T x1, const T x2)
547 {
548 	return (x1 > x2) ? x1 : x2;
549 }
550 
551 //-----------------------------------------------------------------------------
552 
553 /** Return the smaller (according to <code>operator<()</code> of the arguments.
554 	This function was introduced because for some reason compiler tend to
555 	handle the min() function differently. */
556 template <class T> inline T
CoinMin(const T x1,const T x2)557 CoinMin(const T x1, const T x2)
558 {
559 	return (x1 < x2) ? x1 : x2;
560 }
561 
562 //-----------------------------------------------------------------------------
563 
564 /** Return the absolute value of the argument. This function was introduced
565 	because for some reason compiler tend to handle the abs() function
566 	differently. */
567 template <class T> inline T
CoinAbs(const T value)568 CoinAbs(const T value)
569 {
570 	return value<0 ? -value : value;
571 }
572 
573 //#############################################################################
574 
575 /** This helper function tests whether the entries of an array are sorted
576 	according to operator<. The array is given by a pointer to its first entry
577 	and by its size. */
578 template <class T> inline bool
CoinIsSorted(const T * first,const int size)579 CoinIsSorted(const T* first, const int size)
580 {
581 	if (size == 0)
582 	return true;
583 
584 #ifndef NDEBUG
585 	if (size < 0)
586 	throw CoinError("negative number of entries", "CoinIsSorted", "");
587 #endif
588 #if 1
589 	// size1 is the number of comparisons to be made
590 	const int size1 = size  - 1;
591 	for (int n = size1 / 8; n > 0; --n, first += 8) {
592 	if (first[8] < first[7]) return false;
593 	if (first[7] < first[6]) return false;
594 	if (first[6] < first[5]) return false;
595 	if (first[5] < first[4]) return false;
596 	if (first[4] < first[3]) return false;
597 	if (first[3] < first[2]) return false;
598 	if (first[2] < first[1]) return false;
599 	if (first[1] < first[0]) return false;
600 	}
601 
602 	switch (size1 % 8) {
603 	case 7: if (first[7] < first[6]) return false;
604 	case 6: if (first[6] < first[5]) return false;
605 	case 5: if (first[5] < first[4]) return false;
606 	case 4: if (first[4] < first[3]) return false;
607 	case 3: if (first[3] < first[2]) return false;
608 	case 2: if (first[2] < first[1]) return false;
609 	case 1: if (first[1] < first[0]) return false;
610 	case 0: break;
611 	}
612 #else
613 	const T* next = first;
614 	const T* last = first + size;
615 	for (++next; next != last; first = next, ++next)
616 	if (*next < *first)
617 		return false;
618 #endif
619 	return true;
620 }
621 
622 //-----------------------------------------------------------------------------
623 
624 /** This helper function tests whether the entries of an array are sorted
625 	according to operator<. The array is given by its first and "after
626 	last" entry. */
627 template <class T> inline bool
CoinIsSorted(const T * first,const T * last)628 CoinIsSorted(const T* first, const T* last)
629 {
630 	return CoinIsSorted(first, static_cast<int>(last - first));
631 }
632 
633 //#############################################################################
634 
635 /** This helper function fills an array with the values init, init+1, init+2,
636 	etc. For speed 8 entries are filled at a time. The array is given by a
637 	pointer to its first entry and its size. */
638 template <class T> inline void
CoinIotaN(T * first,const int size,T init)639 CoinIotaN(T* first, const int size, T init)
640 {
641 	if (size == 0)
642 	return;
643 
644 #ifndef NDEBUG
645 	if (size < 0)
646 	throw CoinError("negative number of entries", "CoinIotaN", "");
647 #endif
648 #if 1
649 	for (int n = size / 8; n > 0; --n, first += 8, init += 8) {
650 	first[0] = init;
651 	first[1] = init + 1;
652 	first[2] = init + 2;
653 	first[3] = init + 3;
654 	first[4] = init + 4;
655 	first[5] = init + 5;
656 	first[6] = init + 6;
657 	first[7] = init + 7;
658 	}
659 	switch (size % 8) {
660 	case 7: first[6] = init + 6;
661 	case 6: first[5] = init + 5;
662 	case 5: first[4] = init + 4;
663 	case 4: first[3] = init + 3;
664 	case 3: first[2] = init + 2;
665 	case 2: first[1] = init + 1;
666 	case 1: first[0] = init;
667 	case 0: break;
668 	}
669 #else
670 	// Use Duff's device to fill
671 	int n = (size + 7) / 8;
672 	--first;
673 	--init;
674 	switch (size % 8) {
675 	case 0: do{     *++first = ++init;
676 	case 7:         *++first = ++init;
677 	case 6:         *++first = ++init;
678 	case 5:         *++first = ++init;
679 	case 4:         *++first = ++init;
680 	case 3:         *++first = ++init;
681 	case 2:         *++first = ++init;
682 	case 1:         *++first = ++init;
683 	}while(--n>0);
684 	}
685 #endif
686 }
687 
688 //-----------------------------------------------------------------------------
689 
690 /** This helper function fills an array with the values init, init+1, init+2,
691 	etc. For speed 8 entries are filled at a time. The array is given by its
692 	first and "after last" entry. */
693 template <class T> inline void
CoinIota(T * first,const T * last,T init)694 CoinIota(T* first, const T* last, T init)
695 {
696 	CoinIotaN(first, last-first, init);
697 }
698 
699 //#############################################################################
700 
701 /** This helper function deletes certain entries from an array. The array is
702 	given by pointers to its first and "after last" entry (first two
703 	arguments). The positions of the entries to be deleted are given in the
704 	integer array specified by the last two arguments (again, first and "after
705 	last" entry). */
706 template <class T> inline T *
CoinDeleteEntriesFromArray(T * arrayFirst,T * arrayLast,const int * firstDelPos,const int * lastDelPos)707 CoinDeleteEntriesFromArray(T * arrayFirst, T * arrayLast,
708 			   const int * firstDelPos, const int * lastDelPos)
709 {
710 	int delNum = static_cast<int>(lastDelPos - firstDelPos);
711 	if (delNum == 0)
712 	return arrayLast;
713 
714 	if (delNum < 0)
715 	throw CoinError("trying to delete negative number of entries",
716 			"CoinDeleteEntriesFromArray", "");
717 
718 	int * delSortedPos = nullptr;
719 	if (! (CoinIsSorted(firstDelPos, lastDelPos) &&
720 	   std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) {
721 	// the positions of the to be deleted is either not sorted or not unique
722 	delSortedPos = new int[delNum];
723 	CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos);
724 	std::sort(delSortedPos, delSortedPos + delNum);
725 	delNum = static_cast<int>(std::unique(delSortedPos,
726 				  delSortedPos+delNum) - delSortedPos);
727 	}
728 	const int * delSorted = delSortedPos ? delSortedPos : firstDelPos;
729 
730 	const int last = delNum - 1;
731 	int size = delSorted[0];
732 	for (int i = 0; i < last; ++i) {
733 	const int copyFirst = delSorted[i] + 1;
734 	const int copyLast = delSorted[i+1];
735 	CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
736 		 arrayFirst + size);
737 	size += copyLast - copyFirst;
738 	}
739 	const int copyFirst = delSorted[last] + 1;
740 	const int copyLast = static_cast<int>(arrayLast - arrayFirst);
741 	CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
742 		 arrayFirst + size);
743 	size += copyLast - copyFirst;
744 
745 	if (delSortedPos)
746 	delete[] delSortedPos;
747 
748 	return arrayFirst + size;
749 }
750 
751 //#############################################################################
752 
753 #define COIN_OWN_RANDOM_32
754 
755 #if defined COIN_OWN_RANDOM_32
756 /* Thanks to Stefano Gliozzi for providing an operating system
757    independent random number generator.  */
758 
759 /*! \brief Return a random number between 0 and 1
760 
761   A platform-independent linear congruential generator. For a given seed, the
762   generated sequence is always the same regardless of the (32-bit)
763   architecture. This allows to build & test in different environments, getting
764   in most cases the same optimization path.
765 
766   Set \p isSeed to true and supply an integer seed to set the seed
767   (vid. #CoinSeedRandom)
768 
769   \todo Anyone want to volunteer an upgrade for 64-bit architectures?
770 */
CoinDrand48(bool isSeed=false,unsigned int seed=1)771 inline double CoinDrand48 (bool isSeed = false, unsigned int seed = 1)
772 {
773   static unsigned int last = 123456;
774   if (isSeed) {
775 	last = seed;
776   } else {
777 	last = 1664525*last+1013904223;
778 	return ((static_cast<double> (last))/4294967296.0);
779   }
780   return (0.0);
781 }
782 
783 /// Set the seed for the random number generator
CoinSeedRandom(int iseed)784 inline void CoinSeedRandom(int iseed)
785 {
786   CoinDrand48(true, iseed);
787 }
788 
789 #else // COIN_OWN_RANDOM_32
790 
791 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
792 
793 /// Return a random number between 0 and 1
CoinDrand48()794 inline double CoinDrand48() { return rand() / (double) RAND_MAX; }
795 /// Set the seed for the random number generator
CoinSeedRandom(int iseed)796 inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); }
797 
798 #else
799 
800 /// Return a random number between 0 and 1
CoinDrand48()801 inline double CoinDrand48() { return drand48(); }
802 /// Set the seed for the random number generator
CoinSeedRandom(int iseed)803 inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); }
804 
805 #endif
806 
807 #endif // COIN_OWN_RANDOM_32
808 
809 //#############################################################################
810 
811 /** This function figures out whether file names should contain slashes or
812 	backslashes as directory separator */
CoinFindDirSeparator()813 inline char CoinFindDirSeparator()
814 {
815 	int size = 1000;
816 	char* buf = nullptr;
817 	while (true) {
818 		buf = new char[size];
819 		if (getcwd(buf, size))
820 			break;
821 		delete[] buf;
822 		buf = nullptr;
823 		size = 2*size;
824 	}
825 	// if first char is '/' then it's unix and the dirsep is '/'. otherwise we
826 	// assume it's dos and the dirsep is '\'
827 	char dirsep = buf[0] == '/' ? '/' : '\\';
828 	delete[] buf;
829 	return dirsep;
830 }
831 //#############################################################################
832 
CoinStrNCaseCmp(const char * s0,const char * s1,const size_t len)833 inline int CoinStrNCaseCmp(const char* s0, const char* s1,
834 			   const size_t len)
835 {
836 	for (size_t i = 0; i < len; ++i) {
837 	if (s0[i] == 0) {
838 		return s1[i] == 0 ? 0 : -1;
839 	}
840 	if (s1[i] == 0) {
841 		return 1;
842 	}
843 	const int c0 = tolower(s0[i]);
844 	const int c1 = tolower(s1[i]);
845 	if (c0 < c1)
846 		return -1;
847 	if (c0 > c1)
848 		return 1;
849 	}
850 	return 0;
851 }
852 
853 //#############################################################################
854 
855 /// Swap the arguments.
CoinSwap(T & x,T & y)856 template <class T> inline void CoinSwap (T &x, T &y)
857 {
858 	T t = x;
859 	x = y;
860 	y = t;
861 }
862 
863 //#############################################################################
864 
865 /** This helper function copies an array to file
866 	Returns 0 if OK, 1 if bad write.
867 */
868 
869 template <class T> inline int
CoinToFile(const T * array,CoinBigIndex size,FILE * fp)870 CoinToFile( const T* array, CoinBigIndex size, FILE * fp)
871 {
872 	CoinBigIndex numberWritten;
873 	if (array&&size) {
874 	numberWritten =
875 		static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp));
876 	if (numberWritten!=1)
877 		return 1;
878 	numberWritten =
879 		static_cast<CoinBigIndex>(fwrite(array,sizeof(T),size_t(size),fp));
880 	if (numberWritten!=size)
881 		return 1;
882 	} else {
883 	size = 0;
884 	numberWritten =
885 		static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp));
886 	if (numberWritten!=1)
887 		return 1;
888 	}
889 	return 0;
890 }
891 
892 //#############################################################################
893 
894 /** This helper function copies an array from file and creates with new.
895 	Passed in array is ignored i.e. not deleted.
896 	But if NULL and size does not match and newSize 0 then leaves as NULL and 0
897 	Returns 0 if OK, 1 if bad read, 2 if size did not match.
898 */
899 
900 template <class T> inline int
CoinFromFile(T * & array,CoinBigIndex size,FILE * fp,CoinBigIndex & newSize)901 CoinFromFile( T* &array, CoinBigIndex size, FILE * fp, CoinBigIndex & newSize)
902 {
903 	CoinBigIndex numberRead;
904 	numberRead =
905 		static_cast<CoinBigIndex>(fread(&newSize,sizeof(int),1,fp));
906 	if (numberRead!=1)
907 	return 1;
908 	int returnCode=0;
909 	if (size!=newSize&&(newSize||array))
910 	returnCode=2;
911 	if (newSize) {
912 	array = new T [newSize];
913 	numberRead =
914 		static_cast<CoinBigIndex>(fread(array,sizeof(T),newSize,fp));
915 	if (numberRead!=newSize)
916 		returnCode=1;
917 	} else {
918 	array = NULL;
919 	}
920 	return returnCode;
921 }
922 
923 //#############################################################################
924 
925 /// Cube Root
926 #if 0
927 inline double CoinCbrt(double x)
928 {
929 #if defined(_MSC_VER)
930 	return pow(x,(1./3.));
931 #else
932 	return cbrt(x);
933 #endif
934 }
935 #endif
936 
937 //-----------------------------------------------------------------------------
938 
939 /// This helper returns "sizeof" as an int
940 #define CoinSizeofAsInt(type) (static_cast<int>(sizeof(type)))
941 /// This helper returns "strlen" as an int
942 inline int
CoinStrlenAsInt(const char * string)943 CoinStrlenAsInt(const char * string)
944 {
945 	return static_cast<int>(strlen(string));
946 }
947 
948 /** Class for thread specific random numbers
949 */
950 #if defined COIN_OWN_RANDOM_32
951 class CoinThreadRandom  {
952 public:
953   /**@name Constructors, destructor */
954 
955   //@{
956   /** Default constructor. */
CoinThreadRandom()957   CoinThreadRandom()
958   { seed_=12345678;}
959   /** Constructor wih seed. */
CoinThreadRandom(int seed)960   CoinThreadRandom(int seed)
961   {
962 	seed_ = seed;
963   }
964   /** Destructor */
~CoinThreadRandom()965   ~CoinThreadRandom() {}
966   // Copy
CoinThreadRandom(const CoinThreadRandom & rhs)967   CoinThreadRandom(const CoinThreadRandom & rhs)
968   { seed_ = rhs.seed_;}
969   // Assignment
operator =(const CoinThreadRandom & rhs)970   CoinThreadRandom& operator=(const CoinThreadRandom & rhs)
971   {
972 	if (this != &rhs) {
973 	  seed_ = rhs.seed_;
974 	}
975 	return *this;
976   }
977 
978   //@}
979 
980   /**@name Sets/gets */
981 
982   //@{
983   /** Set seed. */
setSeed(int seed)984   inline void setSeed(int seed)
985   {
986 	seed_ = seed;
987   }
988   /** Get seed. */
getSeed() const989   inline unsigned int getSeed() const
990   {
991 	return seed_;
992   }
993   /// return a random number
randomDouble() const994   inline double randomDouble() const
995   {
996 	double retVal;
997 	seed_ = 1664525*(seed_)+1013904223;
998 	retVal = ((static_cast<double> (seed_))/4294967296.0);
999 	return retVal;
1000   }
1001   //@}
1002 
1003 
1004 protected:
1005   /**@name Data members
1006 	 The data members are protected to allow access for derived classes. */
1007   //@{
1008   /// Current seed
1009   mutable unsigned int seed_;
1010   //@}
1011 };
1012 #else
1013 class CoinThreadRandom  {
1014 public:
1015   /**@name Constructors, destructor */
1016 
1017   //@{
1018   /** Default constructor. */
CoinThreadRandom()1019   CoinThreadRandom()
1020   { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;}
1021   /** Constructor wih seed. */
CoinThreadRandom(const unsigned short seed[3])1022   CoinThreadRandom(const unsigned short seed[3])
1023   { memcpy(seed_,seed,3*sizeof(unsigned short));}
1024   /** Constructor wih seed. */
CoinThreadRandom(int seed)1025   CoinThreadRandom(int seed)
1026   {
1027 	union { int i[2]; unsigned short int s[4];} put;
1028 	put.i[0]=seed;
1029 	put.i[1]=seed;
1030 	memcpy(seed_,put.s,3*sizeof(unsigned short));
1031   }
1032   /** Destructor */
~CoinThreadRandom()1033   ~CoinThreadRandom() {}
1034   // Copy
CoinThreadRandom(const CoinThreadRandom & rhs)1035   CoinThreadRandom(const CoinThreadRandom & rhs)
1036   { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));}
1037   // Assignment
operator =(const CoinThreadRandom & rhs)1038   CoinThreadRandom& operator=(const CoinThreadRandom & rhs)
1039   {
1040 	if (this != &rhs) {
1041 	  memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));
1042 	}
1043 	return *this;
1044   }
1045 
1046   //@}
1047 
1048   /**@name Sets/gets */
1049 
1050   //@{
1051   /** Set seed. */
setSeed(const unsigned short seed[3])1052   inline void setSeed(const unsigned short seed[3])
1053   { memcpy(seed_,seed,3*sizeof(unsigned short));}
1054   /** Set seed. */
setSeed(int seed)1055   inline void setSeed(int seed)
1056   {
1057 	union { int i[2]; unsigned short int s[4];} put;
1058 	put.i[0]=seed;
1059 	put.i[1]=seed;
1060 	memcpy(seed_,put.s,3*sizeof(unsigned short));
1061   }
1062   /// return a random number
randomDouble() const1063   inline double randomDouble() const
1064   {
1065 	double retVal;
1066 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
1067 	retVal=rand();
1068 	retVal=retVal/(double) RAND_MAX;
1069 #else
1070 	retVal = erand48(seed_);
1071 #endif
1072 	return retVal;
1073   }
1074   //@}
1075 
1076 
1077 protected:
1078   /**@name Data members
1079 	 The data members are protected to allow access for derived classes. */
1080   //@{
1081   /// Current seed
1082   mutable unsigned short seed_[3];
1083   //@}
1084 };
1085 #endif
1086 #ifndef COIN_DETAIL
1087 #define COIN_DETAIL_PRINT(s) {}
1088 #else
1089 #define COIN_DETAIL_PRINT(s) s
1090 #endif
1091 #endif
1092