pub struct EndianNat<B: Base> {
pub endian: Endian,
pub digits: Seq<int>,
pub phantom: PhantomData<B>,
}Expand description
Provides either little-endian or big-endian interpretation of a sequence of numbers with a given base. This interpretation may have any number of leading zeros. With little-endian, the first digit is the least significant position; the last digit is the most significant position. With big-endian, the last digit of a sequence is the least significant position; the first digit is the most significant position.
Fields§
§endian: Endian§digits: Seq<int>§phantom: PhantomData<B>Implementations§
Source§impl<B: Base> EndianNat<B>
impl<B: Base> EndianNat<B>
Sourcepub open spec fn in_bounds(s: Seq<int>) -> bool
pub open spec fn in_bounds(s: Seq<int>) -> bool
{ forall |i| 0 <= i < s.len() ==> 0 <= #[trigger] s[i] < B::base() }True when all numbers in s are valid digits in the given base.
Sourcepub open spec fn wf(self) -> bool
pub open spec fn wf(self) -> bool
{ Self::in_bounds(self.digits) }True when all of self.digits are valid digits in the given base.
Sourcepub open spec fn new(endian: Endian, digits: Seq<int>) -> Self
pub open spec fn new(endian: Endian, digits: Seq<int>) -> Self
Self::in_bounds(digits),{
EndianNat {
endian,
digits,
phantom: PhantomData,
}
}Creates a new EndianNat with the given digits and endianness.
Sourcepub open spec fn new_default(digits: Seq<int>) -> Self
pub open spec fn new_default(digits: Seq<int>) -> Self
Self::in_bounds(digits),{
EndianNat {
endian: endianness(),
digits,
phantom: PhantomData,
}
}Creates a new EndianNat with the given digits and the default endianness (endianness()).
Sourcepub open spec fn index(self, i: int) -> int
pub open spec fn index(self, i: int) -> int
0 <= i < self.digits.len(),{ self.digits[i] }The ith digit in this EndianNat.
Sourcepub open spec fn first(self) -> nat
pub open spec fn first(self) -> nat
self.digits.len() > 0,{ self.digits.first() as nat }The first digit in this EndianNat. Ignores endianness.
Sourcepub open spec fn last(self) -> nat
pub open spec fn last(self) -> nat
self.digits.len() > 0,{ self.digits.last() as nat }The last digit in this EndianNat. Ignores endianness.
Sourcepub open spec fn least(self) -> nat
pub open spec fn least(self) -> nat
self.digits.len() > 0,{
match self.endian {
Endian::Little => self.first(),
Endian::Big => self.last(),
}
}The least significant digit in this EndianNat.
Sourcepub open spec fn most(self) -> nat
pub open spec fn most(self) -> nat
self.digits.len() > 0,{
match self.endian {
Endian::Little => self.last(),
Endian::Big => self.first(),
}
}The most significant digit in this EndianNat.
Sourcepub open spec fn skip(self, n: nat) -> Self
pub open spec fn skip(self, n: nat) -> Self
0 <= n <= self.digits.len(),{
EndianNat {
endian: self.endian,
digits: self.digits.skip(n as int),
phantom: self.phantom,
}
}Constructs an EndianNat by skipping the first n digits of the original EndianNat. Ignores endianness.
Sourcepub open spec fn take(self, n: nat) -> Self
pub open spec fn take(self, n: nat) -> Self
0 <= n <= self.digits.len(),{
EndianNat {
endian: self.endian,
digits: self.digits.take(n as int),
phantom: self.phantom,
}
}Constructs an EndianNat by taking only the first n digits of the original EndianNat. Ignores endianness.
Sourcepub open spec fn skip_least(self, n: nat) -> Self
pub open spec fn skip_least(self, n: nat) -> Self
0 <= n <= self.digits.len(),{
match self.endian {
Endian::Little => self.skip(n),
Endian::Big => self.take((self.len() - n) as nat),
}
}Constructs an EndianNat by skipping the least significant n digits of the original EndianNat.
Sourcepub open spec fn skip_most(self, n: nat) -> Self
pub open spec fn skip_most(self, n: nat) -> Self
0 <= n <= self.digits.len(),{
match self.endian {
Endian::Little => self.take((self.len() - n) as nat),
Endian::Big => self.skip(n),
}
}Constructs an EndianNat by skipping the most significant n digits of the original EndianNat.
Sourcepub open spec fn take_least(self, n: nat) -> Self
pub open spec fn take_least(self, n: nat) -> Self
0 <= n <= self.digits.len(),{
match self.endian {
Endian::Little => self.take(n),
Endian::Big => self.skip((self.len() - n) as nat),
}
}Constructs an EndianNat by taking only the least significant n digits of the original EndianNat.
Sourcepub open spec fn take_most(self, n: nat) -> Self
pub open spec fn take_most(self, n: nat) -> Self
0 <= n <= self.digits.len(),{
match self.endian {
Endian::Little => self.skip((self.len() - n) as nat),
Endian::Big => self.take(n),
}
}Constructs an EndianNat by taking only the most significant n digits of the original EndianNat.
Sourcepub open spec fn drop_first(self) -> Self
pub open spec fn drop_first(self) -> Self
self.len() > 0,{
EndianNat {
endian: self.endian,
digits: self.digits.drop_first(),
phantom: self.phantom,
}
}Constructs an EndianNat by dropping the first digit of the original EndianNat. Ignores endianness.
Sourcepub open spec fn drop_last(self) -> Self
pub open spec fn drop_last(self) -> Self
self.len() > 0,{
EndianNat {
endian: self.endian,
digits: self.digits.drop_last(),
phantom: self.phantom,
}
}Constructs an EndianNat by dropping the last digit of the original EndianNat. Ignores endianness.
Sourcepub open spec fn drop_least(self) -> Self
pub open spec fn drop_least(self) -> Self
self.len() > 0,{
match self.endian {
Endian::Little => self.drop_first(),
Endian::Big => self.drop_last(),
}
}Constructs an EndianNat by dropping the least significant digit of the original EndianNat.
Sourcepub open spec fn drop_most(self) -> Self
pub open spec fn drop_most(self) -> Self
self.len() > 0,{
match self.endian {
Endian::Little => self.drop_last(),
Endian::Big => self.drop_first(),
}
}Constructs an EndianNat by dropping the most significant digits of the original EndianNat.
Sourcepub open spec fn append(self, other: Self) -> Self
pub open spec fn append(self, other: Self) -> Self
self.endian == other.endian,{ EndianNat::new(self.endian, self.digits + other.digits) }Constructs an EndianNat by appending the digits of other to the end of the digits of self. Ignores endianness.
Sourcepub open spec fn append_least(self, other: Self) -> Self
pub open spec fn append_least(self, other: Self) -> Self
self.endian == other.endian,{
match self.endian {
Endian::Little => other.append(self),
Endian::Big => self.append(other),
}
}Constructs an EndianNat by appending the digits of other to the digits of self in the least significant position
(i.e., other becomes the least significant bits).
Sourcepub open spec fn append_most(self, other: Self) -> Self
pub open spec fn append_most(self, other: Self) -> Self
self.endian == other.endian,{
match self.endian {
Endian::Little => self.append(other),
Endian::Big => other.append(self),
}
}Constructs an EndianNat by appending the digits of other to the digits of self in the most significant position
(i.e., other becomes the most significant bits).
Sourcepub open spec fn push_first(self, n: int) -> Self
pub open spec fn push_first(self, n: int) -> Self
n < B::base(),{
EndianNat {
endian: self.endian,
digits: seq![n].add(self.digits),
phantom: self.phantom,
}
}Constructs an EndianNat by appending n to the front of the digits of self. Ignores endianness.
Sourcepub open spec fn push_last(self, n: int) -> Self
pub open spec fn push_last(self, n: int) -> Self
n < B::base(),{
EndianNat {
endian: self.endian,
digits: self.digits.push(n),
phantom: self.phantom,
}
}Constructs an EndianNat by appending n to the end of the digits of self. Ignores endianness.
Sourcepub open spec fn push_least(self, n: int) -> Self
pub open spec fn push_least(self, n: int) -> Self
n < B::base(),{
match self.endian {
Endian::Little => self.push_first(n),
Endian::Big => self.push_last(n),
}
}Constructs an EndianNat by appending n to the least significant position in the digits of self.
Sourcepub open spec fn push_most(self, n: int) -> Self
pub open spec fn push_most(self, n: int) -> Self
n < B::base(),{
match self.endian {
Endian::Little => self.push_last(n),
Endian::Big => self.push_first(n),
}
}Constructs an EndianNat by appending n to the most significant position in the digits of self.
Sourcepub open spec fn to_nat(self) -> nat
pub open spec fn to_nat(self) -> nat
{
if self.len() == 0 {
0
} else {
self.drop_least().to_nat() * B::base() + self.least()
}
}Converts an EndianNat to the natural number that it represents, processing the digits from least significant to most significant, hiding the details of endianness.
Sourcepub broadcast proof fn to_nat_properties(self)
pub broadcast proof fn to_nat_properties(self)
self.wf(),ensures#[trigger] self.to_nat() < base_upper_bound_excl::<B>(self.len()),Sourcepub proof fn to_nat_append_least(endian: Self, other: Self)
pub proof fn to_nat_append_least(endian: Self, other: Self)
endian.wf(),other.wf(),endian.endian == other.endian,ensuresendian.append_least(other).to_nat()
== (endian.to_nat() * base_upper_bound_excl::<B>(other.len())) + other.to_nat(),Sourcepub open spec fn from_nat(n: nat, len: nat) -> Self
pub open spec fn from_nat(n: nat, len: nat) -> Self
n < base_upper_bound_excl::<B>(len),{
if len == 0 {
EndianNat {
digits: Seq::empty(),
endian: endianness(),
phantom: PhantomData,
}
} else {
let least = (n % B::base()) as int;
let rest = n / B::base();
let rest_endian = Self::from_nat(rest, (len - 1) as nat);
rest_endian.push_least(least)
}
}Converts a natural number to an EndianNat representation with the specified number of digits (len) and default endianness (endianness()).
n should be less than the maximum number that can be represented in len digits in this base.
Sourcepub broadcast proof fn from_nat_properties(n: nat, len: nat)
pub broadcast proof fn from_nat_properties(n: nat, len: nat)
n < base_upper_bound_excl::<B>(len),ensuresSelf::from_nat(n, len).len() == len,Self::from_nat(n, len).endian == endianness(),Self::from_nat(n, len).wf(),Sourcepub broadcast proof fn from_nat_to_nat(n: nat, len: nat)
pub broadcast proof fn from_nat_to_nat(n: nat, len: nat)
Sourcepub broadcast proof fn to_nat_from_nat(endian_nat: Self)
pub broadcast proof fn to_nat_from_nat(endian_nat: Self)
Sourcepub broadcast proof fn to_nat_injective(n1: Self, n2: Self)
pub broadcast proof fn to_nat_injective(n1: Self, n2: Self)
n1.wf(),n2.wf(),n1.endian == endianness(),n2.endian == endianness(),n1.len() == n2.len(),#[trigger] n1.to_nat() == #[trigger] n2.to_nat(),ensuresn1 == n2,Sourcepub broadcast proof fn from_nat_injective(n1: nat, len1: nat, n2: nat, len2: nat)
pub broadcast proof fn from_nat_injective(n1: nat, len1: nat, n2: nat, len2: nat)
n1 < base_upper_bound_excl::<B>(len1),n2 < base_upper_bound_excl::<B>(len2),#[trigger] Self::from_nat(n1, len1) == #[trigger] Self::from_nat(n2, len2),ensuresn1 == n2,Sourcepub open spec fn to_nat_most(self) -> nat
pub open spec fn to_nat_most(self) -> nat
{
if self.len() == 0 {
0
} else {
(self.drop_most().to_nat_most()
+ self.most() * pow(B::base() as int, (self.len() - 1) as nat)) as nat
}
}Converts an EndianNat to the natural number that it represents, processing the digits from most significant to least significant, hiding the details of endianness.
Sourcepub broadcast proof fn to_nat_eq_to_nat_most(self)
pub broadcast proof fn to_nat_eq_to_nat_most(self)
self.wf(),ensures#[trigger] self.to_nat() == #[trigger] self.to_nat_most(),Ensures that to_nat and to_nat_most agree.
Source§impl<B: Base> EndianNat<B>
impl<B: Base> EndianNat<B>
Sourcepub open spec fn exp<BIG>() -> natwhere
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub open spec fn exp<BIG>() -> natwhere
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
{ BIG::bits() / B::bits() }B::base() to the power of exp() is BIG::base().
In other words, exp() is the number of digits in base B that correspond to a single digit in base BIG.
Sourcepub broadcast proof fn exp_properties<BIG>()where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub broadcast proof fn exp_properties<BIG>()where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
base_upper_bound_excl::<B>(Self::exp()) == BIG::base(),Self::exp() > 0,Sourcepub open spec fn from_big<BIG>(n: EndianNat<BIG>) -> Selfwhere
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub open spec fn from_big<BIG>(n: EndianNat<BIG>) -> Selfwhere
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
{
if n.len() == 0 {
EndianNat::new(n.endian, Seq::empty())
} else {
Self::from_big(n.drop_least())
.append_least(EndianNat::from_nat(n.least(), Self::exp()))
}
}Converts an EndianNat representation in the “big” base BIG to an EndianNat representation in the “small” base B.
The result represents the same non-negative number as the original.
Sourcepub broadcast proof fn from_big_properties<BIG>(n: EndianNat<BIG>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub broadcast proof fn from_big_properties<BIG>(n: EndianNat<BIG>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
n.wf(),n.endian == endianness(),ensuresSelf::from_big(n).wf(),Self::from_big(n).endian == endianness(),Self::from_big(n).len() == n.len() * Self::exp(),Self::from_big(n).to_nat() == n.to_nat(),Sourcepub open spec fn to_big<BIG>(n: EndianNat<B>) -> EndianNat<BIG>where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub open spec fn to_big<BIG>(n: EndianNat<B>) -> EndianNat<BIG>where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
n.len() % Self::exp() == 0,{
if n.len() == 0 {
EndianNat::new(n.endian, Seq::empty())
} else {
Self::to_big(n.skip_least(Self::exp()))
.append_least(
EndianNat::new(n.endian, seq![n.take_least(Self::exp()).to_nat() as int]),
)
}
}Converts an EndianNat representation in the “small” base B to an EndianNat representation in the “big” base BIG.
The result represents the same non-negative number as the original.
Sourcepub broadcast proof fn to_big_properties<BIG>(n: EndianNat<B>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub broadcast proof fn to_big_properties<BIG>(n: EndianNat<B>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
n.wf(),n.endian == endianness(),n.len() % Self::exp() == 0,ensuresSelf::to_big(n).wf(),Self::to_big(n).endian == endianness(),Self::to_big(n).len() == n.len() / Self::exp(),Self::to_big(n).to_nat() == n.to_nat(),Sourcepub broadcast proof fn to_big_from_big<BIG>(n: EndianNat<B>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub broadcast proof fn to_big_from_big<BIG>(n: EndianNat<B>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
Sourcepub broadcast proof fn from_big_to_big<BIG>(n: EndianNat<BIG>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub broadcast proof fn from_big_to_big<BIG>(n: EndianNat<BIG>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
Sourcepub broadcast proof fn to_big_injective<BIG>(n1: EndianNat<B>, n2: EndianNat<B>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub broadcast proof fn to_big_injective<BIG>(n1: EndianNat<B>, n2: EndianNat<B>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
n1.wf(),n2.wf(),n1.endian == endianness(),n2.endian == endianness(),n1.len() % Self::exp() == 0,n2.len() % Self::exp() == 0,#[trigger] Self::to_big(n1) == #[trigger] Self::to_big(n2),ensuresn1 == n2,Sourcepub broadcast proof fn from_big_injective<BIG>(n1: EndianNat<BIG>, n2: EndianNat<BIG>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub broadcast proof fn from_big_injective<BIG>(n1: EndianNat<BIG>, n2: EndianNat<BIG>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
n1.wf(),n2.wf(),n1.endian == endianness(),n2.endian == endianness(),#[trigger] Self::from_big(n1) == #[trigger] Self::from_big(n2),ensuresn1 == n2,Sourcepub proof fn to_big_single<BIG>(x: EndianNat<B>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
pub proof fn to_big_single<BIG>(x: EndianNat<B>)where
BIG: BasePow2,
B: CompatibleSmallerBaseFor<BIG>,
x.len() == Self::exp(),x.len() > 0,ensuresSelf::to_big(x).len() == 1,Self::to_big(x).index(0) == x.to_nat() as int,Auto Trait Implementations§
impl<B> Freeze for EndianNat<B>
impl<B> RefUnwindSafe for EndianNat<B>where
B: RefUnwindSafe,
impl<B> Send for EndianNat<B>where
B: Send,
impl<B> Sync for EndianNat<B>where
B: Sync,
impl<B> Unpin for EndianNat<B>where
B: Unpin,
impl<B> UnwindSafe for EndianNat<B>where
B: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
impl<T, U> IntoSpecImpl<U> for Twhere
U: From<T>,
Source§impl<T, VERUS_SPEC__A> TryFromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: TryFrom<T>,
impl<T, VERUS_SPEC__A> TryFromSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: TryFrom<T>,
Source§exec fn obeys_try_from_spec() -> bool
exec fn obeys_try_from_spec() -> bool
Source§impl<T, VERUS_SPEC__A> TryIntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: TryInto<T>,
impl<T, VERUS_SPEC__A> TryIntoSpec<T> for VERUS_SPEC__Awhere
VERUS_SPEC__A: TryInto<T>,
Source§exec fn obeys_try_into_spec() -> bool
exec fn obeys_try_into_spec() -> bool
Source§impl<T, U> TryIntoSpecImpl<U> for Twhere
U: TryFrom<T>,
impl<T, U> TryIntoSpecImpl<U> for Twhere
U: TryFrom<T>,
Source§open spec fn obeys_try_into_spec() -> bool
open spec fn obeys_try_into_spec() -> bool
{ <U as TryFromSpec<Self>>::obeys_try_from_spec() }