]> git.lizzy.rs Git - rust.git/commitdiff
rustc_apfloat: stub IEEE & PPC implementations.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Tue, 11 Jul 2017 22:06:02 +0000 (01:06 +0300)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Wed, 2 Aug 2017 00:45:03 +0000 (03:45 +0300)
src/librustc_apfloat/ieee.rs [new file with mode: 0644]
src/librustc_apfloat/lib.rs
src/librustc_apfloat/ppc.rs [new file with mode: 0644]

diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs
new file mode 100644 (file)
index 0000000..aab426a
--- /dev/null
@@ -0,0 +1,265 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use {Category, ExpInt};
+use {Float, FloatConvert, ParseError, Round, StatusAnd};
+
+use std::cmp::Ordering;
+use std::fmt;
+use std::marker::PhantomData;
+use std::ops::Neg;
+
+#[must_use]
+pub struct IeeeFloat<S> {
+    marker: PhantomData<S>,
+}
+
+/// Represents floating point arithmetic semantics.
+pub trait Semantics: Sized {
+    /// Total number of bits in the in-memory format.
+    const BITS: usize;
+
+    /// Number of bits in the significand. This includes the integer bit.
+    const PRECISION: usize;
+
+    /// The largest E such that 2^E is representable; this matches the
+    /// definition of IEEE 754.
+    const MAX_EXP: ExpInt;
+
+    /// The smallest E such that 2^E is a normalized number; this
+    /// matches the definition of IEEE 754.
+    const MIN_EXP: ExpInt = -Self::MAX_EXP + 1;
+}
+
+impl<S> Copy for IeeeFloat<S> {}
+impl<S> Clone for IeeeFloat<S> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+macro_rules! ieee_semantics {
+    ($($name:ident = $sem:ident($bits:tt : $exp_bits:tt)),*) => {
+        $(pub struct $sem;)*
+        $(pub type $name = IeeeFloat<$sem>;)*
+        $(impl Semantics for $sem {
+            const BITS: usize = $bits;
+            const PRECISION: usize = ($bits - 1 - $exp_bits) + 1;
+            const MAX_EXP: ExpInt = (1 << ($exp_bits - 1)) - 1;
+        })*
+    }
+}
+
+ieee_semantics! {
+    Half = HalfS(16:5),
+    Single = SingleS(32:8),
+    Double = DoubleS(64:11),
+    Quad = QuadS(128:15)
+}
+
+pub struct X87DoubleExtendedS;
+pub type X87DoubleExtended = IeeeFloat<X87DoubleExtendedS>;
+impl Semantics for X87DoubleExtendedS {
+    const BITS: usize = 80;
+    const PRECISION: usize = 64;
+    const MAX_EXP: ExpInt = (1 << (15 - 1)) - 1;
+}
+
+float_common_impls!(IeeeFloat<S>);
+
+impl<S: Semantics> PartialEq for IeeeFloat<S> {
+    fn eq(&self, rhs: &Self) -> bool {
+        self.partial_cmp(rhs) == Some(Ordering::Equal)
+    }
+}
+
+#[allow(unused)]
+impl<S: Semantics> PartialOrd for IeeeFloat<S> {
+    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
+        panic!("NYI PartialOrd::partial_cmp");
+    }
+}
+
+impl<S> Neg for IeeeFloat<S> {
+    type Output = Self;
+    fn neg(self) -> Self {
+        panic!("NYI Neg::neg");
+    }
+}
+
+/// Prints this value as a decimal string.
+///
+/// \param precision The maximum number of digits of
+///   precision to output. If there are fewer digits available,
+///   zero padding will not be used unless the value is
+///   integral and small enough to be expressed in
+///   precision digits. 0 means to use the natural
+///   precision of the number.
+/// \param width The maximum number of zeros to
+///   consider inserting before falling back to scientific
+///   notation. 0 means to always use scientific notation.
+///
+/// \param alternate Indicate whether to remove the trailing zero in
+///   fraction part or not. Also setting this parameter to true forces
+///   producing of output more similar to default printf behavior.
+///   Specifically the lower e is used as exponent delimiter and exponent
+///   always contains no less than two digits.
+///
+/// Number       precision    width      Result
+/// ------       ---------    -----      ------
+/// 1.01E+4              5        2       10100
+/// 1.01E+4              4        2       1.01E+4
+/// 1.01E+4              5        1       1.01E+4
+/// 1.01E-2              5        2       0.0101
+/// 1.01E-2              4        2       0.0101
+/// 1.01E-2              4        1       1.01E-2
+#[allow(unused)]
+impl<S: Semantics> fmt::Display for IeeeFloat<S> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let frac_digits = f.precision().unwrap_or(0);
+        let width = f.width().unwrap_or(3);
+        let alternate = f.alternate();
+        panic!("NYI Display::fmt");
+    }
+}
+
+impl<S: Semantics> fmt::Debug for IeeeFloat<S> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self)
+    }
+}
+
+#[allow(unused)]
+impl<S: Semantics> Float for IeeeFloat<S> {
+    const BITS: usize = S::BITS;
+    const PRECISION: usize = S::PRECISION;
+    const MAX_EXP: ExpInt = S::MAX_EXP;
+    const MIN_EXP: ExpInt = S::MIN_EXP;
+
+    const ZERO: Self = IeeeFloat { marker: PhantomData };
+
+    const INFINITY: Self = IeeeFloat { marker: PhantomData };
+
+    // FIXME(eddyb) remove when qnan becomes const fn.
+    const NAN: Self = IeeeFloat { marker: PhantomData };
+
+    fn qnan(payload: Option<u128>) -> Self {
+        panic!("NYI qnan")
+    }
+
+    fn snan(payload: Option<u128>) -> Self {
+        panic!("NYI snan")
+    }
+
+    fn largest() -> Self {
+        panic!("NYI largest")
+    }
+
+    const SMALLEST: Self = IeeeFloat { marker: PhantomData };
+
+    fn smallest_normalized() -> Self {
+        panic!("NYI smallest_normalized")
+    }
+
+    fn add_r(self, rhs: Self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI add_r")
+    }
+
+    fn mul_r(self, rhs: Self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI mul_r")
+    }
+
+    fn mul_add_r(self, multiplicand: Self, addend: Self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI mul_add_r")
+    }
+
+    fn div_r(self, rhs: Self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI div_r")
+    }
+
+    fn c_fmod(self, rhs: Self) -> StatusAnd<Self> {
+        panic!("NYI c_fmod")
+    }
+
+    fn round_to_integral(self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI round_to_integral")
+    }
+
+    fn next_up(self) -> StatusAnd<Self> {
+        panic!("NYI next_up")
+    }
+
+    fn from_bits(input: u128) -> Self {
+        panic!("NYI from_bits")
+    }
+
+    fn from_u128_r(input: u128, round: Round) -> StatusAnd<Self> {
+        panic!("NYI from_u128_r")
+    }
+
+    fn from_str_r(s: &str, round: Round) -> Result<StatusAnd<Self>, ParseError> {
+        panic!("NYI from_str_r")
+    }
+
+    fn to_bits(self) -> u128 {
+        panic!("NYI to_bits")
+    }
+
+    fn to_u128_r(self, width: usize, round: Round, is_exact: &mut bool) -> StatusAnd<u128> {
+        panic!("NYI to_u128_r");
+    }
+
+    fn cmp_abs_normal(self, rhs: Self) -> Ordering {
+        panic!("NYI cmp_abs_normal")
+    }
+
+    fn bitwise_eq(self, rhs: Self) -> bool {
+        panic!("NYI bitwise_eq")
+    }
+
+    fn is_negative(self) -> bool {
+        panic!("NYI is_negative")
+    }
+
+    fn is_denormal(self) -> bool {
+        panic!("NYI is_denormal")
+    }
+
+    fn is_signaling(self) -> bool {
+        panic!("NYI is_signaling")
+    }
+
+    fn category(self) -> Category {
+        panic!("NYI category")
+    }
+
+    fn get_exact_inverse(self) -> Option<Self> {
+        panic!("NYI get_exact_inverse")
+    }
+
+    fn ilogb(self) -> ExpInt {
+        panic!("NYI ilogb")
+    }
+
+    fn scalbn_r(self, exp: ExpInt, round: Round) -> Self {
+        panic!("NYI scalbn")
+    }
+
+    fn frexp_r(self, exp: &mut ExpInt, round: Round) -> Self {
+        panic!("NYI frexp")
+    }
+}
+
+#[allow(unused)]
+impl<S: Semantics, T: Semantics> FloatConvert<IeeeFloat<T>> for IeeeFloat<S> {
+    fn convert_r(self, round: Round, loses_info: &mut bool) -> StatusAnd<IeeeFloat<T>> {
+        panic!("NYI convert_r");
+    }
+}
index 184f90c86decf8fb4961414608bcfd3d49c8949b..eb372b52c0a1044af9b785bf3939d611b5167070 100644 (file)
@@ -603,7 +603,6 @@ fn convert(self, loses_info: &mut bool) -> StatusAnd<T> {
     }
 }
 
