]> git.lizzy.rs Git - rust.git/blob - src/librustc_const_math/float.rs
f557edffbda462053b3a8bfcfb737d407a291bd7
[rust.git] / src / librustc_const_math / float.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::cmp::Ordering;
12 use std::hash;
13 use std::mem::transmute;
14
15 use super::err::*;
16
17 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
18 pub enum ConstFloat {
19     F32(f32),
20     F64(f64)
21 }
22 pub use self::ConstFloat::*;
23
24 impl ConstFloat {
25     /// Description of the type, not the value
26     pub fn description(&self) -> &'static str {
27         match *self {
28             F32(_) => "f32",
29             F64(_) => "f64",
30         }
31     }
32
33     pub fn is_nan(&self) -> bool {
34         match *self {
35             F32(f) => f.is_nan(),
36             F64(f) => f.is_nan(),
37         }
38     }
39
40     /// Compares the values if they are of the same type
41     pub fn try_cmp(self, rhs: Self) -> Result<Ordering, ConstMathErr> {
42         match (self, rhs) {
43             (F64(a), F64(b))  => {
44                 // This is pretty bad but it is the existing behavior.
45                 Ok(if a == b {
46                     Ordering::Equal
47                 } else if a < b {
48                     Ordering::Less
49                 } else {
50                     Ordering::Greater
51                 })
52             }
53
54             (F32(a), F32(b)) => {
55                 Ok(if a == b {
56                     Ordering::Equal
57                 } else if a < b {
58                     Ordering::Less
59                 } else {
60                     Ordering::Greater
61                 })
62             }
63
64             _ => Err(CmpBetweenUnequalTypes),
65         }
66     }
67 }
68
69 /// Note that equality for `ConstFloat` means that the it is the same
70 /// constant, not that the rust values are equal. In particular, `NaN
71 /// == NaN` (at least if it's the same NaN; distinct encodings for NaN
72 /// are considering unequal).
73 impl PartialEq for ConstFloat {
74     fn eq(&self, other: &Self) -> bool {
75         match (*self, *other) {
76             (F64(a), F64(b)) => {
77                 unsafe{transmute::<_,u64>(a) == transmute::<_,u64>(b)}
78             }
79             (F32(a), F32(b)) => {
80                 unsafe{transmute::<_,u32>(a) == transmute::<_,u32>(b)}
81             }
82             _ => false
83         }
84     }
85 }
86
87 impl Eq for ConstFloat {}
88
89 impl hash::Hash for ConstFloat {
90     fn hash<H: hash::Hasher>(&self, state: &mut H) {
91         match *self {
92             F64(a) => {
93                 unsafe { transmute::<_,u64>(a) }.hash(state)
94             }
95             F32(a) => {
96                 unsafe { transmute::<_,u32>(a) }.hash(state)
97             }
98         }
99     }
100 }
101
102 impl ::std::fmt::Display for ConstFloat {
103     fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
104         match *self {
105             F32(f) => write!(fmt, "{}f32", f),
106             F64(f) => write!(fmt, "{}f64", f),
107         }
108     }
109 }
110
111 macro_rules! derive_binop {
112     ($op:ident, $func:ident) => {
113         impl ::std::ops::$op for ConstFloat {
114             type Output = Result<Self, ConstMathErr>;
115             fn $func(self, rhs: Self) -> Result<Self, ConstMathErr> {
116                 match (self, rhs) {
117                     (F32(a), F32(b)) => Ok(F32(a.$func(b))),
118                     (F64(a), F64(b)) => Ok(F64(a.$func(b))),
119                     _ => Err(UnequalTypes(Op::$op)),
120                 }
121             }
122         }
123     }
124 }
125
126 derive_binop!(Add, add);
127 derive_binop!(Sub, sub);
128 derive_binop!(Mul, mul);
129 derive_binop!(Div, div);
130 derive_binop!(Rem, rem);
131
132 impl ::std::ops::Neg for ConstFloat {
133     type Output = Self;
134     fn neg(self) -> Self {
135         match self {
136             F32(f) => F32(-f),
137             F64(f) => F64(-f),
138         }
139     }
140 }