Fixed a bug: clearing the module tree on image read.
[fic.git] / util.h
blob80e36a966f17a9123948c6f65fe0901091d92000
1 #ifndef UTIL_HEADER_
2 #define UTIL_HEADER_
4 /// \file
6 /** Field containing 2^i on i-th position, defined in modules.cpp */
7 extern const int powers[31];
9 /** Helper template function computing the square of a number */
10 template<typename T> inline T sqr(T i)
11 { return i*i; }
12 /** Helper template function computing the cube of a number */
13 template<typename T> inline T cube(T i)
14 { return i*i*i; }
16 /** Returns i*2^bits */
17 template<typename T> inline T lShift(T i,T bits)
18 { ASSERT(bits>=0); return i<<bits; }
20 /** Returns i/2^bits */
21 template<typename T> inline T rShift(T i,T bits)
22 { ASSERT(bits>=0 && i>=0); return i>>bits; }
24 /** This function is missing in earlier GCC versions, here implemented via exp2 and log2 */
25 template<typename T> inline T exp10(T val)
26 { return exp2( val*log2(T(10)) ); }
28 /** Returns ceil(log2(i)) */
29 inline int log2ceil(int i) {
30 ASSERT(i>0);
31 --i;
32 int result= 0;
33 while (i) {
34 i/= 2;
35 ++result;
37 return result;
40 /** A wrapper around isnan() because of compiler support */
41 template<class T> inline bool isNaN(T num) {
42 #ifndef __ICC
43 return isnan(num);
44 #else
45 return num!=num;
46 #endif
49 /** How many short intervals (shifted by density) can fit into a long interval (discrete) */
50 inline int getCountForDensity(int longLength,int density,int shortLength)
51 { return (longLength-shortLength)/density +1; }
53 /** The same as above, but in 2D for squares fitting into a rectangle */
54 inline int getCountForDensity2D(int width,int height,int density,int sideSize) {
55 return getCountForDensity(width,density,sideSize)
56 * getCountForDensity(height,density,sideSize);
59 /** General bounds-checking template routine - returns max(low,min(value,high)) */
60 template<class T> inline T checkBoundsFunc(T low,T value,T high) {
61 if (value<low)
62 return low;
63 if (value>high)
64 return high;
65 return value;
68 /** Struct for conversion between 0-1 Real and 0-(2^power-1) integer */
69 template<int power,class R> struct Float2int {
70 static R convert(int i)
71 { return std::ldexp( i+R(0.5), -power ); }
73 static int convert(R r)
74 { return (int)trunc(std::ldexp( r, power )); }
75 static int convertCheck(R r)
76 { return checkBoundsFunc( 0, convert(r), powers[power]-1 ); }
79 template<class C,class F> inline F for_each(C &container,F functor)
80 { return for_each( container.begin(), container.end(), functor ); }
82 /** Counts the number of '\n' characters in a C-string */
83 inline int countEOLs(const char *s) {
84 int result= 0;
85 for (; *s; ++s)
86 if (*s=='\n')
87 ++result;
88 return result;
91 /** Type convertor - NonConstType<T>::Result is a non-const variant of T or T itself if N/A */
92 template<class T> struct NonConstType { typedef T Result; };
93 template<class T> struct NonConstType<const T> { typedef T Result; };
95 /** Automatic version of const_cast for pointers */
96 template <class T> inline T* constCast(const T* toCast) { return const_cast<T*>(toCast); }
97 /** Automatic version of const_cast for references */
98 template <class T> inline T& constCast(const T& toCast) { return const_cast<T&>(toCast); }
100 /** Checking a condition - throws std::exception if false */
101 inline void checkThrow(bool check) { if (!check) throw std::exception(); }
104 /** Template object for automated deletion of pointers (useful in for_each) */
105 struct SingleDeleter {
106 template <class T> void operator()(T *toDelete) const { delete toDelete; }
108 /** Template object for automated deletion of field pointers (useful in for_each) */
109 struct MultiDeleter {
110 template <class T> void operator()(T *toDelete) const { delete[] toDelete; }
114 /** Deletes all pointers in a container (it has to support \c begin and \c end methods) */
115 template<class C> inline void clearContainer(const C &container)
116 { for_each( container, SingleDeleter() ); }
117 /** Clears a QList of pointers (and deletes the pointers) */
118 template<class C> inline void clearQtContainer(C container)
119 { while (!container.isEmpty()) delete container.takeFirst(); }
121 template <class T,int bulkKb=64>
122 class BulkAllocator {
123 enum { bulkCount=(bulkKb*1024)/sizeof(T) };
125 std::vector<T*> pools;
126 PtrInt nextIndex;
128 public:
129 BulkAllocator()
130 : nextIndex(bulkCount) {}
131 BulkAllocator(const BulkAllocator &DEBUG_ONLY(copy))
132 { nextIndex=bulkCount; ASSERT(copy.pools.empty()); }
133 ~BulkAllocator()
134 { for_each( pools, MultiDeleter() ); }
136 T* make() {
137 // check for errors
138 ASSERT(nextIndex<=bulkCount);
139 // allocate a new bulk if needed
140 if (nextIndex==bulkCount) {
141 nextIndex= 0;
142 pools.push_back( new T[bulkCount] );
144 return & (pools.back()[nextIndex++]);
146 T* makeField(PtrInt count) {
147 // check for errors
148 ASSERT(nextIndex<=bulkCount);
150 if (count>bulkCount/2) {
151 T *result= new T[count];
152 if (pools.empty())
153 pools.push_back(result);
154 else {
155 pools.push_back(pools.back());
156 *(pools.end()-2)= result;
158 return result;
161 if (nextIndex+count>bulkCount) {
162 // some space will be wasted
163 nextIndex=0;
164 pools.push_back(new T[bulkCount]);
166 T *result=&pools.back()[nextIndex];
167 nextIndex+=count;
168 return result;
170 }; // BulkAllocator class
172 /** Structure providing support for progress update and interruption (used for encoding) */
173 struct UpdateInfo {
174 typedef void (*IncInt)(int increment); ///< Type for used functions -> more readable code
176 static void emptyFunction(int) {} ///< does nothing, default for IncInt functions
177 static const bool noTerminate= false; ///< default for #terminate, defined in modules.cpp
178 static const UpdateInfo none; ///< empty UpdateInfo instance, in modules.cpp
180 volatile const bool *terminate; ///< true if the action should be terminated
181 IncInt incMaxProgress /// function for increasing the maximum progress (100%)
182 , incProgress; ///< function for increasing the current progress
184 /** Initializes the structure from supplied parametres */
185 UpdateInfo( const bool &terminate_, IncInt incMaxProgress_, IncInt incProgress_ )
186 : terminate(&terminate_), incMaxProgress(incMaxProgress_), incProgress(incProgress_)
187 { ASSERT(isValid()); }
189 bool isValid() const { return terminate && incMaxProgress && incProgress; }
192 #endif // UTIL_HEADER_