/* Copyright (C) 2003 David Bateman 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 2, 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 Octave; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. In addition to the terms of the GPL, you are permitted to link this program with any Open Source program, as defined by the Open Source Initiative (www.opensource.org) */ #include #include #include #include #include // A simplified version of the filter function for specific lengths of a and b // in the Galois field GF(2) Array filter_gf2 (const Array& b, const Array& a, const Array& x, const int& n) { int x_len = x.length (); Array si (n, 0); Array y (x_len, 0); for (int i=0; i < x_len; i++) { y(i) = si(0); if (b(0) && x(i)) y(i) ^= 1; for (int j = 0; j < n - 1; j++) { si(j) = si(j+1); if (a(j+1) && y(i)) si(j) ^= 1; if (b(j+1) && x(i)) si(j) ^= 1; } si(n-1) = 0; if (a(n) && y(i)) si(n-1) ^= 1; if (b(n) && x(i)) si(n-1) ^= 1; } return y; } // Cyclic polynomial is irreducible. I.E. it divides into x^n-1 without remainder // There must surely be an easier way of doing this as the polynomials are over // GF(2). static bool do_is_cyclic_polynomial (const Array& a, const int& n, const int& m) { Array y (n+1, 0); Array x (n-m+2, 0); y(0) = 1; y(n) = 1; x(0) = 1; Array b = filter_gf2 (y, a, x, n); b.resize(n+1,0); Array p (m+1,0); p(0) = 1; Array q = filter_gf2 (a, p, b, m); for (int i=0; i < n+1; i++) if (y(i) ^ q(i)) return false; return true; } DEFUN_DLD (cyclgen, args, nargout, "-*- texinfo -*-\n" "@deftypefn {Loadable Function} {@var{h} =} cyclgen (@var{n},@var{p})\n" "@deftypefnx {Loadable Function} {@var{h} =} cyclgen (@var{n},@var{p},@var{typ})\n" "@deftypefnx {Loadable Function} {[@var{h}, @var{g}] =} cyclgen (@var{...})\n" "@deftypefnx {Loadable Function} {[@var{h}, @var{g}, @var{k}] =} cyclgen (@var{...})\n" "\n" "Produce the parity check and generator matrix of a cyclic code. The parity\n" "check matrix is returned as a @var{m} by @var{n} matrix, representing the\n" "[@var{n},@var{k}] cyclic code. @var{m} is the order of the generator\n" "polynomial @var{p} and the message length @var{k} is given by\n" "@code{@var{n} - @var{m}}.\n" "\n" "The generator polynomial can either be a vector of ones and zeros,\n" "and length @var{m} representing,\n" "@iftex\n" "@tex\n" "$$ p_0 + p_1 x + p_2 x^2 + \\cdots + p_m x^{m-1} $$\n" "@end tex\n" "@end iftex\n" "@ifinfo\n" "\n" "@example\n" " @var{p}(1) + @var{p}(2) * x + @var{p}(3) * x^2 + ... + @var{p}(@var{m}) * x^(m-1)\n" "@end example\n" "@end ifinfo\n" "\n" "The terms of the polynomial are stored least-significant term first.\n" "Alternatively, @var{p} can be an integer representation of the same\n" "polynomial.\n" "\n" "The form of the parity check matrix is determined by @var{typ}. If\n" " @var{typ} is 'system', a systematic parity check matrix is produced. If\n" " @var{typ} is 'nosys' and non-systematic parity check matrix is produced.\n" "\n" "If requested @dfn{cyclgen} also returns the @var{k} by @var{n} generator\n" "matrix @var{g}." "\n" "@end deftypefn\n" "@seealso{hammgen,gen2par,cyclpoly}") { octave_value_list retval; int nargin = args.length (); unsigned long long p = 0; int n, m, k, mm; bool system = true; Array pp; if ((nargin < 2) || (nargin > 3)) { error ("cyclgen: incorrect number of arguments"); return retval; } n = args(0).int_value (); m = 1; while (n > (1<<(m+1))) m++; pp.resize(n+1, 0); if (args(1).is_scalar_type ()) { p = (unsigned long long)(args(1).int_value()); mm = 1; while (p > ((unsigned long long)1<<(mm+1))) mm++; for (int i=0; i < mm+1; i++) pp(i) = (p & (1< 2) if (args(2).is_string ()) { std::string s_arg = args(2).string_value (); if (s_arg == "system") system = true; else if (s_arg == "nosys") system = false; else { error ("cyclgen: illegal argument"); return retval; } } else { error ("cyclgen: illegal argument"); return retval; } // Haven't implemented this since I'm not sure what matlab wants here if (!system) { error ("cyclgen: non-systematic generator matrices not implemented"); return retval; } if (!do_is_cyclic_polynomial(pp, n, mm)) { error ("cyclgen: generator polynomial does not produce cyclic code"); return retval; } unsigned long long mask = 1; unsigned long long *alpha_to = (unsigned long long *)malloc(sizeof(unsigned long long) * n); for (int i = 0; i < n; i++) { alpha_to[i] = mask; mask <<= 1; if (mask & ((unsigned long long)1< 1) { Matrix generator(k,n,0); for (int i = 0; i < (int)k; i++) for (int j = 0; j < (int)mm; j++) generator(i,j) = parity(j,i+mm); for (int i = 0; i < (int)k; i++) generator(i,i+mm) = 1; retval(1) = octave_value(generator); retval(2) = octave_value((double)k); } return retval; } /* ;;; Local Variables: *** ;;; mode: C++ *** ;;; End: *** */