Skip to content

Commit

Permalink
Move architecture-specific code to src/math/arch
Browse files Browse the repository at this point in the history
Move the code and call into its new location with
`select_implementation`.
  • Loading branch information
tgross35 committed Oct 29, 2024
1 parent 61ea1a9 commit 3c110e1
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 249 deletions.
37 changes: 37 additions & 0 deletions src/math/arch/i586.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Architecture-specific support for x86-32 without SSE2
use super::super::fabs;

/// Use an alternative implementation on x86, because the
/// main implementation fails with the x87 FPU used by
/// debian i386, probably due to excess precision issues.
/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
pub fn ceil(x: f64) -> f64 {
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated < x {
return truncated + 1.0;
} else {
return truncated;
}
} else {
return x;
}
}

/// Use an alternative implementation on x86, because the
/// main implementation fails with the x87 FPU used by
/// debian i386, probably due to excess precision issues.
/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
pub fn floor(x: f64) -> f64 {
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated > x {
return truncated - 1.0;
} else {
return truncated;
}
} else {
return x;
}
}
24 changes: 24 additions & 0 deletions src/math/arch/i686.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Architecture-specific support for x86-32 and x86-64 with SSE2
#![cfg(not(feature = "force-soft-floats"))]

#[cfg(target_arch = "x86")]
use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;

pub fn sqrtf(x: f32) -> f32 {
unsafe {
let m = _mm_set_ss(x);
let m_sqrt = _mm_sqrt_ss(m);
_mm_cvtss_f32(m_sqrt)
}
}

pub fn sqrt(x: f64) -> f64 {
unsafe {
let m = _mm_set_sd(x);
let m_sqrt = _mm_sqrt_pd(m);
_mm_cvtsd_f64(m_sqrt)
}
}
19 changes: 19 additions & 0 deletions src/math/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,22 @@
#[cfg(intrinsics_enabled)]
pub mod intrinsics;

// Most implementations should be defined here, to ensure they are not made available when
// soft floats are required.
#[cfg(arch_enabled)]
cfg_if! {
if #[cfg(target_feature = "sse2")] {
mod i686;
pub use i686::{sqrt, sqrtf};
}
}

// There are certain architecture-specific implementations that are needed for correctness
// even with `force-soft-float`. These are configured here.
cfg_if! {
if #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] {
mod i586;
pub use i586::{ceil, floor};
}
}
19 changes: 1 addition & 18 deletions src/math/ceil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,11 @@ const TOINT: f64 = 1. / f64::EPSILON;
pub fn ceil(x: f64) -> f64 {
select_implementation! {
name: ceil,
use_arch_required: all(target_arch = "x86", not(target_feature = "sse2")),
use_intrinsic: target_arch = "wasm32",
args: x,
}

#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
{
//use an alternative implementation on x86, because the
//main implementation fails with the x87 FPU used by
//debian i386, probably due to excess precision issues.
//basic implementation taken from https://github.com/rust-lang/libm/issues/219
use super::fabs;
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated < x {
return truncated + 1.0;
} else {
return truncated;
}
} else {
return x;
}
}
let u: u64 = x.to_bits();
let e: i64 = (u >> 52 & 0x7ff) as i64;
let y: f64;
Expand Down
19 changes: 1 addition & 18 deletions src/math/floor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,11 @@ const TOINT: f64 = 1. / f64::EPSILON;
pub fn floor(x: f64) -> f64 {
select_implementation! {
name: floor,
use_arch_required: all(target_arch = "x86", not(target_feature = "sse2")),
use_intrinsic: target_arch = "wasm32",
args: x,
}

#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
{
//use an alternative implementation on x86, because the
//main implementation fails with the x87 FPU used by
//debian i386, probably due to excess precision issues.
//basic implementation taken from https://github.com/rust-lang/libm/issues/219
use super::fabs;
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated > x {
return truncated - 1.0;
} else {
return truncated;
}
} else {
return x;
}
}
let ui = x.to_bits();
let e = ((ui >> 52) & 0x7ff) as i32;

Expand Down
Loading

0 comments on commit 3c110e1

Please sign in to comment.