Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ pub trait PrimeField: Field {

fn make_cfg(modulus: &Self::Inner) -> Result<Self::Config, FieldError>;

/// Creates a new instance of a prime field element from
/// an arbitrary element of `Self::Inner`. The method
/// should not assume the `Self::Inner` is coming in a
/// form internally used by the field type. So it
/// always should perform a reduction first.
fn new_with_cfg(inner: Self::Inner, cfg: &Self::Config) -> Self;

/// Creates a new instance of the prime field element from a representation
/// known to be valid - should consume exactly the value returned by
/// `inner()`. Ideally, this should not check the validity of the
Expand All @@ -83,6 +90,13 @@ pub trait ConstPrimeField:
const MODULUS: Self::Inner;
const MODULUS_MINUS_ONE_DIV_TWO: Self::Inner;

/// Creates a new instance of a prime field element from
/// an arbitrary element of `Self::Inner`. The method
/// should not assume the `Self::Inner` is coming in a
/// form internally used by the field type. So it
/// always should perform a reduction first.
fn new(inner: Self::Inner) -> Self;

/// Creates a new instance of the prime field element from a representation
/// known to be valid - should consume exactly the value returned by
/// `inner()`. Ideally, this should not check the validity of the
Expand Down Expand Up @@ -117,6 +131,11 @@ impl<T: ConstPrimeField> PrimeField for T {
}
}

#[inline(always)]
fn new_with_cfg(inner: Self::Inner, _cfg: &Self::Config) -> Self {
ConstPrimeField::new(inner)
}

