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