#ifndef CORRECT_REED_SOLOMON
#define CORRECT_REED_SOLOMON
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <stdint.h>

#include "correct.h"
#include "portable.h"

// an element in GF(2^8)
typedef uint8_t field_element_t;

// a power of the primitive element alpha
typedef uint8_t field_logarithm_t;

// give us some bits of headroom to do arithmetic
// variables of this type aren't really in any proper space
typedef uint16_t field_operation_t;

// generated by find_poly
typedef struct {
    const field_element_t *exp;
    const field_logarithm_t *log;
} field_t;

typedef struct {
    field_element_t *coeff;
    unsigned int order;
} polynomial_t;

struct correct_reed_solomon {
    size_t block_length;
    size_t message_length;
    size_t min_distance;

    field_logarithm_t first_consecutive_root;
    field_logarithm_t generator_root_gap;

    field_t field;

    polynomial_t generator;
    field_element_t *generator_roots;
    field_logarithm_t **generator_root_exp;

    polynomial_t encoded_polynomial;
    polynomial_t encoded_remainder;

    field_element_t *syndromes;
    field_element_t *modified_syndromes;
    polynomial_t received_polynomial;
    polynomial_t error_locator;
    polynomial_t error_locator_log;
    polynomial_t erasure_locator;
    field_element_t *error_roots;
    field_element_t *error_vals;
    field_logarithm_t *error_locations;

    field_logarithm_t **element_exp;

    // scratch
    // (do no allocations at steady state)

    // used during find_error_locator
    polynomial_t last_error_locator;

    // used during error value search
    polynomial_t error_evaluator;
    polynomial_t error_locator_derivative;
    polynomial_t init_from_roots_scratch[2];
    bool has_init_decode;

};
#endif
