Skip to content

Commit

Permalink
Cargo fmt and clippy
Browse files Browse the repository at this point in the history
  • Loading branch information
cmpute committed Mar 31, 2024
1 parent e741138 commit b0783d0
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 41 deletions.
80 changes: 55 additions & 25 deletions integer/src/convert.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
//! Conversions between types.
use crate::{
add, arch::word::{DoubleWord, Word}, buffer::Buffer, helper_macros::debug_assert_zero, ibig::IBig, math, primitive::{self, PrimitiveSigned, PrimitiveUnsigned, DWORD_BITS_USIZE, DWORD_BYTES, WORD_BITS, WORD_BITS_USIZE, WORD_BYTES}, repr::{
add,
arch::word::{DoubleWord, Word},
buffer::Buffer,
helper_macros::debug_assert_zero,
ibig::IBig,
math,
primitive::{
self, PrimitiveSigned, PrimitiveUnsigned, DWORD_BITS_USIZE, DWORD_BYTES, WORD_BITS,
WORD_BITS_USIZE, WORD_BYTES,
},
repr::{
Repr,
TypedReprRef::{self, *},
}, shift, ubig::UBig, Sign::*
},
shift,
ubig::UBig,
Sign::*,
};
use alloc::{boxed::Box, vec::Vec, vec};
use static_assertions::const_assert;
use alloc::{boxed::Box, vec, vec::Vec};
use core::convert::{TryFrom, TryInto};
use dashu_base::{
Approximation::{self, *},
BitTest, ConversionError, FloatEncoding, PowerOfTwo, Sign,
};
use static_assertions::const_assert;

impl Default for UBig {
/// Default value: 0.
Expand Down Expand Up @@ -65,28 +78,29 @@ fn words_to_be_bytes<const FLIP: bool>(words: &[Word]) -> Vec<u8> {
}

/// Convert a integer into an array of chunks by bit chunking
///
///
/// Requirements:
/// - chunks_out.len() tightly fits all chunks.
/// - All words in chunks_out must has enough length (i.e. ceil(chunk_bits / WORD_BITS))
fn words_to_chunks(words: &[Word], chunks_out: &mut [&mut [Word]], chunk_bits: usize) {
assert!(words.len() > 0);
assert!(!words.is_empty());

if chunk_bits % WORD_BITS_USIZE == 0 {
// shortcut for word aligned chunks
let words_per_chunk = chunk_bits / WORD_BITS_USIZE;
for (i, chunk_out) in chunks_out.iter_mut().enumerate() {
let start_pos = i * words_per_chunk;
let end_pos = start_pos + words_per_chunk;
chunk_out[..end_pos-start_pos].copy_from_slice(&words[start_pos..end_pos]);
chunk_out[..end_pos - start_pos].copy_from_slice(&words[start_pos..end_pos]);
}
} else {
let bit_len = words.len() * WORD_BITS_USIZE - words.last().unwrap().leading_zeros() as usize;
let bit_len =
words.len() * WORD_BITS_USIZE - words.last().unwrap().leading_zeros() as usize;
for (i, chunk_out) in chunks_out.iter_mut().enumerate() {
let start = i * chunk_bits;
let end = bit_len.min(start + chunk_bits);
debug_assert!(start < end); // make sure that there is no empty chunk

let (start_pos, end_pos) = (start / WORD_BITS_USIZE, end / WORD_BITS_USIZE);
let end_bits = (end % WORD_BITS_USIZE) as u32;
let len;
Expand All @@ -104,18 +118,26 @@ fn words_to_chunks(words: &[Word], chunks_out: &mut [&mut [Word]], chunk_bits: u
}

/// Convert chunks to a single integer by shifting and adding.
///
///
/// Requirements:
/// - words_out must have enough length
/// - buffer must have enough length: buffer.len() > max(chunk.len()) for chunk in chunks
fn chunks_to_words(words_out: &mut [Word], chunks: &[&[Word]], chunk_bits: usize, buffer: &mut [Word]) {
assert!(chunks.len() > 0);
fn chunks_to_words(
words_out: &mut [Word],
chunks: &[&[Word]],
chunk_bits: usize,
buffer: &mut [Word],
) {
assert!(!chunks.is_empty());
for (i, chunk) in chunks.iter().enumerate() {
let shift = i * chunk_bits;
buffer[..chunk.len()].copy_from_slice(chunk);
buffer[chunk.len()] = 0;
shift::shl_in_place(&mut buffer[..=chunk.len()], (shift % WORD_BITS_USIZE) as u32);
debug_assert_zero!(add::add_in_place(&mut words_out[shift / WORD_BITS_USIZE..], &buffer[..=chunk.len()]));
debug_assert_zero!(add::add_in_place(
&mut words_out[shift / WORD_BITS_USIZE..],
&buffer[..=chunk.len()]
));
}
}

Expand Down Expand Up @@ -235,7 +257,7 @@ impl TypedReprRef<'_> {
buffers
}
},
RefLarge(words) =>{
RefLarge(words) => {
let mut buffers = Vec::<Buffer>::new();
let word_per_chunk = math::ceil_div(chunk_bits, WORD_BITS_USIZE);
buffers.resize_with(chunk_count, || {
Expand All @@ -244,10 +266,14 @@ impl TypedReprRef<'_> {
buf.push_zeros(word_per_chunk + 1);
buf
});
let mut buffer_refs: Box<[&mut [Word]]> = buffers.iter_mut().map(|buf| buf.as_mut()).collect();
let mut buffer_refs: Box<[&mut [Word]]> =
buffers.iter_mut().map(|buf| buf.as_mut()).collect();
words_to_chunks(words, &mut buffer_refs, chunk_bits);
buffers.into_iter().map(|buf| Repr::from_buffer(buf)).collect()
}
buffers
.into_iter()
.map(Repr::from_buffer)
.collect()
}
}
}
}
Expand Down Expand Up @@ -421,13 +447,13 @@ impl UBig {
}

