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