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 const long dist = to - from;
00034 register int n = (size + 7) / 8;
00035 if (dist > 0) {
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 const long dist = to - from;
00101 if (-size < dist && dist < size)
00102 throw CoinError("overlapping arrays", "CoinDisjointCopyN", "");
00103
00104 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00105 to[0] = from[0];
00106 to[1] = from[1];
00107 to[2] = from[2];
00108 to[3] = from[3];
00109 to[4] = from[4];
00110 to[5] = from[5];
00111 to[6] = from[6];
00112 to[7] = from[7];
00113 }
00114 switch (size % 8) {
00115 case 7: to[6] = from[6];
00116 case 6: to[5] = from[5];
00117 case 5: to[4] = from[4];
00118 case 4: to[3] = from[3];
00119 case 3: to[2] = from[2];
00120 case 2: to[1] = from[1];
00121 case 1: to[0] = from[0];
00122 case 0: break;
00123 }
00124 #else
00125 CoinCopyN(from, size, to);
00126 #endif
00127 }
00128
00129
00130
00135 template <class T> inline void
00136 CoinDisjointCopy(register const T* first, register const T* last,
00137 register T* to)
00138 {
00139 CoinDisjointCopyN(first, static_cast<int>(last - first), to);
00140 }
00141
00142
00143
00148 template <class T> inline T*
00149 CoinCopyOfArray( const T * array, const int size)
00150 {
00151 if (array) {
00152 T * arrayNew = new T[size];
00153 memcpy(arrayNew,array,size*sizeof(T));
00154 return arrayNew;
00155 } else {
00156 return NULL;
00157 }
00158 }
00159
00164 template <class T> inline T*
00165 CoinCopyOfArray( const T * array, const int size, T value)
00166 {
00167 T * arrayNew = new T[size];
00168 if (array) {
00169 memcpy(arrayNew,array,size*sizeof(T));
00170 } else {
00171 int i;
00172 for (i=0;i<size;i++)
00173 arrayNew[i] = value;
00174 }
00175 return arrayNew;
00176 }
00177
00178
00183 template <class T> inline T*
00184 CoinCopyOfArrayOrZero( const T * array , const int size)
00185 {
00186 T * arrayNew = new T[size];
00187 if (array) {
00188 memcpy(arrayNew,array,size*sizeof(T));
00189 } else {
00190 memset(arrayNew,0,size*sizeof(T));
00191 }
00192 return arrayNew;
00193 }
00194
00195
00196
00197
00205 template <class T> inline void
00206 CoinMemcpyN(register const T* from, const int size, register T* to)
00207 {
00208 #ifndef _MSC_VER
00209 #ifdef USE_MEMCPY
00210
00211 #ifndef NDEBUG
00212
00213 if (size < 0)
00214 throw CoinError("trying to copy negative number of entries",
00215 "CoinMemcpyN", "");
00216
00217 const long dist = to - from;
00218 if (-size < dist && dist < size)
00219 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00220 #endif
00221 memcpy(to,from,size*sizeof(T));
00222 #else
00223 if (size == 0 || from == to)
00224 return;
00225
00226 if (size < 0)
00227 throw CoinError("trying to copy negative number of entries",
00228 "CoinMemcpyN", "");
00229
00230 const long dist = to - from;
00231 if (-size < dist && dist < size)
00232 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00233
00234 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00235 to[0] = from[0];
00236 to[1] = from[1];
00237 to[2] = from[2];
00238 to[3] = from[3];
00239 to[4] = from[4];
00240 to[5] = from[5];
00241 to[6] = from[6];
00242 to[7] = from[7];
00243 }
00244 switch (size % 8) {
00245 case 7: to[6] = from[6];
00246 case 6: to[5] = from[5];
00247 case 5: to[4] = from[4];
00248 case 4: to[3] = from[3];
00249 case 3: to[2] = from[2];
00250 case 2: to[1] = from[1];
00251 case 1: to[0] = from[0];
00252 case 0: break;
00253 }
00254 #endif
00255 #else
00256 CoinCopyN(from, size, to);
00257 #endif
00258 }
00259
00260
00261
00266 template <class T> inline void
00267 CoinMemcpy(register const T* first, register const T* last,
00268 register T* to)
00269 {
00270 CoinMemcpyN(first, static_cast<int>(last - first), to);
00271 }
00272
00273
00274
00281 template <class T> inline void
00282 CoinFillN(register T* to, const int size, register const T value)
00283 {
00284 if (size == 0)
00285 return;
00286
00287 if (size < 0)
00288 throw CoinError("trying to fill negative number of entries",
00289 "CoinFillN", "");
00290
00291 #if 1
00292 for (register int n = size / 8; n > 0; --n, to += 8) {
00293 to[0] = value;
00294 to[1] = value;
00295 to[2] = value;
00296 to[3] = value;
00297 to[4] = value;
00298 to[5] = value;
00299 to[6] = value;
00300 to[7] = value;
00301 }
00302 switch (size % 8) {
00303 case 7: to[6] = value;
00304 case 6: to[5] = value;
00305 case 5: to[4] = value;
00306 case 4: to[3] = value;
00307 case 3: to[2] = value;
00308 case 2: to[1] = value;
00309 case 1: to[0] = value;
00310 case 0: break;
00311 }
00312 #else
00313
00314 register int n = (size + 7) / 8;
00315 --to;
00316 switch (size % 8) {
00317 case 0: do{ *++to = value;
00318 case 7: *++to = value;
00319 case 6: *++to = value;
00320 case 5: *++to = value;
00321 case 4: *++to = value;
00322 case 3: *++to = value;
00323 case 2: *++to = value;
00324 case 1: *++to = value;
00325 }while(--n>0);
00326 }
00327 #endif
00328 }
00329
00330
00331
00335 template <class T> inline void
00336 CoinFill(register T* first, register T* last, const T value)
00337 {
00338 CoinFillN(first, last - first, value);
00339 }
00340
00341
00342
00349 template <class T> inline void
00350 CoinZeroN(register T* to, const int size)
00351 {
00352 #ifdef USE_MEMCPY
00353
00354 #ifndef NDEBUG
00355
00356 if (size < 0)
00357 throw CoinError("trying to fill negative number of entries",
00358 "CoinZeroN", "");
00359 #endif
00360 memset(to,0,size*sizeof(T));
00361 #else
00362 if (size == 0)
00363 return;
00364
00365 if (size < 0)
00366 throw CoinError("trying to fill negative number of entries",
00367 "CoinZeroN", "");
00368 #if 1
00369 for (register int n = size / 8; n > 0; --n, to += 8) {
00370 to[0] = 0;
00371 to[1] = 0;
00372 to[2] = 0;
00373 to[3] = 0;
00374 to[4] = 0;
00375 to[5] = 0;
00376 to[6] = 0;
00377 to[7] = 0;
00378 }
00379 switch (size % 8) {
00380 case 7: to[6] = 0;
00381 case 6: to[5] = 0;
00382 case 5: to[4] = 0;
00383 case 4: to[3] = 0;
00384 case 3: to[2] = 0;
00385 case 2: to[1] = 0;
00386 case 1: to[0] = 0;
00387 case 0: break;
00388 }
00389 #else
00390
00391 register int n = (size + 7) / 8;
00392 --to;
00393 switch (size % 8) {
00394 case 0: do{ *++to = 0;
00395 case 7: *++to = 0;
00396 case 6: *++to = 0;
00397 case 5: *++to = 0;
00398 case 4: *++to = 0;
00399 case 3: *++to = 0;
00400 case 2: *++to = 0;
00401 case 1: *++to = 0;
00402 }while(--n>0);
00403 }
00404 #endif
00405 #endif
00406 }
00408 inline void
00409 CoinCheckDoubleZero(double * to, const int size)
00410 {
00411 int n=0;
00412 for (int j=0;j<size;j++) {
00413 if (to[j])
00414 n++;
00415 }
00416 if (n) {
00417 printf("array of length %d should be zero has %d nonzero\n",size,n);
00418 }
00419 }
00421 inline void
00422 CoinCheckIntZero(int * to, const int size)
00423 {
00424 int n=0;
00425 for (int j=0;j<size;j++) {
00426 if (to[j])
00427 n++;
00428 }
00429 if (n) {
00430 printf("array of length %d should be zero has %d nonzero\n",size,n);
00431 }
00432 }
00433
00434
00435
00439 template <class T> inline void
00440 CoinZero(register T* first, register T* last)
00441 {
00442 CoinZeroN(first, last - first);
00443 }
00444
00445
00446
00450 template <class T> inline T
00451 CoinMax(register const T x1, register const T x2)
00452 {
00453 return (x1 > x2) ? x1 : x2;
00454 }
00455
00456
00457
00461 template <class T> inline T
00462 CoinMin(register const T x1, register const T x2)
00463 {
00464 return (x1 < x2) ? x1 : x2;
00465 }
00466
00467
00468
00472 template <class T> inline T
00473 CoinAbs(const T value)
00474 {
00475 return value<0 ? -value : value;
00476 }
00477
00478
00479
00483 template <class T> inline bool
00484 CoinIsSorted(register const T* first, const int size)
00485 {
00486 if (size == 0)
00487 return true;
00488
00489 if (size < 0)
00490 throw CoinError("negative number of entries", "CoinIsSorted", "");
00491
00492 #if 1
00493
00494 const int size1 = size - 1;
00495 for (register int n = size1 / 8; n > 0; --n, first += 8) {
00496 if (first[8] < first[7]) return false;
00497 if (first[7] < first[6]) return false;
00498 if (first[6] < first[5]) return false;
00499 if (first[5] < first[4]) return false;
00500 if (first[4] < first[3]) return false;
00501 if (first[3] < first[2]) return false;
00502 if (first[2] < first[1]) return false;
00503 if (first[1] < first[0]) return false;
00504 }
00505
00506 switch (size1 % 8) {
00507 case 7: if (first[7] < first[6]) return false;
00508 case 6: if (first[6] < first[5]) return false;
00509 case 5: if (first[5] < first[4]) return false;
00510 case 4: if (first[4] < first[3]) return false;
00511 case 3: if (first[3] < first[2]) return false;
00512 case 2: if (first[2] < first[1]) return false;
00513 case 1: if (first[1] < first[0]) return false;
00514 case 0: break;
00515 }
00516 #else
00517 register const T* next = first;
00518 register const T* last = first + size;
00519 for (++next; next != last; first = next, ++next)
00520 if (*next < *first)
00521 return false;
00522 #endif
00523 return true;
00524 }
00525
00526
00527
00531 template <class T> inline bool
00532 CoinIsSorted(register const T* first, register const T* last)
00533 {
00534 return CoinIsSorted(first, static_cast<int>(last - first));
00535 }
00536
00537
00538
00542 template <class T> inline void
00543 CoinIotaN(register T* first, const int size, register T init)
00544 {
00545 if (size == 0)
00546 return;
00547
00548 if (size < 0)
00549 throw CoinError("negative number of entries", "CoinIotaN", "");
00550
00551 #if 1
00552 for (register int n = size / 8; n > 0; --n, first += 8, init += 8) {
00553 first[0] = init;
00554 first[1] = init + 1;
00555 first[2] = init + 2;
00556 first[3] = init + 3;
00557 first[4] = init + 4;
00558 first[5] = init + 5;
00559 first[6] = init + 6;
00560 first[7] = init + 7;
00561 }
00562 switch (size % 8) {
00563 case 7: first[6] = init + 6;
00564 case 6: first[5] = init + 5;
00565 case 5: first[4] = init + 4;
00566 case 4: first[3] = init + 3;
00567 case 3: first[2] = init + 2;
00568 case 2: first[1] = init + 1;
00569 case 1: first[0] = init;
00570 case 0: break;
00571 }
00572 #else
00573
00574 register int n = (size + 7) / 8;
00575 --first;
00576 --init;
00577 switch (size % 8) {
00578 case 0: do{ *++first = ++init;
00579 case 7: *++first = ++init;
00580 case 6: *++first = ++init;
00581 case 5: *++first = ++init;
00582 case 4: *++first = ++init;
00583 case 3: *++first = ++init;
00584 case 2: *++first = ++init;
00585 case 1: *++first = ++init;
00586 }while(--n>0);
00587 }
00588 #endif
00589 }
00590
00591
00592
00596 template <class T> inline void
00597 CoinIota(T* first, const T* last, T init)
00598 {
00599 CoinIotaN(first, last-first, init);
00600 }
00601
00602
00603
00609 template <class T> inline T *
00610 CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast,
00611 const int * firstDelPos, const int * lastDelPos)
00612 {
00613 int delNum = lastDelPos - firstDelPos;
00614 if (delNum == 0)
00615 return arrayLast;
00616
00617 if (delNum < 0)
00618 throw CoinError("trying to delete negative number of entries",
00619 "CoinDeleteEntriesFromArray", "");
00620
00621 int * delSortedPos = NULL;
00622 if (! (CoinIsSorted(firstDelPos, lastDelPos) &&
00623 std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) {
00624
00625 delSortedPos = new int[delNum];
00626 CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos);
00627 std::sort(delSortedPos, delSortedPos + delNum);
00628 delNum = std::unique(delSortedPos, delSortedPos + delNum) - delSortedPos;
00629 }
00630 const int * delSorted = delSortedPos ? delSortedPos : firstDelPos;
00631
00632 const int last = delNum - 1;
00633 int size = delSorted[0];
00634 for (int i = 0; i < last; ++i) {
00635 const int copyFirst = delSorted[i] + 1;
00636 const int copyLast = delSorted[i+1];
00637 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00638 arrayFirst + size);
00639 size += copyLast - copyFirst;
00640 }
00641 const int copyFirst = delSorted[last] + 1;
00642 const int copyLast = arrayLast - arrayFirst;
00643 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00644 arrayFirst + size);
00645 size += copyLast - copyFirst;
00646
00647 if (delSortedPos)
00648 delete[] delSortedPos;
00649
00650 return arrayFirst + size;
00651 }
00652
00653
00654
00656 inline void CoinSeedRandom(int iseed)
00657 {
00658 int jseed;
00659 jseed = iseed + 69822;
00660 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00661 srand(jseed);
00662 #else
00663 srand48(jseed);
00664 #endif
00665 }
00666
00668 inline double CoinDrand48()
00669 {
00670 double retVal;
00671 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00672 retVal=rand();
00673 retVal=retVal/(double) RAND_MAX;
00674 #else
00675 retVal = drand48();
00676 #endif
00677 return retVal;
00678 }
00679
00680
00681
00684 inline char CoinFindDirSeparator()
00685 {
00686 int size = 1000;
00687 char* buf = 0;
00688 while (true) {
00689 buf = new char[size];
00690 if (getcwd(buf, size))
00691 break;
00692 delete[] buf;
00693 buf = 0;
00694 size = 2*size;
00695 }
00696
00697
00698 char dirsep = buf[0] == '/' ? '/' : '\\';
00699 delete[] buf;
00700 return dirsep;
00701 }
00702
00703
00704 inline int CoinStrNCaseCmp(const char* s0, const char* s1,
00705 const size_t len)
00706 {
00707 for (size_t i = 0; i < len; ++i) {
00708 if (s0[i] == 0) {
00709 return s1[i] == 0 ? 0 : -1;
00710 }
00711 if (s1[i] == 0) {
00712 return 1;
00713 }
00714 const int c0 = tolower(s0[i]);
00715 const int c1 = tolower(s1[i]);
00716 if (c0 < c1)
00717 return -1;
00718 if (c0 > c1)
00719 return 1;
00720 }
00721 return 0;
00722 }
00723
00724
00725
00727 template <class T> inline void CoinSwap (T &x, T &y)
00728 {
00729 T t = x;
00730 x = y;
00731 y = t;
00732 }
00733
00734
00735
00740 template <class T> inline int
00741 CoinToFile( const T* array, int size, FILE * fp)
00742 {
00743 int numberWritten;
00744 if (array&&size) {
00745 numberWritten = fwrite(&size,sizeof(int),1,fp);
00746 if (numberWritten!=1)
00747 return 1;
00748 numberWritten = fwrite(array,sizeof(T),size,fp);
00749 if (numberWritten!=size)
00750 return 1;
00751 } else {
00752 size = 0;
00753 numberWritten = fwrite(&size,sizeof(int),1,fp);
00754 if (numberWritten!=1)
00755 return 1;
00756 }
00757 return 0;
00758 }
00759
00760
00761
00768 template <class T> inline int
00769 CoinFromFile( T* &array, int size, FILE * fp,int & newSize)
00770 {
00771 int numberRead;
00772 numberRead = fread(&newSize,sizeof(int),1,fp);
00773 if (numberRead!=1)
00774 return 1;
00775 int returnCode=0;
00776 if (size!=newSize&&(newSize||array))
00777 returnCode=2;
00778 if (newSize) {
00779 array = new T [newSize];
00780 numberRead = fread(array,sizeof(T),newSize,fp);
00781 if (numberRead!=newSize)
00782 returnCode=1;
00783 } else {
00784 array = NULL;
00785 }
00786 return returnCode;
00787 }
00788
00789
00790
00792 inline double CoinCbrt(double x)
00793 {
00794 #if defined(_MSC_VER)
00795 return pow(x,(1./3.));
00796 #else
00797 return cbrt(x);
00798 #endif
00799 }
00800
00801 #endif