Skip to content

Commit

Permalink
polynomial: use FieldVec in Polynomial
Browse files Browse the repository at this point in the history
We can now use `PrintImpl` even without an allocator. This is of limited
use of course, but it paves the ground for use to do error correction
without an allocator, which is interesting.
  • Loading branch information
apoelstra committed Sep 22, 2024
1 parent f2ec582 commit 690fc7d
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 141 deletions.
33 changes: 9 additions & 24 deletions src/primitives/checksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@
//!
//! [BCH]: <https://en.wikipedia.org/wiki/BCH_code>
#[cfg(all(feature = "alloc", not(feature = "std"), not(test)))]
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;
#[cfg(feature = "alloc")]
use core::fmt;
#[cfg(feature = "alloc")]
use core::marker::PhantomData;
use core::{mem, ops};
use core::{fmt, mem, ops};

#[cfg(feature = "alloc")]
use super::Polynomial;
use crate::primitives::hrp::Hrp;
#[cfg(feature = "alloc")]
use crate::Fe1024;
use crate::Fe32;
use crate::{Fe1024, Fe32};

/// Trait defining a particular checksum.
///
Expand Down Expand Up @@ -169,18 +163,16 @@ pub trait Checksum {
/// to compute the values yourself. The reason is that the specific values
/// used depend on the representation of extension fields, which may differ
/// between implementations (and between specifications) of your BCH code.
#[cfg(feature = "alloc")]
pub struct PrintImpl<'a, ExtField = Fe1024> {
name: &'a str,
generator: &'a [Fe32],
generator: Polynomial<Fe32>,
target: &'a [Fe32],
bit_len: usize,
hex_width: usize,
midstate_repr: &'static str,
phantom: PhantomData<ExtField>,
}

#[cfg(feature = "alloc")]
impl<'a, ExtField> PrintImpl<'a, ExtField> {
/// Constructor for an object to print an impl-block for the [`Checksum`] trait.
///
Expand Down Expand Up @@ -225,7 +217,7 @@ impl<'a, ExtField> PrintImpl<'a, ExtField> {
// End sanity checks.
PrintImpl {
name,
generator,
generator: Polynomial::with_monic_leading_term(generator),
target,
bit_len,
hex_width,
Expand All @@ -235,23 +227,16 @@ impl<'a, ExtField> PrintImpl<'a, ExtField> {
}
}

#[cfg(feature = "alloc")]
impl<'a, ExtField> fmt::Display for PrintImpl<'a, ExtField>
where
ExtField: super::Bech32Field + super::ExtensionField<BaseField = Fe32>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Generator polynomial as a polynomial over GF1024
let gen_poly = {
let mut v = Vec::with_capacity(self.generator.len() + 1);
v.push(ExtField::ONE);
v.extend(self.generator.iter().cloned().map(ExtField::from));
Polynomial::new(v)
};
let (gen, length, exponents) = gen_poly.bch_generator_primitive_element();
let (gen, length, exponents) = self.generator.bch_generator_primitive_element::<ExtField>();

write!(f, "// Code block generated by Checksum::print_impl polynomial ")?;
for fe in self.generator {
for fe in self.generator.as_inner() {
write!(f, "{}", fe)?;
}
write!(f, " target ")?;
Expand All @@ -278,9 +263,9 @@ where
)?;
f.write_str("\n")?;
writeln!(f, " const CODE_LENGTH: usize = {};", length)?;
writeln!(f, " const CHECKSUM_LENGTH: usize = {};", gen_poly.degree())?;
writeln!(f, " const CHECKSUM_LENGTH: usize = {};", self.generator.degree())?;
writeln!(f, " const GENERATOR_SH: [{}; 5] = [", self.midstate_repr)?;
let mut gen5 = self.generator.to_vec();
let mut gen5 = self.generator.clone().into_inner();
for _ in 0..5 {
let gen_packed = u128::pack(gen5.iter().copied().map(From::from));
writeln!(f, " 0x{:0width$x},", gen_packed, width = self.hex_width)?;
Expand Down
28 changes: 28 additions & 0 deletions src/primitives/fieldvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,34 @@ impl<F: Field> FieldVec<F> {
}
}

impl<F: Default> FieldVec<F> {
/// Pushes an item onto the end of the vector.
///
/// # Panics
///
/// Panics if [`Self::has_data`] is false, or if it would be false after the push.
pub fn push(&mut self, item: F) {
self.len += 1;
self.assert_has_data();

#[cfg(not(feature = "alloc"))]
{
self.inner_a[self.len - 1] = item;
}

#[cfg(feature = "alloc")]
if self.len < NO_ALLOC_MAX_LENGTH + 1 {
self.inner_a[self.len - 1] = item;
} else {
if self.len == NO_ALLOC_MAX_LENGTH + 1 {
let inner_a = core::mem::take(&mut self.inner_a);
self.inner_v = inner_a.into();
}
self.inner_v.push(item);
}
}
}

impl<F: Clone + Default> iter::FromIterator<F> for FieldVec<F> {
/// Constructor from an iterator of elements.
///
Expand Down
3 changes: 1 addition & 2 deletions src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@ pub mod gf32;
pub mod gf32_ext;
pub mod hrp;
pub mod iter;
#[cfg(feature = "alloc")]
mod polynomial;
pub mod segwit;

use checksum::{Checksum, PackedNull};
use field::impl_ops_for_fe;
pub use field::{Bech32Field, ExtensionField, Field};
#[cfg(feature = "alloc")]
use fieldvec::FieldVec;
use polynomial::Polynomial;

use crate::{Fe1024, Fe32};
Expand Down
Loading

0 comments on commit 690fc7d

Please sign in to comment.