use super::*;
impl<E: Environment> CastLossy<Address<E>> for Field<E> {
#[inline]
fn cast_lossy(&self) -> Address<E> {
let group: Group<E> = self.cast_lossy();
Address::from_group(group)
}
}
impl<E: Environment> CastLossy<Boolean<E>> for Field<E> {
#[inline]
fn cast_lossy(&self) -> Boolean<E> {
let bits_le = self.to_bits_le();
debug_assert!(!bits_le.is_empty(), "An integer must have at least one bit");
bits_le[0].clone()
}
}
impl<E: Environment> CastLossy<Field<E>> for Field<E> {
#[inline]
fn cast_lossy(&self) -> Field<E> {
self.clone()
}
}
impl<E: Environment> CastLossy<Group<E>> for Field<E> {
#[inline]
fn cast_lossy(&self) -> Group<E> {
debug_assert!(console::Group::from_x_coordinate(<console::Field<E::Network> as console::One>::one()).is_err());
let (point_with_x, x_is_not_in_group) = Group::from_x_coordinate_flagged(self.clone());
let is_x_zero = self.is_zero();
let is_x_one = self.is_one();
let generator = Group::generator();
let elligator_input = Field::ternary(&is_x_zero, &Field::one(), self);
let elligator_point = Elligator2::encode(&elligator_input);
let generator_or_elligator_point = Group::ternary(&is_x_one, &generator, &elligator_point);
Group::ternary(&x_is_not_in_group, &generator_or_elligator_point, &point_with_x)
}
}
impl<E: Environment, I: IntegerType> CastLossy<Integer<E, I>> for Field<E> {
#[inline]
fn cast_lossy(&self) -> Integer<E, I> {
Integer::from_field_lossy(self)
}
}
impl<E: Environment> CastLossy<Scalar<E>> for Field<E> {
#[inline]
fn cast_lossy(&self) -> Scalar<E> {
Scalar::from_field_lossy(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
use console::CastLossy as _;
use console_root::{
network::MainnetV0,
prelude::{One, TestRng, Uniform, Zero},
};
use snarkvm_circuit_types::environment::{Circuit, Eject, Inject, Mode, UpdatableCount, count_is, count_less_than};
use std::fmt::Debug;
const ITERATIONS: usize = 100;
fn sample_values(
i: usize,
mode: Mode,
rng: &mut TestRng,
) -> (console_root::types::Field<MainnetV0>, Field<Circuit>) {
let console_value = match i {
0 => console_root::types::Field::<MainnetV0>::zero(),
1 => console_root::types::Field::<MainnetV0>::one(),
_ => Uniform::rand(rng),
};
let circuit_value = Field::<Circuit>::new(mode, console_value);
(console_value, circuit_value)
}
check_cast_lossy!(cast_lossy, Field<Circuit>, console_root::types::Field::<MainnetV0>);
#[test]
fn test_field_to_address() {
check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
Mode::Constant,
count_less_than!(4303, 0, 0, 0),
);
check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
Mode::Public,
count_is!(2029, 0, 6745, 6750),
);
check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
Mode::Private,
count_is!(2029, 0, 6745, 6750),
);
}
#[test]
fn test_field_to_boolean() {
check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
Mode::Constant,
count_is!(253, 0, 0, 0),
);
check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
Mode::Public,
count_is!(0, 0, 505, 507),
);
check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
Mode::Private,
count_is!(0, 0, 505, 507),
);
}
#[test]
fn test_field_to_field() {
check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(
Mode::Constant,
count_is!(0, 0, 0, 0),
);
check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(Mode::Public, count_is!(0, 0, 0, 0));
check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(Mode::Private, count_is!(0, 0, 0, 0));
}
#[test]
fn test_field_to_group() {
check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(
Mode::Constant,
count_less_than!(4303, 0, 0, 0),
);
check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(
Mode::Public,
count_is!(2029, 0, 6745, 6750),
);
check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(
Mode::Private,
count_is!(2029, 0, 6745, 6750),
);
}
#[test]
fn test_field_to_i8() {
check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
}
#[test]
fn test_field_to_i16() {
check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
}
#[test]
fn test_field_to_i32() {
check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
}
#[test]
fn test_field_to_i64() {
check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
}
#[test]
fn test_field_to_i128() {
check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(
Mode::Constant,
count_is!(253, 0, 0, 0),
);
check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(
Mode::Public,
count_is!(0, 0, 505, 507),
);
check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(
Mode::Private,
count_is!(0, 0, 505, 507),
);
}
#[test]
fn test_field_to_scalar() {
check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
Mode::Constant,
count_is!(253, 0, 0, 0),
);
check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
Mode::Public,
count_is!(0, 0, 505, 507),
);
check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
Mode::Private,
count_is!(0, 0, 505, 507),
);
}
#[test]
fn test_field_to_u8() {
check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
}
#[test]
fn test_field_to_u16() {
check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
}
#[test]
fn test_field_to_u32() {
check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
}
#[test]
fn test_field_to_u64() {
check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
}
#[test]
fn test_field_to_u128() {
check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(
Mode::Constant,
count_is!(253, 0, 0, 0),
);
check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(
Mode::Public,
count_is!(0, 0, 505, 507),
);
check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(
Mode::Private,
count_is!(0, 0, 505, 507),
);
}
}