pub struct BitVec<B = u32> {
pub(crate) storage: Vec<B>,
pub(crate) nbits: usize,
}
Expand description
The bitvector type.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(10, false);
// insert all primes less than 10
bv.set(2, true);
bv.set(3, true);
bv.set(5, true);
bv.set(7, true);
println!("{:?}", bv);
println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
// flip all values in bitvector, producing non-primes less than 10
bv.negate();
println!("{:?}", bv);
println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
// reset bitvector to empty
bv.clear();
println!("{:?}", bv);
println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
Fields§
§storage: Vec<B>
Internal representation of the bit vector
nbits: usize
The number of valid bits in the internal representation
Implementations§
source§impl BitVec<u32>
impl BitVec<u32>
sourcepub fn from_elem(nbits: usize, bit: bool) -> Self
pub fn from_elem(nbits: usize, bit: bool) -> Self
Creates a BitVec
that holds nbits
elements, setting each element
to bit
.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(10, false);
assert_eq!(bv.len(), 10);
for x in bv.iter() {
assert_eq!(x, false);
}
sourcepub fn with_capacity(nbits: usize) -> Self
pub fn with_capacity(nbits: usize) -> Self
Constructs a new, empty BitVec
with the specified capacity.
The bitvector will be able to hold at least capacity
bits without
reallocating. If capacity
is 0, it will not allocate.
It is important to note that this function does not specify the length of the returned bitvector, but only the capacity.
sourcepub fn from_bytes(bytes: &[u8]) -> Self
pub fn from_bytes(bytes: &[u8]) -> Self
Transforms a byte-vector into a BitVec
. Each byte becomes eight bits,
with the most significant bits of each byte coming first. Each
bit becomes true
if equal to 1 or false
if equal to 0.
§Examples
use bit_vec::BitVec;
let bv = BitVec::from_bytes(&[0b10100000, 0b00010010]);
assert!(bv.eq_vec(&[true, false, true, false,
false, false, false, false,
false, false, false, true,
false, false, true, false]));
source§impl<B: BitBlock> BitVec<B>
impl<B: BitBlock> BitVec<B>
sourcepub(crate) fn process<F>(&mut self, other: &BitVec<B>, op: F) -> boolwhere
F: FnMut(B, B) -> B,
pub(crate) fn process<F>(&mut self, other: &BitVec<B>, op: F) -> boolwhere
F: FnMut(B, B) -> B,
Applies the given operation to the blocks of self and other, and sets self to be the result. This relies on the caller not to corrupt the last word.
sourcepub(crate) fn blocks_mut(&mut self) -> IterMut<'_, B> ⓘ
pub(crate) fn blocks_mut(&mut self) -> IterMut<'_, B> ⓘ
Iterator over mutable refs to the underlying blocks of data.
sourcepub fn storage(&self) -> &[B]
pub fn storage(&self) -> &[B]
Exposes the raw block storage of this BitVec
.
Only really intended for BitSet
.
sourcepub unsafe fn storage_mut(&mut self) -> &mut Vec<B>
pub unsafe fn storage_mut(&mut self) -> &mut Vec<B>
Exposes the raw block storage of this BitVec
.
§Safety
Can probably cause unsafety. Only really intended for BitSet
.
sourcepub(crate) fn last_block_with_mask(&self) -> Option<(B, B)>
pub(crate) fn last_block_with_mask(&self) -> Option<(B, B)>
Helper for procedures involving spare space in the last block.
sourcepub(crate) fn last_block_mut_with_mask(&mut self) -> Option<(&mut B, B)>
pub(crate) fn last_block_mut_with_mask(&mut self) -> Option<(&mut B, B)>
Helper for procedures involving spare space in the last block.
sourcepub(crate) fn fix_last_block(&mut self)
pub(crate) fn fix_last_block(&mut self)
An operation might screw up the unused bits in the last block of the
BitVec
. As per (3), it’s assumed to be all 0s. This method fixes it up.
sourcepub(crate) fn fix_last_block_with_ones(&mut self)
pub(crate) fn fix_last_block_with_ones(&mut self)
Operations such as change detection for xnor, nor and nand are easiest to implement when unused bits are all set to 1s.
sourcepub(crate) fn is_last_block_fixed(&self) -> bool
pub(crate) fn is_last_block_fixed(&self) -> bool
Check whether last block’s invariant is fine.
sourcepub(crate) fn ensure_invariant(&self)
pub(crate) fn ensure_invariant(&self)
Ensure the invariant for the last block.
An operation might screw up the unused bits in the last block of the
BitVec
.
This method fails in case the last block is not fixed. The check is skipped outside testing.
sourcepub fn get(&self, i: usize) -> Option<bool>
pub fn get(&self, i: usize) -> Option<bool>
Retrieves the value at index i
, or None
if the index is out of bounds.
§Examples
use bit_vec::BitVec;
let bv = BitVec::from_bytes(&[0b01100000]);
assert_eq!(bv.get(0), Some(false));
assert_eq!(bv.get(1), Some(true));
assert_eq!(bv.get(100), None);
// Can also use array indexing
assert_eq!(bv[1], true);
sourcepub unsafe fn get_unchecked(&self, i: usize) -> bool
pub unsafe fn get_unchecked(&self, i: usize) -> bool
Retrieves the value at index i
, without doing bounds checking.
For a safe alternative, see get
.
§Safety
Calling this method with an out-of-bounds index is undefined behavior even if the resulting reference is not used.
§Examples
use bit_vec::BitVec;
let bv = BitVec::from_bytes(&[0b01100000]);
unsafe {
assert_eq!(bv.get_unchecked(0), false);
assert_eq!(bv.get_unchecked(1), true);
}
sourcepub fn get_mut(&mut self, index: usize) -> Option<MutBorrowedBit<'_, B>>
pub fn get_mut(&mut self, index: usize) -> Option<MutBorrowedBit<'_, B>>
Retrieves a smart pointer to the value at index i
, or None
if the index is out of bounds.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_bytes(&[0b01100000]);
*bv.get_mut(0).unwrap() = true;
*bv.get_mut(1).unwrap() = false;
assert!(bv.get_mut(100).is_none());
assert_eq!(bv, BitVec::from_bytes(&[0b10100000]));
sourcepub unsafe fn get_unchecked_mut(
&mut self,
index: usize,
) -> MutBorrowedBit<'_, B>
pub unsafe fn get_unchecked_mut( &mut self, index: usize, ) -> MutBorrowedBit<'_, B>
Retrieves a smart pointer to the value at index i
, without doing bounds checking.
§Safety
Calling this method with out-of-bounds index
may cause undefined behavior even when
the result is not used.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_bytes(&[0b01100000]);
unsafe {
*bv.get_unchecked_mut(0) = true;
*bv.get_unchecked_mut(1) = false;
}
assert_eq!(bv, BitVec::from_bytes(&[0b10100000]));
sourcepub fn set_all(&mut self)
pub fn set_all(&mut self)
Sets all bits to 1.
§Examples
use bit_vec::BitVec;
let before = 0b01100000;
let after = 0b11111111;
let mut bv = BitVec::from_bytes(&[before]);
bv.set_all();
assert_eq!(bv, BitVec::from_bytes(&[after]));
sourcepub fn negate(&mut self)
pub fn negate(&mut self)
Flips all bits.
§Examples
use bit_vec::BitVec;
let before = 0b01100000;
let after = 0b10011111;
let mut bv = BitVec::from_bytes(&[before]);
bv.negate();
assert_eq!(bv, BitVec::from_bytes(&[after]));
sourcepub fn union(&mut self, other: &Self) -> bool
👎Deprecated since 0.7.0: Please use the ‘or’ function instead
pub fn union(&mut self, other: &Self) -> bool
Calculates the union of two bitvectors. This acts like the bitwise or
function.
Sets self
to the union of self
and other
. Both bitvectors must be
the same length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different lengths.
§Examples
use bit_vec::BitVec;
let a = 0b01100100;
let b = 0b01011010;
let res = 0b01111110;
let mut a = BitVec::from_bytes(&[a]);
let b = BitVec::from_bytes(&[b]);
assert!(a.union(&b));
assert_eq!(a, BitVec::from_bytes(&[res]));
sourcepub fn intersect(&mut self, other: &Self) -> bool
👎Deprecated since 0.7.0: Please use the ‘and’ function instead
pub fn intersect(&mut self, other: &Self) -> bool
Calculates the intersection of two bitvectors. This acts like the
bitwise and
function.
Sets self
to the intersection of self
and other
. Both bitvectors
must be the same length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different lengths.
§Examples
use bit_vec::BitVec;
let a = 0b01100100;
let b = 0b01011010;
let res = 0b01000000;
let mut a = BitVec::from_bytes(&[a]);
let b = BitVec::from_bytes(&[b]);
assert!(a.intersect(&b));
assert_eq!(a, BitVec::from_bytes(&[res]));
sourcepub fn or(&mut self, other: &Self) -> bool
pub fn or(&mut self, other: &Self) -> bool
Calculates the bitwise or
of two bitvectors.
Sets self
to the union of self
and other
. Both bitvectors must be
the same length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different lengths.
§Examples
use bit_vec::BitVec;
let a = 0b01100100;
let b = 0b01011010;
let res = 0b01111110;
let mut a = BitVec::from_bytes(&[a]);
let b = BitVec::from_bytes(&[b]);
assert!(a.or(&b));
assert_eq!(a, BitVec::from_bytes(&[res]));
sourcepub fn and(&mut self, other: &Self) -> bool
pub fn and(&mut self, other: &Self) -> bool
Calculates the bitwise and
of two bitvectors.
Sets self
to the intersection of self
and other
. Both bitvectors
must be the same length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different lengths.
§Examples
use bit_vec::BitVec;
let a = 0b01100100;
let b = 0b01011010;
let res = 0b01000000;
let mut a = BitVec::from_bytes(&[a]);
let b = BitVec::from_bytes(&[b]);
assert!(a.and(&b));
assert_eq!(a, BitVec::from_bytes(&[res]));
sourcepub fn difference(&mut self, other: &Self) -> bool
pub fn difference(&mut self, other: &Self) -> bool
Calculates the difference between two bitvectors.
Sets each element of self
to the value of that element minus the
element of other
at the same index. Both bitvectors must be the same
length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different length.
§Examples
use bit_vec::BitVec;
let a = 0b01100100;
let b = 0b01011010;
let a_b = 0b00100100; // a - b
let b_a = 0b00011010; // b - a
let mut bva = BitVec::from_bytes(&[a]);
let bvb = BitVec::from_bytes(&[b]);
assert!(bva.difference(&bvb));
assert_eq!(bva, BitVec::from_bytes(&[a_b]));
let bva = BitVec::from_bytes(&[a]);
let mut bvb = BitVec::from_bytes(&[b]);
assert!(bvb.difference(&bva));
assert_eq!(bvb, BitVec::from_bytes(&[b_a]));
sourcepub fn xor(&mut self, other: &Self) -> bool
pub fn xor(&mut self, other: &Self) -> bool
Calculates the xor of two bitvectors.
Sets self
to the xor of self
and other
. Both bitvectors must be
the same length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different length.
§Examples
use bit_vec::BitVec;
let a = 0b01100110;
let b = 0b01010100;
let res = 0b00110010;
let mut a = BitVec::from_bytes(&[a]);
let b = BitVec::from_bytes(&[b]);
assert!(a.xor(&b));
assert_eq!(a, BitVec::from_bytes(&[res]));
sourcepub fn nand(&mut self, other: &Self) -> bool
pub fn nand(&mut self, other: &Self) -> bool
Calculates the nand of two bitvectors.
Sets self
to the nand of self
and other
. Both bitvectors must be
the same length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different length.
§Examples
use bit_vec::BitVec;
let a = 0b01100110;
let b = 0b01010100;
let res = 0b10111011;
let mut a = BitVec::from_bytes(&[a]);
let b = BitVec::from_bytes(&[b]);
assert!(a.nand(&b));
assert_eq!(a, BitVec::from_bytes(&[res]));
sourcepub fn nor(&mut self, other: &Self) -> bool
pub fn nor(&mut self, other: &Self) -> bool
Calculates the nor of two bitvectors.
Sets self
to the nor of self
and other
. Both bitvectors must be
the same length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different length.
§Examples
use bit_vec::BitVec;
let a = 0b01100110;
let b = 0b01010100;
let res = 0b10001001;
let mut a = BitVec::from_bytes(&[a]);
let b = BitVec::from_bytes(&[b]);
assert!(a.nor(&b));
assert_eq!(a, BitVec::from_bytes(&[res]));
sourcepub fn xnor(&mut self, other: &Self) -> bool
pub fn xnor(&mut self, other: &Self) -> bool
Calculates the xnor of two bitvectors.
Sets self
to the xnor of self
and other
. Both bitvectors must be
the same length. Returns true
if self
changed.
§Panics
Panics if the bitvectors are of different length.
§Examples
use bit_vec::BitVec;
let a = 0b01100110;
let b = 0b01010100;
let res = 0b11001101;
let mut a = BitVec::from_bytes(&[a]);
let b = BitVec::from_bytes(&[b]);
assert!(a.xnor(&b));
assert_eq!(a, BitVec::from_bytes(&[res]));
sourcepub fn all(&self) -> bool
pub fn all(&self) -> bool
Returns true
if all bits are 1.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(5, true);
assert_eq!(bv.all(), true);
bv.set(1, false);
assert_eq!(bv.all(), false);
sourcepub fn count_ones(&self) -> u64
pub fn count_ones(&self) -> u64
Returns the number of ones in the binary representation.
Also known as the Hamming weight.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(100, true);
assert_eq!(bv.count_ones(), 100);
bv.set(50, false);
assert_eq!(bv.count_ones(), 99);
sourcepub fn count_zeros(&self) -> u64
pub fn count_zeros(&self) -> u64
Returns the number of zeros in the binary representation.
Also known as the opposite of Hamming weight.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(100, false);
assert_eq!(bv.count_zeros(), 100);
bv.set(50, true);
assert_eq!(bv.count_zeros(), 99);
sourcepub fn iter(&self) -> Iter<'_, B> ⓘ
pub fn iter(&self) -> Iter<'_, B> ⓘ
Returns an iterator over the elements of the vector in order.
§Examples
use bit_vec::BitVec;
let bv = BitVec::from_bytes(&[0b01110100, 0b10010010]);
assert_eq!(bv.iter().filter(|x| *x).count(), 7);
sourcepub fn iter_mut(&mut self) -> IterMut<'_, B> ⓘ
pub fn iter_mut(&mut self) -> IterMut<'_, B> ⓘ
Returns an iterator over mutable smart pointers to the elements of the vector in order.
§Examples
use bit_vec::BitVec;
let mut a = BitVec::from_elem(8, false);
a.iter_mut().enumerate().for_each(|(index, mut bit)| {
*bit = if index % 2 == 1 { true } else { false };
});
assert!(a.eq_vec(&[
false, true, false, true, false, true, false, true
]));
sourcepub fn append(&mut self, other: &mut Self)
pub fn append(&mut self, other: &mut Self)
Moves all bits from other
into Self
, leaving other
empty.
§Examples
use bit_vec::BitVec;
let mut a = BitVec::from_bytes(&[0b10000000]);
let mut b = BitVec::from_bytes(&[0b01100001]);
a.append(&mut b);
assert_eq!(a.len(), 16);
assert_eq!(b.len(), 0);
assert!(a.eq_vec(&[true, false, false, false, false, false, false, false,
false, true, true, false, false, false, false, true]));
sourcepub fn split_off(&mut self, at: usize) -> Self
pub fn split_off(&mut self, at: usize) -> Self
Splits the BitVec
into two at the given bit,
retaining the first half in-place and returning the second one.
§Panics
Panics if at
is out of bounds.
§Examples
use bit_vec::BitVec;
let mut a = BitVec::new();
a.push(true);
a.push(false);
a.push(false);
a.push(true);
let b = a.split_off(2);
assert_eq!(a.len(), 2);
assert_eq!(b.len(), 2);
assert!(a.eq_vec(&[true, false]));
assert!(b.eq_vec(&[false, true]));
sourcepub fn none(&self) -> bool
pub fn none(&self) -> bool
Returns true
if all bits are 0.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(10, false);
assert_eq!(bv.none(), true);
bv.set(3, true);
assert_eq!(bv.none(), false);
sourcepub fn any(&self) -> bool
pub fn any(&self) -> bool
Returns true
if any bit is 1.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(10, false);
assert_eq!(bv.any(), false);
bv.set(3, true);
assert_eq!(bv.any(), true);
sourcepub fn to_bytes(&self) -> Vec<u8>
pub fn to_bytes(&self) -> Vec<u8>
Organises the bits into bytes, such that the first bit in the
BitVec
becomes the high-order bit of the first byte. If the
size of the BitVec
is not a multiple of eight then trailing bits
will be filled-in with false
.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(3, true);
bv.set(1, false);
assert_eq!(bv.to_bytes(), [0b10100000]);
let mut bv = BitVec::from_elem(9, false);
bv.set(2, true);
bv.set(8, true);
assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]);
sourcepub fn eq_vec(&self, v: &[bool]) -> bool
pub fn eq_vec(&self, v: &[bool]) -> bool
Compares a BitVec
to a slice of bool
s.
Both the BitVec
and slice must have the same length.
§Panics
Panics if the BitVec
and slice are of different length.
§Examples
use bit_vec::BitVec;
let bv = BitVec::from_bytes(&[0b10100000]);
assert!(bv.eq_vec(&[true, false, true, false,
false, false, false, false]));
sourcepub fn truncate(&mut self, len: usize)
pub fn truncate(&mut self, len: usize)
Shortens a BitVec
, dropping excess elements.
If len
is greater than the vector’s current length, this has no
effect.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_bytes(&[0b01001011]);
bv.truncate(2);
assert!(bv.eq_vec(&[false, true]));
sourcepub fn reserve(&mut self, additional: usize)
pub fn reserve(&mut self, additional: usize)
Reserves capacity for at least additional
more bits to be inserted in the given
BitVec
. The collection may reserve more space to avoid frequent reallocations.
§Panics
Panics if the new capacity overflows usize
.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(3, false);
bv.reserve(10);
assert_eq!(bv.len(), 3);
assert!(bv.capacity() >= 13);
sourcepub fn reserve_exact(&mut self, additional: usize)
pub fn reserve_exact(&mut self, additional: usize)
Reserves the minimum capacity for exactly additional
more bits to be inserted in the
given BitVec
. Does nothing if the capacity is already sufficient.
Note that the allocator may give the collection more space than it requests. Therefore
capacity can not be relied upon to be precisely minimal. Prefer reserve
if future
insertions are expected.
§Panics
Panics if the new capacity overflows usize
.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_elem(3, false);
bv.reserve(10);
assert_eq!(bv.len(), 3);
assert!(bv.capacity() >= 13);
sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the capacity in bits for this bit vector. Inserting any element less than this amount will not trigger a resizing.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::new();
bv.reserve(10);
assert!(bv.capacity() >= 10);
sourcepub fn pop(&mut self) -> Option<bool>
pub fn pop(&mut self) -> Option<bool>
Removes the last bit from the BitVec
, and returns it. Returns None
if the BitVec
is empty.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::from_bytes(&[0b01001001]);
assert_eq!(bv.pop(), Some(true));
assert_eq!(bv.pop(), Some(false));
assert_eq!(bv.len(), 6);
sourcepub fn push(&mut self, elem: bool)
pub fn push(&mut self, elem: bool)
Pushes a bool
onto the end.
§Examples
use bit_vec::BitVec;
let mut bv = BitVec::new();
bv.push(true);
bv.push(false);
assert!(bv.eq_vec(&[true, false]));
sourcepub unsafe fn set_len(&mut self, len: usize)
pub unsafe fn set_len(&mut self, len: usize)
Sets the number of bits that this BitVec
considers initialized.
§Safety
Almost certainly can cause bad stuff. Only really intended for BitSet
.
sourcepub fn shrink_to_fit(&mut self)
pub fn shrink_to_fit(&mut self)
Shrinks the capacity of the underlying storage as much as possible.
It will drop down as close as possible to the length but the allocator may still inform the underlying storage that there is space for a few more elements/bits.
sourcepub fn insert(&mut self, at: usize, bit: bool)
pub fn insert(&mut self, at: usize, bit: bool)
Inserts a given bit at index at
, shifting all bits after by one
§Panics
Panics if at
is out of bounds for BitVec
’s length (that is, if at > BitVec::len()
)
§Examples
use bit_vec::BitVec;
let mut b = BitVec::new();
b.push(true);
b.push(true);
b.insert(1, false);
assert!(b.eq_vec(&[true, false, true]));
§Time complexity
Takes O(len
) time. All items after the insertion index must be
shifted to the right. In the worst case, all elements are shifted when
the insertion index is 0.
Trait Implementations§
source§impl<B: BitBlock> Extend<bool> for BitVec<B>
impl<B: BitBlock> Extend<bool> for BitVec<B>
source§fn extend<I: IntoIterator<Item = bool>>(&mut self, iterable: I)
fn extend<I: IntoIterator<Item = bool>>(&mut self, iterable: I)
source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)source§impl<'a, B: BitBlock> IntoIterator for &'a BitVec<B>
impl<'a, B: BitBlock> IntoIterator for &'a BitVec<B>
source§impl<B: BitBlock> IntoIterator for BitVec<B>
impl<B: BitBlock> IntoIterator for BitVec<B>
source§impl<B: BitBlock> Ord for BitVec<B>
impl<B: BitBlock> Ord for BitVec<B>
source§impl<B: BitBlock> PartialOrd for BitVec<B>
impl<B: BitBlock> PartialOrd for BitVec<B>
impl<B: BitBlock> Eq for BitVec<B>
Auto Trait Implementations§
impl<B> Freeze for BitVec<B>
impl<B> RefUnwindSafe for BitVec<B>where
B: RefUnwindSafe,
impl<B> Send for BitVec<B>where
B: Send,
impl<B> Sync for BitVec<B>where
B: Sync,
impl<B> Unpin for BitVec<B>where
B: Unpin,
impl<B> UnwindSafe for BitVec<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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)