00001
00002
00003
00004 #ifndef CoinHelperFunctions_H
00005 #define CoinHelperFunctions_H
00006 #if defined(_MSC_VER)
00007 # include <direct.h>
00008 # define getcwd _getcwd
00009 #else
00010 # include <unistd.h>
00011 #endif
00012
00013 #include <cstdlib>
00014 #include <cstdio>
00015 #include "CoinError.hpp"
00016 #include "CoinFinite.hpp"
00017
00018
00024 template <class T> inline void
00025 CoinCopyN(register const T* from, const int size, register T* to)
00026 {
00027 if (size == 0 || from == to)
00028 return;
00029
00030 if (size < 0)
00031 throw CoinError("trying to copy negative number of entries",
00032 "CoinCopyN", "");
00033
00034 register int n = (size + 7) / 8;
00035 if (to > from) {
00036 register const T* downfrom = from + size;
00037 register T* downto = to + size;
00038
00039 switch (size % 8) {
00040 case 0: do{ *--downto = *--downfrom;
00041 case 7: *--downto = *--downfrom;
00042 case 6: *--downto = *--downfrom;
00043 case 5: *--downto = *--downfrom;
00044 case 4: *--downto = *--downfrom;
00045 case 3: *--downto = *--downfrom;
00046 case 2: *--downto = *--downfrom;
00047 case 1: *--downto = *--downfrom;
00048 }while(--n>0);
00049 }
00050 } else {
00051
00052 --from;
00053 --to;
00054 switch (size % 8) {
00055 case 0: do{ *++to = *++from;
00056 case 7: *++to = *++from;
00057 case 6: *++to = *++from;
00058 case 5: *++to = *++from;
00059 case 4: *++to = *++from;
00060 case 3: *++to = *++from;
00061 case 2: *++to = *++from;
00062 case 1: *++to = *++from;
00063 }while(--n>0);
00064 }
00065 }
00066 }
00067
00068
00069
00074 template <class T> inline void
00075 CoinCopy(register const T* first, register const T* last, register T* to)
00076 {
00077 CoinCopyN(first, last - first, to);
00078 }
00079
00080
00081
00089 template <class T> inline void
00090 CoinDisjointCopyN(register const T* from, const int size, register T* to)
00091 {
00092 #ifndef _MSC_VER
00093 if (size == 0 || from == to)
00094 return;
00095
00096 if (size < 0)
00097 throw CoinError("trying to copy negative number of entries",
00098 "CoinDisjointCopyN", "");
00099
00100 #if 0
00101
00102
00103
00104 const long dist = to - from;
00105 if (-size < dist && dist < size)
00106 throw CoinError("overlapping arrays", "CoinDisjointCopyN", "");
00107 #endif
00108
00109 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00110 to[0] = from[0];
00111 to[1] = from[1];
00112 to[2] = from[2];
00113 to[3] = from[3];
00114 to[4] = from[4];
00115 to[5] = from[5];
00116 to[6] = from[6];
00117 to[7] = from[7];
00118 }
00119 switch (size % 8) {
00120 case 7: to[6] = from[6];
00121 case 6: to[5] = from[5];
00122 case 5: to[4] = from[4];
00123 case 4: to[3] = from[3];
00124 case 3: to[2] = from[2];
00125 case 2: to[1] = from[1];
00126 case 1: to[0] = from[0];
00127 case 0: break;
00128 }
00129 #else
00130 CoinCopyN(from, size, to);
00131 #endif
00132 }
00133
00134
00135
00140 template <class T> inline void
00141 CoinDisjointCopy(register const T* first, register const T* last,
00142 register T* to)
00143 {
00144 CoinDisjointCopyN(first, static_cast<int>(last - first), to);
00145 }
00146
00147
00148
00153 template <class T> inline T*
00154 CoinCopyOfArray( const T * array, const int size)
00155 {
00156 if (array) {
00157 T * arrayNew = new T[size];
00158 std::memcpy(arrayNew,array,size*sizeof(T));
00159 return arrayNew;
00160 } else {
00161 return NULL;
00162 }
00163 }
00164
00165
00170 template <class T> inline T*
00171 CoinCopyOfArrayPartial( const T * array, const int size,const int copySize)
00172 {
00173 if (array) {
00174 T * arrayNew = new T[size];
00175 assert (copySize<=size);
00176 std::memcpy(arrayNew,array,copySize*sizeof(T));
00177 return arrayNew;
00178 } else {
00179 return NULL;
00180 }
00181 }
00182
00187 template <class T> inline T*
00188 CoinCopyOfArray( const T * array, const int size, T value)
00189 {
00190 T * arrayNew = new T[size];
00191 if (array) {
00192 std::memcpy(arrayNew,array,size*sizeof(T));
00193 } else {
00194 int i;
00195 for (i=0;i<size;i++)
00196 arrayNew[i] = value;
00197 }
00198 return arrayNew;
00199 }
00200
00201
00206 template <class T> inline T*
00207 CoinCopyOfArrayOrZero( const T * array , const int size)
00208 {
00209 T * arrayNew = new T[size];
00210 if (array) {
00211 std::memcpy(arrayNew,array,size*sizeof(T));
00212 } else {
00213 std::memset(arrayNew,0,size*sizeof(T));
00214 }
00215 return arrayNew;
00216 }
00217
00218
00219
00220
00228 template <class T> inline void
00229 CoinMemcpyN(register const T* from, const int size, register T* to)
00230 {
00231 #ifndef _MSC_VER
00232 #ifdef USE_MEMCPY
00233
00234 #ifndef NDEBUG
00235
00236 if (size < 0)
00237 throw CoinError("trying to copy negative number of entries",
00238 "CoinMemcpyN", "");
00239
00240 #if 0
00241
00242
00243
00244 const long dist = to - from;
00245 if (-size < dist && dist < size)
00246 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00247 #endif
00248 #endif
00249 std::memcpy(to,from,size*sizeof(T));
00250 #else
00251 if (size == 0 || from == to)
00252 return;
00253
00254 if (size < 0)
00255 throw CoinError("trying to copy negative number of entries",
00256 "CoinMemcpyN", "");
00257
00258 #if 0
00259
00260
00261
00262 const long dist = to - from;
00263 if (-size < dist && dist < size)
00264 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00265 #endif
00266
00267 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00268 to[0] = from[0];
00269 to[1] = from[1];
00270 to[2] = from[2];
00271 to[3] = from[3];
00272 to[4] = from[4];
00273 to[5] = from[5];
00274 to[6] = from[6];
00275 to[7] = from[7];
00276 }
00277 switch (size % 8) {
00278 case 7: to[6] = from[6];
00279 case 6: to[5] = from[5];
00280 case 5: to[4] = from[4];
00281 case 4: to[3] = from[3];
00282 case 3: to[2] = from[2];
00283 case 2: to[1] = from[1];
00284 case 1: to[0] = from[0];
00285 case 0: break;
00286 }
00287 #endif
00288 #else
00289 CoinCopyN(from, size, to);
00290 #endif
00291 }
00292
00293
00294
00299 template <class T> inline void
00300 CoinMemcpy(register const T* first, register const T* last,
00301 register T* to)
00302 {
00303 CoinMemcpyN(first, static_cast<int>(last - first), to);
00304 }
00305
00306
00307
00314 template <class T> inline void
00315 CoinFillN(register T* to, const int size, register const T value)
00316 {
00317 if (size == 0)
00318 return;
00319
00320 if (size < 0)
00321 throw CoinError("trying to fill negative number of entries",
00322 "CoinFillN", "");
00323
00324 #if 1
00325 for (register int n = size / 8; n > 0; --n, to += 8) {
00326 to[0] = value;
00327 to[1] = value;
00328 to[2] = value;
00329 to[3] = value;
00330 to[4] = value;
00331 to[5] = value;
00332 to[6] = value;
00333 to[7] = value;
00334 }
00335 switch (size % 8) {
00336 case 7: to[6] = value;
00337 case 6: to[5] = value;
00338 case 5: to[4] = value;
00339 case 4: to[3] = value;
00340 case 3: to[2] = value;
00341 case 2: to[1] = value;
00342 case 1: to[0] = value;
00343 case 0: break;
00344 }
00345 #else
00346
00347 register int n = (size + 7) / 8;
00348 --to;
00349 switch (size % 8) {
00350 case 0: do{ *++to = value;
00351 case 7: *++to = value;
00352 case 6: *++to = value;
00353 case 5: *++to = value;
00354 case 4: *++to = value;
00355 case 3: *++to = value;
00356 case 2: *++to = value;
00357 case 1: *++to = value;
00358 }while(--n>0);
00359 }
00360 #endif
00361 }
00362
00363
00364
00368 template <class T> inline void
00369 CoinFill(register T* first, register T* last, const T value)
00370 {
00371 CoinFillN(first, last - first, value);
00372 }
00373
00374
00375
00382 template <class T> inline void
00383 CoinZeroN(register T* to, const int size)
00384 {
00385 #ifdef USE_MEMCPY
00386
00387 #ifndef NDEBUG
00388
00389 if (size < 0)
00390 throw CoinError("trying to fill negative number of entries",
00391 "CoinZeroN", "");
00392 #endif
00393 memset(to,0,size*sizeof(T));
00394 #else
00395 if (size == 0)
00396 return;
00397
00398 if (size < 0)
00399 throw CoinError("trying to fill negative number of entries",
00400 "CoinZeroN", "");
00401 #if 1
00402 for (register int n = size / 8; n > 0; --n, to += 8) {
00403 to[0] = 0;
00404 to[1] = 0;
00405 to[2] = 0;
00406 to[3] = 0;
00407 to[4] = 0;
00408 to[5] = 0;
00409 to[6] = 0;
00410 to[7] = 0;
00411 }
00412 switch (size % 8) {
00413 case 7: to[6] = 0;
00414 case 6: to[5] = 0;
00415 case 5: to[4] = 0;
00416 case 4: to[3] = 0;
00417 case 3: to[2] = 0;
00418 case 2: to[1] = 0;
00419 case 1: to[0] = 0;
00420 case 0: break;
00421 }
00422 #else
00423
00424 register int n = (size + 7) / 8;
00425 --to;
00426 switch (size % 8) {
00427 case 0: do{ *++to = 0;
00428 case 7: *++to = 0;
00429 case 6: *++to = 0;
00430 case 5: *++to = 0;
00431 case 4: *++to = 0;
00432 case 3: *++to = 0;
00433 case 2: *++to = 0;
00434 case 1: *++to = 0;
00435 }while(--n>0);
00436 }
00437 #endif
00438 #endif
00439 }
00441 inline void
00442 CoinCheckDoubleZero(double * to, const int size)
00443 {
00444 int n=0;
00445 for (int j=0;j<size;j++) {
00446 if (to[j])
00447 n++;
00448 }
00449 if (n) {
00450 printf("array of length %d should be zero has %d nonzero\n",size,n);
00451 }
00452 }
00454 inline void
00455 CoinCheckIntZero(int * to, const int size)
00456 {
00457 int n=0;
00458 for (int j=0;j<size;j++) {
00459 if (to[j])
00460 n++;
00461 }
00462 if (n) {
00463 printf("array of length %d should be zero has %d nonzero\n",size,n);
00464 }
00465 }
00466
00467
00468
00472 template <class T> inline void
00473 CoinZero(register T* first, register T* last)
00474 {
00475 CoinZeroN(first, last - first);
00476 }
00477
00478
00479
00481 inline char * CoinStrdup(const char * name)
00482 {
00483 char* dup = NULL;
00484 if (name) {
00485 const int len = strlen(name);
00486 dup = (char*)malloc(len+1);
00487 CoinMemcpyN(name, len, dup);
00488 dup[len] = 0;
00489 }
00490 return dup;
00491 }
00492
00493
00494
00498 template <class T> inline T
00499 CoinMax(register const T x1, register const T x2)
00500 {
00501 return (x1 > x2) ? x1 : x2;
00502 }
00503
00504
00505
00509 template <class T> inline T
00510 CoinMin(register const T x1, register const T x2)
00511 {
00512 return (x1 < x2) ? x1 : x2;
00513 }
00514
00515
00516
00520 template <class T> inline T
00521 CoinAbs(const T value)
00522 {
00523 return value<0 ? -value : value;
00524 }
00525
00526
00527
00531 template <class T> inline bool
00532 CoinIsSorted(register const T* first, const int size)
00533 {
00534 if (size == 0)
00535 return true;
00536
00537 if (size < 0)
00538 throw CoinError("negative number of entries", "CoinIsSorted", "");
00539
00540 #if 1
00541
00542 const int size1 = size - 1;
00543 for (register int n = size1 / 8; n > 0; --n, first += 8) {
00544 if (first[8] < first[7]) return false;
00545 if (first[7] < first[6]) return false;
00546 if (first[6] < first[5]) return false;
00547 if (first[5] < first[4]) return false;
00548 if (first[4] < first[3]) return false;
00549 if (first[3] < first[2]) return false;
00550 if (first[2] < first[1]) return false;
00551 if (first[1] < first[0]) return false;
00552 }
00553
00554 switch (size1 % 8) {
00555 case 7: if (first[7] < first[6]) return false;
00556 case 6: if (first[6] < first[5]) return false;
00557 case 5: if (first[5] < first[4]) return false;
00558 case 4: if (first[4] < first[3]) return false;
00559 case 3: if (first[3] < first[2]) return false;
00560 case 2: if (first[2] < first[1]) return false;
00561 case 1: if (first[1] < first[0]) return false;
00562 case 0: break;
00563 }
00564 #else
00565 register const T* next = first;
00566 register const T* last = first + size;
00567 for (++next; next != last; first = next, ++next)
00568 if (*next < *first)
00569 return false;
00570 #endif
00571 return true;
00572 }
00573
00574
00575
00579 template <class T> inline bool
00580 CoinIsSorted(register const T* first, register const T* last)
00581 {
00582 return CoinIsSorted(first, static_cast<int>(last - first));
00583 }
00584
00585
00586
00590 template <class T> inline void
00591 CoinIotaN(register T* first, const int size, register T init)
00592 {
00593 if (size == 0)
00594 return;
00595
00596 if (size < 0)
00597 throw CoinError("negative number of entries", "CoinIotaN", "");
00598
00599 #if 1
00600 for (register int n = size / 8; n > 0; --n, first += 8, init += 8) {
00601 first[0] = init;
00602 first[1] = init + 1;
00603 first[2] = init + 2;
00604 first[3] = init + 3;
00605 first[4] = init + 4;
00606 first[5] = init + 5;
00607 first[6] = init + 6;
00608 first[7] = init + 7;
00609 }
00610 switch (size % 8) {
00611 case 7: first[6] = init + 6;
00612 case 6: first[5] = init + 5;
00613 case 5: first[4] = init + 4;
00614 case 4: first[3] = init + 3;
00615 case 3: first[2] = init + 2;
00616 case 2: first[1] = init + 1;
00617 case 1: first[0] = init;
00618 case 0: break;
00619 }
00620 #else
00621
00622 register int n = (size + 7) / 8;
00623 --first;
00624 --init;
00625 switch (size % 8) {
00626 case 0: do{ *++first = ++init;
00627 case 7: *++first = ++init;
00628 case 6: *++first = ++init;
00629 case 5: *++first = ++init;
00630 case 4: *++first = ++init;
00631 case 3: *++first = ++init;
00632 case 2: *++first = ++init;
00633 case 1: *++first = ++init;
00634 }while(--n>0);
00635 }
00636 #endif
00637 }
00638
00639
00640
00644 template <class T> inline void
00645 CoinIota(T* first, const T* last, T init)
00646 {
00647 CoinIotaN(first, last-first, init);
00648 }
00649
00650
00651
00657 template <class T> inline T *
00658 CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast,
00659 const int * firstDelPos, const int * lastDelPos)
00660 {
00661 int delNum = lastDelPos - firstDelPos;
00662 if (delNum == 0)
00663 return arrayLast;
00664
00665 if (delNum < 0)
00666 throw CoinError("trying to delete negative number of entries",
00667 "CoinDeleteEntriesFromArray", "");
00668
00669 int * delSortedPos = NULL;
00670 if (! (CoinIsSorted(firstDelPos, lastDelPos) &&
00671 std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) {
00672
00673 delSortedPos = new int[delNum];
00674 CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos);
00675 std::sort(delSortedPos, delSortedPos + delNum);
00676 delNum = std::unique(delSortedPos, delSortedPos + delNum) - delSortedPos;
00677 }
00678 const int * delSorted = delSortedPos ? delSortedPos : firstDelPos;
00679
00680 const int last = delNum - 1;
00681 int size = delSorted[0];
00682 for (int i = 0; i < last; ++i) {
00683 const int copyFirst = delSorted[i] + 1;
00684 const int copyLast = delSorted[i+1];
00685 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00686 arrayFirst + size);
00687 size += copyLast - copyFirst;
00688 }
00689 const int copyFirst = delSorted[last] + 1;
00690 const int copyLast = arrayLast - arrayFirst;
00691 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00692 arrayFirst + size);
00693 size += copyLast - copyFirst;
00694
00695 if (delSortedPos)
00696 delete[] delSortedPos;
00697
00698 return arrayFirst + size;
00699 }
00700
00701
00702
00703 #define COIN_OWN_RANDOM_32
00704
00705 #if defined COIN_OWN_RANDOM_32
00706
00707
00708
00709
00710
00711
00712
00714 inline double CoinDrand48(bool isSeed = false, unsigned int seed=1)
00715 {
00716 static unsigned int last = 123456;
00717 if (isSeed) {
00718 last = seed;
00719 } else {
00720 last = 1664525*last+1013904223;
00721 return (((double) last)/4294967296.0);
00722 }
00723 return(0.0);
00724 }
00726 inline void CoinSeedRandom(int iseed)
00727 {
00728 CoinDrand48(true, iseed);
00729 }
00730
00731 #else // COIN_OWN_RANDOM_32
00732
00733 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00734
00735 inline double CoinDrand48() { return rand() / (double) RAND_MAX; }
00736 inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); }
00737
00738 #else
00739
00740 inline double CoinDrand48() { return drand48(); }
00741 inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); }
00742
00743 #endif
00744
00745 #endif // COIN_OWN_RANDOM_32
00746
00747
00748
00751 inline char CoinFindDirSeparator()
00752 {
00753 int size = 1000;
00754 char* buf = 0;
00755 while (true) {
00756 buf = new char[size];
00757 if (getcwd(buf, size))
00758 break;
00759 delete[] buf;
00760 buf = 0;
00761 size = 2*size;
00762 }
00763
00764
00765 char dirsep = buf[0] == '/' ? '/' : '\\';
00766 delete[] buf;
00767 return dirsep;
00768 }
00769
00770
00771 inline int CoinStrNCaseCmp(const char* s0, const char* s1,
00772 const size_t len)
00773 {
00774 for (size_t i = 0; i < len; ++i) {
00775 if (s0[i] == 0) {
00776 return s1[i] == 0 ? 0 : -1;
00777 }
00778 if (s1[i] == 0) {
00779 return 1;
00780 }
00781 const int c0 = tolower(s0[i]);
00782 const int c1 = tolower(s1[i]);
00783 if (c0 < c1)
00784 return -1;
00785 if (c0 > c1)
00786 return 1;
00787 }
00788 return 0;
00789 }
00790
00791
00792
00794 template <class T> inline void CoinSwap (T &x, T &y)
00795 {
00796 T t = x;
00797 x = y;
00798 y = t;
00799 }
00800
00801
00802
00807 template <class T> inline int
00808 CoinToFile( const T* array, int size, FILE * fp)
00809 {
00810 int numberWritten;
00811 if (array&&size) {
00812 numberWritten = fwrite(&size,sizeof(int),1,fp);
00813 if (numberWritten!=1)
00814 return 1;
00815 numberWritten = fwrite(array,sizeof(T),size,fp);
00816 if (numberWritten!=size)
00817 return 1;
00818 } else {
00819 size = 0;
00820 numberWritten = fwrite(&size,sizeof(int),1,fp);
00821 if (numberWritten!=1)
00822 return 1;
00823 }
00824 return 0;
00825 }
00826
00827
00828
00835 template <class T> inline int
00836 CoinFromFile( T* &array, int size, FILE * fp,int & newSize)
00837 {
00838 int numberRead;
00839 numberRead = fread(&newSize,sizeof(int),1,fp);
00840 if (numberRead!=1)
00841 return 1;
00842 int returnCode=0;
00843 if (size!=newSize&&(newSize||array))
00844 returnCode=2;
00845 if (newSize) {
00846 array = new T [newSize];
00847 numberRead = fread(array,sizeof(T),newSize,fp);
00848 if (numberRead!=newSize)
00849 returnCode=1;
00850 } else {
00851 array = NULL;
00852 }
00853 return returnCode;
00854 }
00855
00856
00857
00859 inline double CoinCbrt(double x)
00860 {
00861 #if defined(_MSC_VER)
00862 return pow(x,(1./3.));
00863 #else
00864 return cbrt(x);
00865 #endif
00866 }
00869 #if defined COIN_OWN_RANDOM_32
00870 class CoinThreadRandom {
00871 public:
00876 CoinThreadRandom()
00877 { seed_=12345678;}
00879 CoinThreadRandom(int seed)
00880 {
00881 seed_ = seed;
00882 }
00884 ~CoinThreadRandom() {}
00885
00886 CoinThreadRandom(const CoinThreadRandom & rhs)
00887 { seed_ = rhs.seed_;}
00888
00889 CoinThreadRandom& operator=(const CoinThreadRandom & rhs)
00890 {
00891 if (this != &rhs) {
00892 seed_ = rhs.seed_;
00893 }
00894 return *this;
00895 }
00896
00898
00903 inline void setSeed(int seed)
00904 {
00905 seed_ = seed;
00906 }
00908 inline double randomDouble() const
00909 {
00910 double retVal;
00911 seed_ = 1664525*(seed_)+1013904223;
00912 retVal = (((double) seed_)/4294967296.0);
00913 return retVal;
00914 }
00916
00917
00918 protected:
00922
00923 mutable unsigned int seed_;
00925 };
00926 #else
00927 class CoinThreadRandom {
00928 public:
00933 CoinThreadRandom()
00934 { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;}
00936 CoinThreadRandom(const unsigned short seed[3])
00937 { memcpy(seed_,seed,3*sizeof(unsigned short));}
00939 CoinThreadRandom(int seed)
00940 {
00941 union { int i[2]; unsigned short int s[4];} put;
00942 put.i[0]=seed;
00943 put.i[1]=seed;
00944 memcpy(seed_,put.s,3*sizeof(unsigned short));
00945 }
00947 ~CoinThreadRandom() {}
00948
00949 CoinThreadRandom(const CoinThreadRandom & rhs)
00950 { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));}
00951
00952 CoinThreadRandom& operator=(const CoinThreadRandom & rhs)
00953 {
00954 if (this != &rhs) {
00955 memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));
00956 }
00957 return *this;
00958 }
00959
00961
00966 inline void setSeed(const unsigned short seed[3])
00967 { memcpy(seed_,seed,3*sizeof(unsigned short));}
00969 inline void setSeed(int seed)
00970 {
00971 union { int i[2]; unsigned short int s[4];} put;
00972 put.i[0]=seed;
00973 put.i[1]=seed;
00974 memcpy(seed_,put.s,3*sizeof(unsigned short));
00975 }
00977 inline double randomDouble() const
00978 {
00979 double retVal;
00980 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00981 retVal=rand();
00982 retVal=retVal/(double) RAND_MAX;
00983 #else
00984 retVal = erand48(seed_);
00985 #endif
00986 return retVal;
00987 }
00989
00990
00991 protected:
00995
00996 mutable unsigned short seed_[3];
00998 };
00999 #endif
01000 #endif