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 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||size) {
00174 T * arrayNew = new T[size];
00175 assert (copySize<=size);
00176 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 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 memcpy(arrayNew,array,size*sizeof(T));
00212 } else {
00213 memset(arrayNew,0,size*sizeof(T));
00214 }
00215 return arrayNew;
00216 }
00217
00218
00219
00220
00228 #ifndef COIN_USE_RESTRICT
00229 template <class T> inline void
00230 CoinMemcpyN(register const T* from, const int size, register T* to)
00231 {
00232 #ifndef _MSC_VER
00233 #ifdef USE_MEMCPY
00234
00235 #ifndef NDEBUG
00236
00237 if (size < 0)
00238 throw CoinError("trying to copy negative number of entries",
00239 "CoinMemcpyN", "");
00240
00241 #if 0
00242
00243
00244
00245 const long dist = to - from;
00246 if (-size < dist && dist < size)
00247 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00248 #endif
00249 #endif
00250 memcpy(to,from,size*sizeof(T));
00251 #else
00252 if (size == 0 || from == to)
00253 return;
00254
00255 if (size < 0)
00256 throw CoinError("trying to copy negative number of entries",
00257 "CoinMemcpyN", "");
00258
00259 #if 0
00260
00261
00262
00263 const long dist = to - from;
00264 if (-size < dist && dist < size)
00265 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00266 #endif
00267
00268 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00269 to[0] = from[0];
00270 to[1] = from[1];
00271 to[2] = from[2];
00272 to[3] = from[3];
00273 to[4] = from[4];
00274 to[5] = from[5];
00275 to[6] = from[6];
00276 to[7] = from[7];
00277 }
00278 switch (size % 8) {
00279 case 7: to[6] = from[6];
00280 case 6: to[5] = from[5];
00281 case 5: to[4] = from[4];
00282 case 4: to[3] = from[3];
00283 case 3: to[2] = from[2];
00284 case 2: to[1] = from[1];
00285 case 1: to[0] = from[0];
00286 case 0: break;
00287 }
00288 #endif
00289 #else
00290 CoinCopyN(from, size, to);
00291 #endif
00292 }
00293 #else
00294 template <class T> inline void
00295 CoinMemcpyN(const T * COIN_RESTRICT from, int size, T* COIN_RESTRICT to)
00296 {
00297 T * put = (T *) to;
00298 const T * get = (const T *) from;
00299 for ( ; 0<size ; --size)
00300 *put++ = *get++;
00301 }
00302 #endif
00303
00304
00305
00310 template <class T> inline void
00311 CoinMemcpy(register const T* first, register const T* last,
00312 register T* to)
00313 {
00314 CoinMemcpyN(first, static_cast<int>(last - first), to);
00315 }
00316
00317
00318
00325 template <class T> inline void
00326 CoinFillN(register T* to, const int size, register const T value)
00327 {
00328 if (size == 0)
00329 return;
00330
00331 if (size < 0)
00332 throw CoinError("trying to fill negative number of entries",
00333 "CoinFillN", "");
00334
00335 #if 1
00336 for (register int n = size / 8; n > 0; --n, to += 8) {
00337 to[0] = value;
00338 to[1] = value;
00339 to[2] = value;
00340 to[3] = value;
00341 to[4] = value;
00342 to[5] = value;
00343 to[6] = value;
00344 to[7] = value;
00345 }
00346 switch (size % 8) {
00347 case 7: to[6] = value;
00348 case 6: to[5] = value;
00349 case 5: to[4] = value;
00350 case 4: to[3] = value;
00351 case 3: to[2] = value;
00352 case 2: to[1] = value;
00353 case 1: to[0] = value;
00354 case 0: break;
00355 }
00356 #else
00357
00358 register int n = (size + 7) / 8;
00359 --to;
00360 switch (size % 8) {
00361 case 0: do{ *++to = value;
00362 case 7: *++to = value;
00363 case 6: *++to = value;
00364 case 5: *++to = value;
00365 case 4: *++to = value;
00366 case 3: *++to = value;
00367 case 2: *++to = value;
00368 case 1: *++to = value;
00369 }while(--n>0);
00370 }
00371 #endif
00372 }
00373
00374
00375
00379 template <class T> inline void
00380 CoinFill(register T* first, register T* last, const T value)
00381 {
00382 CoinFillN(first, last - first, value);
00383 }
00384
00385
00386
00393 template <class T> inline void
00394 CoinZeroN(register T* to, const int size)
00395 {
00396 #ifdef USE_MEMCPY
00397
00398 #ifndef NDEBUG
00399
00400 if (size < 0)
00401 throw CoinError("trying to fill negative number of entries",
00402 "CoinZeroN", "");
00403 #endif
00404 memset(to,0,size*sizeof(T));
00405 #else
00406 if (size == 0)
00407 return;
00408
00409 if (size < 0)
00410 throw CoinError("trying to fill negative number of entries",
00411 "CoinZeroN", "");
00412 #if 1
00413 for (register int n = size / 8; n > 0; --n, to += 8) {
00414 to[0] = 0;
00415 to[1] = 0;
00416 to[2] = 0;
00417 to[3] = 0;
00418 to[4] = 0;
00419 to[5] = 0;
00420 to[6] = 0;
00421 to[7] = 0;
00422 }
00423 switch (size % 8) {
00424 case 7: to[6] = 0;
00425 case 6: to[5] = 0;
00426 case 5: to[4] = 0;
00427 case 4: to[3] = 0;
00428 case 3: to[2] = 0;
00429 case 2: to[1] = 0;
00430 case 1: to[0] = 0;
00431 case 0: break;
00432 }
00433 #else
00434
00435 register int n = (size + 7) / 8;
00436 --to;
00437 switch (size % 8) {
00438 case 0: do{ *++to = 0;
00439 case 7: *++to = 0;
00440 case 6: *++to = 0;
00441 case 5: *++to = 0;
00442 case 4: *++to = 0;
00443 case 3: *++to = 0;
00444 case 2: *++to = 0;
00445 case 1: *++to = 0;
00446 }while(--n>0);
00447 }
00448 #endif
00449 #endif
00450 }
00452 inline void
00453 CoinCheckDoubleZero(double * to, const int size)
00454 {
00455 int n=0;
00456 for (int j=0;j<size;j++) {
00457 if (to[j])
00458 n++;
00459 }
00460 if (n) {
00461 printf("array of length %d should be zero has %d nonzero\n",size,n);
00462 }
00463 }
00465 inline void
00466 CoinCheckIntZero(int * to, const int size)
00467 {
00468 int n=0;
00469 for (int j=0;j<size;j++) {
00470 if (to[j])
00471 n++;
00472 }
00473 if (n) {
00474 printf("array of length %d should be zero has %d nonzero\n",size,n);
00475 }
00476 }
00477
00478
00479
00483 template <class T> inline void
00484 CoinZero(register T* first, register T* last)
00485 {
00486 CoinZeroN(first, last - first);
00487 }
00488
00489
00490
00494 template <class T> inline T
00495 CoinMax(register const T x1, register const T x2)
00496 {
00497 return (x1 > x2) ? x1 : x2;
00498 }
00499
00500
00501
00505 template <class T> inline T
00506 CoinMin(register const T x1, register const T x2)
00507 {
00508 return (x1 < x2) ? x1 : x2;
00509 }
00510
00511
00512
00516 template <class T> inline T
00517 CoinAbs(const T value)
00518 {
00519 return value<0 ? -value : value;
00520 }
00521
00522
00523
00527 template <class T> inline bool
00528 CoinIsSorted(register const T* first, const int size)
00529 {
00530 if (size == 0)
00531 return true;
00532
00533 if (size < 0)
00534 throw CoinError("negative number of entries", "CoinIsSorted", "");
00535
00536 #if 1
00537
00538 const int size1 = size - 1;
00539 for (register int n = size1 / 8; n > 0; --n, first += 8) {
00540 if (first[8] < first[7]) return false;
00541 if (first[7] < first[6]) return false;
00542 if (first[6] < first[5]) return false;
00543 if (first[5] < first[4]) return false;
00544 if (first[4] < first[3]) return false;
00545 if (first[3] < first[2]) return false;
00546 if (first[2] < first[1]) return false;
00547 if (first[1] < first[0]) return false;
00548 }
00549
00550 switch (size1 % 8) {
00551 case 7: if (first[7] < first[6]) return false;
00552 case 6: if (first[6] < first[5]) return false;
00553 case 5: if (first[5] < first[4]) return false;
00554 case 4: if (first[4] < first[3]) return false;
00555 case 3: if (first[3] < first[2]) return false;
00556 case 2: if (first[2] < first[1]) return false;
00557 case 1: if (first[1] < first[0]) return false;
00558 case 0: break;
00559 }
00560 #else
00561 register const T* next = first;
00562 register const T* last = first + size;
00563 for (++next; next != last; first = next, ++next)
00564 if (*next < *first)
00565 return false;
00566 #endif
00567 return true;
00568 }
00569
00570
00571
00575 template <class T> inline bool
00576 CoinIsSorted(register const T* first, register const T* last)
00577 {
00578 return CoinIsSorted(first, static_cast<int>(last - first));
00579 }
00580
00581
00582
00586 template <class T> inline void
00587 CoinIotaN(register T* first, const int size, register T init)
00588 {
00589 if (size == 0)
00590 return;
00591
00592 if (size < 0)
00593 throw CoinError("negative number of entries", "CoinIotaN", "");
00594
00595 #if 1
00596 for (register int n = size / 8; n > 0; --n, first += 8, init += 8) {
00597 first[0] = init;
00598 first[1] = init + 1;
00599 first[2] = init + 2;
00600 first[3] = init + 3;
00601 first[4] = init + 4;
00602 first[5] = init + 5;
00603 first[6] = init + 6;
00604 first[7] = init + 7;
00605 }
00606 switch (size % 8) {
00607 case 7: first[6] = init + 6;
00608 case 6: first[5] = init + 5;
00609 case 5: first[4] = init + 4;
00610 case 4: first[3] = init + 3;
00611 case 3: first[2] = init + 2;
00612 case 2: first[1] = init + 1;
00613 case 1: first[0] = init;
00614 case 0: break;
00615 }
00616 #else
00617
00618 register int n = (size + 7) / 8;
00619 --first;
00620 --init;
00621 switch (size % 8) {
00622 case 0: do{ *++first = ++init;
00623 case 7: *++first = ++init;
00624 case 6: *++first = ++init;
00625 case 5: *++first = ++init;
00626 case 4: *++first = ++init;
00627 case 3: *++first = ++init;
00628 case 2: *++first = ++init;
00629 case 1: *++first = ++init;
00630 }while(--n>0);
00631 }
00632 #endif
00633 }
00634
00635
00636
00640 template <class T> inline void
00641 CoinIota(T* first, const T* last, T init)
00642 {
00643 CoinIotaN(first, last-first, init);
00644 }
00645
00646
00647
00653 template <class T> inline T *
00654 CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast,
00655 const int * firstDelPos, const int * lastDelPos)
00656 {
00657 int delNum = lastDelPos - firstDelPos;
00658 if (delNum == 0)
00659 return arrayLast;
00660
00661 if (delNum < 0)
00662 throw CoinError("trying to delete negative number of entries",
00663 "CoinDeleteEntriesFromArray", "");
00664
00665 int * delSortedPos = NULL;
00666 if (! (CoinIsSorted(firstDelPos, lastDelPos) &&
00667 std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) {
00668
00669 delSortedPos = new int[delNum];
00670 CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos);
00671 std::sort(delSortedPos, delSortedPos + delNum);
00672 delNum = std::unique(delSortedPos, delSortedPos + delNum) - delSortedPos;
00673 }
00674 const int * delSorted = delSortedPos ? delSortedPos : firstDelPos;
00675
00676 const int last = delNum - 1;
00677 int size = delSorted[0];
00678 for (int i = 0; i < last; ++i) {
00679 const int copyFirst = delSorted[i] + 1;
00680 const int copyLast = delSorted[i+1];
00681 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00682 arrayFirst + size);
00683 size += copyLast - copyFirst;
00684 }
00685 const int copyFirst = delSorted[last] + 1;
00686 const int copyLast = arrayLast - arrayFirst;
00687 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00688 arrayFirst + size);
00689 size += copyLast - copyFirst;
00690
00691 if (delSortedPos)
00692 delete[] delSortedPos;
00693
00694 return arrayFirst + size;
00695 }
00696
00697
00698
00699 #define COIN_OWN_RANDOM_32
00700
00701 #if defined COIN_OWN_RANDOM_32
00702
00703
00704
00705
00706
00707
00708
00710 inline double CoinDrand48(bool isSeed = false, unsigned int seed=1)
00711 {
00712 static unsigned int last = 123456;
00713 if (isSeed) {
00714 last = seed;
00715 } else {
00716 last = 1664525*last+1013904223;
00717 return (((double) last)/4294967296.0);
00718 }
00719 return(0.0);
00720 }
00722 inline void CoinSeedRandom(int iseed)
00723 {
00724 CoinDrand48(true, iseed);
00725 }
00726
00727 #else // COIN_OWN_RANDOM_32
00728
00729 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00730
00731 inline double CoinDrand48() { return rand() / (double) RAND_MAX; }
00732 inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); }
00733
00734 #else
00735
00736 inline double CoinDrand48() { return drand48(); }
00737 inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); }
00738
00739 #endif
00740
00741 #endif // COIN_OWN_RANDOM_32
00742
00743
00744
00747 inline char CoinFindDirSeparator()
00748 {
00749 int size = 1000;
00750 char* buf = 0;
00751 while (true) {
00752 buf = new char[size];
00753 if (getcwd(buf, size))
00754 break;
00755 delete[] buf;
00756 buf = 0;
00757 size = 2*size;
00758 }
00759
00760
00761 char dirsep = buf[0] == '/' ? '/' : '\\';
00762 delete[] buf;
00763 return dirsep;
00764 }
00765
00766
00767 inline int CoinStrNCaseCmp(const char* s0, const char* s1,
00768 const size_t len)
00769 {
00770 for (size_t i = 0; i < len; ++i) {
00771 if (s0[i] == 0) {
00772 return s1[i] == 0 ? 0 : -1;
00773 }
00774 if (s1[i] == 0) {
00775 return 1;
00776 }
00777 const int c0 = tolower(s0[i]);
00778 const int c1 = tolower(s1[i]);
00779 if (c0 < c1)
00780 return -1;
00781 if (c0 > c1)
00782 return 1;
00783 }
00784 return 0;
00785 }
00786
00787
00788
00790 template <class T> inline void CoinSwap (T &x, T &y)
00791 {
00792 T t = x;
00793 x = y;
00794 y = t;
00795 }
00796
00797
00798
00803 template <class T> inline int
00804 CoinToFile( const T* array, int size, FILE * fp)
00805 {
00806 int numberWritten;
00807 if (array&&size) {
00808 numberWritten = fwrite(&size,sizeof(int),1,fp);
00809 if (numberWritten!=1)
00810 return 1;
00811 numberWritten = fwrite(array,sizeof(T),size,fp);
00812 if (numberWritten!=size)
00813 return 1;
00814 } else {
00815 size = 0;
00816 numberWritten = fwrite(&size,sizeof(int),1,fp);
00817 if (numberWritten!=1)
00818 return 1;
00819 }
00820 return 0;
00821 }
00822
00823
00824
00831 template <class T> inline int
00832 CoinFromFile( T* &array, int size, FILE * fp,int & newSize)
00833 {
00834 int numberRead;
00835 numberRead = fread(&newSize,sizeof(int),1,fp);
00836 if (numberRead!=1)
00837 return 1;
00838 int returnCode=0;
00839 if (size!=newSize&&(newSize||array))
00840 returnCode=2;
00841 if (newSize) {
00842 array = new T [newSize];
00843 numberRead = fread(array,sizeof(T),newSize,fp);
00844 if (numberRead!=newSize)
00845 returnCode=1;
00846 } else {
00847 array = NULL;
00848 }
00849 return returnCode;
00850 }
00851
00852
00853
00855 inline double CoinCbrt(double x)
00856 {
00857 #if defined(_MSC_VER)
00858 return pow(x,(1./3.));
00859 #else
00860 return cbrt(x);
00861 #endif
00862 }
00865 #if defined COIN_OWN_RANDOM_32
00866 class CoinThreadRandom {
00867 public:
00872 CoinThreadRandom()
00873 { seed_=12345678;}
00875 CoinThreadRandom(int seed)
00876 {
00877 seed_ = seed;
00878 }
00880 ~CoinThreadRandom() {}
00881
00882 CoinThreadRandom(const CoinThreadRandom & rhs)
00883 { seed_ = rhs.seed_;}
00884
00885 CoinThreadRandom& operator=(const CoinThreadRandom & rhs)
00886 {
00887 if (this != &rhs) {
00888 seed_ = rhs.seed_;
00889 }
00890 return *this;
00891 }
00892
00894
00899 inline void setSeed(int seed)
00900 {
00901 seed_ = seed;
00902 }
00904 inline double randomDouble() const
00905 {
00906 double retVal;
00907 seed_ = 1664525*(seed_)+1013904223;
00908 retVal = (((double) seed_)/4294967296.0);
00909 return retVal;
00910 }
00912
00913
00914 protected:
00918
00919 mutable unsigned int seed_;
00921 };
00922 #else
00923 class CoinThreadRandom {
00924 public:
00929 CoinThreadRandom()
00930 { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;}
00932 CoinThreadRandom(const unsigned short seed[3])
00933 { memcpy(seed_,seed,3*sizeof(unsigned short));}
00935 CoinThreadRandom(int seed)
00936 {
00937 union { int i[2]; unsigned short int s[4];} put;
00938 put.i[0]=seed;
00939 put.i[1]=seed;
00940 memcpy(seed_,put.s,3*sizeof(unsigned short));
00941 }
00943 ~CoinThreadRandom() {}
00944
00945 CoinThreadRandom(const CoinThreadRandom & rhs)
00946 { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));}
00947
00948 CoinThreadRandom& operator=(const CoinThreadRandom & rhs)
00949 {
00950 if (this != &rhs) {
00951 memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));
00952 }
00953 return *this;
00954 }
00955
00957
00962 inline void setSeed(const unsigned short seed[3])
00963 { memcpy(seed_,seed,3*sizeof(unsigned short));}
00965 inline void setSeed(int seed)
00966 {
00967 union { int i[2]; unsigned short int s[4];} put;
00968 put.i[0]=seed;
00969 put.i[1]=seed;
00970 memcpy(seed_,put.s,3*sizeof(unsigned short));
00971 }
00973 inline double randomDouble() const
00974 {
00975 double retVal;
00976 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00977 retVal=rand();
00978 retVal=retVal/(double) RAND_MAX;
00979 #else
00980 retVal = erand48(seed_);
00981 #endif
00982 return retVal;
00983 }
00985
00986
00987 protected:
00991
00992 mutable unsigned short seed_[3];
00994 };
00995 #endif
00996 #endif