summaryrefslogtreecommitdiff
path: root/aapl/resize.h
blob: 9e8491aa44000640c1929556c439f6e497c3f495 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/*
 *  Copyright 2002 Adrian Thurston <thurston@complang.org>
 */

/*  This file is part of Aapl.
 *
 *  Aapl is free software; you can redistribute it and/or modify it under the
 *  terms of the GNU Lesser General Public License as published by the Free
 *  Software Foundation; either version 2.1 of the License, or (at your option)
 *  any later version.
 *
 *  Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *  FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 *  more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with Aapl; if not, write to the Free Software Foundation, Inc., 59
 *  Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef _AAPL_RESIZE_H
#define _AAPL_RESIZE_H

#include <assert.h>

#ifdef AAPL_NAMESPACE
namespace Aapl {
#endif

/* This step is expressed in units of T. Changing this requires changes to
 * docs in ResizeLin constructor.  */
#define LIN_DEFAULT_STEP 256

/*
 * Resizing macros giving different resize methods.
 */

/* If needed is greater than existing, give twice needed. */
#define EXPN_UP( existing, needed ) \
		needed > existing ? (needed<<1) : existing
	
/* If needed is less than 1 quarter existing, give twice needed. */
#define EXPN_DOWN( existing, needed ) \
		needed < (existing>>2) ? (needed<<1) : existing

/* If needed is greater than existing, give needed plus step. */
#define LIN_UP( existing, needed ) \
	needed > existing ? (needed+step) : existing

/* If needed is less than existing - 2 * step then give needed plus step. */
#define LIN_DOWN( existing, needed ) \
	needed < (existing-(step<<1)) ? (needed+step) : existing

/* Return existing. */
#define CONST_UP( existing, needed ) existing

/* Return existing. */
#define CONST_DOWN( existing, needed ) existing

/**
 * \addtogroup vector
 * @{
 */

/** \class ResizeLin
 * \brief Linear table resizer.
 *
 * When an up resize or a down resize is needed, ResizeLin allocates the space
 * needed plus some user defined step. The result is that when growing the
 * vector in a linear fashion, the number of resizes is also linear.
 *
 * If only up resizing is done, then there will never be more than step unused
 * spaces in the vector. If down resizing is done as well, there will never be
 * more than 2*step unused spaces in the vector. The up resizing and down
 * resizing policies are offset to improve performance when repeatedly
 * inserting and removing a small number of elements relative to the step.
 * This scheme guarantees that repetitive inserting and removing of a small
 * number of elements will never result in repetative reallocation.
 *
 * The vectors pass sizes to the resizer in units of T, so the step gets
 * interpreted as units of T.
 */

/*@}*/

/* Linear resizing. */
class ResizeLin
{
protected:
	/**
	 * \brief Default constructor.
	 *
	 * Intializes resize step to 256 units of the table type T.
	 */
	ResizeLin() : step(LIN_DEFAULT_STEP) { }

	/**
	 * \brief Determine the new table size when up resizing.
	 *
	 * If the existing size is insufficient for the space needed, then allocate
	 * the space needed plus the step. The step is in units of T.
	 */
	inline long upResize( long existing, long needed )
		{ return LIN_UP(existing, needed); }

	/**
	 * \brief Determine the new table size when down resizing.
	 *
	 * If space needed is less than the existing - 2*step, then allocate the
	 * space needed space plus the step. The step is in units of T.
	 */
	inline long downResize( long existing, long needed )
		{ return LIN_DOWN(existing, needed); }

public:
	/**
	 * \brief Step for linear resize.
	 *
	 * Amount of extra space in units of T added each time a resize must take
	 * place. This may be changed at any time. The step should be >= 0.
	 */
	long step;
};

/**
 * \addtogroup vector
 * @{
 */

/** \class ResizeCtLin
 * \brief Linear table resizer with compile time step.
 *
 * When an up resize or a down resize is needed, ResizeCtLin allocates the
 * space needed plus some compile time defined step. The result is that when
 * growing the vector in a linear fashion, the number of resizes is also
 * linear.
 *
 * If only up resizing is done, then there will never be more than step unused
 * spaces in the vector. If down resizing is done as well, there will never be
 * more than 2*step unused spaces in the vector. The up resizing and down
 * resizing policies are offset to improve performance when repeatedly
 * inserting and removing a small number of elements relative to the step.
 * This scheme guarantees that repetitive inserting and removing of a small
 * number of elements will never result in repetative reallocation.
 *
 * The vectors pass sizes to the resizer in units of T, so the step gets
 * interpreted as units of T.
 */

/*@}*/

