Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Memory to reduce unsafe code #39

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions integer/src/div/divide_conquer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ use crate::{
mul,
Sign::*,
};
use alloc::alloc::Layout;
use static_assertions::const_assert;

/// Memory requirement for division.
pub fn memory_requirement_exact(lhs_len: usize, rhs_len: usize) -> Layout {
pub fn memory_requirement_exact(lhs_len: usize, rhs_len: usize) -> usize {
assert!(lhs_len >= rhs_len);
// We need space for multiplications summing up to rhs.len(),
// and at most lhs_len - rhs_len long.
Expand Down
7 changes: 3 additions & 4 deletions integer/src/div/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ use crate::{
arch::word::{DoubleWord, Word},
helper_macros::debug_assert_zero,
math::{shl_dword, shr_word, FastDivideNormalized, FastDivideNormalized2},
memory::{self, Memory},
memory::Memory,
primitive::{double_word, extend_word, highest_dword, lowest_dword, split_dword, WORD_BITS},
shift,
};
use alloc::alloc::Layout;

mod divide_conquer;
mod simple;
Expand Down Expand Up @@ -231,10 +230,10 @@ pub(crate) fn fast_rem_by_normalized_dword(
}

/// Memory requirement for division.
pub fn memory_requirement_exact(lhs_len: usize, rhs_len: usize) -> Layout {
pub fn memory_requirement_exact(lhs_len: usize, rhs_len: usize) -> usize {
assert!(lhs_len >= rhs_len && rhs_len >= 2);
if rhs_len <= THRESHOLD_SIMPLE || lhs_len - rhs_len <= THRESHOLD_SIMPLE {
memory::zero_layout()
0
} else {
divide_conquer::memory_requirement_exact(lhs_len, rhs_len)
}
Expand Down
16 changes: 7 additions & 9 deletions integer/src/gcd/lehmer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use alloc::alloc::Layout;
use core::{mem, ptr, slice};
use dashu_base::{ExtendedGcd, Gcd};

Expand Down Expand Up @@ -223,7 +222,7 @@ pub(crate) fn lehmer_step(x: &mut [Word], y: &mut [Word], a: Word, b: Word, c: W

/// Temporary memory required for gcd.
#[inline]
pub fn memory_requirement_up_to(lhs_len: usize, rhs_len: usize) -> Layout {
pub fn memory_requirement_up_to(lhs_len: usize, rhs_len: usize) -> usize {
// Required memory:
// - temporary space for the division in the euclidean step
div::memory_requirement_exact(lhs_len, rhs_len)
Expand Down Expand Up @@ -328,15 +327,14 @@ fn lehmer_ext_step(
}

/// Temporary memory required for extended gcd.
pub fn memory_requirement_ext_up_to(lhs_len: usize, rhs_len: usize) -> Layout {
pub fn memory_requirement_ext_up_to(lhs_len: usize, rhs_len: usize) -> usize {
// Required memory:
// - two numbers (t0 & t1) with at most the same size as lhs, add 1 buffer word
// - temporary space for a division (for euclidean step), and later a mulitplication (for coeff update)
let t_words = 2 * lhs_len + 2;
memory::add_layout(
memory::array_layout::<Word>(t_words),
memory::max_layout(
div::memory_requirement_exact(lhs_len, rhs_len), //
memory::add_capacity(
t_words,
div::memory_requirement_exact(lhs_len, rhs_len).max(
mul::memory_requirement_up_to(lhs_len, lhs_len / 2), // for coeff update
),
)
Expand All @@ -358,8 +356,8 @@ pub fn gcd_ext_in_place(
// the normal way is to have four variables s0, s1, t0, t1 and keep gcd(x, y) = gcd(lhs, rhs),
// x = s0*lhs - t0*rhs, y = t1*rhs - s1*lhs. Here we simplify it by only tracking the
// coefficient of rhs, so that x = -t0*rhs mod lhs, y = t1*rhs mod lhs,
let (mut t0, mut memory) = memory.allocate_slice_fill::<Word>(lhs_len + 1, 0);
let (mut t1, mut memory) = memory.allocate_slice_fill::<Word>(lhs_len + 1, 0);
let (mut t0, mut memory) = memory.allocate_slice_fill(lhs_len + 1, 0);
let (mut t1, mut memory) = memory.allocate_slice_fill(lhs_len + 1, 0);
let (mut t0_len, mut t1_len) = (1, 1);
*t1.first_mut().unwrap() = 1;

Expand Down
5 changes: 2 additions & 3 deletions integer/src/gcd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::{
primitive::{extend_word, shrink_dword, PrimitiveSigned},
Sign,
};
use alloc::alloc::Layout;
use dashu_base::ExtendedGcd;

mod lehmer;
Expand All @@ -30,7 +29,7 @@ pub fn gcd_in_place(lhs: &mut [Word], rhs: &mut [Word], memory: &mut Memory) ->
}

/// Memory requirement for GCD.
pub fn memory_requirement_exact(lhs_len: usize, rhs_len: usize) -> Layout {
pub fn memory_requirement_exact(lhs_len: usize, rhs_len: usize) -> usize {
lehmer::memory_requirement_up_to(lhs_len, rhs_len)
}

Expand All @@ -53,7 +52,7 @@ pub fn gcd_ext_in_place(
}

/// Memory requirement for extended GCD.
pub fn memory_requirement_ext_exact(lhs_len: usize, rhs_len: usize) -> Layout {
pub fn memory_requirement_ext_exact(lhs_len: usize, rhs_len: usize) -> usize {
lehmer::memory_requirement_ext_up_to(lhs_len, rhs_len)
}

Expand Down
20 changes: 8 additions & 12 deletions integer/src/gcd_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,21 +295,17 @@ mod repr {
let (lhs_len, rhs_len) = (lhs.len(), rhs.len());

// allocate memory
let clone_mem = memory::array_layout::<Word>(lhs_len + rhs_len);
let clone_mem = memory::add_capacity(lhs_len, rhs_len);
let gcd_mem = gcd::memory_requirement_ext_exact(lhs_len, rhs_len);
let post_mem = memory::add_layout(
let post_mem = memory::add_capacity(
// temporary space to store residue
memory::array_layout::<Word>(lhs_len + rhs_len),
memory::max_layout(
// memory required for post processing: one multiplication + one division
mul::memory_requirement_exact(lhs_len + rhs_len, rhs_len),
div::memory_requirement_exact(lhs_len + rhs_len + 1, rhs_len),
),
);
let mut allocation = MemoryAllocation::new(memory::add_layout(
clone_mem,
memory::max_layout(gcd_mem, post_mem),
));
// memory required for post processing: one multiplication + one division
mul::memory_requirement_exact(clone_mem, rhs_len)
.max(div::memory_requirement_exact(memory::add_capacity(clone_mem, 1), rhs_len)),
);
let mut allocation =
MemoryAllocation::new(memory::add_capacity(clone_mem, gcd_mem.max(post_mem)));
let mut memory = allocation.memory();

// copy oprands for post processing
Expand Down
Loading
Loading