use super::*;
impl<E: Environment, I: IntegerType> FromBits for Integer<E, I> {
type Boolean = Boolean<E>;
fn from_bits_le(bits_le: &[Self::Boolean]) -> Self {
let num_bits = bits_le.len() as u64;
if num_bits > I::BITS {
for bit in &bits_le[I::BITS as usize..] {
E::assert_eq(E::zero(), bit);
}
}
let mut bits_le = bits_le.iter().take(I::BITS as usize).cloned().collect::<Vec<_>>();
bits_le.resize(I::BITS as usize, Boolean::constant(false));
Self { bits_le, phantom: Default::default() }
}
fn from_bits_be(bits_be: &[Self::Boolean]) -> Self {
let mut bits_le = bits_be.to_vec();
bits_le.reverse();
Self::from_bits_le(&bits_le)
}
}
#[cfg(test)]
mod tests {
use super::*;
use snarkvm_circuit_environment::Circuit;
const ITERATIONS: u64 = 128;
fn check_from_bits_le<I: IntegerType>(
mode: Mode,
num_constants: u64,
num_public: u64,
num_private: u64,
num_constraints: u64,
) {
let mut rng = TestRng::default();
for i in 0..ITERATIONS {
let expected = Uniform::rand(&mut rng);
let given_bits = Integer::<Circuit, I>::new(mode, expected).to_bits_le();
let expected_size_in_bits = given_bits.len();
Circuit::scope(&format!("{mode} {i}"), || {
let candidate = Integer::<Circuit, I>::from_bits_le(&given_bits);
assert_eq!(expected, candidate.eject_value());
assert_eq!(expected_size_in_bits, candidate.bits_le.len());
assert_scope!(num_constants, num_public, num_private, num_constraints);
});
let candidate = vec![given_bits, vec![Boolean::new(mode, false); i as usize]].concat();
Circuit::scope(&format!("Excess {mode} {i}"), || {
let candidate = Integer::<Circuit, I>::from_bits_le(&candidate);
assert_eq!(expected, candidate.eject_value());
assert_eq!(expected_size_in_bits, candidate.bits_le.len());
match mode.is_constant() {
true => assert_scope!(num_constants, num_public, num_private, num_constraints),
false => {
assert_scope!(num_constants, num_public, num_private, num_constraints + i)
}
};
});
}
}
fn check_from_bits_be<I: IntegerType>(
mode: Mode,
num_constants: u64,
num_public: u64,
num_private: u64,
num_constraints: u64,
) {
let mut rng = TestRng::default();
for i in 0..ITERATIONS {
let expected = Uniform::rand(&mut rng);
let given_bits = Integer::<Circuit, I>::new(mode, expected).to_bits_be();
let expected_size_in_bits = given_bits.len();
Circuit::scope(&format!("{mode} {i}"), || {
let candidate = Integer::<Circuit, I>::from_bits_be(&given_bits);
assert_eq!(expected, candidate.eject_value());
assert_eq!(expected_size_in_bits, candidate.bits_le.len());
assert_scope!(num_constants, num_public, num_private, num_constraints);
});
let candidate = vec![vec![Boolean::new(mode, false); i as usize], given_bits].concat();
Circuit::scope(&format!("Excess {mode} {i}"), || {
let candidate = Integer::<Circuit, I>::from_bits_be(&candidate);
assert_eq!(expected, candidate.eject_value());
assert_eq!(expected_size_in_bits, candidate.bits_le.len());
match mode.is_constant() {
true => assert_scope!(num_constants, num_public, num_private, num_constraints),
false => {
assert_scope!(num_constants, num_public, num_private, num_constraints + i)
}
};
});
}
}
#[test]
fn test_u8_from_bits_le_constant() {
type I = u8;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u8_from_bits_le_public() {
type I = u8;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u8_from_bits_le_private() {
type I = u8;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u8_from_bits_be_constant() {
type I = u8;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u8_from_bits_be_public() {
type I = u8;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u8_from_bits_be_private() {
type I = u8;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i8_from_bits_le_constant() {
type I = i8;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i8_from_bits_le_public() {
type I = i8;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i8_from_bits_le_private() {
type I = i8;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i8_from_bits_be_constant() {
type I = i8;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i8_from_bits_be_public() {
type I = i8;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i8_from_bits_be_private() {
type I = i8;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u16_from_bits_le_constant() {
type I = u16;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u16_from_bits_le_public() {
type I = u16;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u16_from_bits_le_private() {
type I = u16;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u16_from_bits_be_constant() {
type I = u16;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u16_from_bits_be_public() {
type I = u16;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u16_from_bits_be_private() {
type I = u16;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i16_from_bits_le_constant() {
type I = i16;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i16_from_bits_le_public() {
type I = i16;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i16_from_bits_le_private() {
type I = i16;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i16_from_bits_be_constant() {
type I = i16;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i16_from_bits_be_public() {
type I = i16;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i16_from_bits_be_private() {
type I = i16;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u32_from_bits_le_constant() {
type I = u32;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u32_from_bits_le_public() {
type I = u32;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u32_from_bits_le_private() {
type I = u32;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u32_from_bits_be_constant() {
type I = u32;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u32_from_bits_be_public() {
type I = u32;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u32_from_bits_be_private() {
type I = u32;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i32_from_bits_le_constant() {
type I = i32;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i32_from_bits_le_public() {
type I = i32;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i32_from_bits_le_private() {
type I = i32;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i32_from_bits_be_constant() {
type I = i32;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i32_from_bits_be_public() {
type I = i32;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i32_from_bits_be_private() {
type I = i32;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u64_from_bits_le_constant() {
type I = u64;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u64_from_bits_le_public() {
type I = u64;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u64_from_bits_le_private() {
type I = u64;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u64_from_bits_be_constant() {
type I = u64;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u64_from_bits_be_public() {
type I = u64;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u64_from_bits_be_private() {
type I = u64;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i64_from_bits_le_constant() {
type I = i64;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i64_from_bits_le_public() {
type I = i64;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i64_from_bits_le_private() {
type I = i64;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i64_from_bits_be_constant() {
type I = i64;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i64_from_bits_be_public() {
type I = i64;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i64_from_bits_be_private() {
type I = i64;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u128_from_bits_le_constant() {
type I = u128;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u128_from_bits_le_public() {
type I = u128;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u128_from_bits_le_private() {
type I = u128;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_u128_from_bits_be_constant() {
type I = u128;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_u128_from_bits_be_public() {
type I = u128;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_u128_from_bits_be_private() {
type I = u128;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i128_from_bits_le_constant() {
type I = i128;
check_from_bits_le::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i128_from_bits_le_public() {
type I = i128;
check_from_bits_le::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i128_from_bits_le_private() {
type I = i128;
check_from_bits_le::<I>(Mode::Private, 0, 0, 0, 0);
}
#[test]
fn test_i128_from_bits_be_constant() {
type I = i128;
check_from_bits_be::<I>(Mode::Constant, 0, 0, 0, 0);
}
#[test]
fn test_i128_from_bits_be_public() {
type I = i128;
check_from_bits_be::<I>(Mode::Public, 0, 0, 0, 0);
}
#[test]
fn test_i128_from_bits_be_private() {
type I = i128;
check_from_bits_be::<I>(Mode::Private, 0, 0, 0, 0);
}
}