OpenASIP 2.2
Loading...
Searching...
No Matches
MathTools.icc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file MathTools.icc
26 *
27 * Inline implementations.
28 *
29 * @author Ari Metsähalme 2005 (ari.metsahalme-no.spam-tut.fi)
30 * @author Pekka Jääskeläinen 2006 (pekka.jaaskelainen-no.spam-tut.fi)
31 */
32
33#include <cstdlib>
34#include <bitset>
35#include <cmath>
36#include <ctime>
37#include "Exception.hh"
38#include "MathTools.hh"
39#include "BaseType.hh"
40
41/**
42 * Returns the number of bits required to represent the given (nonzero) number
43 * as an unsigned number. Gives result(1) for 0.
44 *
45 * @note assumes that integers are stored as 2's complement.
46 *
47 * @param number The number.
48 * @return The number of bits required to represent the given number.
49 */
50inline int
51MathTools::requiredBits(unsigned long int number) {
52 if (number == 0) {
53 return 1;
54 } else {
55 return requiredBits0Bit0(number);
56 }
57}
58
59/**
60 * Returns the number of bits required to represent the given number
61 * as an unsigned number. Gives result(0) for 0.
62 */
63inline int
64MathTools::requiredBits0Bit0(long unsigned int number) {
65 unsigned int bits = 0;
66 while (number != 0) {
67 number = number >> 1;
68 bits++;
69 }
70 return bits;
71}
72
73/**
74 * Returns ceiling of base-2 logarithm of given number as integer.
75 */
76inline int
77MathTools::ceil_log2(long unsigned int number) {
78 return static_cast<int>(ceil(log(number)/log(2.0)));
79}
80
81/**
82 * Returns ceiling of divided numbers as integer.
83 */
84template<typename NumberType>
85inline int
86MathTools::ceil_div(NumberType dividee, NumberType diveder) {
87 return static_cast<int>(ceil((double) dividee / (double) diveder));
88}
89
90
91
92/**
93 * Returns the number of bits required to represent the given number as
94 * a signed integer.
95 *
96 * @note assumes that integers are stored as 2's complement.
97 *
98 * @param number The number.
99 * @return The number of bits required to represent the given number.
100 */
101
102inline int
103MathTools::requiredBitsSigned(SLongWord number) {
104 int bits = 1;
105 while (number != -1 && number != 0) {
106 number = number >> 1;
107 bits++;
108 }
109 return bits;
110}
111
112/**
113 * Returns the number of bits required to represent the given number as
114 * a signed integer.
115 *
116 * @note assumes that integers are stored as 2's complement.
117 *
118 * @param number The number.
119 * @return The number of bits required to represent the given number.
120 */
121
122inline int
123MathTools::requiredBitsSigned(UInt32 number) {
124
125 // first cast to a signed type
126 int32_t numberSigned = static_cast<int32_t>(number);
127 return requiredBitsSigned(static_cast<SLongWord>(numberSigned));
128}
129
130/**
131 * Returns the number of bits required to represent the given number as
132 * a signed integer.
133 *
134 * @note assumes that integers are stored as 2's complement.
135 *
136 * @param number The number.
137 * @return The number of bits required to represent the given number.
138 */
139
140inline int
141MathTools::requiredBitsSigned(int number) {
142
143 return requiredBitsSigned(static_cast<SLongWord>(number));
144}
145
146/**
147 * Returns the number of bits required to represent the given number as
148 * a signed integer.
149 *
150 * @note assumes that integers are stored as 2's complement.
151 *
152 * @param number The number.
153 * @return The number of bits required to represent the given number.
154 */
155
156inline int
157MathTools::requiredBitsSigned(ULongWord number) {
158 return requiredBitsSigned(static_cast<SLongWord>(number));
159}
160
161/**
162 * Returns the number of bits required to represent the give number as
163 * an unsigned number. 0 is implicit 0.
164 *
165 * @note assumes that integers are stored as 2's complement.
166 *
167 * @param number The number.
168 * @return The number of bits required to represent the given number.
169 */
170inline unsigned int
171MathTools::bitLength(long unsigned int number) {
172 unsigned int bits = 0;
173 while (number != 0) {
174 number = number >> 1;
175 bits++;
176 }
177 return bits;
178}
179
180
181/**
182 * Compares bit fields (binary encoded) of enc1 and enc2.
183 *
184 * @verbatim
185 * Example:
186 * ->| |<-----| pos1 = 6
187 * 00001101011011| enc1 = 859 => 1101
188 * 00001011110100| enc2 = 756 => = 1101
189 * ->| |<-| pos2 = 2 ---------
190 * --------------- width = 4 true
191 * @endverbatim
192 *
193 * @param enc1 The first binary encoded bit field.
194 * @param pos1 The first LSB bit from right of the enc1.
195 * @param enc2 The second binary encoded bit field.
196 * @param pos2 The first LSB bit from right of the enc2.
197 * @param width The number of bits considered in the comparison.
198 * @return True if the fields do match. Otherwise, false.
199 */
200inline bool
201MathTools::bitFieldsEquals(
202 unsigned enc1, unsigned pos1,
203 unsigned enc2, unsigned pos2,
204 unsigned width) {
205
206 if (width) {
207 enc1 = enc1 >> pos1;
208 enc2 = enc2 >> pos2;
209 enc1 = enc1 & ~(~(0u) << width);
210 enc2 = enc2 & ~(~(0u) << width);
211 return enc1 == enc2;
212 }
213 return false;
214}
215
216
217/**
218 * Returns the value of the bit at a given position in an integer.
219 *
220 * @param integer The integer.
221 * @param index Indicates which bit should be returned (0 = LSB).
222 * @return The value of the bit indicated by the given index.
223 */
224inline bool
225MathTools::bit(ULongWord integer, unsigned int index) {
226 return (integer & (1 << index)) != 0;
227}
228
229
230/**
231 * Sets or clears bit at the index.
232 *
233 * @param bits The bits.
234 * @param index The index of the bit starting from zero. The bits are indexed
235 * from LSB.
236 * @param bitState The state of the bit to be set. By default sets bit to one.
237 */
238template<class IntegerType>
239inline
240void
241MathTools::setBit(
242 IntegerType& bits, unsigned int index, bool bitState) {
243 if (bitState) {
244 bits |= IntegerType(1) << index;
245 } else {
246 bits &= ~(IntegerType(1) << index);
247 }
248}
249
250
251/**
252 * Chops a signed integer number to a given bit width.
253 *
254 * Overwrites all bits that do not fit in the given bit width with the sign
255 * bit (the bit at position width - 1).
256 *
257 * This operation corresponds to reinterpreting the given number as a signed
258 * word of given bit width.
259 *
260 * @param value A signed integer.
261 * @param width Number of meaningful bits in the given integer.
262 * @return The sign-extended value of the integer.
263 * @exception OutOfRange If width > integer size
264 */
265inline SLongWord
266MathTools::signExtendTo(SLongWord value, int width) {
267
268 int bitsInInt = sizeof(value) * BYTE_BITWIDTH;
269 if (width > bitsInInt) {
270 throw OutOfRange(__FILE__, __LINE__, __func__);
271 }
272
273 value = value << (bitsInInt - width);
274 value = value >> (bitsInInt - width);
275
276 return value;
277}
278
279
280/**
281 * Chops an unsigned integer number to a given bit width.
282 *
283 * Overwrites all bits that do not fit in the given bit width with zero.
284 *
285 * This operation corresponds to reinterpreting the given number as an
286 * unsigned word of given bit width.
287 *
288 * @param value An unsigned integer.
289 * @param width Number of meaningful bits in the given integer.
290 * @return The zero-extended value of the integer.
291 * @exception OutOfRange If width > integer size
292 */
293inline ULongWord
294MathTools::zeroExtendTo(ULongWord value, int width) {
295
296 int bitsInInt = sizeof(value) * BYTE_BITWIDTH;
297 if (width > bitsInInt) {
298 throw OutOfRange(__FILE__, __LINE__, __func__);
299 }
300
301 // and with a mask with only the lower 'width' bits '1'
302 value = value & (~(ULongWord)0 >> (bitsInInt - width));
303
304 return value;
305}
306
307
308/**
309 * Same as signExtendTo, except without additional overhead of exceptions
310 *
311 * @param value A signed integer.
312 * @param width Number of meaningful bits in the given integer.
313 * @note width must not exceed int bitwidth!
314 * @return The sign-extended value of the integer.
315 */
316inline SLongWord
317MathTools::fastSignExtendTo(SLongWord value, int width) {
318
319 const int bitsInInt = sizeof(SLongWord) * BYTE_BITWIDTH;
320
321 value = value << (bitsInInt - width);
322 value = value >> (bitsInInt - width);
323
324 return value;
325}
326
327
328/**
329 * Same as zeroExtendTo, except without additional overhead of exceptions
330 *
331 * @param value An unsigned integer.
332 * @param width Number of meaningful bits in the given integer.
333 * @note width must not exceed int bitwidth!
334 * @return The zero-extended value of the integer.
335 */
336inline ULongWord
337MathTools::fastZeroExtendTo(ULongWord value, int width) {
338
339 const int bitsInInt = sizeof(value) * BYTE_BITWIDTH;
340
341 // and with a mask with only the lower 'width' bits '1'
342 value = value & (~(ULongWord)0 >> (bitsInInt - width));
343
344 return value;
345}
346
347
348/**
349 * Returns a random number between range min..max
350 *
351 * @param min minimum value
352 * @param max maximum value
353 * @return The generated pseudo-random number
354 */
355inline int
356MathTools::random(int min, int max) {
357 static bool initialized = false;
358 if (!initialized) {
359 srand(std::time(0));
360 initialized = true;
361 }
362 return (rand() % (max - min + 1)) + min;
363}
364
365/**
366 * Rounds a number upwards to a number which is of power-2.
367 */
368inline unsigned int
369MathTools::roundUpToPowerTwo(unsigned int number) {
370 unsigned int i = 0;
371 if (number == 0) {
372 return 0;
373 }
374 for (; (1u << i) < number; i++) ;
375 return (1u << i);
376}
377
378/**
379 * Rounds a number downwards to a number which is of power-2.
380 */
381inline ULongWord
382MathTools::roundDownToPowerTwo(ULongWord number) {
383 ULongWord i = 0;
384 if (number == 0) {
385 return 0;
386 }
387 for (; 1lu << i <= number; i++) ;
388 return (1lu<<i) >> 1;
389}
390
391/**
392 * Rounds a number upwards to a number which is of power-2.
393 */
394inline int
395MathTools::roundUpToPowerTwo(int number) {
396 return static_cast<int>(roundUpToPowerTwo(
397 static_cast<unsigned int>(number)));
398}
399
400/**
401 * Rounds a number downwards to a number which is of power-2.
402 */
403inline SLongWord
404MathTools::roundDownToPowerTwo(SLongWord number) {
405 return static_cast<SLongWord>(roundDownToPowerTwo(
406 static_cast<ULongWord>(number)));
407}
408
409
410/**
411 * Returns true if the number is in set of 2^i where i is positive integer.
412 */
413inline bool
414MathTools::isInPowerOfTwo(unsigned int number) {
415 std::bitset<sizeof(unsigned int)*8> bits(number);
416 return bits.count() == 1;
417}
418
419
420/**
421 * Return integer range that can be expressed by a binary field.
422 *
423 * The template argument must implement:
424 * - ResultNumberType(0), ResultNumberType(1),
425 * - (-ResultNumberType) -> ResultNumberType,
426 * - (ResultNumberType << unsigned) -> ResultNumberType and
427 * - (ResultNumberType - int) -> ResultNumberType
428 */
429template<typename ResultNumberTypeS, typename ResultNumberTypeU>
430inline std::pair<ResultNumberTypeS, ResultNumberTypeU>
431MathTools::bitsToIntegerRange(
432 unsigned bitWidth, bool signExtending) {
433
434 if (bitWidth == 0) {
435 return std::make_pair(ResultNumberTypeS(0), ResultNumberTypeU(0));
436 }
437
438 // Todo needs different handling when
439 // bitWidth == bitWidth(ResultNumberType)
440
441 ResultNumberTypeS currLowerBound(0);
442 ResultNumberTypeU currUpperBound(0);
443 if (signExtending) {
444 currLowerBound = -(ResultNumberTypeS(1) << (bitWidth-1));
445 currUpperBound = (ResultNumberTypeU(1) << (bitWidth-1))-1;
446 } else {
447 currUpperBound = (ResultNumberTypeU(1) << (bitWidth))-1;
448 }
449 return std::make_pair(currLowerBound, currUpperBound);
450}
451