// // Created by zemon on 29.07.2022. // #include #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; }