use std::fmt::{self, Debug, Display};
use std::num::TryFromIntError;
use gate_calc_log_bits::*;
pub const MACH_MEM_ADDRESS_READ_FORWARD: u8 = 0;
pub const MACH_MEM_READ: u8 = 1;
pub const MACH_MEM_READ_WRITE_0: u8 = 2;
pub const MACH_MEM_READ_WRITE_1: u8 = 3;
pub const MACH_MEM_ADDRESS_BACKWARD: u8 = 4;
pub const MACH_MEM_ADDRESS_READ: u8 = 5;
pub const MACH_MEM_ADDRESS_READ_WRITE_0: u8 = 6;
pub const MACH_MEM_ADDRESS_READ_WRITE_1: u8 = 7;
pub const MACH_TEMP_BUFFER_READ_FORWARD: u8 = 8;
pub const MACH_TEMP_BUFFER_READ: u8 = 9;
pub const MACH_TEMP_BUFFER_READ_WRITE_0: u8 = 10;
pub const MACH_TEMP_BUFFER_READ_WRITE_1: u8 = 11;
pub const MACH_TEMP_BUFFER_BACKWARD: u8 = 12;
pub const MACH_STOP_3: u8 = 13;
pub const MACH_STOP_2: u8 = 14;
pub const MACH_STOP: u8 = 15;
pub const MACH_MARF: u8 = MACH_MEM_ADDRESS_READ_FORWARD;
pub const MACH_MR: u8 = MACH_MEM_READ;
pub const MACH_MRW0: u8 = MACH_MEM_READ_WRITE_0;
pub const MACH_MRW1: u8 = MACH_MEM_READ_WRITE_1;
pub const MACH_MAB: u8 = MACH_MEM_ADDRESS_BACKWARD;
pub const MACH_MAR: u8 = MACH_MEM_ADDRESS_READ;
pub const MACH_MARW0: u8 = MACH_MEM_ADDRESS_READ_WRITE_0;
pub const MACH_MARW1: u8 = MACH_MEM_ADDRESS_READ_WRITE_1;
pub const MACH_TBRF: u8 = MACH_TEMP_BUFFER_READ_FORWARD;
pub const MACH_TBR: u8 = MACH_TEMP_BUFFER_READ;
pub const MACH_TBRW0: u8 = MACH_TEMP_BUFFER_READ_WRITE_0;
pub const MACH_TBRW1: u8 = MACH_TEMP_BUFFER_READ_WRITE_1;
pub const MACH_TBB: u8 = MACH_TEMP_BUFFER_BACKWARD;
pub const MACH_S3: u8 = MACH_STOP_3;
pub const MACH_S2: u8 = MACH_STOP_2;
pub const MACH_S: u8 = MACH_STOP;
const DFS_EXT_ADD: usize = 1usize << (usize::BITS - 1);
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum MinInfFunc {
#[default]
MemAddressReadForward,
MemRead,
MemReadWrite0,
MemReadWrite1,
MemAddressBackward,
MemAddressRead,
MemAddressReadWrite0,
MemAddressReadWrite1,
TempBufferReadForward,
TempBufferRead,
TempBufferReadWrite0,
TempBufferReadWrite1,
TempBufferBackward,
Stop3,
Stop2,
Stop,
}
pub const MINF_MARF: MinInfFunc = MinInfFunc::MemAddressReadForward;
pub const MINF_MR: MinInfFunc = MinInfFunc::MemRead;
pub const MINF_MRW0: MinInfFunc = MinInfFunc::MemReadWrite0;
pub const MINF_MRW1: MinInfFunc = MinInfFunc::MemReadWrite1;
pub const MINF_MAB: MinInfFunc = MinInfFunc::MemAddressBackward;
pub const MINF_MAR: MinInfFunc = MinInfFunc::MemAddressRead;
pub const MINF_MARW0: MinInfFunc = MinInfFunc::MemAddressReadWrite0;
pub const MINF_MARW1: MinInfFunc = MinInfFunc::MemAddressReadWrite1;
pub const MINF_TBRF: MinInfFunc = MinInfFunc::TempBufferReadForward;
pub const MINF_TBR: MinInfFunc = MinInfFunc::TempBufferRead;
pub const MINF_TBRW0: MinInfFunc = MinInfFunc::TempBufferReadWrite0;
pub const MINF_TBRW1: MinInfFunc = MinInfFunc::TempBufferReadWrite1;
pub const MINF_TBB: MinInfFunc = MinInfFunc::TempBufferBackward;
pub const MINF_STOP3: MinInfFunc = MinInfFunc::Stop3;
pub const MINF_S3: MinInfFunc = MinInfFunc::Stop3;
pub const MINF_STOP2: MinInfFunc = MinInfFunc::Stop2;
pub const MINF_S2: MinInfFunc = MinInfFunc::Stop2;
pub const MINF_STOP: MinInfFunc = MinInfFunc::Stop;
pub const MINF_S: MinInfFunc = MinInfFunc::Stop;
#[inline]
pub fn minf_mrw(bit: bool) -> MinInfFunc {
if bit { MINF_MRW1 } else { MINF_MRW0 }
}
#[inline]
pub fn minf_marw(bit: bool) -> MinInfFunc {
if bit { MINF_MARW1 } else { MINF_MARW0 }
}
#[inline]
pub fn minf_tbrw(bit: bool) -> MinInfFunc {
if bit { MINF_TBRW1 } else { MINF_TBRW0 }
}
#[derive(Clone, Copy, Debug, thiserror::Error)]
pub enum MinInfFuncConvertError {
#[error("Value {0} Out of range")]
OutOfRange(u8),
}
#[inline]
pub fn minf_db(temp_buffer: bool) -> MinInfFunc {
if temp_buffer { MINF_TBB } else { MINF_MAB }
}
#[inline]
pub fn minf_drf(temp_buffer: bool) -> MinInfFunc {
if temp_buffer { MINF_TBRF } else { MINF_MARF }
}
#[inline]
pub fn minf_dr(temp_buffer: bool) -> MinInfFunc {
if temp_buffer { MINF_TBR } else { MINF_MAR }
}
#[inline]
pub fn minf_drw0(temp_buffer: bool) -> MinInfFunc {
if temp_buffer { MINF_TBRW0 } else { MINF_MARW0 }
}
#[inline]
pub fn minf_drw1(temp_buffer: bool) -> MinInfFunc {
if temp_buffer { MINF_TBRW1 } else { MINF_MARW1 }
}
#[inline]
pub fn minf_drw(temp_buffer: bool, bit: bool) -> MinInfFunc {
if temp_buffer {
if bit { MINF_TBRW1 } else { MINF_TBRW0 }
} else {
if bit { MINF_MARW1 } else { MINF_MARW0 }
}
}
impl MinInfFunc {
#[inline]
pub fn is_stop(self) -> bool {
self == MinInfFunc::Stop || self == MinInfFunc::Stop2 || self == MinInfFunc::Stop3
}
}
impl Display for MinInfFunc {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match self {
MinInfFunc::MemAddressReadForward => "MINF_MARF",
MinInfFunc::MemRead => "MINF_MR",
MinInfFunc::MemReadWrite0 => "MINF_MRW0",
MinInfFunc::MemReadWrite1 => "MINF_MRW1",
MinInfFunc::MemAddressBackward => "MINF_MAB",
MinInfFunc::MemAddressRead => "MINF_MAR",
MinInfFunc::MemAddressReadWrite0 => "MINF_MARW0",
MinInfFunc::MemAddressReadWrite1 => "MINF_MARW1",
MinInfFunc::TempBufferReadForward => "MINF_TBRF",
MinInfFunc::TempBufferRead => "MINF_TBR",
MinInfFunc::TempBufferReadWrite0 => "MINF_TBRW0",
MinInfFunc::TempBufferReadWrite1 => "MINF_TBRW1",
MinInfFunc::TempBufferBackward => "MINF_TBB",
MinInfFunc::Stop3 => "MINF_STOP3",
MinInfFunc::Stop2 => "MINF_STOP2",
MinInfFunc::Stop => "MINF_STOP",
};
write!(f, "{}", name)
}
}
impl TryFrom<u8> for MinInfFunc {
type Error = MinInfFuncConvertError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
use MinInfFunc::*;
match value {
MACH_MEM_ADDRESS_READ_FORWARD => Ok(MemAddressReadForward),
MACH_MEM_READ => Ok(MemRead),
MACH_MEM_READ_WRITE_0 => Ok(MemReadWrite0),
MACH_MEM_READ_WRITE_1 => Ok(MemReadWrite1),
MACH_MEM_ADDRESS_BACKWARD => Ok(MemAddressBackward),
MACH_MEM_ADDRESS_READ => Ok(MemAddressRead),
MACH_MEM_ADDRESS_READ_WRITE_0 => Ok(MemAddressReadWrite0),
MACH_MEM_ADDRESS_READ_WRITE_1 => Ok(MemAddressReadWrite1),
MACH_TEMP_BUFFER_READ_FORWARD => Ok(TempBufferReadForward),
MACH_TEMP_BUFFER_READ => Ok(TempBufferRead),
MACH_TEMP_BUFFER_READ_WRITE_0 => Ok(TempBufferReadWrite0),
MACH_TEMP_BUFFER_READ_WRITE_1 => Ok(TempBufferReadWrite1),
MACH_TEMP_BUFFER_BACKWARD => Ok(TempBufferBackward),
MACH_STOP_3 => Ok(Stop3),
MACH_STOP_2 => Ok(Stop2),
MACH_STOP => Ok(Stop),
_ => Err(MinInfFuncConvertError::OutOfRange(value)),
}
}
}
impl From<MinInfFunc> for u8 {
fn from(f: MinInfFunc) -> u8 {
use MinInfFunc::*;
match f {
MemAddressReadForward => MACH_MEM_ADDRESS_READ_FORWARD,
MemRead => MACH_MEM_READ,
MemReadWrite0 => MACH_MEM_READ_WRITE_0,
MemReadWrite1 => MACH_MEM_READ_WRITE_1,
MemAddressBackward => MACH_MEM_ADDRESS_BACKWARD,
MemAddressRead => MACH_MEM_ADDRESS_READ,
MemAddressReadWrite0 => MACH_MEM_ADDRESS_READ_WRITE_0,
MemAddressReadWrite1 => MACH_MEM_ADDRESS_READ_WRITE_1,
TempBufferReadForward => MACH_TEMP_BUFFER_READ_FORWARD,
TempBufferRead => MACH_TEMP_BUFFER_READ,
TempBufferReadWrite0 => MACH_TEMP_BUFFER_READ_WRITE_0,
TempBufferReadWrite1 => MACH_TEMP_BUFFER_READ_WRITE_1,
TempBufferBackward => MACH_TEMP_BUFFER_BACKWARD,
Stop3 => MACH_STOP_3,
Stop2 => MACH_STOP_2,
Stop => MACH_STOP,
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum MinInfInstrConvertError<U64TError, TU64Error> {
#[error("NextFr0 overflow: {0}")]
NextFr0Overflow(u64),
#[error("NextFr1 overflow: {0}")]
NextFr1Overflow(u64),
#[error("U64 from T error: {0}")]
U64FromTConversion(U64TError),
#[error("T from U64 error: {0}")]
TFromU64Conversion(TU64Error),
#[error("U64 from Usize error: {0}")]
U64FromUsizeConversion(TryFromIntError),
#[error("Usize from U64 error: {0}")]
UsizeFromU64Conversion(TryFromIntError),
#[error("U8 from MinInfFunc error: {0}")]
MinInfFuncConversion(#[from] MinInfFuncConvertError),
#[error("U64 from U8 error: {0}")]
U64FromU8Conversion(TryFromIntError),
#[error("State length is too big: {0}")]
StateLenTooBig(u32),
#[error("Add overflow: {0} {1}")]
AddOverflow(u64, u64),
}
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct MinInfInstr {
pub func_fr0: MinInfFunc,
pub func_fr1: MinInfFunc,
pub next_fr0: usize,
pub next_fr1: usize,
}
impl MinInfInstr {
pub fn new(func0: MinInfFunc, func1: MinInfFunc, next0: usize, next1: usize) -> Self {
Self {
func_fr0: func0,
func_fr1: func1,
next_fr0: next0,
next_fr1: next1,
}
}
pub fn new_01(func: MinInfFunc, next: usize) -> Self {
Self {
func_fr0: func,
func_fr1: func,
next_fr0: next,
next_fr1: next,
}
}
pub fn new_next01(func0: MinInfFunc, func1: MinInfFunc, next: usize) -> Self {
Self {
func_fr0: func0,
func_fr1: func1,
next_fr0: next,
next_fr1: next,
}
}
pub fn new_func01(func: MinInfFunc, next0: usize, next1: usize) -> Self {
Self {
func_fr0: func,
func_fr1: func,
next_fr0: next0,
next_fr1: next1,
}
}
pub fn try_into_pair<T>(
&self,
state_len: u32,
) -> Result<
(T, T),
MinInfInstrConvertError<<u64 as TryFrom<T>>::Error, <T as TryFrom<u64>>::Error>,
>
where
T: TryFrom<u64>,
u64: TryFrom<T>,
<u64 as TryFrom<T>>::Error: Debug,
<T as TryFrom<u64>>::Error: Debug,
{
if state_len > u64::BITS - 4 {
return Err(MinInfInstrConvertError::StateLenTooBig(state_len));
}
let func_fr0 = u64::from(u8::from(self.func_fr0));
let func_fr1 = u64::from(u8::from(self.func_fr1));
let next_fr0 = <u64 as TryFrom<usize>>::try_from(self.next_fr0)
.map_err(|e| MinInfInstrConvertError::U64FromUsizeConversion(e))?;
let next_fr1 = <u64 as TryFrom<usize>>::try_from(self.next_fr1)
.map_err(|e| MinInfInstrConvertError::U64FromUsizeConversion(e))?;
let state_num = 1u64 << state_len;
if next_fr0 >= state_num {
return Err(MinInfInstrConvertError::NextFr0Overflow(next_fr0));
}
if next_fr1 >= state_num {
return Err(MinInfInstrConvertError::NextFr1Overflow(next_fr1));
}
let add0 = next_fr0.checked_add(func_fr0 << state_len).ok_or(
MinInfInstrConvertError::AddOverflow(next_fr0, func_fr0 << state_len),
)?;
let add1 = next_fr1.checked_add(func_fr1 << state_len).ok_or(
MinInfInstrConvertError::AddOverflow(next_fr1, func_fr1 << state_len),
)?;
Ok((
T::try_from(add0).map_err(|e| MinInfInstrConvertError::TFromU64Conversion(e))?,
T::try_from(add1).map_err(|e| MinInfInstrConvertError::TFromU64Conversion(e))?,
))
}
pub fn try_from_pair<T>(
(fr0, fr1): (T, T),
state_len: u32,
) -> Result<Self, MinInfInstrConvertError<<u64 as TryFrom<T>>::Error, <T as TryFrom<u64>>::Error>>
where
T: TryFrom<u64>,
u64: TryFrom<T>,
<u64 as TryFrom<T>>::Error: Debug,
<T as TryFrom<u64>>::Error: Debug,
{
let fr0 = u64::try_from(fr0).map_err(|e| MinInfInstrConvertError::U64FromTConversion(e))?;
let fr1 = u64::try_from(fr1).map_err(|e| MinInfInstrConvertError::U64FromTConversion(e))?;
let mask = (1u64 << state_len) - 1;
Ok(Self {
func_fr0: u8::try_from(fr0 >> state_len)
.map_err(|e| MinInfInstrConvertError::U64FromU8Conversion(e))?
.try_into()?,
func_fr1: u8::try_from(fr1 >> state_len)
.map_err(|e| MinInfInstrConvertError::U64FromU8Conversion(e))?
.try_into()?,
next_fr0: usize::try_from(fr0 & mask)
.map_err(|e| MinInfInstrConvertError::UsizeFromU64Conversion(e))?,
next_fr1: usize::try_from(fr1 & mask)
.map_err(|e| MinInfInstrConvertError::UsizeFromU64Conversion(e))?,
})
}
pub fn equal_by_inner_states(&self, b: &MinInfInstr) -> bool {
self.func_fr0 == b.func_fr0
&& self.func_fr1 == b.func_fr1
&& ((self.next_fr0 >= DFS_EXT_ADD && b.next_fr0 >= DFS_EXT_ADD)
|| self.next_fr0 == b.next_fr0)
&& ((self.next_fr1 >= DFS_EXT_ADD && b.next_fr1 >= DFS_EXT_ADD)
|| self.next_fr1 == b.next_fr1)
}
}
impl Display for MinInfInstr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"({}, {}, {}, {})",
self.func_fr0, self.func_fr1, self.next_fr0, self.next_fr1
)
}
}
impl From<(MinInfFunc, usize)> for MinInfInstr {
fn from(f: (MinInfFunc, usize)) -> Self {
Self::new_01(f.0, f.1)
}
}
impl From<(MinInfFunc, usize, usize)> for MinInfInstr {
fn from(f: (MinInfFunc, usize, usize)) -> Self {
Self::new_func01(f.0, f.1, f.2)
}
}
impl From<(MinInfFunc, MinInfFunc, usize)> for MinInfInstr {
fn from(f: (MinInfFunc, MinInfFunc, usize)) -> Self {
Self::new_next01(f.0, f.1, f.2)
}
}
impl From<(MinInfFunc, MinInfFunc, usize, usize)> for MinInfInstr {
fn from(f: (MinInfFunc, MinInfFunc, usize, usize)) -> Self {
Self::new(f.0, f.1, f.2, f.3)
}
}
pub fn try_to_table<T>(
code: Vec<MinInfInstr>,
) -> Result<Vec<T>, MinInfInstrConvertError<<u64 as TryFrom<T>>::Error, <T as TryFrom<u64>>::Error>>
where
T: Clone + Default + TryFrom<u64>,
u64: TryFrom<T>,
<u64 as TryFrom<T>>::Error: Debug,
<T as TryFrom<u64>>::Error: Debug,
{
let state_num = code.len();
let state_len = calc_log_bits(state_num) as u32;
let inter = code
.into_iter()
.map(|x| x.try_into_pair(state_len))
.collect::<Result<Vec<_>, _>>()?;
let mut out = vec![T::default(); 1 << (state_len + 1)];
for (i, (fr0, fr1)) in inter.into_iter().enumerate() {
out[i] = fr0;
out[i + (1 << state_len)] = fr1;
}
Ok(out)
}
pub fn to_table<T>(code: Vec<MinInfInstr>) -> Vec<T>
where
T: Clone + Default + TryFrom<u64>,
u64: TryFrom<T>,
<u64 as TryFrom<T>>::Error: Debug,
<T as TryFrom<u64>>::Error: Debug,
{
try_to_table(code).unwrap_or_else(|e| {
panic!("While conversion to table: {:?}", e);
})
}
#[derive(Debug, thiserror::Error)]
pub enum FromTableError<ConvError> {
#[error("Bad table length")]
BadTableLength,
#[error("Conversion: {0}")]
Conversion(#[from] ConvError),
}
pub fn try_from_table<T>(
table: Vec<T>,
) -> Result<
Vec<MinInfInstr>,
FromTableError<MinInfInstrConvertError<<u64 as TryFrom<T>>::Error, <T as TryFrom<u64>>::Error>>,
>
where
T: Clone + TryFrom<u64>,
u64: TryFrom<T>,
<u64 as TryFrom<T>>::Error: Debug,
<T as TryFrom<u64>>::Error: Debug,
{
if (table.len() & 1) != 0 {
return Err(FromTableError::BadTableLength);
}
let state_num = table.len() >> 1;
let state_len = calc_log_bits(state_num) as u32;
Ok(table[0..state_num]
.iter()
.zip(table[state_num..state_num << 1].iter())
.map(|(fr0, fr1)| MinInfInstr::try_from_pair((fr0.clone(), fr1.clone()), state_len))
.collect::<Result<Vec<_>, _>>()?)
}
pub type MinInfPos = (usize, bool);
#[inline]
pub fn is_fr0(p: MinInfPos) -> bool {
!p.1
}
#[inline]
pub fn is_fr1(p: MinInfPos) -> bool {
p.1
}
pub fn from_table<T>(table: Vec<T>) -> Vec<MinInfInstr>
where
T: Clone + TryFrom<u64>,
u64: TryFrom<T>,
<u64 as TryFrom<T>>::Error: Debug,
<T as TryFrom<u64>>::Error: Debug,
{
try_from_table(table).unwrap_or_else(|e| {
panic!("While conversion from table: {:?}", e);
})
}
pub mod builder;
pub mod handler;
pub mod handler_builder;
pub mod table_opt;