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