Merge performance improvements #29
2 changed files with 91 additions and 27 deletions
|
|
@ -8,6 +8,8 @@ use std::{
|
||||||
|
|
||||||
use anyhow::{anyhow, Ok, Result};
|
use anyhow::{anyhow, Ok, Result};
|
||||||
|
|
||||||
|
use crate::utils::poly::bgfmul;
|
||||||
|
|
||||||
use super::poly::polynomial_2_block;
|
use super::poly::polynomial_2_block;
|
||||||
use super::{
|
use super::{
|
||||||
math::{reverse_bits_in_bytevec, xor_bytes},
|
math::{reverse_bits_in_bytevec, xor_bytes},
|
||||||
|
|
@ -21,7 +23,7 @@ pub struct FieldElement {
|
||||||
|
|
||||||
impl FieldElement {
|
impl FieldElement {
|
||||||
pub const IRREDUCIBLE_POLYNOMIAL: [u8; 17] = [
|
pub const IRREDUCIBLE_POLYNOMIAL: [u8; 17] = [
|
||||||
87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 01,
|
0x87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x01,
|
||||||
];
|
];
|
||||||
|
|
||||||
pub fn rand() -> Self {
|
pub fn rand() -> Self {
|
||||||
|
|
@ -29,10 +31,14 @@ impl FieldElement {
|
||||||
FieldElement::new(rand_field.to_vec())
|
FieldElement::new(rand_field.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zero(self) -> Self {
|
pub fn zero() -> Self {
|
||||||
FieldElement::new(vec![0])
|
FieldElement::new(vec![0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn one() -> Self {
|
||||||
|
FieldElement::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn new(field_element: Vec<u8>) -> Self {
|
pub const fn new(field_element: Vec<u8>) -> Self {
|
||||||
Self { field_element }
|
Self { field_element }
|
||||||
}
|
}
|
||||||
|
|
@ -46,8 +52,7 @@ impl FieldElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pow(mut self, mut exponent: u128) -> FieldElement {
|
pub fn pow(mut self, mut exponent: u128) -> FieldElement {
|
||||||
let mut result: FieldElement =
|
let mut result: FieldElement = FieldElement::one();
|
||||||
FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap());
|
|
||||||
|
|
||||||
if exponent == 1 {
|
if exponent == 1 {
|
||||||
eprintln!("special case 1: {:02X?}", self.clone());
|
eprintln!("special case 1: {:02X?}", self.clone());
|
||||||
|
|
@ -56,7 +61,7 @@ impl FieldElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
if exponent == 0 {
|
if exponent == 0 {
|
||||||
let result = FieldElement::new(polynomial_2_block(vec![0], "gcm").unwrap());
|
let result = FieldElement::one();
|
||||||
|
|
||||||
eprintln!("Returned value is: {:02X?}", result);
|
eprintln!("Returned value is: {:02X?}", result);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -89,8 +94,10 @@ impl FieldElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inv(mut self) -> Self {
|
pub fn inv(mut self) -> Self {
|
||||||
let mut inverser: u128 = 0xfffffffffffffffffffffffffffffffe;
|
const INVERSER_START: u128 = 0xfffffffffffffffffffffffffffffffe;
|
||||||
let mut inverse: Vec<u8> = polynomial_2_block(vec![0], "gcm").unwrap();
|
|
||||||
|
let mut inverser = INVERSER_START;
|
||||||
|
let mut inverse: Vec<u8> = vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
//eprintln!("Inverse start {:02X?}", inverse);
|
//eprintln!("Inverse start {:02X?}", inverse);
|
||||||
|
|
||||||
while inverser > 0 {
|
while inverser > 0 {
|
||||||
|
|
@ -186,7 +193,7 @@ impl Div for FieldElement {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn div(self, rhs: Self) -> Self::Output {
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
let inverse = rhs.inv();
|
let inverse = rhs.inv();
|
||||||
self.clone() * inverse
|
self * inverse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,10 +201,7 @@ impl Div for &FieldElement {
|
||||||
type Output = FieldElement;
|
type Output = FieldElement;
|
||||||
|
|
||||||
fn div(self, rhs: Self) -> Self::Output {
|
fn div(self, rhs: Self) -> Self::Output {
|
||||||
// First clone and invert the divisor (rhs)
|
self.clone() * rhs.clone().inv()
|
||||||
let rhs_inv = rhs.clone().inv();
|
|
||||||
// Multiply original number by the inverse
|
|
||||||
self.clone() * rhs_inv
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::utils::field::ByteArray;
|
use crate::utils::field::ByteArray;
|
||||||
use base64::prelude::*;
|
use base64::prelude::*;
|
||||||
use num::{BigUint, One, Zero};
|
|
||||||
|
use num::traits::FromBytes;
|
||||||
|
use num::{BigInt, BigUint, One, Zero};
|
||||||
|
|
||||||
use std::{str::FromStr, u128, u8, usize};
|
use std::{str::FromStr, u128, u8, usize};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -12,6 +15,7 @@ use anyhow::{anyhow, Ok, Result};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use super::field::FieldElement;
|
use super::field::FieldElement;
|
||||||
|
use super::math::reverse_bits_in_bytevec;
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Polynomial {
|
pub struct Polynomial {
|
||||||
|
|
@ -290,10 +294,7 @@ impl Polynomial {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut quotient_coeffs =
|
let mut quotient_coeffs =
|
||||||
vec![
|
vec![FieldElement::new(vec![0; 16]); dividend_deg - divisor_deg + 1];
|
||||||
FieldElement::new(polynomial_2_block(vec![0; 16], "gcm").unwrap());
|
|
||||||
dividend_deg - divisor_deg + 1
|
|
||||||
];
|
|
||||||
|
|
||||||
while remainder.polynomial.len() >= divisor.polynomial.len() {
|
while remainder.polynomial.len() >= divisor.polynomial.len() {
|
||||||
let deg_diff = remainder.polynomial.len() - divisor.polynomial.len();
|
let deg_diff = remainder.polynomial.len() - divisor.polynomial.len();
|
||||||
|
|
@ -304,8 +305,7 @@ impl Polynomial {
|
||||||
|
|
||||||
quotient_coeffs[deg_diff] = quot_coeff.clone();
|
quotient_coeffs[deg_diff] = quot_coeff.clone();
|
||||||
|
|
||||||
let mut subtrahend =
|
let mut subtrahend = vec![FieldElement::new(vec![0; 16]); deg_diff];
|
||||||
vec![FieldElement::new(polynomial_2_block(vec![0; 16], "gcm").unwrap()); deg_diff];
|
|
||||||
subtrahend.extend(
|
subtrahend.extend(
|
||||||
divisor
|
divisor
|
||||||
.polynomial
|
.polynomial
|
||||||
|
|
@ -614,20 +614,20 @@ pub const RED_POLY: u128 = 0x87000000_00000000_00000000_00000000;
|
||||||
|
|
||||||
pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
|
pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
|
||||||
let mut red_poly_bytes: ByteArray = ByteArray(RED_POLY.to_be_bytes().to_vec());
|
let mut red_poly_bytes: ByteArray = ByteArray(RED_POLY.to_be_bytes().to_vec());
|
||||||
red_poly_bytes.0.push(0x01);
|
//red_poly_bytes.0.push(0x01);
|
||||||
|
|
||||||
let mut poly1: ByteArray = ByteArray(poly_a.to_owned());
|
let mut poly1: ByteArray = ByteArray(poly_a.to_owned());
|
||||||
poly1.0.push(0x00);
|
//poly1.0.push(0x00);
|
||||||
|
|
||||||
let mut poly2: ByteArray = ByteArray(poly_b.to_owned());
|
let mut poly2: ByteArray = ByteArray(poly_b.to_owned());
|
||||||
poly2.0.push(0x00);
|
//poly2.0.push(0x00);
|
||||||
|
|
||||||
if semantic == "gcm" {
|
if semantic == "gcm" {
|
||||||
poly1.reverse_bits_in_bytevec();
|
poly1.reverse_bits_in_bytevec();
|
||||||
poly2.reverse_bits_in_bytevec();
|
poly2.reverse_bits_in_bytevec();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
let mut result: ByteArray = ByteArray(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
|
|
||||||
if poly2.LSB_is_one() {
|
if poly2.LSB_is_one() {
|
||||||
result.xor_byte_arrays(&poly1);
|
result.xor_byte_arrays(&poly1);
|
||||||
|
|
@ -635,9 +635,9 @@ pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u
|
||||||
poly2.right_shift("xex")?;
|
poly2.right_shift("xex")?;
|
||||||
|
|
||||||
while !poly2.is_empty() {
|
while !poly2.is_empty() {
|
||||||
poly1.left_shift("xex")?;
|
let carry = poly1.left_shift("xex")?;
|
||||||
|
|
||||||
if poly1.msb_is_one() {
|
if carry == 1 {
|
||||||
poly1.xor_byte_arrays(&red_poly_bytes);
|
poly1.xor_byte_arrays(&red_poly_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -648,7 +648,7 @@ pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u
|
||||||
poly2.right_shift("xex")?;
|
poly2.right_shift("xex")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.0.remove(16);
|
//result.0.remove(16);
|
||||||
|
|
||||||
if semantic == "gcm" {
|
if semantic == "gcm" {
|
||||||
result.reverse_bits_in_bytevec();
|
result.reverse_bits_in_bytevec();
|
||||||
|
|
@ -657,6 +657,53 @@ pub fn gfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u
|
||||||
Ok(result.0)
|
Ok(result.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bgfmul(poly_a: &Vec<u8>, poly_b: &Vec<u8>, semantic: &str) -> Result<Vec<u8>> {
|
||||||
|
//TODO: Implement gfmul with bigint
|
||||||
|
let red_poly_bytes: BigUint = BigUint::from_slice(&[
|
||||||
|
0x87, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0x01,
|
||||||
|
]);
|
||||||
|
|
||||||
|
let mut poly1: BigUint = BigUint::from_le_bytes(&reverse_bits_in_bytevec(poly_a.to_owned()));
|
||||||
|
|
||||||
|
let mut poly2: BigUint = BigUint::from_le_bytes(&reverse_bits_in_bytevec(poly_b.to_owned()));
|
||||||
|
|
||||||
|
/*
|
||||||
|
if semantic == "gcm" {
|
||||||
|
poly1.re;
|
||||||
|
poly2.reverse_bits_in_bytevec();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
let mut result: BigUint = BigUint::zero();
|
||||||
|
|
||||||
|
if (&poly2 & (BigUint::one() << 127)) == BigUint::one() {
|
||||||
|
result = &result ^ &poly1;
|
||||||
|
}
|
||||||
|
poly2 = &poly2 >> 1;
|
||||||
|
|
||||||
|
while &poly2 != &BigUint::zero() {
|
||||||
|
poly1 = &poly1 << 1;
|
||||||
|
|
||||||
|
if (&poly1 & (BigUint::one() << 127)) == BigUint::one() {
|
||||||
|
poly1 = &poly1 ^ &red_poly_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if &poly2 & BigUint::one() == BigUint::one() {
|
||||||
|
result = &result ^ &poly1;
|
||||||
|
}
|
||||||
|
|
||||||
|
poly2 = &poly2 >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if semantic == "gcm" {
|
||||||
|
result.reverse_bits_in_bytevec();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Ok(reverse_bits_in_bytevec(result.to_bytes_le()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn convert_gcm_to_xex(gcm_poly: Vec<u8>) -> Result<Vec<u8>> {
|
pub fn convert_gcm_to_xex(gcm_poly: Vec<u8>) -> Result<Vec<u8>> {
|
||||||
let xex_poly = gcm_poly
|
let xex_poly = gcm_poly
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -794,7 +841,7 @@ pub fn coefficient_to_binary(coefficients: Vec<u8>) -> u128 {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::utils::poly::b64_2_num;
|
use crate::utils::poly::{b64_2_num, gcd};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
// Note this useful idiom: importing names from outer (for mod tests) scope.
|
||||||
|
|
@ -1428,4 +1475,17 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(json!(result.to_c_array()), expected);
|
assert_eq!(json!(result.to_c_array()), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_poly_gcd_stress() {
|
||||||
|
eprintln!("{:?}", Polynomial::one());
|
||||||
|
|
||||||
|
let poly1 = Polynomial::rand(&(500 as usize));
|
||||||
|
let poly2 = Polynomial::rand(&(500 as usize));
|
||||||
|
|
||||||
|
let result = gcd(&poly1.monic(), &poly2.monic());
|
||||||
|
|
||||||
|
eprintln!("{:02X?}", result.to_c_array());
|
||||||
|
assert!(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue