apint/apint/
utils.rs

1
2use storage::{Storage};
3use digit::{Digit, Bit};
4use apint::{ApInt};
5use errors::{Error, Result};
6use traits::Width;
7use bitwidth::BitWidth;
8use digit_seq::{
9	ContiguousDigitSeq,
10	ContiguousDigitSeqMut
11};
12
13use std::fmt;
14use std::hash::{Hash, Hasher};
15
16impl fmt::Debug for ApInt {
17	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18		f.debug_struct("ApInt")
19		 .field("len", &self.width())
20		 .field("digits", &self.as_digit_slice())
21		 .finish()
22	}
23}
24
25impl Hash for ApInt {
26	fn hash<H: Hasher>(&self, state: &mut H) {
27		self.len.hash(state);
28		self.as_digit_slice().hash(state);
29	}
30}
31
32// ============================================================================
33
34impl ApInt {
35	pub(in apint) fn digits(&self) -> ContiguousDigitSeq {
36		ContiguousDigitSeq::from(self.as_digit_slice())
37	}
38
39	pub(in apint) fn digits_mut(&mut self) -> ContiguousDigitSeqMut {
40		ContiguousDigitSeqMut::from(self.as_digit_slice_mut())
41	}
42}
43
44// ============================================================================
45
46#[derive(Debug, Copy, Clone, PartialEq, Eq)]
47pub(crate) enum DataAccess<'a> {
48	Inl(Digit),
49	Ext(&'a [Digit])
50}
51
52#[derive(Debug, PartialEq, Eq)]
53pub(crate) enum DataAccessMut<'a> {
54	Inl(&'a mut Digit),
55	Ext(&'a mut [Digit])
56}
57
58#[derive(Debug, Copy, Clone, PartialEq, Eq)]
59pub(crate) enum ZipDataAccess<'a, 'b> {
60	Inl(Digit, Digit),
61	Ext(&'a [Digit], &'b [Digit])
62}
63
64#[derive(Debug, PartialEq, Eq)]
65pub(crate) enum ZipDataAccessMut<'a, 'b> {
66	Inl(&'a mut Digit, Digit),
67	Ext(&'a mut [Digit], &'b [Digit])
68}
69
70// ============================================================================
71
72impl Width for ApInt {
73	/// Returns the `BitWidth` of this `ApInt`.
74	#[inline]
75	fn width(&self) -> BitWidth {
76		BitWidth::new(self.len_bits()).unwrap()
77	}
78}
79
80/// # Utility & Helper Methods
81impl ApInt {
82	/// Returns the number of bits of the bit width of this `ApInt`.
83	#[inline]
84	pub(in apint) fn len_bits(&self) -> usize {
85		self.len.to_usize()
86	}
87
88	/// Returns the number of digits used internally for the value
89	/// representation of this `ApInt`.
90	#[inline]
91	pub(in apint) fn len_digits(&self) -> usize {
92		self.len.required_digits()
93	}
94
95	/// Returns the storage specifier of this `ApInt`.
96	/// 
97	/// This is `Storage::Inl` for `ApInt` instances that can be stored
98	/// entirely on the stack and `Storage::Ext` otherwise.
99	#[inline]
100	pub(in apint) fn storage(&self) -> Storage {
101		self.len.storage()
102	}
103
104	/// Accesses the internal `Digit` data of this `ApInt` in a safe way.
105	#[inline]
106	pub(in apint) fn access_data(&self) -> DataAccess {
107		match self.storage() {
108			Storage::Inl => DataAccess::Inl(unsafe{self.data.inl}),
109			Storage::Ext => DataAccess::Ext(self.as_digit_slice())
110		}
111	}
112
113	/// Mutably accesses the internal `Digit` data of this `ApInt` in a safe way.
114	#[inline]
115	pub(in apint) fn access_data_mut(&mut self) -> DataAccessMut {
116		match self.storage() {
117			Storage::Inl => DataAccessMut::Inl(unsafe{&mut self.data.inl}),
118			Storage::Ext => DataAccessMut::Ext(self.as_digit_slice_mut())
119		}
120	}
121
122	/// Zips both given `ApInt` instances and tries to access their data in a safe way.
123	/// 
124	/// # Errors
125	/// 
126	/// - If both given `ApInt` instances have non-matching bit widths.
127	pub(in apint) fn zip_access_data<'a, 'b>(&'a self, other: &'b ApInt) -> Result<ZipDataAccess<'a, 'b>> {
128		if self.width() != other.width() {
129			return Error::unmatching_bitwidths(self.width(), other.width()).into()
130		}
131		Ok(match self.storage() {
132			Storage::Inl => {
133				ZipDataAccess::Inl(
134					unsafe{ self.data.inl},
135					unsafe{other.data.inl})
136			},
137			Storage::Ext => {
138				ZipDataAccess::Ext(
139					self.as_digit_slice(),
140					other.as_digit_slice())
141			}
142		})
143	}
144
145	/// Zips both given `ApInt` instances and tries to mutably access their data in a safe way.
146	/// 
147	/// # Errors
148	/// 
149	/// - If both given `ApInt` instances have non-matching bit widths.
150	pub(in apint) fn zip_access_data_mut<'a, 'b>(&'a mut self, other: &'b ApInt) -> Result<ZipDataAccessMut<'a, 'b>> {
151		if self.width() != other.width() {
152			return Error::unmatching_bitwidths(self.width(), other.width()).into()
153		}
154		Ok(match self.storage() {
155			Storage::Inl => {
156				ZipDataAccessMut::Inl(
157					unsafe{&mut self.data.inl},
158					unsafe{other.data.inl})
159			},
160			Storage::Ext => {
161				ZipDataAccessMut::Ext(
162					self.as_digit_slice_mut(),
163					other.as_digit_slice())
164			}
165		})
166	}
167
168	/// Computes the given operation on all digits of this `ApInt`.
169	/// 
170	/// # Note
171	/// 
172	/// Prefer this utility method if you want to perform the same
173	/// operation for all digits within this `ApInt` as this operation
174	/// uses the most efficient way to do so.
175	pub(in apint) fn modify_digits<F>(&mut self, f: F)
176		where F: Fn(&mut Digit)
177	{
178		use self::DataAccessMut::*;
179		match self.access_data_mut() {
180			Inl(digit) => f(digit),
181			Ext(digits) => {
182				for digit in digits {
183					f(digit)
184				}
185			}
186		}
187	}
188
189	/// Computes the given operation on all digits of this `ApInt`
190	/// zipped with the digits of `rhs`.
191	/// 
192	/// # Note
193	/// 
194	/// Prefer this utility method for these use cases since this operation
195	/// uses the most efficient way to perform the specified task.
196	pub(in apint) fn modify_zipped_digits<F>(&mut self, rhs: &ApInt, f: F) -> Result<()>
197		where F: Fn(&mut Digit, Digit)
198	{
199		use self::ZipDataAccessMut::*;
200		match self.zip_access_data_mut(rhs)? {
201			Inl(lhs, rhs) => f(lhs, rhs),
202			Ext(lhs, rhs) => {
203				for (l, &r) in lhs.into_iter().zip(rhs) {
204					f(l, r)
205				}
206			}
207		}
208		Ok(())
209	}
210
211	/// Returns a slice over the `Digit`s of this `ApInt` in little-endian order.
212	pub(in apint) fn as_digit_slice(&self) -> &[Digit] {
213		use std::slice;
214		match self.len.storage() {
215			Storage::Inl => unsafe {
216				slice::from_raw_parts(&self.data.inl, 1)
217			},
218			Storage::Ext => unsafe {
219				slice::from_raw_parts(self.data.ext.as_ptr(), self.len_digits())
220			}
221		}
222	}
223
224	/// Returns a mutable slice over the `Digit`s of this `ApInt` in little-endian order.
225	pub(in apint) fn as_digit_slice_mut(&mut self) -> &mut [Digit] {
226		use std::slice;
227		match self.len.storage() {
228			Storage::Inl => unsafe {
229				slice::from_raw_parts_mut(&mut self.data.inl, 1)
230			},
231			Storage::Ext => unsafe {
232				slice::from_raw_parts_mut(self.data.ext.as_ptr(), self.len_digits())
233			}
234		}
235	}
236
237	/// Returns the most significant `Digit` of this `ApInt`.
238	pub(in apint) fn most_significant_digit(&self) -> Digit {
239		match self.access_data() {
240			DataAccess::Inl(digit) => digit,
241			DataAccess::Ext(digits) => {
242				*digits.last().unwrap()
243			}
244		}
245	}
246
247	/// Returns a mutable reference to the most significant `Digit` of this `ApInt`.
248	pub(in apint) fn most_significant_digit_mut(&mut self) -> &mut Digit {
249		match self.access_data_mut() {
250			DataAccessMut::Inl(digit) => digit,
251			DataAccessMut::Ext(digits) => {
252				digits.last_mut().unwrap()
253			}
254		}
255	}
256
257	/// Returns the least significant `Digit` of this `ApInt`.
258	pub(in apint) fn least_significant_digit(&self) -> Digit {
259		match self.access_data() {
260			DataAccess::Inl(digit) => digit,
261			DataAccess::Ext(digits) => digits[0]
262		}
263	}
264
265	/// Returns `Bit::Set` if the most significant bit of this `ApInt` is set
266	/// and `Bit::Unset` otherwise.
267	pub(in apint) fn most_significant_bit(&self) -> Bit {
268		let sign_bit_pos = self.width().sign_bit_pos();
269		self.most_significant_digit()
270			.get(sign_bit_pos.to_pos_within_digit())
271			.expect("`BitWidth::excess_bits` returns a number that \
272			         is always a valid `BitPos` for a `Digit` so this \
273			         operation cannot fail.")
274	}
275
276	/// Returns `Bit::Set` if the least significant bit of this `ApInt` is set
277	/// and `Bit::Unset` otherwise.
278	pub(in apint) fn least_significant_bit(&self) -> Bit {
279		self.least_significant_digit().least_significant_bit()
280	}
281
282	/// Clears unused bits of this `ApInt`.
283	/// 
284	/// # Example
285	/// 
286	/// An `ApInt` with a `BitWidth` of `100` bits requires
287	/// 2 `Digit`s for its internal value representation,
288	/// each having 64-bits which totals in `128` bits for the
289	/// `ApInt` instance.
290	/// So upon a call to `ApInt::clear_unused_bits` the upper
291	/// `128-100 = 28` bits are cleared (set to zero (`0`)).
292	pub(in apint) fn clear_unused_bits(&mut self) {
293		if let Some(bits) = self.width().excess_bits() {
294			self.most_significant_digit_mut()
295			    .retain_last_n(bits)
296			    .expect("`BitWidth::excess_bits` always returns a number of \
297				         bits that can safely forwarded to `Digit::retain_last_n`.");
298		}
299	}
300
301	/// Returns `true` if this `ApInt` represents the value zero (`0`).
302	/// 
303	/// # Note
304	/// 
305	/// - Zero (`0`) is also called the additive neutral element.
306	/// - This operation is more efficient than comparing two instances
307	///   of `ApInt` for the same reason.
308	pub fn is_zero(&self) -> bool {
309		match self.access_data() {
310			DataAccess::Inl(digit) => digit.is_zero(),
311			DataAccess::Ext(digits) => {
312				digits.into_iter().all(|digit| digit.is_zero())
313			}
314		}
315	}
316
317	/// Returns `true` if this `ApInt` represents the value one (`1`).
318	/// 
319	/// # Note
320	/// 
321	/// - One (`1`) is also called the multiplicative neutral element.
322	/// - This operation is more efficient than comparing two instances
323	///   of `ApInt` for the same reason.
324	pub fn is_one(&self) -> bool {
325		match self.access_data() {
326			DataAccess::Inl(digit) => digit == Digit::one(),
327			DataAccess::Ext(digits) => {
328				let (last, rest) = digits.split_last()
329					.expect("An `ApInt` always has at least one digit so calling \
330					         `split_last` on a slice of its digits will never \
331					         return `None`.");
332				last.is_one() && rest.into_iter().all(|digit| digit.is_zero())
333			}
334		}
335	}
336
337	/// Returns `true` if this `ApInt` represents an even number.
338	#[inline]
339	pub fn is_even(&self) -> bool {
340		self.least_significant_bit() == Bit::Unset
341	}
342
343	/// Returns `true` if this `ApInt` represents an odd number.
344	#[inline]
345	pub fn is_odd(&self) -> bool {
346		self.least_significant_bit() == Bit::Set
347	}
348
349	/// Splits the least significant digits from the rest of the digit slice
350	/// and returns it as well as the remaining part of the digit slice.
351	pub(in apint) fn split_least_significant_digit(&self) -> (Digit, &[Digit]) {
352		match self.access_data() {
353			DataAccess::Inl(digit) => (digit, &[]),
354			DataAccess::Ext(digits) => {
355				let (lsd, rest) = digits.split_first()
356					.expect("An `ApInt` always has at least one digit so calling \
357					         `split_first` on a slice of its digits will never \
358					         return `None`.");
359				(*lsd, rest)
360			}
361		}
362	}
363
364	/// Splits the most significant digits from the rest of the digit slice
365	/// and returns it as well as the remaining part of the digit slice.
366	pub(in apint) fn split_most_significant_digit(&self) -> (Digit, &[Digit]) {
367		match self.access_data() {
368			DataAccess::Inl(digit) => (digit, &[]),
369			DataAccess::Ext(digits) => {
370				let (lsd, rest) = digits.split_last()
371					.expect("An `ApInt` always has at least one digit so calling \
372					         `split_last` on a slice of its digits will never \
373					         return `None`.");
374				(*lsd, rest)
375			}
376		}
377	}
378}
379
380#[cfg(test)]
381mod tests {
382	use super::*;
383
384	#[test]
385	fn most_significant_bit() {
386		assert_eq!(Bit::Unset,
387			ApInt::from_bit(false).most_significant_bit());
388		assert_eq!(Bit::Set,
389			ApInt::from_bit(true).most_significant_bit());
390		assert_eq!(Bit::Unset,
391			ApInt::from_u8(0b0101_0101).most_significant_bit());
392		assert_eq!(Bit::Set,
393			ApInt::from_u8(0b1101_0101).most_significant_bit());
394		assert_eq!(Bit::Unset,
395			ApInt::from_u16(0b0111_1000_1101_0101).most_significant_bit());
396		assert_eq!(Bit::Set,
397			ApInt::from_u16(0b1011_0001_0101_0101).most_significant_bit());
398		assert_eq!(Bit::Unset,
399			ApInt::from_u32(0x7000_0000).most_significant_bit());
400		assert_eq!(Bit::Set,
401			ApInt::from_u32(0x8000_0000).most_significant_bit());
402		assert_eq!(Bit::Unset,
403			ApInt::from_u64(0x70FC_A875_4321_1234).most_significant_bit());
404		assert_eq!(Bit::Set,
405			ApInt::from_u64(0x8765_4321_5555_6666).most_significant_bit());
406	}
407}