Auto merge of #142 - rust-lang-nursery:sub, r=alexcrichton
implement float subtraction as a + (-b) r? @alexcrichton
This commit is contained in:
commit
1550b0d32f
2
build.rs
2
build.rs
|
@ -170,8 +170,6 @@ fn main() {
|
||||||
"popcountdi2.c",
|
"popcountdi2.c",
|
||||||
"popcountsi2.c",
|
"popcountsi2.c",
|
||||||
"powixf2.c",
|
"powixf2.c",
|
||||||
"subdf3.c",
|
|
||||||
"subsf3.c",
|
|
||||||
"subvdi3.c",
|
"subvdi3.c",
|
||||||
"subvsi3.c",
|
"subvsi3.c",
|
||||||
"truncdfhf2.c",
|
"truncdfhf2.c",
|
||||||
|
|
|
@ -60,6 +60,8 @@ fn main() {
|
||||||
"addsf3.c",
|
"addsf3.c",
|
||||||
"powidf2.c",
|
"powidf2.c",
|
||||||
"powisf2.c",
|
"powisf2.c",
|
||||||
|
"subdf3.c",
|
||||||
|
"subsf3.c",
|
||||||
// 128 bit integers
|
// 128 bit integers
|
||||||
"lshrti3.c",
|
"lshrti3.c",
|
||||||
"modti3.c",
|
"modti3.c",
|
||||||
|
|
|
@ -24,6 +24,8 @@ extern {
|
||||||
fn __adddf3();
|
fn __adddf3();
|
||||||
fn __powisf2();
|
fn __powisf2();
|
||||||
fn __powidf2();
|
fn __powidf2();
|
||||||
|
fn __subsf3();
|
||||||
|
fn __subdf3();
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! declare {
|
macro_rules! declare {
|
||||||
|
@ -57,6 +59,8 @@ declare!(___addsf3, __addsf3);
|
||||||
declare!(___adddf3, __adddf3);
|
declare!(___adddf3, __adddf3);
|
||||||
declare!(___powisf2, __powisf2);
|
declare!(___powisf2, __powisf2);
|
||||||
declare!(___powidf2, __powidf2);
|
declare!(___powidf2, __powidf2);
|
||||||
|
declare!(___subsf3, __subsf3);
|
||||||
|
declare!(___subdf3, __subdf3);
|
||||||
|
|
||||||
#[cfg(all(not(windows),
|
#[cfg(all(not(windows),
|
||||||
not(target_arch = "mips64"),
|
not(target_arch = "mips64"),
|
||||||
|
|
12
src/arm.rs
12
src/arm.rs
|
@ -60,7 +60,6 @@ pub unsafe fn __aeabi_ldivmod() {
|
||||||
intrinsics::unreachable();
|
intrinsics::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: These aeabi_* functions should be defined as aliases
|
|
||||||
#[cfg_attr(not(test), no_mangle)]
|
#[cfg_attr(not(test), no_mangle)]
|
||||||
pub extern "aapcs" fn __aeabi_dadd(a: f64, b: f64) -> f64 {
|
pub extern "aapcs" fn __aeabi_dadd(a: f64, b: f64) -> f64 {
|
||||||
::float::add::__adddf3(a, b)
|
::float::add::__adddf3(a, b)
|
||||||
|
@ -71,6 +70,16 @@ pub extern "aapcs" fn __aeabi_fadd(a: f32, b: f32) -> f32 {
|
||||||
::float::add::__addsf3(a, b)
|
::float::add::__addsf3(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(test), no_mangle)]
|
||||||
|
pub extern "aapcs" fn __aeabi_dsub(a: f64, b: f64) -> f64 {
|
||||||
|
::float::sub::__subdf3(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(test), no_mangle)]
|
||||||
|
pub extern "aapcs" fn __aeabi_fsub(a: f32, b: f32) -> f32 {
|
||||||
|
::float::sub::__subsf3(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))]
|
#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))]
|
||||||
#[cfg_attr(not(test), no_mangle)]
|
#[cfg_attr(not(test), no_mangle)]
|
||||||
pub extern "aapcs" fn __aeabi_idiv(a: i32, b: i32) -> i32 {
|
pub extern "aapcs" fn __aeabi_idiv(a: i32, b: i32) -> i32 {
|
||||||
|
@ -103,6 +112,7 @@ pub extern "aapcs" fn __aeabi_uidiv(a: u32, b: u32) -> u32 {
|
||||||
::int::udiv::__udivsi3(a, b)
|
::int::udiv::__udivsi3(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: These aeabi_* functions should be defined as aliases
|
||||||
#[cfg(not(feature = "mem"))]
|
#[cfg(not(feature = "mem"))]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
|
fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
|
||||||
|
|
|
@ -2,6 +2,7 @@ use core::mem;
|
||||||
|
|
||||||
pub mod add;
|
pub mod add;
|
||||||
pub mod pow;
|
pub mod pow;
|
||||||
|
pub mod sub;
|
||||||
|
|
||||||
/// Trait for some basic operations on floats
|
/// Trait for some basic operations on floats
|
||||||
pub trait Float: Sized + Copy {
|
pub trait Float: Sized + Copy {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
use float::Float;
|
||||||
|
|
||||||
|
macro_rules! sub {
|
||||||
|
($(#[$attr:meta])*
|
||||||
|
| $intrinsic:ident: $ty:ty) => {
|
||||||
|
/// Returns `a - b`
|
||||||
|
$(#[$attr])*
|
||||||
|
pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty {
|
||||||
|
a + <$ty>::from_repr(b.repr() ^ <$ty>::sign_mask())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)]
|
||||||
|
#[cfg_attr(all(not(test), target_arch = "arm"), inline(always))]
|
||||||
|
| __subsf3: f32);
|
||||||
|
|
||||||
|
sub!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)]
|
||||||
|
#[cfg_attr(all(not(test), target_arch = "arm"), inline(always))]
|
||||||
|
| __subdf3: f64);
|
||||||
|
|
||||||
|
// NOTE(cfg) for some reason, on arm*-unknown-linux-gnueabi*, our implementation doesn't
|
||||||
|
// match the output of its gcc_s or compiler-rt counterpart. Until we investigate further, we'll
|
||||||
|
// just avoid testing against them on those targets. Do note that our implementation gives the
|
||||||
|
// correct answer; gcc_s and compiler-rt are incorrect in this case.
|
||||||
|
#[cfg(all(test, not(arm_linux)))]
|
||||||
|
mod tests {
|
||||||
|
use core::{f32, f64};
|
||||||
|
use qc::{F32, F64};
|
||||||
|
|
||||||
|
check! {
|
||||||
|
fn __subsf3(f: extern "C" fn(f32, f32) -> f32,
|
||||||
|
a: F32,
|
||||||
|
b: F32)
|
||||||
|
-> Option<F32> {
|
||||||
|
Some(F32(f(a.0, b.0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn __subdf3(f: extern "C" fn(f64, f64) -> f64,
|
||||||
|
a: F64,
|
||||||
|
b: F64) -> Option<F64> {
|
||||||
|
Some(F64(f(a.0, b.0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue