Struct awint_core::Bits[][src]

#[repr(transparent)]
pub struct Bits { /* fields omitted */ }
Expand description

A reference to the bits in an InlAwi, ExtAwi, or other backing construct. This allows the same functions that operate on a dynamic ExtAwi at runtime to also operate on an InlAwi at compile time.

Bits do not know signedness. Instead, the methods on Bits are specified to interpret the bits as unsigned or signed two’s complement integers. If a method’s documentation does not mention signedness, it either works for both kinds or views the bits as a plain bit string with no integral properties.

Note

Unless otherwise specified, functions on Bits that return an Option<()> return None if the input bitwidths are not equal to each other. The Bits have been left unchanged if None is returned.

Portability

There are many functions that depend on usize and NonZeroUsize. In cases where the usize describes the bitwidth, a bit shift, or a bit position, the user should not need to worry about portability, since if the values are close to usize::MAX, the user is already close to running out of possible memory any way.

There are a few usages of usize that are not just indexes but are actual views into a contiguous range of bits inside Bits, such as Bits::as_slice, Bits::first, and Bits::get_digit (which are all hidden from the documentation, please refer to the source code of bits.rs if needed). Most end users should not uses these, since they have a strong dependence on the size of usize. These functions are actual views into the inner building blocks of this crate that other functions are built around in such a way that they are portable (e.g. the addition functions may internally operate on differing numbers of usize digits depending on the size of usize, but the end result looks the same to users on different architectures). The only reason these functions are exposed, is that someone may want to write their own custom performant algorithms, and they want as few abstractions as possible in the way.

Visible functions that are not portable in general, but always start from the zeroeth bit or a given bit position like Bits::short_cin_mul, Bits::short_udivide_assign, or Bits::usize_or_assign, are always portable as long as the digit inputs and/or outputs are restricted to 0..u8::MAX.

The Bits::as_bytes function and related functions, the serialization impls enabled by serde_support, the strings produced by the const serialization functions, and the serialization free functions in the awint_ext crate are all portable and should be used when sending representations of Bits between architectures.

The Hash impl and the rand_assign_using function enabled by rand_support use a deterministic byte oriented implementation to avoid portability issues.

Implementations

impl<'a> Bits[src]

pub const fn nzbw(&self) -> NonZeroUsize[src]

Returns the bitwidth as a NonZeroUsize

pub const fn bw(&self) -> usize[src]

Returns the bitwidth as a usize

pub const fn len(&self) -> usize[src]

Returns the exact number of usize digits needed to store all bits.

pub const fn clear_unused_bits(&mut self)[src]

Clears the unused bits.

