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
00014 #include "CoinError.hpp"
00015
00016
00022 template <class T> inline void
00023 CoinCopyN(register const T* from, const int size, register T* to)
00024 {
00025 if (size == 0 || from == to)
00026 return;
00027
00028 if (size < 0)
00029 throw CoinError("trying to copy negative number of entries",
00030 "CoinCopyN", "");
00031
00032 const int dist = to - from;
00033 register int n = (size + 7) / 8;
00034 if (dist > 0) {
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 const int dist = to - from;
00100 if (-size < dist && dist < size)
00101 throw CoinError("overlapping arrays", "CoinDisjointCopyN", "");
00102
00103 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00104 to[0] = from[0];
00105 to[1] = from[1];
00106 to[2] = from[2];
00107 to[3] = from[3];
00108 to[4] = from[4];
00109 to[5] = from[5];
00110 to[6] = from[6];
00111 to[7] = from[7];
00112 }
00113 switch (size % 8) {
00114 case 7: to[6] = from[6];
00115 case 6: to[5] = from[5];
00116 case 5: to[4] = from[4];
00117 case 4: to[3] = from[3];
00118 case 3: to[2] = from[2];
00119 case 2: to[1] = from[1];
00120 case 1: to[0] = from[0];
00121 case 0: break;
00122 }
00123 #else
00124 CoinCopyN(from, size, to);
00125 #endif
00126 }
00127
00128
00129
00134 template <class T> inline void
00135 CoinDisjointCopy(register const T* first, register const T* last,
00136 register T* to)
00137 {
00138 CoinDisjointCopyN(first, static_cast<int>(last - first), to);
00139 }
00140
00141
00142
00150 template <class T> inline void
00151 CoinMemcpyN(register const T* from, const int size, register T* to)
00152 {
00153 #ifndef _MSC_VER
00154 #ifdef USE_MEMCPY
00155
00156 #ifndef NDEBUG
00157
00158 if (size < 0)
00159 throw CoinError("trying to copy negative number of entries",
00160 "CoinMemcpyN", "");
00161
00162 const int dist = to - from;
00163 if (-size < dist && dist < size)
00164 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00165 #endif
00166 memcpy(to,from,size*sizeof(T));
00167 #else
00168 if (size == 0 || from == to)
00169 return;
00170
00171 if (size < 0)
00172 throw CoinError("trying to copy negative number of entries",
00173 "CoinMemcpyN", "");
00174
00175 const int dist = to - from;
00176 if (-size < dist && dist < size)
00177 throw CoinError("overlapping arrays", "CoinMemcpyN", "");
00178
00179 for (register int n = size / 8; n > 0; --n, from += 8, to += 8) {
00180 to[0] = from[0];
00181 to[1] = from[1];
00182 to[2] = from[2];
00183 to[3] = from[3];
00184 to[4] = from[4];
00185 to[5] = from[5];
00186 to[6] = from[6];
00187 to[7] = from[7];
00188 }
00189 switch (size % 8) {
00190 case 7: to[6] = from[6];
00191 case 6: to[5] = from[5];
00192 case 5: to[4] = from[4];
00193 case 4: to[3] = from[3];
00194 case 3: to[2] = from[2];
00195 case 2: to[1] = from[1];
00196 case 1: to[0] = from[0];
00197 case 0: break;
00198 }
00199 #endif
00200 #else
00201 CoinCopyN(from, size, to);
00202 #endif
00203 }
00204
00205
00206
00211 template <class T> inline void
00212 CoinMemcpy(register const T* first, register const T* last,
00213 register T* to)
00214 {
00215 CoinMemcpyN(first, static_cast<int>(last - first), to);
00216 }
00217
00218
00219
00226 template <class T> inline void
00227 CoinFillN(register T* to, const int size, register const T value)
00228 {
00229 if (size == 0)
00230 return;
00231
00232 if (size < 0)
00233 throw CoinError("trying to fill negative number of entries",
00234 "CoinFillN", "");
00235
00236 #if 1
00237 for (register int n = size / 8; n > 0; --n, to += 8) {
00238 to[0] = value;
00239 to[1] = value;
00240 to[2] = value;
00241 to[3] = value;
00242 to[4] = value;
00243 to[5] = value;
00244 to[6] = value;
00245 to[7] = value;
00246 }
00247 switch (size % 8) {
00248 case 7: to[6] = value;
00249 case 6: to[5] = value;
00250 case 5: to[4] = value;
00251 case 4: to[3] = value;
00252 case 3: to[2] = value;
00253 case 2: to[1] = value;
00254 case 1: to[0] = value;
00255 case 0: break;
00256 }
00257 #else
00258
00259 register int n = (size + 7) / 8;
00260 --to;
00261 switch (size % 8) {
00262 case 0: do{ *++to = value;
00263 case 7: *++to = value;
00264 case 6: *++to = value;
00265 case 5: *++to = value;
00266 case 4: *++to = value;
00267 case 3: *++to = value;
00268 case 2: *++to = value;
00269 case 1: *++to = value;
00270 }while(--n>0);
00271 }
00272 #endif
00273 }
00274
00275
00276
00280 template <class T> inline void
00281 CoinFill(register T* first, register T* last, const T value)
00282 {
00283 CoinFillN(first, last - first, value);
00284 }
00285
00286
00287
00294 template <class T> inline void
00295 CoinZeroN(register T* to, const int size)
00296 {
00297 #ifdef USE_MEMCPY
00298
00299 #ifndef NDEBUG
00300
00301 if (size < 0)
00302 throw CoinError("trying to fill negative number of entries",
00303 "CoinZeroN", "");
00304 #endif
00305 memset(to,0,size*sizeof(T));
00306 #else
00307 if (size == 0)
00308 return;
00309
00310 if (size < 0)
00311 throw CoinError("trying to fill negative number of entries",
00312 "CoinZeroN", "");
00313
00314 #if 1
00315 for (register int n = size / 8; n > 0; --n, to += 8) {
00316 to[0] = 0;
00317 to[1] = 0;
00318 to[2] = 0;
00319 to[3] = 0;
00320 to[4] = 0;
00321 to[5] = 0;
00322 to[6] = 0;
00323 to[7] = 0;
00324 }
00325 switch (size % 8) {
00326 case 7: to[6] = 0;
00327 case 6: to[5] = 0;
00328 case 5: to[4] = 0;
00329 case 4: to[3] = 0;
00330 case 3: to[2] = 0;
00331 case 2: to[1] = 0;
00332 case 1: to[0] = 0;
00333 case 0: break;
00334 }
00335 #else
00336
00337 register int n = (size + 7) / 8;
00338 --to;
00339 switch (size % 8) {
00340 case 0: do{ *++to = 0;
00341 case 7: *++to = 0;
00342 case 6: *++to = 0;
00343 case 5: *++to = 0;
00344 case 4: *++to = 0;
00345 case 3: *++to = 0;
00346 case 2: *++to = 0;
00347 case 1: *++to = 0;
00348 }while(--n>0);
00349 }
00350 #endif
00351 #endif
00352 }
00353
00354
00355
00359 template <class T> inline void
00360 CoinZero(register T* first, register T* last, const T value)
00361 {
00362 CoinZeroN(first, last - first, value);
00363 }
00364
00365
00366
00370 template <class T> inline T
00371 CoinMax(register const T x1, register const T x2)
00372 {
00373 return (x1 > x2) ? x1 : x2;
00374 }
00375
00376
00377
00381 template <class T> inline T
00382 CoinMin(register const T x1, register const T x2)
00383 {
00384 return (x1 < x2) ? x1 : x2;
00385 }
00386
00387
00388
00392 template <class T> inline T
00393 CoinAbs(const T value)
00394 {
00395 return value<0 ? -value : value;
00396 }
00397
00398
00399
00403 template <class T> inline bool
00404 CoinIsSorted(register const T* first, const int size)
00405 {
00406 if (size == 0)
00407 return true;
00408
00409 if (size < 0)
00410 throw CoinError("negative number of entries", "CoinIsSorted", "");
00411
00412 #if 1
00413
00414 const int size1 = size - 1;
00415 for (register int n = size1 / 8; n > 0; --n, first += 8) {
00416 if (first[8] < first[7]) return false;
00417 if (first[7] < first[6]) return false;
00418 if (first[6] < first[5]) return false;
00419 if (first[5] < first[4]) return false;
00420 if (first[4] < first[3]) return false;
00421 if (first[3] < first[2]) return false;
00422 if (first[2] < first[1]) return false;
00423 if (first[1] < first[0]) return false;
00424 }
00425
00426 switch (size1 % 8) {
00427 case 7: if (first[7] < first[6]) return false;
00428 case 6: if (first[6] < first[5]) return false;
00429 case 5: if (first[5] < first[4]) return false;
00430 case 4: if (first[4] < first[3]) return false;
00431 case 3: if (first[3] < first[2]) return false;
00432 case 2: if (first[2] < first[1]) return false;
00433 case 1: if (first[1] < first[0]) return false;
00434 case 0: break;
00435 }
00436 #else
00437 register const T* next = first;
00438 register const T* last = first + size;
00439 for (++next; next != last; first = next, ++next)
00440 if (*next < *first)
00441 return false;
00442 #endif
00443 return true;
00444 }
00445
00446
00447
00451 template <class T> inline bool
00452 CoinIsSorted(register const T* first, register const T* last)
00453 {
00454 return CoinIsSorted(first, static_cast<int>(last - first));
00455 }
00456
00457
00458
00462 template <class T> inline void
00463 CoinIotaN(register T* first, const int size, register T init)
00464 {
00465 if (size == 0)
00466 return;
00467
00468 if (size < 0)
00469 throw CoinError("negative number of entries", "CoinIotaN", "");
00470
00471 #if 1
00472 for (register int n = size / 8; n > 0; --n, first += 8, init += 8) {
00473 first[0] = init;
00474 first[1] = init + 1;
00475 first[2] = init + 2;
00476 first[3] = init + 3;
00477 first[4] = init + 4;
00478 first[5] = init + 5;
00479 first[6] = init + 6;
00480 first[7] = init + 7;
00481 }
00482 switch (size % 8) {
00483 case 7: first[6] = init + 6;
00484 case 6: first[5] = init + 5;
00485 case 5: first[4] = init + 4;
00486 case 4: first[3] = init + 3;
00487 case 3: first[2] = init + 2;
00488 case 2: first[1] = init + 1;
00489 case 1: first[0] = init;
00490 case 0: break;
00491 }
00492 #else
00493
00494 register int n = (size + 7) / 8;
00495 --first;
00496 --init;
00497 switch (size % 8) {
00498 case 0: do{ *++first = ++init;
00499 case 7: *++first = ++init;
00500 case 6: *++first = ++init;
00501 case 5: *++first = ++init;
00502 case 4: *++first = ++init;
00503 case 3: *++first = ++init;
00504 case 2: *++first = ++init;
00505 case 1: *++first = ++init;
00506 }while(--n>0);
00507 }
00508 #endif
00509 }
00510
00511
00512
00516 template <class T> inline void
00517 CoinIota(T* first, const T* last, T init)
00518 {
00519 CoinIotaN(first, last-first, init);
00520 }
00521
00522
00523
00529 template <class T> inline T *
00530 CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast,
00531 const int * firstDelPos, const int * lastDelPos)
00532 {
00533 int delNum = lastDelPos - firstDelPos;
00534 if (delNum == 0)
00535 return arrayLast;
00536
00537 if (delNum < 0)
00538 throw CoinError("trying to delete negative number of entries",
00539 "CoinDeleteEntriesFromArray", "");
00540
00541 int * delSortedPos = NULL;
00542 if (! (CoinIsSorted(firstDelPos, lastDelPos) &&
00543 std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) {
00544
00545 delSortedPos = new int[delNum];
00546 CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos);
00547 std::sort(delSortedPos, delSortedPos + delNum);
00548 delNum = std::unique(delSortedPos, delSortedPos + delNum) - delSortedPos;
00549 }
00550 const int * delSorted = delSortedPos ? delSortedPos : firstDelPos;
00551
00552 const int last = delNum - 1;
00553 int size = delSorted[0];
00554 for (int i = 0; i < last; ++i) {
00555 const int copyFirst = delSorted[i] + 1;
00556 const int copyLast = delSorted[i+1];
00557 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00558 arrayFirst + size);
00559 size += copyLast - copyFirst;
00560 }
00561 const int copyFirst = delSorted[last] + 1;
00562 const int copyLast = arrayLast - arrayFirst;
00563 CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast,
00564 arrayFirst + size);
00565 size += copyLast - copyFirst;
00566
00567 if (delSortedPos)
00568 delete[] delSortedPos;
00569
00570 return arrayFirst + size;
00571 }
00572
00573
00574
00576 inline void CoinSeedRandom(int iseed)
00577 {
00578 int jseed;
00579 jseed = iseed + 69822;
00580 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00581 srand(jseed);
00582 #else
00583 srand48(jseed);
00584 #endif
00585 }
00586
00588 inline double CoinDrand48()
00589 {
00590 double retVal;
00591 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__)
00592 retVal=rand();
00593 retVal=retVal/(double) RAND_MAX;
00594 #else
00595 retVal = drand48();
00596 #endif
00597 return retVal;
00598 }
00599
00600
00601
00604 inline char CoinFindDirSeparator()
00605 {
00606 size_t size = 1000;
00607 char* buf = 0;
00608 while (true) {
00609 buf = new char[size];
00610 if (getcwd(buf, size))
00611 break;
00612 delete[] buf;
00613 buf = 0;
00614 size = 2*size;
00615 }
00616
00617
00618 char dirsep = buf[0] == '/' ? '/' : '\\';
00619 delete[] buf;
00620 return dirsep;
00621 }
00622
00623 #endif