diff options
Diffstat (limited to 'build/Bonmin/include/coin/CoinHelperFunctions.hpp')
-rw-r--r-- | build/Bonmin/include/coin/CoinHelperFunctions.hpp | 1111 |
1 files changed, 1111 insertions, 0 deletions
diff --git a/build/Bonmin/include/coin/CoinHelperFunctions.hpp b/build/Bonmin/include/coin/CoinHelperFunctions.hpp new file mode 100644 index 0000000..3409bbc --- /dev/null +++ b/build/Bonmin/include/coin/CoinHelperFunctions.hpp @@ -0,0 +1,1111 @@ +/* $Id: CoinHelperFunctions.hpp 1679 2013-12-05 11:27:45Z forrest $ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinHelperFunctions_H +#define CoinHelperFunctions_H + +#include "CoinUtilsConfig.h" + +#if defined(_MSC_VER) +# include <direct.h> +# include <cctype> +# define getcwd _getcwd +# include <cctype> +#else +# include <unistd.h> +#endif +//#define USE_MEMCPY + +#include <cstdlib> +#include <cstdio> +#include <algorithm> +#include "CoinTypes.hpp" +#include "CoinError.hpp" + +// Compilers can produce better code if they know about __restrict +#ifndef COIN_RESTRICT +#ifdef COIN_USE_RESTRICT +#define COIN_RESTRICT __restrict +#else +#define COIN_RESTRICT +#endif +#endif + +//############################################################################# + +/** This helper function copies an array to another location using Duff's + device (for a speedup of ~2). The arrays are given by pointers to their + first entries and by the size of the source array. Overlapping arrays are + handled correctly. */ + +template <class T> inline void +CoinCopyN(register const T* from, const int size, register T* to) +{ + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinCopyN", ""); +#endif + + register int n = (size + 7) / 8; + if (to > from) { + register const T* downfrom = from + size; + register T* downto = to + size; + // Use Duff's device to copy + switch (size % 8) { + case 0: do{ *--downto = *--downfrom; + case 7: *--downto = *--downfrom; + case 6: *--downto = *--downfrom; + case 5: *--downto = *--downfrom; + case 4: *--downto = *--downfrom; + case 3: *--downto = *--downfrom; + case 2: *--downto = *--downfrom; + case 1: *--downto = *--downfrom; + }while(--n>0); + } + } else { + // Use Duff's device to copy + --from; + --to; + switch (size % 8) { + case 0: do{ *++to = *++from; + case 7: *++to = *++from; + case 6: *++to = *++from; + case 5: *++to = *++from; + case 4: *++to = *++from; + case 3: *++to = *++from; + case 2: *++to = *++from; + case 1: *++to = *++from; + }while(--n>0); + } + } +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location using Duff's + device (for a speedup of ~2). The source array is given by its first and + "after last" entry; the target array is given by its first entry. + Overlapping arrays are handled correctly. + + All of the various CoinCopyN variants use an int for size. On 64-bit + architectures, the address diff last-first will be a 64-bit quantity. + Given that everything else uses an int, I'm going to choose to kick + the difference down to int. -- lh, 100823 -- +*/ +template <class T> inline void +CoinCopy(register const T* first, register const T* last, register T* to) +{ + CoinCopyN(first, static_cast<int>(last-first), to); +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The arrays are given by pointers to their first + entries and by the size of the source array. + + Note JJF - the speed claim seems to be false on IA32 so I have added + CoinMemcpyN which can be used for atomic data */ +template <class T> inline void +CoinDisjointCopyN(register const T* from, const int size, register T* to) +{ +#ifndef _MSC_VER + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinDisjointCopyN", ""); +#endif + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinDisjointCopyN", ""); +#endif + + for (register int n = size / 8; n > 0; --n, from += 8, to += 8) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to[4] = from[4]; + to[5] = from[5]; + to[6] = from[6]; + to[7] = from[7]; + } + switch (size % 8) { + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + } +#else + CoinCopyN(from, size, to); +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The source array is given by its first and "after + last" entry; the target array is given by its first entry. */ +template <class T> inline void +CoinDisjointCopy(register const T* first, register const T* last, + register T* to) +{ + CoinDisjointCopyN(first, static_cast<int>(last - first), to); +} + +//----------------------------------------------------------------------------- + +/*! \brief Return an array of length \p size filled with input from \p array, + or null if \p array is null. +*/ + +template <class T> inline T* +CoinCopyOfArray( const T * array, const int size) +{ + if (array) { + T * arrayNew = new T[size]; + std::memcpy(arrayNew,array,size*sizeof(T)); + return arrayNew; + } else { + return NULL; + } +} + + +/*! \brief Return an array of length \p size filled with first copySize from \p array, + or null if \p array is null. +*/ + +template <class T> inline T* +CoinCopyOfArrayPartial( const T * array, const int size,const int copySize) +{ + if (array||size) { + T * arrayNew = new T[size]; + assert (copySize<=size); + std::memcpy(arrayNew,array,copySize*sizeof(T)); + return arrayNew; + } else { + return NULL; + } +} + +/*! \brief Return an array of length \p size filled with input from \p array, + or filled with (scalar) \p value if \p array is null +*/ + +template <class T> inline T* +CoinCopyOfArray( const T * array, const int size, T value) +{ + T * arrayNew = new T[size]; + if (array) { + std::memcpy(arrayNew,array,size*sizeof(T)); + } else { + int i; + for (i=0;i<size;i++) + arrayNew[i] = value; + } + return arrayNew; +} + + +/*! \brief Return an array of length \p size filled with input from \p array, + or filled with zero if \p array is null +*/ + +template <class T> inline T* +CoinCopyOfArrayOrZero( const T * array , const int size) +{ + T * arrayNew = new T[size]; + if (array) { + std::memcpy(arrayNew,array,size*sizeof(T)); + } else { + std::memset(arrayNew,0,size*sizeof(T)); + } + return arrayNew; +} + + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The arrays are given by pointers to their first + entries and by the size of the source array. + + Note JJF - the speed claim seems to be false on IA32 so I have added + alternative coding if USE_MEMCPY defined*/ +#ifndef COIN_USE_RESTRICT +template <class T> inline void +CoinMemcpyN(register const T* from, const int size, register T* to) +{ +#ifndef _MSC_VER +#ifdef USE_MEMCPY + // Use memcpy - seems a lot faster on Intel with gcc +#ifndef NDEBUG + // Some debug so check + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinMemcpyN", ""); + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinMemcpyN", ""); +#endif +#endif + std::memcpy(to,from,size*sizeof(T)); +#else + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinMemcpyN", ""); +#endif + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinMemcpyN", ""); +#endif + + for (register int n = size / 8; n > 0; --n, from += 8, to += 8) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to[4] = from[4]; + to[5] = from[5]; + to[6] = from[6]; + to[7] = from[7]; + } + switch (size % 8) { + case 7: to[6] = from[6]; + case 6: to[5] = from[5]; + case 5: to[4] = from[4]; + case 4: to[3] = from[3]; + case 3: to[2] = from[2]; + case 2: to[1] = from[1]; + case 1: to[0] = from[0]; + case 0: break; + } +#endif +#else + CoinCopyN(from, size, to); +#endif +} +#else +template <class T> inline void +CoinMemcpyN(const T * COIN_RESTRICT from, int size, T* COIN_RESTRICT to) +{ +#ifdef USE_MEMCPY + std::memcpy(to,from,size*sizeof(T)); +#else + T * COIN_RESTRICT put = to; + const T * COIN_RESTRICT get = from; + for ( ; 0<size ; --size) + *put++ = *get++; +#endif +} +#endif + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The source array is given by its first and "after + last" entry; the target array is given by its first entry. */ +template <class T> inline void +CoinMemcpy(register const T* first, register const T* last, + register T* to) +{ + CoinMemcpyN(first, static_cast<int>(last - first), to); +} + +//############################################################################# + +/** This helper function fills an array with a given value. For speed 8 entries + are filled at a time. The array is given by a pointer to its first entry + and its size. + + Note JJF - the speed claim seems to be false on IA32 so I have added + CoinZero to allow for memset. */ +template <class T> inline void +CoinFillN(register T* to, const int size, register const T value) +{ + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinFillN", ""); +#endif +#if 1 + for (register int n = size / 8; n > 0; --n, to += 8) { + to[0] = value; + to[1] = value; + to[2] = value; + to[3] = value; + to[4] = value; + to[5] = value; + to[6] = value; + to[7] = value; + } + switch (size % 8) { + case 7: to[6] = value; + case 6: to[5] = value; + case 5: to[4] = value; + case 4: to[3] = value; + case 3: to[2] = value; + case 2: to[1] = value; + case 1: to[0] = value; + case 0: break; + } +#else + // Use Duff's device to fill + register int n = (size + 7) / 8; + --to; + switch (size % 8) { + case 0: do{ *++to = value; + case 7: *++to = value; + case 6: *++to = value; + case 5: *++to = value; + case 4: *++to = value; + case 3: *++to = value; + case 2: *++to = value; + case 1: *++to = value; + }while(--n>0); + } +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with a given value. For speed 8 + entries are filled at a time. The array is given by its first and "after + last" entry. */ +template <class T> inline void +CoinFill(register T* first, register T* last, const T value) +{ + CoinFillN(first, last - first, value); +} + +//############################################################################# + +/** This helper function fills an array with zero. For speed 8 entries + are filled at a time. The array is given by a pointer to its first entry + and its size. + + Note JJF - the speed claim seems to be false on IA32 so I have allowed + for memset as an alternative */ +template <class T> inline void +CoinZeroN(register T* to, const int size) +{ +#ifdef USE_MEMCPY + // Use memset - seems faster on Intel with gcc +#ifndef NDEBUG + // Some debug so check + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinZeroN", ""); +#endif + memset(to,0,size*sizeof(T)); +#else + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinZeroN", ""); +#endif +#if 1 + for (register int n = size / 8; n > 0; --n, to += 8) { + to[0] = 0; + to[1] = 0; + to[2] = 0; + to[3] = 0; + to[4] = 0; + to[5] = 0; + to[6] = 0; + to[7] = 0; + } + switch (size % 8) { + case 7: to[6] = 0; + case 6: to[5] = 0; + case 5: to[4] = 0; + case 4: to[3] = 0; + case 3: to[2] = 0; + case 2: to[1] = 0; + case 1: to[0] = 0; + case 0: break; + } +#else + // Use Duff's device to fill + register int n = (size + 7) / 8; + --to; + switch (size % 8) { + case 0: do{ *++to = 0; + case 7: *++to = 0; + case 6: *++to = 0; + case 5: *++to = 0; + case 4: *++to = 0; + case 3: *++to = 0; + case 2: *++to = 0; + case 1: *++to = 0; + }while(--n>0); + } +#endif +#endif +} +/// This Debug helper function checks an array is all zero +inline void +CoinCheckDoubleZero(double * to, const int size) +{ + int n=0; + for (int j=0;j<size;j++) { + if (to[j]) + n++; + } + if (n) { + printf("array of length %d should be zero has %d nonzero\n",size,n); + } +} +/// This Debug helper function checks an array is all zero +inline void +CoinCheckIntZero(int * to, const int size) +{ + int n=0; + for (int j=0;j<size;j++) { + if (to[j]) + n++; + } + if (n) { + printf("array of length %d should be zero has %d nonzero\n",size,n); + } +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with a given value. For speed 8 + entries are filled at a time. The array is given by its first and "after + last" entry. */ +template <class T> inline void +CoinZero(register T* first, register T* last) +{ + CoinZeroN(first, last - first); +} + +//############################################################################# + +/** Returns strdup or NULL if original NULL */ +inline char * CoinStrdup(const char * name) +{ + char* dup = NULL; + if (name) { + const int len = static_cast<int>(strlen(name)); + dup = static_cast<char*>(malloc(len+1)); + CoinMemcpyN(name, len, dup); + dup[len] = 0; + } + return dup; +} + +//############################################################################# + +/** Return the larger (according to <code>operator<()</code> of the arguments. + This function was introduced because for some reason compiler tend to + handle the <code>max()</code> function differently. */ +template <class T> inline T +CoinMax(register const T x1, register const T x2) +{ + return (x1 > x2) ? x1 : x2; +} + +//----------------------------------------------------------------------------- + +/** Return the smaller (according to <code>operator<()</code> of the arguments. + This function was introduced because for some reason compiler tend to + handle the min() function differently. */ +template <class T> inline T +CoinMin(register const T x1, register const T x2) +{ + return (x1 < x2) ? x1 : x2; +} + +//----------------------------------------------------------------------------- + +/** Return the absolute value of the argument. This function was introduced + because for some reason compiler tend to handle the abs() function + differently. */ +template <class T> inline T +CoinAbs(const T value) +{ + return value<0 ? -value : value; +} + +//############################################################################# + +/** This helper function tests whether the entries of an array are sorted + according to operator<. The array is given by a pointer to its first entry + and by its size. */ +template <class T> inline bool +CoinIsSorted(register const T* first, const int size) +{ + if (size == 0) + return true; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("negative number of entries", "CoinIsSorted", ""); +#endif +#if 1 + // size1 is the number of comparisons to be made + const int size1 = size - 1; + for (register int n = size1 / 8; n > 0; --n, first += 8) { + if (first[8] < first[7]) return false; + if (first[7] < first[6]) return false; + if (first[6] < first[5]) return false; + if (first[5] < first[4]) return false; + if (first[4] < first[3]) return false; + if (first[3] < first[2]) return false; + if (first[2] < first[1]) return false; + if (first[1] < first[0]) return false; + } + + switch (size1 % 8) { + case 7: if (first[7] < first[6]) return false; + case 6: if (first[6] < first[5]) return false; + case 5: if (first[5] < first[4]) return false; + case 4: if (first[4] < first[3]) return false; + case 3: if (first[3] < first[2]) return false; + case 2: if (first[2] < first[1]) return false; + case 1: if (first[1] < first[0]) return false; + case 0: break; + } +#else + register const T* next = first; + register const T* last = first + size; + for (++next; next != last; first = next, ++next) + if (*next < *first) + return false; +#endif + return true; +} + +//----------------------------------------------------------------------------- + +/** This helper function tests whether the entries of an array are sorted + according to operator<. The array is given by its first and "after + last" entry. */ +template <class T> inline bool +CoinIsSorted(register const T* first, register const T* last) +{ + return CoinIsSorted(first, static_cast<int>(last - first)); +} + +//############################################################################# + +/** This helper function fills an array with the values init, init+1, init+2, + etc. For speed 8 entries are filled at a time. The array is given by a + pointer to its first entry and its size. */ +template <class T> inline void +CoinIotaN(register T* first, const int size, register T init) +{ + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("negative number of entries", "CoinIotaN", ""); +#endif +#if 1 + for (register int n = size / 8; n > 0; --n, first += 8, init += 8) { + first[0] = init; + first[1] = init + 1; + first[2] = init + 2; + first[3] = init + 3; + first[4] = init + 4; + first[5] = init + 5; + first[6] = init + 6; + first[7] = init + 7; + } + switch (size % 8) { + case 7: first[6] = init + 6; + case 6: first[5] = init + 5; + case 5: first[4] = init + 4; + case 4: first[3] = init + 3; + case 3: first[2] = init + 2; + case 2: first[1] = init + 1; + case 1: first[0] = init; + case 0: break; + } +#else + // Use Duff's device to fill + register int n = (size + 7) / 8; + --first; + --init; + switch (size % 8) { + case 0: do{ *++first = ++init; + case 7: *++first = ++init; + case 6: *++first = ++init; + case 5: *++first = ++init; + case 4: *++first = ++init; + case 3: *++first = ++init; + case 2: *++first = ++init; + case 1: *++first = ++init; + }while(--n>0); + } +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with the values init, init+1, init+2, + etc. For speed 8 entries are filled at a time. The array is given by its + first and "after last" entry. */ +template <class T> inline void +CoinIota(T* first, const T* last, T init) +{ + CoinIotaN(first, last-first, init); +} + +//############################################################################# + +/** This helper function deletes certain entries from an array. The array is + given by pointers to its first and "after last" entry (first two + arguments). The positions of the entries to be deleted are given in the + integer array specified by the last two arguments (again, first and "after + last" entry). */ +template <class T> inline T * +CoinDeleteEntriesFromArray(register T * arrayFirst, register T * arrayLast, + const int * firstDelPos, const int * lastDelPos) +{ + int delNum = static_cast<int>(lastDelPos - firstDelPos); + if (delNum == 0) + return arrayLast; + + if (delNum < 0) + throw CoinError("trying to delete negative number of entries", + "CoinDeleteEntriesFromArray", ""); + + int * delSortedPos = NULL; + if (! (CoinIsSorted(firstDelPos, lastDelPos) && + std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) { + // the positions of the to be deleted is either not sorted or not unique + delSortedPos = new int[delNum]; + CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos); + std::sort(delSortedPos, delSortedPos + delNum); + delNum = static_cast<int>(std::unique(delSortedPos, + delSortedPos+delNum) - delSortedPos); + } + const int * delSorted = delSortedPos ? delSortedPos : firstDelPos; + + const int last = delNum - 1; + int size = delSorted[0]; + for (int i = 0; i < last; ++i) { + const int copyFirst = delSorted[i] + 1; + const int copyLast = delSorted[i+1]; + CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast, + arrayFirst + size); + size += copyLast - copyFirst; + } + const int copyFirst = delSorted[last] + 1; + const int copyLast = static_cast<int>(arrayLast - arrayFirst); + CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast, + arrayFirst + size); + size += copyLast - copyFirst; + + if (delSortedPos) + delete[] delSortedPos; + + return arrayFirst + size; +} + +//############################################################################# + +#define COIN_OWN_RANDOM_32 + +#if defined COIN_OWN_RANDOM_32 +/* Thanks to Stefano Gliozzi for providing an operating system + independent random number generator. */ + +/*! \brief Return a random number between 0 and 1 + + A platform-independent linear congruential generator. For a given seed, the + generated sequence is always the same regardless of the (32-bit) + architecture. This allows to build & test in different environments, getting + in most cases the same optimization path. + + Set \p isSeed to true and supply an integer seed to set the seed + (vid. #CoinSeedRandom) + + \todo Anyone want to volunteer an upgrade for 64-bit architectures? +*/ +inline double CoinDrand48 (bool isSeed = false, unsigned int seed = 1) +{ + static unsigned int last = 123456; + if (isSeed) { + last = seed; + } else { + last = 1664525*last+1013904223; + return ((static_cast<double> (last))/4294967296.0); + } + return (0.0); +} + +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) +{ + CoinDrand48(true, iseed); +} + +#else // COIN_OWN_RANDOM_32 + +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__) + +/// Return a random number between 0 and 1 +inline double CoinDrand48() { return rand() / (double) RAND_MAX; } +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); } + +#else + +/// Return a random number between 0 and 1 +inline double CoinDrand48() { return drand48(); } +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); } + +#endif + +#endif // COIN_OWN_RANDOM_32 + +//############################################################################# + +/** This function figures out whether file names should contain slashes or + backslashes as directory separator */ +inline char CoinFindDirSeparator() +{ + int size = 1000; + char* buf = 0; + while (true) { + buf = new char[size]; + if (getcwd(buf, size)) + break; + delete[] buf; + buf = 0; + size = 2*size; + } + // if first char is '/' then it's unix and the dirsep is '/'. otherwise we + // assume it's dos and the dirsep is '\' + char dirsep = buf[0] == '/' ? '/' : '\\'; + delete[] buf; + return dirsep; +} +//############################################################################# + +inline int CoinStrNCaseCmp(const char* s0, const char* s1, + const size_t len) +{ + for (size_t i = 0; i < len; ++i) { + if (s0[i] == 0) { + return s1[i] == 0 ? 0 : -1; + } + if (s1[i] == 0) { + return 1; + } + const int c0 = std::tolower(s0[i]); + const int c1 = std::tolower(s1[i]); + if (c0 < c1) + return -1; + if (c0 > c1) + return 1; + } + return 0; +} + +//############################################################################# + +/// Swap the arguments. +template <class T> inline void CoinSwap (T &x, T &y) +{ + T t = x; + x = y; + y = t; +} + +//############################################################################# + +/** This helper function copies an array to file + Returns 0 if OK, 1 if bad write. +*/ + +template <class T> inline int +CoinToFile( const T* array, CoinBigIndex size, FILE * fp) +{ + CoinBigIndex numberWritten; + if (array&&size) { + numberWritten = + static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp)); + if (numberWritten!=1) + return 1; + numberWritten = + static_cast<CoinBigIndex>(fwrite(array,sizeof(T),size_t(size),fp)); + if (numberWritten!=size) + return 1; + } else { + size = 0; + numberWritten = + static_cast<CoinBigIndex>(fwrite(&size,sizeof(int),1,fp)); + if (numberWritten!=1) + return 1; + } + return 0; +} + +//############################################################################# + +/** This helper function copies an array from file and creates with new. + Passed in array is ignored i.e. not deleted. + But if NULL and size does not match and newSize 0 then leaves as NULL and 0 + Returns 0 if OK, 1 if bad read, 2 if size did not match. +*/ + +template <class T> inline int +CoinFromFile( T* &array, CoinBigIndex size, FILE * fp, CoinBigIndex & newSize) +{ + CoinBigIndex numberRead; + numberRead = + static_cast<CoinBigIndex>(fread(&newSize,sizeof(int),1,fp)); + if (numberRead!=1) + return 1; + int returnCode=0; + if (size!=newSize&&(newSize||array)) + returnCode=2; + if (newSize) { + array = new T [newSize]; + numberRead = + static_cast<CoinBigIndex>(fread(array,sizeof(T),newSize,fp)); + if (numberRead!=newSize) + returnCode=1; + } else { + array = NULL; + } + return returnCode; +} + +//############################################################################# + +/// Cube Root +#if 0 +inline double CoinCbrt(double x) +{ +#if defined(_MSC_VER) + return pow(x,(1./3.)); +#else + return cbrt(x); +#endif +} +#endif + +//----------------------------------------------------------------------------- + +/// This helper returns "sizeof" as an int +#define CoinSizeofAsInt(type) (static_cast<int>(sizeof(type))) +/// This helper returns "strlen" as an int +inline int +CoinStrlenAsInt(const char * string) +{ + return static_cast<int>(strlen(string)); +} + +/** Class for thread specific random numbers +*/ +#if defined COIN_OWN_RANDOM_32 +class CoinThreadRandom { +public: + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + CoinThreadRandom() + { seed_=12345678;} + /** Constructor wih seed. */ + CoinThreadRandom(int seed) + { + seed_ = seed; + } + /** Destructor */ + ~CoinThreadRandom() {} + // Copy + CoinThreadRandom(const CoinThreadRandom & rhs) + { seed_ = rhs.seed_;} + // Assignment + CoinThreadRandom& operator=(const CoinThreadRandom & rhs) + { + if (this != &rhs) { + seed_ = rhs.seed_; + } + return *this; + } + + //@} + + /**@name Sets/gets */ + + //@{ + /** Set seed. */ + inline void setSeed(int seed) + { + seed_ = seed; + } + /** Get seed. */ + inline unsigned int getSeed() const + { + return seed_; + } + /// return a random number + inline double randomDouble() const + { + double retVal; + seed_ = 1664525*(seed_)+1013904223; + retVal = ((static_cast<double> (seed_))/4294967296.0); + return retVal; + } + /// make more random (i.e. for startup) + inline void randomize(int n=0) + { + if (!n) + n=seed_ & 255; + for (int i=0;i<n;i++) + randomDouble(); + } + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Current seed + mutable unsigned int seed_; + //@} +}; +#else +class CoinThreadRandom { +public: + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + CoinThreadRandom() + { seed_[0]=50000;seed_[1]=40000;seed_[2]=30000;} + /** Constructor wih seed. */ + CoinThreadRandom(const unsigned short seed[3]) + { memcpy(seed_,seed,3*sizeof(unsigned short));} + /** Constructor wih seed. */ + CoinThreadRandom(int seed) + { + union { int i[2]; unsigned short int s[4];} put; + put.i[0]=seed; + put.i[1]=seed; + memcpy(seed_,put.s,3*sizeof(unsigned short)); + } + /** Destructor */ + ~CoinThreadRandom() {} + // Copy + CoinThreadRandom(const CoinThreadRandom & rhs) + { memcpy(seed_,rhs.seed_,3*sizeof(unsigned short));} + // Assignment + CoinThreadRandom& operator=(const CoinThreadRandom & rhs) + { + if (this != &rhs) { + memcpy(seed_,rhs.seed_,3*sizeof(unsigned short)); + } + return *this; + } + + //@} + + /**@name Sets/gets */ + + //@{ + /** Set seed. */ + inline void setSeed(const unsigned short seed[3]) + { memcpy(seed_,seed,3*sizeof(unsigned short));} + /** Set seed. */ + inline void setSeed(int seed) + { + union { int i[2]; unsigned short int s[4];} put; + put.i[0]=seed; + put.i[1]=seed; + memcpy(seed_,put.s,3*sizeof(unsigned short)); + } + /// return a random number + inline double randomDouble() const + { + double retVal; +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__) + retVal=rand(); + retVal=retVal/(double) RAND_MAX; +#else + retVal = erand48(seed_); +#endif + return retVal; + } + /// make more random (i.e. for startup) + inline void randomize(int n=0) + { + if (!n) { + n=seed_[0]+seed_[1]+seed_[2]; + n &= 255; + } + for (int i=0;i<n;i++) + randomDouble(); + } + //@} + + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Current seed + mutable unsigned short seed_[3]; + //@} +}; +#endif +#ifndef COIN_DETAIL +#define COIN_DETAIL_PRINT(s) {} +#else +#define COIN_DETAIL_PRINT(s) s +#endif +#endif |