pub struct InlAwi<const BW: usize, const LEN: usize> { /* private fields */ }
Expand description

An arbitrary width integer with const generic bitwidth that can be stored inline on the stack like an array.

NOTE: Ideally, you could just type let _: InlAwi<100> = InlAwi<100>::zero(); if you wanted to specify and construct an InlAwi type with bitwidth 100. However, Rust’s lack of custom DST support and const generics limitations makes this currently impossible. The two const generic parameters of an InlAwi are part of a workaround for this. Typing out a let _: InlAwi<BW, LEN> = InlAwi<BW, LEN>::zero() should not be done directly because it is non-portable and relies on unstable internal details. Instead, you should use

let _: inlawi_ty!(100) = inlawi!(0u100); or let _ = <inlawi_ty!(100)>::zero(); using macros from the awint_macros crate.

See the crate level documentation of awint_macros for more macros and information.

// only needed if you are trying to use in `const` contexts
#![feature(const_trait_impl)]
#![feature(const_mut_refs)]
#![feature(const_option)]
use awint::{cc, inlawi, inlawi_ty, Bits, InlAwi};

const fn const_fn(mut lhs: &mut Bits, rhs: &Bits) {
    // `InlAwi` stored on the stack does no allocation
    let mut tmp = inlawi!(0i100);
    tmp.mul_add_assign(lhs, rhs).unwrap();
    cc!(tmp; lhs).unwrap();
}

// Because `InlAwi`'s construction functions are `const`, we can make full
// use of `Bits` `const` abilities
const AWI: inlawi_ty!(100) = {
    let mut x = inlawi!(123i100);
    let y = inlawi!(2i100);
    x.neg_assign(true);
    const_fn(&mut x, &y);
    x
};
const X: &'static Bits = &AWI;

assert_eq!(X, inlawi!(-246i100).const_as_ref());

Implementations

Returns a reference to self in the form of &Bits.

Returns a reference to self in the form of &mut Bits.

Returns the bitwidth of this type of InlAwi as a NonZeroUsize

Returns the bitwidth of this type of InlAwi as a usize

The same as Self::const_nzbw() except that it takes &self, this exists to help with macros

The same as Self::const_bw() except that it takes &self, this exists to help with macros

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

Zero-value construction with bitwidth BW

Unsigned-maximum-value construction with bitwidth BW

Signed-maximum-value construction with bitwidth BW

Signed-minimum-value construction with bitwidth BW

Unsigned-one-value construction with bitwidth BW

Creates an InlAwi with one bit set to this bool

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Methods from Deref<Target = Bits>

Returns the bitwidth as a NonZeroUsize

Returns the bitwidth as a usize

Assigns the bits of buf to self. If (buf.len() * 8) > self.bw() then the corresponding bits in buf beyond self.bw() are ignored. If (buf.len() * 8) < self.bw() then the rest of the bits in self are zeroed. This function is portable across target architecture pointer sizes and endianness.

Assigns the bits of self to buf. If (buf.len() * 8) > self.bw() then the corresponding bits in buf beyond self.bw() are zeroed. If (buf.len() * 8) < self.bw() then the bits of self beyond the buffer do nothing. This function is portable across target architecture pointer sizes and endianness.

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

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

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

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

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.

Not-assigns self

Copy-assigns the bits of rhs to self

Or-assigns rhs to self

And-assigns rhs to self

Xor-assigns rhs to self

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().

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

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.

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.

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.

If self is zero

If self is unsigned-maximum

If self is signed-maximum

If self is signed-minimum

If self is unsigned-one

Equality comparison, self == rhs

Not-equal comparison, self != rhs

Unsigned-less-than comparison, self < rhs

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

Unsigned-greater-than comparison, self > rhs

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

Signed-less-than comparison, self < rhs

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

Signed-greater-than comparison, self > rhs

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

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.

Assigns the [u8] representation of self to dst (sign indicators, prefixes, and postfixes not included). 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.

Unsigned-divides self by div, sets self to the quotient, and returns the remainder. Returns None if div == 0.

Returns the least significant bit

Returns the most significant bit

Gets the bit at inx bits from the least significant bit, returning None if inx >= self.bw()

Sets the bit at inx bits from the least significant bit, returning None if inx >= self.bw()

Returns the number of leading zero bits

Returns the number of trailing zero bits

Returns the number of significant bits, self.bw() - self.lz()

Returns the number of set ones

“Fielding” bitfields with targeted copy assigns. The bitwidths of self and rhs do not have to be equal, but the inputs must collectively obey width <= self.bw() && width <= rhs.bw() && to <= (self.bw() - width) && from <= (rhs.bw() - width) or else None is returned. width can be zero, in which case this function just checks the input correctness and does not mutate self.

This function works by copying a width sized bitfield from rhs at bitposition from and overwriting width bits at bitposition to in self. Only the width bits in self are mutated, any bits before and after the bitfield are left unchanged.

use awint::{Bits, inlawi, InlAwi};
// As an example, two hexadecimal digits will be overwritten
// starting with the 12th digit in `y` using a bitfield with
// value 0x42u8 extracted from `x`.
let x = inlawi!(0x11142111u50);
// the underscores are just for emphasis
let mut y = inlawi!(0xfd_ec_ba9876543210u100);
// from `x` digit place 3, we copy 2 digits to `y` digit place 12.
y.field(12 * 4, &x, 3 * 4, 2 * 4);
assert_eq!(y, inlawi!(0xfd_42_ba9876543210u100));