pub const fn as_bytes(&'a self) -> &'a [u8][src]

Returns a reference to the underlying bits of self, including unused bits (which occur if self.bw() is not a multiple of 8).

Note

If the Bits has unused bits, those bits will always be set to zero, even if the Bits are intended to be a sign extended integer.

pub const fn as_mut_bytes(&'a mut self) -> &'a mut [u8][src]

Returns a mutable reference to the underlying bits of self, including unused bits (which occur if self.bw() is not a multiple of 8).

Note

Unused bits can be temporarily set but should be cleared before they are used by another function that expects the standard Bits invariants to be upheld. Set unused bits will not cause Rust undefined behavior, but may cause incorrect arithmetical results.

impl Bits[src]

pub const fn zero_assign(&mut self)[src]

Zero-assigns. Same as the Unsigned-minimum-value. All bits are set to 0.

pub const fn umax_assign(&mut self)[src]

Unsigned-maximum-value-assigns. All bits are set to 1.

pub const fn imax_assign(&mut self)[src]

Signed-maximum-value-assigns. All bits are set to 1, except for the most significant bit.

pub const fn imin_assign(&mut self)[src]

Signed-minimum-value-assigns. Only the most significant bit is set.

pub const fn uone_assign(&mut self)[src]

Unsigned-one-assigns. Only the least significant bit is set. The unsigned distinction is important, because a positive one value does not exist for signed integers with a bitwidth of 1.

pub const fn not_assign(&mut self)[src]

Not-assigns self

pub const fn copy_assign(&mut self, rhs: &Self) -> Option<()>[src]

Copy-assigns the bits of rhs to self

pub const fn resize_assign(&mut self, rhs: &Self, extension: bool)[src]

Resize-copy-assigns rhs to self. If self.bw() >= rhs.bw(), the copied value of rhs will be extended with bits set to extension. If self.bw() < rhs.bw(), the copied value of rhs will be truncated.

pub const fn zero_resize_assign(&mut self, rhs: &Self) -> bool[src]

Zero-resize-copy-assigns rhs to self and returns overflow. This is the same as lhs.resize_assign(rhs, false), but returns true if the unsigned meaning of the integer is changed.

pub const fn sign_resize_assign(&mut self, rhs: &Self) -> bool[src]

Sign-resize-copy-assigns rhs to self and returns overflow. This is the same as lhs.resize_assign(rhs, rhs.msb()), but returns true if the signed meaning of the integer is changed.

pub const fn or_assign(&mut self, rhs: &Self) -> Option<()>[src]

Or-assigns rhs to self

pub const fn and_assign(&mut self, rhs: &Self) -> Option<()>[src]

And-assigns rhs to self

pub const fn xor_assign(&mut self, rhs: &Self) -> Option<()>[src]

Xor-assigns rhs to self

pub const fn range_and_assign(&mut self, range: Range<usize>) -> Option<()>[src]

And-assigns a range of ones to self. Useful for masking. An empty or reversed range zeroes self. None is returned if range.start >= self.bw() or range.end > self.bw().

pub const fn usize_or_assign(&mut self, rhs: usize, shl: usize)[src]

Or-assigns rhs to self at a position shl. Set bits of rhs that are shifted beyond the bitwidth of self are truncated.

impl Bits[src]

pub const fn is_zero(&self) -> bool[src]

If self is zero

pub const fn is_umax(&self) -> bool[src]

If self is unsigned-maximum

pub const fn is_imax(&self) -> bool[src]

If self is signed-maximum

pub const fn is_imin(&self) -> bool[src]

If self is signed-minimum

pub const fn is_uone(&self) -> bool[src]

If self is unsigned-one

pub const fn const_eq(&self, rhs: &Self) -> Option<bool>[src]

Equality comparison, self == rhs

pub const fn const_ne(&self, rhs: &Self) -> Option<bool>[src]

Not-equal comparison, self != rhs

pub const fn ult(&self, rhs: &Self) -> Option<bool>[src]

Unsigned-less-than comparison, self < rhs

pub const fn ule(&self, rhs: &Self) -> Option<bool>[src]

Unsigned-less-than-or-equal comparison, self <= rhs

pub const fn ugt(&self, rhs: &Self) -> Option<bool>[src]

Unsigned-greater-than comparison, self > rhs

pub const fn uge(&self, rhs: &Self) -> Option<bool>[src]

Unsigned-greater-than-or-equal comparison, self >= rhs

pub const fn ilt(&self, rhs: &Self) -> Option<bool>[src]

Signed-less-than comparison, self < rhs

pub const fn ile(&self, rhs: &Self) -> Option<bool>[src]

Signed-less-than-or-equal comparison, self <= rhs

pub const fn igt(&self, rhs: &Self) -> Option<bool>[src]

Signed-greater-than comparison, self > rhs

pub const fn ige(&self, rhs: &Self) -> Option<bool>[src]

Signed-greater-than-or-equal comparison, self >= rhs

impl Bits[src]

const string representation conversion

note: see higher level allocating functions from the awint_ext crate for more.

pub const fn bytes_radix_assign(
    &mut self,
    sign: Option<bool>,
    src: &[u8],
    radix: u8,
    pad0: &mut Self,
    pad1: &mut Self
) -> Result<(), SerdeError>
[src]

Assigns to self the integer value represented by src in the given radix. If src should be interpreted as unsigned, sign should be None, otherwise it should be set to the sign. In order for this function to be const, two scratchpads pad0 and pad1 with the same bitwidth as self must be supplied, which can be mutated by the function in arbitrary ways.

Errors

self is not mutated if an error occurs. See crate::SerdeError for error conditions. The characters 0..=9, a..=z, and A..=Z are allowed depending on the radix. The char _ is ignored, and all other chars result in an error. src cannot be empty. The value of the string must be representable in the bitwidth of self with the specified sign, otherwise an overflow error is returned.

pub const fn to_bytes_radix(
    &self,
    signed: bool,
    dst: &mut [u8],
    radix: u8,
    upper: bool,
    pad: &mut Self
) -> Result<(), SerdeError>
[src]

Assigns the [u8] representation of self to dst, not including a sign indicator. signed specifies if self should be interpreted as signed. radix specifies the radix, and upper specifies if letters should be uppercase. In order for this function to be const, a scratchpad pad with the same bitwidth as self must be supplied. Note that if dst.len() is more than what is needed to store the representation, the leading bytes will all be set to b’0’.

Errors

Note: If an error is returned, dst may be set to anything

This function can fail from NonEqualWidths, InvalidRadix, and Overflow (if dst cannot represent the value of self). See crate::SerdeError.

impl Bits[src]

Division

These operations are not inplace unlike many other functions in this crate, because extra mutable space is needed in order to avoid allocation.

Note that signed divisions can overflow when duo.is_imin() and div.is_umax() (negative one in signed interpretation). The overflow results in quo.is_imin() and rem.is_zero().

Note about terminology: we like short three letter shorthands, but run into a problem where the first three letters of “divide”, “dividend”, and “divisor” all clash with each other. Additionally, the standard Rust terminology for a function returning a quotient is things such as i64::wrapping_div, which should have been named i64::wrapping_quo instead. Here, we choose to type out “divide” in full whenever the operation involves both quotients and remainders. We don’t use “num” or “den”, because it may cause confusion later if an awint crate gains rational number capabilities. We use “quo” for quotient and “rem” for remainder. We use “div” for divisor. That still leaves a name clash with dividend, so we choose to use the shorthand “duo”. This originates from the fact that for inplace division operations (which this crate does not have for performance purposes and avoiding allocation), the dividend is often subtracted from in the internal algorithms until it becomes the remainder, so that it serves two purposes.

pub const fn short_udivide_assign(&mut self, div: usize) -> Option<usize>[src]

Unsigned-divide-assign self by div, and returns the remainder. Returns None if div == 0.

pub const fn short_udivide_triop(
    &mut self,
    duo: &Self,
    div: usize
) -> Option<usize>
[src]

Unsigned-divides duo by div, sets self to the quotient, and returns the remainder. Returns None if self.bw() != duo.bw() or div == 0.

pub const fn udivide(
    quo: &mut Self,
    rem: &mut Self,
    duo: &Self,
    div: &Self
) -> Option<()>
[src]

Unsigned-divides duo by div and assigns the quotient to quo and remainder to rem. Returns None if any bitwidths are not equal or div.is_zero().

pub const fn idivide(
    quo: &mut Self,
    rem: &mut Self,
    duo: &mut Self,
    div: &mut Self
) -> Option<()>
[src]

Signed-divides duo by div and assigns the quotient to quo and remainder to rem. Returns None if any bitwidths are not equal or div.is_zero(). duo and div are marked mutable but their values are not changed by this function. They are mutable in order to prevent internal complications.

impl Bits[src]

pub const fn lsb(&self) -> bool[src]

Returns the least significant bit

pub const fn msb(&self) -> bool[src]

Returns the most significant bit

pub const fn lz(&self) -> usize[src]

Returns the number of leading zero bits

pub const fn tz(&self) -> usize[src]

Returns the number of trailing zero bits

pub const fn count_ones(&self) -> usize[src]

Returns the number of set ones

impl Bits[src]

pub const fn short_cin_mul(&mut self, cin: usize, rhs: usize) -> usize[src]

Assigns cin + (self * rhs) to self and returns the overflow

pub const fn short_mul_add_triop(
    &mut self,
    lhs: &Self,
    rhs: usize
) -> Option<bool>
[src]

Add-assigns lhs * rhs to self and returns if overflow happened

pub const fn mul_add_triop(&mut self, lhs: &Self, rhs: &Self) -> Option<()>[src]

Multiplies lhs by rhs and add-assigns the product to self. Three operands eliminates the need for an allocating temporary.

impl Bits[src]

pub const fn shl_assign(&mut self, s: usize) -> Option<()>[src]

Left-shifts-assigns by s bits. If s >= self.bw(), then None is returned and the Bits are left unchanged.

Left shifts can act as a very fast multiplication by a power of two for both the signed and unsigned interpretation of Bits.

pub const fn lshr_assign(&mut self, s: usize) -> Option<()>[src]

Logically-right-shift-assigns by s bits. If s >= self.bw(), then None is returned and the Bits are left unchanged.

Logical right shifts do not copy the sign bit, and thus can act as a very fast floored division by a power of two for the unsigned interpretation of Bits.

pub const fn ashr_assign(&mut self, s: usize) -> Option<()>[src]

Arithmetically-right-shift-assigns by s bits. If s >= self.bw(), then None is returned and the Bits are left unchanged.

Arithmetic right shifts copy the sign bit, and thus can act as a very fast floored division by a power of two for the signed interpretation of Bits. Note that signed division also diverges from this if s == (self.bw() - 1) because the corresponding positive value cannot be represented.

pub const fn rotl_assign(&mut self, s: usize) -> Option<()>[src]

Left-rotate-assigns by s bits. If s >= self.bw(), then None is returned and the Bits are left unchanged.

This function is equivalent to the following:

use awint::{inlawi, inlawi_zero, ExtAwi, InlAwi};
let mut awi_input = inlawi!(0x4321u16);
let mut awi_output = inlawi_zero!(16);
let input = awi_input.const_as_ref();
let output = awi_output.const_as_mut();
// rotate left by 4 bits or one hexadecimal digit
let shift = 4;

output.copy_assign(input).unwrap();
// temporary clone of the input
let mut tmp = ExtAwi::from(input);
if shift != 0 {
    if shift >= input.bw() {
        panic!();
    }
    output.shl_assign(shift).unwrap();
    tmp[..].lshr_assign(input.bw() - shift).unwrap();
    output.or_assign(&tmp[..]);
};

assert_eq!(awi_output, inlawi!(0x3214u16));
let mut using_rotate = ExtAwi::from(input);
using_rotate[..].rotl_assign(shift).unwrap();
assert_eq!(
    using_rotate.const_as_ref(),
    inlawi!(0x3214u16).const_as_ref()
);

// Note that slices are typed in a little-endian order opposite of
// how integers are typed, but they still visually rotate in the
// same way. This means `Rust`s built in slice rotation is in the
// opposite direction to integers and `Bits`
let mut array = [4, 3, 2, 1];
array.rotate_left(1);
assert_eq!(array, [3, 2, 1, 4]);
assert_eq!(0x4321u16.rotate_left(4), 0x3214);
let mut x = inlawi!(0x4321u16);
x.const_as_mut().rotl_assign(4);
// `Bits` has the preferred endianness
assert_eq!(x, inlawi!(0x3214u16));

Unlike the example above which needs cloning, this function avoids any allocation and has many optimized branches for different input sizes and shifts.

pub const fn rotr_assign(&mut self, s: usize) -> Option<()>[src]

Right-rotate-assigns by s bits. If s >= self.bw(), then None is returned and the Bits are left unchanged.

See Bits::rotl_assign for more details.

pub const fn reverse_bits(&mut self)[src]

Reverse-bit-order-assigns self. The least significant bit becomes the most significant bit, the second least significant bit becomes the second most significant bit, etc.

impl Bits[src]

Primitive assignment

If self.bw() is smaller than the primitive bitwidth, truncation will be used when copying bits from x to self. If the primitive is unsigned (or is a boolean), then zero extension will be used if self.bw() is larger than the primitive bitwidth. If the primitive is signed, then sign extension will be used if self.bw() is larger than the primitive bitwidth.

pub const fn usize_assign(&mut self, x: usize)[src]

pub const fn isize_assign(&mut self, x: isize)[src]

pub const fn u8_assign(&mut self, x: u8)[src]

pub const fn i8_assign(&mut self, x: i8)[src]

pub const fn u16_assign(&mut self, x: u16)[src]

pub const fn i16_assign(&mut self, x: i16)[src]

pub const fn u32_assign(&mut self, x: u32)[src]

pub const fn i32_assign(&mut self, x: i32)[src]

pub const fn u64_assign(&mut self, x: u64)[src]

pub const fn i64_assign(&mut self, x: i64)[src]

pub const fn u128_assign(&mut self, x: u128)[src]

pub const fn i128_assign(&mut self, x: i128)[src]

pub const fn bool_assign(&mut self, x: bool)[src]

impl Bits[src]

Primitive conversion

If self.bw() is larger than the primitive bitwidth, truncation will be used when copying the bits of self and returning them. If the primitive is unsigned, then zero extension will be used if self.bw() is smaller than the primitive bitwidth. If the primitive is signed, then sign extension will be used if self.bw() is smaller than the primitive bitwidth.

pub const fn to_usize(&self) -> usize[src]

pub const fn to_isize(&self) -> isize[src]

pub const fn to_u8(&self) -> u8[src]

pub const fn to_i8(&self) -> i8[src]

pub const fn to_u16(&self) -> u16[src]

pub const fn to_i16(&self) -> i16[src]

pub const fn to_u32(&self) -> u32[src]

pub const fn to_i32(&self) -> i32[src]

pub const fn to_u64(&self) -> u64[src]

pub const fn to_i64(&self) -> i64[src]

pub const fn to_u128(&self) -> u128[src]

pub const fn to_i128(&self) -> i128[src]

pub const fn to_bool(&self) -> bool[src]

impl Bits[src]

pub const fn inc_assign(&mut self, cin: bool) -> bool[src]

Increment-assigns self with a carry-in cin and returns the carry-out bit. If cin == true then one is added to self, otherwise nothing happens. false is always returned unless self.is_umax().

pub const fn dec_assign(&mut self, cin: bool) -> bool[src]

Decrement-assigns self with a carry-in cin and returns the carry-out bit. If cin == false then one is subtracted from self, otherwise nothing happens. true is always returned unless self.is_zero().

pub const fn neg_assign(&mut self)[src]

Negate-assigns self. Note that signed minimum values will overflow.

pub const fn abs_assign(&mut self)[src]

Absolute-value-assigns self. Note that signed minimum values will overflow.

pub const fn add_assign(&mut self, rhs: &Self) -> Option<()>[src]

Add-assigns by rhs

pub const fn sub_assign(&mut self, rhs: &Self) -> Option<()>[src]

Subtract-assigns by rhs

pub const fn rsb_assign(&mut self, rhs: &Self) -> Option<()>[src]

Reverse-subtract-assigns by rhs. Sets self to (-self) + rhs.

pub const fn cin_sum_triop(
    &mut self,
    cin: bool,
    lhs: &Self,
    rhs: &Self
) -> Option<(bool, bool)>
[src]

A general summation with carry-in cin and two inputs lhs and rhs. self is set to the sum. The unsigned overflow (equivalent to the carry-out bit) and the signed overflow is returned as a tuple. None is returned if any bitwidths do not match. If subtraction is desired, one of the operands can be negated.

Trait Implementations

impl<'a> AddAssign<&'a Bits> for Bits[src]

fn add_assign(&mut self, rhs: &'a Self)[src]

Performs the += operation. Read more

impl Binary for Bits[src]

Binary formatting.

use awint::{inlawi, InlAwi};
assert_eq!(format!("{:b}", inlawi!(11000101)), "0b11000101_u8");

fn fmt(&self, f: &mut Formatter<'_>) -> Result[src]

Formats the value using the given formatter.

impl<'a> BitAndAssign<&'a Bits> for Bits[src]

fn bitand_assign(&mut self, rhs: &'a Self)[src]

Performs the &= operation. Read more

impl<'a> BitOrAssign<&'a Bits> for Bits[src]

fn bitor_assign(&mut self, rhs: &'a Self)[src]

Performs the |= operation. Read more

impl<'a> BitXorAssign<&'a Bits> for Bits[src]

fn bitxor_assign(&mut self, rhs: &'a Self)[src]

Performs the ^= operation. Read more

impl Debug for Bits[src]

Forwards to the LowerHex impl.

fn fmt(&self, f: &mut Formatter<'_>) -> Result[src]

Formats the value using the given formatter. Read more

impl Hash for Bits[src]

fn hash<H: Hasher>(&self, state: &mut H)[src]

Feeds this value into the given Hasher. Read more

fn hash_slice<H>(data: &[Self], state: &mut H) where
    H: Hasher
1.3.0[src]

Feeds a slice of this type into the given Hasher. Read more

impl LowerHex for Bits[src]

Lowercase hexadecimal formatting.

use awint::{InlAwi, inlawi};
assert_eq!(format!("{:x}", inlawi!(0xfedcba9876543210u100)), "0xfedcba98_76543210_u100");

fn fmt(&self, f: &mut Formatter<'_>) -> Result[src]

Formats the value using the given formatter.

impl MulAssign<u8> for Bits[src]

fn mul_assign(&mut self, rhs: u8)[src]

Performs the *= operation. Read more

impl Octal for Bits[src]

Octal formatting.

use awint::{InlAwi, inlawi};
assert_eq!(format!("{:o}", inlawi!(0o776543210u100)), "0o7_76543210_u100");

fn fmt(&self, f: &mut Formatter<'_>) -> Result[src]

Formats the value using the given formatter.

impl PartialEq<Bits> for Bits[src]

If self and other have unmatching bit widths, false will be returned.

fn eq(&self, rhs: &Self) -> bool[src]

This method tests for self and other values to be equal, and is used by ==. Read more

#[must_use]
fn ne(&self, other: &Rhs) -> bool
1.0.0[src]

This method tests for !=.

impl Pointer for Bits[src]

fn fmt(&self, f: &mut Formatter<'_>) -> Result[src]

Formats the value using the given formatter.

impl ShlAssign<usize> for Bits[src]

fn shl_assign(&mut self, s: usize)[src]

Performs the <<= operation. Read more

impl<'a> SubAssign<&'a Bits> for Bits[src]

fn sub_assign(&mut self, rhs: &'a Self)[src]

Performs the -= operation. Read more

impl UpperHex for Bits[src]

Uppercase hexadecimal formatting.

use awint::{InlAwi, inlawi};
assert_eq!(format!("{:X}", inlawi!(0xFEDCBA9876543210u100)), "0xFEDCBA98_76543210_u100");

fn fmt(&self, f: &mut Formatter<'_>) -> Result[src]

Formats the value using the given formatter.

impl Eq for Bits[src]

If self and other have unmatching bit widths, false will be returned.

impl Send for Bits[src]

Bits is safe to send between threads since it does not own aliasing memory and has no reference counting mechanism like Rc.

impl Sync for Bits[src]

Bits is safe to share between threads since it does not own aliasing memory and has no mutable internal state like Cell or RefCell.

Auto Trait Implementations

impl !Sized for Bits

impl Unpin for Bits

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

pub fn type_id(&self) -> TypeId[src]

Gets the TypeId of self. Read more

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

pub fn borrow(&self) -> &T[src]

Immutably borrows from an owned value. Read more

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

pub fn borrow_mut(&mut self) -> &mut T[src]

Mutably borrows from an owned value. Read more