Skip to content

Commit ba0a984

Browse files
committed
core: Move intrinsic float functionality from std
The Float trait in libstd is quite a large trait which has dependencies on cmath (libm) and such, which libcore cannot satisfy. It also has many functions that libcore can implement, however, as LLVM has intrinsics or they're just bit twiddling. This commit moves what it can of the Float trait from the standard library into libcore to allow floats to be usable in the core library. The remaining functions are now resident in a FloatMath trait in the standard library (in the prelude now). Previous code which was generic over just the Float trait may now need to be generic over the FloatMath trait. [breaking-change]
1 parent 4994f3c commit ba0a984

File tree

8 files changed

+712
-696
lines changed

8 files changed

+712
-696
lines changed

src/libcore/num/f32.rs

Lines changed: 271 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
1313
use default::Default;
1414
use intrinsics;
15-
use num::{Zero, One, Bounded, Signed, Num, Primitive};
15+
use mem;
16+
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
17+
use num::{Zero, One, Bounded, Signed, Num, Primitive, Float};
18+
use option::Option;
1619

1720
#[cfg(not(test))] use cmp::{Eq, Ord};
1821
#[cfg(not(test))] use ops::{Add, Sub, Mul, Div, Rem, Neg};
@@ -225,3 +228,270 @@ impl Bounded for f32 {
225228
#[inline]
226229
fn max_value() -> f32 { MAX_VALUE }
227230
}
231+
232+
impl Float for f32 {
233+
#[inline]
234+
fn nan() -> f32 { NAN }
235+
236+
#[inline]
237+
fn infinity() -> f32 { INFINITY }
238+
239+
#[inline]
240+
fn neg_infinity() -> f32 { NEG_INFINITY }
241+
242+
#[inline]
243+
fn neg_zero() -> f32 { -0.0 }
244+
245+
/// Returns `true` if the number is NaN
246+
#[inline]
247+
fn is_nan(self) -> bool { self != self }
248+
249+
/// Returns `true` if the number is infinite
250+
#[inline]
251+
fn is_infinite(self) -> bool {
252+
self == Float::infinity() || self == Float::neg_infinity()
253+
}
254+
255+
/// Returns `true` if the number is neither infinite or NaN
256+
#[inline]
257+
fn is_finite(self) -> bool {
258+
!(self.is_nan() || self.is_infinite())
259+
}
260+
261+
/// Returns `true` if the number is neither zero, infinite, subnormal or NaN
262+
#[inline]
263+
fn is_normal(self) -> bool {
264+
self.classify() == FPNormal
265+
}
266+
267+
/// Returns the floating point category of the number. If only one property
268+
/// is going to be tested, it is generally faster to use the specific
269+
/// predicate instead.
270+
fn classify(self) -> FPCategory {
271+
static EXP_MASK: u32 = 0x7f800000;
272+
static MAN_MASK: u32 = 0x007fffff;
273+
274+
let bits: u32 = unsafe { mem::transmute(self) };
275+
match (bits & MAN_MASK, bits & EXP_MASK) {
276+
(0, 0) => FPZero,
277+
(_, 0) => FPSubnormal,
278+
(0, EXP_MASK) => FPInfinite,
279+
(_, EXP_MASK) => FPNaN,
280+
_ => FPNormal,
281+
}
282+
}
283+
284+
#[inline]
285+
fn mantissa_digits(_: Option<f32>) -> uint { MANTISSA_DIGITS }
286+
287+
#[inline]
288+
fn digits(_: Option<f32>) -> uint { DIGITS }
289+
290+
#[inline]
291+
fn epsilon() -> f32 { EPSILON }
292+
293+
#[inline]
294+
fn min_exp(_: Option<f32>) -> int { MIN_EXP }
295+
296+
#[inline]
297+
fn max_exp(_: Option<f32>) -> int { MAX_EXP }
298+
299+
#[inline]
300+
fn min_10_exp(_: Option<f32>) -> int { MIN_10_EXP }
301+
302+
#[inline]
303+
fn max_10_exp(_: Option<f32>) -> int { MAX_10_EXP }
304+
305+
#[inline]
306+
fn min_pos_value(_: Option<f32>) -> f32 { MIN_POS_VALUE }
307+
308+
/// Returns the mantissa, exponent and sign as integers.
309+
fn integer_decode(self) -> (u64, i16, i8) {
310+
let bits: u32 = unsafe { mem::transmute(self) };
311+
let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
312+
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
313+
let mantissa = if exponent == 0 {
314+
(bits & 0x7fffff) << 1
315+
} else {
316+
(bits & 0x7fffff) | 0x800000
317+
};
318+
// Exponent bias + mantissa shift
319+
exponent -= 127 + 23;
320+
(mantissa as u64, exponent, sign)
321+
}
322+
323+
/// Round half-way cases toward `NEG_INFINITY`
324+
#[inline]
325+
fn floor(self) -> f32 {
326+
unsafe { intrinsics::floorf32(self) }
327+
}
328+
329+
/// Round half-way cases toward `INFINITY`
330+
#[inline]
331+
fn ceil(self) -> f32 {
332+
unsafe { intrinsics::ceilf32(self) }
333+
}
334+
335+
/// Round half-way cases away from `0.0`
336+
#[inline]
337+
fn round(self) -> f32 {
338+
unsafe { intrinsics::roundf32(self) }
339+
}
340+
341+
/// The integer part of the number (rounds towards `0.0`)
342+
#[inline]
343+
fn trunc(self) -> f32 {
344+
unsafe { intrinsics::truncf32(self) }
345+
}
346+
347+
/// The fractional part of the number, satisfying:
348+
///
349+
/// ```rust
350+
/// let x = 1.65f32;
351+
/// assert!(x == x.trunc() + x.fract())
352+
/// ```
353+
#[inline]
354+
fn fract(self) -> f32 { self - self.trunc() }
355+
356+
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
357+
/// error. This produces a more accurate result with better performance than
358+
/// a separate multiplication operation followed by an add.
359+
#[inline]
360+
fn mul_add(self, a: f32, b: f32) -> f32 {
361+
unsafe { intrinsics::fmaf32(self, a, b) }
362+
}
363+
364+
/// The reciprocal (multiplicative inverse) of the number
365+
#[inline]
366+
fn recip(self) -> f32 { 1.0 / self }
367+
368+
fn powi(self, n: i32) -> f32 {
369+
unsafe { intrinsics::powif32(self, n) }
370+
}
371+
372+
#[inline]
373+
fn powf(self, n: f32) -> f32 {
374+
unsafe { intrinsics::powf32(self, n) }
375+
}
376+
377+
/// sqrt(2.0)
378+
#[inline]
379+
fn sqrt2() -> f32 { consts::SQRT2 }
380+
381+
/// 1.0 / sqrt(2.0)
382+
#[inline]
383+
fn frac_1_sqrt2() -> f32 { consts::FRAC_1_SQRT2 }
384+
385+
#[inline]
386+
fn sqrt(self) -> f32 {
387+
unsafe { intrinsics::sqrtf32(self) }
388+
}
389+
390+
#[inline]
391+
fn rsqrt(self) -> f32 { self.sqrt().recip() }
392+
393+
/// Archimedes' constant
394+
#[inline]
395+
fn pi() -> f32 { consts::PI }
396+
397+
/// 2.0 * pi
398+
#[inline]
399+
fn two_pi() -> f32 { consts::PI_2 }
400+
401+
/// pi / 2.0
402+
#[inline]
403+
fn frac_pi_2() -> f32 { consts::FRAC_PI_2 }
404+
405+
/// pi / 3.0
406+
#[inline]
407+
fn frac_pi_3() -> f32 { consts::FRAC_PI_3 }
408+
409+
/// pi / 4.0
410+
#[inline]
411+
fn frac_pi_4() -> f32 { consts::FRAC_PI_4 }
412+
413+
/// pi / 6.0
414+
#[inline]
415+
fn frac_pi_6() -> f32 { consts::FRAC_PI_6 }
416+
417+
/// pi / 8.0
418+
#[inline]
419+
fn frac_pi_8() -> f32 { consts::FRAC_PI_8 }
420+
421+
/// 1 .0/ pi
422+
#[inline]
423+
fn frac_1_pi() -> f32 { consts::FRAC_1_PI }
424+
425+
/// 2.0 / pi
426+
#[inline]
427+
fn frac_2_pi() -> f32 { consts::FRAC_2_PI }
428+
429+
/// 2.0 / sqrt(pi)
430+
#[inline]
431+
fn frac_2_sqrtpi() -> f32 { consts::FRAC_2_SQRTPI }
432+
433+
/// Euler's number
434+
#[inline]
435+
fn e() -> f32 { consts::E }
436+
437+
/// log2(e)
438+
#[inline]
439+
fn log2_e() -> f32 { consts::LOG2_E }
440+
441+
/// log10(e)
442+
#[inline]
443+
fn log10_e() -> f32 { consts::LOG10_E }
444+
445+
/// ln(2.0)
446+
#[inline]
447+
fn ln_2() -> f32 { consts::LN_2 }
448+
449+
/// ln(10.0)
450+
#[inline]
451+
fn ln_10() -> f32 { consts::LN_10 }
452+
453+
/// Returns the exponential of the number
454+
#[inline]
455+
fn exp(self) -> f32 {
456+
unsafe { intrinsics::expf32(self) }
457+
}
458+
459+
/// Returns 2 raised to the power of the number
460+
#[inline]
461+
fn exp2(self) -> f32 {
462+
unsafe { intrinsics::exp2f32(self) }
463+
}
464+
465+
/// Returns the natural logarithm of the number
466+
#[inline]
467+
fn ln(self) -> f32 {
468+
unsafe { intrinsics::logf32(self) }
469+
}
470+
471+
/// Returns the logarithm of the number with respect to an arbitrary base
472+
#[inline]
473+
fn log(self, base: f32) -> f32 { self.ln() / base.ln() }
474+
475+
/// Returns the base 2 logarithm of the number
476+
#[inline]
477+
fn log2(self) -> f32 {
478+
unsafe { intrinsics::log2f32(self) }
479+
}
480+
481+
/// Returns the base 10 logarithm of the number
482+
#[inline]
483+
fn log10(self) -> f32 {
484+
unsafe { intrinsics::log10f32(self) }
485+
}
486+
487+
/// Converts to degrees, assuming the number is in radians
488+
#[inline]
489+
fn to_degrees(self) -> f32 { self * (180.0f32 / Float::pi()) }
490+
491+
/// Converts to radians, assuming the number is in degrees
492+
#[inline]
493+
fn to_radians(self) -> f32 {
494+
let value: f32 = Float::pi();
495+
self * (value / 180.0f32)
496+
}
497+
}

0 commit comments

Comments
 (0)