use core::fmt;
use std::cmp::Ordering;
use std::ops::BitAnd;
use std::ops::BitAndAssign;
use std::ops::BitOr;
use std::ops::BitOrAssign;
use std::ops::BitXor;
use std::ops::BitXorAssign;
use std::ops::Not;
use crate::bdd::*;
use crate::canonization::*;
use crate::decomposition::*;
use crate::operations::*;
use crate::Lut;
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
pub struct StaticLut<const NUM_VARS: usize, const NUM_WORDS: usize> {
table: [u64; NUM_WORDS],
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> Default for StaticLut<NUM_VARS, NUM_WORDS> {
fn default() -> Self {
Self::zero()
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> StaticLut<NUM_VARS, NUM_WORDS> {
pub const fn num_vars(&self) -> usize {
NUM_VARS
}
pub const fn num_bits(&self) -> usize {
1 << self.num_vars()
}
pub const fn num_blocks(&self) -> usize {
table_size(self.num_vars())
}
fn check_var(&self, ind: usize) {
assert!(ind < self.num_vars());
}
fn check_lut(&self, rhs: &Self) {
assert_eq!(self.num_vars(), rhs.num_vars());
}
fn check_bit(&self, ind: usize) {
assert!(ind < self.num_bits());
}
pub const fn one() -> Self {
Self {
table: [num_vars_mask(NUM_VARS); NUM_WORDS],
}
}
pub const fn zero() -> Self {
Self {
table: [0; NUM_WORDS],
}
}
pub fn nth_var(var: usize) -> Self {
assert!(var < NUM_VARS);
let mut ret = Self::default();
fill_nth_var(NUM_VARS, ret.table.as_mut(), var);
ret
}
pub fn parity() -> Self {
let mut ret = Self::default();
fill_parity(NUM_VARS, ret.table.as_mut());
ret
}
pub fn majority() -> Self {
let mut ret = Self::default();
fill_majority(NUM_VARS, ret.table.as_mut());
ret
}
pub fn threshold(k: usize) -> Self {
let mut ret = Self::default();
fill_threshold(NUM_VARS, ret.table.as_mut(), k);
ret
}
pub fn equals(k: usize) -> Self {
let mut ret = Self::default();
fill_equals(NUM_VARS, ret.table.as_mut(), k);
ret
}
pub fn symmetric(count_values: usize) -> Self {
let mut ret = Self::default();
fill_symmetric(NUM_VARS, ret.table.as_mut(), count_values);
ret
}
#[cfg(feature = "rand")]
pub fn random() -> Self {
let mut ret = Self::default();
fill_random(NUM_VARS, ret.table.as_mut());
ret
}
pub fn value(&self, mask: usize) -> bool {
self.get_bit(mask)
}
pub fn get_bit(&self, mask: usize) -> bool {
self.check_bit(mask);
get_bit(self.num_vars(), self.table.as_ref(), mask)
}
pub fn set_value(&mut self, mask: usize, value: bool) {
if value {
self.set_bit(mask)
} else {
self.unset_bit(mask)
}
}
pub fn set_bit(&mut self, mask: usize) {
self.check_bit(mask);
set_bit(self.num_vars(), self.table.as_mut(), mask);
}
pub fn unset_bit(&mut self, mask: usize) {
self.check_bit(mask);
unset_bit(self.num_vars(), self.table.as_mut(), mask);
}
pub fn count_ones(&self) -> usize {
count_ones(self.num_vars(), self.table.as_ref())
}
pub fn count_zeros(&self) -> usize {
count_zeros(self.num_vars(), self.table.as_ref())
}
pub fn not_inplace(&mut self) {
not_inplace(self.num_vars(), self.table.as_mut());
}
pub fn and_inplace(&mut self, rhs: &Self) {
self.check_lut(rhs);
and_inplace(self.table.as_mut(), rhs.table.as_ref());
}
pub fn or_inplace(&mut self, rhs: &Self) {
self.check_lut(rhs);
or_inplace(self.table.as_mut(), rhs.table.as_ref());
}
pub fn xor_inplace(&mut self, rhs: &Self) {
self.check_lut(rhs);
xor_inplace(self.table.as_mut(), rhs.table.as_ref());
}
pub fn flip_inplace(&mut self, ind: usize) {
self.check_var(ind);
flip_inplace(self.num_vars(), self.table.as_mut(), ind);
}
pub fn flip_n_inplace(&mut self, mask: u32) {
flip_n_inplace(self.num_vars(), self.table.as_mut(), mask);
}
pub fn swap_inplace(&mut self, ind1: usize, ind2: usize) {
self.check_var(ind1);
self.check_var(ind2);
swap_inplace(self.num_vars(), self.table.as_mut(), ind1, ind2);
}
pub fn permute_inplace(&mut self, perm: &[u8]) {
assert_eq!(self.num_vars(), perm.len());
permute_inplace(self.num_vars(), self.table.as_mut(), perm);
}
pub fn swap_adjacent_inplace(&mut self, ind: usize) {
self.check_var(ind);
self.check_var(ind + 1);
swap_adjacent_inplace(self.num_vars(), self.table.as_mut(), ind);
}
pub fn not(&self) -> Self {
let mut l = *self;
l.not_inplace();
l
}
pub fn and(&self, rhs: &Self) -> Self {
let mut l = *self;
l.and_inplace(rhs);
l
}
pub fn or(&self, rhs: &Self) -> Self {
let mut l = *self;
l.or_inplace(rhs);
l
}
pub fn xor(&self, rhs: &Self) -> Self {
let mut l = *self;
l.xor_inplace(rhs);
l
}
pub fn flip(&self, ind: usize) -> Self {
let mut l = *self;
l.flip_inplace(ind);
l
}
pub fn flip_n(&self, mask: u32) -> Self {
let mut l = *self;
l.flip_n_inplace(mask);
l
}
pub fn swap(&self, ind1: usize, ind2: usize) -> Self {
let mut l = *self;
l.swap_inplace(ind1, ind2);
l
}
pub fn permute(&self, perm: &[u8]) -> Self {
let mut l = *self;
l.permute_inplace(perm);
l
}
pub fn swap_adjacent(&self, ind: usize) -> Self {
let mut l = *self;
l.swap_adjacent_inplace(ind);
l
}
pub fn cofactors(&self, ind: usize) -> (Self, Self) {
let mut c = (*self, *self);
cofactor0_inplace(self.num_vars(), c.0.table.as_mut(), ind);
cofactor1_inplace(self.num_vars(), c.1.table.as_mut(), ind);
c
}
pub fn from_cofactors(c0: &Self, c1: &Self, ind: usize) -> Self {
let mut ret = Self::zero();
from_cofactors_inplace(
NUM_VARS,
ret.table.as_mut(),
c0.table.as_ref(),
c1.table.as_ref(),
ind,
);
ret
}
pub fn blocks(&self) -> &[u64] {
self.table.as_ref()
}
pub fn from_blocks(blocks: &[u64]) -> Self {
let mut ret = Self::default();
ret.table.clone_from_slice(blocks);
ret
}
pub fn p_canonization(&self) -> (Self, [u8; NUM_VARS]) {
let mut work = *self;
let mut ret = *self;
let mut perm = [0; NUM_VARS];
p_canonization(
self.num_vars(),
work.table.as_mut(),
ret.table.as_mut(),
perm.as_mut(),
);
(ret, perm)
}
pub fn is_p_canonical(&self) -> bool {
let mut work = *self;
is_p_canonical(self.num_vars(), &self.table, work.table.as_mut())
}
pub fn n_canonization(&self) -> (Self, u32) {
let mut work = *self;
let mut ret = *self;
let flip = n_canonization(self.num_vars(), work.table.as_mut(), ret.table.as_mut());
(ret, flip)
}
pub fn is_n_canonical(&self) -> bool {
let mut work = *self;
is_n_canonical(self.num_vars(), &self.table, work.table.as_mut())
}
pub fn npn_canonization(&self) -> (Self, [u8; NUM_VARS], u32) {
let mut work = *self;
let mut ret = *self;
let mut perm = [0; NUM_VARS];
let flip = npn_canonization(
self.num_vars(),
work.table.as_mut(),
ret.table.as_mut(),
perm.as_mut(),
);
(ret, perm, flip)
}
pub fn is_npn_canonical(&self) -> bool {
let mut work = *self;
is_npn_canonical(self.num_vars(), &self.table, work.table.as_mut())
}
pub fn top_decomposition(&self, ind: usize) -> DecompositionType {
top_decomposition(self.num_vars(), self.table.as_ref(), ind)
}
pub fn is_pos_unate(&self, ind: usize) -> bool {
input_pos_unate(self.num_vars(), self.table.as_ref(), ind)
}
pub fn is_neg_unate(&self, ind: usize) -> bool {
input_neg_unate(self.num_vars(), self.table.as_ref(), ind)
}
pub fn all_functions() -> StaticLutIterator<NUM_VARS, NUM_WORDS> {
StaticLutIterator {
lut: StaticLut::zero(),
ok: true,
}
}
pub fn bdd_complexity(luts: &[Self]) -> usize {
let mut table = Vec::<u64>::new();
for l in luts {
table.extend(l.blocks().iter());
}
table_bdd_complexity(NUM_VARS, table.as_slice())
}
pub fn to_hex_string(&self) -> String {
to_hex(self.num_vars(), self.table.as_ref())
}
pub fn to_bin_string(&self) -> String {
to_bin(self.num_vars(), self.table.as_ref())
}
pub fn from_hex_string(s: &str) -> Result<Self, ParseLutError> {
let mut ret = Self::zero();
fill_hex(ret.num_vars(), ret.table.as_mut(), s)?;
Ok(ret)
}
pub fn from_bin_string(s: &str) -> Result<Self, ParseLutError> {
let mut ret = Self::zero();
fill_bin(ret.num_vars(), ret.table.as_mut(), s)?;
Ok(ret)
}
}
#[doc(hidden)]
pub struct StaticLutIterator<const NUM_VARS: usize, const NUM_WORDS: usize> {
lut: StaticLut<NUM_VARS, NUM_WORDS>,
ok: bool,
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> Iterator
for StaticLutIterator<NUM_VARS, NUM_WORDS>
{
type Item = StaticLut<NUM_VARS, NUM_WORDS>;
fn next(&mut self) -> Option<Self::Item> {
if !self.ok {
None
} else {
let ret = self.lut;
self.ok = next_inplace(NUM_VARS, self.lut.table.as_mut());
Some(ret)
}
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> Ord for StaticLut<NUM_VARS, NUM_WORDS> {
fn cmp(&self, other: &Self) -> Ordering {
cmp(self.table.as_ref(), other.table.as_ref())
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> PartialOrd for StaticLut<NUM_VARS, NUM_WORDS> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> Not for StaticLut<NUM_VARS, NUM_WORDS> {
type Output = Self;
fn not(self) -> Self::Output {
let mut l = self;
l.not_inplace();
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> Not for &StaticLut<NUM_VARS, NUM_WORDS> {
type Output = StaticLut<NUM_VARS, NUM_WORDS>;
fn not(self) -> Self::Output {
let mut l = *self;
l.not_inplace();
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitAndAssign<StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
fn bitand_assign(&mut self, rhs: Self) {
and_inplace(self.table.as_mut(), rhs.table.as_ref());
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitAndAssign<&StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
fn bitand_assign(&mut self, rhs: &Self) {
and_inplace(self.table.as_mut(), rhs.table.as_ref());
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitAnd<StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
let mut l = self;
l &= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitAnd<&StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = Self;
fn bitand(self, rhs: &StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = self;
l &= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitAnd<StaticLut<NUM_VARS, NUM_WORDS>>
for &StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = StaticLut<NUM_VARS, NUM_WORDS>;
fn bitand(self, rhs: StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = *self;
l &= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitAnd<&StaticLut<NUM_VARS, NUM_WORDS>>
for &StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = StaticLut<NUM_VARS, NUM_WORDS>;
fn bitand(self, rhs: &StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = *self;
l &= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitOrAssign<StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
fn bitor_assign(&mut self, rhs: Self) {
or_inplace(self.table.as_mut(), rhs.table.as_ref());
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitOrAssign<&StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
fn bitor_assign(&mut self, rhs: &Self) {
or_inplace(self.table.as_mut(), rhs.table.as_ref());
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitOr<StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
let mut l = self;
l |= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitOr<&StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = Self;
fn bitor(self, rhs: &StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = self;
l |= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitOr<StaticLut<NUM_VARS, NUM_WORDS>>
for &StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = StaticLut<NUM_VARS, NUM_WORDS>;
fn bitor(self, rhs: StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = *self;
l |= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitOr<&StaticLut<NUM_VARS, NUM_WORDS>>
for &StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = StaticLut<NUM_VARS, NUM_WORDS>;
fn bitor(self, rhs: &StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = *self;
l |= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitXorAssign<StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
fn bitxor_assign(&mut self, rhs: Self) {
xor_inplace(self.table.as_mut(), rhs.table.as_ref());
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitXorAssign<&StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
fn bitxor_assign(&mut self, rhs: &Self) {
xor_inplace(self.table.as_mut(), rhs.table.as_ref());
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitXor<StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = Self;
fn bitxor(self, rhs: Self) -> Self::Output {
let mut l = self;
l ^= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitXor<&StaticLut<NUM_VARS, NUM_WORDS>>
for StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = Self;
fn bitxor(self, rhs: &StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = self;
l ^= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitXor<StaticLut<NUM_VARS, NUM_WORDS>>
for &StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = StaticLut<NUM_VARS, NUM_WORDS>;
fn bitxor(self, rhs: StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = *self;
l ^= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> BitXor<&StaticLut<NUM_VARS, NUM_WORDS>>
for &StaticLut<NUM_VARS, NUM_WORDS>
{
type Output = StaticLut<NUM_VARS, NUM_WORDS>;
fn bitxor(self, rhs: &StaticLut<NUM_VARS, NUM_WORDS>) -> Self::Output {
let mut l = *self;
l ^= rhs;
l
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> fmt::Display
for StaticLut<NUM_VARS, NUM_WORDS>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_hex(self.num_vars(), self.table.as_ref(), f)
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> fmt::Debug for StaticLut<NUM_VARS, NUM_WORDS> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_hex(self.num_vars(), self.table.as_ref(), f)
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> fmt::LowerHex
for StaticLut<NUM_VARS, NUM_WORDS>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_hex(self.num_vars(), self.table.as_ref(), f)
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> fmt::Binary for StaticLut<NUM_VARS, NUM_WORDS> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt_bin(self.num_vars(), self.table.as_ref(), f)
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> TryFrom<Lut>
for StaticLut<NUM_VARS, NUM_WORDS>
{
type Error = ();
fn try_from(lut: Lut) -> Result<Self, Self::Error> {
if lut.num_vars() != NUM_VARS {
return Err(());
}
Ok(StaticLut::<NUM_VARS, NUM_WORDS>::from_blocks(lut.blocks()))
}
}
impl<const NUM_VARS: usize, const NUM_WORDS: usize> From<StaticLut<NUM_VARS, NUM_WORDS>> for Lut {
fn from(lut: StaticLut<NUM_VARS, NUM_WORDS>) -> Lut {
Lut::from_blocks(lut.num_vars(), lut.blocks())
}
}
pub type Lut0 = StaticLut<0, 1>;
pub type Lut1 = StaticLut<1, 1>;
pub type Lut2 = StaticLut<2, 1>;
pub type Lut3 = StaticLut<3, 1>;
pub type Lut4 = StaticLut<4, 1>;
pub type Lut5 = StaticLut<5, 1>;
pub type Lut6 = StaticLut<6, 1>;
pub type Lut7 = StaticLut<7, 2>;
pub type Lut8 = StaticLut<8, 4>;
pub type Lut9 = StaticLut<9, 8>;
pub type Lut10 = StaticLut<10, 16>;
pub type Lut11 = StaticLut<11, 32>;
pub type Lut12 = StaticLut<12, 64>;
pub type Lut13 = StaticLut<13, 128>;
pub type Lut14 = StaticLut<14, 256>;
pub type Lut15 = StaticLut<15, 512>;
pub type Lut16 = StaticLut<16, 1024>;
impl From<u8> for Lut3 {
fn from(table: u8) -> Lut3 {
Lut3::from_blocks(&[table as u64])
}
}
impl From<u16> for Lut4 {
fn from(table: u16) -> Lut4 {
Lut4::from_blocks(&[table as u64])
}
}
impl From<u32> for Lut5 {
fn from(table: u32) -> Lut5 {
Lut5::from_blocks(&[table as u64])
}
}
impl From<u64> for Lut6 {
fn from(table: u64) -> Lut6 {
Lut6::from_blocks(&[table])
}
}
impl From<u128> for Lut7 {
fn from(table: u128) -> Lut7 {
Lut7::from_blocks(&[(table & 0xffff_ffff_ffff_ffff) as u64, (table >> 64) as u64])
}
}
impl From<Lut3> for u8 {
fn from(lut: Lut3) -> u8 {
(lut.table[0] & !VAR_MASK[3]) as u8
}
}
impl From<Lut4> for u16 {
fn from(lut: Lut4) -> u16 {
(lut.table[0] & !VAR_MASK[4]) as u16
}
}
impl From<Lut5> for u32 {
fn from(lut: Lut5) -> u32 {
(lut.table[0] & !VAR_MASK[5]) as u32
}
}
impl From<Lut6> for u64 {
fn from(lut: Lut6) -> u64 {
lut.table[0]
}
}
impl From<Lut7> for u128 {
fn from(lut: Lut7) -> u128 {
lut.table[0] as u128 + ((lut.table[1] as u128) << 64)
}
}
#[cfg(test)]
mod tests {
use crate::{Lut0, Lut1, Lut2, Lut3, Lut4, Lut5, Lut6, Lut7};
#[test]
fn test_symmetric() {
assert_eq!(Lut3::majority().to_string(), "Lut3(e8)");
assert_eq!(Lut4::majority().to_string(), "Lut4(fee8)");
assert_eq!(Lut3::equals(0).to_string(), "Lut3(01)");
assert_eq!(Lut4::equals(0).to_string(), "Lut4(0001)");
assert_eq!(Lut3::equals(1).to_string(), "Lut3(16)");
assert_eq!(Lut4::equals(1).to_string(), "Lut4(0116)");
assert_eq!(Lut3::parity().to_string(), "Lut3(96)");
assert_eq!(Lut4::parity().to_string(), "Lut4(6996)");
}
#[test]
fn test_display() {
assert_eq!(format!("{:}", Lut0::zero()), "Lut0(0)");
assert_eq!(format!("{:}", Lut0::one()), "Lut0(1)");
assert_eq!(format!("{:}", Lut1::zero()), "Lut1(0)");
assert_eq!(format!("{:}", Lut1::one()), "Lut1(3)");
assert_eq!(format!("{:}", Lut2::zero()), "Lut2(0)");
assert_eq!(format!("{:}", Lut2::one()), "Lut2(f)");
assert_eq!(format!("{:}", Lut3::zero()), "Lut3(00)");
assert_eq!(format!("{:}", Lut3::one()), "Lut3(ff)");
assert_eq!(format!("{:}", Lut4::zero()), "Lut4(0000)");
assert_eq!(format!("{:}", Lut4::one()), "Lut4(ffff)");
assert_eq!(format!("{:}", Lut5::zero()), "Lut5(00000000)");
assert_eq!(format!("{:}", Lut5::one()), "Lut5(ffffffff)");
assert_eq!(format!("{:}", Lut6::zero()), "Lut6(0000000000000000)");
assert_eq!(format!("{:}", Lut6::one()), "Lut6(ffffffffffffffff)");
assert_eq!(
format!("{:}", Lut7::zero()),
"Lut7(00000000000000000000000000000000)"
);
assert_eq!(
format!("{:}", Lut7::one()),
"Lut7(ffffffffffffffffffffffffffffffff)"
);
}
#[test]
#[allow(
unused_must_use,
clippy::no_effect,
clippy::unnecessary_operation,
clippy::op_ref
)]
fn test_ops() {
let mut a = Lut6::nth_var(0);
let b = Lut6::nth_var(1);
!a;
!&a;
&a & &b;
&a & b;
a & &b;
a & b;
&a | &b;
&a | b;
a | &b;
a | b;
&a ^ &b;
&a ^ b;
a ^ &b;
a ^ b;
a &= b;
a &= &b;
a |= b;
a |= &b;
a ^= b;
a ^= &b;
}
#[test]
#[cfg(feature = "rand")]
fn test_random() {
Lut0::random();
Lut1::random();
Lut2::random();
Lut3::random();
Lut4::random();
Lut5::random();
Lut6::random();
Lut7::random();
}
#[test]
#[cfg(feature = "rand")]
fn test_lut_conversion() {
use crate::{Lut, Lut7};
for _ in 0..10 {
let lut = Lut3::random();
assert_eq!(lut, Lut3::try_from(Lut::from(lut)).unwrap());
}
for _ in 0..10 {
let lut = Lut7::random();
assert_eq!(lut, Lut7::try_from(Lut::from(lut)).unwrap());
}
}
#[test]
#[cfg(feature = "rand")]
fn test_int_conversion() {
for _ in 0..10 {
let lut = Lut3::random();
assert_eq!(lut, Lut3::from(u8::from(lut)));
assert_eq!(lut.to_hex_string(), format!("{:02x}", u8::from(lut)));
}
for _ in 0..10 {
let lut = Lut4::random();
assert_eq!(lut, Lut4::from(u16::from(lut)));
assert_eq!(lut.to_hex_string(), format!("{:04x}", u16::from(lut)));
}
for _ in 0..10 {
let lut = Lut5::random();
assert_eq!(lut, Lut5::from(u32::from(lut)));
assert_eq!(lut.to_hex_string(), format!("{:08x}", u32::from(lut)));
}
for _ in 0..10 {
let lut = Lut6::random();
assert_eq!(lut, Lut6::from(u64::from(lut)));
assert_eq!(lut.to_hex_string(), format!("{:016x}", u64::from(lut)));
}
for _ in 0..10 {
let lut = Lut7::random();
assert_eq!(lut, Lut7::from(u128::from(lut)));
assert_eq!(lut.to_hex_string(), format!("{:032x}", u128::from(lut)));
}
}
#[test]
#[cfg(feature = "rand")]
fn test_string_conversion() {
use crate::Lut8;
for _ in 0..10 {
let lut = Lut0::random();
assert_eq!(lut, Lut0::from_hex_string(&lut.to_hex_string()).unwrap());
assert_eq!(lut, Lut0::from_bin_string(&lut.to_bin_string()).unwrap());
}
for _ in 0..10 {
let lut = Lut1::random();
assert_eq!(lut, Lut1::from_hex_string(&lut.to_hex_string()).unwrap());
assert_eq!(lut, Lut1::from_bin_string(&lut.to_bin_string()).unwrap());
}
for _ in 0..10 {
let lut = Lut2::random();
assert_eq!(lut, Lut2::from_hex_string(&lut.to_hex_string()).unwrap());
assert_eq!(lut, Lut2::from_bin_string(&lut.to_bin_string()).unwrap());
}
for _ in 0..10 {
let lut = Lut3::random();
assert_eq!(lut, Lut3::from_hex_string(&lut.to_hex_string()).unwrap());
assert_eq!(lut, Lut3::from_bin_string(&lut.to_bin_string()).unwrap());
}
for _ in 0..10 {
let lut = Lut8::random();
assert_eq!(lut, Lut8::from_hex_string(&lut.to_hex_string()).unwrap());
assert_eq!(lut, Lut8::from_bin_string(&lut.to_bin_string()).unwrap());
}
}
}