-#[allow(unused)]
 macro_rules! float_common_impls {
     ($ty:ident<$t:tt>) => {
         impl<$t> Default for $ty<$t> where Self: Float {
@@ -687,3 +686,6 @@ fn rem_assign(&mut self, rhs: Self) {
         }
     }
 }
+
+pub mod ieee;
+pub mod ppc;
diff --git a/src/librustc_apfloat/ppc.rs b/src/librustc_apfloat/ppc.rs
new file mode 100644 (file)
index 0000000..03c4830
--- /dev/null
@@ -0,0 +1,187 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use {ieee, Category, ExpInt, Float, Round, ParseError, StatusAnd};
+
+use std::cmp::Ordering;
+use std::fmt;
+use std::ops::Neg;
+
+#[must_use]
+#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
+pub struct DoubleFloat<F>(F, F);
+pub type DoubleDouble = DoubleFloat<ieee::Double>;
+
+// These are legacy semantics for the Fallback, inaccrurate implementation of
+// IBM double-double, if the accurate DoubleDouble doesn't handle the
+// operation. It's equivalent to having an IEEE number with consecutive 106
+// bits of mantissa and 11 bits of exponent.
+//
+// It's not equivalent to IBM double-double. For example, a legit IBM
+// double-double, 1 + epsilon:
+//
+//   1 + epsilon = 1 + (1 >> 1076)
+//
+// is not representable by a consecutive 106 bits of mantissa.
+//
+// Currently, these semantics are used in the following way:
+//
+//   DoubleDouble -> (Double, Double) ->
+//   DoubleDouble's Fallback -> IEEE operations
+//
+// FIXME: Implement all operations in DoubleDouble, and delete these
+// semantics.
+// FIXME(eddyb) This shouldn't need to be `pub`, it's only used in bounds.
+pub struct FallbackS<F>(F);
+type Fallback<F> = ieee::IeeeFloat<FallbackS<F>>;
+impl<F: Float> ieee::Semantics for FallbackS<F> {
+    // Forbid any conversion to/from bits.
+    const BITS: usize = 0;
+    const PRECISION: usize = F::PRECISION * 2;
+    const MAX_EXP: ExpInt = F::MAX_EXP as ExpInt;
+    const MIN_EXP: ExpInt = F::MIN_EXP as ExpInt + F::PRECISION as ExpInt;
+}
+
+float_common_impls!(DoubleFloat<F>);
+
+impl<F: Float> Neg for DoubleFloat<F> {
+    type Output = Self;
+    fn neg(self) -> Self {
+        panic!("NYI Neg::neg");
+    }
+}
+
+#[allow(unused)]
+impl<F: Float> fmt::Display for DoubleFloat<F> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        panic!("NYI Display::fmt");
+    }
+}
+
+#[allow(unused)]
+impl<F: Float> Float for DoubleFloat<F> {
+    const BITS: usize = F::BITS * 2;
+    const PRECISION: usize = Fallback::<F>::PRECISION;
+    const MAX_EXP: ExpInt = Fallback::<F>::MAX_EXP;
+    const MIN_EXP: ExpInt = Fallback::<F>::MIN_EXP;
+
+    const ZERO: Self = DoubleFloat(F::ZERO, F::ZERO);
+
+    const INFINITY: Self = DoubleFloat(F::INFINITY, F::ZERO);
+
+    // FIXME(eddyb) remove when qnan becomes const fn.
+    const NAN: Self = DoubleFloat(F::NAN, F::ZERO);
+
+    fn qnan(payload: Option<u128>) -> Self {
+        panic!("NYI qnan")
+    }
+
+    fn snan(payload: Option<u128>) -> Self {
+        panic!("NYI snan")
+    }
+
+    fn largest() -> Self {
+        panic!("NYI largest")
+    }
+
+    const SMALLEST: Self = DoubleFloat(F::SMALLEST, F::ZERO);
+
+    fn smallest_normalized() -> Self {
+        panic!("NYI smallest_normalized")
+    }
+
+    fn add_r(self, rhs: Self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI add_r")
+    }
+
+    fn mul_r(self, rhs: Self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI mul_r")
+    }
+
+    fn mul_add_r(self, multiplicand: Self, addend: Self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI mul_add_r")
+    }
+
+    fn div_r(self, rhs: Self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI div_r")
+    }
+
+    fn c_fmod(self, rhs: Self) -> StatusAnd<Self> {
+        panic!("NYI c_fmod")
+    }
+
+    fn round_to_integral(self, round: Round) -> StatusAnd<Self> {
+        panic!("NYI round_to_integral")
+    }
+
+    fn next_up(self) -> StatusAnd<Self> {
+        panic!("NYI next_up")
+    }
+
+    fn from_bits(input: u128) -> Self {
+        panic!("NYI from_bits")
+    }
+
+    fn from_u128_r(input: u128, round: Round) -> StatusAnd<Self> {
+        panic!("NYI from_u128_r")
+    }
+
+    fn from_str_r(s: &str, round: Round) -> Result<StatusAnd<Self>, ParseError> {
+        panic!("NYI from_str_r")
+    }
+
+    fn to_bits(self) -> u128 {
+        panic!("NYI to_bits")
+    }
+
+    fn to_u128_r(self, width: usize, round: Round, is_exact: &mut bool) -> StatusAnd<u128> {
+        panic!("NYI to_u128_r");
+    }
+
+    fn cmp_abs_normal(self, rhs: Self) -> Ordering {
+        panic!("NYI cmp_abs_normal")
+    }
+
+    fn bitwise_eq(self, rhs: Self) -> bool {
+        panic!("NYI bitwise_eq")
+    }
+
+    fn is_negative(self) -> bool {
+        panic!("NYI is_negative")
+    }
+
+    fn is_denormal(self) -> bool {
+        panic!("NYI is_denormal")
+    }
+
+    fn is_signaling(self) -> bool {
+        panic!("NYI is_signaling")
+    }
+
+    fn category(self) -> Category {
+        panic!("NYI category")
+    }
+
+    fn get_exact_inverse(self) -> Option<Self> {
+        panic!("NYI get_exact_inverse")
+    }
+
+    fn ilogb(self) -> ExpInt {
+        panic!("NYI ilogb")
+    }
+
+    fn scalbn_r(self, exp: ExpInt, round: Round) -> Self {
+        panic!("NYI scalbn")
+    }
+
+    fn frexp_r(self, exp: &mut ExpInt, round: Round) -> Self {
+        panic!("NYI frexp")
+    }
+}