/* Linear resizing. */
template <long step> class ResizeCtLin
{
protected:
	/**
	 * \brief Determine the new table size when up resizing.
	 *
	 * If the existing size is insufficient for the space needed, then allocate
	 * the space needed plus the step. The step is in units of T.
	 */
	inline long upResize( long existing, long needed )
		{ return LIN_UP(existing, needed); }

	/**
	 * \brief Determine the new table size when down resizing.
	 *
	 * If space needed is less than the existing - 2*step, then allocate the
	 * space needed space plus the step. The step is in units of T.
	 */
	inline long downResize( long existing, long needed )
		{ return LIN_DOWN(existing, needed); }
};

/**
 * \addtogroup vector
 * @{
 */

/** \class ResizeConst
 * \brief Constant table resizer.
 *
 * When an up resize is needed the existing size is always used. ResizeConst
 * does not allow dynamic resizing. To use ResizeConst, the vector needs to be
 * constructed with and initial allocation amount otherwise it will be
 * unusable.
 */

/*@}*/

/* Constant table resizing. */
class ResizeConst
{
protected:
	/* Assert don't need more than exists. Return existing. */
	static inline long upResize( long existing, long needed );

	/**
	 * \brief Determine the new table size when down resizing.
	 *
	 * Always returns the existing table size.
	 */
	static inline long downResize( long existing, long needed )
		{ return CONST_DOWN(existing, needed); }
};

/**
 * \brief Determine the new table size when up resizing.
 *
 * If the existing size is insufficient for the space needed, then an assertion
 * will fail. Otherwise returns the existing size.
 */
inline long ResizeConst::upResize( long existing, long needed )
{	
	assert( needed <= existing ); 
	return CONST_UP(existing, needed); 
}

/**
 * \addtogroup vector
 * @{
 */

/** \class ResizeRunTime
 * \brief Run time settable table resizer.
 *
 * ResizeRunTime can have it's up and down resizing policies set at run time.
 * Both up and down policies can be set independently to one of Exponential,
 * Linear, or Constant. See the documentation for ResizeExpn, ResizeLin, and
 * ResizeConst for the details of the resizing policies. 
 *
 * The policies may be changed at any time. The default policies are
 * both Exponential.
 */

/*@}*/

/* Run time resizing. */
class ResizeRunTime
{
protected:
	/**
	 * \brief Default constuctor.
	 *
	 * The up and down resizing it initialized to Exponetial. The step
	 * defaults to 256 units of T.
	 */
	inline ResizeRunTime();

	/**
	 * \brief Resizing policies.
	 */
	enum ResizeType {
		Exponential,  /*!< Exponential resizing. */
		Linear,       /*!< Linear resizing. */
		Constant      /*!< Constant table size. */
	};

	inline long upResize( long existing, long needed );
	inline long downResize( long existing, long needed );

public:
	/**
	 * \brief Step for linear resize.
	 *
	 * Amount of extra space in units of T added each time a resize must take
	 * place. This may be changed at any time. The step should be >= 0.
	 */
	long step;

	/**
	 * \brief Up resizing policy.
	 */
	ResizeType upResizeType;

	/**
	 * \brief Down resizing policy.
	 */
	ResizeType downResizeType;
};

inline ResizeRunTime::ResizeRunTime()
:
	step( LIN_DEFAULT_STEP ),
	upResizeType( Exponential ),
	downResizeType( Exponential )
{
}

/**
 * \brief Determine the new table size when up resizing.
 *
 * Type of up resizing is determined by upResizeType. Exponential, Linear and
 * Constant resizing is the same as that of ResizeExpn, ResizeLin and
 * ResizeConst.
 */
inline long ResizeRunTime::upResize( long existing, long needed )
{
	switch ( upResizeType ) {
	case Exponential:
		return EXPN_UP(existing, needed);
	case Linear:
		return LIN_UP(existing, needed);
	case Constant:
		assert( needed <= existing ); 
		return CONST_UP(existing, needed);
	}
	return 0;
};

/**
 * \brief Determine the new table size when down resizing.
 *
 * Type of down resizing is determined by downResiizeType. Exponential, Linear
 * and Constant resizing is the same as that of ResizeExpn, ResizeLin and
 * ResizeConst.
 */
inline long ResizeRunTime::downResize( long existing, long needed )
{
	switch ( downResizeType ) {
	case Exponential:
		return EXPN_DOWN(existing, needed);
	case Linear:
		return LIN_DOWN(existing, needed);
	case Constant:
		return CONST_DOWN(existing, needed);
	}
	return 0;
}

/* Don't need these anymore. */
#undef EXPN_UP
#undef EXPN_DOWN
#undef LIN_UP
#undef LIN_DOWN
#undef CONST_UP
#undef CONST_DOWN

#ifdef AAPL_NAMESPACE
}
#endif

#endif /* _AAPL_RESIZE_H */