/// Reconstruct an integer from a group of bit chunks.
///
///
/// Denote the chunks as C_i, then this function calculates sum(C_i * 2^(i * chunk_bits))
/// for i from 0 to len(chunks) - 1.
///
///
/// Note that it's allowed for each chunk to have more bits than chunk_bits, which is different
/// from the [UBig::to_chunks] method.
///
///
/// # Examples
///
/// ```
Expand All @@ -437,9 +463,9 @@ impl UBig {
/// UBig::from(0x010203u32)
/// );
/// ```
///
///
/// # Panics
///
///
/// Panics if chunk_bits is zero.
#[inline]
pub fn from_chunks<'a, I: Iterator<Item = &'a UBig>>(chunks: I, chunk_bits: usize) -> Self {
Expand All @@ -459,13 +485,17 @@ impl UBig {
/// assert_eq!(*UBig::from(0x010203u32).to_chunks(8),
/// [0x3u8.into(), 0x2u8.into(), 0x1u8.into()]);
/// ```
///
///
/// # Panics
///
///
/// Panics if chunk_bits is zero.
#[inline]
pub fn to_chunks(&self, chunk_bits: usize) -> Box<[UBig]> {
self.repr().to_chunks(chunk_bits).into_iter().map(|r| UBig(r)).collect()
self.repr()
.to_chunks(chunk_bits)
.into_iter()
.map(UBig)
.collect()
}

/// Convert to f32.
Expand Down
36 changes: 28 additions & 8 deletions integer/tests/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,30 @@ fn test_from_to_chunks() {
assert_eq!(*ubig!(0xabcd).to_chunks(8), [ubig!(0xcd), ubig!(0xab)]);
assert_eq!(*ubig!(0xabcd).to_chunks(12), [ubig!(0xbcd), ubig!(0xa)]);
assert_eq!(*ubig!(0xabcd).to_chunks(16), [ubig!(0xabcd)]);
assert_eq!(*ubig!(0x123456789abcdef).to_chunks(17), [ubig!(0x1cdef), ubig!(0x1c4d5), ubig!(0xd159), ubig!(0x24)]);
assert_eq!(*ubig!(0x123456789abcdef0123456789abcdef0123456789abcdef).to_chunks(29), [
ubig!(0x9abcdef), ubig!(0x91a2b3c), ubig!(0xaf37bc0), ubig!(0x68acf13), ubig!(0x1cdef012), ubig!(0x2b3c4d5), ubig!(0x48d)
]);
assert_eq!(*ubig!(0x123456789abcdef0123456789abcdef0123456789abcdef).to_chunks(64), [
ubig!(0x123456789abcdef), ubig!(0x123456789abcdef), ubig!(0x123456789abcdef)
]);
assert_eq!(
*ubig!(0x123456789abcdef).to_chunks(17),
[ubig!(0x1cdef), ubig!(0x1c4d5), ubig!(0xd159), ubig!(0x24)]
);
assert_eq!(
*ubig!(0x123456789abcdef0123456789abcdef0123456789abcdef).to_chunks(29),
[
ubig!(0x9abcdef),
ubig!(0x91a2b3c),
ubig!(0xaf37bc0),
ubig!(0x68acf13),
ubig!(0x1cdef012),
ubig!(0x2b3c4d5),
ubig!(0x48d)
]
);
assert_eq!(
*ubig!(0x123456789abcdef0123456789abcdef0123456789abcdef).to_chunks(64),
[
ubig!(0x123456789abcdef),
ubig!(0x123456789abcdef),
ubig!(0x123456789abcdef)
]
);

assert_eq!(UBig::from_chunks(empty.iter(), 1), UBig::ZERO);
assert_eq!(UBig::from_chunks([ubig!(1)].iter(), 1), UBig::ONE);
Expand All @@ -74,7 +91,10 @@ fn test_from_to_chunks() {
(ubig!(0xffff), vec![1, 3]),
(ubig!(0xfefefefe), vec![3, 4]),
(ubig!(0xffffffff000000001), vec![16, 32, 64, 65, 66]),
(ubig!(0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000), vec![13, 32, 64]),
(
ubig!(0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000),
vec![13, 32, 64],
),
];
for (n, chunk_bits) in test_cases {
for bits in chunk_bits {
Expand Down
14 changes: 8 additions & 6 deletions python/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,14 @@ impl<'a> UniInput<'a> {
Self::Uint(x) => Ok(x.into()),
Self::BUint(x) => Ok(x.0.clone()),
Self::OBInt(x) => x.try_into().map_err(|_| err),
Self::BInt(x) => if let Some(u) = x.0.as_ubig() {
Ok(u.clone())
} else {
Err(err)
Self::BInt(x) => {
if let Some(u) = x.0.as_ubig() {
Ok(u.clone())
} else {
Err(err)
}
}
_ => Err(err)
_ => Err(err),
}
}
}
}
9 changes: 7 additions & 2 deletions python/src/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,14 +419,19 @@ impl UPy {
if chunk_bits == 0 {
Err(PyValueError::new_err(ERRMSG_ZERO_CHUNK_SIZE))
} else {
let iter = self.0.to_chunks(chunk_bits).into_vec().into_iter().map(|u| UPy(u).into_py(py));
let iter = self
.0
.to_chunks(chunk_bits)
.into_vec()
.into_iter()
.map(|u| UPy(u).into_py(py));
Ok(PyTuple::new(py, iter).into_py(py))
}
}
#[staticmethod]
fn from_chunks(chunks: &PyAny, chunk_bits: usize) -> PyResult<Self> {
if chunk_bits == 0 {
return Err(PyValueError::new_err(ERRMSG_ZERO_CHUNK_SIZE))
return Err(PyValueError::new_err(ERRMSG_ZERO_CHUNK_SIZE));
}

let mut input = Vec::new();
Expand Down

0 comments on commit b0783d0

Please sign in to comment.