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
41template <class T> inline void
42CoinCopyN(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*/
99template <class T> inline void
100CoinCopy(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 */
114template <class T> inline void
115CoinDisjointCopyN(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. */
167template <class T> inline void
168CoinDisjointCopy(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
180template <class T> inline T*
181CoinCopyOfArray( 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
197template <class T> inline T*
198CoinCopyOfArrayPartial( 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
214template <class T> inline T*
215CoinCopyOfArray( 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
233template <class T> inline T*
234CoinCopyOfArrayOrZero( 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
256template <class T> inline void
257CoinMemcpyN(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
323template <class T> inline void
324CoinMemcpyN(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. */
343template <class T> inline void
344CoinMemcpy(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. */
358template <class T> inline void
359CoinFillN(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. */
413template <class T> inline void
414CoinFill(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 */
427template <class T> inline void
428CoinZeroN(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
488inline void
489CoinCheckDoubleZero(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
501inline void
502CoinCheckIntZero(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. */
519template <class T> inline void
520CoinZero(T* first, T* last)
521{
522 CoinZeroN(first, last - first);
523}
524
525//#############################################################################
526
527/** Returns strdup or NULL if original NULL */
528inline 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. */
545template <class T> inline T
546CoinMax(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. */
556template <class T> inline T
557CoinMin(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. */
567template <class T> inline T
568CoinAbs(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. */
578template <class T> inline bool
579CoinIsSorted(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. */
627template <class T> inline bool
628CoinIsSorted(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. */
638template <class T> inline void
639CoinIotaN(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. */
693template <class T> inline void
694CoinIota(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). */
706template <class T> inline T *
707CoinDeleteEntriesFromArray(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*/
771inline 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
784inline 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
794inline double CoinDrand48() { return rand() / (double) RAND_MAX; }
795/// Set the seed for the random number generator
796inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); }
797
798#else
799
800/// Return a random number between 0 and 1
801inline double CoinDrand48() { return drand48(); }
802/// Set the seed for the random number generator
803inline 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 */
813inline 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
833inline 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.
856template <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
869template <class T> inline int
870CoinToFile( 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
900template <class T> inline int
901CoinFromFile( 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
927inline 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
942inline int
943CoinStrlenAsInt(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
951class CoinThreadRandom {
952public:
953 /**@name Constructors, destructor */
954
955 //@{
956 /** Default constructor. */
957 CoinThreadRandom()
958 { seed_=12345678;}
959 /** Constructor wih seed. */
960 CoinThreadRandom(int seed)
961 {
962 seed_ = seed;
963 }
964 /** Destructor */
965 ~CoinThreadRandom() {}
966 // Copy
967 CoinThreadRandom(const CoinThreadRandom & rhs)
968 { seed_ = rhs.seed_;}
969 // Assignment
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. */
984 inline void setSeed(int seed)
985 {
986 seed_ = seed;
987 }
988 /** Get seed. */
989 inline unsigned int getSeed() const
990 {
991 return seed_;
992 }
993 /// return a random number
994 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
1004protected:
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
1013class CoinThreadRandom {
1014public:
1015 /**@name Constructors, destructor */
1016
1017 //@{
1018 /** Default constructor. */
1019 CoinThreadRandom()
1020 { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;}
1021 /** Constructor wih seed. */
1022 CoinThreadRandom(const unsigned short seed[3])
1023 { memcpy(seed_,seed,3*sizeof(unsigned short));}
1024 /** Constructor wih 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 */
1033 ~CoinThreadRandom() {}
1034 // Copy
1035 CoinThreadRandom(const CoinThreadRandom & rhs)
1036 { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));}
1037 // Assignment
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. */
1052 inline void setSeed(const unsigned short seed[3])
1053 { memcpy(seed_,seed,3*sizeof(unsigned short));}
1054 /** Set 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
1063 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
1077protected:
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