Skip to content

Commit 5136ee1

Browse files
MogballDeep Dhillon
authored andcommitted
Fixed up Bitset (#36)
* Fixed up Bitset * code review changes * cast changed from int to uint32_t
1 parent f0bbe05 commit 5136ee1

File tree

8 files changed

+275
-83
lines changed

8 files changed

+275
-83
lines changed

lib/wlib/CMakeLists.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
project(wlib)
22

33
file (GLOB header_files
4-
"Wlib.h"
5-
"strings/*.h"
6-
"stl/*.h"
7-
"memory/*.h")
4+
"Wlib.h"
5+
"strings/*.h"
6+
"stl/*.h"
7+
"memory/*.h")
88

99
file (GLOB source_files
10-
"memory/*.cpp")
10+
"memory/*.cpp")
1111

1212
set(HEADER_FILES ${header_files} )
1313
set(SOURCE_FILES ${source_files})

lib/wlib/Wlib.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
#ifndef EMBEDDEDTESTS_WLIB_H
22
#define EMBEDDEDTESTS_WLIB_H
33

4-
#define max(a,b) \
5-
({ __typeof__ (a) _a = (a); \
6-
__typeof__ (b) _b = (b); \
7-
_a > _b ? _a : _b; })
8-
4+
#define max(x, y) (((x) > (y)) ? (x) : (y))
95
#define min(x, y) (((x) < (y)) ? (x) : (y))
106

7+
#define BYTE_SIZE 8
8+
#define INT_SIZE (BYTE_SIZE * sizeof(uint32_t))
9+
1110
#endif //EMBEDDEDTESTS_WLIB_H

lib/wlib/stl/Bitset.h

Lines changed: 128 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,149 +17,215 @@
1717
#include <stdint.h>
1818
#include <math.h>
1919

