Skip to content

Commit 38271f6

Browse files
committed
Implement powi_f2
1 parent e34a605 commit 38271f6

File tree

7 files changed

+75
-28
lines changed

7 files changed

+75
-28
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ porting that particular intrinsic.
159159
- [x] mulodi4.c
160160
- [x] mulosi4.c
161161
- [ ] mulsf3.c
162-
- [ ] powidf2.c
163-
- [ ] powisf2.c
162+
- [x] powidf2.c
163+
- [x] powisf2.c
164164
- [ ] subdf3.c
165165
- [ ] subsf3.c
166166
- [ ] truncdfhf2.c

compiler-rt/compiler-rt-cdylib/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ fn main() {
5858
"udivmodsi4.c",
5959
"adddf3.c",
6060
"addsf3.c",
61+
"powidf2.c",
62+
"powisf2.c",
6163
]);
6264

6365
for src in sources.files.iter() {

compiler-rt/compiler-rt-cdylib/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ extern {
2222
fn __umodsi3();
2323
fn __addsf3();
2424
fn __adddf3();
25+
fn __powisf2();
26+
fn __powidf2();
2527
}
2628

2729
macro_rules! declare {
@@ -53,6 +55,8 @@ declare!(___umoddi3, __umoddi3);
5355
declare!(___umodsi3, __umodsi3);
5456
declare!(___addsf3, __addsf3);
5557
declare!(___adddf3, __adddf3);
58+
declare!(___powisf2, __powisf2);
59+
declare!(___powidf2, __powidf2);
5660

5761
#[lang = "eh_personality"]
5862
fn eh_personality() {}

src/float/add.rs

+4-26
Original file line numberDiff line numberDiff line change
@@ -190,40 +190,18 @@ mod tests {
190190
use float::Float;
191191
use qc::{F32, F64};
192192

193-
// NOTE The tests below have special handing for NaN values.
194-
// Because NaN != NaN, the floating-point representations must be used
195-
// Because there are many diffferent values of NaN, and the implementation
196-
// doesn't care about calculating the 'correct' one, if both values are NaN
197-
// the values are considered equivalent.
198-
199-
struct FRepr<F>(F);
200-
201-
impl<F: Float> PartialEq for FRepr<F> {
202-
fn eq(&self, other: &FRepr<F>) -> bool {
203-
// NOTE(cfg) for some reason, on hard float targets, our implementation doesn't
204-
// match the output of its gcc_s counterpart. Until we investigate further, we'll
205-
// just avoid testing against gcc_s on those targets. Do note that our
206-
// implementation matches the output of the FPU instruction on *hard* float targets
207-
// and matches its gcc_s counterpart on *soft* float targets.
208-
if cfg!(gnueabihf) {
209-
return true
210-
}
211-
self.0.eq_repr(other.0)
212-
}
213-
}
214-
215193
check! {
216194
fn __addsf3(f: extern fn(f32, f32) -> f32,
217195
a: F32,
218196
b: F32)
219-
-> Option<FRepr<f32> > {
220-
Some(FRepr(f(a.0, b.0)))
197+
-> Option<F32> {
198+
Some(F32(f(a.0, b.0)))
221199
}
222200

223201
fn __adddf3(f: extern fn(f64, f64) -> f64,
224202
a: F64,
225-
b: F64) -> Option<FRepr<f64> > {
226-
Some(FRepr(f(a.0, b.0)))
203+
b: F64) -> Option<F64> {
204+
Some(F64(f(a.0, b.0)))
227205
}
228206
}
229207
}

src/float/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use core::mem;
22

33
pub mod add;
4+
pub mod pow;
45

56
/// Trait for some basic operations on floats
67
pub trait Float: Sized + Copy {

src/float/pow.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
2+
macro_rules! pow {
3+
($intrinsic:ident: $fty:ty, $ity:ty) => {
4+
/// Returns `a` raised to the power `b`
5+
#[cfg_attr(not(test), no_mangle)]
6+
pub extern "C" fn $intrinsic(a: $fty, b: $ity) -> $fty {
7+
let (mut a, mut b) = (a, b);
8+
let recip = b < 0;
9+
let mut r: $fty = 1.0;
10+
loop {
11+
if (b & 1) != 0 {
12+
r *= a;
13+
}
14+
b /= 2;
15+
if b == 0 {
16+
break;
17+
}
18+
a *= a;
19+
}
20+
21+
if recip {
22+
1.0 / r
23+
} else {
24+
r
25+
}
26+
}
27+
}
28+
}
29+
30+
pow!(__powisf2: f32, i32);
31+
pow!(__powidf2: f64, i32);
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use qc::{I32, F32, F64};
36+
37+
check! {
38+
fn __powisf2(f: extern fn(f32, i32) -> f32, a: F32, b: I32) -> Option<F32> {
39+
let (a, b) = (a.0, b.0);
40+
Some(F32(f(a, b)))
41+
}
42+
43+
fn __powidf2(f: extern fn(f64, i32) -> f64, a: F64, b: I32) -> Option<F64> {
44+
let (a, b) = (a.0, b.0);
45+
Some(F64(f(a, b)))
46+
}
47+
}
48+
}

src/qc.rs

+14
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,20 @@ macro_rules! arbitrary_float {
190190
fmt::Debug::fmt(&self.0, f)
191191
}
192192
}
193+
194+
impl PartialEq for $TY {
195+
fn eq(&self, other: &Self) -> bool {
196+
// NOTE(cfg) for some reason, on hard float targets, our implementation doesn't
197+
// match the output of its gcc_s counterpart. Until we investigate further, we'll
198+
// just avoid testing against gcc_s on those targets. Do note that our
199+
// implementation matches the output of the FPU instruction on *hard* float targets
200+
// and matches its gcc_s counterpart on *soft* float targets.
201+
if cfg!(gnueabihf) {
202+
return true
203+
}
204+
self.0.eq_repr(other.0)
205+
}
206+
}
193207
}
194208
}
195209

0 commit comments

Comments
 (0)