diff options
-rw-r--r-- | gr-fec/examples/271.127.3.112 | 402 | ||||
-rw-r--r-- | gr-fec/grc/fec_block_tree.xml | 2 | ||||
-rw-r--r-- | gr-fec/grc/ldpc_decoder_def_list.xml | 83 | ||||
-rwxr-xr-x | gr-fec/grc/ldpc_encoder_def_list.xml | 69 | ||||
-rw-r--r-- | gr-fec/lib/CMakeLists.txt | 5 | ||||
-rw-r--r-- | gr-fec/lib/alist.cc | 210 | ||||
-rw-r--r-- | gr-fec/lib/awgn_bp.cc | 264 | ||||
-rw-r--r-- | gr-fec/lib/cldpc.cc | 133 | ||||
-rw-r--r-- | gr-fec/lib/gf2mat.cc | 199 | ||||
-rw-r--r-- | gr-fec/lib/gf2vec.cc | 96 | ||||
-rw-r--r-- | gr-fec/swig/fec_swig.i | 4 |
11 files changed, 1467 insertions, 0 deletions
diff --git a/gr-fec/examples/271.127.3.112 b/gr-fec/examples/271.127.3.112 new file mode 100644 index 0000000000..205d5adab1 --- /dev/null +++ b/gr-fec/examples/271.127.3.112 @@ -0,0 +1,402 @@ +271 127 +3 7 +3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 +121 50 63 +20 1 68 +98 56 60 +48 99 57 +53 31 59 +93 101 46 +47 15 2 +9 49 75 +38 39 77 +118 16 55 +76 13 40 +29 54 91 +48 23 114 +94 24 68 +100 114 21 +127 19 34 +44 8 33 +3 123 50 +78 100 79 +59 81 98 +67 39 37 +124 54 47 +7 27 64 +67 28 74 +51 75 118 +5 88 55 +45 81 18 +66 103 99 +41 82 102 +65 123 86 +118 25 119 +60 78 113 +89 110 87 +88 30 22 +4 14 44 +110 102 17 +122 125 70 +46 22 109 +16 90 97 +35 73 58 +102 3 119 +127 11 10 +59 36 111 +37 50 78 +34 73 101 +92 74 29 +79 26 40 +97 22 100 +65 84 12 +26 55 9 +38 21 31 +108 45 70 +3 43 26 +57 105 33 +51 31 74 +69 71 60 +96 124 117 +93 72 71 +13 5 30 +42 86 11 +37 6 95 +12 50 47 +43 113 80 +90 107 9 +24 125 44 +83 82 15 +107 28 21 +7 87 81 +124 104 23 +89 121 98 +5 122 27 +83 38 12 +77 120 76 +4 25 33 +40 114 95 +108 20 23 +37 56 2 +126 89 24 +53 52 10 +120 109 117 +49 64 8 +111 6 77 +70 49 19 +112 96 1 +14 72 10 +36 17 87 +7 32 115 +28 34 5 +72 18 8 +29 49 11 +63 119 13 +83 61 11 +27 17 26 +51 93 82 +39 91 61 +30 110 115 +22 15 28 +115 20 42 +96 67 97 +116 38 105 +27 45 32 +16 3 6 +106 14 88 +58 51 61 +103 29 20 +94 84 117 +6 109 13 +19 66 53 +86 30 57 +48 105 43 +35 12 25 +58 14 18 +44 36 1 +62 46 35 +41 64 69 +113 121 1 +9 127 4 +43 92 42 +52 25 104 +35 7 122 +112 120 36 +65 71 23 +52 54 41 +39 85 32 +32 80 24 +48 123 63 +15 40 31 +90 106 56 +21 45 91 +116 92 68 +112 18 116 +80 125 47 +4 17 2 +106 107 101 +94 108 62 +126 69 99 +41 95 34 +111 19 2 +75 62 42 +104 103 33 +84 85 16 +73 46 76 +10 85 8 +79 126 66 +68 63 3 +59 25 91 +69 2 81 +50 23 89 +69 49 22 +80 98 30 +24 31 127 +88 37 104 +52 18 37 +6 104 65 +40 2 22 +6 81 40 +110 33 51 +110 5 42 +112 84 119 +74 53 63 +60 123 124 +4 104 60 +122 105 55 +43 12 16 +126 44 114 +124 84 118 +57 10 50 +98 108 13 +116 22 126 +54 95 18 +107 19 7 +45 28 118 +61 54 72 +6 39 97 +67 34 93 +10 42 121 +94 91 123 +66 96 40 +75 78 44 +71 49 101 +88 83 26 +20 62 7 +119 87 38 +17 32 100 +63 87 85 +92 30 15 +82 23 60 +113 98 20 +5 73 24 +46 102 89 +71 62 58 +65 9 48 +99 45 62 +86 23 26 +91 117 51 +65 42 36 +87 112 126 +127 50 114 +125 124 102 +41 8 114 +54 77 1 +29 99 33 +111 45 47 +30 14 105 +108 107 116 +19 47 32 +76 122 112 +116 21 64 +72 80 92 +110 14 64 +35 108 78 +55 4 89 +115 82 27 +25 56 27 +17 95 111 +59 43 29 +47 61 16 +39 81 90 +15 35 18 +103 85 13 +106 99 34 +109 66 90 +26 115 31 +120 27 3 +83 70 10 +118 57 4 +41 15 58 +34 36 117 +125 28 53 +109 38 24 +35 20 5 +36 96 16 +72 106 19 +1 46 122 +94 76 97 +106 2 61 +80 48 13 +68 52 74 +94 121 82 +86 113 14 +57 37 107 +44 119 48 +121 68 31 +66 46 125 +77 7 79 +90 3 83 +102 9 73 +84 100 58 +29 73 78 +103 67 11 +33 49 32 +12 8 28 +93 69 97 +120 127 67 +71 75 103 +92 101 52 +105 96 85 +120 75 56 +88 79 53 +17 8 1 +59 64 101 +109 12 79 +77 21 113 +11 93 38 +11 74 70 +41 115 123 +25 117 55 +70 86 100 +43 56 76 +95 9 51 +21 111 39 +260 234 201 116 113 84 2 +236 155 147 138 133 77 7 +246 224 145 102 53 41 18 +226 212 162 133 117 74 35 +231 189 158 88 71 59 26 +174 156 154 107 102 82 61 +245 182 171 120 87 68 23 +260 252 200 143 89 81 17 +270 247 192 117 64 50 8 +225 176 167 143 85 79 42 +265 264 250 92 90 60 42 +262 252 164 111 72 62 49 +237 220 168 107 91 59 11 +240 210 204 112 103 85 35 +227 219 186 127 97 66 7 +232 217 164 141 102 39 10 +260 215 184 133 93 86 36 +219 170 153 131 112 89 27 +233 206 171 138 108 83 16 +231 188 182 105 98 76 2 +271 263 208 129 67 51 15 +169 155 149 97 48 38 34 +194 187 148 122 76 69 13 +230 189 151 125 78 65 14 +267 214 146 119 111 74 31 +223 194 181 93 53 50 47 +224 214 213 101 93 71 23 +252 229 172 97 88 67 24 +249 216 202 105 90 46 12 +204 186 150 109 96 59 34 +243 223 151 127 55 51 5 +251 206 184 125 124 101 87 +251 202 157 140 74 54 17 +228 221 175 137 88 45 16 +231 219 211 120 114 111 40 +232 228 196 121 113 86 43 +241 153 152 77 61 44 21 +264 230 183 100 72 51 9 +271 218 174 124 95 21 9 +178 156 155 127 75 47 11 +266 227 200 137 123 115 29 +196 176 158 139 118 98 60 +269 216 164 118 110 63 53 +242 179 165 113 65 35 17 +203 193 172 129 101 52 27 +244 234 190 142 114 38 6 +217 206 203 132 62 22 7 +242 237 192 126 110 13 4 +251 180 149 90 83 81 8 +198 167 148 62 44 18 1 +270 195 157 104 94 55 25 +256 238 153 123 119 79 0 +259 229 160 108 79 5 0 +201 173 170 123 22 12 0 +267 212 163 50 26 10 0 +269 258 214 128 77 3 0 +241 226 167 109 54 4 0 +248 227 191 112 104 40 0 +261 216 146 43 20 5 0 +187 162 161 56 32 3 0 +236 217 173 104 95 92 0 +193 191 182 139 135 114 0 +185 160 145 126 91 1 0 +261 210 208 115 81 23 0 +196 192 154 122 49 30 0 +244 222 178 144 108 28 0 +254 250 175 99 24 21 0 +243 238 145 130 14 2 0 +253 149 147 136 115 56 0 +268 265 225 83 52 37 0 +255 191 180 122 58 56 0 +233 209 173 89 85 58 0 +249 247 189 142 45 40 0 +265 238 160 55 46 24 0 +258 255 179 139 25 8 0 +269 235 207 142 73 11 0 +263 245 201 82 73 9 0 +249 211 179 44 32 19 0 +262 259 245 144 47 19 0 +237 209 150 132 125 63 0 +218 156 147 68 27 20 0 +239 213 187 94 66 29 0 +246 225 181 92 72 66 0 +248 166 159 141 106 49 0 +257 220 185 143 141 124 0 +268 240 194 109 60 30 0 +197 185 183 86 68 33 0 +259 181 152 103 34 26 0 +212 190 148 78 70 33 0 +246 222 218 128 64 39 0 +195 177 146 129 95 12 0 +256 209 186 130 118 46 0 +264 253 175 94 58 6 0 +239 235 177 135 106 14 0 +270 215 170 137 75 61 0 +257 232 178 99 84 57 0 +253 235 174 99 48 39 0 +188 168 150 70 20 3 0 +221 202 193 136 28 4 0 +268 248 184 48 19 15 0 +261 256 180 134 45 6 0 +247 199 190 41 36 29 0 +255 250 220 140 105 28 0 +162 154 152 140 119 69 0 +257 204 163 110 100 54 0 +236 233 221 134 128 103 0 +241 205 171 134 67 64 0 +211 205 168 135 76 52 0 +262 230 222 107 80 38 0 +210 158 157 96 36 33 0 +271 215 203 138 82 43 0 +207 197 159 131 121 84 0 +263 240 188 116 63 32 0 +200 198 165 75 15 13 0 +266 223 213 98 96 87 0 +208 205 169 131 130 100 0 +267 228 195 106 80 57 0 +226 172 166 31 25 10 0 +242 183 159 91 41 31 0 +258 254 224 121 80 73 0 +243 239 176 116 70 1 0 +234 207 163 120 71 37 0 +266 177 161 126 30 18 0 +199 166 161 69 57 22 0 +244 229 199 132 65 37 0 +197 169 165 144 136 78 0 +254 198 151 117 42 16 0 diff --git a/gr-fec/grc/fec_block_tree.xml b/gr-fec/grc/fec_block_tree.xml index c674531e3f..97610f08c8 100644 --- a/gr-fec/grc/fec_block_tree.xml +++ b/gr-fec/grc/fec_block_tree.xml @@ -12,6 +12,7 @@ <name>Decoders</name> <block>variable_cc_decoder_def</block> <block>variable_repetition_decoder_def</block> + <block>variable_ldpc_decoder_def</block> <block>variable_dummy_decoder_def</block> </cat> <cat> @@ -19,6 +20,7 @@ <block>variable_cc_encoder_def</block> <block>variable_ccsds_encoder_def</block> <block>variable_repetition_encoder_def</block> + <block>variable_ldpc_encoder_def</block> <block>variable_dummy_encoder_def</block> </cat> <block>fec_extended_encoder</block> diff --git a/gr-fec/grc/ldpc_decoder_def_list.xml b/gr-fec/grc/ldpc_decoder_def_list.xml new file mode 100644 index 0000000000..01bdce7d55 --- /dev/null +++ b/gr-fec/grc/ldpc_decoder_def_list.xml @@ -0,0 +1,83 @@ +<?xml version="1.0"?> +<!-- +################################################### +# FEC MAKING FOR GREAT JUSTICE +################################################### + --> +<block> + <name>LDPC Decoder Definition</name> + <key>variable_ldpc_decoder_def</key> + <import>from gnuradio import fec</import> + <var_make> +#if int($ndim())==1 # +self.$(id) = $(id) = map( (lambda a: fec.ldpc_make_decoder($file, $sigma, $max_iter)), range(0,$dim1) ); #slurp +#else +self.$(id) = $(id) = map( (lambda b: map( ( lambda a: fec.ldpc_make_decoder($file, $sigma, $max_iter)), range(0,$dim2) ) ), range(0,$dim1)); #slurp +#end if</var_make> + <make></make> + +<!-- This definition below is wierd, it seems required for the GRC to be happy, im confused --> + <param> + <name>Ignore Me</name> + <key>value</key> + <value>"ok"</value> + <type>raw</type> + <hide>all</hide> + </param> + + <param> + <name>Threading Dimensions</name> + <key>ndim</key> + <value></value> + <type>enum</type> + <option> + <name>2</name> + <key>2</key> + </option> + <option> + <name>1</name> + <key>1</key> + </option> + + </param> + + <param> + <name>Dimension 1</name> + <key>dim1</key> + <value>4</value> + <type>int</type> + <hide>#if (int($ndim()) >= 1) then 'none' else 'all' #</hide> + </param> + + <param> + <name>Dimension 2</name> + <key>dim2</key> + <value>4</value> + <type>int</type> + <hide>#if (int($ndim()) >= 2) then 'none' else 'all' #</hide> + </param> + + <param> + <name>AList File</name> + <key>file</key> + <type>file_open</type> + </param> + + <param> + <name>Sigma</name> + <key>sigma</key> + <value>0.5</value> + <type>float</type> + </param> + + <param> + <name>Max Iterations</name> + <key>max_iter</key> + <value>50</value> + <type>int</type> + </param> + + <doc> + This block does some kind of ldpc + </doc> +</block> diff --git a/gr-fec/grc/ldpc_encoder_def_list.xml b/gr-fec/grc/ldpc_encoder_def_list.xml new file mode 100755 index 0000000000..26200ab4ba --- /dev/null +++ b/gr-fec/grc/ldpc_encoder_def_list.xml @@ -0,0 +1,69 @@ +<?xml version="1.0"?> +<!-- +################################################### +# FEC MAKING FOR GREAT JUSTICE +################################################### + --> +<block> + <name>LDPC Encoder Definition</name> + <key>variable_ldpc_encoder_def</key> + <import>from gnuradio import fec</import> + <var_make> +#if int($ndim())==1 # +self.$(id) = $(id) = map( (lambda a: fec.ldpc_make_encoder($file)), range(0,$dim1) ); #slurp +#else +self.$(id) = $(id) = map( (lambda b: map( ( lambda a: fec.ldpc_make_encoder($file)), range(0,$dim2) ) ), range(0,$dim1)); #slurp +#end if</var_make> + <make></make> + +<!-- This definition below is wierd, it seems required for the GRC to be happy, im confused --> + <param> + <name>Ignore Me</name> + <key>value</key> + <value>"ok"</value> + <type>raw</type> + <hide>all</hide> + </param> + + <param> + <name>Threading Dimensions</name> + <key>ndim</key> + <value></value> + <type>enum</type> + <option> + <name>2</name> + <key>2</key> + </option> + <option> + <name>1</name> + <key>1</key> + </option> + + </param> + + <param> + <name>Dimension 1</name> + <key>dim1</key> + <value>4</value> + <type>int</type> + <hide>#if (int($ndim()) >= 1) then 'none' else 'all' #</hide> + </param> + + <param> + <name>Dimension 2</name> + <key>dim2</key> + <value>4</value> + <type>int</type> + <hide>#if (int($ndim()) >= 2) then 'none' else 'all' #</hide> + </param> + + <param> + <name>AList File</name> + <key>file</key> + <type>file_open</type> + </param> + + <doc> + This block does LDPC + </doc> +</block> diff --git a/gr-fec/lib/CMakeLists.txt b/gr-fec/lib/CMakeLists.txt index e4a55c2d59..99f701cc2c 100644 --- a/gr-fec/lib/CMakeLists.txt +++ b/gr-fec/lib/CMakeLists.txt @@ -73,6 +73,11 @@ list(APPEND gnuradio_fec_sources depuncture_bb_impl.cc ldpc_encoder.cc ldpc_decoder.cc + cldpc.cc + awgn_bp.cc + gf2vec.cc + gf2mat.cc + alist.cc ) #Add Windows DLL resource file if using MSVC diff --git a/gr-fec/lib/alist.cc b/gr-fec/lib/alist.cc new file mode 100644 index 0000000000..eeeb729ac2 --- /dev/null +++ b/gr-fec/lib/alist.cc @@ -0,0 +1,210 @@ +/*! + * \file + * \brief Implementation of a class to hold sparse matrices in alist-format + * \author Manu T S + * + * ----------------------------------------------------------------- + * + * Copyright 2013 IIT Bombay. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + * ----------------------------------------------------------------- + */ + +#include <gnuradio/fec/alist.h> + +alist::alist(const char * fname) + : data_ok(false) { + read(fname); +} + +std::vector<std::vector<char> > alist::get_matrix() { + std::vector<std::vector<char> > mat; + mat.resize(M); + for ( int i = 0; i < M; i++ ) { + mat[i].resize(N); + for ( int j = 0; j < N; j++ ) { + mat[i][j] = char(0); + } + for ( int k = 0; k < num_mlist[i]; k++ ) { + mat[i][mlist[i][k] - 1] = char(1); + } + } + return mat; +} + +std::vector< std::vector<int> > alist::get_mlist() { + return mlist; +} + +std::vector< std::vector<int> > alist::get_nlist() { + return nlist; +} + +std::vector<int> alist::get_num_mlist() { + return num_mlist; +} + +std::vector<int> alist::get_num_nlist() { + return num_nlist; +} + +void alist::read(const char * fname) { + std::ifstream file; + std::string line; + std::stringstream ss; + + file.open(fname); + if(!(file.is_open())) { + std::cout << "Could not open the file" << std::endl; + } + + // Parse N and M + std::getline(file, line); + ss << line; + ss >> N >> M; + num_nlist.resize(N); + num_mlist.resize(M); + nlist.resize(N); + mlist.resize(M); + ss.seekg(0, std::ios::end); + ss.clear(); + + // parse max_num_n and max_num_m + std::getline(file, line); + ss << line; + ss >> max_num_nlist >> max_num_mlist; + ss.seekg(0, std::ios::end); + ss.clear(); + + // Parse weight of each column n + std::getline(file, line); + ss << line; + for (int i = 0; i < N; i++ ) { + ss >> num_nlist[i]; + nlist[i].resize(num_nlist[i]); + } + ss.seekg(0, std::ios::end); + ss.clear(); + + // Parse weight of each row m + std::getline(file, line); + ss << line; + for (int i = 0; i < M; i++ ) { + ss >> num_mlist[i]; + mlist[i].resize(num_mlist[i]); + } + ss.seekg(0, std::ios::end); + ss.clear(); + + // Parse indices with non zero entries in ith column + for (int column = 0; column < N; column++) { + std::getline(file, line); + ss << line; + for (int entry = 0; entry < num_nlist[column]; entry++) { + ss >> nlist[column][entry]; + } + ss.seekg(0, std::ios::end); + ss.clear(); + } + + // Parse indices with non zero entries in ith row + for (int row = 0; row < M; row++) { + std::getline(file, line); + ss << line; + for (int entry = 0; entry < num_mlist[row]; entry++) { + ss >> mlist[row][entry]; + } + ss.seekg(0, std::ios::end); + ss.clear(); + } + + file.close(); + data_ok = true; +} + +void alist::write(const char * fname) const +{ + if (!data_ok) { + std::cout << "Data not ok, exiting" << std::endl; + exit(1); + } + // Else + std::ofstream file(fname, std::ofstream::out); + // Write N and M + file << N << " " << M << std::endl; + file << max_num_nlist << " " << max_num_mlist << std::endl; + // Write column weights + for (int i = 0; i < num_nlist.size() - 1; i++) { + file << num_nlist[i] << " "; + } + file << num_nlist[num_nlist.size() - 1] << std::endl; + // Write row weights + for (int i = 0; i < num_mlist.size() - 1; i++) { + file << num_mlist[i] << " "; + } + file << num_mlist[num_mlist.size() - 1] << std::endl; + // Write non zero indices in the ith column + for (int i = 0; i < N; i++) { + for (int j = 0; j < num_nlist[i] - 1; j++) { + file << nlist[i][j] << "\t"; + } + file << nlist[i][num_nlist[i] - 1]; + file << std::endl; + } + // Write non zero indices in the ith row + for (int i = 0; i < M; i++) { + for (int j = 0; j < num_mlist[i] - 1; j++) { + file << mlist[i][j] << "\t"; + } + file << mlist[i][num_mlist[i] - 1]; + file << std::endl; + } + file.close(); +} + +int alist::get_N() { + return N; +} + +int alist::get_M() { + return M; +} + +int alist::get_max_num_nlist() { + return max_num_nlist; +} + +int alist::get_max_num_mlist() { + return max_num_mlist; +} + +void alist::print_nlist_i(int column) { + std::cout << "Indices in column " << column << std::endl; + for (int i = 0; i < num_nlist[column] - 1; i++) { + std::cout << nlist[column][i] << ", "; + } + std::cout << nlist[column][num_nlist[column] - 1] << std::endl; +} + +void alist::print_mlist_i(int row) { + std::cout << "Indices in row " << row << std::endl; + for (int i = 0; i < num_mlist[row] - 1; i++) { + std::cout << mlist[row][i] << ", "; + } + std::cout << mlist[row][num_mlist[row] - 1] << std::endl; +} diff --git a/gr-fec/lib/awgn_bp.cc b/gr-fec/lib/awgn_bp.cc new file mode 100644 index 0000000000..7e08e7a6b9 --- /dev/null +++ b/gr-fec/lib/awgn_bp.cc @@ -0,0 +1,264 @@ +/*! + * \file + * \brief Implementation of a class for message passing for AWGN channel + * \author Manu T S + * + * ----------------------------------------------------------------- + * + * Copyright 2013 IIT Bombay. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + * ----------------------------------------------------------------- + */ + +#include <gnuradio/fec/awgn_bp.h> + +awgn_bp::awgn_bp ( const GF2Mat X, float sgma) { + H = X; + M = H.get_M(); + N = H.get_N(); + Q.resize(M); + R.resize(M); + sigma = sgma; + for (int i = 0; i < M; i++) { + Q[i].resize(N); + R[i].resize(N); + } + lr.resize(N); + estimate.resize(N); +} + +awgn_bp::awgn_bp ( alist _list, float sgma) { + H = GF2Mat(_list); + mlist = _list.get_mlist(); + nlist = _list.get_nlist(); + num_mlist = _list.get_num_mlist(); + num_nlist = _list.get_num_nlist(); + M = H.get_M(); + N = H.get_N(); + Q.resize(M); + R.resize(M); + sigma = sgma; + for (int i = 0; i < M; i++) { + Q[i].resize(N); + R[i].resize(N); + } + lr.resize(N); + estimate.resize(N); +} + +void awgn_bp::set_alist_sigma(alist _list, float sgma) { + H = GF2Mat(_list); + mlist = _list.get_mlist(); + nlist = _list.get_nlist(); + num_mlist = _list.get_num_mlist(); + num_nlist = _list.get_num_nlist(); + M = H.get_M(); + N = H.get_N(); + Q.resize(M); + R.resize(M); + sigma = sgma; + for (int i = 0; i < M; i++) { + Q[i].resize(N); + R[i].resize(N); + } + lr.resize(N); + estimate.resize(N); +} + +std::vector< std::vector<double> > awgn_bp::get_Q() { + return Q; +} + +std::vector< std::vector<double> > awgn_bp::get_R() { + return R; +} + +GF2Mat awgn_bp::get_H() { + return H; +} + +void awgn_bp::rx_lr_calc(std::vector<float> codeword) { + rx_lr.resize(N); + float y; + for ( int i = 0; i < N; i++){ + y = codeword[i]; + rx_lr[i] = exp((-1*y)/(2*sigma*sigma)); + } +} + +std::vector<double> awgn_bp::get_rx_lr() { + return rx_lr; +} + +std::vector<double> awgn_bp::get_lr() { + return lr; +} + +void awgn_bp::spa_initialize() { + int row; + for ( int var = 0; var < N; var++ ) { + for ( int i = 0; i < num_nlist[var]; i++ ) { + row = nlist[var][i] - 1; + Q[row][var] = rx_lr[var]; + } + } +} + +void awgn_bp::update_chks() { + double product, _prdct; + int v; + for ( int chk = 0; chk < M; chk++ ) { + product = double(1.0); + for (int i = 0; i < num_mlist[chk]; i++) { + v = mlist[chk][i] - 1; + product = product*double( 2/(1 + Q[chk][v]) - 1 ); + } + for ( int i = 0; i < num_mlist[chk]; i++ ) { + v = mlist[chk][i] - 1; + _prdct = product/double( 2/(1 + Q[chk][v]) - 1); + R[chk][v] = double((1 - _prdct)/(1 + _prdct)); + } + } +} + +void awgn_bp::update_vars() { + double _sum, __sum; + int c; + for ( int var = 0; var < N; var++ ) { + _sum = rx_lr[var]; + for ( int i = 0; i < num_nlist[var]; i++ ) { + c = nlist[var][i] - 1; + _sum = _sum * double(R[c][var]); + } + lr[var] = _sum; + for ( int i = 0; i < num_nlist[var]; i++ ) { + c = nlist[var][i] - 1; + __sum = _sum/R[c][var]; + Q[c][var] = __sum; + } + } +} + +std::vector<char> awgn_bp::get_estimate() { + return estimate; +} + +void awgn_bp::compute_init_estimate(std::vector<float> rx_word) { + for ( int i = 0; i < rx_word.size(); i++ ) { + if (rx_word[i] < 0) + estimate[i] = char(1); + else + estimate[i] = char(0); + } +} + +void awgn_bp::decision() { + for ( int i = 0; i < N; i++ ){ + if ( lr[i] > 1 ) + estimate[i] = char(1); + else + estimate[i] = char(0); + } +} + +void awgn_bp::set_K(int k) { + K = k; +} + +int awgn_bp::get_K() { + return K; +} + +std::vector<char> awgn_bp::get_syndrome(std::vector<char> codeword) { + std::vector<char> synd; + synd.resize(N - K); + GF2Vec in_bvec; + in_bvec.set_vec(codeword); + for ( int i = 0; i < N - K; i++ ) { + synd[i] = H[i]*in_bvec; + } + return synd; +} + +std::vector<char> awgn_bp::get_syndrome() { + std::vector<char> synd; + synd.resize(N - K); + GF2Vec in_bvec; + in_bvec.set_vec(estimate); + for ( int i = 0; i < N - K; i++ ) { + synd[i] = H[i]*in_bvec; + } + return synd; +} + +bool awgn_bp::is_codeword(std::vector<char> codeword) { + std::vector<char> synd; + synd = get_syndrome(codeword); + bool is_code; + is_code = true; + for ( int i = 0; i < N - K; i++ ) { + if ( synd[i] != char(0) ) { + is_code = false; + } + } + return is_code; +} + +bool awgn_bp::is_codeword() { + std::vector<char> synd; + synd = get_syndrome(); + bool is_code; + is_code = true; + for ( int i = 0; i < N - K; i++ ) { + if ( synd[i] != char(0) ) { + is_code = false; + } + } + return is_code; +} + +void awgn_bp::set_max_iterations(int k) { + max_iterations = k; +} + +int awgn_bp::get_max_iterations() { + return max_iterations; +} + +std::vector<char> awgn_bp::decode(std::vector<float> rx_word, + int *niteration) { + *niteration = 0; + compute_init_estimate(rx_word); + if (is_codeword()) { + return estimate; + } + else { + rx_lr_calc(rx_word); + spa_initialize(); + while (*niteration < max_iterations) { + *niteration += 1; + update_chks(); + update_vars(); + decision(); + if (is_codeword()) { + break; + } + } + return estimate; + } +} diff --git a/gr-fec/lib/cldpc.cc b/gr-fec/lib/cldpc.cc new file mode 100644 index 0000000000..0798ff7393 --- /dev/null +++ b/gr-fec/lib/cldpc.cc @@ -0,0 +1,133 @@ +/*! + * \file + * \brief Implementation of a class holding an LDPC code + * \author Manu T S + * + * ----------------------------------------------------------------- + * + * Copyright 2013 IIT Bombay. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + * ----------------------------------------------------------------- + */ + +#include <gnuradio/fec/cldpc.h> + +cldpc::cldpc(const GF2Mat X) { + H = X; + M = H.get_M(); + N = H.get_N(); + G = H.get_G(permute, rank_H); + K = N - rank_H; +} + +cldpc::cldpc(const alist _list) { + H = GF2Mat(_list); + M = H.get_M(); + N = H.get_N(); + G = H.get_G(permute, rank_H); + K = N - rank_H; +} + +void cldpc::set_alist(const alist _list) { + H = GF2Mat(_list); + M = H.get_M(); + N = H.get_N(); + G = H.get_G(permute, rank_H); + K = N - rank_H; +} + +std::vector<char> cldpc::get_systematic_bits(std::vector<char> in) { + std::vector<char> data; + data.resize(K); + int index; + for ( int i = 0; i < K; i++ ) { + index = permute[i + rank_H]; + data[i] = in[index]; + } + return data; +} + +void cldpc::print_permute() { + for ( int i = 0; i < permute.size(); i++ ) { + std::cout << permute[i] << ", "; + } + std::cout << "\n"; +} + +std::vector<char> cldpc::syndrome(const std::vector<char> in) { + std::vector<char> synd; + synd.resize(rank_H); + GF2Vec in_bvec; + in_bvec.set_vec(in); + for ( int i = 0; i < rank_H; i++ ) { + synd[i] = H[i]*in_bvec; + } + return synd; +} + +bool cldpc::is_codeword(const std::vector<char> in) { + std::vector<char> synd; + synd = syndrome(in); + bool is_code; + is_code = true; + for ( int i = 0; i < rank_H; i++ ) { + if ( synd[i] != char(0) ) { + is_code = false; + } + } + return is_code; +} + +std::vector<char> cldpc::encode(std::vector<char> dataword) { + if (dataword.size() == K) { + GF2Vec x(N); + GF2Vec data(K); + data.set_vec(dataword); + for ( int i = rank_H; i < N; i++ ) { + x[i] = dataword[i - rank_H]; + } + for ( int i = 0; i < rank_H; i++ ) { + x[i] = G[i].sub_vector(N-K, N)*data; + } + GF2Vec y(N); + for ( int i = 0; i < N; i++ ) { + y[permute[i]] = x[i]; + } + return y.get_vec(); + } +} + +int cldpc::dimension() { + return K; +} + +int cldpc::get_M() { + return M; +} + +int cldpc::get_N() { + return N; +} + +GF2Mat cldpc::get_H() { + return H; +} + +GF2Mat cldpc::get_G() { + return G; +} diff --git a/gr-fec/lib/gf2mat.cc b/gr-fec/lib/gf2mat.cc new file mode 100644 index 0000000000..61240c8ffb --- /dev/null +++ b/gr-fec/lib/gf2mat.cc @@ -0,0 +1,199 @@ +/*! + * \file + * \brief Implementation of a class for GF2 matrix algebra + * \author Manu T S + * + * ----------------------------------------------------------------- + * + * Copyright 2013 IIT Bombay. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + * ----------------------------------------------------------------- + */ + +#include <gnuradio/fec/gf2mat.h> +#include <iostream> + +GF2Mat::GF2Mat(int m, int n) { + M = m; + N = n; + H.resize(M); + for ( int i = 0; i < M; i++ ) { + H[i].resize(N); + for ( int j = 0; j < N; j++ ) { + H[i][j] = char(0); + } + } +} + +GF2Mat::GF2Mat(std::vector <std::vector<char> > X) { + M = X.size(); + N = X[0].size(); + H.resize(M); + for ( int i = 0; i < M; i++ ) { + H[i].resize(N); + for ( int j = 0; j < N; j++ ){ + H[i][j] = X[i][j]; + } + } +} + +GF2Mat::GF2Mat(alist _list) { + int m, n; + M = _list.get_M(); + N = _list.get_N(); + H.resize(M); + for ( int i = 0; i < M; i++ ) { + H[i].resize(N); + for ( int j = 0; j < N; j++ ) { + H[i][j] = char(0); + } + } + H = _list.get_matrix(); +} + +int GF2Mat::get_M() { + return M; +} + +int GF2Mat::get_N() { + return N; +} + +void GF2Mat::set_element(int i, int j, char val) { + H[i][j] = val; +} + +char GF2Mat::get_element(int i, int j) { + return H[i][j]; +} + +void GF2Mat::print_matrix() { + for (int i = 0; i < M; i++) { + for (int j = 0; j < N; j++) { + std::cout << int(H[i][j]) << " "; + } + std::cout << '\n'; + } +} + +GF2Vec GF2Mat::operator[](int i) { + GF2Vec row(N); + row.set_vec(H[i]); + return row; +} + +GF2Vec GF2Mat::get_row(int i) { + GF2Vec row(N); + for ( int j = 0; j < N; j++ ){ + row[j] = H[i][j]; + } + return row; +} + +GF2Vec GF2Mat::get_col(int i) { + GF2Vec col(M); + for ( int j = 0; j < M; j++ ) { + col[j] = H[j][i]; + } + return col; +} + +void GF2Mat::add_cols(int i, int j) { + for ( int row = 0; row < M; row++ ) { + H[row][i] = H[row][i] xor H[row][j]; + } +} + +void GF2Mat::add_rows(int i, int j) { + for ( int col = 0; col < N; col++ ) { + H[i][col] = H[i][col] xor H[j][col]; + } +} + +void GF2Mat::set_row(int row, GF2Vec vec) { + for ( int j = 0; j < N; j++ ) { + H[row][j] = vec[j]; + } +} + +void GF2Mat::set_col(int col, GF2Vec vec) { + for ( int j = 0; j < M; j++ ) { + H[j][col] = vec[j]; + } +} + +void GF2Mat::swap_cols(int i, int j) { + GF2Vec tmp; + tmp = get_col(i); + set_col(i, get_col(j)); + set_col(j, tmp); +} + +GF2Mat GF2Mat::get_G(std::vector<int> & permute, + int & rank) { + permute.resize(N); + rank = 0; + for ( int col = 0; col < N; col++ ) { + permute[col] = col; + } + GF2Mat G(H); + int diag = 0; + int limit = M; + int temp; + while (diag < limit) { + bool non_zero = false; + for ( int col = diag; col < N; col++ ) { + if ( G.get_element(diag, col) == char(1) ) { + non_zero = true; + rank++; + G.swap_cols(diag, col); + temp = permute[diag]; + permute[diag] = permute[col]; + permute[col] = temp; + break; + } + } + if (non_zero) { + for ( int row = 0; row < diag; row++ ) { + if (G.get_element(row, diag) == char(1)){ + G.add_rows(row, diag); + } + } + for ( int row = diag + 1; row < M; row++ ) { + if (G.get_element(row, diag) == char(1)) { + G.add_rows(row, diag); + } + } + diag++; + } + else{ + GF2Vec current_row; + current_row = G.get_row(diag); + for ( int row = diag; row < limit - 1; row++ ) { + G.set_row(row, G.get_row(row + 1)); + } + G.set_row(limit - 1, current_row); + limit--; + } + } + return G; +} + +std::vector<std::vector<char> > GF2Mat::get_H() { + return H; +} diff --git a/gr-fec/lib/gf2vec.cc b/gr-fec/lib/gf2vec.cc new file mode 100644 index 0000000000..e5c80adb7e --- /dev/null +++ b/gr-fec/lib/gf2vec.cc @@ -0,0 +1,96 @@ +/*! + * \file + * \brief Implementation of a class for GF2 vector algebra + * \author Manu T S + * + * ----------------------------------------------------------------- + * + * Copyright 2013 IIT Bombay. + * + * This 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, or (at your option) + * any later version. + * + * This software 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 software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + * ----------------------------------------------------------------- + */ + +#include <gnuradio/fec/gf2vec.h> +#include <iostream> + +GF2Vec::GF2Vec(int size) { + vec.resize(size); + for( int i = 0; i < size; i++) { + vec[i] = char(0); + } +} + +void GF2Vec::set_vec(const std::vector<char> in) { + resize(in.size()); + for ( int i = 0; i < vec.size(); i++ ) { + vec[i] = in[i]; + } +} + +std::vector<char> GF2Vec::get_vec(){ + return vec; +} + +int GF2Vec::size() { + return vec.size(); +} + +char & GF2Vec::operator[](int i) { + return vec[i]; +} + +GF2Vec operator+(GF2Vec a, GF2Vec b) { + GF2Vec sum(a.size()); + for( int i = 0; i < sum.size(); i++) { + sum[i] = a[i] ^ b[i]; + } + return sum; +} + +GF2Vec GF2Vec::sub_vector(int from, int to) { + int len = to - from; + GF2Vec x(len); + for ( int i = 0; i < len; i++ ) { + x[i] = vec[i + from]; + } + return x; +} + +char operator*(GF2Vec a, GF2Vec b) { + char sum; + sum = char(0); + for (int i = 0; i < a.size(); i++) { + sum = sum ^ ( a[i] & b[i] ); + } + return sum; +} + +void GF2Vec::print_vec() { + for (int i = 0; i < size(); i++ ) { + std::cout << int(vec[i]) << " "; + } + std::cout << '\n'; +} + +void GF2Vec::resize(int size) { + vec.resize(size); +} + +void GF2Vec::operator=(GF2Vec x) { + set_vec(x.get_vec()); +} diff --git a/gr-fec/swig/fec_swig.i b/gr-fec/swig/fec_swig.i index 8ad845fd1c..858c72d78f 100644 --- a/gr-fec/swig/fec_swig.i +++ b/gr-fec/swig/fec_swig.i @@ -58,6 +58,8 @@ #include "gnuradio/fec/puncture_bb.h" #include "gnuradio/fec/puncture_ff.h" #include "gnuradio/fec/depuncture_bb.h" +#include "gnuradio/fec/ldpc_encoder.h" +#include "gnuradio/fec/ldpc_decoder.h" %} %include "gnuradio/fec/generic_decoder.h" @@ -82,6 +84,8 @@ %include "gnuradio/fec/puncture_bb.h" %include "gnuradio/fec/puncture_ff.h" %include "gnuradio/fec/depuncture_bb.h" +%include "gnuradio/fec/ldpc_encoder.h" +%include "gnuradio/fec/ldpc_decoder.h" GR_SWIG_BLOCK_MAGIC2(fec, decoder); GR_SWIG_BLOCK_MAGIC2(fec, encoder); |