/usr/share/octave/packages/communications-1.2.1/poly2trellis.m is in octave-communications-common 1.2.1-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | ## Copyright (C) 2012 Mike Miller <mtmiller@ieee.org>
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU 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 General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, see <http://www.gnu.org/licenses/>.
## -*- texinfo -*-
## @deftypefn {Function File} {@var{t} =} poly2trellis (@var{m}, @var{g})
##
## Convert convolutional code generator polynomials into trellis form.
##
## The arguments @var{m} and @var{g} together describe a rate k/n feedforward
## convolutional encoder. The output @var{t} is a trellis structure describing
## the same encoder with the fields listed below.
##
## The vector @var{m} is a k-by-1 array containing the lengths of each of the
## shift registers for the k input bits to the encoder.
##
## The matrix @var{g} is a k-by-n octal-value matrix describing the generation
## of each of the n outputs from each of the k inputs. For a particular entry
## of @var{g}, the least-significant bit corresponds to the most-delayed input
## bit in the kth shift-register.
##
## The returned trellis structure contains the following fields:
##
## @table @samp
## @item numInputSymbols
## The number of k-bit input symbols possible, i.e. 2^k.
##
## @item numOutputSymbols
## The number of n-bit output symbols possible, i.e. 2^n.
##
## @item numStates
## The number of states in the trellis.
##
## @item nextStates
## The state transition table for the trellis. The ith row contains the indices
## of the states reachable from the (i-1)th state for each possible input
## symbol.
##
## @item outputs
## A table of octal-encoded output values for the trellis. The ith row contains
## values representing the output symbols produced in the (i-1)th state for each
## possible input symbol.
## @end table
##
## Input symbols, output symbols, and encoder states are all interpreted with
## the lowest indices being the most significant bits.
##
## References:
##
## [1] S. Lin and D. J. Costello, "Convolutional codes," in @cite{Error
## Control Coding}, 2nd ed. Upper Saddle River, NJ: Pearson, 2004,
## ch. 11, pp. 453-513.
##
## @seealso{istrellis}
## @end deftypefn
function t = poly2trellis (m, g)
if (nargin != 2)
print_usage ();
endif
## Notation agrees with Lin & Costello for the most part:
## m = length of each modulo-2 adder
## = 1 + nu(:) = one more than length of each shift register
## g = generator sequences, k-by-n
## k = bits per input symbol = number of shift registers
## n = bits per output symbol = number of modulo-2 adders
[nr, k] = size (m);
if (nr != 1)
error ("poly2trellis: M must be a 1-by-k positive integer row vector");
endif
if (! (all (m == fix (m)) && all (m > 0)))
error ("poly2trellis: M must be a 1-by-k positive integer row vector");
endif
[nr, n] = size (g);
if (nr != k)
error ("poly2trellis: G must be a k-by-n octal matrix");
endif
## Convert g to decimal, let oct2dec validate the octal values
g = oct2dec (g);
## Check the ranges of the generators
## nu = total number of linear shift registers for all k
nu = sum (m) - k;
## Number of states and input symbols needed to capture the state machine
nstates = 2^nu;
ninputs = 2^k;
noutputs = 2^n;
t = struct ("numInputSymbols", ninputs,
"numOutputSymbols", noutputs,
"numStates", nstates,
"nextStates", zeros (nstates, ninputs),
"outputs", zeros (nstates, ninputs));
## Split state indices into values for each distinct shift register.
## Also precalculate new bit position for each shift register and the left
## shifts required to reassemble the states into one state value.
##
## Conventions:
## - Each shift register shifts to the right, MSB-to-LSB
## - The MSB of each shift register is the newest input
## - The MSBs of the state represent the k=1 shift register
statebits = de2bi (0:nstates - 1);
states = zeros (nstates, k);
newbit = zeros (1, k);
shifts = zeros (1, k);
offset = 1;
for i = 1:k
nu_i = m(i) - 1;
if (nu_i > 0)
states(:,i) = bi2de (statebits(:, offset:offset + nu_i - 1));
endif
newbit(i) = bitshift (1, nu_i);
shifts(i) = offset - 1;
offset += nu_i;
if (any (g(i,:) >= 2^m(i)))
error ("poly2trellis: code size is greater than constraint length");
endif
if (all (g(i,:) < 2^nu_i) || !any (mod (g(i,:), 2)))
error ("poly2trellis: code size is less than constraint length");
endif
endfor
## Generate conversion list of all possible output octal values
outputs = str2num (dec2base (0:noutputs - 1, 8));
## Walk the trellis, each row index is state, each column index is input
for s = 1:nstates
for i = 1:k
## For each next input bit [0,1] calculate inputs to modulo-2 adder
## and the next state for the ith linear shift register, left-shifted
## to be combined into the total state.
state = states(s,i) + [0; newbit(i)];
next = bitshift (bitshift (state, -1), shifts(i));
## Calculate the modulo-2 sum of the state plus input for each n for
## this particular shift register.
## The MSB of the output represents the n=1 generator(s)
out = [0; 0];
for adder = 1:n
val = mod (sum (de2bi (bitand (g(i, adder), state)), 2), 2);
out += bitshift (val, n - adder);
endfor
## Accumulate contributions to the trellis for this shift register.
## The contribution to each input symbol depends on whether the
## (k-i)th bit is 0 or 1.
bitpos = k - i;
for symbol = 1:ninputs
idx = bitget (symbol - 1, bitpos + 1) + 1;
t.nextStates(s, symbol) += next(idx);
t.outputs(s, symbol) = bitxor (t.outputs(s, symbol), out(idx));
endfor
endfor
## Convert output values to octal representation
t.outputs(s,:) = outputs(t.outputs(s,:) + 1);
endfor
endfunction
%% Test the simple (2,1,3) encoder from Lin & Costello example 11.1
%!test
%! T = struct ("numInputSymbols", 2,
%! "numOutputSymbols", 4,
%! "numStates", 8,
%! "nextStates", [0 4; 0 4; 1 5; 1 5; 2 6; 2 6; 3 7; 3 7],
%! "outputs", [0 3; 3 0; 3 0; 0 3; 1 2; 2 1; 2 1; 1 2]);
%! t = poly2trellis (4, [13 17]);
%! assert (t, T)
%! assert (istrellis (t), true)
%% Test input validation
%!error poly2trellis ()
%!error poly2trellis (1, 2, 3)
%!error poly2trellis (1)
%!error poly2trellis (2, 8)
%!error poly2trellis (0, 0)
%!error poly2trellis (2, 0)
%!error poly2trellis (2, 2)
%!error poly2trellis (2, 7)
|