use std::fmt;
use crate::Exceptions;
use crate::common::Result;
use super::{GenericGFPoly, GenericGFRef};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GenericGF {
expTable: Vec<i32>,
logTable: Vec<i32>,
size: usize,
primitive: i32,
generatorBase: i32,
}
impl GenericGF {
pub fn new(primitive: i32, size: usize, b: i32) -> Self {
let mut expTable = vec![0; size];
let mut logTable = vec![0; size];
let mut x = 1;
for expTableEntry in expTable.iter_mut().take(size) {
*expTableEntry = x;
x *= 2; if x >= size as i32 {
x ^= primitive;
let sz_m_1: i32 = size as i32 - 1;
x &= sz_m_1;
}
}
for (i, loc) in expTable.iter().enumerate().take(size - 1) {
logTable[*loc as usize] = i as i32;
}
logTable[0] = 0;
Self {
expTable,
logTable,
size,
primitive,
generatorBase: b,
}
}
pub fn buildMonomial(source: GenericGFRef, degree: usize, coefficient: i32) -> GenericGFPoly {
if coefficient == 0 {
return GenericGFPoly::new(source, &[0]).unwrap();
}
let mut coefficients = vec![0; degree + 1];
coefficients[0] = coefficient;
GenericGFPoly::new(source, &coefficients).unwrap()
}
pub const fn addOrSubtract(a: i32, b: i32) -> i32 {
a ^ b
}
pub fn exp(&self, a: i32) -> i32 {
self.expTable[a as usize]
}
pub fn log(&self, a: i32) -> Result<i32> {
if a == 0 {
return Err(Exceptions::ILLEGAL_ARGUMENT);
}
Ok(self.logTable[a as usize])
}
pub fn inverse(&self, a: i32) -> Result<i32> {
if a == 0 {
return Err(Exceptions::ARITHMETIC);
}
let log_t_loc: usize = a as usize;
let loc: usize = ((self.size as i32) - self.logTable[log_t_loc] - 1) as usize;
Ok(self.expTable[loc])
}
pub fn multiply(&self, a: i32, b: i32) -> i32 {
if a == 0 || b == 0 {
return 0;
}
let a_loc: usize = a as usize; let b_loc: usize = b as usize; let comb_loc: usize = (self.logTable[a_loc] + self.logTable[b_loc]) as usize;
self.expTable[comb_loc % (self.size - 1)]
}
pub const fn getSize(&self) -> usize {
self.size
}
pub const fn getGeneratorBase(&self) -> i32 {
self.generatorBase
}
}
impl fmt::Display for GenericGF {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "GF({:#06x},{}", self.primitive, self.size)
}
}