#[inline(always)]
fn new_unchecked_with_cfg(inner: Self::Inner, _cfg: &Self::Config) -> Self {
ConstPrimeField::new_unchecked(inner)
Expand Down
4 changes: 4 additions & 0 deletions src/field/ark_ff_fp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,10 @@ impl<M: MontConfig<N>, const N: usize> ConstPrimeField for Fp<MontBackend<M, N>,
const MODULUS_MINUS_ONE_DIV_TWO: Self::Inner =
<ArkWrappedFp<MontBackend<M, N>, N> as ArkPrimeField>::MODULUS_MINUS_ONE_DIV_TWO;

fn new(inner: Self::Inner) -> Self {
Self(ArkWrappedFp::new(inner))
}

fn new_unchecked(inner: Self::Inner) -> Self {
Self(ArkWrappedFp::new_unchecked(inner))
}
Expand Down
17 changes: 17 additions & 0 deletions src/field/crypto_bigint_boxed_monty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,10 @@ impl PrimeField for BoxedMontyField {
Ok(BoxedMontyParams::new(modulus))
}

fn new_with_cfg(inner: Self::Inner, cfg: &Self::Config) -> Self {
Self(BoxedMontyForm::new(inner, cfg.clone()))
}

fn new_unchecked_with_cfg(inner: Self::Inner, cfg: &Self::Config) -> Self {
Self(BoxedMontyForm::from_montgomery(inner, cfg.clone()))
}
Expand Down Expand Up @@ -515,6 +519,19 @@ mod tests {
F::one_with_cfg(&test_config())
}

#[test]
fn new_with_cfg_correct() {
let x = BoxedUint::from_be_hex(
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30",
256,
)
.unwrap();

let y = F::new_with_cfg(x, &test_config());

assert_eq!(y, F::one_with_cfg(&test_config()));
}

#[test]
fn zero_one_basics() {
let z = zero();
Expand Down
50 changes: 34 additions & 16 deletions src/field/crypto_bigint_const_monty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,23 @@ impl<Mod: Params<LIMBS>, const LIMBS: usize> ConstMontyField<Mod, LIMBS> {
pub const LIMBS: usize = Mod::LIMBS;

#[inline(always)]
pub const fn new(value: ConstMontyForm<Mod, LIMBS>) -> Self {
Self(value)
pub const fn new(value: Uint<LIMBS>) -> Self {
Self(ConstMontyForm::new(value.inner()))
}

#[inline(always)]
pub const fn inner(&self) -> &ConstMontyForm<Mod, LIMBS> {
&self.0
pub const fn new_unchecked(inner: Uint<LIMBS>) -> Self {
Self(ConstMontyForm::from_montgomery(inner.into_inner()))
}

#[inline(always)]
pub const fn into_inner(self) -> ConstMontyForm<Mod, LIMBS> {
self.0
pub const fn inner(&self) -> &Uint<LIMBS> {
Uint::new_ref(self.0.as_montgomery())
}

#[inline(always)]
pub const fn into_inner(self) -> Uint<LIMBS> {
Uint::new(self.0.to_montgomery())
}

/// Retrieves the integer currently encoded in this [`ConstMontyForm`],
Expand All @@ -53,12 +58,12 @@ impl<Mod: Params<LIMBS>, const LIMBS: usize> ConstMontyField<Mod, LIMBS> {
Uint::new(self.0.retrieve())
}

/// Access the `ConstMontyForm` value in Montgomery form.
/// Access the value in Montgomery form.
pub const fn as_montgomery(&self) -> &Uint<LIMBS> {
Uint::new_ref(self.0.as_montgomery())
}

/// Mutably access the `ConstMontyForm` value in Montgomery form.
/// Mutably access the value in Montgomery form.
pub fn as_montgomery_mut(&mut self) -> &mut Uint<LIMBS> {
Uint::new_ref_mut(self.0.as_montgomery_mut())
}
Expand Down Expand Up @@ -524,6 +529,11 @@ impl<Mod: Params<LIMBS>, const LIMBS: usize> ConstPrimeField for ConstMontyField
))
};

#[inline(always)]
fn new(inner: Self::Inner) -> Self {
Self(ConstMontyForm::new(inner.inner()))
}

#[inline(always)]
fn new_unchecked(inner: Self::Inner) -> Self {
Self(ConstMontyForm::from_montgomery(inner.into_inner()))
Expand Down Expand Up @@ -599,11 +609,7 @@ impl<Mod: Params<LIMBS>, const LIMBS: usize> ConditionallySelectable
{
#[inline(always)]
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
Self(ConstMontyForm::conditional_select(
a.inner(),
b.inner(),
choice,
))
Self(ConstMontyForm::conditional_select(&a.0, &b.0, choice))
}
}

Expand Down Expand Up @@ -694,6 +700,17 @@ mod tests {
ensure_type_implements_trait!(F, FromPrimitiveWithConfig);
}

#[test]
fn new_with_cfg_correct() {
let x = Uint::new(U256::from_be_hex(
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30",
));

let y = F::new(x);

assert_eq!(y, F::one());
}

#[test]
fn zero_one_basics() {
let z = F::zero();
Expand Down Expand Up @@ -1020,8 +1037,9 @@ mod tests {

#[test]
fn wrapper_methods() {
let value = ConstMontyForm::new(Uint::from(42_u64).inner());
let field = F::new(value);
let value =
Uint::new(ConstMontyForm::<ModP, 4>::new(&CBUint::from_u64(42)).to_montgomery());
let field = F::new_unchecked(value);

// Test inner and into_inner
assert_eq!(field.inner(), &value);
Expand Down Expand Up @@ -1184,7 +1202,7 @@ mod tests {
// Conversions from and to ConstMontyForm
let mont_form = ConstMontyForm::new(Uint::<{ U256::LIMBS }>::from(999_u64).inner());
let f: F = mont_form.into();
let f2 = F::new(mont_form);
let f2 = F::new(Uint::new(mont_form.retrieve()));
assert_eq!(f, f2);
assert_eq!(mont_form, f.into());
}
Expand Down
75 changes: 75 additions & 0 deletions src/field/crypto_bigint_monty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,70 @@ pub struct MontyField<const LIMBS: usize>(MontyForm<LIMBS>);

impl<const LIMBS: usize> MontyField<LIMBS> {
/// Creates a new `MontyField` from a `MontyForm`.
#[inline(always)]
pub const fn new(form: MontyForm<LIMBS>) -> Self {
Self(form)
}

#[inline(always)]
pub const fn new_unchecked(inner: Uint<LIMBS>, config: &MontyParams<LIMBS>) -> Self {
Self(MontyForm::from_montgomery(inner.into_inner(), *config))
}

#[inline(always)]
pub const fn inner(&self) -> &Uint<LIMBS> {
Uint::new_ref(self.0.as_montgomery())
}

#[inline(always)]
pub const fn into_inner(self) -> Uint<LIMBS> {
Uint::new(self.0.to_montgomery())
}

/// Retrieves the integer currently encoded in this [`MontyForm`],
/// guaranteed to be reduced.
pub const fn retrieve(&self) -> Uint<LIMBS> {
Uint::new(self.0.retrieve())
}

/// Access the value in Montgomery form.
pub const fn as_montgomery(&self) -> &Uint<LIMBS> {
Uint::new_ref(self.0.as_montgomery())
}

/// Mutably access the value in Montgomery form.
pub fn as_montgomery_mut(&mut self) -> &mut Uint<LIMBS> {
Uint::new_ref_mut(self.0.as_montgomery_mut())
}

/// Create a `MontyField` from a value in Montgomery form.
pub const fn from_montgomery(integer: Uint<LIMBS>, config: &MontyParams<LIMBS>) -> Self {
Self(MontyForm::from_montgomery(integer.into_inner(), *config))
}

/// Extract the value from the `MontyForm` in Montgomery form.
pub const fn to_montgomery(&self) -> Uint<LIMBS> {
Uint::new(self.0.to_montgomery())
}

/// Performs division by 2, that is returns `x` such that `x + x = self`.
pub const fn div_by_2(&self) -> Self {
Self(self.0.div_by_2())
}

/// Double `self`.
pub const fn double(&self) -> Self {
Self(self.0.double())
}

/// See [MontyForm::pow_bounded_exp].
pub const fn pow_bounded_exp<const RHS_LIMBS: usize>(
&self,
exponent: &Uint<RHS_LIMBS>,
exponent_bits: u32,
) -> Self {
Self(self.0.pow_bounded_exp(exponent.inner(), exponent_bits))
}
}

//
Expand Down Expand Up @@ -454,6 +515,10 @@ impl<const LIMBS: usize> PrimeField for MontyField<LIMBS> {
Ok(MontyParams::new(modulus))
}

fn new_with_cfg(inner: Self::Inner, cfg: &Self::Config) -> Self {
Self(MontyForm::new(inner.inner(), *cfg))
}

fn new_unchecked_with_cfg(inner: Self::Inner, cfg: &Self::Config) -> Self {
Self(MontyForm::from_montgomery(inner.into_inner(), *cfg))
}
Expand Down Expand Up @@ -526,6 +591,16 @@ mod tests {
MontyParams::new(modulus)
}

#[test]
fn new_with_cfg_correct() {
let x =
Uint::from_be_hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30");

let y = F::new_with_cfg(x, &test_config());

assert_eq!(y, F::one_with_cfg(&test_config()));
}

fn from_u64(value: u64) -> F {
F::from_with_cfg(value, &test_config())
}
Expand Down
Loading