1. /* ncblock.h by K.Tsuru */
  2. /***************************************************************
  3. NCBlock template class
  4. Defined an array class of variable size for non class object.
  5. The array has a size of power of two.
  6. Diffrent from SNBlock class the memcpy() and memset() functions are
  7. used.
  8. [Notice for using double]
  9. You must test that all elements are equal to zero or not by use of
  10. clear() function.
  11. [reference]
  12. R.B.Murray "C++ Strategies and Tactics"
  13. ****************************************************************/
  14. #ifndef NC_BLOCK_H
  15. #define NC_BLOCK_H 1
  16. #include <stdio.h>
  17. #include <assert.h>
  18. #include <limits.h>
  19. #include <string.h> // for memset
  20. #include <algorithm> // for min() and max() since ver 2.19
  21. #include <new> // version 2.20
  22. using namespace std; // ver. 2.19
  23. void OutOfMemory(); // defined in smanager.cpp
  24. #ifndef TYPEDEF_H
  25. #include "typedef.h"
  26. #endif
  27. // Maximum value of index.
  28. // #ifndef INDEX_MAX
  29. // #define INDEX_MAX (uint)INT_MAX // = 2,147,483,647 in 32bit system
  30. // #endif
  31. // Return a minimum integer 2^p which satisfies sz <= 2^p.
  32. uint ceilpow2(uint sz);
  33. // Minmum size.
  34. const uint NCBlockMinSize = 2u; // ver.2.17
  35. template <class T> class NCBlock{
  36. public:
  37. enum ErrorType { NORMAL = 0, NULL_COPY };
  38. protected:
  39. ErrorType error ; // error infomation
  40. uint n_elements; // number of elements
  41. T* elements; // pointer of elements
  42. // copy function for operator=()
  43. void copy_block(const NCBlock<T>& a);
  44. // free memory
  45. // Use size(0,0) in non member function.
  46. void mem_free(){
  47. delete[] elements; elements = NULL; n_elements = 0;
  48. }
  49. public:
  50. /**************************************************************************
  51. Change the size of array.
  52. If sz == 0, free the memory.
  53. When copy > 0, copy the old elements to lower region of new array. Upper
  54. elements are initialized by zero.
  55. When copy == 0, initialize all elements by zero.
  56. When copy < 0, does not copy nor initialize.
  57. Return a really allocated size of power of two.
  58. **************************************************************************/
  59. uint size(uint sz, int copy);
  60. /*************************************************************************
  61. Allocate greater than or equal (n + 1) elements(enlarge only) i.e.
  62. n-th elements is substitutable. When n >= n_elements, double the size.
  63. Copy the old elements to lower region and not initialize the upper region.
  64. If the required memory was allocated return a value one, else zero.
  65. *************************************************************************/
  66. bool reserve(uint n);
  67. // clear array : for(i = from; i < min(to+1, n_elements); i++) elements[i] = 0;
  68. uint clear(uint from = 0, uint to = INT_MAX);
  69. // constructor
  70. // Default constructor does not allocate memory.
  71. NCBlock():error(NORMAL), n_elements(0), elements(NULL){}
  72. // constructor by size. If init_val == 0, initialize by 0.
  73. NCBlock(uint n_elem, int init_val = 0);
  74. // copy constructor
  75. NCBlock(const NCBlock<T>& a);
  76. // destructor
  77. virtual ~NCBlock();
  78. uint size() const { return n_elements; }
  79. // Element access, lhs is available
  80. T& operator[](uint index){
  81. #ifndef NDEBUG
  82. if(index >= n_elements){// In debuging, inline expanding switch must be off
  83. // to catch the place where error occured.
  84. fprintf(stderr, "index = [%u], n_elements = %u\n", index, n_elements);
  85. assert(index < n_elements);
  86. exit(-1);
  87. }
  88. #endif
  89. return elements[index];
  90. }
  91. // Element access, rhs only
  92. const T& operator()(uint index) const {
  93. #ifndef NDEBUG
  94. if(index >= n_elements){
  95. fprintf(stderr, "index = (%u), n_elements = %u\n", index, n_elements);
  96. assert(index < n_elements);
  97. exit(-1);
  98. }
  99. #endif
  100. return elements[index];
  101. }
  102. ErrorType Error() {
  103. ErrorType er = error;
  104. error = NORMAL; // reset error
  105. return er;
  106. }
  107. NCBlock<T>& operator=(const NCBlock<T>& a){
  108. copy_block(a); return *this;
  109. }
  110. /***************************************************************************
  111. The speed to access the elements by operator[] or operator() is slow, then
  112. implement a member function which enables us to access via the first address
  113. of elements.
  114. [Notice]
  115. 1. Use this function below the line of size(sz, copy) or reserve().
  116. 2. Get the array size by the function size().
  117. ***************************************************************************/
  118. T* Elements(){ return elements; } // ver. 2.17
  119. };
  120. // constructor by size.
  121. template <class T> NCBlock<T>::NCBlock(uint n_elem, int init_val)
  122. : error(NORMAL), n_elements(0), elements(NULL){
  123. if(n_elem) size(n_elem, (init_val > 0) ? -1 : 0);
  124. }
  125. template <class T> bool NCBlock<T>::reserve(uint index){
  126. if(index < n_elements) return true; // already allocated
  127. uint new_sz = ceilpow2(index);
  128. if( new_sz == index ) new_sz *= 2u;
  129. size(new_sz, 1);
  130. return error == NORMAL; // ver. 2.17
  131. }
  132. template <class T> uint NCBlock<T>::size(uint sz, int copy){
  133. if(!sz){ mem_free(); return 0; }
  134. // new size
  135. uint new_sz = max( ceilpow2(sz), NCBlockMinSize);
  136. if( new_sz == n_elements ){ // The size is same.
  137. if(!copy) clear();
  138. return new_sz;
  139. }
  140. if(copy < 0) mem_free();// Old elements is not nessesary.
  141. #if 1 // It does not appear warning : uninitialized. version 2.20
  142. T* new_ele = new T[new_sz];
  143. if(new_ele == NULL) OutOfMemory(); // ver. 2.17
  144. #else
  145. T* new_ele;
  146. try { // version 2.20
  147. new_ele = new T[new_sz];
  148. }
  149. catch(bad_alloc){
  150. OutOfMemory();
  151. }
  152. #endif
  153. // copy
  154. uint n_copy = 0;
  155. if(copy > 0){
  156. n_copy = min(new_sz, n_elements);
  157. memcpy(new_ele, elements, n_copy*sizeof(T));
  158. }
  159. /* No effect warning : uninitialized.
  160. // else {
  161. // memset(new_ele, 0, new_sz*sizeof(T));
  162. // }
  163. */
  164. delete[] elements;
  165. /***
  166. Let clear() function know the elements and n_elements values.
  167. I cannot remove "warning uninitialized" on gcc 4.6.2.
  168. ***/
  169. elements = new_ele;
  170. n_elements = new_sz;
  171. if(copy >= 0) clear(n_copy); // initialize the upper region by zero
  172. return n_elements;
  173. }
  174. // copy function for operator=()
  175. template <class T> void NCBlock<T>::copy_block(const NCBlock<T>& a){
  176. if( this == &a ) return; // for a = a
  177. error = a.error;
  178. if(n_elements && !a.n_elements) error = NULL_COPY; // Try to copy null.
  179. // no error for n_elements = 0
  180. if(error != NORMAL) return;
  181. // allocate memory without initialization
  182. if(size(a.size(), -1) == 0) return;
  183. // copy
  184. #ifndef NDEBUG
  185. assert(a.n_elements == n_elements);
  186. #endif
  187. memcpy(elements, a.elements, n_elements*sizeof(T));
  188. }
  189. // copy constructor
  190. template <class T> inline NCBlock<T>::NCBlock(const NCBlock<T>& a)
  191. :error(a.error), elements( new T[n_elements = a.n_elements] ){
  192. if(elements == NULL) OutOfMemory(); // ver. 2.17
  193. memcpy(elements, a.elements, n_elements*sizeof(T));
  194. }
  195. /************************************************************
  196. Initialize between elements[from] and elements[to] by zero.
  197. default : from = 0, to = INT_MAX
  198. *************************************************************/
  199. template <class T> uint NCBlock<T>::clear(uint from, uint to){
  200. uint t = (to + 1u) < n_elements ? (to + 1u) : n_elements; // ver. 2.17
  201. // uint t = min(to +1u, n_elements);
  202. uint sz = (t > from) ? (t - from) : 0;
  203. if(!sz) return 0; // No error when n_elements = 0 or from > to.
  204. T* f = &elements[from];
  205. memset(f, 0, sz*sizeof(T));
  206. return sz;
  207. }
  208. // destructor
  209. template <class T> NCBlock<T>::~NCBlock(){
  210. mem_free();
  211. }
  212. #endif // NC_BLOCK_H

ncblock.h : last modifiled at 2017/10/15 15:52:41(7,644 bytes)
created at 2016/04/11 11:18:59
The creation time of this html file is 2017/10/23 10:27:40 (Mon Oct 23 10:27:40 2017).