-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add specialized-div-rem dependency and replace division functions
- Loading branch information
1 parent
6de4f8f
commit 42a8a95
Showing
4 changed files
with
171 additions
and
303 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,101 +1,97 @@ | ||
use int::Int; | ||
|
||
trait Div: Int { | ||
/// Returns `a / b` | ||
fn div(self, other: Self) -> Self { | ||
let s_a = self >> (Self::BITS - 1); | ||
let s_b = other >> (Self::BITS - 1); | ||
// NOTE it's OK to overflow here because of the `.unsigned()` below. | ||
// This whole operation is computing the absolute value of the inputs | ||
// So some overflow will happen when dealing with e.g. `i64::MIN` | ||
// where the absolute value is `(-i64::MIN) as u64` | ||
let a = (self ^ s_a).wrapping_sub(s_a); | ||
let b = (other ^ s_b).wrapping_sub(s_b); | ||
let s = s_a ^ s_b; | ||
|
||
let r = a.unsigned().aborting_div(b.unsigned()); | ||
(Self::from_unsigned(r) ^ s) - s | ||
// see udiv.rs for more documentation | ||
|
||
#[cfg(not(target = "x86_64"))] | ||
intrinsics! { | ||
#[maybe_use_optimized_c_shim] | ||
#[arm_aeabi_alias = __aeabi_idiv] | ||
pub extern "C" fn __divsi3(a: i32, b: i32) -> i32 { | ||
specialized_div_rem::i32_div_rem_binary_long(a, b).0 | ||
} | ||
} | ||
|
||
impl Div for i32 {} | ||
impl Div for i64 {} | ||
impl Div for i128 {} | ||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __modsi3(a: i32, b: i32) -> i32 { | ||
specialized_div_rem::i32_div_rem_binary_long(a, b).1 | ||
} | ||
|
||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __divmodsi4(a: i32, b: i32, rem: &mut i32) -> i32 { | ||
let quo_rem = specialized_div_rem::i32_div_rem_binary_long(a, b); | ||
*rem = quo_rem.1; | ||
quo_rem.0 | ||
} | ||
|
||
trait Mod: Int { | ||
/// Returns `a % b` | ||
fn mod_(self, other: Self) -> Self { | ||
let s = other >> (Self::BITS - 1); | ||
// NOTE(wrapping_sub) see comment in the `div` | ||
let b = (other ^ s).wrapping_sub(s); | ||
let s = self >> (Self::BITS - 1); | ||
let a = (self ^ s).wrapping_sub(s); | ||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __divdi3(a: i64, b: i64) -> i64 { | ||
specialized_div_rem::i64_div_rem_delegate(a, b).0 | ||
} | ||
|
||
let r = a.unsigned().aborting_rem(b.unsigned()); | ||
(Self::from_unsigned(r) ^ s) - s | ||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __moddi3(a: i64, b: i64) -> i64 { | ||
specialized_div_rem::i64_div_rem_delegate(a, b).1 | ||
} | ||
} | ||
|
||
impl Mod for i32 {} | ||
impl Mod for i64 {} | ||
impl Mod for i128 {} | ||
|
||
trait Divmod: Int { | ||
/// Returns `a / b` and sets `*rem = n % d` | ||
fn divmod<F>(self, other: Self, rem: &mut Self, div: F) -> Self | ||
where | ||
F: Fn(Self, Self) -> Self, | ||
{ | ||
let r = div(self, other); | ||
// NOTE won't overflow because it's using the result from the | ||
// previous division | ||
*rem = self - r.wrapping_mul(other); | ||
r | ||
#[aapcs_on_arm] | ||
pub extern "C" fn __divmoddi4(a: i64, b: i64, rem: &mut i64) -> i64 { | ||
let quo_rem = specialized_div_rem::i64_div_rem_delegate(a, b); | ||
*rem = quo_rem.1; | ||
quo_rem.0 | ||
} | ||
} | ||
|
||
impl Divmod for i32 {} | ||
impl Divmod for i64 {} | ||
#[win64_128bit_abi_hack] | ||
pub extern "C" fn __divti3(a: i128, b: i128) -> i128 { | ||
specialized_div_rem::i128_div_rem_trifecta(a, b).0 | ||
} | ||
|
||
#[win64_128bit_abi_hack] | ||
pub extern "C" fn __modti3(a: i128, b: i128) -> i128 { | ||
specialized_div_rem::i128_div_rem_trifecta(a, b).1 | ||
} | ||
} | ||
|
||
#[cfg(target = "x86_64")] | ||
intrinsics! { | ||
#[maybe_use_optimized_c_shim] | ||
#[arm_aeabi_alias = __aeabi_idiv] | ||
pub extern "C" fn __divsi3(a: i32, b: i32) -> i32 { | ||
a.div(b) | ||
specialized_div_rem::i32_div_rem_binary_long(a, b).0 | ||
} | ||
|
||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __divdi3(a: i64, b: i64) -> i64 { | ||
a.div(b) | ||
pub extern "C" fn __modsi3(a: i32, b: i32) -> i32 { | ||
specialized_div_rem::i32_div_rem_binary_long(a, b).1 | ||
} | ||
|
||
#[win64_128bit_abi_hack] | ||
pub extern "C" fn __divti3(a: i128, b: i128) -> i128 { | ||
a.div(b) | ||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __divmodsi4(a: i32, b: i32, rem: &mut i32) -> i32 { | ||
let quo_rem = specialized_div_rem::i32_div_rem_binary_long(a, b); | ||
*rem = quo_rem.1; | ||
quo_rem.0 | ||
} | ||
|
||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __modsi3(a: i32, b: i32) -> i32 { | ||
a.mod_(b) | ||
pub extern "C" fn __divdi3(a: i64, b: i64) -> i64 { | ||
specialized_div_rem::i64_div_rem_delegate(a, b).0 | ||
} | ||
|
||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __moddi3(a: i64, b: i64) -> i64 { | ||
a.mod_(b) | ||
specialized_div_rem::i64_div_rem_delegate(a, b).1 | ||
} | ||
|
||
#[win64_128bit_abi_hack] | ||
pub extern "C" fn __modti3(a: i128, b: i128) -> i128 { | ||
a.mod_(b) | ||
#[aapcs_on_arm] | ||
pub extern "C" fn __divmoddi4(a: i64, b: i64, rem: &mut i64) -> i64 { | ||
let quo_rem = specialized_div_rem::i64_div_rem_delegate(a, b); | ||
*rem = quo_rem.1; | ||
quo_rem.0 | ||
} | ||
|
||
#[maybe_use_optimized_c_shim] | ||
pub extern "C" fn __divmodsi4(a: i32, b: i32, rem: &mut i32) -> i32 { | ||
a.divmod(b, rem, |a, b| __divsi3(a, b)) | ||
#[win64_128bit_abi_hack] | ||
pub extern "C" fn __divti3(a: i128, b: i128) -> i128 { | ||
specialized_div_rem::i128_div_rem_asymmetric(a, b).0 | ||
} | ||
|
||
#[aapcs_on_arm] | ||
pub extern "C" fn __divmoddi4(a: i64, b: i64, rem: &mut i64) -> i64 { | ||
a.divmod(b, rem, |a, b| __divdi3(a, b)) | ||
#[win64_128bit_abi_hack] | ||
pub extern "C" fn __modti3(a: i128, b: i128) -> i128 { | ||
specialized_div_rem::i128_div_rem_asymmetric(a, b).1 | ||
} | ||
} | ||
} |
Oops, something went wrong.