Bitset.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ALVAR, A Library for Virtual and Augmented Reality.
3  *
4  * Copyright 2007-2012 VTT Technical Research Centre of Finland
5  *
6  * Contact: VTT Augmented Reality Team <alvar.info@vtt.fi>
7  * <http://www.vtt.fi/multimedia/alvar.html>
8  *
9  * ALVAR is free software; you can redistribute it and/or modify it under the
10  * terms of the GNU Lesser General Public License as published by the Free
11  * Software Foundation; either version 2.1 of the License, or (at your option)
12  * any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
17  * for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with ALVAR; if not, see
21  * <http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>.
22  */
23 
24 #include "ar_track_alvar/Bitset.h"
25 
26 using namespace std;
27 
28 namespace alvar {
29 using namespace std;
30 
31 int Bitset::Length() {
32  return bits.size();
33 }
34 ostream &Bitset::Output(ostream &os) const {
35  deque<bool>::const_iterator iter=bits.begin();
36  while (iter != bits.end()) {
37  if (*iter) os<<"1";
38  else os<<"0";
39  iter++;
40  }
41  return os;
42 }
43 void Bitset::clear() { bits.clear(); }
44 void Bitset::push_back(const bool bit) { bits.push_back(bit); }
45 void Bitset::push_back(const unsigned char b, int bit_count /*=8*/) {
46  push_back((const unsigned long)b, bit_count);
47 }
48 void Bitset::push_back(const unsigned short s, int bit_count /*=16*/) {
49  push_back((const unsigned long)s, bit_count);
50 }
51 void Bitset::push_back(const unsigned long l, int bit_count /*=32*/) {
52  unsigned long mask;
53  if ((bit_count > 32) || (bit_count == 0)) bit_count=32;
54  mask = 0x01<<(bit_count-1);
55  for (int i=0; i<bit_count; i++) {
56  if (l & mask) push_back(true);
57  else push_back(false);
58  mask>>=1;
59  }
60 }
61 void Bitset::push_back_meaningful(const unsigned long l) {
62  int bit_count = 1;
63  for (int i=0; i<32; i++) {
64  unsigned long mask = 0x01<<i;
65  if (l & mask) bit_count = i+1;
66  }
67  push_back(l, bit_count);
68 }
69 void Bitset::fill_zeros_left(size_t bit_count) {
70  while (bits.size() < bit_count) {
71  bits.push_front(false);
72  }
73 }
74 
75 void Bitset::push_back(string s) {
76  string::const_iterator iter = s.begin();
77  while (iter != s.end()) {
78  unsigned char c = *iter;
79  push_back(c);
80  iter++;
81  }
82 }
83 bool Bitset::pop_front()
84 {
85  bool ret = bits.front();
86  bits.pop_front();
87  return ret;
88 }
89 bool Bitset::pop_back()
90 {
91  bool ret = bits.back();
92  bits.pop_back();
93  return ret;
94 }
95 
96 void Bitset::flip(size_t pos) {
97  bits[pos] = !bits[pos];
98 }
99 
100 string Bitset::hex()
101 {
102  stringstream ss;
103  ss.unsetf(std::ios_base::dec);
104  ss.setf(std::ios_base::hex);
105  unsigned long b=0;
106  int bitpos = (0x08 << (bits.size() % 4));
107  if (bitpos > 0x08) bitpos >>= 4;
108  for (size_t i=0; i < bits.size(); i++) {
109  if (bits[i]) b = b | bitpos;
110  else b = b & (0x0f ^ bitpos);
111  bitpos >>= 1;
112  if (bitpos == 0x00) {
113  bitpos = 0x08;
114  ss << b;
115  }
116  }
117  return ss.str();
118 }
119 
120 unsigned long Bitset::ulong()
121 {
122  //if(bits.size() > (sizeof(unsigned long)*8))
123  // throw "code too big for unsigned long\n";
124  stringstream ss;
125  ss << setbase(16) << hex();
126  unsigned long v;
127  ss >> v;
128  return v;
129 }
130 
131 unsigned char Bitset::uchar()
132 {
133  //if(bits.size() > (sizeof(unsigned char)*8))
134  // throw "code too big for unsigned char\n";
135  stringstream ss;
136  ss << setbase(16) << hex();
137  unsigned long v; //ttehop: Note, that this cannot be char
138  ss >> v;
139  return (unsigned char)v;
140 }
141 
142 void BitsetExt::hamming_enc_block(unsigned long block_len, deque<bool>::iterator &iter) {
143  if (verbose) cout<<"hamming_enc_block: ";
144  unsigned long next_parity=1;
145  for (unsigned long i=1; i<=block_len; i++) {
146  // Add a parity bit if this a place for such
147  if (i == next_parity) {
148  if (verbose) cout<<"p";
149  next_parity <<= 1;
150  iter = bits.insert(iter, false);
151  }
152  // Otherwise if this bit is 1 change all related parity bits
153  else {
154  if (iter == bits.end()) {
155  block_len = i-1;
156  break;
157  }
158  if (verbose) cout<<(*iter?1:0);
159  if (*iter) {
160  unsigned long parity = next_parity>>1;
161  while (parity) {
162  if (i & parity) {
163  deque<bool>::iterator parity_iter=(iter - (i - parity));
164  *parity_iter = !*parity_iter;
165  }
166  parity >>= 1;
167  }
168  }
169  }
170  iter++;
171  }
172  // Update the last parity bit if we have one
173  // Note, that the last parity bit can safely be removed from the code if it is not desired...
174  if (block_len == (next_parity >> 1)) {
175  // If the last bit is parity bit - make parity over the previous data
176  for (unsigned long ii=1; ii<block_len; ii++) {
177  if (*(iter-ii-1)) *(iter-1) = !*(iter-1);
178  }
179  }
180  if (verbose) {
181  cout<<" -> ";
182  for (unsigned long ii=block_len; ii>=1; ii--) {
183  cout<<(*(iter-ii)?1:0);
184  }
185  cout<<" block_len: "<<block_len<<endl;
186  }
187 }
188 int BitsetExt::hamming_dec_block(unsigned long block_len, deque<bool>::iterator &iter) {
189  if (verbose) cout<<"hamming_dec_block: ";
190  bool potentially_double_error = false;
191  unsigned long total_parity=0;
192  unsigned long parity=0;
193  unsigned long next_parity=1;
194  for (unsigned long i=1; i<=block_len; i++) {
195  if (iter == bits.end()) {
196  // ttehop:
197  // At 3.12.2009 I changed the following line because
198  // it crashed with 7x7 markers. However, I didn't fully
199  // understand the reason why it should be so. Lets
200  // give more thought to it when we have more time.
201  // old version: block_len = i-1;
202  block_len = i;
203  break;
204  }
205  if (*iter) {
206  parity = parity ^ i;
207  total_parity = total_parity ^ 1;
208  }
209  if (i == next_parity) {
210  if (verbose) cout<<"("<<*iter<<")";
211  next_parity <<= 1;
212  iter = bits.erase(iter);
213  } else {
214  if (verbose) cout<<*iter;
215  iter++;
216  }
217  }
218  if (block_len < 3) {
219  if (verbose) cout<<" too short"<<endl;
220  return 0;
221  }
222  if (block_len == (next_parity >> 1)) {
223  parity = parity & ~(next_parity >> 1); // The last parity bit shouldn't be included in the other parity tests (TODO: Better solution)
224  if (total_parity == 0) {
225  potentially_double_error = true;
226  }
227  }
228  int steps=0;
229  if (verbose) cout<<" parity: "<<parity;
230  if (parity) {
231  if (potentially_double_error) {
232  if (verbose) cout<<" double error"<<endl;
233  return -1;
234  }
235  next_parity = 1;
236  for (unsigned long i=1; i<=block_len; i++) {
237  if (i == next_parity) {
238  next_parity <<= 1;
239  if (i == parity) {
240  if (verbose) cout<<" parity bit error"<<endl;
241  return 1; // Only parity bit was erroneous
242  }
243  } else if (i >= parity) {
244  steps++;
245  }
246  }
247  iter[-steps] = !iter[-steps];
248  if (verbose) cout<<" corrected"<<endl;
249  return 1;
250  }
251  if (verbose) cout<<" ok"<<endl;
252  return 0;
253 }
254 BitsetExt::BitsetExt() {
255  SetVerbose(false);
256 }
257 BitsetExt::BitsetExt(bool _verbose) {
258  SetVerbose(_verbose);
259 }
260 /*
261 void BitsetExt::str_8to6bit() {
262  // TODO: Assume that the bitset contains 8-bit ASCII chars and change them into 6-bit chars
263 }
264 void BitsetExt::str_6to8bit() {
265  // TODO: Assume that the bitset contains 6-bit chars and change them into 8-bit ASCII chars
266 }
267 void BitsetExt::crc_enc(int crc_len) {
268  // TODO: Add crc_len-bit checksum for the bitset
269 }
270 bool BitsetExt::crc_dec(int crc_len) {
271  // TODO: Check the CRC
272  return false;
273 }
274 */
275 void BitsetExt::SetVerbose(bool _verbose) {
276  verbose = _verbose;
277 }
278 int BitsetExt::count_hamming_enc_len(int block_len, int dec_len) {
279  int parity_len=0;
280  int dec_len_count = dec_len;
281  while (dec_len_count > 0) {
282  unsigned long next_parity = 1;
283  for (unsigned long i=1; i<=(unsigned long)block_len; i++) {
284  if (i == next_parity) {
285  parity_len++;
286  next_parity <<= 1;
287  } else {
288  dec_len_count--;
289  }
290  if (dec_len_count == 0) break;
291  }
292  }
293  return dec_len + parity_len;
294 }
295 int BitsetExt::count_hamming_dec_len(int block_len, int enc_len) {
296  int parity_len=0;
297  int enc_len_count = enc_len;
298  while (enc_len_count > 0) {
299  unsigned long next_parity = 1;
300  unsigned long i;
301  for (i=1; i<=(unsigned long)block_len; i++) {
302  if (i == next_parity) {
303  parity_len++;
304  next_parity <<= 1;
305  }
306  enc_len_count--;
307  if (enc_len_count == 0) break;
308  }
309  }
310  return enc_len - parity_len;
311 }
312 void BitsetExt::hamming_enc(int block_len) {
313  deque<bool>::iterator iter=bits.begin();
314  while (iter != bits.end()) {
315  hamming_enc_block(block_len, iter);
316  }
317 }
318 // Returns number of corrected errors (or -1 if there were unrecoverable error)
319 int BitsetExt::hamming_dec(int block_len) {
320  int error_count=0;
321  deque<bool>::iterator iter=bits.begin();
322  while (iter != bits.end()) {
323  int error=hamming_dec_block(block_len, iter);
324  if ((error == -1) || (error_count == -1)) error_count=-1;
325  else error_count += error;
326  }
327  return error_count;
328 }
329 
330 } // namespace alvar
Main ALVAR namespace.
Definition: Alvar.h:174
This file implements bit set handling.
XmlRpcServer s


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Mon Jun 10 2019 12:47:03