/* * Copyright 2008, 2009, 2014 Free Software Foundation, Inc. * Copyright 2014 Range Networks, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. */ #include "BitVector.h" #include #include #include #include //#include using namespace std; BitVector::BitVector(const char *valString) { // 1-30-2013 pat: I dont know what this was intended to do, but it did not create a normalized BitVector, // and it could even fail if the accum overlows 8 bits. //uint32_t accum = 0; //for (size_t i=0; i=0; i--) { accum = (accum<<1) | ((*dp--) & 0x01); } return accum; } uint64_t BitVector::readField(size_t& readIndex, unsigned length) const { const uint64_t retVal = peekField(readIndex,length); readIndex += length; return retVal; } uint64_t BitVector::readFieldReversed(size_t& readIndex, unsigned length) const { const uint64_t retVal = peekFieldReversed(readIndex,length); readIndex += length; return retVal; } void BitVector::fillField(size_t writeIndex, uint64_t value, unsigned length) { if (length != 0) { char *dpBase = mStart + writeIndex; char *dp = dpBase + length - 1; assert(dp < mEnd); while (dp>=dpBase) { *dp-- = value & 0x01; value >>= 1; } } } void BitVector::fillFieldReversed(size_t writeIndex, uint64_t value, unsigned length) { if (length != 0) { char *dp = mStart + writeIndex; char *dpEnd = dp + length - 1; assert(dpEnd < mEnd); while (dp<=dpEnd) { *dp++ = value & 0x01; value >>= 1; } } } void BitVector::writeField(size_t& writeIndex, uint64_t value, unsigned length) { if (length != 0) { fillField(writeIndex,value,length); writeIndex += length; } } void BitVector::writeFieldReversed(size_t& writeIndex, uint64_t value, unsigned length) { if (length != 0) { fillFieldReversed(writeIndex,value,length); writeIndex += length; } } void BitVector::invert() { for (size_t i=0; i=8); char tmp0 = mStart[0]; mStart[0] = mStart[7]; mStart[7] = tmp0; char tmp1 = mStart[1]; mStart[1] = mStart[6]; mStart[6] = tmp1; char tmp2 = mStart[2]; mStart[2] = mStart[5]; mStart[5] = tmp2; char tmp3 = mStart[3]; mStart[3] = mStart[4]; mStart[4] = tmp3; } void BitVector::LSB8MSB() { if (size()<8) return; size_t size8 = 8*(size()/8); size_t iTop = size8 - 8; for (size_t i=0; i<=iTop; i+=8) segment(i,8).reverse8(); } uint64_t BitVector::syndrome(Generator& gen) const { gen.clear(); const char *dp = mStart; while (dp0.5F) newSig[i]=1; else newSig[i] = 0; } return newSig; } // (pat) Added 6-22-2012 float SoftVector::getEnergy(float *plow) const { const SoftVector &vec = *this; int len = vec.size(); float avg = 0; float low = 1; for (int i = 0; i < len; i++) { float bit = vec[i]; float energy = 2*((bit < 0.5) ? (0.5-bit) : (bit-0.5)); if (energy < low) low = energy; avg += energy/len; } if (plow) { *plow = low; } return avg; } // (pat) Added 1-2014. Compute SNR of a soft vector. Very similar to above. // Since we dont really know what the expected signal values are, we will assume that the signal is 0 or 1 // and return the SNR on that basis. // SNR is power(signal) / power(noise) where power can be calculated as (RMS(signal) / RMS(noise))**2 of the values. // Since RMS is square-rooted, ie RMS = sqrt(1/n * (x1**2 + x2**2 ...)), we just add up the squares. // To compute RMS of the signal we will remove any constant offset, so the signal values are either 0.5 or -0.5, // so the RMS of the signal is just 0.5**2 * len; all we need to compute is the noise component. float SoftVector::getSNR() const { float sumSquaresNoise = 0; const SoftVector &vec = *this; int len = vec.size(); if (len == 0) { return 0.0; } for (int i = 0; i < len; i++) { float bit = vec[i]; if (bit < 0.5) { // Assume signal is 0. sumSquaresNoise += (bit - 0.0) * (bit - 0.0); } else { // Assume signal is 1. sumSquaresNoise += (bit - 1.0) * (bit - 1.0); } } float sumSquaresSignal = 0.5 * 0.5 * len; // I really want log10 of this to convert to dB, but log is expensive, and Harvind seems to like absolute SNR. // Clamp max to 999; it shouldnt get up there but be sure. This also avoids divide by zero. if (sumSquaresNoise * 1000 < sumSquaresSignal) return 999; return sumSquaresSignal / sumSquaresNoise; } ostream& operator<<(ostream& os, const SoftVector& sv) { for (size_t i=0; i0.75) os << "1"; else os << "-"; } return os; } void BitVector::pack(unsigned char* targ) const { // Assumes MSB-first packing. unsigned bytes = size()/8; for (unsigned i=0; ipack(result.c_str()) but technically c_str() is read-only. unsigned bytes = size()/8; for (unsigned i=0; i> (8-rem),rem); } void BitVector::hex(ostream& os) const { os << std::hex; unsigned digits = size()/4; size_t wp=0; for (unsigned i=0; i0) { if (sscanf(src+digits, "%1x", &val) < 1) { return false; } fillField(whole,val,rem); } return true; } bool BitVector::operator==(const BitVector &other) const { unsigned l = size(); return l == other.size() && 0==memcmp(begin(),other.begin(),l); } void BitVector::copyPunctured(BitVector &dst, const unsigned *puncture, const size_t plth) { assert(size() - plth == dst.size()); char *srcp = mStart; char *dstp = dst.mStart; const unsigned *pend = puncture + plth; while (srcp < mEnd) { if (puncture < pend) { int n = (*puncture++) - (srcp - mStart); assert(n >= 0); for (int i = 0; i < n; i++) { assert(srcp < mEnd && dstp < dst.mEnd); *dstp++ = *srcp++; } srcp++; } else { while (srcp < mEnd) { assert(dstp < dst.mEnd); *dstp++ = *srcp++; } } } assert(dstp == dst.mEnd && puncture == pend); } void SoftVector::copyUnPunctured(SoftVector &dst, const unsigned *puncture, const size_t plth) { assert(size() + plth == dst.size()); float *srcp = mStart; float *dstp = dst.mStart; const unsigned *pend = puncture + plth; while (dstp < dst.mEnd) { if (puncture < pend) { int n = (*puncture++) - (dstp - dst.mStart); assert(n >= 0); for (int i = 0; i < n; i++) { assert(srcp < mEnd && dstp < dst.mEnd); *dstp++ = *srcp++; } *dstp++ = 0.5; } else { while (srcp < mEnd) { assert(dstp < dst.mEnd); *dstp++ = *srcp++; } } } assert(dstp == dst.mEnd && puncture == pend); } // vim: ts=4 sw=4