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
179{
180 return appendT<uint8_t>(*this, val, n);
181}
182
184{
185 return appendT<uint16_t>(*this, val, n);
186}
187
189{
190 return appendT<uint32_t>(*this, val, n);
191}
192
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
338{
339 setRangeFromIntegerFast<uint8_t>(*this, a, b, v);
340}
341
343{
344 setRangeFromIntegerFast<uint16_t>(*this, a, b, v);
345}
346
348{
349 setRangeFromIntegerFast<uint32_t>(*this, a, b, v);
350}
351
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
unsigned short int uint16_t
int32_t i
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
uint16_t pos
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
size_t bytes
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:158
std::ostream & operator<<(std::ostream &stream, o2::InteractionRecord const &ir)
uint64_t const void const *restrict const msg
Definition x9.h:153