blob: d2acb5f17140b77bd94b49a250345d7cd548b35d [file] [log] [blame]
dburgess82c46ff2011-10-07 02:40:51 +00001/*
2* Copyright 2008, 2009 Free Software Foundation, Inc.
3*
4* This software is distributed under the terms of the GNU Affero Public License.
5* See the COPYING file in the main directory for details.
6*
7* This use of this software may be subject to additional restrictions.
8* See the LEGAL file in the main directory for details.
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Affero General Public License for more details.
19
20 You should have received a copy of the GNU Affero General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22
23*/
24
25
26#ifndef FECVECTORS_H
27#define FECVECTORS_H
28
29#include "Vector.h"
30#include <stdint.h>
31
32
33class BitVector;
34class SoftVector;
35
36
37
38/** Shift-register (LFSR) generator. */
39class Generator {
40
41 private:
42
43 uint64_t mCoeff; ///< polynomial coefficients. LSB is zero exponent.
44 uint64_t mState; ///< shift register state. LSB is most recent.
45 uint64_t mMask; ///< mask for reading state
46 unsigned mLen; ///< number of bits used in shift register
47 unsigned mLen_1; ///< mLen - 1
48
49 public:
50
51 Generator(uint64_t wCoeff, unsigned wLen)
52 :mCoeff(wCoeff),mState(0),
53 mMask((1ULL<<wLen)-1),
54 mLen(wLen),mLen_1(wLen-1)
55 { assert(wLen<64); }
56
57 void clear() { mState=0; }
58
59 /**@name Accessors */
60 //@{
61 uint64_t state() const { return mState & mMask; }
62 unsigned size() const { return mLen; }
63 //@}
64
65 /**
66 Calculate one bit of a syndrome.
67 This is in the .h for inlining.
68 */
69 void syndromeShift(unsigned inBit)
70 {
71 const unsigned fb = (mState>>(mLen_1)) & 0x01;
72 mState = (mState<<1) ^ (inBit & 0x01);
73 if (fb) mState ^= mCoeff;
74 }
75
76 /**
77 Update the generator state by one cycle.
78 This is in the .h for inlining.
79 */
80 void encoderShift(unsigned inBit)
81 {
82 const unsigned fb = ((mState>>(mLen_1)) ^ inBit) & 0x01;
83 mState <<= 1;
84 if (fb) mState ^= mCoeff;
85 }
86
87
88};
89
90
91
dburgess82c46ff2011-10-07 02:40:51 +000092class BitVector : public Vector<char> {
93
94
95 public:
96
97 /**@name Constructors. */
98 //@{
99
100 /**@name Casts of Vector constructors. */
101 //@{
102 BitVector(char* wData, char* wStart, char* wEnd)
103 :Vector<char>(wData,wStart,wEnd)
104 { }
105 BitVector(size_t len=0):Vector<char>(len) {}
106 BitVector(const Vector<char>& source):Vector<char>(source) {}
107 BitVector(Vector<char>& source):Vector<char>(source) {}
108 BitVector(const Vector<char>& source1, const Vector<char> source2):Vector<char>(source1,source2) {}
109 //@}
110
111 /** Construct from a string of "0" and "1". */
112 BitVector(const char* valString);
113 //@}
114
115 /** Index a single bit. */
116 bool bit(size_t index) const
117 {
118 // We put this code in .h for fast inlining.
119 const char *dp = mStart+index;
120 assert(dp<mEnd);
121 return (*dp) & 0x01;
122 }
123
124 /**@name Casts and overrides of Vector operators. */
125 //@{
126 BitVector segment(size_t start, size_t span)
127 {
128 char* wStart = mStart + start;
129 char* wEnd = wStart + span;
130 assert(wEnd<=mEnd);
131 return BitVector(NULL,wStart,wEnd);
132 }
133
134 BitVector alias()
135 { return segment(0,size()); }
136
137 const BitVector segment(size_t start, size_t span) const
138 { return (BitVector)(Vector<char>::segment(start,span)); }
139
140 BitVector head(size_t span) { return segment(0,span); }
141 const BitVector head(size_t span) const { return segment(0,span); }
142 BitVector tail(size_t start) { return segment(start,size()-start); }
143 const BitVector tail(size_t start) const { return segment(start,size()-start); }
144 //@}
145
146
147 void zero() { fill(0); }
148
149 /**@name FEC operations. */
150 //@{
151 /** Calculate the syndrome of the vector with the given Generator. */
152 uint64_t syndrome(Generator& gen) const;
153 /** Calculate the parity word for the vector with the given Generator. */
154 uint64_t parity(Generator& gen) const;
dburgess82c46ff2011-10-07 02:40:51 +0000155 //@}
156
157
158 /** Invert 0<->1. */
159 void invert();
160
161 /**@name Byte-wise operations. */
162 //@{
163 /** Reverse an 8-bit vector. */
164 void reverse8();
165 /** Reverse groups of 8 within the vector (byte reversal). */
166 void LSB8MSB();
167 //@}
168
169 /**@name Serialization and deserialization. */
170 //@{
171 uint64_t peekField(size_t readIndex, unsigned length) const;
172 uint64_t peekFieldReversed(size_t readIndex, unsigned length) const;
173 uint64_t readField(size_t& readIndex, unsigned length) const;
174 uint64_t readFieldReversed(size_t& readIndex, unsigned length) const;
175 void fillField(size_t writeIndex, uint64_t value, unsigned length);
176 void fillFieldReversed(size_t writeIndex, uint64_t value, unsigned length);
177 void writeField(size_t& writeIndex, uint64_t value, unsigned length);
178 void writeFieldReversed(size_t& writeIndex, uint64_t value, unsigned length);
kurtis.heimerl5a872472013-05-31 21:47:25 +0000179 void write0(size_t& writeIndex) { writeField(writeIndex,0,1); }
180 void write1(size_t& writeIndex) { writeField(writeIndex,1,1); }
181
dburgess82c46ff2011-10-07 02:40:51 +0000182 //@}
183
184 /** Sum of bits. */
185 unsigned sum() const;
186
187 /** Reorder bits, dest[i] = this[map[i]]. */
188 void map(const unsigned *map, size_t mapSize, BitVector& dest) const;
189
190 /** Reorder bits, dest[map[i]] = this[i]. */
191 void unmap(const unsigned *map, size_t mapSize, BitVector& dest) const;
192
193 /** Pack into a char array. */
194 void pack(unsigned char*) const;
195
196 /** Unpack from a char array. */
197 void unpack(const unsigned char*);
198
199 /** Make a hexdump string. */
200 void hex(std::ostream&) const;
kurtis.heimerl5a872472013-05-31 21:47:25 +0000201 std::string hexstr() const;
dburgess82c46ff2011-10-07 02:40:51 +0000202
203 /** Unpack from a hexdump string.
204 * @returns true on success, false on error. */
205 bool unhex(const char*);
206
kurtis.heimerl5a872472013-05-31 21:47:25 +0000207 void set(BitVector other) // That's right. No ampersand.
208 {
209 clear();
210 mData=other.mData;
211 mStart=other.mStart;
212 mEnd=other.mEnd;
213 other.mData=NULL;
214 }
215
216 void settfb(int i, int j) const
217 {
218 mStart[i] = j;
219 }
220
dburgess82c46ff2011-10-07 02:40:51 +0000221};
222
223
224
225std::ostream& operator<<(std::ostream&, const BitVector&);
226
227
228
229
230
231
232/**
233 The SoftVector class is used to represent a soft-decision signal.
234 Values 0..1 represent probabilities that a bit is "true".
235 */
236class SoftVector: public Vector<float> {
237
238 public:
239
240 /** Build a SoftVector of a given length. */
241 SoftVector(size_t wSize=0):Vector<float>(wSize) {}
242
243 /** Construct a SoftVector from a C string of "0", "1", and "X". */
244 SoftVector(const char* valString);
245
246 /** Construct a SoftVector from a BitVector. */
247 SoftVector(const BitVector& source);
248
249 /**
250 Wrap a SoftVector around a block of floats.
251 The block will be delete[]ed upon desctuction.
252 */
253 SoftVector(float *wData, unsigned length)
254 :Vector<float>(wData,length)
255 {}
256
257 SoftVector(float* wData, float* wStart, float* wEnd)
258 :Vector<float>(wData,wStart,wEnd)
259 { }
260
261 /**
262 Casting from a Vector<float>.
263 Note that this is NOT pass-by-reference.
264 */
265 SoftVector(Vector<float> source)
266 :Vector<float>(source)
267 {}
268
269
270 /**@name Casts and overrides of Vector operators. */
271 //@{
272 SoftVector segment(size_t start, size_t span)
273 {
274 float* wStart = mStart + start;
275 float* wEnd = wStart + span;
276 assert(wEnd<=mEnd);
277 return SoftVector(NULL,wStart,wEnd);
278 }
279
280 SoftVector alias()
281 { return segment(0,size()); }
282
283 const SoftVector segment(size_t start, size_t span) const
284 { return (SoftVector)(Vector<float>::segment(start,span)); }
285
286 SoftVector head(size_t span) { return segment(0,span); }
287 const SoftVector head(size_t span) const { return segment(0,span); }
288 SoftVector tail(size_t start) { return segment(start,size()-start); }
289 const SoftVector tail(size_t start) const { return segment(start,size()-start); }
290 //@}
291
Alexander Chemeris7db522b2017-03-17 18:00:50 -0700292 // How good is the SoftVector in the sense of the bits being solid?
Alexander Chemeris38b69872017-03-17 18:20:09 -0700293 // Result of 1 is perfect and 0 means all the bits were 0.0
kurtis.heimerl5a872472013-05-31 21:47:25 +0000294 // If plow is non-NULL, also return the lowest energy bit.
295 float getEnergy(float *low=0) const;
296
dburgess82c46ff2011-10-07 02:40:51 +0000297 /** Fill with "unknown" values. */
Alexander Chemeris38b69872017-03-17 18:20:09 -0700298 void unknown() { fill(0.0F); }
dburgess82c46ff2011-10-07 02:40:51 +0000299
300 /** Return a hard bit value from a given index by slicing. */
301 bool bit(size_t index) const
302 {
303 const float *dp = mStart+index;
304 assert(dp<mEnd);
Alexander Chemeris38b69872017-03-17 18:20:09 -0700305 return (*dp)>0.0F;
dburgess82c46ff2011-10-07 02:40:51 +0000306 }
307
308 /** Slice the whole signal into bits. */
309 BitVector sliced() const;
310
311};
312
313
314
315std::ostream& operator<<(std::ostream&, const SoftVector&);
316
317
318
319
320
321
322#endif
323// vim: ts=4 sw=4