1 // Copyright 2014 The Servo Project Developers. See the COPYRIGHT 2 // file at the top-level directory of this distribution. 3 // 4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 7 // option. This file may not be copied, modified, or distributed 8 // except according to those terms. 9 //! A one-dimensional length, tagged with its units. 10 11 use num_traits; 12 13 // Euclid has its own Zero and One traits instead of of using the num_traits equivalents. 14 // Unfortunately, num_traits::Zero requires Add, which opens a bag of sad things: 15 // - Most importantly, for Point2D to implement Zero it would need to implement Add<Self> which we 16 // don't want (we allow "Point + Vector" and "Vector + Vector" semantics and purposefully disallow 17 // "Point + Point". 18 // - Some operations that require, say, One and Div (for example Scale::inv) currently return a 19 // type parameterized over T::Output which is ambiguous with num_traits::One because it inherits 20 // Mul which also has an Output associated type. To fix it need to complicate type signatures 21 // by using <T as Trait>::Output which makes the code and documentation harder to read. 22 // 23 // On the other hand, euclid::num::Zero/One are automatically implemented for all types that 24 // implement their num_traits counterpart. Euclid users never need to explicitly use 25 // euclid::num::Zero/One and can/should only manipulate the num_traits equivalents without risk 26 // of compatibility issues with euclid. 27 28 pub trait Zero { zero() -> Self29 fn zero() -> Self; 30 } 31 32 impl<T: num_traits::Zero> Zero for T { zero() -> T33 fn zero() -> T { 34 num_traits::Zero::zero() 35 } 36 } 37 38 pub trait One { one() -> Self39 fn one() -> Self; 40 } 41 42 impl<T: num_traits::One> One for T { one() -> T43 fn one() -> T { 44 num_traits::One::one() 45 } 46 } 47 48 /// Defines the nearest integer value to the original value. 49 pub trait Round: Copy { 50 /// Rounds to the nearest integer value. 51 /// 52 /// This behavior is preserved for negative values (unlike the basic cast). 53 #[must_use] round(self) -> Self54 fn round(self) -> Self; 55 } 56 /// Defines the biggest integer equal or lower than the original value. 57 pub trait Floor: Copy { 58 /// Rounds to the biggest integer equal or lower than the original value. 59 /// 60 /// This behavior is preserved for negative values (unlike the basic cast). 61 #[must_use] floor(self) -> Self62 fn floor(self) -> Self; 63 } 64 /// Defines the smallest integer equal or greater than the original value. 65 pub trait Ceil: Copy { 66 /// Rounds to the smallest integer equal or greater than the original value. 67 /// 68 /// This behavior is preserved for negative values (unlike the basic cast). 69 #[must_use] ceil(self) -> Self70 fn ceil(self) -> Self; 71 } 72 73 macro_rules! num_int { 74 ($ty:ty) => { 75 impl Round for $ty { 76 #[inline] 77 fn round(self) -> $ty { 78 self 79 } 80 } 81 impl Floor for $ty { 82 #[inline] 83 fn floor(self) -> $ty { 84 self 85 } 86 } 87 impl Ceil for $ty { 88 #[inline] 89 fn ceil(self) -> $ty { 90 self 91 } 92 } 93 }; 94 } 95 96 macro_rules! num_float { 97 ($ty:ty) => { 98 impl Round for $ty { 99 #[inline] 100 fn round(self) -> $ty { 101 (self + 0.5).floor() 102 } 103 } 104 impl Floor for $ty { 105 #[inline] 106 fn floor(self) -> $ty { 107 num_traits::Float::floor(self) 108 } 109 } 110 impl Ceil for $ty { 111 #[inline] 112 fn ceil(self) -> $ty { 113 num_traits::Float::ceil(self) 114 } 115 } 116 }; 117 } 118 119 num_int!(i16); 120 num_int!(u16); 121 num_int!(i32); 122 num_int!(u32); 123 num_int!(i64); 124 num_int!(u64); 125 num_int!(isize); 126 num_int!(usize); 127 num_float!(f32); 128 num_float!(f64); 129