/home/coin/SVN-release/Cbc-1.1.1/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     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         // Use Duff's device to copy
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         // Use Duff's device to copy
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     // Use memcpy - seems a lot faster on Intel with gcc
00211 #ifndef NDEBUG
00212     // Some debug so check
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     // Use Duff's device to fill
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     // Use memset - seems faster on Intel with gcc
00354 #ifndef NDEBUG
00355     // Some debug so check
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     // Use Duff's device to fill
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     // size1 is the number of comparisons to be made
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     // Use Duff's device to fill
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         // the positions of the to be deleted is either not sorted or not unique
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     // if first char is '/' then it's unix and the dirsep is '/'. otherwise we 
00697     // assume it's dos and the dirsep is '\'
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

Generated on Thu May 15 21:59:05 2008 by  doxygen 1.4.7