LCOV - code coverage report
Current view: top level - src - encode.c (source / functions) Coverage Total Hit
Test: poporon Coverage Report Lines: 87.5 % 72 63
Test Date: 2026-03-07 15:16:43 Functions: 100.0 % 4 4
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * libpoporon - encode.c
       3              :  *
       4              :  * This file is part of libpoporon.
       5              :  *
       6              :  * Author: Brian Armstrong (original, libcorrect)
       7              :  * SPDX-License-Identifier: BSD-3-Clause
       8              :  */
       9              : 
      10              : #include "internal/common.h"
      11              : #include "internal/ldpc.h"
      12              : #include "internal/polynomial.h"
      13              : #include "internal/rs.h"
      14              : 
      15              : #if POPORON_USE_SIMD
      16              : #include "internal/simd.h"
      17              : #endif
      18              : 
      19            7 : static bool rs_encode(poporon_t *pprn, uint8_t *data, size_t size, uint8_t *parity)
      20              : {
      21            7 :     poporon_rs_t *rs = pprn->ctx.rs.rs;
      22              :     size_t pad_length;
      23              :     uint32_t i;
      24              : 
      25            7 :     if (size > (size_t)rs->message_length) {
      26            0 :         return false;
      27              :     }
      28              : 
      29            7 :     pad_length = (size_t)rs->message_length - size;
      30              : 
      31            7 :     pmemset(rs->encoded_polynomial.coeff, 0, (rs->encoded_polynomial.order + 1) * sizeof(uint16_t));
      32              : 
      33          455 :     for (i = 0; i < size; i++) {
      34          448 :         rs->encoded_polynomial.coeff[rs->encoded_polynomial.order - (i + pad_length)] = data[i] & rs->gf->field_size;
      35              :     }
      36              : 
      37            7 :     polynomial_mod(rs->gf, rs->encoded_polynomial, rs->generator, rs->encoded_remainder);
      38              : 
      39          231 :     for (i = 0; i < rs->num_roots; i++) {
      40          224 :         parity[i] = (uint8_t)rs->encoded_remainder.coeff[rs->num_roots - 1 - i];
      41              :     }
      42              : 
      43            7 :     return true;
      44              : }
      45              : 
      46           11 : static bool ldpc_encode(poporon_t *pprn, uint8_t *data, size_t size, uint8_t *parity)
      47              : {
      48           11 :     poporon_ldpc_t *ldpc = pprn->ctx.ldpc.ldpc;
      49              :     uint8_t *outer_buf, *codeword, *interleaved, *encode_input;
      50              :     size_t i;
      51              : 
      52           11 :     if (size != ldpc->info_bytes) {
      53            0 :         return false;
      54              :     }
      55              : 
      56           11 :     if (ldpc->config.use_outer_interleave && ldpc->outer_interleaver.forward) {
      57            7 :         outer_buf = ldpc->temp_outer;
      58            7 :         if (!outer_buf) {
      59            0 :             return false;
      60              :         }
      61              : 
      62            7 :         pmemset(outer_buf, 0, ldpc->info_bytes);
      63              : 
      64          775 :         for (i = 0; i < ldpc->info_bytes; i++) {
      65          768 :             outer_buf[ldpc->outer_interleaver.forward[i]] = data[i];
      66              :         }
      67              : 
      68            7 :         pmemcpy(data, outer_buf, ldpc->info_bytes);
      69            7 :         encode_input = data;
      70              :     } else {
      71            4 :         encode_input = data;
      72              :     }
      73              : 
      74           11 :     if (!poporon_ldpc_encode(ldpc, encode_input, parity)) {
      75            0 :         return false;
      76              :     }
      77              : 
      78           11 :     if (ldpc->config.use_inner_interleave && ldpc->interleaver.forward) {
      79            7 :         codeword = ldpc->temp_codeword;
      80            7 :         pmemcpy(codeword, encode_input, ldpc->info_bytes);
      81            7 :         pmemcpy(codeword + ldpc->info_bytes, parity, ldpc->parity_bytes);
      82              : 
      83            7 :         interleaved = ldpc->temp_interleaved;
      84            7 :         if (!interleaved) {
      85            0 :             return false;
      86              :         }
      87              : 
      88            7 :         poporon_ldpc_interleave(ldpc, codeword, interleaved);
      89              : 
      90            7 :         pmemcpy(data, interleaved, ldpc->info_bytes);
      91            7 :         pmemcpy(parity, interleaved + ldpc->info_bytes, ldpc->parity_bytes);
      92              :     }
      93              : 
      94           11 :     return true;
      95              : }
      96              : 
      97            1 : static bool bch_encode(poporon_t *pprn, uint8_t *data, size_t size, uint8_t *parity)
      98              : {
      99            1 :     poporon_bch_t *bch = pprn->ctx.bch.bch;
     100            1 :     uint32_t data_val = 0, codeword = 0, parity_val;
     101              :     uint16_t i, data_len, codeword_len, parity_bits, data_bytes, parity_bytes;
     102              : 
     103            1 :     data_len = poporon_bch_get_data_length(bch);
     104            1 :     codeword_len = poporon_bch_get_codeword_length(bch);
     105            1 :     parity_bits = codeword_len - data_len;
     106            1 :     data_bytes = (data_len + 7) / 8;
     107            1 :     parity_bytes = (parity_bits + 7) / 8;
     108              : 
     109            1 :     if (size < data_bytes) {
     110            0 :         return false;
     111              :     }
     112              : 
     113            2 :     for (i = 0; i < data_bytes && i < 4; i++) {
     114            1 :         data_val |= ((uint32_t)data[i]) << (8 * (data_bytes - 1 - i));
     115              :     }
     116              : 
     117            1 :     if (data_len < 32) {
     118            1 :         data_val &= ((uint32_t)1 << data_len) - 1;
     119              :     }
     120              : 
     121            1 :     if (!poporon_bch_encode(bch, data_val, &codeword)) {
     122            0 :         return false;
     123              :     }
     124              : 
     125            1 :     parity_val = codeword & (((uint32_t)1 << parity_bits) - 1);
     126            1 :     pmemset(parity, 0, parity_bytes);
     127            3 :     for (i = 0; i < parity_bytes && i < 4; i++) {
     128            2 :         parity[parity_bytes - 1 - i] = (uint8_t)(parity_val >> (8 * i));
     129              :     }
     130              : 
     131            1 :     return true;
     132              : }
     133              : 
     134           24 : extern bool poporon_encode(poporon_t *pprn, uint8_t *data, size_t size, uint8_t *parity)
     135              : {
     136           24 :     if (!pprn || !data || !parity) {
     137            5 :         return false;
     138              :     }
     139              : 
     140           19 :     switch (pprn->fec_type) {
     141            7 :     case PPLN_FEC_RS:
     142            7 :         return rs_encode(pprn, data, size, parity);
     143           11 :     case PPLN_FEC_LDPC:
     144           11 :         return ldpc_encode(pprn, data, size, parity);
     145            1 :     case PPLN_FEC_BCH:
     146            1 :         return bch_encode(pprn, data, size, parity);
     147            0 :     default:
     148            0 :         return false;
     149              :     }
     150              : }
        

Generated by: LCOV version 2.0-1