#[macro_export] macro_rules! nary_field_common_deps {
() => {
#[macro_use] extern crate newtype_derive;
use std::fmt;
#[cfg(feature = "nightly")] use std::convert::TryFrom;
use std::cmp::Ordering;
use std::iter::{FromIterator, IntoIterator, Iterator};
use std::ops::{Add, Sub, Mul, Div, BitAnd, BitOr, BitXor, Index, IndexMut, Shl, Shr};
use finite_fields::error::{ConversionError, DivisionError, OverflowError};
pub trait Peano where Self: Sized {
fn successor(&self) -> Result<Self, OverflowError>;
fn predecessor(&self) -> Result<Self, OverflowError>;
fn cmp (&self, other: &Self) -> Ordering;
}
}
}
#[macro_export] macro_rules! unit_nary_arithmetic {
($tyname:ident, $arity:expr, $storsize:ident) => {
impl Peano for $tyname {
fn successor(&self) -> Result<$tyname, OverflowError> {
if self == &$tyname(($arity - 1) as $storsize) {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: ONE.to_string() })
} else {
Ok($tyname(self.0 + (1 as $storsize)))
}
}
fn predecessor(&self) -> Result<$tyname, OverflowError> {
if self == &$tyname(0 as $storsize) {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: ONE.to_string() })
} else {
Ok($tyname(self.0 - (1 as $storsize)))
}
}
fn cmp (&self, other: &Self) -> Ordering {
if &self == other { Ordering::Equal }
else if self.0 < other.0 { Ordering::Less }
else { Ordering::Greater }
}
}
impl PartialOrd for $tyname {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Add for $tyname {
type Output = Result<$tyname, OverflowError>;
fn add(self, other: $tyname) -> Result<$tyname, OverflowError> {
let sum = self.0 + other.0;
if sum > $arity - 1 {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok($tyname(sum as $storsize))
}
}
}
impl<'a> Add<$tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn add(self, other: $tyname) -> Result<$tyname, OverflowError> {
let sum = self.0 + other.0;
if sum > $arity - 1 {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok($tyname(sum as $storsize))
}
}
}
impl<'a> Add<&'a $tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn add(self, other: &$tyname) -> Result<$tyname, OverflowError> {
let sum = self.0 + other.0;
if sum > $arity - 1 {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok($tyname(sum as $storsize))
}
}
}
impl Sub for $tyname {
type Output = Result<$tyname, OverflowError>;
fn sub(self, other: $tyname) -> Result<$tyname, OverflowError> {
if self.0 < other.0 {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
let diff = self.0 - other.0;
Ok($tyname(diff as $storsize))
}
}
}
impl<'a> Sub<$tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn sub(self, other: $tyname) -> Result<$tyname, OverflowError> {
if self.0 < other.0 {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
let diff = self.0 - other.0;
Ok($tyname(diff as $storsize))
}
}
}
impl<'a> Sub<&'a $tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn sub(self, other: &$tyname) -> Result<$tyname, OverflowError> {
if self.0 < other.0 {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
let diff = self.0 - other.0;
Ok($tyname(diff as $storsize))
}
}
}
impl Mul for $tyname {
type Output = Result<Self, OverflowError>;
fn mul(self, other: $tyname) -> Result<$tyname, OverflowError> {
let prod = self.0 * other.0;
if prod < $arity - 1 {
Ok($tyname(prod as $storsize))
} else {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
}
}
}
impl<'a> Mul<$tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn mul(self, other: $tyname) -> Result<$tyname, OverflowError> {
let prod = self.0 * other.0;
if prod < $arity - 1 {
Ok($tyname(prod as $storsize))
} else {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
}
}
}
impl<'a> Mul<&'a $tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn mul(self, other: &$tyname) -> Result<$tyname, OverflowError> {
let prod = self.0 * other.0;
if prod < $arity - 1 {
Ok($tyname(prod as $storsize))
} else {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
}
}
}
impl Div for $tyname {
type Output = Result<$tyname, DivisionError>;
fn div(self, other: $tyname) -> Result<$tyname, DivisionError> {
if other == ZERO {
Err(DivisionError::DivideByZeroError {
arg1: self.to_string()
})
} else if self < other {
Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
} else {
let one: $tyname = ONE;
let mut sub_count: $tyname = ZERO;
let mut div_lhs = other.clone();
while div_lhs > other {
if let Ok(difference) = div_lhs - other {
div_lhs = difference;
if let Ok(sum) = sub_count + one {
sub_count = sum;
} else {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
} else {
break;
}
}
Ok(sub_count)
}
}
}
impl<'a> Div<$tyname> for &'a $tyname {
type Output = Result<$tyname, DivisionError>;
fn div(self, other: $tyname) -> Result<$tyname, DivisionError> {
if other == ZERO {
Err(DivisionError::DivideByZeroError {
arg1: self.to_string()
})
} else if self < &other {
Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
} else {
let one: $tyname = ONE;
let mut sub_count: $tyname = ZERO;
let mut div_lhs = other.clone();
while div_lhs > other {
if let Ok(difference) = div_lhs - other {
div_lhs = difference;
if let Ok(sum) = sub_count + one {
sub_count = sum;
} else {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
} else {
break;
}
}
Ok(sub_count)
}
}
}
impl<'a> Div<&'a $tyname> for &'a $tyname {
type Output = Result<$tyname, DivisionError>;
fn div(self, other: &$tyname) -> Result<$tyname, DivisionError> {
if *other == ZERO {
Err(DivisionError::DivideByZeroError {
arg1: self.to_string()
})
} else if self < &other {
Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
} else {
let one: $tyname = ONE;
let mut sub_count: $tyname = ZERO;
let mut div_lhs = other.clone();
while div_lhs > *other {
if let Ok(difference) = div_lhs - *other {
div_lhs = difference;
if let Ok(sum) = sub_count + one {
sub_count = sum;
} else {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
} else {
break;
}
}
Ok(sub_count)
}
}
}
}
}
#[macro_export] macro_rules! unit_nary {
($tyname:ident, $arity:expr, $storsize:ident) => {
nary_field_common_deps! {}
#[derive(Clone,Copy,Debug,PartialEq,Eq)]
pub struct $tyname($storsize);
NewtypeFrom! {
() pub struct $tyname($storsize);
}
impl $tyname {
pub fn new(val: $storsize) -> $tyname {
$tyname(val)
}
pub fn max(&self) -> usize {
$arity - 1
}
}
impl fmt::Display for $tyname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[cfg(feature = "nightly")]
impl TryFrom<usize> for $tyname {
type Err = ConversionError;
fn try_from(val: usize) -> Result<Self, Self::Err> {
if val > $arity - 1 {
Err(ConversionError::OverflowError { arg1: val.to_string() })
} else {
Ok((0..val).fold(ZERO, |accum, _| (accum + ONE).unwrap()))
}
}
}
impl From<$tyname> for usize {
fn from(val: $tyname) -> usize {
usize::from(val.0)
}
}
impl BitAnd for $tyname {
type Output = Self;
fn bitand(self, other: $tyname) -> Self {
$tyname(self.0 & other.0)
}
}
impl BitOr for $tyname {
type Output = Self;
fn bitor(self, other: $tyname) -> Self {
$tyname(self.0 | other.0)
}
}
impl BitXor for $tyname {
type Output = Self;
fn bitxor(self, other: $tyname) -> Self {
$tyname(self.0 ^ other.0)
}
}
pub const ZERO: $tyname = $tyname(0 as $storsize);
pub const ONE: $tyname = $tyname(1 as $storsize);
impl<'a> PartialEq<$tyname> for &'a $tyname {
fn eq(&self, other: &$tyname) -> bool {
self.0 == other.0
}
}
impl<'a> PartialEq<&'a $tyname> for $tyname {
fn eq(&self, other: &&'a $tyname) -> bool {
self.0 == other.0
}
}
unit_nary_arithmetic! { $tyname, $arity, $storsize }
}
}
#[macro_export] macro_rules! nary_type_arithmetic {
($tyname:ident, $fieldwidth:expr) => {
impl Add for $tyname {
type Output = Result<Self, OverflowError>;
fn add(self, other: $tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut carry = false;
for place in (0..other.0.len()).rev() {
let augend = match carry {
false => self.0[place].clone(),
true => match self.0[place].successor() {
Ok(res) => {
res.clone()
},
Err(_) => {
ZERO
}
}
};
match augend + other.0[place] {
Ok(res) => {
output.0[place] = res;
carry = false;
}
Err(_) => {
output.0[place] = ZERO;
carry = true
}
}
}
if carry {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok(output)
}
}
}
impl<'a> Add<$tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn add(self, other: $tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut carry = false;
for place in (0..other.0.len()).rev() {
let augend = match carry {
false => self.0[place].clone(),
true => match self.0[place].successor() {
Ok(res) => {
res.clone()
},
Err(_) => {
ZERO
}
}
};
match augend + other.0[place] {
Ok(res) => {
output.0[place] = res;
carry = false;
}
Err(_) => {
output.0[place] = ZERO;
carry = true
}
}
}
if carry {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok(output)
}
}
}
impl<'a> Add<&'a $tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn add(self, other: &$tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut carry = false;
for place in (0..other.0.len()).rev() {
let augend = match carry {
false => self.0[place].clone(),
true => match self.0[place].successor() {
Ok(res) => {
res.clone()
},
Err(_) => {
ZERO
}
}
};
match augend + other.0[place] {
Ok(res) => {
output.0[place] = res;
carry = false;
}
Err(_) => {
output.0[place] = ZERO;
carry = true
}
}
}
if carry {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok(output)
}
}
}
impl Sub for $tyname {
type Output = Result<$tyname, OverflowError>;
fn sub(self, other: $tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut carry = false;
for place in (0..other.0.len()).rev() {
let augend = match carry {
false => self.0[place],
true => match self.0[place].predecessor() {
Ok(res) => {
res
},
Err(_) => {
ZERO
}
}
};
match augend - other.0[place] {
Ok(res) => {
output.0[place] = res;
carry = false;
}
Err(_) => {
output.0[place] = ONE;
carry = true
}
}
}
if carry {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok(output)
}
}
}
impl<'a> Sub<$tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn sub(self, other: $tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut carry = false;
for place in (0..other.0.len()).rev() {
let augend = match carry {
false => self.0[place],
true => match self.0[place].predecessor() {
Ok(res) => {
res
},
Err(_) => {
ZERO
}
}
};
match augend - other.0[place] {
Ok(res) => {
output.0[place] = res;
carry = false;
}
Err(_) => {
output.0[place] = ONE;
carry = true
}
}
}
if carry {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok(output)
}
}
}
impl<'a> Sub<&'a $tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn sub(self, other: &$tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut carry = false;
for place in (0..other.0.len()).rev() {
let augend = match carry {
false => self.0[place],
true => match self.0[place].predecessor() {
Ok(res) => {
res
},
Err(_) => {
ZERO
}
}
};
match augend - other.0[place] {
Ok(res) => {
output.0[place] = res;
carry = false;
}
Err(_) => {
output.0[place] = ONE;
carry = true
}
}
}
if carry {
Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
} else {
Ok(output)
}
}
}
impl Peano for $tyname {
fn successor(&self) -> Result<$tyname, OverflowError> {
let mut one: $tyname = $tyname([ZERO; $fieldwidth]);
one[$fieldwidth - 1] = ONE;
self + one
}
fn predecessor(&self) -> Result<$tyname, OverflowError> {
let mut one: $tyname = $tyname([ZERO; $fieldwidth]);
one[$fieldwidth - 1] = ONE;
self - one
}
fn cmp (&self, other: &Self) -> Ordering {
if *self == *other { Ordering::Equal }
else {
match *self - *other {
Ok(_) => Ordering::Greater,
Err(_) => Ordering::Less
}
}
}
}
impl PartialOrd for $tyname {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl BitAnd for $tyname {
type Output = Self;
fn bitand(self, other: $tyname) -> Self {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] & other.0[place]
}
output
}
}
impl<'a> BitAnd<$tyname> for &'a $tyname {
type Output = $tyname;
fn bitand(self, other: $tyname) -> $tyname {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] & other.0[place]
}
output
}
}
impl<'a> BitAnd<&'a $tyname> for &'a $tyname {
type Output = $tyname;
fn bitand(self, other: &$tyname) -> $tyname {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] & other.0[place]
}
output
}
}
impl BitOr for $tyname {
type Output = Self;
fn bitor(self, other: $tyname) -> Self {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] | other.0[place]
}
output
}
}
impl<'a> BitOr<$tyname> for &'a $tyname {
type Output = $tyname;
fn bitor(self, other: $tyname) -> $tyname {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] | other.0[place]
}
output
}
}
impl<'a> BitOr<&'a $tyname> for &'a $tyname {
type Output = $tyname;
fn bitor(self, other: &$tyname) -> $tyname {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] | other.0[place]
}
output
}
}
impl BitXor for $tyname {
type Output = Self;
fn bitxor(self, other: $tyname) -> Self {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] ^ other.0[place]
}
output
}
}
impl<'a> BitXor<$tyname> for &'a $tyname {
type Output = $tyname;
fn bitxor(self, other: $tyname) -> $tyname {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] ^ other.0[place]
}
output
}
}
impl<'a> BitXor<&'a $tyname> for &'a $tyname {
type Output = $tyname;
fn bitxor(self, other: &$tyname) -> $tyname {
let mut output = $tyname([ZERO; $fieldwidth]);
for place in (0..other.0.len()).rev() {
output.0[place] = self.0[place] ^ other.0[place]
}
output
}
}
impl Shr<usize> for $tyname {
type Output = Self;
fn shr(self, rhs: usize) -> Self {
let mut dest_arr = [ZERO; $fieldwidth];
for dest_ind in 0..dest_arr.len() {
if dest_ind < rhs {
dest_arr[dest_ind] = ZERO;
} else {
dest_arr[dest_ind] = self.0[dest_ind - rhs];
}
}
$tyname(dest_arr)
}
}
impl Shl<usize> for $tyname {
type Output = Self;
fn shl(self, rhs: usize) -> Self {
let mut dest_arr = [ZERO; $fieldwidth];
for dest_ind in 0..dest_arr.len() {
if dest_ind < rhs {
dest_arr[dest_ind] = self.0[dest_ind + rhs];
} else {
dest_arr[dest_ind] = ZERO;
}
}
$tyname(dest_arr)
}
}
impl Mul for $tyname {
type Output = Result<$tyname, OverflowError>;
fn mul(self, other: $tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut mult_rhs = other.clone();
let mut one: $tyname = $tyname([ZERO; $fieldwidth]);
one[$fieldwidth - 1] = ONE;
let zero = $tyname([ZERO; $fieldwidth]);
while mult_rhs > zero {
if let Ok(sum) = output + self {
output = sum
} else {
return Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
}
mult_rhs = (mult_rhs - one).unwrap();
}
Ok(output)
}
}
impl<'a> Mul<$tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn mul(self, other: $tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut mult_rhs = other.clone();
let mut one: $tyname = $tyname([ZERO; $fieldwidth]);
one[$fieldwidth - 1] = ONE;
let zero = $tyname([ZERO; $fieldwidth]);
while mult_rhs > zero {
if let Ok(sum) = output + *self {
output = sum
} else {
return Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
}
mult_rhs = (mult_rhs - one).unwrap();
}
Ok(output)
}
}
impl<'a> Mul<&'a $tyname> for &'a $tyname {
type Output = Result<$tyname, OverflowError>;
fn mul(self, other: &$tyname) -> Result<$tyname, OverflowError> {
let mut output = $tyname([ZERO; $fieldwidth]);
let mut mult_rhs = other.clone();
let mut one: $tyname = $tyname([ZERO; $fieldwidth]);
one[$fieldwidth - 1] = ONE;
let zero = $tyname([ZERO; $fieldwidth]);
while mult_rhs > zero {
if let Ok(sum) = output + *self {
output = sum
} else {
return Err(OverflowError::Default { arg1: self.to_string(),
arg2: other.to_string() })
}
mult_rhs = (mult_rhs - one).unwrap();
}
Ok(output)
}
}
impl Div for $tyname {
type Output = Result<$tyname, DivisionError>;
fn div(self, other: $tyname) -> Result<$tyname, DivisionError> {
let mut one: $tyname = $tyname([ZERO; $fieldwidth]);
one[$fieldwidth - 1] = ONE;
let zero = $tyname([ZERO; $fieldwidth]);
if other == zero {
return Err(DivisionError::DivideByZeroError { arg1: self.to_string() })
} else if self < other {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
let mut div_lhs = other.clone();
let mut sub_count = zero;
while div_lhs > other {
if let Ok(difference) = div_lhs - other {
div_lhs = difference;
if let Ok(sum) = sub_count + one {
sub_count = sum;
} else {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
} else {
break;
}
}
Ok(sub_count)
}
}
impl<'a> Div<$tyname> for &'a $tyname {
type Output = Result<$tyname, DivisionError>;
fn div(self, other: $tyname) -> Result<$tyname, DivisionError> {
let mut one: $tyname = $tyname([ZERO; $fieldwidth]);
one[$fieldwidth - 1] = ONE;
let zero = $tyname([ZERO; $fieldwidth]);
if other == zero {
return Err(DivisionError::DivideByZeroError { arg1: self.to_string() })
} else if self < &other {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
let mut div_lhs = other.clone();
let mut sub_count = zero;
while div_lhs > other {
if let Ok(difference) = div_lhs - other {
div_lhs = difference;
if let Ok(sum) = sub_count + one {
sub_count = sum;
} else {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
} else {
break;
}
}
Ok(sub_count)
}
}
impl<'a> Div<&'a $tyname> for &'a $tyname {
type Output = Result<$tyname, DivisionError>;
fn div(self, other: &$tyname) -> Result<$tyname, DivisionError> {
let mut one: $tyname = $tyname([ZERO; $fieldwidth]);
one[$fieldwidth - 1] = ONE;
let zero = $tyname([ZERO; $fieldwidth]);
if *other == zero {
return Err(DivisionError::DivideByZeroError { arg1: self.to_string() })
} else if self < other {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
let mut div_lhs = other.clone();
let mut sub_count = zero;
while div_lhs > *other {
if let Ok(difference) = div_lhs - *other {
div_lhs = difference;
if let Ok(sum) = sub_count + one {
sub_count = sum;
} else {
return Err(DivisionError::OverflowError { arg1: self.to_string(),
arg2: other.to_string() })
}
} else {
break;
}
}
Ok(sub_count)
}
}
}
}
#[macro_export] macro_rules! nary_type {
($tyname:ident,
$unit_tyname:ident,
$arity:expr,
$storsize:ident,
$fieldwidth:expr) => {
unit_nary! { $unit_tyname, $arity, $storsize }
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct $tyname([$unit_tyname; $fieldwidth]);
impl $tyname {
pub fn new(vals: [$unit_tyname; $fieldwidth]) -> $tyname {
$tyname(vals)
}
pub fn max(&self) -> usize {
($arity as usize).pow($fieldwidth) - 1
}
pub fn len(&self) -> usize {
$fieldwidth
}
pub fn iter(self) -> Iter {
Iter { data: self, index: 0, end: 0 }
}
pub fn bits(&self) -> [$unit_tyname; $fieldwidth] {
self.0
}
pub fn shift_concat(&self, val: $unit_tyname) -> $tyname {
let mut shifted_bin = *self << 1;
shifted_bin[self.len() - 1] = val;
shifted_bin
}
pub fn unshift_concat(&self, val: $unit_tyname) -> $tyname {
let mut unshifted_bin = *self >> 1;
unshifted_bin[0] = val;
unshifted_bin
}
}
impl fmt::Display for $tyname {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut bit_string = String::with_capacity(self.len());
for bit in self.bits().iter() { bit_string.push_str(&bit.to_string()); }
write!(f, "{}", bit_string)
}
}
#[cfg(feature = "nightly")]
impl TryFrom<usize> for $tyname {
type Err = ConversionError;
fn try_from(val: usize) -> Result<Self, Self::Err> {
let mut out_val = $tyname::new([ZERO; $fieldwidth]);
if val > out_val.max() {
Err(ConversionError::OverflowError { arg1: val.to_string() })
} else if val == 0 {
Ok(out_val)
} else {
let mut dec = val.clone();
if dec % $arity != 0 {
out_val[$fieldwidth - 1] = ONE;
}
for place in 0..$fieldwidth {
if dec > 1 {
dec = dec / $arity;
out_val[place] = ONE;
} else {
break;
}
}
Ok(out_val)
}
}
}
impl From<usize> for $tyname {
fn from(val: usize) -> Self {
let mut out_val = $tyname::new([ZERO; $fieldwidth]);
if val > out_val.max() {
panic!("Can't convert {} to $tyname, it's too big.", val);
} else if val == 0 {
out_val
} else {
let mut dec = val.clone();
if dec % $arity != 0 {
out_val[$fieldwidth - 1] = ONE;
}
for place in 0..$fieldwidth {
if dec > 1 {
dec = dec / $arity;
out_val[place] = ONE;
} else {
break;
}
}
out_val
}
}
}
#[cfg(feature = "nightly")]
impl<'a> TryFrom<&'a [$unit_tyname]> for $tyname {
type Err = ConversionError;
fn try_from(val: &[$unit_tyname]) -> Result<Self, Self::Err> {
if val.len() != $fieldwidth {
Err(ConversionError::LengthError { arg1: val.len() })
} else {
let mut out_val = $tyname::new([ZERO; $fieldwidth]);
for place in 0..out_val.len() {
out_val[place] = val[place];
}
Ok(out_val)
}
}
}
impl From<$tyname> for usize {
fn from(val: $tyname) -> usize {
val.bits().iter()
.rev()
.enumerate()
.fold(0, |accum, (place_ind, &bit)| {
usize::from(bit) *
(2 as usize).pow((place_ind) as u32) + accum
})
}
}
impl<'a> Index<usize> for $tyname {
type Output = $unit_tyname;
fn index<'b>(&'b self, idx: usize) -> &'b $unit_tyname {
&self.0[idx]
}
}
impl IndexMut<usize> for $tyname {
fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut $unit_tyname {
&mut self.0[index]
}
}
pub struct Iter {
data: $tyname,
index: usize,
end: usize
}
impl Iterator for Iter {
type Item = $unit_tyname;
fn next(&mut self) -> Option<$unit_tyname> {
self.index += 1;
if self.index < $fieldwidth {
Some(self.data.0[self.index])
} else {
None
}
}
}
impl DoubleEndedIterator for Iter {
fn next_back(&mut self) -> Option<Self::Item> {
if self.end > 0 {
self.end -= 1;
if self.end >= self.index {
Some(self.data.0[self.end])
} else {
None
}
} else {
None
}
}
}
impl IntoIterator for $tyname {
type Item = $unit_tyname;
type IntoIter = ::std::vec::IntoIter<$unit_tyname>;
fn into_iter(self) -> Self::IntoIter {
self.0.to_vec().into_iter()
}
}
impl<'a> IntoIterator for &'a $tyname {
type Item = &'a $unit_tyname;
type IntoIter = ::std::slice::Iter<'a,$unit_tyname>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl FromIterator<$unit_tyname> for $tyname {
fn from_iter<I: IntoIterator<Item=$unit_tyname>>(iter: I) -> Self {
let mut collector = $tyname::new([ZERO; $fieldwidth]);
for (ind, val) in (0..collector.len()).zip(iter) {
collector[ind] = val;
}
collector
}
}
nary_type_arithmetic! { $tyname, $fieldwidth }
}
}