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 <cstdio>
00014 #include "CoinError.hpp"
00015 #include "CoinFinite.hpp"
00016
00017
00023 template <class T> inline void
00024 CoinCopyN(register const T* from, const int size, register T* to)
00025 {
00026 if (size == 0 || from == to)
00027 return;
00028
00029 if (size < 0)
00030 throw CoinError("trying to copy negative number of entries",
00031 "CoinCopyN", "");
00032
00033 register int n = (size + 7) / 8;
00034 if (to > from) {
00035 register const T* downfrom = from + size;
00036 register T* downto = to + size;
00037
00038 switch (size % 8) {
00039 case 0: do{ *--downto = *--downfrom;
00040 case 7: *--downto = *--downfrom;
00041 case 6: *--downto = *--downfrom;
00042 case 5: *--downto = *--downfrom;
00043 case 4: *--downto = *--downfrom;
00044 case 3: *--downto = *--downfrom;
00045 case 2: *--downto = *--downfrom;
00046 case 1: *--downto = *--downfrom;
00047 }while(--n>0);
00048 }
00049 } else {
00050
00051 --from;
00052 --to;
00053 switch (size % 8) {
00054 case 0: do{ *++to = *++from;
00055 case 7: *++to = *++from;
00056 case 6: *++to = *++from;
00057 case 5: *++to = *++from;
00058 case 4: *++to = *++from;
00059 case 3: *++to = *++from;
00060 case 2: *++to = *++from;
00061 case 1: *++to = *++from;
00062 }while(--n>0);
00063 }
00064 }
00065 }
00066
00067
00068
00073 template <class T> inline void
00074 CoinCopy(register const T* first, register const T* last, register T* to)
00075 {
00076 CoinCopyN(first, last - first, to);
00077 }
00078
00079
00080
00088 template <class T> inline void
00089 CoinDisjointCopyN(register const T* from, const int size, register T* to)
00090 {
00091 #ifndef _MSC_VER
00092 if (size == 0 || from == to)
00093 return;
00094
00095 if (size < 0)
00096 throw CoinError("trying to copy negative number of entries",
00097 "CoinDisjointCopyN", "");
00098
00099 #if 0
00100
00101
00102
00103 const long dist = to - from;
00104 if (-size < dist && dist < size)
00105 throw CoinError("overlapping arrays", "CoinDisjointCopyN", "");
00106 #endif
00107
00108 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00109 to[0] = from[0];
00110 to[1] = from[1];
00111 to[2] = from[2];
00112 to[3] = from[3];
00113 to[4] = from[4];
00114 to[5] = from[5];
00115 to[6] = from[6];
00116 to[7] = from[7];
00117 }
00118 switch (size % 8) {
00119 case 7: to[6] = from[6];
00120 case 6: to[5] = from[5];
00121 case 5: to[4] = from[4];
00122 case 4: to[3] = from[3];
00123 case 3: to[2] = from[2];
00124 case 2: to[1] = from[1];
00125 case 1: to[0] = from[0];
00126 case 0: break;
00127 }
00128 #else
00129 CoinCopyN(from, size, to);
00130 #endif
00131 }
00132
00133
00134
00139 template <class T> inline void
00140 CoinDisjointCopy(register const T* first, register const T* last,
00141 register T* to)
00142 {
00143 CoinDisjointCopyN(first, static_cast<int>(last - first), to);
00144 }
00145
00146
00147
00152 template <class T> inline T*
00153 CoinCopyOfArray( const T * array, const int size)
00154 {
00155 if (array) {
00156 T * arrayNew = new T[size];
00157 memcpy(arrayNew,array,size*sizeof(T));
00158 return arrayNew;
00159 } else {
00160 return NULL;
00161 }
00162 }
00163
00168 template <class T> inline T*
00169 CoinCopyOfArray( const T * array, const int size, T value)
00170 {
00171 T * arrayNew = new T[size];
00172 if (array) {
00173 memcpy(arrayNew,array,size*sizeof(T));
00174 } else {
00175 int i;
00176 for (i=0;i<size;i++)
00177 arrayNew[i] = value;
00178 }
00179 return arrayNew;
00180 }
00181
00182
00187 template <class T> inline T*
00188 CoinCopyOfArrayOrZero( const T * array , const int size)
00189 {
00190 T * arrayNew = new T[size];
00191 if (array) {
00192 memcpy(arrayNew,array,size*sizeof(T));
00193 } else {
00194 memset(arrayNew,0,size*sizeof(T));
00195 }
00196 return arrayNew;
00197 }
00198
00199
00200
00201
00209 template <class T> inline void
00210 CoinMemcpyN(register const T* from, const int size, register T* to)
00211 {
00212 #ifndef _MSC_VER
00213 #ifdef USE_MEMCPY
00214
00215 #ifndef NDEBUG
00216
00217 if (size < 0)
00218 throw CoinError("trying to copy negative number of entries",
00219 "CoinMemcpyN", "");
00220
00221 #if 0
00222
00223
00224
00225 const long dist = to - from;
00226 if (-size < dist && dist < size)
00227 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00228 #endif
00229 #endif
00230 memcpy(to,from,size*sizeof(T));
00231 #else
00232 if (size == 0 || from == to)
00233 return;
00234
00235 if (size < 0)
00236 throw CoinError("trying to copy negative number of entries",
00237 "CoinMemcpyN", "");
00238
00239 #if 0
00240
00241
00242
00243 const long dist = to - from;
00244 if (-size < dist && dist < size)
00245 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00246 #endif
00247
00248 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00249 to[0] = from[0];
00250 to[1] = from[1];
00251 to[2] = from[2];
00252 to[3] = from[3];
00253 to[4] = from[4];
00254 to[5] = from[5];
00255 to[6] = from[6];
00256 to[7] = from[7];
00257 }
00258 switch (size % 8) {
00259 case 7: to[6] = from[6];
00260 case 6: to[5] = from[5];
00261 case 5: to[4] = from[4];
00262 case 4: to[3] = from[3];
00263 case 3: to[2] = from[2];
00264 case 2: to[1] = from[1];
00265 case 1: to[0] = from[0];
00266 case 0: break;
00267 }
00268 #endif
00269 #else
00270 CoinCopyN(from, size, to);
00271 #endif
00272 }
00273
00274
00275
00280 template <class T> inline void
00281 CoinMemcpy(register const T* first, register const T* last,
00282 register T* to)
00283 {
00284 CoinMemcpyN(first, static_cast<int>(last - first), to);
00285 }
00286
00287
00288
00295 template <class T> inline void
00296 CoinFillN(register T* to, const int size, register const T value)
00297 {
00298 if (size == 0)
00299 return;
00300
00301 if (size < 0)
00302 throw CoinError("trying to fill negative number of entries",
00303 "CoinFillN", "");
00304
00305 #if 1
00306 for (register int n = size / 8; n > 0; --n, to += 8) {
00307 to[0] = value;
00308 to[1] = value;
00309 to[2] = value;
00310 to[3] = value;
00311 to[4] = value;
00312 to[5] = value;
00313 to[6] = value;
00314 to[7] = value;
00315 }
00316 switch (size % 8) {
00317 case 7: to[6] = value;
00318 case 6: to[5] = value;
00319 case 5: to[4] = value;
00320 case 4: to[3] = value;
00321 case 3: to[2] = value;
00322 case 2: to[1] = value;
00323 case 1: to[0] = value;
00324 case 0: break;
00325 }
00326 #else
00327
00328 register int n = (size + 7) / 8;
00329 --to;
00330 switch (size % 8) {
00331 case 0: do{ *++to = value;
00332 case 7: *++to = value;
00333 case 6: *++to = value;
00334 case 5: *++to = value;
00335 case 4: *++to = value;
00336 case 3: *++to = value;
00337 case 2: *++to = value;
00338 case 1: *++to = value;
00339 }while(--n>0);
00340 }
00341 #endif
00342 }
00343
00344
00345
00349 template <class T> inline void
00350 CoinFill(register T* first, register T* last, const T value)
00351 {
00352 CoinFillN(first, last - first, value);
00353 }
00354
00355
00356
00363 template <class T> inline void
00364 CoinZeroN(register T* to, const int size)
00365 {
00366 #ifdef USE_MEMCPY
00367
00368 #ifndef NDEBUG
00369
00370 if (size < 0)
00371 throw CoinError("trying to fill negative number of entries",
00372 "CoinZeroN", "");
00373 #endif
00374 memset(to,0,size*sizeof(T));
00375 #else
00376 if (size == 0)
00377 return;
00378
00379 if (size < 0)
00380 throw CoinError("trying to fill negative number of entries",
00381 "CoinZeroN", "");
00382 #if 1
00383 for (register int n = size / 8; n > 0; --n, to += 8) {
00384 to[0] = 0;
00385 to[1] = 0;
00386 to[2] = 0;
00387 to[3] = 0;
00388 to[4] = 0;
00389 to[5] = 0;
00390 to[6] = 0;
00391 to[7] = 0;
00392 }
00393 switch (size % 8) {
00394 case 7: to[6] = 0;
00395 case 6: to[5] = 0;
00396 case 5: to[4] = 0;
00397 case 4: to[3] = 0;
00398 case 3: to[2] = 0;
00399 case 2: to[1] = 0;
00400 case 1: to[0] = 0;
00401 case 0: break;
00402 }
00403 #else
00404
00405 register int n = (size + 7) / 8;
00406 --to;
00407 switch (size % 8) {
00408 case 0: do{ *++to = 0;
00409 case 7: *++to = 0;
00410 case 6: *++to = 0;
00411 case 5: *++to = 0;
00412 case 4: *++to = 0;
00413 case 3: *++to = 0;
00414 case 2: *++to = 0;
00415 case 1: *++to = 0;
00416 }while(--n>0);
00417 }
00418 #endif
00419 #endif
00420 }
00422 inline void
00423 CoinCheckDoubleZero(double * to, const int size)
00424 {
00425 int n=0;
00426 for (int j=0;j<size;j++) {
00427 if (to[j])
00428 n++;
00429 }
00430 if (n) {
00431 printf("array of length %d should be zero has %d nonzero\n",size,n);
00432 }
00433 }
00435 inline void
00436 CoinCheckIntZero(int * to, const int size)
00437 {
00438 int n=0;
00439 for (int j=0;j<size;j++) {
00440 if (to[j])
00441 n++;
00442 }
00443 if (n) {
00444 printf("array of length %d should be zero has %d nonzero\n",size,n);
00445 }
00446 }
00447
00448
00449
00453 template <class T> inline void
00454 CoinZero(register T* first, register T* last)
00455 {
00456 CoinZeroN(first, last - first);
00457 }
00458
00459
00460
00464 template <class T> inline T
00465 CoinMax(register const T x1, register const T x2)
00466 {
00467 return (x1 > x2) ? x1 : x2;
00468 }
00469
00470
00471
00475 template <class T> inline T
00476 CoinMin(register const T x1, register const T x2)
00477 {
00478 return (x1 < x2) ? x1 : x2;
00479 }
00480
00481
00482
00486 template <class T> inline T
00487 CoinAbs(const T value)
00488 {
00489 return value<0 ? -value : value;
00490 }
00491
00492
00493
00497 template <class T> inline bool
00498 CoinIsSorted(register const T* first, const int size)
00499 {
00500 if (size == 0)
00501 return true;
00502
00503 if (size < 0)
00504 throw CoinError("negative number of entries", "CoinIsSorted", "");
00505
00506 #if 1
00507
00508 const int size1 = size - 1;
00509 for (register int n = size1 / 8; n > 0; --n, first += 8) {
00510 if (first[8] < first[7]) return false;
00511 if (first[7] < first[6]) return false;
00512 if (first[6] < first[5]) return false;
00513 if (first[5] < first[4]) return false;
00514 if (first[4] < first[3]) return false;
00515 if (first[3] < first[2]) return false;
00516 if (first[2] < first[1]) return false;
00517 if (first[1] < first[0]) return false;
00518 }
00519
00520 switch (size1 % 8) {
00521 case 7: if (first[7] < first[6]) return false;
00522 case 6: if (first[6] < first[5]) return false;
00523 case 5: if (first[5] < first[4]) return false;
00524 case 4: if (first[4] < first[3]) return false;
00525 case 3: if (first[3] < first[2]) return false;
00526 case 2: if (first[2] < first[1]) return false;
00527 case 1: if (first[1] < first[0]) return false;
00528 case 0: break;
00529 }
00530 #else
00531 register const T* next = first;
00532 register const T* last = first + size;
00533 for (++next; next != last; first = next, ++next)
00534 if (*next < *first)
00535 return false;
00536 #endif
00537 return true;
00538 }
00539
00540
00541
00545 template <class T> inline bool
00546 CoinIsSorted(register const T* first, register const T* last)
00547 {
00548 return CoinIsSorted(first, static_cast<int>(last - first));
00549 }
00550
00551
00552
00556 template <class T> inline void
00557 CoinIotaN(register T* first, const int size, register T init)
00558 {
00559 if (size == 0)
00560 return;
00561
00562 if (size < 0)
00563 throw CoinError("negative number of entries", "CoinIotaN", "");
00564
00565 #if 1
00566 for (register int n = size / 8; n > 0; --n, first += 8, init += 8) {
00567 first[0] = init;
00568 first[1] = init + 1;
00569 first[2] = init + 2;
00570 first[3] = init + 3;
00571 first[4] = init + 4;
00572 first[5] = init + 5;
00573 first[6] = init + 6;
00574 first[7] = init + 7;
00575 }
00576 switch (size % 8) {
00577 case 7: first[6] = init + 6;
00578 case 6: first[5] = init + 5;
00579 case 5: first[4] = init + 4;
00580 case 4: first[3] = init + 3;
00581 case 3: first[2] = init + 2;
00582 case 2: first[1] = init + 1;
00583 case 1: first[0] = init;
00584 case 0: break;
00585 }
00586 #else
00587
00588 register int n = (size + 7) / 8;
00589 --first;
00590 --init;
00591 switch (size % 8) {
00592 case 0: do{ *++first = ++init;
00593 case 7: *++first = ++init;
00594 case 6: *++first = ++init;
00595 case 5: *++first = ++init;
00596 case 4: *++first = ++init;
00597 case 3: *++first = ++init;
00598 case 2: *++first = ++init;
00599 case 1: *++first = ++init;
00600 }while(--n>0);
00601 }
00602 #endif
00603 }
00604
00605
00606
00610 template <class T> inline void
00611 CoinIota(T* first, const T* last, T init)
00612 {
00613 CoinIotaN(first, last-first, init);
00614 }
00615
00616
00617
00623 template <class T> inline T *
00624 CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast,
00625 const int * firstDelPos, const int * lastDelPos)
00626 {
00627 int delNum = lastDelPos - firstDelPos;
00628 if (delNum == 0)
00629 return arrayLast;
00630
00631 if (delNum < 0)
00632 throw CoinError("trying to delete negative number of entries",
00633 "CoinDeleteEntriesFromArray", "");
00634
00635 int * delSortedPos = NULL;
00636 if (! (CoinIsSorted(firstDelPos, lastDelPos) &&
00637 std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) {
00638
00639 delSortedPos = new int[delNum];
00640 CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos);
00641 std::sort(delSortedPos, delSortedPos + delNum);
00642 delNum = std::unique(delSortedPos, delSortedPos + delNum) - delSortedPos;
00643 }
00644 const int * delSorted = delSortedPos ? delSortedPos : firstDelPos;
00645
00646 const int last = delNum - 1;
00647 int size = delSorted[0];
00648 for (int i = 0; i < last; ++i) {
00649 const int copyFirst = delSorted[i] + 1;
00650 const int copyLast = delSorted[i+1];
00651 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00652 arrayFirst + size);
00653 size += copyLast - copyFirst;
00654 }
00655 const int copyFirst = delSorted[last] + 1;
00656 const int copyLast = arrayLast - arrayFirst;
00657 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00658 arrayFirst + size);
00659 size += copyLast - copyFirst;
00660
00661 if (delSortedPos)
00662 delete[] delSortedPos;
00663
00664 return arrayFirst + size;
00665 }
00666
00667
00668
00670 inline void CoinSeedRandom(int iseed)
00671 {
00672 int jseed;
00673 jseed = iseed + 69822;
00674 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00675 srand(jseed);
00676 #else
00677 srand48(jseed);
00678 #endif
00679 }
00680
00682 inline double CoinDrand48()
00683 {
00684 double retVal;
00685 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00686 retVal=rand();
00687 retVal=retVal/(double) RAND_MAX;
00688 #else
00689 retVal = drand48();
00690 #endif
00691 return retVal;
00692 }
00693
00694
00695
00698 inline char CoinFindDirSeparator()
00699 {
00700 int size = 1000;
00701 char* buf = 0;
00702 while (true) {
00703 buf = new char[size];
00704 if (getcwd(buf, size))
00705 break;
00706 delete[] buf;
00707 buf = 0;
00708 size = 2*size;
00709 }
00710
00711
00712 char dirsep = buf[0] == '/' ? '/' : '\\';
00713 delete[] buf;
00714 return dirsep;
00715 }
00716
00717
00718 inline int CoinStrNCaseCmp(const char* s0, const char* s1,
00719 const size_t len)
00720 {
00721 for (size_t i = 0; i < len; ++i) {
00722 if (s0[i] == 0) {
00723 return s1[i] == 0 ? 0 : -1;
00724 }
00725 if (s1[i] == 0) {
00726 return 1;
00727 }
00728 const int c0 = tolower(s0[i]);
00729 const int c1 = tolower(s1[i]);
00730 if (c0 < c1)
00731 return -1;
00732 if (c0 > c1)
00733 return 1;
00734 }
00735 return 0;
00736 }
00737
00738
00739
00741 template <class T> inline void CoinSwap (T &x, T &y)
00742 {
00743 T t = x;
00744 x = y;
00745 y = t;
00746 }
00747
00748
00749
00754 template <class T> inline int
00755 CoinToFile( const T* array, int size, FILE * fp)
00756 {
00757 int numberWritten;
00758 if (array&&size) {
00759 numberWritten = fwrite(&size,sizeof(int),1,fp);
00760 if (numberWritten!=1)
00761 return 1;
00762 numberWritten = fwrite(array,sizeof(T),size,fp);
00763 if (numberWritten!=size)
00764 return 1;
00765 } else {
00766 size = 0;
00767 numberWritten = fwrite(&size,sizeof(int),1,fp);
00768 if (numberWritten!=1)
00769 return 1;
00770 }
00771 return 0;
00772 }
00773
00774
00775
00782 template <class T> inline int
00783 CoinFromFile( T* &array, int size, FILE * fp,int & newSize)
00784 {
00785 int numberRead;
00786 numberRead = fread(&newSize,sizeof(int),1,fp);
00787 if (numberRead!=1)
00788 return 1;
00789 int returnCode=0;
00790 if (size!=newSize&&(newSize||array))
00791 returnCode=2;
00792 if (newSize) {
00793 array = new T [newSize];
00794 numberRead = fread(array,sizeof(T),newSize,fp);
00795 if (numberRead!=newSize)
00796 returnCode=1;
00797 } else {
00798 array = NULL;
00799 }
00800 return returnCode;
00801 }
00802
00803
00804
00806 inline double CoinCbrt(double x)
00807 {
00808 #if defined(_MSC_VER)
00809 return pow(x,(1./3.));
00810 #else
00811 return cbrt(x);
00812 #endif
00813 }
00814
00815 #endif