From daa8de6a9f88f007215093f13564fdbf0c9a7660 Mon Sep 17 00:00:00 2001 From: cfif Date: Fri, 24 Jan 2025 13:22:33 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BD=D0=BE=D0=B2=D1=83=D1=8E=20=D0=BE=D1=80?= =?UTF-8?q?=D0=B3=D0=B0=D0=BD=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8E=20GONEC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- GonetsReedSalmon.c | 426 +++++++++++++++++++++++++++++++++++++++++++++ GonetsReedSalmon.h | 37 ++++ modular.json | 17 ++ 3 files changed, 480 insertions(+) create mode 100644 GonetsReedSalmon.c create mode 100644 GonetsReedSalmon.h create mode 100644 modular.json diff --git a/GonetsReedSalmon.c b/GonetsReedSalmon.c new file mode 100644 index 0000000..49d4e4d --- /dev/null +++ b/GonetsReedSalmon.c @@ -0,0 +1,426 @@ +// +// Created by zemon on 24.07.2022. +// + +#include "GonetsReedSalmon.h" +#include "PolyGalois256.h" +#include + +int32_t vGonetsReedSalmonAddDegree(tGonetsReedSalmon *env, int32_t fieldNumber, int32_t degreeAddon) { + int32_t numDegree = iGalois256LogValue(env->gf, fieldNumber); + return iGalois256PowValue(env->gf, numDegree + degreeAddon); +} + + +void vGonetsReedSalmonGenGenerativePoly(tGonetsReedSalmon *env) { + + memset(env->generative_polynomial, 0, env->generative_polynomial_len * sizeof(int8_t)); + + + env->generative_polynomial[0] = 2; + env->generative_polynomial[1] = 1; + + + for (uint8_t i = 2; i < env->generative_polynomial_len; i++) { + env->generative_polynomial[i] = 1; + + for (uint8_t j = i - 1; j > 0; j--) { + if (env->generative_polynomial[j] == 0) { + env->generative_polynomial[j] = env->generative_polynomial[j - 1]; + } else { + env->generative_polynomial[j] = iGalois256Add( + env->gf, + env->generative_polynomial[j - 1], + vGonetsReedSalmonAddDegree(env, env->generative_polynomial[j], i) + ); + } + } + + env->generative_polynomial[0] = vGonetsReedSalmonAddDegree(env, env->generative_polynomial[0], i); + } + +} + +void vGonetsReedSalmonInit(tGonetsReedSalmon *env, tGalois256 *galoisField, uint8_t parity_length) { + env->gf = galoisField; + env->parity_length = parity_length; + env->generative_polynomial_len = env->parity_length + 1; + env->max_fixable_err = env->parity_length / 2; + + vGonetsReedSalmonGenGenerativePoly(env); +} + + +static void vGonetsReedSalmonDividePolynomialsR( + tGalois256 *gf, + + uint8_t dividend_len, + + const uint8_t *divisor, + uint8_t divisor_len, + + uint8_t *remainder +) { + + + --dividend_len; + --divisor_len; + + + uint8_t top_value_of_divisor = divisor[divisor_len]; + + int16_t remainder_len = dividend_len; + + + size_t err_break = dividend_len; + do { + + for (; remainder_len >= 0; --remainder_len) { + if (remainder[-remainder_len] > 0) { + break; + } + } + + if (remainder_len < divisor_len) { + return; + } + + uint8_t product_value = iGalois256Div(gf, remainder[-remainder_len], top_value_of_divisor); + uint8_t product_idx = remainder_len - divisor_len; + + + for (int16_t sub_idx = divisor_len; sub_idx >= 0; --sub_idx) { + + uint8_t element = iGalois256Mul(gf, divisor[sub_idx], product_value); + remainder[-(product_idx + sub_idx)] = iGalois256Sub(gf, remainder[-(product_idx + sub_idx)], element); + + } + + --err_break; + } while (err_break); +} + +void vGonetsReedSalmonEncode( + tGonetsReedSalmon *env, + + const uint8_t *message, + uint8_t message_len, + + uint8_t *encoded_message +) { + + memcpy(encoded_message, message, message_len); + memset(encoded_message + message_len, 0, env->parity_length); + + vGonetsReedSalmonDividePolynomialsR( + env->gf, + message_len + env->parity_length, + env->generative_polynomial, + env->generative_polynomial_len, + encoded_message + message_len + env->parity_length - 1 + ); + + memcpy(encoded_message, message, message_len); +} + +void vGonetsReedSalmonGetLocatorFromErrPos( + tGonetsReedSalmon *env, + tPolyGalois256 *erasures, + tPolyGalois256 *locator_result +) { + + uint8_t prev_buff[1024] = {0}; + uint8_t erasure_sub_buf[2] = {0}; + tPolyGalois256 prev = {.data = prev_buff, .length = 0,}; + tPolyGalois256 erasure_sub = {.data = erasure_sub_buf, .length = 2,}; + erasure_sub.data[0] = 1; + + + locator_result->data[0] = 1; + locator_result->length = 1; + + for (size_t erasures_idx = 0; erasures_idx < erasures->length; ++erasures_idx) { + uint8_t erasure_pow_value = iGalois256PowValue(env->gf, erasures->data[erasures_idx]); + erasure_sub.data[1] = erasure_pow_value; + + vPolyGalois256Mul(env->gf, locator_result, &erasure_sub, &prev); + vPolyGalois256Copy(&prev, locator_result); + + } + +} + +void vGonetsReedSalmonFindLocatorInSyndomes( + tGonetsReedSalmon *env, + tPolyGalois256 *syndromes, + tPolyGalois256 *locator_out +) { + + uint8_t locator_perv_buf[env->parity_length + 1]; + tPolyGalois256 locator_perv = { + .data =locator_perv_buf, + .length = 0, + }; + + + uint8_t locator_next_buf[env->parity_length + 1]; + tPolyGalois256 locator_next = { + .data =locator_next_buf, + .length = 0, + }; + + uint8_t locator_next2_buf[env->parity_length + 1]; + tPolyGalois256 locator_next2 = { + .data =locator_next2_buf, + .length = 0, + }; + + locator_out->data[0] = 1; + locator_out->length = 1; + + locator_perv.data[0] = 1; + locator_perv.length = 1; + + uint8_t syndrome_shift = 0; + + for (uint8_t parity_idx = 0; parity_idx < env->parity_length; parity_idx++) { + + uint8_t k = parity_idx + syndrome_shift; + uint8_t delta = syndromes->data[k]; + + for (size_t locator_idx = 1; locator_idx < locator_out->length; ++locator_idx) { + uint8_t mux = iGalois256Mul(env->gf, locator_out->data[locator_idx], + syndromes->data[parity_idx - locator_idx]); + delta = iGalois256Add(env->gf, delta, mux); + } + + vPolyGalois256MulNumberSelf(env->gf, &locator_perv, 1); + + if (delta != 0) { + + if (locator_perv.length > locator_out->length) { + vPolyGalois256Scale(env->gf, &locator_perv, delta, &locator_next); + vPolyGalois256Scale(env->gf, locator_out, iGalois256Div(env->gf, 1, delta), &locator_perv); + vPolyGalois256Copy(&locator_next, locator_out); + } + + vPolyGalois256Scale(env->gf, &locator_perv, delta, &locator_next2); + vPolyGalois256Add(env->gf, locator_out, &locator_next2, &locator_next); + vPolyGalois256Copy(&locator_next, locator_out); + + } + } +} + +void vGonetsReedSalmonGetErrPosFromLocator( + tGonetsReedSalmon *env, + tPolyGalois256 *locator, + tPolyGalois256 *err_pos_out +) { + err_pos_out->length = 0; + + for (uint16_t arg = 0; arg < 256; ++arg) { + uint8_t value_in_arg = iPolyGalois256Value(env->gf, locator, arg); + if (value_in_arg == 0) { + err_pos_out->data[err_pos_out->length] = iGalois256LogValue(env->gf, iGalois256Div(env->gf, 1, arg)); + ++err_pos_out->length; + } + } +} + +void vGonetsReedSalmonFindMagnitudes( + tGonetsReedSalmon *env, + tPolyGalois256 *syndromes, + tPolyGalois256 *locator, + tPolyGalois256 *err_pos, + tPolyGalois256 *magnitudes_path_out +) { + + uint8_t product_buf[env->parity_length + env->parity_length + 2]; + tPolyGalois256 product = { + .data = product_buf, + .length = 0, + }; + + uint8_t err_buf[env->parity_length + 1]; + tPolyGalois256 err = { + .data = err_buf, + .length = 0, + }; + + uint8_t loc_derivative_buf[env->parity_length + 1]; + tPolyGalois256 loc_derivative = { + .data = loc_derivative_buf, + .length = 0, + }; + + + vPolyGalois256Mul(env->gf, syndromes, locator, &product); + + + memcpy(err.data, product.data, env->parity_length); + err.length = env->parity_length; + + vPolyGalois256FormalDerivative(locator, &loc_derivative); + + magnitudes_path_out->length = err_pos->length; + memset(magnitudes_path_out->data, 0, magnitudes_path_out->length); + + + for (size_t i = 0; i < err_pos->length; ++i) { + + uint8_t err_pos_pow = iGalois256PowValue(env->gf, err_pos->data[i]); + + uint8_t rev = iGalois256Div(env->gf, 1, err_pos_pow); + + uint8_t err_val = iPolyGalois256Value(env->gf, &err, rev); + uint8_t loc_val = iPolyGalois256Value(env->gf, &loc_derivative, rev); + + uint8_t val = iGalois256Div(env->gf, err_val, loc_val); + magnitudes_path_out->data[i] = val; + } + +// printf("product \n"); +// print_arr(product.data, product.length); +// +// printf("err \n"); +// print_arr(err.data, err.length); +// +// printf("loc_derivative \n"); +// print_arr(loc_derivative.data, loc_derivative.length); + +} + +void vGonetsReedSalmonGetSyndromes( + tGonetsReedSalmon *env, + tPolyGalois256 *message, + tPolyGalois256 *syndromes_out +) { + syndromes_out->length = env->parity_length; + + for (uint8_t i = 0; i < env->parity_length; ++i) { + uint8_t pow = iGalois256PowValue(env->gf, i + 1); + syndromes_out->data[i] = iPolyGalois256Value(env->gf, message, pow); + } + +} + +void vGonetsReedSalmonRecovery( + tGonetsReedSalmon *env, + + uint8_t *encoded_message, + uint8_t encoded_message_len, + + uint8_t *recovered_message +) { + + tPolyGalois256 message = { + .data=encoded_message, + .length = encoded_message_len, + }; + + tPolyGalois256 recovered = { + .data=recovered_message, + .length = 0, + }; + + uint8_t syndromes_buf[env->parity_length]; + tPolyGalois256 syndromes = { + .data=syndromes_buf, + .length = 0, + }; + + uint8_t locator_buf[env->parity_length + 1]; + tPolyGalois256 locator = { + .data=locator_buf, + .length = 0, + }; + + + uint8_t err_pos_buf[env->max_fixable_err + 1]; + tPolyGalois256 err_pos = { + .data=err_pos_buf, + .length = 0, + }; + + uint8_t magnitudes_buf[env->max_fixable_err + 1]; + tPolyGalois256 magnitudes_path = { + .data=magnitudes_buf, + .length = 0, + }; + + + vPolyGalois256CopyRevers(&message, &recovered); + + vGonetsReedSalmonGetSyndromes(env, &recovered, &syndromes); + + vGonetsReedSalmonFindLocatorInSyndomes(env, &syndromes, &locator); + vGonetsReedSalmonGetErrPosFromLocator(env, &locator, &err_pos); + + + vGonetsReedSalmonFindMagnitudes(env, &syndromes, &locator, &err_pos, &magnitudes_path); + + + for (size_t i = 0; i < err_pos.length; ++i) { + recovered.data[err_pos.data[i]] = iGalois256Add( + env->gf, + recovered.data[err_pos.data[i]], + magnitudes_path.data[i] + ); + } + + + vPolyGalois256Revers(&recovered); + +// printf("data in\n"); +// print_arr(message.data, message.length); +// +// printf("syndromes\n"); +// print_arr(syndromes.data, syndromes.length); +// +// printf("locator\n"); +// print_arr(locator.data, locator.length); +// +// printf("err_pos_rec\n"); +// print_arr(err_pos.data, err_pos.length); +// +// printf("magnitudes \n"); +// print_arr(magnitudes.data, magnitudes.length); +// +// printf("recovered in\n"); +// print_arr(recovered.data, recovered.length); + +} + +void vGonetsReedSalmonEncode_1410_3430(tGonetsReedSalmon *salmonParity4, uint8_t *data1410) { + uint8_t in[30]; + uint8_t out[34]; + + memset(in, 0, sizeof(in)); + memset(out, 0, sizeof(out)); + memcpy(in, data1410, 10); + + vGonetsReedSalmonEncode(salmonParity4, in, sizeof(in), out); + + memcpy(data1410, out, 10); + memcpy(data1410 + 10, out + 30, 4); +} + + +void vGonetsReedSalmonRecovery_1410_3430(tGonetsReedSalmon *salmonParity4, uint8_t *data1410) { + uint8_t in[34]; + uint8_t out[34]; + + memset(in, 0, sizeof(in)); + memset(out, 0, sizeof(out)); + + memcpy(in, data1410, 10); + memcpy(in + 30, data1410 + 10, 4); + + vGonetsReedSalmonRecovery(salmonParity4, in, sizeof(in), out); + + memcpy(data1410, out, 10); + memcpy(data1410 + 10, out + 30, 4); +} + + diff --git a/GonetsReedSalmon.h b/GonetsReedSalmon.h new file mode 100644 index 0000000..52f9357 --- /dev/null +++ b/GonetsReedSalmon.h @@ -0,0 +1,37 @@ +// +// Created by zemon on 24.07.2022. +// + +#ifndef GonetsReedSalmon_GonetsReedSalmon_H +#define GonetsReedSalmon_GonetsReedSalmon_H + +#include "Galois256.h" + +typedef struct { + tGalois256 *gf; + uint8_t generative_polynomial[32]; + uint8_t generative_polynomial_len; + uint8_t parity_length; + uint8_t max_fixable_err; + +} tGonetsReedSalmon;//fish + +void vGonetsReedSalmonInit(tGonetsReedSalmon *env, tGalois256 *galoisField, uint8_t parity_length); + +void vGonetsReedSalmonEncode(tGonetsReedSalmon *env, const uint8_t *msg, uint8_t msg_len, uint8_t *encoded); + +void vGonetsReedSalmonRecovery( + tGonetsReedSalmon *env, + + uint8_t *encoded_message, + uint8_t encoded_message_len, + + uint8_t *recovered_message +); + + +void vGonetsReedSalmonEncode_1410_3430(tGonetsReedSalmon *salmonParity4, uint8_t *data1410); + +void vGonetsReedSalmonRecovery_1410_3430(tGonetsReedSalmon *salmonParity4, uint8_t *data1410); + +#endif //GonetsReedSalmon_GonetsReedSalmon_H diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..de55294 --- /dev/null +++ b/modular.json @@ -0,0 +1,17 @@ +{ + "dep": [ + { + "type": "git", + "provider": "GONEC", + "repo": "PolyGalois256" + } + ], + "cmake": { + "inc_dirs": [ + "./" + ], + "srcs": [ + "./**.c" + ] + } +} \ No newline at end of file