resize.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * Copyright 2002 Adrian Thurston <thurston@cs.queensu.ca>
  3. */
  4. /* This file is part of Aapl.
  5. *
  6. * Aapl is free software; you can redistribute it and/or modify it under the
  7. * terms of the GNU Lesser General Public License as published by the Free
  8. * Software Foundation; either version 2.1 of the License, or (at your option)
  9. * any later version.
  10. *
  11. * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
  12. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
  14. * more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
  18. * Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #ifndef _AAPL_RESIZE_H
  21. #define _AAPL_RESIZE_H
  22. #include <assert.h>
  23. #ifdef AAPL_NAMESPACE
  24. namespace Aapl {
  25. #endif
  26. /* This step is expressed in units of T. Changing this requires changes to
  27. * docs in ResizeLin constructor. */
  28. #define LIN_DEFAULT_STEP 256
  29. /*
  30. * Resizing macros giving different resize methods.
  31. */
  32. /* If needed is greater than existing, give twice needed. */
  33. #define EXPN_UP( existing, needed ) \
  34. needed > existing ? (needed<<1) : existing
  35. /* If needed is less than 1 quarter existing, give twice needed. */
  36. #define EXPN_DOWN( existing, needed ) \
  37. needed < (existing>>2) ? (needed<<1) : existing
  38. /* If needed is greater than existing, give needed plus step. */
  39. #define LIN_UP( existing, needed ) \
  40. needed > existing ? (needed+step) : existing
  41. /* If needed is less than existing - 2 * step then give needed plus step. */
  42. #define LIN_DOWN( existing, needed ) \
  43. needed < (existing-(step<<1)) ? (needed+step) : existing
  44. /* Return existing. */
  45. #define CONST_UP( existing, needed ) existing
  46. /* Return existing. */
  47. #define CONST_DOWN( existing, needed ) existing
  48. /**
  49. * \addtogroup vector
  50. * @{
  51. */
  52. /** \class ResizeLin
  53. * \brief Linear table resizer.
  54. *
  55. * When an up resize or a down resize is needed, ResizeLin allocates the space
  56. * needed plus some user defined step. The result is that when growing the
  57. * vector in a linear fashion, the number of resizes is also linear.
  58. *
  59. * If only up resizing is done, then there will never be more than step unused
  60. * spaces in the vector. If down resizing is done as well, there will never be
  61. * more than 2*step unused spaces in the vector. The up resizing and down
  62. * resizing policies are offset to improve performance when repeatedly
  63. * inserting and removing a small number of elements relative to the step.
  64. * This scheme guarantees that repetitive inserting and removing of a small
  65. * number of elements will never result in repetative reallocation.
  66. *
  67. * The vectors pass sizes to the resizer in units of T, so the step gets
  68. * interpreted as units of T.
  69. */
  70. /*@}*/
  71. /* Linear resizing. */
  72. class ResizeLin
  73. {
  74. protected:
  75. /**
  76. * \brief Default constructor.
  77. *
  78. * Intializes resize step to 256 units of the table type T.
  79. */
  80. ResizeLin() : step(LIN_DEFAULT_STEP) { }
  81. /**
  82. * \brief Determine the new table size when up resizing.
  83. *
  84. * If the existing size is insufficient for the space needed, then allocate
  85. * the space needed plus the step. The step is in units of T.
  86. */
  87. inline long upResize( long existing, long needed )
  88. { return LIN_UP(existing, needed); }
  89. /**
  90. * \brief Determine the new table size when down resizing.
  91. *
  92. * If space needed is less than the existing - 2*step, then allocate the
  93. * space needed space plus the step. The step is in units of T.
  94. */
  95. inline long downResize( long existing, long needed )
  96. { return LIN_DOWN(existing, needed); }
  97. public:
  98. /**
  99. * \brief Step for linear resize.
  100. *
  101. * Amount of extra space in units of T added each time a resize must take
  102. * place. This may be changed at any time. The step should be >= 0.
  103. */
  104. long step;
  105. };
  106. /**
  107. * \addtogroup vector
  108. * @{
  109. */
  110. /** \class ResizeCtLin
  111. * \brief Linear table resizer with compile time step.
  112. *
  113. * When an up resize or a down resize is needed, ResizeCtLin allocates the
  114. * space needed plus some compile time defined step. The result is that when
  115. * growing the vector in a linear fashion, the number of resizes is also
  116. * linear.
  117. *
  118. * If only up resizing is done, then there will never be more than step unused
  119. * spaces in the vector. If down resizing is done as well, there will never be
  120. * more than 2*step unused spaces in the vector. The up resizing and down
  121. * resizing policies are offset to improve performance when repeatedly
  122. * inserting and removing a small number of elements relative to the step.
  123. * This scheme guarantees that repetitive inserting and removing of a small
  124. * number of elements will never result in repetative reallocation.
  125. *
  126. * The vectors pass sizes to the resizer in units of T, so the step gets
  127. * interpreted as units of T.
  128. */
  129. /*@}*/
  130. /* Linear resizing. */
  131. template <long step> class ResizeCtLin
  132. {
  133. protected:
  134. /**
  135. * \brief Determine the new table size when up resizing.
  136. *
  137. * If the existing size is insufficient for the space needed, then allocate
  138. * the space needed plus the step. The step is in units of T.
  139. */
  140. inline long upResize( long existing, long needed )
  141. { return LIN_UP(existing, needed); }
  142. /**
  143. * \brief Determine the new table size when down resizing.
  144. *
  145. * If space needed is less than the existing - 2*step, then allocate the
  146. * space needed space plus the step. The step is in units of T.
  147. */
  148. inline long downResize( long existing, long needed )
  149. { return LIN_DOWN(existing, needed); }
  150. };
  151. /**
  152. * \addtogroup vector
  153. * @{
  154. */
  155. /** \class ResizeConst
  156. * \brief Constant table resizer.
  157. *
  158. * When an up resize is needed the existing size is always used. ResizeConst
  159. * does not allow dynamic resizing. To use ResizeConst, the vector needs to be
  160. * constructed with and initial allocation amount otherwise it will be
  161. * unusable.
  162. */
  163. /*@}*/
  164. /* Constant table resizing. */
  165. class ResizeConst
  166. {
  167. protected:
  168. /* Assert don't need more than exists. Return existing. */
  169. static inline long upResize( long existing, long needed );
  170. /**
  171. * \brief Determine the new table size when down resizing.
  172. *
  173. * Always returns the existing table size.
  174. */
  175. static inline long downResize( long existing, long needed )
  176. { return CONST_DOWN(existing, needed); }
  177. };
  178. /**
  179. * \brief Determine the new table size when up resizing.
  180. *
  181. * If the existing size is insufficient for the space needed, then an assertion
  182. * will fail. Otherwise returns the existing size.
  183. */
  184. inline long ResizeConst::upResize( long existing, long needed )
  185. {
  186. assert( needed <= existing );
  187. return CONST_UP(existing, needed);
  188. }
  189. /**
  190. * \addtogroup vector
  191. * @{
  192. */
  193. /** \class ResizeRunTime
  194. * \brief Run time settable table resizer.
  195. *
  196. * ResizeRunTime can have it's up and down resizing policies set at run time.
  197. * Both up and down policies can be set independently to one of Exponential,
  198. * Linear, or Constant. See the documentation for ResizeExpn, ResizeLin, and
  199. * ResizeConst for the details of the resizing policies.
  200. *
  201. * The policies may be changed at any time. The default policies are
  202. * both Exponential.
  203. */
  204. /*@}*/
  205. /* Run time resizing. */
  206. class ResizeRunTime
  207. {
  208. protected:
  209. /**
  210. * \brief Default constuctor.
  211. *
  212. * The up and down resizing it initialized to Exponetial. The step
  213. * defaults to 256 units of T.
  214. */
  215. inline ResizeRunTime();
  216. /**
  217. * \brief Resizing policies.
  218. */
  219. enum ResizeType {
  220. Exponential, /*!< Exponential resizing. */
  221. Linear, /*!< Linear resizing. */
  222. Constant /*!< Constant table size. */
  223. };
  224. inline long upResize( long existing, long needed );
  225. inline long downResize( long existing, long needed );
  226. public:
  227. /**
  228. * \brief Step for linear resize.
  229. *
  230. * Amount of extra space in units of T added each time a resize must take
  231. * place. This may be changed at any time. The step should be >= 0.
  232. */
  233. long step;
  234. /**
  235. * \brief Up resizing policy.
  236. */
  237. ResizeType upResizeType;
  238. /**
  239. * \brief Down resizing policy.
  240. */
  241. ResizeType downResizeType;
  242. };
  243. inline ResizeRunTime::ResizeRunTime()
  244. :
  245. step( LIN_DEFAULT_STEP ),
  246. upResizeType( Exponential ),
  247. downResizeType( Exponential )
  248. {
  249. }
  250. /**
  251. * \brief Determine the new table size when up resizing.
  252. *
  253. * Type of up resizing is determined by upResizeType. Exponential, Linear and
  254. * Constant resizing is the same as that of ResizeExpn, ResizeLin and
  255. * ResizeConst.
  256. */
  257. inline long ResizeRunTime::upResize( long existing, long needed )
  258. {
  259. switch ( upResizeType ) {
  260. case Exponential:
  261. return EXPN_UP(existing, needed);
  262. case Linear:
  263. return LIN_UP(existing, needed);
  264. case Constant:
  265. assert( needed <= existing );
  266. return CONST_UP(existing, needed);
  267. }
  268. return 0;
  269. };
  270. /**
  271. * \brief Determine the new table size when down resizing.
  272. *
  273. * Type of down resizing is determined by downResiizeType. Exponential, Linear
  274. * and Constant resizing is the same as that of ResizeExpn, ResizeLin and
  275. * ResizeConst.
  276. */
  277. inline long ResizeRunTime::downResize( long existing, long needed )
  278. {
  279. switch ( downResizeType ) {
  280. case Exponential:
  281. return EXPN_DOWN(existing, needed);
  282. case Linear:
  283. return LIN_DOWN(existing, needed);
  284. case Constant:
  285. return CONST_DOWN(existing, needed);
  286. }
  287. return 0;
  288. }
  289. /* Don't need these anymore. */
  290. #undef EXPN_UP
  291. #undef EXPN_DOWN
  292. #undef LIN_UP
  293. #undef LIN_DOWN
  294. #undef CONST_UP
  295. #undef CONST_DOWN
  296. #ifdef AAPL_NAMESPACE
  297. }
  298. #endif
  299. #endif /* _AAPL_RESIZE_H */