Updated comments, changed FieldMath::assign in debug-mode.
[fic.git] / util.h
blobb5bd826c624e9c5564f9f89fdb1728d0a9652cea
1 #ifndef UTIL_HEADER_
2 #define UTIL_HEADER_
4 #include "headers.h"
5 #include "debug.h"
7 /// \file
9 /** Field containing 2^i on i-th position, defined in modules.cpp */
10 extern const int powers[31];
12 /** Helper template function computing the square of a number */
13 template<typename T> inline T sqr(T i)
14 { return i*i; }
15 /** Helper template function computing the cube of a number */
16 template<typename T> inline T cube(T i)
17 { return i*i*i; }
19 /** Returns i*2^bits */
20 template<typename T> inline T lShift(T i,T bits)
21 { ASSERT(bits>=0); return i<<bits; }
23 /** Returns i/2^bits */
24 template<typename T> inline T rShift(T i,T bits)
25 { ASSERT(bits>=0 && i>=0); return i>>bits; }
27 /** Returns ceil(log2(i)) */
28 inline int log2ceil(int i) {
29 ASSERT(i>0);
30 --i;
31 int result= 0;
32 while (i) {
33 i/= 2;
34 ++result;
36 return result;
39 /** A wrapper around isnan() because of compiler support */
40 template<class T> inline bool isNaN(T num) {
41 #ifndef __ICC
42 return isnan(num);
43 #else
44 return num!=num;
45 #endif
48 /** How many short intervals (shifted by density) can fit into a long interval (discrete) */
49 inline int getCountForDensity(int longLength,int density,int shortLength)
50 { return (longLength-shortLength)/density +1; }
52 /** The same as above, but in 2D for squares fitting into a rectangle */
53 inline int getCountForDensity2D(int width,int height,int density,int sideSize) {
54 return getCountForDensity(width,density,sideSize)
55 * getCountForDensity(height,density,sideSize);
58 /** General bounds-checking template routine - returns max(low,min(value,high)) */
59 template<class T> inline T checkBoundsFunc(T low,T value,T high) {
60 if (value<low)
61 return low;
62 if (value>high)
63 return high;
64 return value;
67 /** Struct for conversion between 0-1 Real and 0-(2^power-1) integer */
68 template<int power,class R> struct Float2int {
69 static R convert(int i)
70 { return std::ldexp( i+R(0.5), -power ); }
72 static int convert(R r)
73 { return (int)trunc(std::ldexp( r, power )); }
74 static int convertCheck(R r)
75 { return checkBoundsFunc( 0, convert(r), powers[power]-1 ); }
78 template<class C,class F> inline F for_each(C &container,F functor)
79 { return for_each( container.begin(), container.end(), functor ); }
81 /** Counts the number of '\n' characters in a C-string */
82 inline int countEOLs(const char *s) {
83 int result= 0;
84 for (; *s; ++s)
85 if (*s=='\n')
86 ++result;
87 return result;
90 /** Converts any type to std::string via std::stringstream */
91 template<class T> inline std::string toString(const T &what) {
92 std::stringstream stream;
93 stream << what;
94 std::string result;
95 stream >> result;
96 return result;
99 /** Type convertor - NonConstType<T>::Result is a non-const variant of T or T itself if N/A */
100 template<class T> struct NonConstType { typedef T Result; };
101 template<class T> struct NonConstType<const T> { typedef T Result; };
103 /** Automatic version of const_cast for pointers */
104 template <class T> inline T* constCast(const T* toCast) { return const_cast<T*>(toCast); }
105 /** Automatic version of const_cast for references */
106 template <class T> inline T& constCast(const T& toCast) { return const_cast<T&>(toCast); }
108 /** Checking a condition - throws std::exception if false */
109 inline void checkThrow(bool check) { if (!check) throw std::exception(); }
112 /** Template object for automated deletion of pointers (useful in for_each) */
113 struct SingleDeleter {
114 template <class T> void operator()(T *toDelete) const { delete toDelete; }
116 /** Template object for automated deletion of field pointers (useful in for_each) */
117 struct MultiDeleter {
118 template <class T> void operator()(T *toDelete) const { delete[] toDelete; }
122 /** Deletes all pointers in a container (it has to support \c begin and \c end methods) */
123 template<class C> inline void clearContainer(const C &container)
124 { for_each( container, SingleDeleter() ); }
125 /** Clears a QList of pointers (and deletes the pointers) */
126 template<class C> inline void clearQtContainer(C container)
127 { while (!container.isEmpty()) delete container.takeFirst(); }
129 template <class T,int bulkKb=64>
130 class BulkAllocator {
131 enum { bulkCount=(bulkKb*1024)/sizeof(T) };
133 std::vector<T*> pools;
134 PtrInt nextIndex;
136 public:
137 BulkAllocator()
138 : nextIndex(bulkCount) {}
139 BulkAllocator(const BulkAllocator &DEBUG_ONLY(copy))
140 { nextIndex=bulkCount; ASSERT(copy.pools.empty()); }
141 ~BulkAllocator()
142 { for_each( pools, MultiDeleter() ); }
144 T* make() {
145 // check for errors
146 ASSERT(nextIndex<=bulkCount);
147 // allocate a new bulk if needed
148 if (nextIndex==bulkCount) {
149 nextIndex= 0;
150 pools.push_back( new T[bulkCount] );
152 return & (pools.back()[nextIndex++]);
154 T* makeField(PtrInt count) {
155 // check for errors
156 ASSERT(nextIndex<=bulkCount);
158 if (count>bulkCount/2) {
159 T *result= new T[count];
160 if (pools.empty())
161 pools.push_back(result);
162 else {
163 pools.push_back(pools.back());
164 *(pools.end()-2)= result;
166 return result;
169 if (nextIndex+count>bulkCount) {
170 // some space will be wasted
171 nextIndex=0;
172 pools.push_back(new T[bulkCount]);
174 T *result=&pools.back()[nextIndex];
175 nextIndex+=count;
176 return result;
178 }; // BulkAllocator class
180 /** Structure providing support for progress update and interruption (used for encoding) */
181 struct UpdateInfo {
182 typedef void (*IncInt)(int increment); ///< Type for used functions -> more readable code
184 static void emptyFunction(int) {} ///< does nothing, default for IncInt functions
185 static const bool noTerminate= false; ///< default for #terminate, defined in modules.cpp
186 static const UpdateInfo none; ///< empty UpdateInfo instance, in modules.cpp
188 volatile const bool *terminate; ///< true if the action should be terminated
189 IncInt incMaxProgress /// function for increasing the maximum progress (100%)
190 , incProgress; ///< function for increasing the current progress
192 /** Initializes the structure from supplied parametres */
193 UpdateInfo( const bool &terminate_, IncInt incMaxProgress_, IncInt incProgress_ )
194 : terminate(&terminate_), incMaxProgress(incMaxProgress_), incProgress(incProgress_)
195 { ASSERT(isValid()); }
197 bool isValid() const { return terminate && incMaxProgress && incProgress; }
200 #endif // UTIL_HEADER_