Skip to content

Commit 8970485

Browse files
committed
Implement mulsf3 and muldf3
1 parent 1be2858 commit 8970485

File tree

7 files changed

+483
-2
lines changed

7 files changed

+483
-2
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,11 @@ features = ["c"]
170170
- [x] lshrdi3.c
171171
- [x] moddi3.c
172172
- [x] modsi3.c
173-
- [ ] muldf3.c
173+
- [x] muldf3.c
174174
- [x] muldi3.c
175175
- [x] mulodi4.c
176176
- [x] mulosi4.c
177-
- [ ] mulsf3.c
177+
- [x] mulsf3.c
178178
- [x] powidf2.c
179179
- [x] powisf2.c
180180
- [ ] subdf3.c

build.rs

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ mod tests {
121121
Subdf3,
122122
Subsf3,
123123

124+
// float/mul.rs
125+
Mulsf3,
126+
Muldf3,
127+
124128
// int/mul.rs
125129
Muldi3,
126130
Mulodi4,
@@ -3221,6 +3225,181 @@ fn subsf3() {
32213225
}
32223226
}
32233227

3228+
#[derive(Eq, Hash, PartialEq)]
3229+
pub struct Mulsf3 {
3230+
a: u32, // f32
3231+
b: u32, // f32
3232+
c: u32, // f32
3233+
}
3234+
3235+
impl TestCase for Mulsf3 {
3236+
fn name() -> &'static str {
3237+
"mulsf3"
3238+
}
3239+
3240+
fn generate<R>(rng: &mut R) -> Option<Self>
3241+
where
3242+
R: Rng,
3243+
Self: Sized,
3244+
{
3245+
let a = gen_large_f32(rng);
3246+
let b = gen_large_f32(rng);
3247+
let c = a * b;
3248+
// TODO accept NaNs. We don't do that right now because we can't check
3249+
// for NaN-ness on the thumb targets (due to missing intrinsics)
3250+
if a.is_nan() || b.is_nan() || c.is_nan() {
3251+
return None;
3252+
}
3253+
3254+
Some(
3255+
Mulsf3 {
3256+
a: to_u32(a),
3257+
b: to_u32(b),
3258+
c: to_u32(c),
3259+
},
3260+
)
3261+
}
3262+
3263+
fn to_string(&self, buffer: &mut String) {
3264+
writeln!(
3265+
buffer,
3266+
"(({a}, {b}), {c}),",
3267+
a = self.a,
3268+
b = self.b,
3269+
c = self.c
3270+
)
3271+
.unwrap();
3272+
}
3273+
3274+
fn prologue() -> &'static str {
3275+
r#"
3276+
#[cfg(all(target_arch = "arm",
3277+
not(any(target_env = "gnu", target_env = "musl")),
3278+
target_os = "linux",
3279+
test))]
3280+
use core::mem;
3281+
#[cfg(not(all(target_arch = "arm",
3282+
not(any(target_env = "gnu", target_env = "musl")),
3283+
target_os = "linux",
3284+
test)))]
3285+
use std::mem;
3286+
use compiler_builtins::float::mul::__mulsf3;
3287+
3288+
fn mk_f32(x: u32) -> f32 {
3289+
unsafe { mem::transmute(x) }
3290+
}
3291+
3292+
fn to_u32(x: f32) -> u32 {
3293+
unsafe { mem::transmute(x) }
3294+
}
3295+
3296+
static TEST_CASES: &[((u32, u32), u32)] = &[
3297+
"#
3298+
}
3299+
3300+
fn epilogue() -> &'static str {
3301+
"
3302+
];
3303+
3304+
#[test]
3305+
fn mulsf3() {
3306+
for &((a, b), c) in TEST_CASES {
3307+
let c_ = __mulsf3(mk_f32(a), mk_f32(b));
3308+
assert_eq!(((a, b), c), ((a, b), to_u32(c_)));
3309+
}
3310+
}
3311+
"
3312+
}
3313+
}
3314+
3315+
#[derive(Eq, Hash, PartialEq)]
3316+
pub struct Muldf3 {
3317+
a: u64, // f64
3318+
b: u64, // f64
3319+
c: u64, // f64
3320+
}
3321+
3322+
impl TestCase for Muldf3 {
3323+
fn name() -> &'static str {
3324+
"muldf3"
3325+
}
3326+
3327+
fn generate<R>(rng: &mut R) -> Option<Self>
3328+
where
3329+
R: Rng,
3330+
Self: Sized,
3331+
{
3332+
let a = gen_large_f64(rng);
3333+
let b = gen_large_f64(rng);
3334+
let c = a * b;
3335+
// TODO accept NaNs. We don't do that right now because we can't check
3336+
// for NaN-ness on the thumb targets (due to missing intrinsics)
3337+
if a.is_nan() || b.is_nan() || c.is_nan() {
3338+
return None;
3339+
}
3340+
3341+
Some(
3342+
Muldf3 {
3343+
a: to_u64(a),
3344+
b: to_u64(b),
3345+
c: to_u64(c),
3346+
},
3347+
)
3348+
}
3349+
3350+
fn to_string(&self, buffer: &mut String) {
3351+
writeln!(
3352+
buffer,
3353+
"(({a}, {b}), {c}),",
3354+
a = self.a,
3355+
b = self.b,
3356+
c = self.c
3357+
)
3358+
.unwrap();
3359+
}
3360+
3361+
fn prologue() -> &'static str {
3362+
r#"
3363+
#[cfg(all(target_arch = "arm",
3364+
not(any(target_env = "gnu", target_env = "musl")),
3365+
target_os = "linux",
3366+
test))]
3367+
use core::mem;
3368+
#[cfg(not(all(target_arch = "arm",
3369+
not(any(target_env = "gnu", target_env = "musl")),
3370+
target_os = "linux",
3371+
test)))]
3372+
use std::mem;
3373+
use compiler_builtins::float::mul::__muldf3;
3374+
3375+
fn mk_f64(x: u64) -> f64 {
3376+
unsafe { mem::transmute(x) }
3377+
}
3378+
3379+
fn to_u64(x: f64) -> u64 {
3380+
unsafe { mem::transmute(x) }
3381+
}
3382+
3383+
static TEST_CASES: &[((u64, u64), u64)] = &[
3384+
"#
3385+
}
3386+
3387+
fn epilogue() -> &'static str {
3388+
"
3389+
];
3390+
3391+
#[test]
3392+
fn muldf3() {
3393+
for &((a, b), c) in TEST_CASES {
3394+
let c_ = __muldf3(mk_f64(a), mk_f64(b));
3395+
assert_eq!(((a, b), c), ((a, b), to_u64(c_)));
3396+
}
3397+
}
3398+
"
3399+
}
3400+
}
3401+
3402+
32243403
#[derive(Eq, Hash, PartialEq)]
32253404
pub struct Udivdi3 {
32263405
a: u64,
@@ -3899,6 +4078,57 @@ macro_rules! panic {
38994078
gen_float!(gen_f32, f32, u32, 32, 23);
39004079
gen_float!(gen_f64, f64, u64, 64, 52);
39014080

4081+
macro_rules! gen_large_float {
4082+
($name:ident,
4083+
$fty:ident,
4084+
$uty:ident,
4085+
$bits:expr,
4086+
$significand_bits:expr) => {
4087+
pub fn $name<R>(rng: &mut R) -> $fty
4088+
where
4089+
R: Rng,
4090+
{
4091+
const BITS: u8 = $bits;
4092+
const SIGNIFICAND_BITS: u8 = $significand_bits;
4093+
4094+
const SIGNIFICAND_MASK: $uty = (1 << SIGNIFICAND_BITS) - 1;
4095+
const SIGN_MASK: $uty = (1 << (BITS - 1));
4096+
const EXPONENT_MASK: $uty = !(SIGN_MASK | SIGNIFICAND_MASK);
4097+
4098+
fn mk_f32(sign: bool, exponent: $uty, significand: $uty) -> $fty {
4099+
unsafe {
4100+
mem::transmute(((sign as $uty) << (BITS - 1)) |
4101+
((exponent & EXPONENT_MASK) <<
4102+
SIGNIFICAND_BITS) |
4103+
(significand & SIGNIFICAND_MASK))
4104+
}
4105+
}
4106+
4107+
if rng.gen_weighted_bool(10) {
4108+
// Special values
4109+
*rng.choose(&[-0.0,
4110+
0.0,
4111+
::std::$fty::NAN,
4112+
::std::$fty::INFINITY,
4113+
-::std::$fty::INFINITY])
4114+
.unwrap()
4115+
} else if rng.gen_weighted_bool(10) {
4116+
// NaN patterns
4117+
mk_f32(rng.gen(), rng.gen(), 0)
4118+
} else if rng.gen() {
4119+
// Denormalized
4120+
mk_f32(rng.gen(), 0, rng.gen())
4121+
} else {
4122+
// Random anything
4123+
rng.gen::<$fty>()
4124+
}
4125+
}
4126+
}
4127+
}
4128+
4129+
gen_large_float!(gen_large_f32, f32, u32, 32, 23);
4130+
gen_large_float!(gen_large_f64, f64, u64, 64, 52);
4131+
39024132
pub fn gen_u128<R>(rng: &mut R) -> u128
39034133
where
39044134
R: Rng,

src/float/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod conv;
77
pub mod add;
88
pub mod pow;
99
pub mod sub;
10+
pub mod mul;
1011

1112
/// Trait for some basic operations on floats
1213
pub trait Float:

0 commit comments

Comments
 (0)