LCOV - code coverage report
Current view: top level - src - polynomial.c (source / functions) Coverage Total Hit
Test: poporon Coverage Report Lines: 86.7 % 120 104
Test Date: 2026-03-07 15:16:43 Functions: 90.9 % 11 10
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * libpoporon - polynomial.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/polynomial.h"
      11              : 
      12          108 : extern polynomial_t polynomial_create(uint32_t order)
      13              : {
      14              :     polynomial_t polynomial;
      15              : 
      16          108 :     polynomial.coeff = (uint16_t *)pcalloc(order + 1, sizeof(uint16_t));
      17          108 :     polynomial.order = order;
      18              : 
      19          108 :     return polynomial;
      20              : }
      21              : 
      22          108 : extern void polynomial_destroy(polynomial_t polynomial)
      23              : {
      24          108 :     pfree(polynomial.coeff);
      25          108 : }
      26              : 
      27          429 : extern void polynomial_mul(poporon_gf_t *gf, polynomial_t l, polynomial_t r, polynomial_t res)
      28              : {
      29              :     uint32_t i, j, j_limit;
      30              : 
      31          429 :     pmemset(res.coeff, 0, sizeof(uint16_t) * (res.order + 1));
      32         1450 :     for (i = 0; i <= l.order; i++) {
      33         1021 :         if (i > res.order) {
      34            0 :             continue;
      35              :         }
      36              : 
      37         1021 :         j_limit = (r.order > res.order - i) ? res.order - i : r.order;
      38              : 
      39        17990 :         for (j = 0; j <= j_limit; j++) {
      40        16969 :             res.coeff[i + j] = field_add(res.coeff[i + j], field_mul(gf, l.coeff[i], r.coeff[j]));
      41              :         }
      42              :     }
      43          429 : }
      44              : 
      45            7 : extern void polynomial_mod(poporon_gf_t *gf, polynomial_t dividend, polynomial_t divisor, polynomial_t mod)
      46              : {
      47              :     uint32_t i, j, q_order;
      48              :     uint16_t divisor_leading, q_coeff;
      49              : 
      50            7 :     if (mod.order < dividend.order) {
      51            0 :         return;
      52              :     }
      53              : 
      54            7 :     pmemcpy(mod.coeff, dividend.coeff, sizeof(uint16_t) * (dividend.order + 1));
      55              : 
      56            7 :     divisor_leading = gf->log[divisor.coeff[divisor.order]];
      57              : 
      58         1568 :     for (i = dividend.order; i > 0; i--) {
      59         1568 :         if (i < divisor.order) {
      60            7 :             break;
      61              :         }
      62              : 
      63         1561 :         if (mod.coeff[i] == 0) {
      64         1113 :             continue;
      65              :         }
      66              : 
      67          448 :         q_order = i - divisor.order;
      68          448 :         q_coeff = field_div_log(gf, gf->log[mod.coeff[i]], divisor_leading);
      69              : 
      70        15232 :         for (j = 0; j <= divisor.order; j++) {
      71        14784 :             if (divisor.coeff[j] == 0) {
      72            0 :                 continue;
      73              :             }
      74              : 
      75        14784 :             mod.coeff[j + q_order] =
      76        14784 :                 field_add(mod.coeff[j + q_order], field_mul_log_element(gf, gf->log[divisor.coeff[j]], q_coeff));
      77              :         }
      78              :     }
      79              : }
      80              : 
      81           21 : extern void polynomial_formal_derivative(poporon_gf_t *gf, polynomial_t poly, polynomial_t der)
      82              : {
      83              :     uint32_t i;
      84              : 
      85           21 :     pmemset(der.coeff, 0, sizeof(uint16_t) * (der.order + 1));
      86              : 
      87          205 :     for (i = 0; i <= der.order; i++) {
      88          184 :         der.coeff[i] = field_sum(poly.coeff[i + 1], i + 1);
      89              :     }
      90           21 : }
      91              : 
      92            0 : extern uint16_t polynomial_eval(poporon_gf_t *gf, polynomial_t poly, uint16_t val)
      93              : {
      94              :     uint32_t i;
      95              :     uint16_t res, val_exponentiated, val_log;
      96              : 
      97            0 :     if (val == 0) {
      98            0 :         return poly.coeff[0];
      99              :     }
     100              : 
     101            0 :     res = 0;
     102            0 :     val_exponentiated = gf->log[1];
     103            0 :     val_log = gf->log[val];
     104              : 
     105            0 :     for (i = 0; i <= poly.order; i++) {
     106            0 :         if (poly.coeff[i] != 0) {
     107            0 :             res = field_add(res, field_mul_log_element(gf, gf->log[poly.coeff[i]], val_exponentiated));
     108              :         }
     109              : 
     110            0 :         val_exponentiated = field_mul_log(gf, val_exponentiated, val_log);
     111              :     }
     112              : 
     113            0 :     return res;
     114              : }
     115              : 
     116         1168 : extern uint16_t polynomial_eval_lut(poporon_gf_t *gf, polynomial_t poly, const uint16_t *val_exp)
     117              : {
     118              :     uint32_t i;
     119              :     uint16_t res;
     120              : 
     121         1168 :     if (val_exp[0] == 0) {
     122            0 :         return poly.coeff[0];
     123              :     }
     124              : 
     125         1168 :     res = 0;
     126       213310 :     for (i = 0; i <= poly.order; i++) {
     127       212142 :         if (poly.coeff[i] != 0) {
     128        79120 :             res = field_add(res, field_mul_log_element(gf, gf->log[poly.coeff[i]], val_exp[i]));
     129              :         }
     130              :     }
     131              : 
     132         1168 :     return res;
     133              : }
     134              : 
     135         5632 : extern uint16_t polynomial_eval_log_lut(poporon_gf_t *gf, polynomial_t poly_log, const uint16_t *val_exp)
     136              : {
     137              :     uint16_t res;
     138              :     uint32_t i;
     139              : 
     140         5632 :     if (val_exp[0] == 0) {
     141           22 :         if (poly_log.coeff[0] == 0) {
     142            0 :             return 0;
     143              :         }
     144              : 
     145           22 :         return gf->exp[poly_log.coeff[0]];
     146              :     }
     147              : 
     148         5610 :     res = 0;
     149        53040 :     for (i = 0; i <= poly_log.order; i++) {
     150        47430 :         if (poly_log.coeff[i] != 0) {
     151        47175 :             res = field_add(res, field_mul_log_element(gf, poly_log.coeff[i], val_exp[i]));
     152              :         }
     153              :     }
     154              : 
     155         5610 :     return res;
     156              : }
     157              : 
     158         1728 : extern void polynomial_build_exp_lut(poporon_gf_t *gf, uint16_t val, uint32_t order, uint16_t *val_exp)
     159              : {
     160              :     uint32_t i;
     161              :     uint16_t val_exponentiated, val_log;
     162              : 
     163         1728 :     val_exponentiated = gf->log[1];
     164         1728 :     val_log = gf->log[val];
     165              : 
     166        99840 :     for (i = 0; i <= order; i++) {
     167        98112 :         if (val == 0) {
     168          192 :             val_exp[i] = 0;
     169              :         } else {
     170        97920 :             val_exp[i] = val_exponentiated;
     171        97920 :             val_exponentiated = field_mul_log(gf, val_exponentiated, val_log);
     172              :         }
     173              :     }
     174         1728 : }
     175              : 
     176            2 : extern polynomial_t polynomial_init_from_roots(poporon_gf_t *gf, uint32_t nroots, uint16_t *roots, polynomial_t poly,
     177              :                                         polynomial_t *scratch)
     178              : {
     179              :     polynomial_t l, r[2];
     180              :     uint32_t i, rcoeffres, nextrcoeff;
     181              :     uint16_t l_coeff[2];
     182              : 
     183            2 :     l.order = 1;
     184            2 :     l.coeff = l_coeff;
     185              : 
     186            2 :     r[0] = scratch[0];
     187            2 :     r[1] = scratch[1];
     188            2 :     rcoeffres = 0;
     189              : 
     190            2 :     r[rcoeffres].coeff[1] = 1;
     191            2 :     r[rcoeffres].coeff[0] = roots[0];
     192            2 :     r[rcoeffres].order = 1;
     193              : 
     194            2 :     l.coeff[1] = 1;
     195              : 
     196           36 :     for (i = 1; i < nroots; i++) {
     197           34 :         l.coeff[0] = roots[i];
     198           34 :         nextrcoeff = rcoeffres;
     199           34 :         rcoeffres = (rcoeffres + 1) % 2;
     200           34 :         r[rcoeffres].order = i + 1;
     201           34 :         polynomial_mul(gf, l, r[nextrcoeff], r[rcoeffres]);
     202              :     }
     203              : 
     204            2 :     pmemcpy(poly.coeff, r[rcoeffres].coeff, (nroots + 1) * sizeof(uint16_t));
     205            2 :     poly.order = nroots;
     206              : 
     207            2 :     return poly;
     208              : }
     209              : 
     210           18 : extern polynomial_t polynomial_create_from_roots(poporon_gf_t *gf, uint32_t nroots, uint16_t *roots)
     211              : {
     212              :     polynomial_t poly, l, r[2];
     213              :     uint32_t rcoeffres, nextrcoeff, i;
     214              : 
     215           18 :     poly = polynomial_create(nroots);
     216              : 
     217           18 :     l.order = 1;
     218           18 :     l.coeff = (uint16_t *)pcalloc(2, sizeof(uint16_t));
     219              : 
     220           18 :     r[0].coeff = (uint16_t *)pcalloc(nroots + 1, sizeof(uint16_t));
     221           18 :     r[0].order = 0;
     222           18 :     r[1].coeff = (uint16_t *)pcalloc(nroots + 1, sizeof(uint16_t));
     223           18 :     r[1].order = 0;
     224           18 :     rcoeffres = 0;
     225              : 
     226           18 :     r[rcoeffres].coeff[0] = roots[0];
     227           18 :     r[rcoeffres].coeff[1] = 1;
     228           18 :     r[rcoeffres].order = 1;
     229              : 
     230           18 :     l.coeff[1] = 1;
     231              : 
     232          392 :     for (i = 1; i < nroots; i++) {
     233          374 :         l.coeff[0] = roots[i];
     234          374 :         nextrcoeff = rcoeffres;
     235          374 :         rcoeffres = (rcoeffres + 1) % 2;
     236          374 :         r[rcoeffres].order = i + 1;
     237          374 :         polynomial_mul(gf, l, r[nextrcoeff], r[rcoeffres]);
     238              :     }
     239              : 
     240           18 :     pmemcpy(poly.coeff, r[rcoeffres].coeff, (nroots + 1) * sizeof(uint16_t));
     241           18 :     poly.order = nroots;
     242              : 
     243           18 :     pfree(l.coeff);
     244           18 :     pfree(r[0].coeff);
     245           18 :     pfree(r[1].coeff);
     246              : 
     247           18 :     return poly;
     248              : }
        

Generated by: LCOV version 2.0-1