A specialization of Bits::field with from set to 0.

A specialization of Bits::field with to set to 0.

A specialization of Bits::field with to and from set to 0.

A specialization of Bits::field with width set to 1.

Copy entry from lookup table. Copies a self.bw() sized bitfield from lut at bit position inx.to_usize() * self.bw(). If lut.bw() != (self.bw() * (2^inx.bw())), None will be returned.

use awint::{Bits, inlawi, InlAwi};
let mut out = inlawi!(0u10);
// lookup table consisting of 4 10-bit entries
let lut = inlawi!(4u10, 3u10, 2u10, 1u10);
// the indexer has to have a bitwidth of 2 to index 2^2 = 4 entries
let mut inx = inlawi!(0u2);

// get the third entry (this is using zero indexing)
inx.usize_assign(2);
out.lut_assign(&lut, &inx).unwrap();
assert_eq!(out, inlawi!(3u10));

Set entry in lookup table. The inverse of Bits::lut_assign, this uses entry as a bitfield to overwrite part of self at bit position inx.to_usize() * entry.bw(). If self.bw() != (entry.bw() * (2^inx.bw())), None will be returned.

Multiplex by conditionally copy-assigning rhs to self if b

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

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

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

Multiply-assigns self by rhs. pad is a scratchpad that will be mutated arbitrarily.

Arbitrarily-unsigned-multiplies lhs by rhs and add-assigns the product to self. This function is equivalent to:

use awint::prelude::*;

fn arb_umul_assign(add: &mut Bits, lhs: &Bits, rhs: &Bits) {
    let mut resized_lhs = ExtAwi::zero(add.nzbw());
    // Note that this function is specified as unsigned,
    // because we use `zero_resize_assign`
    resized_lhs.zero_resize_assign(lhs);
    let mut resized_rhs = ExtAwi::zero(add.nzbw());
    resized_rhs.zero_resize_assign(rhs);
    add.mul_add_assign(&resized_lhs, &resized_rhs).unwrap();
}

except that it avoids allocation and is more efficient overall

Arbitrarily-signed-multiplies lhs by rhs and add-assigns the product to self. duo and div are marked mutable but their values are not changed by this function.

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.

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.

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.

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::prelude::*;
let mut input = inlawi!(0x4321u16);
let mut output = inlawi!(0u16);
// rotate left by 4 bits or one hexadecimal digit
let shift = 4;

// temporary clone of the input
let mut tmp = ExtAwi::from(input);
cc!(input; output).unwrap();
if shift != 0 {
    if shift >= input.bw() {
        // the actual function would return `None`
        panic!();
    }
    output.shl_assign(shift).unwrap();
    tmp.lshr_assign(input.bw() - shift).unwrap();
    output.or_assign(&tmp);
};

assert_eq!(output, inlawi!(0x3214u16));
let mut using_rotate = ExtAwi::from(input);
using_rotate.rotl_assign(shift).unwrap();
assert_eq!(using_rotate, extawi!(0x3214u16));

// 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.rotl_assign(4).unwrap();
// `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.

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.

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.

Funnel shift with power-of-two bitwidths. Returns None if 2*self.bw() != rhs.bw() || 2^s.bw() != self.bw(). A self.bw() sized field is assigned to self from rhs starting from the bit position s. The shift cannot overflow because of the restriction on the bitwidth of s.

use awint::prelude::*;
let mut lhs = inlawi!(0xffff_ffffu32);
let mut rhs = inlawi!(0xfedc_ba98_7654_3210u64);
// `lhs.bw()` must be a power of two, `s.bw()` here is
// `log_2(32) == 5`. The value of `s` is set to what bit
// of `rhs` should be the starting bit for `lhs`.
let mut s = inlawi!(12u5);
lhs.funnel(&rhs, &s).unwrap();
assert_eq!(lhs, inlawi!(0xa9876543_u32))

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().

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().

Negate-assigns self if neg is true. Note that signed minimum values will overflow.

Absolute-value-assigns self. Note that signed minimum values will overflow, unless self is interpreted as unsigned after a call to this function.

Add-assigns by rhs

Subtract-assigns by rhs

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

Negate-add-assigns by rhs. Negates conditionally on neg.

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

Converts this type into a mutable reference of the (usually inferred) input type.

Converts this type into a shared reference of the (usually inferred) input type.

Forwards to the corresponding impl for Bits

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Forwards to the corresponding impl for Bits

The resulting type after dereferencing.

Dereferences the value.

Mutably dereferences the value.

Forwards to the corresponding impl for Bits

Creates an ExtAwi from copying an InlAwi

Converts to this type from the input type.

Creates an InlAwi with one bit set to this bool

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Creates an InlAwi with the same bitwidth and bits as the integer

Feeds this value into the given Hasher. Read more

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

The returned type after indexing.

Performs the indexing (container[index]) operation. Read more

Performs the mutable indexing (container[index]) operation. Read more

Forwards to the corresponding impl for Bits

Forwards to the corresponding impl for Bits

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

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

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more

Forwards to the corresponding impl for Bits

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

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

InlAwi 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

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

Uses borrowed data to replace owned data, usually by cloning. Read more

Converts the given value to a String. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.