]> git.lizzy.rs Git - rust.git/blob - src/libcore/num/num.rs
3e43ebfef12228152ba43c8a5eb09a24cabba120
[rust.git] / src / libcore / num / num.rs
1 // Copyright 2012-2013 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 //! An interface for numeric types
12 use cmp::{Eq, Ord};
13 #[cfg(stage0)]
14 use ops::{Add, Sub, Mul, Neg};
15 #[cfg(stage0)]
16 use Quot = ops::Div;
17 #[cfg(stage0)]
18 use Rem = ops::Modulo;
19 #[cfg(not(stage0))]
20 use ops::{Add, Sub, Mul, Quot, Rem, Neg};
21 use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
22 use option::Option;
23 use kinds::Copy;
24
25 pub mod strconv;
26
27 ///
28 /// The base trait for numeric types
29 ///
30 pub trait Num: Eq + Zero + One
31              + Neg<Self>
32              + Add<Self,Self>
33              + Sub<Self,Self>
34              + Mul<Self,Self>
35              + Quot<Self,Self>
36              + Rem<Self,Self> {}
37
38 pub trait IntConvertible {
39     fn to_int(&self) -> int;
40     fn from_int(n: int) -> Self;
41 }
42
43 pub trait Orderable: Ord {
44     // These should be methods on `Ord`, with overridable default implementations. We don't want
45     // to encumber all implementors of Ord by requiring them to implement these functions, but at
46     // the same time we want to be able to take advantage of the speed of the specific numeric
47     // functions (like the `fmin` and `fmax` intrinsics).
48     fn min(&self, other: &Self) -> Self;
49     fn max(&self, other: &Self) -> Self;
50     fn clamp(&self, mn: &Self, mx: &Self) -> Self;
51 }
52
53 pub trait Zero {
54     fn zero() -> Self;      // FIXME (#5527): This should be an associated constant
55     fn is_zero(&self) -> bool;
56 }
57
58 pub trait One {
59     fn one() -> Self;       // FIXME (#5527): This should be an associated constant
60 }
61
62 pub trait Signed: Num
63                 + Neg<Self> {
64     fn abs(&self) -> Self;
65     fn signum(&self) -> Self;
66     fn is_positive(&self) -> bool;
67     fn is_negative(&self) -> bool;
68 }
69
70 pub trait Unsigned: Num {}
71
72 // This should be moved into the default implementation for Signed::abs
73 pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
74     if v < Zero::zero() { v.neg() } else { v }
75 }
76
77 pub trait Integer: Num
78                  + Orderable
79                  + Quot<Self,Self>
80                  + Rem<Self,Self> {
81     fn div(&self, other: &Self) -> Self;
82     fn modulo(&self, other: &Self) -> Self;
83     fn div_mod(&self, other: &Self) -> (Self,Self);
84     fn quot_rem(&self, other: &Self) -> (Self,Self);
85
86     fn gcd(&self, other: &Self) -> Self;
87     fn lcm(&self, other: &Self) -> Self;
88
89     fn is_multiple_of(&self, other: &Self) -> bool;
90     fn is_even(&self) -> bool;
91     fn is_odd(&self) -> bool;
92 }
93
94 pub trait Round {
95     fn floor(&self) -> Self;
96     fn ceil(&self) -> Self;
97     fn round(&self) -> Self;
98     fn trunc(&self) -> Self;
99     fn fract(&self) -> Self;
100 }
101
102 pub trait Fractional: Num
103                     + Orderable
104                     + Round
105                     + Quot<Self,Self> {
106     fn recip(&self) -> Self;
107 }
108
109 pub trait Algebraic {
110     fn pow(&self, n: Self) -> Self;
111     fn sqrt(&self) -> Self;
112     fn rsqrt(&self) -> Self;
113     fn cbrt(&self) -> Self;
114     fn hypot(&self, other: Self) -> Self;
115 }
116
117 pub trait Trigonometric {
118     fn sin(&self) -> Self;
119     fn cos(&self) -> Self;
120     fn tan(&self) -> Self;
121     fn asin(&self) -> Self;
122     fn acos(&self) -> Self;
123     fn atan(&self) -> Self;
124     fn atan2(&self, other: Self) -> Self;
125 }
126
127 pub trait Exponential {
128     fn exp(&self) -> Self;
129     fn exp2(&self) -> Self;
130     fn expm1(&self) -> Self;
131     fn log(&self) -> Self;
132     fn log2(&self) -> Self;
133     fn log10(&self) -> Self;
134 }
135
136 pub trait Hyperbolic: Exponential {
137     fn sinh(&self) -> Self;
138     fn cosh(&self) -> Self;
139     fn tanh(&self) -> Self;
140 }
141
142 ///
143 /// Defines constants and methods common to real numbers
144 ///
145 pub trait Real: Signed
146               + Fractional
147               + Algebraic
148               + Trigonometric
149               + Hyperbolic {
150     // Common Constants
151     // FIXME (#5527): These should be associated constants
152     fn pi() -> Self;
153     fn two_pi() -> Self;
154     fn frac_pi_2() -> Self;
155     fn frac_pi_3() -> Self;
156     fn frac_pi_4() -> Self;
157     fn frac_pi_6() -> Self;
158     fn frac_pi_8() -> Self;
159     fn frac_1_pi() -> Self;
160     fn frac_2_pi() -> Self;
161     fn frac_2_sqrtpi() -> Self;
162     fn sqrt2() -> Self;
163     fn frac_1_sqrt2() -> Self;
164     fn e() -> Self;
165     fn log2_e() -> Self;
166     fn log10_e() -> Self;
167     fn log_2() -> Self;
168     fn log_10() -> Self;
169
170     // Angular conversions
171     fn to_degrees(&self) -> Self;
172     fn to_radians(&self) -> Self;
173 }
174
175 ///
176 /// Methods that are harder to implement and not commonly used.
177 ///
178 pub trait RealExt: Real {
179     // FIXME (#5527): usages of `int` should be replaced with an associated
180     // integer type once these are implemented
181
182     // Gamma functions
183     fn lgamma(&self) -> (int, Self);
184     fn tgamma(&self) -> Self;
185
186     // Bessel functions
187     fn j0(&self) -> Self;
188     fn j1(&self) -> Self;
189     fn jn(&self, n: int) -> Self;
190     fn y0(&self) -> Self;
191     fn y1(&self) -> Self;
192     fn yn(&self, n: int) -> Self;
193 }
194
195 ///
196 /// Collects the bitwise operators under one trait.
197 ///
198 pub trait Bitwise: Not<Self>
199                  + BitAnd<Self,Self>
200                  + BitOr<Self,Self>
201                  + BitXor<Self,Self>
202                  + Shl<Self,Self>
203                  + Shr<Self,Self> {}
204
205 pub trait BitCount {
206     fn population_count(&self) -> Self;
207     fn leading_zeros(&self) -> Self;
208     fn trailing_zeros(&self) -> Self;
209 }
210
211 pub trait Bounded {
212     // FIXME (#5527): These should be associated constants
213     fn min_value() -> Self;
214     fn max_value() -> Self;
215 }
216
217 ///
218 /// Specifies the available operations common to all of Rust's core numeric primitives.
219 /// These may not always make sense from a purely mathematical point of view, but
220 /// may be useful for systems programming.
221 ///
222 pub trait Primitive: Num
223                    + NumCast
224                    + Bounded
225                    + Neg<Self>
226                    + Add<Self,Self>
227                    + Sub<Self,Self>
228                    + Mul<Self,Self>
229                    + Quot<Self,Self>
230                    + Rem<Self,Self> {
231     // FIXME (#5527): These should be associated constants
232     fn bits() -> uint;
233     fn bytes() -> uint;
234 }
235
236 ///
237 /// A collection of traits relevant to primitive signed and unsigned integers
238 ///
239 pub trait Int: Integer
240              + Primitive
241              + Bitwise
242              + BitCount {}
243
244 ///
245 /// Primitive floating point numbers
246 ///
247 pub trait Float: Real
248                + Signed
249                + Primitive {
250     // FIXME (#5527): These should be associated constants
251     fn NaN() -> Self;
252     fn infinity() -> Self;
253     fn neg_infinity() -> Self;
254     fn neg_zero() -> Self;
255
256     fn is_NaN(&self) -> bool;
257     fn is_infinite(&self) -> bool;
258     fn is_finite(&self) -> bool;
259
260     fn mantissa_digits() -> uint;
261     fn digits() -> uint;
262     fn epsilon() -> Self;
263     fn min_exp() -> int;
264     fn max_exp() -> int;
265     fn min_10_exp() -> int;
266     fn max_10_exp() -> int;
267
268     fn mul_add(&self, a: Self, b: Self) -> Self;
269     fn next_after(&self, other: Self) -> Self;
270 }
271
272 ///
273 /// Cast from one machine scalar to another
274 ///
275 /// # Example
276 ///
277 /// ~~~
278 /// let twenty: f32 = num::cast(0x14);
279 /// assert_eq!(twenty, 20f32);
280 /// ~~~
281 ///
282 #[inline(always)]
283 pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
284     NumCast::from(n)
285 }
286
287 ///
288 /// An interface for casting between machine scalars
289 ///
290 pub trait NumCast {
291     fn from<T:NumCast>(n: T) -> Self;
292
293     fn to_u8(&self) -> u8;
294     fn to_u16(&self) -> u16;
295     fn to_u32(&self) -> u32;
296     fn to_u64(&self) -> u64;
297     fn to_uint(&self) -> uint;
298
299     fn to_i8(&self) -> i8;
300     fn to_i16(&self) -> i16;
301     fn to_i32(&self) -> i32;
302     fn to_i64(&self) -> i64;
303     fn to_int(&self) -> int;
304
305     fn to_f32(&self) -> f32;
306     fn to_f64(&self) -> f64;
307     fn to_float(&self) -> float;
308 }
309
310 macro_rules! impl_num_cast(
311     ($T:ty, $conv:ident) => (
312         impl NumCast for $T {
313             #[inline(always)]
314             fn from<N:NumCast>(n: N) -> $T {
315                 // `$conv` could be generated using `concat_idents!`, but that
316                 // macro seems to be broken at the moment
317                 n.$conv()
318             }
319
320             #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
321             #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
322             #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
323             #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
324             #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
325
326             #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
327             #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
328             #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
329             #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
330             #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
331
332             #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
333             #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
334             #[inline(always)] fn to_float(&self) -> float { *self as float }
335         }
336     )
337 )
338
339 impl_num_cast!(u8,    to_u8)
340 impl_num_cast!(u16,   to_u16)
341 impl_num_cast!(u32,   to_u32)
342 impl_num_cast!(u64,   to_u64)
343 impl_num_cast!(uint,  to_uint)
344 impl_num_cast!(i8,    to_i8)
345 impl_num_cast!(i16,   to_i16)
346 impl_num_cast!(i32,   to_i32)
347 impl_num_cast!(i64,   to_i64)
348 impl_num_cast!(int,   to_int)
349 impl_num_cast!(f32,   to_f32)
350 impl_num_cast!(f64,   to_f64)
351 impl_num_cast!(float, to_float)
352
353 pub trait ToStrRadix {
354     pub fn to_str_radix(&self, radix: uint) -> ~str;
355 }
356
357 pub trait FromStrRadix {
358     pub fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
359 }
360
361 ///
362 /// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
363 ///
364 /// Returns `radix^pow` as `T`.
365 ///
366 /// Note:
367 /// Also returns `1` for `0^0`, despite that technically being an
368 /// undefined number. The reason for this is twofold:
369 /// - If code written to use this function cares about that special case, it's
370 ///   probably going to catch it before making the call.
371 /// - If code written to use this function doesn't care about it, it's
372 ///   probably assuming that `x^0` always equals `1`.
373 ///
374 pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Quot<T,T>+Mul<T,T>>(
375     radix: uint, pow: uint) -> T {
376     let _0: T = Zero::zero();
377     let _1: T = One::one();
378
379     if pow   == 0u { return _1; }
380     if radix == 0u { return _0; }
381     let mut my_pow     = pow;
382     let mut total      = _1;
383     let mut multiplier = cast(radix as int);
384     while (my_pow > 0u) {
385         if my_pow % 2u == 1u {
386             total *= multiplier;
387         }
388         my_pow     /= 2u;
389         multiplier *= multiplier;
390     }
391     total
392 }
393
394 /// Helper function for testing numeric operations
395 #[cfg(stage0,test)]
396 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
397     assert_eq!(ten.add(&two),    cast(12));
398     assert_eq!(ten.sub(&two),    cast(8));
399     assert_eq!(ten.mul(&two),    cast(20));
400     assert_eq!(ten.div(&two),    cast(5));
401     assert_eq!(ten.modulo(&two), cast(0));
402
403     assert_eq!(ten.add(&two),    ten + two);
404     assert_eq!(ten.sub(&two),    ten - two);
405     assert_eq!(ten.mul(&two),    ten * two);
406     assert_eq!(ten.div(&two),    ten / two);
407     assert_eq!(ten.modulo(&two), ten % two);
408 }
409 #[cfg(stage1,test)]
410 #[cfg(stage2,test)]
411 #[cfg(stage3,test)]
412 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
413     assert_eq!(ten.add(&two),  cast(12));
414     assert_eq!(ten.sub(&two),  cast(8));
415     assert_eq!(ten.mul(&two),  cast(20));
416     assert_eq!(ten.quot(&two), cast(5));
417     assert_eq!(ten.rem(&two),  cast(0));
418
419     assert_eq!(ten.add(&two),  ten + two);
420     assert_eq!(ten.sub(&two),  ten - two);
421     assert_eq!(ten.mul(&two),  ten * two);
422     assert_eq!(ten.quot(&two), ten / two);
423     assert_eq!(ten.rem(&two),  ten % two);
424 }
425
426 macro_rules! test_cast_20(
427     ($_20:expr) => ({
428         let _20 = $_20;
429
430         assert_eq!(20u,   _20.to_uint());
431         assert_eq!(20u8,  _20.to_u8());
432         assert_eq!(20u16, _20.to_u16());
433         assert_eq!(20u32, _20.to_u32());
434         assert_eq!(20u64, _20.to_u64());
435         assert_eq!(20i,   _20.to_int());
436         assert_eq!(20i8,  _20.to_i8());
437         assert_eq!(20i16, _20.to_i16());
438         assert_eq!(20i32, _20.to_i32());
439         assert_eq!(20i64, _20.to_i64());
440         assert_eq!(20f,   _20.to_float());
441         assert_eq!(20f32, _20.to_f32());
442         assert_eq!(20f64, _20.to_f64());
443
444         assert_eq!(_20, NumCast::from(20u));
445         assert_eq!(_20, NumCast::from(20u8));
446         assert_eq!(_20, NumCast::from(20u16));
447         assert_eq!(_20, NumCast::from(20u32));
448         assert_eq!(_20, NumCast::from(20u64));
449         assert_eq!(_20, NumCast::from(20i));
450         assert_eq!(_20, NumCast::from(20i8));
451         assert_eq!(_20, NumCast::from(20i16));
452         assert_eq!(_20, NumCast::from(20i32));
453         assert_eq!(_20, NumCast::from(20i64));
454         assert_eq!(_20, NumCast::from(20f));
455         assert_eq!(_20, NumCast::from(20f32));
456         assert_eq!(_20, NumCast::from(20f64));
457
458         assert_eq!(_20, cast(20u));
459         assert_eq!(_20, cast(20u8));
460         assert_eq!(_20, cast(20u16));
461         assert_eq!(_20, cast(20u32));
462         assert_eq!(_20, cast(20u64));
463         assert_eq!(_20, cast(20i));
464         assert_eq!(_20, cast(20i8));
465         assert_eq!(_20, cast(20i16));
466         assert_eq!(_20, cast(20i32));
467         assert_eq!(_20, cast(20i64));
468         assert_eq!(_20, cast(20f));
469         assert_eq!(_20, cast(20f32));
470         assert_eq!(_20, cast(20f64));
471     })
472 )
473
474 #[test] fn test_u8_cast()    { test_cast_20!(20u8)  }
475 #[test] fn test_u16_cast()   { test_cast_20!(20u16) }
476 #[test] fn test_u32_cast()   { test_cast_20!(20u32) }
477 #[test] fn test_u64_cast()   { test_cast_20!(20u64) }
478 #[test] fn test_uint_cast()  { test_cast_20!(20u)   }
479 #[test] fn test_i8_cast()    { test_cast_20!(20i8)  }
480 #[test] fn test_i16_cast()   { test_cast_20!(20i16) }
481 #[test] fn test_i32_cast()   { test_cast_20!(20i32) }
482 #[test] fn test_i64_cast()   { test_cast_20!(20i64) }
483 #[test] fn test_int_cast()   { test_cast_20!(20i)   }
484 #[test] fn test_f32_cast()   { test_cast_20!(20f32) }
485 #[test] fn test_f64_cast()   { test_cast_20!(20f64) }
486 #[test] fn test_float_cast() { test_cast_20!(20f)   }