Project
Loading...
Searching...
No Matches
BitSet.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include "BitSet.h"
13#include <algorithm>
14#include <cmath>
15#include <fmt/format.h>
16#include <iostream>
17#include <stdexcept>
18#include "NofBits.h"
20
21namespace o2::mch::raw
22{
23
24namespace
25{
26
27template <typename T>
28void assertRange(int a, int b, T s)
29{
30 if (a > b || b - a >= sizeof(T) * 8) {
31 throw std::invalid_argument(fmt::format("Range [a,b]=[{0},{1}] is incorrect (max range={2}])", a, b, sizeof(T) * 8));
32 }
33}
34
35template <typename T>
36void setRangeFromIntegerFast(BitSet& bs, int a, int b, T v)
37{
38 assertRange<T>(a, b, v);
39 if (b > bs.size()) {
40 bs.grow(b);
41 }
42 for (int i = 0; i <= b - a; i++) {
43 T check = static_cast<T>(1) << i;
44 bs.setFast(i + a, (v & check) != 0);
45 }
46}
47
48template <typename T>
49T uint(const BitSet& bs, int a, int b)
50{
51 if (b < 0) {
52 b = bs.len() - 1;
53 }
54 if (a < 0 || b < 0 || (b - a) > (sizeof(T) * 8) || a >= bs.size() || b >= bs.size()) {
55 throw std::out_of_range(fmt::format("Range [{0},{1}] out of range. bs.size()={2}", a, b, bs.size()));
56 }
57 T value{0};
58 for (T i = a; i <= b; i++) {
59 if (bs.get(i)) {
60 value |= (static_cast<T>(1) << (i - a));
61 }
62 }
63 return value;
64}
65
66template <typename T>
67int appendT(BitSet& bs, T val, int n)
68{
69 if (n <= 0) {
70 if (val > 0) {
72 } else {
73 n = 1;
74 }
75 }
76
77 if (n > sizeof(T) * 8) {
78 throw std::invalid_argument(fmt::format("n={0} is invalid : should be between 0 and {1}",
79 n, sizeof(T)));
80 }
81
82 for (T i = 0; i < static_cast<T>(n); i++) {
83 T p = static_cast<T>(1) << i;
84 if ((val & p) == p) {
85 bs.append(true);
86 } else {
87 bs.append(false);
88 }
89 }
90 return n;
91} // namespace
92
93bool isValidString(std::string_view s)
94{
95 auto ones = std::count(begin(s), end(s), '1');
96 auto zeros = std::count(begin(s), end(s), '0');
97 return s.size() == ones + zeros;
98}
99
100void assertString(std::string_view s)
101{
102 if (!isValidString(s)) {
103 throw std::invalid_argument(fmt::format("{0} is not a valid bitset string (should only get 0 and 1 in there", s));
104 }
105}
106
107} // namespace
108
109BitSet::BitSet() : mSize(8), mLen(0), mMaxLen(0), mBytes(1)
110{
111}
112
113BitSet::BitSet(uint8_t v, int n) : mSize(n > 0 ? n : 8), mLen(0), mBytes(1)
114{
115 if (n <= 0) {
116 n = 8;
117 }
118 assertRange(1, n - 1, v);
119 setRangeFromUint(0, n - 1, v);
120}
121
122BitSet::BitSet(uint16_t v, int n) : mSize(n > 0 ? n : 16), mLen(0), mBytes(2)
123{
124 if (n <= 0) {
125 n = 16;
126 }
127 assertRange(1, n - 1, v);
128 setRangeFromUint(0, n - 1, v);
129}
130
131BitSet::BitSet(uint32_t v, int n) : mSize(n > 0 ? n : 32), mLen(0), mBytes(4)
132{
133 if (n <= 0) {
134 n = 32;
135 }
136 assertRange(1, n - 1, v);
137 setRangeFromUint(0, n - 1, v);
138}
139
140BitSet::BitSet(uint64_t v, int n) : mSize(n > 0 ? n : 64), mLen(0), mBytes(8)
141{
142 if (n <= 0) {
143 n = 64;
144 }
145 assertRange(1, n - 1, v);
146 setRangeFromUint(0, n - 1, v);
147}
148
149BitSet::BitSet(std::string_view s) : mSize(8), mLen(0), mBytes(1)
150{
151 setRangeFromString(0, s.size() - 1, s);
152}
153
154bool BitSet::operator==(const BitSet& rhs) const
155{
156 if (len() != rhs.len()) {
157 return false;
158 }
159 for (int i = 0; i < len(); i++) {
160 if (get(i) != rhs.get(i)) {
161 return false;
162 }
163 }
164 return true;
165}
166
167bool BitSet::operator!=(const BitSet& rhs) const
168{
169 return !(*this == rhs);
170}
171
173{
174 set(len(), val);
175 return 1;
176}
177
178int BitSet::append(uint8_t val, int n)
179{
180 return appendT<uint8_t>(*this, val, n);
181}
182
183int BitSet::append(uint16_t val, int n)
184{
185 return appendT<uint16_t>(*this, val, n);
186}
187
188int BitSet::append(uint32_t val, int n)
189{
190 return appendT<uint32_t>(*this, val, n);
191}
192
193int BitSet::append(uint64_t val, int n)
194{
195 return appendT<uint64_t>(*this, val, n);
196}
197
198bool BitSet::any() const
199{
200 for (int i = 0; i < len(); i++) {
201 if (get(i)) {
202 return true;
203 }
204 }
205 return false;
206}
207
209{
210 std::fill(begin(mBytes), end(mBytes), 0);
211 mLen = 0;
212}
213
214int BitSet::count() const
215{
216 int n{0};
217 for (int i = 0; i < len(); i++) {
218 if (get(i)) {
219 n++;
220 }
221 }
222 return n;
223}
224
225bool BitSet::get(int pos) const
226{
227 if (pos < 0 || pos >= size()) {
228 throw std::out_of_range(fmt::format("pos {0} is out of bounds", pos));
229 }
230 auto b = mBytes[pos / 8];
231 return ((b >> (pos % 8)) & 1) == 1;
232}
233
235{
236 if (n <= 0) {
237 throw std::invalid_argument("n should be >= 0");
238 }
239 if (n < size()) {
240 return false;
241 }
242 if (n > BitSet::maxSize()) {
243 throw std::length_error(fmt::format("trying to allocate a bitset of more than {0} bytes", BitSet::maxSize()));
244 }
245 auto nbytes = mBytes.size();
246 while (nbytes * 8 < n) {
247 nbytes *= 2;
248 }
249 mBytes.resize(nbytes, 0);
250 mSize = mBytes.size() * 8;
251 return true;
252}
253
255{
256 if (len() < n) {
257 throw std::length_error(fmt::format("cannot get {0} bits out of a bitset of size {1}", n, len()));
258 }
259 auto subbs = subset(len() - n, len() - 1);
260 if (subbs.len() != n) {
261 throw std::logic_error("subset not of the expected len");
262 }
263 return subbs;
264}
265
267{
268 if (len() < n) {
269 throw std::invalid_argument(fmt::format("cannot prune {0} bits", n));
270 }
271 for (int i = 0; i < len() - n; i++) {
272 set(i, get(i + n));
273 }
274 mLen -= n;
275}
276
277void BitSet::set(int pos, bool val)
278{
279 if (pos >= mSize) {
280 grow(pos + 1);
281 }
282 if (pos < 0) {
283 throw std::invalid_argument("pos should be > 0");
284 }
285 setFast(pos, val);
286}
287
288void BitSet::setFast(int pos, bool val)
289{
290 uint8_t ix = pos % 8;
291 uint8_t& b = mBytes[pos / 8];
292
293 uint8_t mask = 1 << ix;
294
295 if (val) {
296 b |= mask;
297 } else {
298 b &= ~mask;
299 }
300
301 if ((pos + 1) > mLen) {
302 mLen = pos + 1;
303 mMaxLen = std::max(mMaxLen, mLen);
304 }
305}
306
307void BitSet::setFromBytes(gsl::span<uint8_t> bytes)
308{
309 if (mSize < bytes.size() * 8) {
310 grow(bytes.size() * 8);
311 }
312 mBytes.clear();
313 std::copy(bytes.begin(), bytes.end(), std::back_inserter(mBytes));
314 mBytes.resize(bytes.size());
315 mLen = mBytes.size() * 8;
316 mMaxLen = std::max(mMaxLen, mLen);
317 mSize = mLen;
318}
319
320void BitSet::setRangeFromString(int a, int b, std::string_view s)
321{
322 assertString(s);
323 if (a > b) {
324 throw std::invalid_argument(fmt::format("range [{0},{1}] is invalid : {0} > {1}", a, b));
325 }
326 if (b - a + 1 != s.size()) {
327 throw std::invalid_argument(fmt::format("range [{0},{1}] is not the same size as string={2}", a, b, s));
328 }
329 if (a >= size() || b >= size()) {
330 grow(b);
331 }
332 for (int i = 0; i < s.size(); i++) {
333 set(i + a, s[i] == '1');
334 }
335}
336
337void BitSet::setRangeFromUint(int a, int b, uint8_t v)
338{
339 setRangeFromIntegerFast<uint8_t>(*this, a, b, v);
340}
341
342void BitSet::setRangeFromUint(int a, int b, uint16_t v)
343{
344 setRangeFromIntegerFast<uint16_t>(*this, a, b, v);
345}
346
347void BitSet::setRangeFromUint(int a, int b, uint32_t v)
348{
349 setRangeFromIntegerFast<uint32_t>(*this, a, b, v);
350}
351
352void BitSet::setRangeFromUint(int a, int b, uint64_t v)
353{
354 setRangeFromIntegerFast<uint64_t>(*this, a, b, v);
355}
356
357std::string BitSet::stringLSBLeft() const
358{
359 std::string s{""};
360 for (int i = 0; i < len(); i++) {
361 if (get(i)) {
362 s += "1";
363 } else {
364 s += "0";
365 }
366 }
367 return s;
368}
369
370std::string BitSet::stringLSBRight() const
371{
372 std::string s{""};
373 for (int i = len() - 1; i >= 0; i--) {
374 if (get(i)) {
375 s += "1";
376 } else {
377 s += "0";
378 }
379 }
380 return s;
381}
382
383BitSet BitSet::subset(int a, int b) const
384{
385 if (a >= size() || b > size() || b < a) {
386 auto msg = fmt::format("BitSet::subset : range [{},{}] is incorrect. size={}", a, b, size());
387 throw std::invalid_argument(msg);
388 }
389 BitSet sub;
390 sub.grow(b - a);
391 for (int i = a; i <= b; i++) {
392 sub.set(i - a, get(i));
393 }
394 return sub;
395}
396
397uint8_t BitSet::uint8(int a, int b) const
398{
399 return uint<uint8_t>(*this, a, b);
400}
401
402uint16_t BitSet::uint16(int a, int b) const
403{
404 return uint<uint16_t>(*this, a, b);
405}
406
407uint32_t BitSet::uint32(int a, int b) const
408{
409 return uint<uint32_t>(*this, a, b);
410}
411
412uint64_t BitSet::uint64(int a, int b) const
413{
414 return uint<uint64_t>(*this, a, b);
415}
416
417// append n bits to BitSet bs.
418// those n bits are taken from ringBuffer, starting at ringBuffer[startBit]
419// return the value of startBit to be used for a future call to this method
420// so the sequence of ringBuffer is not lost.
421int circularAppend(BitSet& bs, const BitSet& ringBuffer, int startBit, int n)
422{
423 int ix = startBit;
424
425 while (n > 0) {
426 bs.append(ringBuffer.get(ix));
427 --n;
428 ix++;
429 ix %= ringBuffer.len();
430 }
431 return ix;
432}
433
434std::ostream& operator<<(std::ostream& os, const BitSet& bs)
435{
436 os << bs.stringLSBLeft();
437 return os;
438}
439
440std::string compactString(const BitSet& bs)
441{
442 // replaces multiple sync patterns by nxSYNC
443 static BitSet syncWord(sampaSync().uint64(), 50);
444
445 if (bs.size() < 49) {
446 return bs.stringLSBLeft();
447 }
448 std::string s;
449
450 int i = 0;
451 int nsync = 0;
452 while (i + 49 < bs.len()) {
453 bool sync{false};
454 while (i + 49 < bs.len() && bs.subset(i, i + 49) == syncWord) {
455 i += 50;
456 nsync++;
457 sync = true;
458 }
459 if (sync) {
460 s += fmt::format("[{}SYNC]", nsync);
461 } else {
462 nsync = 0;
463 s += bs.get(i) ? "1" : "0";
464 i++;
465 }
466 }
467 for (int j = i; j < bs.len(); j++) {
468 s += bs.get(j) ? "1" : "0";
469 }
470 return s;
471}
472} // namespace o2::mch::raw
int32_t i
uint16_t pos
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
uint8_t uint8(int a, int b) const
Definition BitSet.cxx:397
uint16_t uint16(int a, int b) const
Definition BitSet.cxx:402
uint64_t uint64(int a, int b) const
Definition BitSet.cxx:412
bool grow(int n)
Definition BitSet.cxx:234
void pruneFirst(int n)
Definition BitSet.cxx:266
void setFromBytes(gsl::span< uint8_t > bytes)
Definition BitSet.cxx:307
static int maxSize()
Definition BitSet.h:100
BitSet last(int n) const
Definition BitSet.cxx:254
bool operator!=(const BitSet &rhs) const
Definition BitSet.cxx:167
std::string stringLSBLeft() const
Definition BitSet.cxx:357
void setRangeFromString(int a, int b, std::string_view s)
Definition BitSet.cxx:320
void setFast(int pos, bool val)
Definition BitSet.cxx:288
void setRangeFromUint(int a, int b, uint8_t v)
Definition BitSet.cxx:337
int append(bool val)
Definition BitSet.cxx:172
bool operator==(const BitSet &rhs) const
Definition BitSet.cxx:154
bool any() const
Definition BitSet.cxx:198
int len() const
Definition BitSet.h:103
bool get(int pos) const
Definition BitSet.cxx:225
uint32_t uint32(int a, int b) const
Definition BitSet.cxx:407
BitSet subset(int a, int b) const
Definition BitSet.cxx:383
int count() const
Definition BitSet.cxx:214
void set(int pos, bool val)
Definition BitSet.cxx:277
int size() const
Definition BitSet.h:97
std::string stringLSBRight() const
Definition BitSet.cxx:370
GLdouble n
Definition glcorearb.h:1982
GLuint GLuint end
Definition glcorearb.h:469
const GLdouble * v
Definition glcorearb.h:832
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLuint GLfloat * val
Definition glcorearb.h:1582
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLint GLuint mask
Definition glcorearb.h:291
void check(const std::vector< std::string > &arguments, const std::vector< ConfigParamSpec > &workflowOptions, const std::vector< DeviceSpec > &deviceSpecs, CheckMatrix &matrix)
int nofBits(T val)
Definition NofBits.h:23
int circularAppend(BitSet &bs, const BitSet &ringBuffer, int startBit, int n)
Definition BitSet.cxx:421
SampaHeader sampaSync()
The 50-bits Sampa SYNC word.
std::string compactString(const BitSet &bs)
Definition BitSet.cxx:440
Enum< T >::Iterator begin(Enum< T >)
Definition Defs.h:173
std::ostream & operator<<(std::ostream &stream, o2::InteractionRecord const &ir)
uint64_t const void const *restrict const msg
Definition x9.h:153