PolyGalois256/PolyGalois256.c

193 lines
5.4 KiB
C

//
// Created by zemon on 29.07.2022.
//
#include <memory.h>
#include "PolyGalois256.h"
inline size_t sPolyGalois256HighestDegree(tPolyGalois256 *poly) {
return poly->length - 1;
}
void vPolyGalois256Mul(tGalois256 *gf, tPolyGalois256 *first, tPolyGalois256 *second, tPolyGalois256 *result) {
uint8_t result_degree = sPolyGalois256HighestDegree(first) + sPolyGalois256HighestDegree(second);
result->length = result_degree + 1;
memset(result->data, 0, result->length);
for (size_t first_idx = 0; first_idx < first->length; ++first_idx) {
for (size_t second_idx = 0; second_idx < second->length; ++second_idx) {
uint8_t mux_degree = first_idx + second_idx;
uint8_t mux = iGalois256Mul(gf, first->data[first_idx], second->data[second_idx]);
result->data[mux_degree] = iGalois256Add(gf, result->data[mux_degree], mux);
}
}
}
void vPolyGalois256Add(tGalois256 *gf, tPolyGalois256 *first, tPolyGalois256 *second, tPolyGalois256 *result) {
uint8_t result_degree = first->length > second->length ? first->length : second->length;
result->length = result_degree;
for (size_t idx = 0; idx < result_degree; ++idx) {
result->data[idx] = 0;
if (first->length > idx) {
result->data[idx] = iGalois256Add(gf, result->data[idx], first->data[idx]);
}
if (second->length > idx) {
result->data[idx] = iGalois256Add(gf, result->data[idx], second->data[idx]);
}
}
}
void vPolyGalois256MulNumber(tGalois256 *gf, tPolyGalois256 *first, uint8_t number, tPolyGalois256 *result) {
result->length = sPolyGalois256HighestDegree(first) + number;
memset(result->data, 0, number);
memcpy(result->data + number, first->data, result->length - number);
}
void vPolyGalois256MulNumberSelf(tGalois256 *gf, tPolyGalois256 *poly, uint8_t number) {
memmove(poly->data + number, poly->data, poly->length);
memset(poly->data, 0, number);
poly->length += number;
}
void vPolyGalois256Scale(tGalois256 *gf, tPolyGalois256 *orgn, uint8_t number, tPolyGalois256 *result) {
result->length = orgn->length;
for (size_t idx = 0; idx < orgn->length; ++idx) {
result->data[idx] = iGalois256Mul(gf, orgn->data[idx], number);
}
}
void vPolyGalois256Copy(tPolyGalois256 *source, tPolyGalois256 *target) {
target->length = source->length;
memcpy(target->data, source->data, source->length);
}
void vPolyGalois256CopyRevers(tPolyGalois256 *source, tPolyGalois256 *target) {
target->length = source->length;
for (size_t target_idx = 0, source_idx = source->length - 1;
target_idx < source->length;
++target_idx, --source_idx) {
target->data[target_idx] = source->data[source_idx];
}
}
void vPolyGalois256Revers(tPolyGalois256 *source) {
size_t swaps_count = source->length / 2;
size_t top = source->length - 1;
uint8_t tmp;
for (size_t idx = 0; idx < swaps_count; ++idx) {
tmp = source->data[idx];
source->data[idx] = source->data[top - idx];
source->data[top - idx] = tmp;
}
}
void vPolyGalois256FormalDerivative(tPolyGalois256 *source, tPolyGalois256 *derivative) {
derivative->length = source->length - 1;
for (size_t idx = 0; idx < derivative->length; ++idx) {
if (idx % 2) {
derivative->data[idx] = 0;
} else {
derivative->data[idx] = source->data[idx + 1];
}
}
}
uint8_t iPolyGalois256GetMax(tPolyGalois256 *source) {
uint8_t max = 0;
for (size_t idx = 0; idx < source->length; ++idx) {
if (source->data[idx] > max) {
max = source->data[idx];
}
}
return max;
}
uint8_t iPolyGalois256Value(tGalois256 *gf, tPolyGalois256 *env, uint8_t input) {
uint8_t value = 0;
uint8_t deg = 1;
for (size_t idx = 0; idx < env->length; ++idx) {
uint8_t element = iGalois256Mul(gf, deg, env->data[idx]);
value = iGalois256Add(gf, value, element);
deg = iGalois256Mul(gf, deg, input);
}
return value;
}
uint8_t iPolyGalois256IsZero(tPolyGalois256 *source) {
for (size_t idx = 0; idx < source->length; ++idx) {
if (source->data[idx] != 0) {
return 1;
}
}
return 0;
}
void vPolyGalois256DividePolynomials(
tGalois256 *gf,
tPolyGalois256 *remainder_out,
tPolyGalois256 *divisor
) {
size_t dividend_left = remainder_out->length - 1;
size_t divisor_left = divisor->length - 1;
uint8_t top_value_of_divisor = divisor->data[divisor_left];
int16_t remainder_left = dividend_left;
size_t err_break = dividend_left;
do {
for (; remainder_left >= 0; --remainder_left) {
if (remainder_out->data[remainder_left] > 0) {
break;
}
}
if (remainder_left < divisor_left) {
return;
}
uint8_t product_value = iGalois256Div(gf, remainder_out->data[remainder_left], top_value_of_divisor);
uint8_t product_idx = remainder_left - divisor_left;
for (int16_t sub_idx = divisor_left; sub_idx >= 0; --sub_idx) {
uint8_t element = iGalois256Mul(gf, divisor->data[sub_idx], product_value);
remainder_out->data[(product_idx + sub_idx)] =
iGalois256Sub(gf, remainder_out->data[(product_idx + sub_idx)], element);
}
--err_break;
} while (err_break);
remainder_out->length = remainder_left + 1;
}