191 lines
4.5 KiB
Rust
191 lines
4.5 KiB
Rust
//! Simple heap-allocated vector.
|
|
|
|
#![cfg(feature = "alloc")]
|
|
#![doc(hidden)]
|
|
|
|
use crate::bigint;
|
|
#[cfg(not(feature = "std"))]
|
|
use alloc::vec::Vec;
|
|
use core::{cmp, ops};
|
|
#[cfg(feature = "std")]
|
|
use std::vec::Vec;
|
|
|
|
/// Simple heap vector implementation.
|
|
#[derive(Clone)]
|
|
pub struct HeapVec {
|
|
/// The heap-allocated buffer for the elements.
|
|
data: Vec<bigint::Limb>,
|
|
}
|
|
|
|
#[allow(clippy::new_without_default)]
|
|
impl HeapVec {
|
|
/// Construct an empty vector.
|
|
#[inline]
|
|
pub fn new() -> Self {
|
|
Self {
|
|
data: Vec::with_capacity(bigint::BIGINT_LIMBS),
|
|
}
|
|
}
|
|
|
|
/// Construct a vector from an existing slice.
|
|
#[inline]
|
|
pub fn try_from(x: &[bigint::Limb]) -> Option<Self> {
|
|
let mut vec = Self::new();
|
|
vec.try_extend(x)?;
|
|
Some(vec)
|
|
}
|
|
|
|
/// Sets the length of a vector.
|
|
///
|
|
/// This will explicitly set the size of the vector, without actually
|
|
/// modifying its buffers, so it is up to the caller to ensure that the
|
|
/// vector is actually the specified size.
|
|
///
|
|
/// # Safety
|
|
///
|
|
/// Safe as long as `len` is less than `self.capacity()` and has been initialized.
|
|
#[inline]
|
|
pub unsafe fn set_len(&mut self, len: usize) {
|
|
debug_assert!(len <= bigint::BIGINT_LIMBS);
|
|
unsafe { self.data.set_len(len) };
|
|
}
|
|
|
|
/// The number of elements stored in the vector.
|
|
#[inline]
|
|
pub fn len(&self) -> usize {
|
|
self.data.len()
|
|
}
|
|
|
|
/// If the vector is empty.
|
|
#[inline]
|
|
pub fn is_empty(&self) -> bool {
|
|
self.len() == 0
|
|
}
|
|
|
|
/// The number of items the vector can hold.
|
|
#[inline]
|
|
pub fn capacity(&self) -> usize {
|
|
self.data.capacity()
|
|
}
|
|
|
|
/// Append an item to the vector.
|
|
#[inline]
|
|
pub fn try_push(&mut self, value: bigint::Limb) -> Option<()> {
|
|
self.data.push(value);
|
|
Some(())
|
|
}
|
|
|
|
/// Remove an item from the end of the vector and return it, or None if empty.
|
|
#[inline]
|
|
pub fn pop(&mut self) -> Option<bigint::Limb> {
|
|
self.data.pop()
|
|
}
|
|
|
|
/// Copy elements from a slice and append them to the vector.
|
|
#[inline]
|
|
pub fn try_extend(&mut self, slc: &[bigint::Limb]) -> Option<()> {
|
|
self.data.extend_from_slice(slc);
|
|
Some(())
|
|
}
|
|
|
|
/// Try to resize the buffer.
|
|
///
|
|
/// If the new length is smaller than the current length, truncate
|
|
/// the input. If it's larger, then append elements to the buffer.
|
|
#[inline]
|
|
pub fn try_resize(&mut self, len: usize, value: bigint::Limb) -> Option<()> {
|
|
self.data.resize(len, value);
|
|
Some(())
|
|
}
|
|
|
|
// HI
|
|
|
|
/// Get the high 64 bits from the vector.
|
|
#[inline(always)]
|
|
pub fn hi64(&self) -> (u64, bool) {
|
|
bigint::hi64(&self.data)
|
|
}
|
|
|
|
// FROM
|
|
|
|
/// Create StackVec from u64 value.
|
|
#[inline(always)]
|
|
pub fn from_u64(x: u64) -> Self {
|
|
bigint::from_u64(x)
|
|
}
|
|
|
|
// MATH
|
|
|
|
/// Normalize the integer, so any leading zero values are removed.
|
|
#[inline]
|
|
pub fn normalize(&mut self) {
|
|
bigint::normalize(self)
|
|
}
|
|
|
|
/// Get if the big integer is normalized.
|
|
#[inline]
|
|
pub fn is_normalized(&self) -> bool {
|
|
bigint::is_normalized(self)
|
|
}
|
|
|
|
/// AddAssign small integer.
|
|
#[inline]
|
|
pub fn add_small(&mut self, y: bigint::Limb) -> Option<()> {
|
|
bigint::small_add(self, y)
|
|
}
|
|
|
|
/// MulAssign small integer.
|
|
#[inline]
|
|
pub fn mul_small(&mut self, y: bigint::Limb) -> Option<()> {
|
|
bigint::small_mul(self, y)
|
|
}
|
|
}
|
|
|
|
impl PartialEq for HeapVec {
|
|
#[inline]
|
|
#[allow(clippy::op_ref)]
|
|
fn eq(&self, other: &Self) -> bool {
|
|
use core::ops::Deref;
|
|
self.len() == other.len() && self.deref() == other.deref()
|
|
}
|
|
}
|
|
|
|
impl Eq for HeapVec {
|
|
}
|
|
|
|
impl cmp::PartialOrd for HeapVec {
|
|
#[inline]
|
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
Some(bigint::compare(self, other))
|
|
}
|
|
}
|
|
|
|
impl cmp::Ord for HeapVec {
|
|
#[inline]
|
|
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
bigint::compare(self, other)
|
|
}
|
|
}
|
|
|
|
impl ops::Deref for HeapVec {
|
|
type Target = [bigint::Limb];
|
|
#[inline]
|
|
fn deref(&self) -> &[bigint::Limb] {
|
|
&self.data
|
|
}
|
|
}
|
|
|
|
impl ops::DerefMut for HeapVec {
|
|
#[inline]
|
|
fn deref_mut(&mut self) -> &mut [bigint::Limb] {
|
|
&mut self.data
|
|
}
|
|
}
|
|
|
|
impl ops::MulAssign<&[bigint::Limb]> for HeapVec {
|
|
#[inline]
|
|
fn mul_assign(&mut self, rhs: &[bigint::Limb]) {
|
|
bigint::large_mul(self, rhs).unwrap();
|
|
}
|
|
}
|