1cbd624adSopenharmony_ci//! Simple heap-allocated vector.
2cbd624adSopenharmony_ci
3cbd624adSopenharmony_ci#![cfg(feature = "alloc")]
4cbd624adSopenharmony_ci#![doc(hidden)]
5cbd624adSopenharmony_ci
6cbd624adSopenharmony_ciuse crate::bigint;
7cbd624adSopenharmony_ci#[cfg(not(feature = "std"))]
8cbd624adSopenharmony_ciuse alloc::vec::Vec;
9cbd624adSopenharmony_ciuse core::{cmp, ops};
10cbd624adSopenharmony_ci#[cfg(feature = "std")]
11cbd624adSopenharmony_ciuse std::vec::Vec;
12cbd624adSopenharmony_ci
13cbd624adSopenharmony_ci/// Simple heap vector implementation.
14cbd624adSopenharmony_ci#[derive(Clone)]
15cbd624adSopenharmony_cipub struct HeapVec {
16cbd624adSopenharmony_ci    /// The heap-allocated buffer for the elements.
17cbd624adSopenharmony_ci    data: Vec<bigint::Limb>,
18cbd624adSopenharmony_ci}
19cbd624adSopenharmony_ci
20cbd624adSopenharmony_ci#[allow(clippy::new_without_default)]
21cbd624adSopenharmony_ciimpl HeapVec {
22cbd624adSopenharmony_ci    /// Construct an empty vector.
23cbd624adSopenharmony_ci    #[inline]
24cbd624adSopenharmony_ci    pub fn new() -> Self {
25cbd624adSopenharmony_ci        Self {
26cbd624adSopenharmony_ci            data: Vec::with_capacity(bigint::BIGINT_LIMBS),
27cbd624adSopenharmony_ci        }
28cbd624adSopenharmony_ci    }
29cbd624adSopenharmony_ci
30cbd624adSopenharmony_ci    /// Construct a vector from an existing slice.
31cbd624adSopenharmony_ci    #[inline]
32cbd624adSopenharmony_ci    pub fn try_from(x: &[bigint::Limb]) -> Option<Self> {
33cbd624adSopenharmony_ci        let mut vec = Self::new();
34cbd624adSopenharmony_ci        vec.try_extend(x)?;
35cbd624adSopenharmony_ci        Some(vec)
36cbd624adSopenharmony_ci    }
37cbd624adSopenharmony_ci
38cbd624adSopenharmony_ci    /// Sets the length of a vector.
39cbd624adSopenharmony_ci    ///
40cbd624adSopenharmony_ci    /// This will explicitly set the size of the vector, without actually
41cbd624adSopenharmony_ci    /// modifying its buffers, so it is up to the caller to ensure that the
42cbd624adSopenharmony_ci    /// vector is actually the specified size.
43cbd624adSopenharmony_ci    ///
44cbd624adSopenharmony_ci    /// # Safety
45cbd624adSopenharmony_ci    ///
46cbd624adSopenharmony_ci    /// Safe as long as `len` is less than `self.capacity()` and has been initialized.
47cbd624adSopenharmony_ci    #[inline]
48cbd624adSopenharmony_ci    pub unsafe fn set_len(&mut self, len: usize) {
49cbd624adSopenharmony_ci        debug_assert!(len <= bigint::BIGINT_LIMBS);
50cbd624adSopenharmony_ci        unsafe { self.data.set_len(len) };
51cbd624adSopenharmony_ci    }
52cbd624adSopenharmony_ci
53cbd624adSopenharmony_ci    /// The number of elements stored in the vector.
54cbd624adSopenharmony_ci    #[inline]
55cbd624adSopenharmony_ci    pub fn len(&self) -> usize {
56cbd624adSopenharmony_ci        self.data.len()
57cbd624adSopenharmony_ci    }
58cbd624adSopenharmony_ci
59cbd624adSopenharmony_ci    /// If the vector is empty.
60cbd624adSopenharmony_ci    #[inline]
61cbd624adSopenharmony_ci    pub fn is_empty(&self) -> bool {
62cbd624adSopenharmony_ci        self.len() == 0
63cbd624adSopenharmony_ci    }
64cbd624adSopenharmony_ci
65cbd624adSopenharmony_ci    /// The number of items the vector can hold.
66cbd624adSopenharmony_ci    #[inline]
67cbd624adSopenharmony_ci    pub fn capacity(&self) -> usize {
68cbd624adSopenharmony_ci        self.data.capacity()
69cbd624adSopenharmony_ci    }
70cbd624adSopenharmony_ci
71cbd624adSopenharmony_ci    /// Append an item to the vector.
72cbd624adSopenharmony_ci    #[inline]
73cbd624adSopenharmony_ci    pub fn try_push(&mut self, value: bigint::Limb) -> Option<()> {
74cbd624adSopenharmony_ci        self.data.push(value);
75cbd624adSopenharmony_ci        Some(())
76cbd624adSopenharmony_ci    }
77cbd624adSopenharmony_ci
78cbd624adSopenharmony_ci    /// Remove an item from the end of the vector and return it, or None if empty.
79cbd624adSopenharmony_ci    #[inline]
80cbd624adSopenharmony_ci    pub fn pop(&mut self) -> Option<bigint::Limb> {
81cbd624adSopenharmony_ci        self.data.pop()
82cbd624adSopenharmony_ci    }
83cbd624adSopenharmony_ci
84cbd624adSopenharmony_ci    /// Copy elements from a slice and append them to the vector.
85cbd624adSopenharmony_ci    #[inline]
86cbd624adSopenharmony_ci    pub fn try_extend(&mut self, slc: &[bigint::Limb]) -> Option<()> {
87cbd624adSopenharmony_ci        self.data.extend_from_slice(slc);
88cbd624adSopenharmony_ci        Some(())
89cbd624adSopenharmony_ci    }
90cbd624adSopenharmony_ci
91cbd624adSopenharmony_ci    /// Try to resize the buffer.
92cbd624adSopenharmony_ci    ///
93cbd624adSopenharmony_ci    /// If the new length is smaller than the current length, truncate
94cbd624adSopenharmony_ci    /// the input. If it's larger, then append elements to the buffer.
95cbd624adSopenharmony_ci    #[inline]
96cbd624adSopenharmony_ci    pub fn try_resize(&mut self, len: usize, value: bigint::Limb) -> Option<()> {
97cbd624adSopenharmony_ci        self.data.resize(len, value);
98cbd624adSopenharmony_ci        Some(())
99cbd624adSopenharmony_ci    }
100cbd624adSopenharmony_ci
101cbd624adSopenharmony_ci    // HI
102cbd624adSopenharmony_ci
103cbd624adSopenharmony_ci    /// Get the high 64 bits from the vector.
104cbd624adSopenharmony_ci    #[inline(always)]
105cbd624adSopenharmony_ci    pub fn hi64(&self) -> (u64, bool) {
106cbd624adSopenharmony_ci        bigint::hi64(&self.data)
107cbd624adSopenharmony_ci    }
108cbd624adSopenharmony_ci
109cbd624adSopenharmony_ci    // FROM
110cbd624adSopenharmony_ci
111cbd624adSopenharmony_ci    /// Create StackVec from u64 value.
112cbd624adSopenharmony_ci    #[inline(always)]
113cbd624adSopenharmony_ci    pub fn from_u64(x: u64) -> Self {
114cbd624adSopenharmony_ci        bigint::from_u64(x)
115cbd624adSopenharmony_ci    }
116cbd624adSopenharmony_ci
117cbd624adSopenharmony_ci    // MATH
118cbd624adSopenharmony_ci
119cbd624adSopenharmony_ci    /// Normalize the integer, so any leading zero values are removed.
120cbd624adSopenharmony_ci    #[inline]
121cbd624adSopenharmony_ci    pub fn normalize(&mut self) {
122cbd624adSopenharmony_ci        bigint::normalize(self)
123cbd624adSopenharmony_ci    }
124cbd624adSopenharmony_ci
125cbd624adSopenharmony_ci    /// Get if the big integer is normalized.
126cbd624adSopenharmony_ci    #[inline]
127cbd624adSopenharmony_ci    pub fn is_normalized(&self) -> bool {
128cbd624adSopenharmony_ci        bigint::is_normalized(self)
129cbd624adSopenharmony_ci    }
130cbd624adSopenharmony_ci
131cbd624adSopenharmony_ci    /// AddAssign small integer.
132cbd624adSopenharmony_ci    #[inline]
133cbd624adSopenharmony_ci    pub fn add_small(&mut self, y: bigint::Limb) -> Option<()> {
134cbd624adSopenharmony_ci        bigint::small_add(self, y)
135cbd624adSopenharmony_ci    }
136cbd624adSopenharmony_ci
137cbd624adSopenharmony_ci    /// MulAssign small integer.
138cbd624adSopenharmony_ci    #[inline]
139cbd624adSopenharmony_ci    pub fn mul_small(&mut self, y: bigint::Limb) -> Option<()> {
140cbd624adSopenharmony_ci        bigint::small_mul(self, y)
141cbd624adSopenharmony_ci    }
142cbd624adSopenharmony_ci}
143cbd624adSopenharmony_ci
144cbd624adSopenharmony_ciimpl PartialEq for HeapVec {
145cbd624adSopenharmony_ci    #[inline]
146cbd624adSopenharmony_ci    #[allow(clippy::op_ref)]
147cbd624adSopenharmony_ci    fn eq(&self, other: &Self) -> bool {
148cbd624adSopenharmony_ci        use core::ops::Deref;
149cbd624adSopenharmony_ci        self.len() == other.len() && self.deref() == other.deref()
150cbd624adSopenharmony_ci    }
151cbd624adSopenharmony_ci}
152cbd624adSopenharmony_ci
153cbd624adSopenharmony_ciimpl Eq for HeapVec {
154cbd624adSopenharmony_ci}
155cbd624adSopenharmony_ci
156cbd624adSopenharmony_ciimpl cmp::PartialOrd for HeapVec {
157cbd624adSopenharmony_ci    #[inline]
158cbd624adSopenharmony_ci    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
159cbd624adSopenharmony_ci        Some(bigint::compare(self, other))
160cbd624adSopenharmony_ci    }
161cbd624adSopenharmony_ci}
162cbd624adSopenharmony_ci
163cbd624adSopenharmony_ciimpl cmp::Ord for HeapVec {
164cbd624adSopenharmony_ci    #[inline]
165cbd624adSopenharmony_ci    fn cmp(&self, other: &Self) -> cmp::Ordering {
166cbd624adSopenharmony_ci        bigint::compare(self, other)
167cbd624adSopenharmony_ci    }
168cbd624adSopenharmony_ci}
169cbd624adSopenharmony_ci
170cbd624adSopenharmony_ciimpl ops::Deref for HeapVec {
171cbd624adSopenharmony_ci    type Target = [bigint::Limb];
172cbd624adSopenharmony_ci    #[inline]
173cbd624adSopenharmony_ci    fn deref(&self) -> &[bigint::Limb] {
174cbd624adSopenharmony_ci        &self.data
175cbd624adSopenharmony_ci    }
176cbd624adSopenharmony_ci}
177cbd624adSopenharmony_ci
178cbd624adSopenharmony_ciimpl ops::DerefMut for HeapVec {
179cbd624adSopenharmony_ci    #[inline]
180cbd624adSopenharmony_ci    fn deref_mut(&mut self) -> &mut [bigint::Limb] {
181cbd624adSopenharmony_ci        &mut self.data
182cbd624adSopenharmony_ci    }
183cbd624adSopenharmony_ci}
184cbd624adSopenharmony_ci
185cbd624adSopenharmony_ciimpl ops::MulAssign<&[bigint::Limb]> for HeapVec {
186cbd624adSopenharmony_ci    #[inline]
187cbd624adSopenharmony_ci    fn mul_assign(&mut self, rhs: &[bigint::Limb]) {
188cbd624adSopenharmony_ci        bigint::large_mul(self, rhs).unwrap();
189cbd624adSopenharmony_ci    }
190cbd624adSopenharmony_ci}
191