/*---------------------------------------------------------------------------* * IT++ * *---------------------------------------------------------------------------* * Copyright (c) 1995-2001 by Tony Ottosson, Thomas Eriksson, Pål Frenger, * * Tobias Ringström, and Jonas Samuelsson. * * * * Permission to use, copy, modify, and distribute this software and its * * documentation under the terms of the GNU General Public License is hereby * * granted. No representations are made about the suitability of this * * software for any purpose. It is provided "as is" without expressed or * * implied warranty. See the GNU General Public License for more details. * *---------------------------------------------------------------------------*/ /*! \file \brief Definitions of interleaver classes \author Pål Frenger 1.12 2004/05/10 15:08:58 */ #ifndef __interleave_h #define __interleave_h #include "base/binary.h" #include "base/matfunc.h" #include "base/random.h" #include "base/vec.h" #include "base/mat.h" namespace itpp { /*! \defgroup interl Interleavers */ /*! \ingroup interl \class Block_Interleaver comm/interleave.h \brief Block Interleaver Class. Data is written row-wise and read column-wise when interleaving.

Example of use:

\code BPSK bpsk; bvec bits = "0 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1"; vec symbols = bpsk.modulate_bits(bits); Block_Interleaver block_interleaver(4,4); vec interleaved_symbols = block_interleaver.interleave(symbols); \endcode */ template class Block_Interleaver { public: //! Block_Interleaver constructor Block_Interleaver(void) {rows = 0; cols = 0;}; //! Block_Interleaver constructor Block_Interleaver(int in_rows, int in_cols); //! Function for block interleaving. May add some zeros. Vec interleave(const Vec &input); //! Function for block interleaving. May add some zeros. void interleave(const Vec &input, Vec &output); //! Function for block deinterleaving. Removes additional zeros if \a keepzeros = 0. Vec deinterleave(const Vec &input, short keepzeros = 0 ); //! Function for block deinterleaving. Removes additional zeros if \a keepzeros = 0. void deinterleave(const Vec &input, Vec &output, short keepzeros = 0 ); //! Set the number of \a rows for block interleaving void set_rows(int in_rows) {rows = in_rows;}; //! Set the number of \a columns for block interleaving void set_cols(int in_cols) {cols = in_cols;}; //! Get the number of \a rows for block interleaving int get_rows(void) {return rows;}; //! Get the number of \a columns for block interleaving int get_cols(void) {return cols;}; private: int rows, cols, input_length; }; /*! \ingroup interl \class Cross_Interleaver comm/interleave.h \brief Cross Interleaver Class.

Example of use:

\code BPSK bpsk; bvec bits = "0 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1"; vec symbols = bpsk.modulate_bits(bits); Cross_Interleaver cross_interleaver(4); vec interleaved_symbols = cross_interleaver.interleave(symbols); \endcode
  • See S. B. Wicker, "Error control systems for digital communications and storage," Prentice Hall 1995, p. 427 for details.
*/ template class Cross_Interleaver { public: //! Cross_Interleaver constructor Cross_Interleaver(void) {order = 0;}; //! Cross_Interleaver constructor Cross_Interleaver(int in_order); //! Function for cross interleaving. Adds some zeros. Vec interleave(const Vec &input); //! Function for cross interleaving. Adds some zeros. void interleave(const Vec &input, Vec &output); //! Function for cross deinterleaving. Removes aditional zeros if \a keepzeros = 0. Vec deinterleave(const Vec &input, short keepzeros = 0); //! Function for cross deinterleaving. Removes aditional zeros if \a keepzeros = 0. void deinterleave(const Vec &input, Vec &output, short keepzeros = 0); //! Set the \a order of the Cross Interleaver void set_order(int in_order); //! Get the \a order of the Cross Interleaver int get_order(void) {return order;}; private: int order; int input_length; Mat inter_matrix; Vec tempvec, zerostemp; }; /*! \ingroup interl \class Sequence_Interleaver comm/interleave.h \brief Sequence Interleaver Class

Example of use:

\code BPSK bpsk; bvec bits = "0 1 1 0 0 0 1 1 1 1 0 0 1 0 0 1"; vec symbols = bpsk.modulate_bits(bits); Sequence_Interleaver sequence_interleaver(16); sequence_interleaver.randomize_interleaver_sequence(); vec interleaved_symbols = sequence_snterleaver.interleave(symbols); \endcode */ template class Sequence_Interleaver { public: //! Sequence_Interleaver constructor. Sequence_Interleaver(void) {interleaver_depth = 0;}; /*! \brief Sequence_Interleaver constructor. Chooses a random sequence of length \a in_interleaver_depth for interleaving. */ Sequence_Interleaver(int in_interleaver_depth); /*! \brief Sequence_Interleaver constructor. Uses the \a in_interleaver_sequence for interleaving. */ Sequence_Interleaver(ivec in_interleaver_sequence); //! Function for sequence interleaving. May add some zeros. Vec interleave(const Vec &input); //! Function for sequence interleaving. May add some zeros. void interleave(const Vec &input, Vec &output); //! Function for sequence deinterleaving. Removes additional zeros if \a keepzeros = 0. Vec deinterleave(const Vec &input, short keepzeros = 0 ); //! Function for sequence deinterleaving. Removes additional zeros if \a keepzeros = 0. void deinterleave(const Vec &input, Vec &output, short keepzeros = 0 ); //! Generate a new random sequence for interleaving. void randomize_interleaver_sequence(); //! Returns the interleaver sequence presently used. ivec get_interleaver_sequence(); //! Set the interleaver sequence to be used. void set_interleaver_sequence(ivec in_interleaver_sequence); //! Set the length of the interleaver sequence to be used. void set_interleaver_depth(int in_interleaver_depth) { interleaver_depth = in_interleaver_depth; }; //! Get the length of the interleaver sequence presently used. int get_interleaver_depth(void) { return interleaver_depth; }; private: ivec interleaver_sequence; int interleaver_depth, input_length; }; //----------------------------------------------------------------------------- // Implementation of templated members starts here //----------------------------------------------------------------------------- //-------------------------- Block Interleaver --------------------------------- template Block_Interleaver::Block_Interleaver(int in_rows, int in_cols) { rows = in_rows; cols = in_cols; input_length = 0; }; template void Block_Interleaver::interleave(const Vec &input, Vec &output) { input_length = input.length(); int steps = (int)std::ceil( double(input_length)/double(rows*cols) ); int output_length = steps * rows * cols; output.set_length(output_length,false); int s, r, c; if (input_length==output_length) { //Block interleaver loop: All steps. for (s=0; s zerovect(output_length - input_length); zerovect.clear(); Vec temp_last_input = concat( input.right(rows*cols-zerovect.length()), zerovect ); for (c=0; c Vec Block_Interleaver::interleave(const Vec &input) { Vec output; interleave(input,output); return output; } template void Block_Interleaver::deinterleave(const Vec &input, Vec &output, short keepzeros) { int thisinput_length = input.length(); int steps = (int)std::ceil( double(thisinput_length)/double(rows*cols) ); int output_length = steps * rows * cols; output.set_size(output_length,false); int s, r, c; if (thisinput_length==output_length) { //Block deinterleaver loop: All, but the last, steps. for (s=0; s zerovect(output_length - thisinput_length); zerovect.clear(); Vec temp_last_input = concat( input.right(rows*cols-zerovect.length()), zerovect ); for (r=0; r Vec Block_Interleaver::deinterleave(const Vec &input, short keepzeros) { Vec output; deinterleave(input,output,keepzeros); return output; } //---------------------------- Cross Interleaver --------------------------- template Cross_Interleaver::Cross_Interleaver(int in_order) { order = in_order; input_length = 0; inter_matrix.set_size(order,order,false); tempvec.set_size(order,false); zerostemp.set_size(order,false); } template void Cross_Interleaver::interleave(const Vec &input, Vec &output) { input_length = input.length(); int steps = (int)std::ceil( float(input_length) / order ) + order; int output_length = steps * order; output.set_length(output_length,false); int i, r, c; inter_matrix.clear(); zerostemp.clear(); //Cross interleaver loop: for (i=0; i< steps; i++ ){ //Shift the matrix to the right: for (c=order-1; c>0; c--) inter_matrix.set_col(c, inter_matrix.get_col(c-1) ); // Write the new data to the matrix if ((i*order+order) Vec Cross_Interleaver::interleave(const Vec &input) { Vec output; interleave(input,output); return output; } template void Cross_Interleaver::deinterleave(const Vec &input, Vec &output, short keepzeros) { int thisinput_length = input.length(); int steps = (int)std::ceil( float(thisinput_length) / order ) + order; int output_length = steps * order; output.set_size(output_length,false); int i, r, c; inter_matrix.clear(); zerostemp.clear(); //Cross interleaver loop: for (i=0; i0; c--) inter_matrix.set_col(c,inter_matrix.get_col(c-1)); // Write the new data to the matrix if ((i*order+order) Vec Cross_Interleaver::deinterleave(const Vec &input, short keepzeros) { Vec output; deinterleave(input,output,keepzeros); return output; } template void Cross_Interleaver::set_order(int in_order) { order = in_order; input_length = 0; inter_matrix.set_size(order,order,false); tempvec.set_size(order,false); zerostemp.set_size(order,false); } //------------------- Sequence Interleaver -------------------------------- template Sequence_Interleaver::Sequence_Interleaver(int in_interleaver_depth) { interleaver_depth = in_interleaver_depth; interleaver_sequence = sort_index(randu(in_interleaver_depth)); input_length = 0; } template Sequence_Interleaver::Sequence_Interleaver(ivec in_interleaver_sequence) { interleaver_depth = in_interleaver_sequence.length(); interleaver_sequence = in_interleaver_sequence; input_length = 0; } template void Sequence_Interleaver::interleave(const Vec &input, Vec &output) { input_length = input.length(); int steps = (int)std::ceil( double(input_length)/double(interleaver_depth) ); int output_length = steps*interleaver_depth; output.set_size(output_length,false); int s, i; if (input_length==output_length) { //Sequence interleaver loop: All steps. for (s=0; s zerovect(output_length - input_length); zerovect.clear(); Vec temp_last_input = concat( input.right(interleaver_depth-zerovect.length()), zerovect ); for (i=0; i Vec Sequence_Interleaver::interleave(const Vec &input) { Vec output; interleave(input,output); return output; } template void Sequence_Interleaver::deinterleave(const Vec &input, Vec &output, short keepzeros) { int thisinput_length = input.length(); int steps = (int)std::ceil( double(thisinput_length)/double(interleaver_depth) ); int output_length = steps*interleaver_depth; //long_long thisinput_length = input.length(); //long_long steps = (long_long)std::ceil( double(thisinput_length)/double(interleaver_depth) ); //long_long output_length = steps*interleaver_depth; output.set_length(output_length,false); int s, i; //long_long s, i; if (thisinput_length == output_length) { //Sequence interleaver loop: All steps. for (s=0; s zerovect(output_length - thisinput_length); zerovect.clear(); Vec temp_last_input = concat( input.right(interleaver_depth-zerovect.length()), zerovect ); for (i=0; i Vec Sequence_Interleaver::deinterleave(const Vec &input, short keepzeros) { Vec output; deinterleave(input,output,keepzeros); return output; } template void Sequence_Interleaver::randomize_interleaver_sequence() { interleaver_sequence = sort_index(randu(interleaver_depth)); } template ivec Sequence_Interleaver::get_interleaver_sequence() { return interleaver_sequence; } template void Sequence_Interleaver::set_interleaver_sequence(ivec in_interleaver_sequence) { interleaver_sequence = in_interleaver_sequence; interleaver_depth = interleaver_sequence.size(); } } //namespace itpp #endif // __interleave_h