/home/coin/SVN-release/Smi-0.81.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

Generated on Fri May 16 19:29:34 2008 by  doxygen 1.4.7