mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
				synced 2025-10-30 19:53:35 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			371 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			371 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| * Copyright 2008, 2009 Free Software Foundation, Inc.
 | |
| *
 | |
| * SPDX-License-Identifier: AGPL-3.0+
 | |
| *
 | |
| * This software is distributed under the terms of the GNU Affero Public License.
 | |
| * See the COPYING file in the main directory for details.
 | |
| *
 | |
| * This use of this software may be subject to additional restrictions.
 | |
| * See the LEGAL file in the main directory for details.
 | |
| 
 | |
| 	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 <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| */
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #include "BitVector.h"
 | |
| #include <iostream>
 | |
| #include <stdio.h>
 | |
| #include <sstream>
 | |
| #include <math.h>
 | |
| 
 | |
| using namespace std;
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Apply a Galois polymonial to a binary sequence.
 | |
|   @param val The input sequence.
 | |
|   @param poly The polynomial.
 | |
|   @param order The order of the polynomial.
 | |
|   @return Single-bit result.
 | |
| */
 | |
| unsigned applyPoly(uint64_t val, uint64_t poly, unsigned order)
 | |
| {
 | |
| 	uint64_t prod = val & poly;
 | |
| 	unsigned sum = prod;
 | |
| 	for (unsigned i=1; i<order; i++) sum ^= prod>>i;
 | |
| 	return sum & 0x01;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| BitVector::BitVector(const char *valString)
 | |
| 	:Vector<char>(strlen(valString))
 | |
| {
 | |
| 	uint32_t accum = 0;
 | |
| 	for (size_t i=0; i<size(); i++) {
 | |
| 		accum <<= 1;
 | |
| 		if (valString[i]=='1') accum |= 0x01;
 | |
| 		mStart[i] = accum;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| uint64_t BitVector::peekField(size_t readIndex, unsigned length) const
 | |
| {
 | |
| 	uint64_t accum = 0;
 | |
| 	char *dp = mStart + readIndex;
 | |
| 	assert(dp+length <= mEnd);
 | |
| 	for (unsigned i=0; i<length; i++) {
 | |
| 		accum = (accum<<1) | ((*dp++) & 0x01);
 | |
| 	}
 | |
| 	return accum;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| uint64_t BitVector::peekFieldReversed(size_t readIndex, unsigned length) const
 | |
| {
 | |
| 	uint64_t accum = 0;
 | |
| 	char *dp = mStart + readIndex + length - 1;
 | |
| 	assert(dp<mEnd);
 | |
| 	for (int i=(length-1); 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)
 | |
| {
 | |
| 	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)
 | |
| {
 | |
| 	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)
 | |
| {
 | |
| 	fillField(writeIndex,value,length);
 | |
| 	writeIndex += length;
 | |
| }
 | |
| 
 | |
| 
 | |
| void BitVector::writeFieldReversed(size_t& writeIndex, uint64_t value, unsigned length)
 | |
| {
 | |
| 	fillFieldReversed(writeIndex,value,length);
 | |
| 	writeIndex += length;
 | |
| }
 | |
| 
 | |
| 
 | |
| void BitVector::invert()
 | |
| {
 | |
| 	for (size_t i=0; i<size(); i++) {
 | |
| 		mStart[i] = ~mStart[i];
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| void BitVector::reverse8()
 | |
| {
 | |
| 	assert(size()>=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();
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| unsigned BitVector::sum() const
 | |
| {
 | |
| 	unsigned sum = 0;
 | |
| 	for (size_t i=0; i<size(); i++) sum += mStart[i] & 0x01;
 | |
| 	return sum;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| void BitVector::map(const unsigned *map, size_t mapSize, BitVector& dest) const
 | |
| {
 | |
| 	for (unsigned i=0; i<mapSize; i++) {
 | |
| 		dest.mStart[i] = mStart[map[i]];
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| void BitVector::unmap(const unsigned *map, size_t mapSize, BitVector& dest) const
 | |
| {
 | |
| 	for (unsigned i=0; i<mapSize; i++) {
 | |
| 		dest.mStart[map[i]] = mStart[i];
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| ostream& operator<<(ostream& os, const BitVector& hv)
 | |
| {
 | |
| 	for (size_t i=0; i<hv.size(); i++) {
 | |
| 		if (hv.bit(i)) os << '1';
 | |
| 		else os << '0';
 | |
| 	}
 | |
| 	return os;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| SoftVector::SoftVector(const BitVector& source)
 | |
| {
 | |
| 	resize(source.size());
 | |
| 	for (size_t i=0; i<size(); i++) {
 | |
| 		if (source.bit(i)) mStart[i]=1.0F;
 | |
| 		else mStart[i]=-1.0F;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| BitVector SoftVector::sliced() const
 | |
| {
 | |
| 	size_t sz = size();
 | |
| 	BitVector newSig(sz);
 | |
| 	for (size_t i=0; i<sz; i++) {
 | |
| 		if (mStart[i]>0.0F) newSig[i]=1;
 | |
| 		else newSig[i] = 0;
 | |
| 	}
 | |
| 	return newSig;
 | |
| }
 | |
| 
 | |
| 
 | |
| 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 energy = fabsf(vec[i]);
 | |
| 		if (energy < low) low = energy;
 | |
| 		avg += energy/len;
 | |
| 	}
 | |
| 	if (plow) { *plow = low; }
 | |
| 	return avg;
 | |
| }
 | |
| 
 | |
| 
 | |
| ostream& operator<<(ostream& os, const SoftVector& sv)
 | |
| {
 | |
| 	for (size_t i=0; i<sv.size(); i++) {
 | |
| 		if (sv[i]<-0.5) os << "0";
 | |
| 		else if (sv[i]<-0.25) os << "o";
 | |
| 		else if (sv[i]<0.0) os << ".";
 | |
| 		else if (sv[i]>0.5) os << "1";
 | |
| 		else if (sv[i]>0.25) os << "|";
 | |
| 		else if (sv[i]>0.0) os << "'";
 | |
| 		else os << "-";
 | |
| 	}
 | |
| 	return os;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void BitVector::pack(unsigned char* targ) const
 | |
| {
 | |
| 	// Assumes MSB-first packing.
 | |
| 	unsigned bytes = size()/8;
 | |
| 	for (unsigned i=0; i<bytes; i++) {
 | |
| 		targ[i] = peekField(i*8,8);
 | |
| 	}
 | |
| 	unsigned whole = bytes*8;
 | |
| 	unsigned rem = size() - whole;
 | |
| 	if (rem==0) return;
 | |
| 	targ[bytes] = peekField(whole,rem) << (8-rem);
 | |
| }
 | |
| 
 | |
| 
 | |
| void BitVector::unpack(const unsigned char* src)
 | |
| {
 | |
| 	// Assumes MSB-first packing.
 | |
| 	unsigned bytes = size()/8;
 | |
| 	for (unsigned i=0; i<bytes; i++) {
 | |
| 		fillField(i*8,src[i],8);
 | |
| 	}
 | |
| 	unsigned whole = bytes*8;
 | |
| 	unsigned rem = size() - whole;
 | |
| 	if (rem==0) return;
 | |
|         fillField(whole,src[bytes] >> (8-rem),rem);
 | |
| }
 | |
| 
 | |
| void BitVector::hex(ostream& os) const
 | |
| {
 | |
| 	os << std::hex;
 | |
| 	unsigned digits = size()/4;
 | |
| 	size_t wp=0;
 | |
| 	for (unsigned i=0; i<digits; i++) {
 | |
| 		os << readField(wp,4);
 | |
| 	}
 | |
| 	os << std::dec;
 | |
| }
 | |
| 
 | |
| std::string BitVector::hexstr() const
 | |
| {
 | |
| 	std::ostringstream ss;
 | |
| 	hex(ss);
 | |
| 	return ss.str();
 | |
| }
 | |
| 
 | |
| 
 | |
| bool BitVector::unhex(const char* src)
 | |
| {
 | |
| 	// Assumes MSB-first packing.
 | |
| 	unsigned int val;
 | |
| 	unsigned digits = size()/4;
 | |
| 	for (unsigned i=0; i<digits; i++) {
 | |
| 		if (sscanf(src+i, "%1x", &val) < 1) {
 | |
| 			return false;
 | |
| 		}
 | |
| 		fillField(i*4,val,4);
 | |
| 	}
 | |
| 	unsigned whole = digits*4;
 | |
| 	unsigned rem = size() - whole;
 | |
| 	if (rem>0) {
 | |
| 		if (sscanf(src+digits, "%1x", &val) < 1) {
 | |
| 			return false;
 | |
| 		}
 | |
| 		fillField(whole,val,rem);
 | |
| 	}
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| // vim: ts=4 sw=4
 |