]>
Commit | Line | Data |
---|---|---|
7453a54e | 1 | //! Additional functionality for numerics. |
1a4d82fc | 2 | //! |
7453a54e SL |
3 | //! This module provides some extra types that are useful when doing numerical |
4 | //! work. See the individual documentation for each piece for more information. | |
1a4d82fc | 5 | |
85aaf69f | 6 | #![stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
7 | #![allow(missing_docs)] |
8 | ||
92a42be0 | 9 | #[stable(feature = "rust1", since = "1.0.0")] |
a7813a04 | 10 | pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError}; |
92a42be0 | 11 | #[stable(feature = "rust1", since = "1.0.0")] |
54a0048b | 12 | pub use core::num::Wrapping; |
1a4d82fc | 13 | |
94b46f34 XL |
14 | #[stable(feature = "nonzero", since = "1.28.0")] |
15 | pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize}; | |
0531ce1d | 16 | |
d9579d0f | 17 | #[cfg(test)] use fmt; |
d9579d0f | 18 | #[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem}; |
1a4d82fc JJ |
19 | |
20 | /// Helper function for testing numeric operations | |
21 | #[cfg(test)] | |
22 | pub fn test_num<T>(ten: T, two: T) where | |
9346a6ac | 23 | T: PartialEq |
1a4d82fc JJ |
24 | + Add<Output=T> + Sub<Output=T> |
25 | + Mul<Output=T> + Div<Output=T> | |
9346a6ac | 26 | + Rem<Output=T> + fmt::Debug |
1a4d82fc JJ |
27 | + Copy |
28 | { | |
1a4d82fc JJ |
29 | assert_eq!(ten.add(two), ten + two); |
30 | assert_eq!(ten.sub(two), ten - two); | |
31 | assert_eq!(ten.mul(two), ten * two); | |
32 | assert_eq!(ten.div(two), ten / two); | |
33 | assert_eq!(ten.rem(two), ten % two); | |
34 | } | |
35 | ||
36 | #[cfg(test)] | |
37 | mod tests { | |
1a4d82fc JJ |
38 | use u8; |
39 | use u16; | |
40 | use u32; | |
41 | use u64; | |
c34b1796 | 42 | use usize; |
9346a6ac | 43 | use ops::Mul; |
1a4d82fc JJ |
44 | |
45 | #[test] | |
46 | fn test_saturating_add_uint() { | |
c34b1796 | 47 | use usize::MAX; |
85aaf69f SL |
48 | assert_eq!(3_usize.saturating_add(5_usize), 8_usize); |
49 | assert_eq!(3_usize.saturating_add(MAX-1), MAX); | |
1a4d82fc JJ |
50 | assert_eq!(MAX.saturating_add(MAX), MAX); |
51 | assert_eq!((MAX-2).saturating_add(1), MAX-1); | |
52 | } | |
53 | ||
54 | #[test] | |
55 | fn test_saturating_sub_uint() { | |
c34b1796 | 56 | use usize::MAX; |
85aaf69f SL |
57 | assert_eq!(5_usize.saturating_sub(3_usize), 2_usize); |
58 | assert_eq!(3_usize.saturating_sub(5_usize), 0_usize); | |
59 | assert_eq!(0_usize.saturating_sub(1_usize), 0_usize); | |
1a4d82fc JJ |
60 | assert_eq!((MAX-1).saturating_sub(MAX), 0); |
61 | } | |
62 | ||
63 | #[test] | |
64 | fn test_saturating_add_int() { | |
c34b1796 | 65 | use isize::{MIN,MAX}; |
9346a6ac AL |
66 | assert_eq!(3i32.saturating_add(5), 8); |
67 | assert_eq!(3isize.saturating_add(MAX-1), MAX); | |
1a4d82fc JJ |
68 | assert_eq!(MAX.saturating_add(MAX), MAX); |
69 | assert_eq!((MAX-2).saturating_add(1), MAX-1); | |
9346a6ac | 70 | assert_eq!(3i32.saturating_add(-5), -2); |
85aaf69f | 71 | assert_eq!(MIN.saturating_add(-1), MIN); |
9346a6ac | 72 | assert_eq!((-2isize).saturating_add(-MAX), MIN); |
1a4d82fc JJ |
73 | } |
74 | ||
75 | #[test] | |
76 | fn test_saturating_sub_int() { | |
c34b1796 | 77 | use isize::{MIN,MAX}; |
9346a6ac | 78 | assert_eq!(3i32.saturating_sub(5), -2); |
85aaf69f | 79 | assert_eq!(MIN.saturating_sub(1), MIN); |
9346a6ac AL |
80 | assert_eq!((-2isize).saturating_sub(MAX), MIN); |
81 | assert_eq!(3i32.saturating_sub(-5), 8); | |
82 | assert_eq!(3isize.saturating_sub(-(MAX-1)), MAX); | |
1a4d82fc JJ |
83 | assert_eq!(MAX.saturating_sub(-MAX), MAX); |
84 | assert_eq!((MAX-2).saturating_sub(-1), MAX-1); | |
85 | } | |
86 | ||
87 | #[test] | |
88 | fn test_checked_add() { | |
c34b1796 AL |
89 | let five_less = usize::MAX - 5; |
90 | assert_eq!(five_less.checked_add(0), Some(usize::MAX - 5)); | |
91 | assert_eq!(five_less.checked_add(1), Some(usize::MAX - 4)); | |
92 | assert_eq!(five_less.checked_add(2), Some(usize::MAX - 3)); | |
93 | assert_eq!(five_less.checked_add(3), Some(usize::MAX - 2)); | |
94 | assert_eq!(five_less.checked_add(4), Some(usize::MAX - 1)); | |
95 | assert_eq!(five_less.checked_add(5), Some(usize::MAX)); | |
1a4d82fc JJ |
96 | assert_eq!(five_less.checked_add(6), None); |
97 | assert_eq!(five_less.checked_add(7), None); | |
98 | } | |
99 | ||
100 | #[test] | |
101 | fn test_checked_sub() { | |
85aaf69f SL |
102 | assert_eq!(5_usize.checked_sub(0), Some(5)); |
103 | assert_eq!(5_usize.checked_sub(1), Some(4)); | |
104 | assert_eq!(5_usize.checked_sub(2), Some(3)); | |
105 | assert_eq!(5_usize.checked_sub(3), Some(2)); | |
106 | assert_eq!(5_usize.checked_sub(4), Some(1)); | |
107 | assert_eq!(5_usize.checked_sub(5), Some(0)); | |
108 | assert_eq!(5_usize.checked_sub(6), None); | |
109 | assert_eq!(5_usize.checked_sub(7), None); | |
1a4d82fc JJ |
110 | } |
111 | ||
112 | #[test] | |
113 | fn test_checked_mul() { | |
c34b1796 | 114 | let third = usize::MAX / 3; |
1a4d82fc JJ |
115 | assert_eq!(third.checked_mul(0), Some(0)); |
116 | assert_eq!(third.checked_mul(1), Some(third)); | |
117 | assert_eq!(third.checked_mul(2), Some(third * 2)); | |
118 | assert_eq!(third.checked_mul(3), Some(third * 3)); | |
119 | assert_eq!(third.checked_mul(4), None); | |
120 | } | |
121 | ||
122 | macro_rules! test_is_power_of_two { | |
123 | ($test_name:ident, $T:ident) => ( | |
124 | fn $test_name() { | |
125 | #![test] | |
126 | assert_eq!((0 as $T).is_power_of_two(), false); | |
127 | assert_eq!((1 as $T).is_power_of_two(), true); | |
128 | assert_eq!((2 as $T).is_power_of_two(), true); | |
129 | assert_eq!((3 as $T).is_power_of_two(), false); | |
130 | assert_eq!((4 as $T).is_power_of_two(), true); | |
131 | assert_eq!((5 as $T).is_power_of_two(), false); | |
c34b1796 | 132 | assert_eq!(($T::MAX / 2 + 1).is_power_of_two(), true); |
1a4d82fc JJ |
133 | } |
134 | ) | |
135 | } | |
136 | ||
137 | test_is_power_of_two!{ test_is_power_of_two_u8, u8 } | |
138 | test_is_power_of_two!{ test_is_power_of_two_u16, u16 } | |
139 | test_is_power_of_two!{ test_is_power_of_two_u32, u32 } | |
140 | test_is_power_of_two!{ test_is_power_of_two_u64, u64 } | |
c34b1796 | 141 | test_is_power_of_two!{ test_is_power_of_two_uint, usize } |
1a4d82fc JJ |
142 | |
143 | macro_rules! test_next_power_of_two { | |
144 | ($test_name:ident, $T:ident) => ( | |
145 | fn $test_name() { | |
146 | #![test] | |
147 | assert_eq!((0 as $T).next_power_of_two(), 1); | |
148 | let mut next_power = 1; | |
c34b1796 | 149 | for i in 1 as $T..40 { |
1a4d82fc JJ |
150 | assert_eq!(i.next_power_of_two(), next_power); |
151 | if i == next_power { next_power *= 2 } | |
152 | } | |
153 | } | |
154 | ) | |
155 | } | |
156 | ||
157 | test_next_power_of_two! { test_next_power_of_two_u8, u8 } | |
158 | test_next_power_of_two! { test_next_power_of_two_u16, u16 } | |
159 | test_next_power_of_two! { test_next_power_of_two_u32, u32 } | |
160 | test_next_power_of_two! { test_next_power_of_two_u64, u64 } | |
c34b1796 | 161 | test_next_power_of_two! { test_next_power_of_two_uint, usize } |
1a4d82fc JJ |
162 | |
163 | macro_rules! test_checked_next_power_of_two { | |
164 | ($test_name:ident, $T:ident) => ( | |
165 | fn $test_name() { | |
166 | #![test] | |
167 | assert_eq!((0 as $T).checked_next_power_of_two(), Some(1)); | |
041b39d2 XL |
168 | let smax = $T::MAX >> 1; |
169 | assert_eq!(smax.checked_next_power_of_two(), Some(smax+1)); | |
170 | assert_eq!((smax + 1).checked_next_power_of_two(), Some(smax + 1)); | |
171 | assert_eq!((smax + 2).checked_next_power_of_two(), None); | |
1a4d82fc JJ |
172 | assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None); |
173 | assert_eq!($T::MAX.checked_next_power_of_two(), None); | |
174 | let mut next_power = 1; | |
c34b1796 | 175 | for i in 1 as $T..40 { |
1a4d82fc JJ |
176 | assert_eq!(i.checked_next_power_of_two(), Some(next_power)); |
177 | if i == next_power { next_power *= 2 } | |
178 | } | |
179 | } | |
180 | ) | |
181 | } | |
182 | ||
183 | test_checked_next_power_of_two! { test_checked_next_power_of_two_u8, u8 } | |
184 | test_checked_next_power_of_two! { test_checked_next_power_of_two_u16, u16 } | |
185 | test_checked_next_power_of_two! { test_checked_next_power_of_two_u32, u32 } | |
186 | test_checked_next_power_of_two! { test_checked_next_power_of_two_u64, u64 } | |
c34b1796 | 187 | test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, usize } |
1a4d82fc | 188 | |
1a4d82fc JJ |
189 | #[test] |
190 | fn test_pow() { | |
3157f602 | 191 | fn naive_pow<T: Mul<Output=T> + Copy>(one: T, base: T, exp: usize) -> T { |
85aaf69f | 192 | (0..exp).fold(one, |acc, _| acc * base) |
1a4d82fc JJ |
193 | } |
194 | macro_rules! assert_pow { | |
195 | (($num:expr, $exp:expr) => $expected:expr) => {{ | |
196 | let result = $num.pow($exp); | |
197 | assert_eq!(result, $expected); | |
3157f602 | 198 | assert_eq!(result, naive_pow(1, $num, $exp)); |
1a4d82fc JJ |
199 | }} |
200 | } | |
9346a6ac AL |
201 | assert_pow!((3u32, 0 ) => 1); |
202 | assert_pow!((5u32, 1 ) => 5); | |
203 | assert_pow!((-4i32, 2 ) => 16); | |
204 | assert_pow!((8u32, 3 ) => 512); | |
205 | assert_pow!((2u64, 50) => 1125899906842624); | |
1a4d82fc | 206 | } |
c34b1796 AL |
207 | |
208 | #[test] | |
209 | fn test_uint_to_str_overflow() { | |
210 | let mut u8_val: u8 = 255; | |
211 | assert_eq!(u8_val.to_string(), "255"); | |
212 | ||
213 | u8_val = u8_val.wrapping_add(1); | |
214 | assert_eq!(u8_val.to_string(), "0"); | |
215 | ||
216 | let mut u16_val: u16 = 65_535; | |
217 | assert_eq!(u16_val.to_string(), "65535"); | |
218 | ||
219 | u16_val = u16_val.wrapping_add(1); | |
220 | assert_eq!(u16_val.to_string(), "0"); | |
221 | ||
222 | let mut u32_val: u32 = 4_294_967_295; | |
223 | assert_eq!(u32_val.to_string(), "4294967295"); | |
224 | ||
225 | u32_val = u32_val.wrapping_add(1); | |
226 | assert_eq!(u32_val.to_string(), "0"); | |
227 | ||
228 | let mut u64_val: u64 = 18_446_744_073_709_551_615; | |
229 | assert_eq!(u64_val.to_string(), "18446744073709551615"); | |
230 | ||
231 | u64_val = u64_val.wrapping_add(1); | |
232 | assert_eq!(u64_val.to_string(), "0"); | |
233 | } | |
234 | ||
235 | fn from_str<T: ::str::FromStr>(t: &str) -> Option<T> { | |
236 | ::str::FromStr::from_str(t).ok() | |
237 | } | |
238 | ||
239 | #[test] | |
240 | fn test_uint_from_str_overflow() { | |
241 | let mut u8_val: u8 = 255; | |
242 | assert_eq!(from_str::<u8>("255"), Some(u8_val)); | |
243 | assert_eq!(from_str::<u8>("256"), None); | |
244 | ||
245 | u8_val = u8_val.wrapping_add(1); | |
246 | assert_eq!(from_str::<u8>("0"), Some(u8_val)); | |
247 | assert_eq!(from_str::<u8>("-1"), None); | |
248 | ||
249 | let mut u16_val: u16 = 65_535; | |
250 | assert_eq!(from_str::<u16>("65535"), Some(u16_val)); | |
251 | assert_eq!(from_str::<u16>("65536"), None); | |
252 | ||
253 | u16_val = u16_val.wrapping_add(1); | |
254 | assert_eq!(from_str::<u16>("0"), Some(u16_val)); | |
255 | assert_eq!(from_str::<u16>("-1"), None); | |
256 | ||
257 | let mut u32_val: u32 = 4_294_967_295; | |
258 | assert_eq!(from_str::<u32>("4294967295"), Some(u32_val)); | |
259 | assert_eq!(from_str::<u32>("4294967296"), None); | |
260 | ||
261 | u32_val = u32_val.wrapping_add(1); | |
262 | assert_eq!(from_str::<u32>("0"), Some(u32_val)); | |
263 | assert_eq!(from_str::<u32>("-1"), None); | |
264 | ||
265 | let mut u64_val: u64 = 18_446_744_073_709_551_615; | |
266 | assert_eq!(from_str::<u64>("18446744073709551615"), Some(u64_val)); | |
267 | assert_eq!(from_str::<u64>("18446744073709551616"), None); | |
268 | ||
269 | u64_val = u64_val.wrapping_add(1); | |
270 | assert_eq!(from_str::<u64>("0"), Some(u64_val)); | |
271 | assert_eq!(from_str::<u64>("-1"), None); | |
272 | } | |
1a4d82fc JJ |
273 | } |
274 | ||
275 | ||
276 | #[cfg(test)] | |
277 | mod bench { | |
278 | extern crate test; | |
279 | use self::test::Bencher; | |
1a4d82fc JJ |
280 | |
281 | #[bench] | |
282 | fn bench_pow_function(b: &mut Bencher) { | |
9346a6ac AL |
283 | let v = (0..1024).collect::<Vec<u32>>(); |
284 | b.iter(|| {v.iter().fold(0u32, |old, new| old.pow(*new as u32));}); | |
1a4d82fc JJ |
285 | } |
286 | } |