Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

CoinHelperFunctions.hpp

00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
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       // Use Duff's device to copy
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       // Use Duff's device to copy
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   // Use memcpy - seems a lot faster on Intel with gcc
00156 #ifndef NDEBUG
00157   // Some debug so check
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    // Use Duff's device to fill
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   // Use memset - seems faster on Intel with gcc
00299 #ifndef NDEBUG
00300   // Some debug so check
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    // Use Duff's device to fill
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    // size1 is the number of comparisons to be made
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    // Use Duff's device to fill
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       // the positions of the to be deleted is either not sorted or not unique
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   // if first char is '/' then it's unix and the dirsep is '/'. otherwise we 
00617   // assume it's dos and the dirsep is '\'
00618   char dirsep = buf[0] == '/' ? '/' : '\\';
00619   delete[] buf;
00620   return dirsep;
00621 }
00622 
00623 #endif

Generated on Wed Dec 3 14:34:18 2003 for Coin by doxygen 1.3.5