CoinUtils  2.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CoinHelperFunctions.hpp
Go to the documentation of this file.
1 /* $Id: CoinHelperFunctions.hpp 1581 2013-04-06 12:48:50Z 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 
41 template <class T> inline void
42 CoinCopyN(register const T* from, const int size, register 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  register int n = (size + 7) / 8;
54  if (to > from) {
55  register const T* downfrom = from + size;
56  register 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 
99 template <class T> inline void
100 CoinCopy(register const T* first, register const T* last, register T* to)
101 {
102  CoinCopyN(first, static_cast<int>(last-first), to);
103 }
104 
105 //-----------------------------------------------------------------------------
106 
114 template <class T> inline void
115 CoinDisjointCopyN(register const T* from, const int size, register 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 (register 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 
167 template <class T> inline void
168 CoinDisjointCopy(register const T* first, register const T* last,
169  register T* to)
170 {
171  CoinDisjointCopyN(first, static_cast<int>(last - first), to);
172 }
173 
174 //-----------------------------------------------------------------------------
175 
180 template <class T> inline T*
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 
197 template <class T> inline T*
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 
214 template <class T> inline T*
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 
233 template <class T> inline T*
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 
255 #ifndef COIN_USE_RESTRICT
256 template <class T> inline void
257 CoinMemcpyN(register const T* from, const int size, register 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 (register 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
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 
343 template <class T> inline void
344 CoinMemcpy(register const T* first, register const T* last,
345  register T* to)
346 {
347  CoinMemcpyN(first, static_cast<int>(last - first), to);
348 }
349 
350 //#############################################################################
351 
358 template <class T> inline void
359 CoinFillN(register T* to, const int size, register 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 (register 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  register 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 
413 template <class T> inline void
414 CoinFill(register T* first, register T* last, const T value)
415 {
416  CoinFillN(first, last - first, value);
417 }
418 
419 //#############################################################################
420 
427 template <class T> inline void
428 CoinZeroN(register 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 (register 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  register 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 }
488 inline void
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 }
501 inline void
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 
519 template <class T> inline void
520 CoinZero(register T* first, register T* last)
521 {
522  CoinZeroN(first, last - first);
523 }
524 
525 //#############################################################################
526 
528 inline char * CoinStrdup(const char * name)
529 {
530  char* dup = NULL;
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 
545 template <class T> inline T
546 CoinMax(register const T x1, register const T x2)
547 {
548  return (x1 > x2) ? x1 : x2;
549 }
550 
551 //-----------------------------------------------------------------------------
552 
556 template <class T> inline T
557 CoinMin(register const T x1, register const T x2)
558 {
559  return (x1 < x2) ? x1 : x2;
560 }
561 
562 //-----------------------------------------------------------------------------
563 
567 template <class T> inline T
568 CoinAbs(const T value)
569 {
570  return value<0 ? -value : value;
571 }
572 
573 //#############################################################################
574 
578 template <class T> inline bool
579 CoinIsSorted(register 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 (register 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  register const T* next = first;
614  register 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 
627 template <class T> inline bool
628 CoinIsSorted(register const T* first, register const T* last)
629 {
630  return CoinIsSorted(first, static_cast<int>(last - first));
631 }
632 
633 //#############################################################################
634 
638 template <class T> inline void
639 CoinIotaN(register T* first, const int size, register 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 (register 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  register 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 
693 template <class T> inline void
694 CoinIota(T* first, const T* last, T init)
695 {
696  CoinIotaN(first, last-first, init);
697 }
698 
699 //#############################################################################
700 
706 template <class T> inline T *
707 CoinDeleteEntriesFromArray(register T * arrayFirst, register 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 = NULL;
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 
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 
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 
794 inline double CoinDrand48() { return rand() / (double) RAND_MAX; }
796 inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); }
797 
798 #else
799 
801 inline double CoinDrand48() { return drand48(); }
803 inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); }
804 
805 #endif
806 
807 #endif // COIN_OWN_RANDOM_32
808 
809 //#############################################################################
810 
813 inline char CoinFindDirSeparator()
814 {
815  int size = 1000;
816  char* buf = 0;
817  while (true) {
818  buf = new char[size];
819  if (getcwd(buf, size))
820  break;
821  delete[] buf;
822  buf = 0;
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 
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 
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 
869 template <class T> inline int
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 
900 template <class T> inline int
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 
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 
940 #define CoinSizeofAsInt(type) (static_cast<int>(sizeof(type)))
941 
942 inline int
943 CoinStrlenAsInt(const char * string)
944 {
945  return static_cast<int>(strlen(string));
946 }
947 
950 #if defined COIN_OWN_RANDOM_32
952 public:
958  { seed_=12345678;}
961  {
962  seed_ = seed;
963  }
966  // Copy
968  { seed_ = rhs.seed_;}
969  // Assignment
971  {
972  if (this != &rhs) {
973  seed_ = rhs.seed_;
974  }
975  return *this;
976  }
977 
979 
984  inline void setSeed(int seed)
985  {
986  seed_ = seed;
987  }
989  inline unsigned int getSeed() const
990  {
991  return seed_;
992  }
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  }
1002  inline void randomize(int n=0)
1003  {
1004  if (!n)
1005  n=seed_ & 255;
1006  for (int i=0;i<n;i++)
1007  randomDouble();
1008  }
1010 
1011 
1012 protected:
1016 
1017  mutable unsigned int seed_;
1019 };
1020 #else
1021 class CoinThreadRandom {
1022 public:
1028  { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;}
1030  CoinThreadRandom(const unsigned short seed[3])
1031  { memcpy(seed_,seed,3*sizeof(unsigned short));}
1033  CoinThreadRandom(int seed)
1034  {
1035  union { int i[2]; unsigned short int s[4];} put;
1036  put.i[0]=seed;
1037  put.i[1]=seed;
1038  memcpy(seed_,put.s,3*sizeof(unsigned short));
1039  }
1041  ~CoinThreadRandom() {}
1042  // Copy
1043  CoinThreadRandom(const CoinThreadRandom & rhs)
1044  { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));}
1045  // Assignment
1047  {
1048  if (this != &rhs) {
1049  memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));
1050  }
1051  return *this;
1052  }
1053 
1055 
1060  inline void setSeed(const unsigned short seed[3])
1061  { memcpy(seed_,seed,3*sizeof(unsigned short));}
1063  inline void setSeed(int seed)
1064  {
1065  union { int i[2]; unsigned short int s[4];} put;
1066  put.i[0]=seed;
1067  put.i[1]=seed;
1068  memcpy(seed_,put.s,3*sizeof(unsigned short));
1069  }
1071  inline double randomDouble() const
1072  {
1073  double retVal;
1074 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
1075  retVal=rand();
1076  retVal=retVal/(double) RAND_MAX;
1077 #else
1078  retVal = erand48(seed_);
1079 #endif
1080  return retVal;
1081  }
1083  inline void randomize(int n=0)
1084  {
1085  if (!n) {
1086  n=seed_[0]+seed_[1]+seed_[2];
1087  n &= 255;
1088  }
1089  for (int i=0;i<n;i++)
1090  randomDouble();
1091  }
1093 
1094 
1095 protected:
1099 
1100  mutable unsigned short seed_[3];
1102 };
1103 #endif
1104 #ifndef COIN_DETAIL
1105 #define COIN_DETAIL_PRINT(s) {}
1106 #else
1107 #define COIN_DETAIL_PRINT(s) s
1108 #endif
1109 #endif