- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# /home/coin/SVN-release/Clp-1.5.0/CoinUtils/src/CoinHelperFunctions.hpp

Go to the documentation of this file.

    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 #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         // 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 #if 0
    00100     /* There is no point to do this test. If to and from are from different
    00101        blocks then dist is undefined, so this can crash correct code. It's
    00102        better to trust the user that the arrays are really disjoint. */
    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     // Use memcpy - seems a lot faster on Intel with gcc
    00215 #ifndef NDEBUG
    00216     // Some debug so check
    00217     if (size < 0)
    00218         throw CoinError("trying to copy negative number of entries",
    00219                         "CoinMemcpyN", "");
    00220
    00221 #if 0
    00222     /* There is no point to do this test. If to and from are from different
    00223        blocks then dist is undefined, so this can crash correct code. It's
    00224        better to trust the user that the arrays are really disjoint. */
    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     /* There is no point to do this test. If to and from are from different
    00241        blocks then dist is undefined, so this can crash correct code. It's
    00242        better to trust the user that the arrays are really disjoint. */
    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     // Use Duff's device to fill
    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     // Use memset - seems faster on Intel with gcc
    00368 #ifndef NDEBUG
    00369     // Some debug so check
    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     // Use Duff's device to fill
    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     // size1 is the number of comparisons to be made
    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     // Use Duff's device to fill
    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         // the positions of the to be deleted is either not sorted or not unique
    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     // if first char is '/' then it's unix and the dirsep is '/'. otherwise we
    00711     // assume it's dos and the dirsep is '\'
    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