blob: 00730f662797b5e41c0592404aaaa24acb0f13c5 [file] [log] [blame]
Roman Khassraf059bab92015-05-20 12:49:46 +02001/*
Piotr Krysikb9a87a12017-08-23 15:59:28 +02002 * Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
3 * Copyright 2014 Range Networks, Inc.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * This use of this software may be subject to additional restrictions.
19 * See the LEGAL file in the main directory for details.
20 */
Roman Khassraf059bab92015-05-20 12:49:46 +020021
22#include "BitVector.h"
23#include <iostream>
Roman Khassrafd71e6582015-06-02 08:49:12 +020024#include <stdio.h>
25#include <sstream>
26#include <string.h>
27//#include <Logger.h>
Roman Khassraf059bab92015-05-20 12:49:46 +020028
29using namespace std;
30
31
Roman Khassraf059bab92015-05-20 12:49:46 +020032
33BitVector::BitVector(const char *valString)
Roman Khassraf059bab92015-05-20 12:49:46 +020034{
Roman Khassrafd71e6582015-06-02 08:49:12 +020035 // 1-30-2013 pat: I dont know what this was intended to do, but it did not create a normalized BitVector,
36 // and it could even fail if the accum overlows 8 bits.
37 //uint32_t accum = 0;
38 //for (size_t i=0; i<size(); i++) {
39 // accum <<= 1;
40 // if (valString[i]=='1') accum |= 0x01;
41 // mStart[i] = accum;
42 //}
43 vInit(strlen(valString));
44 char *rp = begin();
45 for (const char *cp = valString; *cp; cp++, rp++) {
46 *rp = (*cp == '1');
Roman Khassraf059bab92015-05-20 12:49:46 +020047 }
48}
49
50
Roman Khassraf059bab92015-05-20 12:49:46 +020051uint64_t BitVector::peekField(size_t readIndex, unsigned length) const
52{
53 uint64_t accum = 0;
54 char *dp = mStart + readIndex;
Roman Khassrafd71e6582015-06-02 08:49:12 +020055
Roman Khassraf059bab92015-05-20 12:49:46 +020056 for (unsigned i=0; i<length; i++) {
57 accum = (accum<<1) | ((*dp++) & 0x01);
58 }
59 return accum;
60}
61
62
Roman Khassrafd71e6582015-06-02 08:49:12 +020063
64
65uint64_t BitVector::peekFieldReversed(size_t readIndex, unsigned length) const
66{
67 uint64_t accum = 0;
68 char *dp = mStart + readIndex + length - 1;
69 assert(dp<mEnd);
70 for (int i=(length-1); i>=0; i--) {
71 accum = (accum<<1) | ((*dp--) & 0x01);
72 }
73 return accum;
74}
75
76
77
78
Roman Khassraf059bab92015-05-20 12:49:46 +020079uint64_t BitVector::readField(size_t& readIndex, unsigned length) const
80{
81 const uint64_t retVal = peekField(readIndex,length);
82 readIndex += length;
83 return retVal;
84}
85
86
Roman Khassrafd71e6582015-06-02 08:49:12 +020087uint64_t BitVector::readFieldReversed(size_t& readIndex, unsigned length) const
88{
89
90 const uint64_t retVal = peekFieldReversed(readIndex,length);
91 readIndex += length;
92 return retVal;
93
94}
95
96
97
98
Roman Khassraf059bab92015-05-20 12:49:46 +020099void BitVector::fillField(size_t writeIndex, uint64_t value, unsigned length)
100{
Roman Khassrafd71e6582015-06-02 08:49:12 +0200101 if (length != 0) {
102 char *dpBase = mStart + writeIndex;
103 char *dp = dpBase + length - 1;
104 assert(dp < mEnd);
105 while (dp>=dpBase) {
106 *dp-- = value & 0x01;
107 value >>= 1;
108 }
Roman Khassraf059bab92015-05-20 12:49:46 +0200109 }
110}
111
Roman Khassrafd71e6582015-06-02 08:49:12 +0200112
113void BitVector::fillFieldReversed(size_t writeIndex, uint64_t value, unsigned length)
114{
115 if (length != 0) {
116 char *dp = mStart + writeIndex;
117 char *dpEnd = dp + length - 1;
118 assert(dpEnd < mEnd);
119 while (dp<=dpEnd) {
120 *dp++ = value & 0x01;
121 value >>= 1;
122 }
123 }
124}
125
126
127
128
Roman Khassraf059bab92015-05-20 12:49:46 +0200129void BitVector::writeField(size_t& writeIndex, uint64_t value, unsigned length)
130{
Roman Khassrafd71e6582015-06-02 08:49:12 +0200131 if (length != 0) {
132 fillField(writeIndex,value,length);
133 writeIndex += length;
134 }
135}
136
137
138void BitVector::writeFieldReversed(size_t& writeIndex, uint64_t value, unsigned length)
139{
140 if (length != 0) {
141 fillFieldReversed(writeIndex,value,length);
142 writeIndex += length;
143 }
Roman Khassraf059bab92015-05-20 12:49:46 +0200144}
145
146
147void BitVector::invert()
148{
149 for (size_t i=0; i<size(); i++) {
150 mStart[i] = ~mStart[i];
151 }
152}
153
154
155
156
157void BitVector::reverse8()
158{
159 assert(size()>=8);
160
161 char tmp0 = mStart[0];
162 mStart[0] = mStart[7];
163 mStart[7] = tmp0;
164
165 char tmp1 = mStart[1];
166 mStart[1] = mStart[6];
167 mStart[6] = tmp1;
168
169 char tmp2 = mStart[2];
170 mStart[2] = mStart[5];
171 mStart[5] = tmp2;
172
173 char tmp3 = mStart[3];
174 mStart[3] = mStart[4];
175 mStart[4] = tmp3;
176}
177
178
179
180void BitVector::LSB8MSB()
181{
Roman Khassrafd71e6582015-06-02 08:49:12 +0200182 if (size()<8) return;
Roman Khassraf059bab92015-05-20 12:49:46 +0200183 size_t size8 = 8*(size()/8);
184 size_t iTop = size8 - 8;
185 for (size_t i=0; i<=iTop; i+=8) segment(i,8).reverse8();
186}
187
188
189
190uint64_t BitVector::syndrome(Generator& gen) const
191{
192 gen.clear();
193 const char *dp = mStart;
194 while (dp<mEnd) gen.syndromeShift(*dp++);
195 return gen.state();
196}
197
198
199uint64_t BitVector::parity(Generator& gen) const
200{
201 gen.clear();
202 const char *dp = mStart;
203 while (dp<mEnd) gen.encoderShift(*dp++);
204 return gen.state();
205}
206
207
Roman Khassraf059bab92015-05-20 12:49:46 +0200208unsigned BitVector::sum() const
209{
210 unsigned sum = 0;
211 for (size_t i=0; i<size(); i++) sum += mStart[i] & 0x01;
212 return sum;
213}
214
215
216
217
218void BitVector::map(const unsigned *map, size_t mapSize, BitVector& dest) const
219{
220 for (unsigned i=0; i<mapSize; i++) {
221 dest.mStart[i] = mStart[map[i]];
222 }
223}
224
225
226
227
228void BitVector::unmap(const unsigned *map, size_t mapSize, BitVector& dest) const
229{
230 for (unsigned i=0; i<mapSize; i++) {
231 dest.mStart[map[i]] = mStart[i];
232 }
233}
234
235
236
237
238
239
240
Roman Khassraf059bab92015-05-20 12:49:46 +0200241ostream& operator<<(ostream& os, const BitVector& hv)
242{
243 for (size_t i=0; i<hv.size(); i++) {
244 if (hv.bit(i)) os << '1';
245 else os << '0';
246 }
247 return os;
248}
249
250
251
252
Roman Khassraf059bab92015-05-20 12:49:46 +0200253uint64_t Parity::syndrome(const BitVector& receivedCodeword)
254{
255 return receivedCodeword.syndrome(*this);
256}
257
258
259void Parity::writeParityWord(const BitVector& data, BitVector& parityTarget, bool invert)
260{
261 uint64_t pWord = data.parity(*this);
Roman Khassrafd71e6582015-06-02 08:49:12 +0200262 if (invert) pWord = ~pWord;
Roman Khassraf059bab92015-05-20 12:49:46 +0200263 parityTarget.fillField(0,pWord,size());
264}
265
266
267
268
269
270
271
272
273
274SoftVector::SoftVector(const BitVector& source)
275{
276 resize(source.size());
277 for (size_t i=0; i<size(); i++) {
278 if (source.bit(i)) mStart[i]=1.0F;
279 else mStart[i]=0.0F;
280 }
281}
282
283
284BitVector SoftVector::sliced() const
285{
286 size_t sz = size();
287 BitVector newSig(sz);
288 for (size_t i=0; i<sz; i++) {
289 if (mStart[i]>0.5F) newSig[i]=1;
290 else newSig[i] = 0;
291 }
292 return newSig;
293}
294
295
296
Roman Khassrafd71e6582015-06-02 08:49:12 +0200297// (pat) Added 6-22-2012
298float SoftVector::getEnergy(float *plow) const
Roman Khassraf059bab92015-05-20 12:49:46 +0200299{
Roman Khassrafd71e6582015-06-02 08:49:12 +0200300 const SoftVector &vec = *this;
301 int len = vec.size();
302 float avg = 0; float low = 1;
303 for (int i = 0; i < len; i++) {
304 float bit = vec[i];
305 float energy = 2*((bit < 0.5) ? (0.5-bit) : (bit-0.5));
306 if (energy < low) low = energy;
307 avg += energy/len;
Roman Khassraf059bab92015-05-20 12:49:46 +0200308 }
Roman Khassrafd71e6582015-06-02 08:49:12 +0200309 if (plow) { *plow = low; }
310 return avg;
Roman Khassraf059bab92015-05-20 12:49:46 +0200311}
312
Roman Khassrafd71e6582015-06-02 08:49:12 +0200313// (pat) Added 1-2014. Compute SNR of a soft vector. Very similar to above.
314// Since we dont really know what the expected signal values are, we will assume that the signal is 0 or 1
315// and return the SNR on that basis.
316// SNR is power(signal) / power(noise) where power can be calculated as (RMS(signal) / RMS(noise))**2 of the values.
317// Since RMS is square-rooted, ie RMS = sqrt(1/n * (x1**2 + x2**2 ...)), we just add up the squares.
318// To compute RMS of the signal we will remove any constant offset, so the signal values are either 0.5 or -0.5,
319// so the RMS of the signal is just 0.5**2 * len; all we need to compute is the noise component.
320float SoftVector::getSNR() const
321{
322 float sumSquaresNoise = 0;
323 const SoftVector &vec = *this;
324 int len = vec.size();
325 if (len == 0) { return 0.0; }
326 for (int i = 0; i < len; i++) {
327 float bit = vec[i];
328 if (bit < 0.5) {
329 // Assume signal is 0.
330 sumSquaresNoise += (bit - 0.0) * (bit - 0.0);
331 } else {
332 // Assume signal is 1.
333 sumSquaresNoise += (bit - 1.0) * (bit - 1.0);
334 }
335 }
336 float sumSquaresSignal = 0.5 * 0.5 * len;
337 // I really want log10 of this to convert to dB, but log is expensive, and Harvind seems to like absolute SNR.
338 // Clamp max to 999; it shouldnt get up there but be sure. This also avoids divide by zero.
339 if (sumSquaresNoise * 1000 < sumSquaresSignal) return 999;
340 return sumSquaresSignal / sumSquaresNoise;
341}
Roman Khassraf059bab92015-05-20 12:49:46 +0200342
343
344
345ostream& operator<<(ostream& os, const SoftVector& sv)
346{
347 for (size_t i=0; i<sv.size(); i++) {
348 if (sv[i]<0.25) os << "0";
349 else if (sv[i]>0.75) os << "1";
350 else os << "-";
351 }
352 return os;
353}
354
355
356
357void BitVector::pack(unsigned char* targ) const
358{
359 // Assumes MSB-first packing.
360 unsigned bytes = size()/8;
361 for (unsigned i=0; i<bytes; i++) {
362 targ[i] = peekField(i*8,8);
363 }
364 unsigned whole = bytes*8;
365 unsigned rem = size() - whole;
366 if (rem==0) return;
367 targ[bytes] = peekField(whole,rem) << (8-rem);
368}
369
Roman Khassrafd38206c2015-06-07 16:26:29 +0200370void BitVector::pack2(unsigned char* targ) const
371{
372 unsigned int i;
373 unsigned char curbyte = 0;
374
375 for (i = 0; i < size(); i++)
376 {
377 uint8_t bitnum = 7 - (i % 8);
378 curbyte |= ((char)bit(i) << bitnum);
379 if(i % 8 == 7){
380 *targ++ = curbyte;
381 curbyte = 0;
382 }
383 }
384
385 // Assumes MSB-first packing.
386// unsigned bytes = size()/8;
387// for (unsigned i=0; i<bytes; i++) {
388// targ[i] = peekField(i*8,8);
389// }
390// unsigned whole = bytes*8;
391// unsigned rem = size() - whole;
392// if (rem==0) return;
393// targ[bytes] = peekField(whole,rem) << (8-rem);
394}
395
396
397
Roman Khassrafd71e6582015-06-02 08:49:12 +0200398string BitVector::packToString() const
399{
400 string result;
401 result.reserve((size()+7)/8);
402 // Tempting to call this->pack(result.c_str()) but technically c_str() is read-only.
403 unsigned bytes = size()/8;
404 for (unsigned i=0; i<bytes; i++) {
405 result.push_back(peekField(i*8,8));
406 }
407 unsigned whole = bytes*8;
408 unsigned rem = size() - whole;
409 if (rem==0) return result;
410 result.push_back(peekField(whole,rem) << (8-rem));
411 return result;
412}
413
Roman Khassraf059bab92015-05-20 12:49:46 +0200414
415void BitVector::unpack(const unsigned char* src)
416{
417 // Assumes MSB-first packing.
418 unsigned bytes = size()/8;
419 for (unsigned i=0; i<bytes; i++) {
420 fillField(i*8,src[i],8);
421 }
422 unsigned whole = bytes*8;
423 unsigned rem = size() - whole;
424 if (rem==0) return;
Roman Khassrafd71e6582015-06-02 08:49:12 +0200425 fillField(whole,src[bytes] >> (8-rem),rem);
426}
427
428void BitVector::hex(ostream& os) const
429{
430 os << std::hex;
431 unsigned digits = size()/4;
432 size_t wp=0;
433 for (unsigned i=0; i<digits; i++) {
434 os << readField(wp,4);
435 }
436 os << std::dec;
437}
438
439std::string BitVector::hexstr() const
440{
441 std::ostringstream ss;
442 hex(ss);
443 return ss.str();
444}
445
446
447bool BitVector::unhex(const char* src)
448{
449 // Assumes MSB-first packing.
450 unsigned int val;
451 unsigned digits = size()/4;
452 for (unsigned i=0; i<digits; i++) {
453 if (sscanf(src+i, "%1x", &val) < 1) {
454 return false;
455 }
456 fillField(i*4,val,4);
457 }
458 unsigned whole = digits*4;
459 unsigned rem = size() - whole;
460 if (rem>0) {
461 if (sscanf(src+digits, "%1x", &val) < 1) {
462 return false;
463 }
464 fillField(whole,val,rem);
465 }
466 return true;
467}
468
469bool BitVector::operator==(const BitVector &other) const
470{
471 unsigned l = size();
472 return l == other.size() && 0==memcmp(begin(),other.begin(),l);
473}
474
475void BitVector::copyPunctured(BitVector &dst, const unsigned *puncture, const size_t plth)
476{
477 assert(size() - plth == dst.size());
478 char *srcp = mStart;
479 char *dstp = dst.mStart;
480 const unsigned *pend = puncture + plth;
481 while (srcp < mEnd) {
482 if (puncture < pend) {
483 int n = (*puncture++) - (srcp - mStart);
484 assert(n >= 0);
485 for (int i = 0; i < n; i++) {
486 assert(srcp < mEnd && dstp < dst.mEnd);
487 *dstp++ = *srcp++;
488 }
489 srcp++;
490 } else {
491 while (srcp < mEnd) {
492 assert(dstp < dst.mEnd);
493 *dstp++ = *srcp++;
494 }
495 }
496 }
497 assert(dstp == dst.mEnd && puncture == pend);
498}
499
500void SoftVector::copyUnPunctured(SoftVector &dst, const unsigned *puncture, const size_t plth)
501{
502 assert(size() + plth == dst.size());
503 float *srcp = mStart;
504 float *dstp = dst.mStart;
505 const unsigned *pend = puncture + plth;
506 while (dstp < dst.mEnd) {
507 if (puncture < pend) {
508 int n = (*puncture++) - (dstp - dst.mStart);
509 assert(n >= 0);
510 for (int i = 0; i < n; i++) {
511 assert(srcp < mEnd && dstp < dst.mEnd);
512 *dstp++ = *srcp++;
513 }
514 *dstp++ = 0.5;
515 } else {
516 while (srcp < mEnd) {
517 assert(dstp < dst.mEnd);
518 *dstp++ = *srcp++;
519 }
520 }
521 }
522 assert(dstp == dst.mEnd && puncture == pend);
Roman Khassraf059bab92015-05-20 12:49:46 +0200523}
524
525// vim: ts=4 sw=4