00001
00002
00003
00004
00005
00006 #ifndef CoinHelperFunctions_H
00007 #define CoinHelperFunctions_H
00008
00009 #include "CoinUtilsConfig.h"
00010
00011 #if defined(_MSC_VER)
00012 # include <direct.h>
00013 # include <cctype>
00014 # define getcwd _getcwd
00015 #else
00016 # include <unistd.h>
00017 #endif
00018
00019
00020 #include <cstdlib>
00021 #include <cstdio>
00022 #include <algorithm>
00023 #include "CoinTypes.hpp"
00024 #include "CoinError.hpp"
00025
00026
00027 #ifndef COIN_RESTRICT
00028 #ifdef COIN_USE_RESTRICT
00029 #define COIN_RESTRICT __restrict
00030 #else
00031 #define COIN_RESTRICT
00032 #endif
00033 #endif
00034
00035
00036
00042 template <class T> inline void
00043 CoinCopyN(register const T* from, const int size, register T* to)
00044 {
00045 if (size == 0 || from == to)
00046 return;
00047
00048 #ifndef NDEBUG
00049 if (size < 0)
00050 throw CoinError("trying to copy negative number of entries",
00051 "CoinCopyN", "");
00052 #endif
00053
00054 register int n = (size + 7) / 8;
00055 if (to > from) {
00056 register const T* downfrom = from + size;
00057 register T* downto = to + size;
00058
00059 switch (size % 8) {
00060 case 0: do{ *--downto = *--downfrom;
00061 case 7: *--downto = *--downfrom;
00062 case 6: *--downto = *--downfrom;
00063 case 5: *--downto = *--downfrom;
00064 case 4: *--downto = *--downfrom;
00065 case 3: *--downto = *--downfrom;
00066 case 2: *--downto = *--downfrom;
00067 case 1: *--downto = *--downfrom;
00068 }while(--n>0);
00069 }
00070 } else {
00071
00072 --from;
00073 --to;
00074 switch (size % 8) {
00075 case 0: do{ *++to = *++from;
00076 case 7: *++to = *++from;
00077 case 6: *++to = *++from;
00078 case 5: *++to = *++from;
00079 case 4: *++to = *++from;
00080 case 3: *++to = *++from;
00081 case 2: *++to = *++from;
00082 case 1: *++to = *++from;
00083 }while(--n>0);
00084 }
00085 }
00086 }
00087
00088
00089
00100 template <class T> inline void
00101 CoinCopy(register const T* first, register const T* last, register T* to)
00102 {
00103 CoinCopyN(first, static_cast<int>(last-first), to);
00104 }
00105
00106
00107
00115 template <class T> inline void
00116 CoinDisjointCopyN(register const T* from, const int size, register T* to)
00117 {
00118 #ifndef _MSC_VER
00119 if (size == 0 || from == to)
00120 return;
00121
00122 #ifndef NDEBUG
00123 if (size < 0)
00124 throw CoinError("trying to copy negative number of entries",
00125 "CoinDisjointCopyN", "");
00126 #endif
00127
00128 #if 0
00129
00130
00131
00132 const long dist = to - from;
00133 if (-size < dist && dist < size)
00134 throw CoinError("overlapping arrays", "CoinDisjointCopyN", "");
00135 #endif
00136
00137 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00138 to[0] = from[0];
00139 to[1] = from[1];
00140 to[2] = from[2];
00141 to[3] = from[3];
00142 to[4] = from[4];
00143 to[5] = from[5];
00144 to[6] = from[6];
00145 to[7] = from[7];
00146 }
00147 switch (size % 8) {
00148 case 7: to[6] = from[6];
00149 case 6: to[5] = from[5];
00150 case 5: to[4] = from[4];
00151 case 4: to[3] = from[3];
00152 case 3: to[2] = from[2];
00153 case 2: to[1] = from[1];
00154 case 1: to[0] = from[0];
00155 case 0: break;
00156 }
00157 #else
00158 CoinCopyN(from, size, to);
00159 #endif
00160 }
00161
00162
00163
00168 template <class T> inline void
00169 CoinDisjointCopy(register const T* first, register const T* last,
00170 register T* to)
00171 {
00172 CoinDisjointCopyN(first, static_cast<int>(last - first), to);
00173 }
00174
00175
00176
00181 template <class T> inline T*
00182 CoinCopyOfArray( const T * array, const int size)
00183 {
00184 if (array) {
00185 T * arrayNew = new T[size];
00186 std::memcpy(arrayNew,array,size*sizeof(T));
00187 return arrayNew;
00188 } else {
00189 return NULL;
00190 }
00191 }
00192
00193
00198 template <class T> inline T*
00199 CoinCopyOfArrayPartial( const T * array, const int size,const int copySize)
00200 {
00201 if (array||size) {
00202 T * arrayNew = new T[size];
00203 assert (copySize<=size);
00204 std::memcpy(arrayNew,array,copySize*sizeof(T));
00205 return arrayNew;
00206 } else {
00207 return NULL;
00208 }
00209 }
00210
00215 template <class T> inline T*
00216 CoinCopyOfArray( const T * array, const int size, T value)
00217 {
00218 T * arrayNew = new T[size];
00219 if (array) {
00220 std::memcpy(arrayNew,array,size*sizeof(T));
00221 } else {
00222 int i;
00223 for (i=0;i<size;i++)
00224 arrayNew[i] = value;
00225 }
00226 return arrayNew;
00227 }
00228
00229
00234 template <class T> inline T*
00235 CoinCopyOfArrayOrZero( const T * array , const int size)
00236 {
00237 T * arrayNew = new T[size];
00238 if (array) {
00239 std::memcpy(arrayNew,array,size*sizeof(T));
00240 } else {
00241 std::memset(arrayNew,0,size*sizeof(T));
00242 }
00243 return arrayNew;
00244 }
00245
00246
00247
00248
00256 #ifndef COIN_USE_RESTRICT
00257 template <class T> inline void
00258 CoinMemcpyN(register const T* from, const int size, register T* to)
00259 {
00260 #ifndef _MSC_VER
00261 #ifdef USE_MEMCPY
00262
00263 #ifndef NDEBUG
00264
00265 if (size < 0)
00266 throw CoinError("trying to copy negative number of entries",
00267 "CoinMemcpyN", "");
00268
00269 #if 0
00270
00271
00272
00273 const long dist = to - from;
00274 if (-size < dist && dist < size)
00275 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00276 #endif
00277 #endif
00278 std::memcpy(to,from,size*sizeof(T));
00279 #else
00280 if (size == 0 || from == to)
00281 return;
00282
00283 #ifndef NDEBUG
00284 if (size < 0)
00285 throw CoinError("trying to copy negative number of entries",
00286 "CoinMemcpyN", "");
00287 #endif
00288
00289 #if 0
00290
00291
00292
00293 const long dist = to - from;
00294 if (-size < dist && dist < size)
00295 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00296 #endif
00297
00298 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00299 to[0] = from[0];
00300 to[1] = from[1];
00301 to[2] = from[2];
00302 to[3] = from[3];
00303 to[4] = from[4];
00304 to[5] = from[5];
00305 to[6] = from[6];
00306 to[7] = from[7];
00307 }
00308 switch (size % 8) {
00309 case 7: to[6] = from[6];
00310 case 6: to[5] = from[5];
00311 case 5: to[4] = from[4];
00312 case 4: to[3] = from[3];
00313 case 3: to[2] = from[2];
00314 case 2: to[1] = from[1];
00315 case 1: to[0] = from[0];
00316 case 0: break;
00317 }
00318 #endif
00319 #else
00320 CoinCopyN(from, size, to);
00321 #endif
00322 }
00323 #else
00324 template <class T> inline void
00325 CoinMemcpyN(const T * COIN_RESTRICT from, int size, T* COIN_RESTRICT to)
00326 {
00327 #ifdef USE_MEMCPY
00328 std::memcpy(to,from,size*sizeof(T));
00329 #else
00330 T * COIN_RESTRICT put = to;
00331 const T * COIN_RESTRICT get = from;
00332 for ( ; 0<size ; --size)
00333 *put++ = *get++;
00334 #endif
00335 }
00336 #endif
00337
00338
00339
00344 template <class T> inline void
00345 CoinMemcpy(register const T* first, register const T* last,
00346 register T* to)
00347 {
00348 CoinMemcpyN(first, static_cast<int>(last - first), to);
00349 }
00350
00351
00352
00359 template <class T> inline void
00360 CoinFillN(register T* to, const int size, register const T value)
00361 {
00362 if (size == 0)
00363 return;
00364
00365 #ifndef NDEBUG
00366 if (size < 0)
00367 throw CoinError("trying to fill negative number of entries",
00368 "CoinFillN", "");
00369 #endif
00370 #if 1
00371 for (register int n = size / 8; n > 0; --n, to += 8) {
00372 to[0] = value;
00373 to[1] = value;
00374 to[2] = value;
00375 to[3] = value;
00376 to[4] = value;
00377 to[5] = value;
00378 to[6] = value;
00379 to[7] = value;
00380 }
00381 switch (size % 8) {
00382 case 7: to[6] = value;
00383 case 6: to[5] = value;
00384 case 5: to[4] = value;
00385 case 4: to[3] = value;
00386 case 3: to[2] = value;
00387 case 2: to[1] = value;
00388 case 1: to[0] = value;
00389 case 0: break;
00390 }
00391 #else
00392
00393 register int n = (size + 7) / 8;
00394 --to;
00395 switch (size % 8) {
00396 case 0: do{ *++to = value;
00397 case 7: *++to = value;
00398 case 6: *++to = value;
00399 case 5: *++to = value;
00400 case 4: *++to = value;
00401 case 3: *++to = value;
00402 case 2: *++to = value;
00403 case 1: *++to = value;
00404 }while(--n>0);
00405 }
00406 #endif
00407 }
00408
00409
00410
00414 template <class T> inline void
00415 CoinFill(register T* first, register T* last, const T value)
00416 {
00417 CoinFillN(first, last - first, value);
00418 }
00419
00420
00421
00428 template <class T> inline void
00429 CoinZeroN(register T* to, const int size)
00430 {
00431 #ifdef USE_MEMCPY
00432
00433 #ifndef NDEBUG
00434
00435 if (size < 0)
00436 throw CoinError("trying to fill negative number of entries",
00437 "CoinZeroN", "");
00438 #endif
00439 memset(to,0,size*sizeof(T));
00440 #else
00441 if (size == 0)
00442 return;
00443
00444 #ifndef NDEBUG
00445 if (size < 0)
00446 throw CoinError("trying to fill negative number of entries",
00447 "CoinZeroN", "");
00448 #endif
00449 #if 1
00450 for (register int n = size / 8; n > 0; --n, to += 8) {
00451 to[0] = 0;
00452 to[1] = 0;
00453 to[2] = 0;
00454 to[3] = 0;
00455 to[4] = 0;
00456 to[5] = 0;
00457 to[6] = 0;
00458 to[7] = 0;
00459 }
00460 switch (size % 8) {
00461 case 7: to[6] = 0;
00462 case 6: to[5] = 0;
00463 case 5: to[4] = 0;
00464 case 4: to[3] = 0;
00465 case 3: to[2] = 0;
00466 case 2: to[1] = 0;
00467 case 1: to[0] = 0;
00468 case 0: break;
00469 }
00470 #else
00471
00472 register int n = (size + 7) / 8;
00473 --to;
00474 switch (size % 8) {
00475 case 0: do{ *++to = 0;
00476 case 7: *++to = 0;
00477 case 6: *++to = 0;
00478 case 5: *++to = 0;
00479 case 4: *++to = 0;
00480 case 3: *++to = 0;
00481 case 2: *++to = 0;
00482 case 1: *++to = 0;
00483 }while(--n>0);
00484 }
00485 #endif
00486 #endif
00487 }
00489 inline void
00490 CoinCheckDoubleZero(double * to, const int size)
00491 {
00492 int n=0;
00493 for (int j=0;j<size;j++) {
00494 if (to[j])
00495 n++;
00496 }
00497 if (n) {
00498 printf("array of length %d should be zero has %d nonzero\n",size,n);
00499 }
00500 }
00502 inline void
00503 CoinCheckIntZero(int * to, const int size)
00504 {
00505 int n=0;
00506 for (int j=0;j<size;j++) {
00507 if (to[j])
00508 n++;
00509 }
00510 if (n) {
00511 printf("array of length %d should be zero has %d nonzero\n",size,n);
00512 }
00513 }
00514
00515
00516
00520 template <class T> inline void
00521 CoinZero(register T* first, register T* last)
00522 {
00523 CoinZeroN(first, last - first);
00524 }
00525
00526
00527
00529 inline char * CoinStrdup(const char * name)
00530 {
00531 char* dup = NULL;
00532 if (name) {
00533 const int len = static_cast<int>(strlen(name));
00534 dup = static_cast<char*>(malloc(len+1));
00535 CoinMemcpyN(name, len, dup);
00536 dup[len] = 0;
00537 }
00538 return dup;
00539 }
00540
00541
00542
00546 template <class T> inline T
00547 CoinMax(register const T x1, register const T x2)
00548 {
00549 return (x1 > x2) ? x1 : x2;
00550 }
00551
00552
00553
00557 template <class T> inline T
00558 CoinMin(register const T x1, register const T x2)
00559 {
00560 return (x1 < x2) ? x1 : x2;
00561 }
00562
00563
00564
00568 template <class T> inline T
00569 CoinAbs(const T value)
00570 {
00571 return value<0 ? -value : value;
00572 }
00573
00574
00575
00579 template <class T> inline bool
00580 CoinIsSorted(register const T* first, const int size)
00581 {
00582 if (size == 0)
00583 return true;
00584
00585 #ifndef NDEBUG
00586 if (size < 0)
00587 throw CoinError("negative number of entries", "CoinIsSorted", "");
00588 #endif
00589 #if 1
00590
00591 const int size1 = size - 1;
00592 for (register int n = size1 / 8; n > 0; --n, first += 8) {
00593 if (first[8] < first[7]) return false;
00594 if (first[7] < first[6]) return false;
00595 if (first[6] < first[5]) return false;
00596 if (first[5] < first[4]) return false;
00597 if (first[4] < first[3]) return false;
00598 if (first[3] < first[2]) return false;
00599 if (first[2] < first[1]) return false;
00600 if (first[1] < first[0]) return false;
00601 }
00602
00603 switch (size1 % 8) {
00604 case 7: if (first[7] < first[6]) return false;
00605 case 6: if (first[6] < first[5]) return false;
00606 case 5: if (first[5] < first[4]) return false;
00607 case 4: if (first[4] < first[3]) return false;
00608 case 3: if (first[3] < first[2]) return false;
00609 case 2: if (first[2] < first[1]) return false;
00610 case 1: if (first[1] < first[0]) return false;
00611 case 0: break;
00612 }
00613 #else
00614 register const T* next = first;
00615 register const T* last = first + size;
00616 for (++next; next != last; first = next, ++next)
00617 if (*next < *first)
00618 return false;
00619 #endif
00620 return true;
00621 }
00622
00623
00624
00628 template <class T> inline bool
00629 CoinIsSorted(register const T* first, register const T* last)
00630 {
00631 return CoinIsSorted(first, static_cast<int>(last - first));
00632 }
00633
00634
00635
00639 template <class T> inline void
00640 CoinIotaN(register T* first, const int size, register T init)
00641 {
00642 if (size == 0)
00643 return;
00644
00645 #ifndef NDEBUG
00646 if (size < 0)
00647 throw CoinError("negative number of entries", "CoinIotaN", "");
00648 #endif
00649 #if 1
00650 for (register int n = size / 8; n > 0; --n, first += 8, init += 8) {
00651 first[0] = init;
00652 first[1] = init + 1;
00653 first[2] = init + 2;
00654 first[3] = init + 3;
00655 first[4] = init + 4;
00656 first[5] = init + 5;
00657 first[6] = init + 6;
00658 first[7] = init + 7;
00659 }
00660 switch (size % 8) {
00661 case 7: first[6] = init + 6;
00662 case 6: first[5] = init + 5;
00663 case 5: first[4] = init + 4;
00664 case 4: first[3] = init + 3;
00665 case 3: first[2] = init + 2;
00666 case 2: first[1] = init + 1;
00667 case 1: first[0] = init;
00668 case 0: break;
00669 }
00670 #else
00671
00672 register int n = (size + 7) / 8;
00673 --first;
00674 --init;
00675 switch (size % 8) {
00676 case 0: do{ *++first = ++init;
00677 case 7: *++first = ++init;
00678 case 6: *++first = ++init;
00679 case 5: *++first = ++init;
00680 case 4: *++first = ++init;
00681 case 3: *++first = ++init;
00682 case 2: *++first = ++init;
00683 case 1: *++first = ++init;
00684 }while(--n>0);
00685 }
00686 #endif
00687 }
00688
00689
00690
00694 template <class T> inline void
00695 CoinIota(T* first, const T* last, T init)
00696 {
00697 CoinIotaN(first, last-first, init);
00698 }
00699
00700
00701
00707 template <class T> inline T *
00708 CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast,
00709 const int * firstDelPos, const int * lastDelPos)
00710 {
00711 int delNum = static_cast<int>(lastDelPos - firstDelPos);
00712 if (delNum == 0)
00713 return arrayLast;
00714
00715 if (delNum < 0)
00716 throw CoinError("trying to delete negative number of entries",
00717 "CoinDeleteEntriesFromArray", "");
00718
00719 int * delSortedPos = NULL;
00720 if (! (CoinIsSorted(firstDelPos, lastDelPos) &&
00721 std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) {
00722
00723 delSortedPos = new int[delNum];
00724 CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos);
00725 std::sort(delSortedPos, delSortedPos + delNum);
00726 delNum = static_cast<int>(std::unique(delSortedPos,
00727 delSortedPos+delNum) - delSortedPos);
00728 }
00729 const int * delSorted = delSortedPos ? delSortedPos : firstDelPos;
00730
00731 const int last = delNum - 1;
00732 int size = delSorted[0];
00733 for (int i = 0; i < last; ++i) {
00734 const int copyFirst = delSorted[i] + 1;
00735 const int copyLast = delSorted[i+1];
00736 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00737 arrayFirst + size);
00738 size += copyLast - copyFirst;
00739 }
00740 const int copyFirst = delSorted[last] + 1;
00741 const int copyLast = static_cast<int>(arrayLast - arrayFirst);
00742 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00743 arrayFirst + size);
00744 size += copyLast - copyFirst;
00745
00746 if (delSortedPos)
00747 delete[] delSortedPos;
00748
00749 return arrayFirst + size;
00750 }
00751
00752
00753
00754 #define COIN_OWN_RANDOM_32
00755
00756 #if defined COIN_OWN_RANDOM_32
00757
00758
00759
00772 inline double CoinDrand48 (bool isSeed = false, unsigned int seed = 1)
00773 {
00774 static unsigned int last = 123456;
00775 if (isSeed) {
00776 last = seed;
00777 } else {
00778 last = 1664525*last+1013904223;
00779 return ((static_cast<double> (last))/4294967296.0);
00780 }
00781 return (0.0);
00782 }
00783
00785 inline void CoinSeedRandom(int iseed)
00786 {
00787 CoinDrand48(true, iseed);
00788 }
00789
00790 #else // COIN_OWN_RANDOM_32
00791
00792 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00793
00795 inline double CoinDrand48() { return rand() / (double) RAND_MAX; }
00797 inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); }
00798
00799 #else
00800
00802 inline double CoinDrand48() { return drand48(); }
00804 inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); }
00805
00806 #endif
00807
00808 #endif // COIN_OWN_RANDOM_32
00809
00810
00811
00814 inline char CoinFindDirSeparator()
00815 {
00816 int size = 1000;
00817 char* buf = 0;
00818 while (true) {
00819 buf = new char[size];
00820 if (getcwd(buf, size))
00821 break;
00822 delete[] buf;
00823 buf = 0;
00824 size = 2*size;
00825 }
00826
00827
00828 char dirsep = buf[0] == '/' ? '/' : '\\';
00829 delete[] buf;
00830 return dirsep;
00831 }
00832
00833
00834 inline int CoinStrNCaseCmp(const char* s0, const char* s1,
00835 const size_t len)
00836 {
00837 for (size_t i = 0; i < len; ++i) {
00838 if (s0[i] == 0) {
00839 return s1[i] == 0 ? 0 : -1;
00840 }
00841 if (s1[i] == 0) {
00842 return 1;
00843 }
00844 const int c0 = std::tolower(s0[i]);
00845 const int c1 = std::tolower(s1[i]);
00846 if (c0 < c1)
00847 return -1;
00848 if (c0 > c1)
00849 return 1;
00850 }
00851 return 0;
00852 }
00853
00854
00855
00857 template <class T> inline void CoinSwap (T &x, T &y)
00858 {
00859 T t = x;
00860 x = y;
00861 y = t;
00862 }
00863
00864
00865
00870 template <class T> inline int
00871 CoinToFile( const T* array, CoinBigIndex size, FILE * fp)
00872 {
00873 CoinBigIndex numberWritten;
00874 if (array&&size) {
00875 numberWritten =
00876 static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp));
00877 if (numberWritten!=1)
00878 return 1;
00879 numberWritten =
00880 static_cast<CoinBigIndex>(fwrite(array,sizeof(T),size_t(size),fp));
00881 if (numberWritten!=size)
00882 return 1;
00883 } else {
00884 size = 0;
00885 numberWritten =
00886 static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp));
00887 if (numberWritten!=1)
00888 return 1;
00889 }
00890 return 0;
00891 }
00892
00893
00894
00901 template <class T> inline int
00902 CoinFromFile( T* &array, CoinBigIndex size, FILE * fp, CoinBigIndex & newSize)
00903 {
00904 CoinBigIndex numberRead;
00905 numberRead =
00906 static_cast<CoinBigIndex>(fread(&newSize,sizeof(int),1,fp));
00907 if (numberRead!=1)
00908 return 1;
00909 int returnCode=0;
00910 if (size!=newSize&&(newSize||array))
00911 returnCode=2;
00912 if (newSize) {
00913 array = new T [newSize];
00914 numberRead =
00915 static_cast<CoinBigIndex>(fread(array,sizeof(T),newSize,fp));
00916 if (numberRead!=newSize)
00917 returnCode=1;
00918 } else {
00919 array = NULL;
00920 }
00921 return returnCode;
00922 }
00923
00924
00925
00927 #if 0
00928 inline double CoinCbrt(double x)
00929 {
00930 #if defined(_MSC_VER)
00931 return pow(x,(1./3.));
00932 #else
00933 return cbrt(x);
00934 #endif
00935 }
00936 #endif
00937
00938
00939
00941 #define CoinSizeofAsInt(type) (static_cast<int>(sizeof(type)))
00943 inline int
00944 CoinStrlenAsInt(const char * string)
00945 {
00946 return static_cast<int>(strlen(string));
00947 }
00948
00951 #if defined COIN_OWN_RANDOM_32
00952 class CoinThreadRandom {
00953 public:
00958 CoinThreadRandom()
00959 { seed_=12345678;}
00961 CoinThreadRandom(int seed)
00962 {
00963 seed_ = seed;
00964 }
00966 ~CoinThreadRandom() {}
00967
00968 CoinThreadRandom(const CoinThreadRandom & rhs)
00969 { seed_ = rhs.seed_;}
00970
00971 CoinThreadRandom& operator=(const CoinThreadRandom & rhs)
00972 {
00973 if (this != &rhs) {
00974 seed_ = rhs.seed_;
00975 }
00976 return *this;
00977 }
00978
00980
00985 inline void setSeed(int seed)
00986 {
00987 seed_ = seed;
00988 }
00990 inline unsigned int getSeed() const
00991 {
00992 return seed_;
00993 }
00995 inline double randomDouble() const
00996 {
00997 double retVal;
00998 seed_ = 1664525*(seed_)+1013904223;
00999 retVal = ((static_cast<double> (seed_))/4294967296.0);
01000 return retVal;
01001 }
01003 inline void randomize(int n=0)
01004 {
01005 if (!n)
01006 n=seed_ & 255;
01007 for (int i=0;i<n;i++)
01008 randomDouble();
01009 }
01011
01012
01013 protected:
01017
01018 mutable unsigned int seed_;
01020 };
01021 #else
01022 class CoinThreadRandom {
01023 public:
01028 CoinThreadRandom()
01029 { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;}
01031 CoinThreadRandom(const unsigned short seed[3])
01032 { memcpy(seed_,seed,3*sizeof(unsigned short));}
01034 CoinThreadRandom(int seed)
01035 {
01036 union { int i[2]; unsigned short int s[4];} put;
01037 put.i[0]=seed;
01038 put.i[1]=seed;
01039 memcpy(seed_,put.s,3*sizeof(unsigned short));
01040 }
01042 ~CoinThreadRandom() {}
01043
01044 CoinThreadRandom(const CoinThreadRandom & rhs)
01045 { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));}
01046
01047 CoinThreadRandom& operator=(const CoinThreadRandom & rhs)
01048 {
01049 if (this != &rhs) {
01050 memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));
01051 }
01052 return *this;
01053 }
01054
01056
01061 inline void setSeed(const unsigned short seed[3])
01062 { memcpy(seed_,seed,3*sizeof(unsigned short));}
01064 inline void setSeed(int seed)
01065 {
01066 union { int i[2]; unsigned short int s[4];} put;
01067 put.i[0]=seed;
01068 put.i[1]=seed;
01069 memcpy(seed_,put.s,3*sizeof(unsigned short));
01070 }
01072 inline double randomDouble() const
01073 {
01074 double retVal;
01075 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
01076 retVal=rand();
01077 retVal=retVal/(double) RAND_MAX;
01078 #else
01079 retVal = erand48(seed_);
01080 #endif
01081 return retVal;
01082 }
01084 inline void randomize(int n=0)
01085 {
01086 if (!n) {
01087 n=seed_[0]+seed_[1]+seed_[2];
01088 n &= 255;
01089 }
01090 for (int i=0;i<n;i++)
01091 randomDouble();
01092 }
01094
01095
01096 protected:
01100
01101 mutable unsigned short seed_[3];
01103 };
01104 #endif
01105 #ifndef COIN_DETAIL
01106 #define COIN_DETAIL_PRINT(s) {}
01107 #else
01108 #define COIN_DETAIL_PRINT(s) s
01109 #endif
01110 #endif