20+
#include "Wlib.h"
21+
2022
namespace wlp {
21-
#define NO_OF_BITS (8 * sizeof(unsigned int))
2223

23-
template<uint8_t bits>
24+
/**
25+
* Computes the mask corresponding to the number of bits
26+
* or the exponent in the from 2^n - 1.
27+
* @tparam exp the number of bits, 32 or less
28+
*/
29+
template<uint8_t exp>
30+
struct pow_mask {
31+
static const uint32_t value = (uint32_t) ((1 << exp) - 1);
32+
};
33+
34+
/**
35+
* Template specialization for 32 bits to
36+
* prevent overflow.
37+
*/
38+
template<> struct pow_mask<32> {
39+
static const uint32_t value = 0xffffffff;
40+
};
41+
42+
/**
43+
* Compute the minimum number of integers
44+
* needed to store a certain number of bits.
45+
* @tparam nBits the bits to store
46+
*/
47+
template<uint8_t nBits>
48+
struct ceil_bits {
49+
static const uint32_t value = (nBits + INT_SIZE - 1) / INT_SIZE;
50+
};
51+
52+
template<uint8_t nBits>
2453
class Bitset {
2554
public:
2655
/**
27-
* Default Constructor creates an empty bitset
56+
* Default Constructor creates an empty bitset.
2857
*/
2958
Bitset() {
3059
memset(m_array, 0, sizeof(m_array));
3160
}
3261

3362
/**
34-
* Constructor creates a bitset from a number that can be of max
35-
* 64 bit in size
63+
* Constructor creates a bitset from a number that
64+
* can be of max 64 bit in size.
3665
*
37-
* @param number the number to create bitset from
66+
* @param n the number to create bitset from
3867
*/
39-
explicit Bitset(uint64_t number){
40-
memset(m_array, 0, sizeof(m_array));
41-
42-
uint16_t size = sizeof(number) * 8;
68+
explicit Bitset(uint64_t n) {
69+
setFromNumber(n);
70+
}
4371

44-
if (size > bits) size = bits;
72+
/**
73+
* Copy constructor.
74+
* @param b Bitset to copy
75+
*/
76+
Bitset(Bitset<nBits>& b) {
77+
uint32_t end = ceil_bits<nBits>::value;
78+
for (uint16_t i = 0; i < end; i++) {
79+
m_array[i] = (m_array[i] & 0) | b.m_array[i];
80+
}
81+
}
4582

46-
for (uint16_t index = 0; index < size; ++index) {
47-
uint8_t remainder = (uint8_t) (number % 2);
48-
number /= 2;
83+
/**
84+
* Copy constructor for const.
85+
* @param b Bitset to copy
86+
*/
87+
Bitset(const Bitset<nBits>& b) {
88+
uint32_t end = ceil_bits<nBits>::value;
89+
for (uint16_t i = 0; i < end; i++) {
90+
m_array[i] = (m_array[i] & 0) | b.m_array[i];
91+
}
92+
}
4993

50-
if (remainder) set(index);
51-
else reset(index);
94+
/**
95+
* Set the value of the Bitset from a number
96+
* of maximum 64 bit size.
97+
* @param n the number to set from
98+
*/
99+
void setFromNumber(uint64_t n) {
100+
memset(m_array, 0, sizeof(m_array));
101+
constexpr uint32_t end = nBits / INT_SIZE;
102+
constexpr uint32_t extra = nBits - end * INT_SIZE;
103+
for (uint16_t i = 0; i < end; ++i) {
104+
m_array[i] = (uint32_t) n;
105+
n >>= INT_SIZE;
106+
}
107+
if (extra) {
108+
m_array[end] = ((uint32_t) n) & pow_mask<extra>::value;
52109
}
53110
}
54111

55112

56113
/**
57-
* Sets the bit at @code index to be true
114+
* Sets the bit at @code index to be true.
58115
*
59116
* @param index the index of the bit
60117
*/
61118
void set(uint16_t index) {
62-
m_array[index / NO_OF_BITS] |= (1U << (index % NO_OF_BITS));
119+
m_array[index / INT_SIZE] |= (1U << (index % INT_SIZE));
63120
}
64121

65122
/**
66-
* Sets the bit at @code index to be false
123+
* Sets the bit at @code index to be false.
67124
*
68125
* @param index the index of the bit
69126
*/
70127
void reset(uint16_t index) {
71-
m_array[index / NO_OF_BITS] &= ~(1U << (index % NO_OF_BITS));
128+
m_array[index / INT_SIZE] &= ~(1U << (index % INT_SIZE));
72129
}
73130

74131
/**
75-
* Toggles the but at @code index
132+
* Toggles the but at @code index.
76133
*
77134
* @param index the index of the bit
78135
*/
79136
void flip(uint16_t index) {
80-
m_array[index / NO_OF_BITS] ^= (1U << (index % NO_OF_BITS));
137+
m_array[index / INT_SIZE] ^= (1U << (index % INT_SIZE));
81138
}
82139

83140
/**
84-
* Returns the value of bit at @code index
141+
* Returns the value of bit at @code index.
85142
*
86143
* @param index the index of the bit
87144
* @return the bit value
88145
*/
89-
bool test(uint16_t index) {
90-
return (m_array[index / NO_OF_BITS] & (1U << (index % NO_OF_BITS))) != 0;
146+
bool test(uint16_t index) const {
147+
return (m_array[index / INT_SIZE] & (1U << (index % INT_SIZE))) != 0;
91148
}
92149

93150
/**
94151
* Converts the bits into 64 bit unsigned integer
95152
*
96153
* @return unsigned 64 bit integer
97154
*/
98-
uint64_t to_uint64_t() {
99-
uint64_t number = 0;
100-
101-
for (uint8_t i = 0; i < 64; ++i) {
102-
uint64_t powerVal = (uint64_t) ceil(pow(2, i));
103-
uint8_t bitVal = (uint8_t) test(i);
104-
number += bitVal * powerVal;
155+
uint64_t to_uint64_t() const {
156+
if (nBits <= 32) {
157+
return to_uint32_t();
105158
}
106-
107-
return number;
159+
return (((uint64_t) m_array[1]) << INT_SIZE) | ((uint32_t) m_array[0]);
108160
}
109161

110162
/**
111163
* Converts the bits into 32 bit unsigned integer
112164
*
113165
* @return unsigned 32 bit integer
114166
*/
115-
uint32_t to_uint32_t() {
116-
uint32_t number = 0;
117-
118-
for (uint8_t i = 0; i < 32; ++i) {
119-
uint32_t powerVal = (uint32_t) ceil(pow(2, i));
120-
uint8_t bitVal = (uint8_t) test(i);
121-
number += bitVal * powerVal;
122-
}
123-
124-
return number;
167+
uint32_t to_uint32_t() const {
168+
return (uint32_t) m_array[0];
125169
}
126170

127171
/**
128172
* Converts the bits into 16 bit unsigned integer
129173
*
130174
* @return unsigned 16 bit integer
131175
*/
132-
uint16_t to_uint16_t() {
133-
uint16_t number = 0;
134-
135-
for (uint8_t i = 0; i < 16; ++i) {
136-
uint16_t powerVal = (uint16_t) ceil(pow(2, i));
137-
uint8_t bitVal = (uint8_t) test(i);
138-
number += bitVal * powerVal;
139-
}
140-
141-
return number;
176+
uint16_t to_uint16_t() const {
177+
return (uint16_t) (m_array[0] & pow_mask<16>::value);
142178
}
143179

144180
/**
145181
* Converts the bits into 8 bit unsigned integer
146182
*
147183
* @return unsigned 8 bit integer
148184
*/
149-
uint8_t to_uint8_t() {
150-
uint8_t number = 0;
185+
uint8_t to_uint8_t() const {
186+
return (uint8_t) (m_array[0] & pow_mask<8>::value);
187+
}
151188

152-
for (uint8_t i = 0; i < 8; ++i) {
153-
uint8_t powerVal = (uint8_t) ceil(pow(2, i));
154-
uint8_t bitVal = (uint8_t) test(i);
155-
number += bitVal * powerVal;
189+
/**
190+
* Access operator returns the bit at the given position.
191+
* @param i the position of the bit to test
192+
* @return the value of the bit
193+
*/
194+
bool operator[](const uint16_t i) const {
195+
return test(i);
196+
}
197+
198+
/**
199+
* Assignment operator copies the contents of the bitset.
200+
* @param b Bitset to assign
201+
*/
202+
Bitset<nBits>& operator=(Bitset<nBits>& b) {
203+
uint32_t end = ceil_bits<nBits>::value;
204+
for (uint16_t i = 0; i < end; i++) {
205+
m_array[i] = (m_array[i] & 0) | b.m_array[i];
156206
}
207+
return *this;
208+
}
157209

158-
return number;
210+
/**
211+
* Assignment operator copies the contents of the bitset.
212+
* @param b Bitset to assign
213+
*/
214+
Bitset<nBits>& operator=(const Bitset<nBits>& b) {
215+
uint32_t end = ceil_bits<nBits>::value;
216+
for (uint16_t i = 0; i < end; i++) {
217+
m_array[i] = (m_array[i] & 0) | b.m_array[i];
218+
}
219+
return *this;
159220
}
160221

161222
private:
162-
int m_array[bits/ NO_OF_BITS];
223+
/**
224+
* Backing array of integers that contain the bites.
225+
* Integer type arrays generally have the fastest access
226+
* times in C++.
227+
*/
228+
uint32_t m_array[ceil_bits<nBits>::value];
163229
};
164230
}
165231

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ include_directories(${WLIB_INCLUDE_DIR})
1010

1111
file(GLOB files
1212
"test.cpp"
13+
"stl/*.cpp"
1314
"strings/*.cpp")
1415

1516
add_executable(tests ${files})

0 commit comments

Comments
 (0)