]> git.lizzy.rs Git - rust.git/blob - src/libcore/num/f64.rs
9f1944e3fad7fd3dc225ed66bb01bd9ee9f5ccc4
[rust.git] / src / libcore / num / f64.rs
1 // Copyright 2012 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 //! Operations and constants for `f64`
12
13 use from_str;
14 use libc::c_int;
15 use num::{Zero, One, strconv};
16 use prelude::*;
17
18 pub use cmath::c_double_targ_consts::*;
19 pub use cmp::{min, max};
20
21 // An inner module is required to get the #[inline(always)] attribute on the
22 // functions.
23 pub use self::delegated::*;
24
25 macro_rules! delegate(
26     (
27         $(
28             fn $name:ident(
29                 $(
30                     $arg:ident : $arg_ty:ty
31                 ),*
32             ) -> $rv:ty = $bound_name:path
33         ),*
34     ) => (
35         mod delegated {
36             use cmath::c_double_utils;
37             use libc::{c_double, c_int};
38             use unstable::intrinsics;
39
40             $(
41                 #[inline(always)]
42                 pub fn $name($( $arg : $arg_ty ),*) -> $rv {
43                     unsafe {
44                         $bound_name($( $arg ),*)
45                     }
46                 }
47             )*
48         }
49     )
50 )
51
52 delegate!(
53     // intrinsics
54     fn abs(n: f64) -> f64 = intrinsics::fabsf64,
55     fn cos(n: f64) -> f64 = intrinsics::cosf64,
56     fn exp(n: f64) -> f64 = intrinsics::expf64,
57     fn exp2(n: f64) -> f64 = intrinsics::exp2f64,
58     fn floor(x: f64) -> f64 = intrinsics::floorf64,
59     fn ln(n: f64) -> f64 = intrinsics::logf64,
60     fn log10(n: f64) -> f64 = intrinsics::log10f64,
61     fn log2(n: f64) -> f64 = intrinsics::log2f64,
62     fn mul_add(a: f64, b: f64, c: f64) -> f64 = intrinsics::fmaf64,
63     fn pow(n: f64, e: f64) -> f64 = intrinsics::powf64,
64     fn powi(n: f64, e: c_int) -> f64 = intrinsics::powif64,
65     fn sin(n: f64) -> f64 = intrinsics::sinf64,
66     fn sqrt(n: f64) -> f64 = intrinsics::sqrtf64,
67
68     // LLVM 3.3 required to use intrinsics for these four
69     fn ceil(n: c_double) -> c_double = c_double_utils::ceil,
70     fn trunc(n: c_double) -> c_double = c_double_utils::trunc,
71     /*
72     fn ceil(n: f64) -> f64 = intrinsics::ceilf64,
73     fn trunc(n: f64) -> f64 = intrinsics::truncf64,
74     fn rint(n: c_double) -> c_double = intrinsics::rintf64,
75     fn nearbyint(n: c_double) -> c_double = intrinsics::nearbyintf64,
76     */
77
78     // cmath
79     fn acos(n: c_double) -> c_double = c_double_utils::acos,
80     fn asin(n: c_double) -> c_double = c_double_utils::asin,
81     fn atan(n: c_double) -> c_double = c_double_utils::atan,
82     fn atan2(a: c_double, b: c_double) -> c_double = c_double_utils::atan2,
83     fn cbrt(n: c_double) -> c_double = c_double_utils::cbrt,
84     fn copysign(x: c_double, y: c_double) -> c_double = c_double_utils::copysign,
85     fn cosh(n: c_double) -> c_double = c_double_utils::cosh,
86     fn erf(n: c_double) -> c_double = c_double_utils::erf,
87     fn erfc(n: c_double) -> c_double = c_double_utils::erfc,
88     fn expm1(n: c_double) -> c_double = c_double_utils::expm1,
89     fn abs_sub(a: c_double, b: c_double) -> c_double = c_double_utils::abs_sub,
90     fn fmax(a: c_double, b: c_double) -> c_double = c_double_utils::fmax,
91     fn fmin(a: c_double, b: c_double) -> c_double = c_double_utils::fmin,
92     fn next_after(x: c_double, y: c_double) -> c_double = c_double_utils::next_after,
93     fn frexp(n: c_double, value: &mut c_int) -> c_double = c_double_utils::frexp,
94     fn hypot(x: c_double, y: c_double) -> c_double = c_double_utils::hypot,
95     fn ldexp(x: c_double, n: c_int) -> c_double = c_double_utils::ldexp,
96     fn lgamma(n: c_double, sign: &mut c_int) -> c_double = c_double_utils::lgamma,
97     fn log_radix(n: c_double) -> c_double = c_double_utils::log_radix,
98     fn ln1p(n: c_double) -> c_double = c_double_utils::ln1p,
99     fn ilog_radix(n: c_double) -> c_int = c_double_utils::ilog_radix,
100     fn modf(n: c_double, iptr: &mut c_double) -> c_double = c_double_utils::modf,
101     fn round(n: c_double) -> c_double = c_double_utils::round,
102     fn ldexp_radix(n: c_double, i: c_int) -> c_double = c_double_utils::ldexp_radix,
103     fn sinh(n: c_double) -> c_double = c_double_utils::sinh,
104     fn tan(n: c_double) -> c_double = c_double_utils::tan,
105     fn tanh(n: c_double) -> c_double = c_double_utils::tanh,
106     fn tgamma(n: c_double) -> c_double = c_double_utils::tgamma,
107     fn j0(n: c_double) -> c_double = c_double_utils::j0,
108     fn j1(n: c_double) -> c_double = c_double_utils::j1,
109     fn jn(i: c_int, n: c_double) -> c_double = c_double_utils::jn,
110     fn y0(n: c_double) -> c_double = c_double_utils::y0,
111     fn y1(n: c_double) -> c_double = c_double_utils::y1,
112     fn yn(i: c_int, n: c_double) -> c_double = c_double_utils::yn
113 )
114
115 // FIXME (#1433): obtain these in a different way
116
117 // These are not defined inside consts:: for consistency with
118 // the integer types
119
120 pub static radix: uint = 2u;
121
122 pub static mantissa_digits: uint = 53u;
123 pub static digits: uint = 15u;
124
125 pub static epsilon: f64 = 2.2204460492503131e-16_f64;
126
127 pub static min_value: f64 = 2.2250738585072014e-308_f64;
128 pub static max_value: f64 = 1.7976931348623157e+308_f64;
129
130 pub static min_exp: int = -1021;
131 pub static max_exp: int = 1024;
132
133 pub static min_10_exp: int = -307;
134 pub static max_10_exp: int = 308;
135
136 pub static NaN: f64 = 0.0_f64/0.0_f64;
137
138 pub static infinity: f64 = 1.0_f64/0.0_f64;
139
140 pub static neg_infinity: f64 = -1.0_f64/0.0_f64;
141
142 #[inline(always)]
143 pub fn add(x: f64, y: f64) -> f64 { return x + y; }
144
145 #[inline(always)]
146 pub fn sub(x: f64, y: f64) -> f64 { return x - y; }
147
148 #[inline(always)]
149 pub fn mul(x: f64, y: f64) -> f64 { return x * y; }
150
151 #[inline(always)]
152 pub fn div(x: f64, y: f64) -> f64 { return x / y; }
153
154 #[inline(always)]
155 pub fn rem(x: f64, y: f64) -> f64 { return x % y; }
156
157 #[inline(always)]
158 pub fn lt(x: f64, y: f64) -> bool { return x < y; }
159
160 #[inline(always)]
161 pub fn le(x: f64, y: f64) -> bool { return x <= y; }
162
163 #[inline(always)]
164 pub fn eq(x: f64, y: f64) -> bool { return x == y; }
165
166 #[inline(always)]
167 pub fn ne(x: f64, y: f64) -> bool { return x != y; }
168
169 #[inline(always)]
170 pub fn ge(x: f64, y: f64) -> bool { return x >= y; }
171
172 #[inline(always)]
173 pub fn gt(x: f64, y: f64) -> bool { return x > y; }
174
175
176 // FIXME (#1999): add is_normal, is_subnormal, and fpclassify
177
178 /* Module: consts */
179 pub mod consts {
180     // FIXME (requires Issue #1433 to fix): replace with mathematical
181     // constants from cmath.
182     /// Archimedes' constant
183     pub static pi: f64 = 3.14159265358979323846264338327950288_f64;
184
185     /// pi/2.0
186     pub static frac_pi_2: f64 = 1.57079632679489661923132169163975144_f64;
187
188     /// pi/4.0
189     pub static frac_pi_4: f64 = 0.785398163397448309615660845819875721_f64;
190
191     /// 1.0/pi
192     pub static frac_1_pi: f64 = 0.318309886183790671537767526745028724_f64;
193
194     /// 2.0/pi
195     pub static frac_2_pi: f64 = 0.636619772367581343075535053490057448_f64;
196
197     /// 2.0/sqrt(pi)
198     pub static frac_2_sqrtpi: f64 = 1.12837916709551257389615890312154517_f64;
199
200     /// sqrt(2.0)
201     pub static sqrt2: f64 = 1.41421356237309504880168872420969808_f64;
202
203     /// 1.0/sqrt(2.0)
204     pub static frac_1_sqrt2: f64 = 0.707106781186547524400844362104849039_f64;
205
206     /// Euler's number
207     pub static e: f64 = 2.71828182845904523536028747135266250_f64;
208
209     /// log2(e)
210     pub static log2_e: f64 = 1.44269504088896340735992468100189214_f64;
211
212     /// log10(e)
213     pub static log10_e: f64 = 0.434294481903251827651128918916605082_f64;
214
215     /// ln(2.0)
216     pub static ln_2: f64 = 0.693147180559945309417232121458176568_f64;
217
218     /// ln(10.0)
219     pub static ln_10: f64 = 2.30258509299404568401799145468436421_f64;
220 }
221
222 #[inline(always)]
223 pub fn logarithm(n: f64, b: f64) -> f64 {
224     return log2(n) / log2(b);
225 }
226
227 impl Num for f64 {}
228
229 #[cfg(notest)]
230 impl Eq for f64 {
231     #[inline(always)]
232     fn eq(&self, other: &f64) -> bool { (*self) == (*other) }
233     #[inline(always)]
234     fn ne(&self, other: &f64) -> bool { (*self) != (*other) }
235 }
236
237 #[cfg(notest)]
238 impl Ord for f64 {
239     #[inline(always)]
240     fn lt(&self, other: &f64) -> bool { (*self) < (*other) }
241     #[inline(always)]
242     fn le(&self, other: &f64) -> bool { (*self) <= (*other) }
243     #[inline(always)]
244     fn ge(&self, other: &f64) -> bool { (*self) >= (*other) }
245     #[inline(always)]
246     fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
247 }
248
249 impl Orderable for f64 {
250     /// Returns `NaN` if either of the numbers are `NaN`.
251     #[inline(always)]
252     fn min(&self, other: &f64) -> f64 {
253         if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) }
254     }
255
256     /// Returns `NaN` if either of the numbers are `NaN`.
257     #[inline(always)]
258     fn max(&self, other: &f64) -> f64 {
259         if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) }
260     }
261
262     /// Returns the number constrained within the range `mn <= self <= mx`.
263     /// If any of the numbers are `NaN` then `NaN` is returned.
264     #[inline(always)]
265     fn clamp(&self, mn: &f64, mx: &f64) -> f64 {
266         if self.is_NaN() { *self }
267         else if !(*self <= *mx) { *mx }
268         else if !(*self >= *mn) { *mn }
269         else { *self }
270     }
271 }
272
273 impl Zero for f64 {
274     #[inline(always)]
275     fn zero() -> f64 { 0.0 }
276
277     /// Returns true if the number is equal to either `0.0` or `-0.0`
278     #[inline(always)]
279     fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
280 }
281
282 impl One for f64 {
283     #[inline(always)]
284     fn one() -> f64 { 1.0 }
285 }
286
287 #[cfg(notest)]
288 impl Add<f64,f64> for f64 {
289     fn add(&self, other: &f64) -> f64 { *self + *other }
290 }
291 #[cfg(notest)]
292 impl Sub<f64,f64> for f64 {
293     fn sub(&self, other: &f64) -> f64 { *self - *other }
294 }
295 #[cfg(notest)]
296 impl Mul<f64,f64> for f64 {
297     fn mul(&self, other: &f64) -> f64 { *self * *other }
298 }
299 #[cfg(notest)]
300 impl Div<f64,f64> for f64 {
301     fn div(&self, other: &f64) -> f64 { *self / *other }
302 }
303 #[cfg(stage0,notest)]
304 impl Modulo<f64,f64> for f64 {
305     fn modulo(&self, other: &f64) -> f64 { *self % *other }
306 }
307 #[cfg(not(stage0),notest)]
308 impl Rem<f64,f64> for f64 {
309     #[inline(always)]
310     fn rem(&self, other: &f64) -> f64 { *self % *other }
311 }
312 #[cfg(notest)]
313 impl Neg<f64> for f64 {
314     fn neg(&self) -> f64 { -*self }
315 }
316
317 impl Signed for f64 {
318     /// Computes the absolute value. Returns `NaN` if the number is `NaN`.
319     #[inline(always)]
320     fn abs(&self) -> f64 { abs(*self) }
321
322     ///
323     /// # Returns
324     ///
325     /// - `1.0` if the number is positive, `+0.0` or `infinity`
326     /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
327     /// - `NaN` if the number is NaN
328     ///
329     #[inline(always)]
330     fn signum(&self) -> f64 {
331         if self.is_NaN() { NaN } else { copysign(1.0, *self) }
332     }
333
334     /// Returns `true` if the number is positive, including `+0.0` and `infinity`
335     #[inline(always)]
336     fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
337
338     /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
339     #[inline(always)]
340     fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
341 }
342
343 impl Round for f64 {
344     /// Round half-way cases toward `neg_infinity`
345     #[inline(always)]
346     fn floor(&self) -> f64 { floor(*self) }
347
348     /// Round half-way cases toward `infinity`
349     #[inline(always)]
350     fn ceil(&self) -> f64 { ceil(*self) }
351
352     /// Round half-way cases away from `0.0`
353     #[inline(always)]
354     fn round(&self) -> f64 { round(*self) }
355
356     /// The integer part of the number (rounds towards `0.0`)
357     #[inline(always)]
358     fn trunc(&self) -> f64 { trunc(*self) }
359
360     ///
361     /// The fractional part of the number, satisfying:
362     ///
363     /// ~~~
364     /// assert!(x == trunc(x) + fract(x))
365     /// ~~~
366     ///
367     #[inline(always)]
368     fn fract(&self) -> f64 { *self - self.trunc() }
369 }
370
371 impl Fractional for f64 {
372     /// The reciprocal (multiplicative inverse) of the number
373     #[inline(always)]
374     fn recip(&self) -> f64 { 1.0 / *self }
375 }
376
377 impl Algebraic for f64 {
378     #[inline(always)]
379     fn pow(&self, n: f64) -> f64 { pow(*self, n) }
380
381     #[inline(always)]
382     fn sqrt(&self) -> f64 { sqrt(*self) }
383
384     #[inline(always)]
385     fn rsqrt(&self) -> f64 { self.sqrt().recip() }
386
387     #[inline(always)]
388     fn cbrt(&self) -> f64 { cbrt(*self) }
389
390     #[inline(always)]
391     fn hypot(&self, other: f64) -> f64 { hypot(*self, other) }
392 }
393
394 impl Trigonometric for f64 {
395     #[inline(always)]
396     fn sin(&self) -> f64 { sin(*self) }
397
398     #[inline(always)]
399     fn cos(&self) -> f64 { cos(*self) }
400
401     #[inline(always)]
402     fn tan(&self) -> f64 { tan(*self) }
403
404     #[inline(always)]
405     fn asin(&self) -> f64 { asin(*self) }
406
407     #[inline(always)]
408     fn acos(&self) -> f64 { acos(*self) }
409
410     #[inline(always)]
411     fn atan(&self) -> f64 { atan(*self) }
412
413     #[inline(always)]
414     fn atan2(&self, other: f64) -> f64 { atan2(*self, other) }
415 }
416
417 impl Exponential for f64 {
418     #[inline(always)]
419     fn exp(&self) -> f64 { exp(*self) }
420
421     #[inline(always)]
422     fn exp2(&self) -> f64 { exp2(*self) }
423
424     #[inline(always)]
425     fn expm1(&self) -> f64 { expm1(*self) }
426
427     #[inline(always)]
428     fn log(&self) -> f64 { ln(*self) }
429
430     #[inline(always)]
431     fn log2(&self) -> f64 { log2(*self) }
432
433     #[inline(always)]
434     fn log10(&self) -> f64 { log10(*self) }
435 }
436
437 impl Hyperbolic for f64 {
438     #[inline(always)]
439     fn sinh(&self) -> f64 { sinh(*self) }
440
441     #[inline(always)]
442     fn cosh(&self) -> f64 { cosh(*self) }
443
444     #[inline(always)]
445     fn tanh(&self) -> f64 { tanh(*self) }
446 }
447
448 impl Real for f64 {
449     /// Archimedes' constant
450     #[inline(always)]
451     fn pi() -> f64 { 3.14159265358979323846264338327950288 }
452
453     /// 2.0 * pi
454     #[inline(always)]
455     fn two_pi() -> f64 { 6.28318530717958647692528676655900576 }
456
457     /// pi / 2.0
458     #[inline(always)]
459     fn frac_pi_2() -> f64 { 1.57079632679489661923132169163975144 }
460
461     /// pi / 3.0
462     #[inline(always)]
463     fn frac_pi_3() -> f64 { 1.04719755119659774615421446109316763 }
464
465     /// pi / 4.0
466     #[inline(always)]
467     fn frac_pi_4() -> f64 { 0.785398163397448309615660845819875721 }
468
469     /// pi / 6.0
470     #[inline(always)]
471     fn frac_pi_6() -> f64 { 0.52359877559829887307710723054658381 }
472
473     /// pi / 8.0
474     #[inline(always)]
475     fn frac_pi_8() -> f64 { 0.39269908169872415480783042290993786 }
476
477     /// 1.0 / pi
478     #[inline(always)]
479     fn frac_1_pi() -> f64 { 0.318309886183790671537767526745028724 }
480
481     /// 2.0 / pi
482     #[inline(always)]
483     fn frac_2_pi() -> f64 { 0.636619772367581343075535053490057448 }
484
485     /// 2.0 / sqrt(pi)
486     #[inline(always)]
487     fn frac_2_sqrtpi() -> f64 { 1.12837916709551257389615890312154517 }
488
489     /// sqrt(2.0)
490     #[inline(always)]
491     fn sqrt2() -> f64 { 1.41421356237309504880168872420969808 }
492
493     /// 1.0 / sqrt(2.0)
494     #[inline(always)]
495     fn frac_1_sqrt2() -> f64 { 0.707106781186547524400844362104849039 }
496
497     /// Euler's number
498     #[inline(always)]
499     fn e() -> f64 { 2.71828182845904523536028747135266250 }
500
501     /// log2(e)
502     #[inline(always)]
503     fn log2_e() -> f64 { 1.44269504088896340735992468100189214 }
504
505     /// log10(e)
506     #[inline(always)]
507     fn log10_e() -> f64 { 0.434294481903251827651128918916605082 }
508
509     /// log(2.0)
510     #[inline(always)]
511     fn log_2() -> f64 { 0.693147180559945309417232121458176568 }
512
513     /// log(10.0)
514     #[inline(always)]
515     fn log_10() -> f64 { 2.30258509299404568401799145468436421 }
516
517     /// Converts to degrees, assuming the number is in radians
518     #[inline(always)]
519     fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::<f64>()) }
520
521     /// Converts to radians, assuming the number is in degrees
522     #[inline(always)]
523     fn to_radians(&self) -> f64 { *self * (Real::pi::<f64>() / 180.0) }
524 }
525
526 impl RealExt for f64 {
527     #[inline(always)]
528     fn lgamma(&self) -> (int, f64) {
529         let mut sign = 0;
530         let result = lgamma(*self, &mut sign);
531         (sign as int, result)
532     }
533
534     #[inline(always)]
535     fn tgamma(&self) -> f64 { tgamma(*self) }
536
537     #[inline(always)]
538     fn j0(&self) -> f64 { j0(*self) }
539
540     #[inline(always)]
541     fn j1(&self) -> f64 { j1(*self) }
542
543     #[inline(always)]
544     fn jn(&self, n: int) -> f64 { jn(n as c_int, *self) }
545
546     #[inline(always)]
547     fn y0(&self) -> f64 { y0(*self) }
548
549     #[inline(always)]
550     fn y1(&self) -> f64 { y1(*self) }
551
552     #[inline(always)]
553     fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) }
554 }
555
556 impl Bounded for f64 {
557     #[inline(always)]
558     fn min_value() -> f64 { 2.2250738585072014e-308 }
559
560     #[inline(always)]
561     fn max_value() -> f64 { 1.7976931348623157e+308 }
562 }
563
564 impl Primitive for f64 {
565     #[inline(always)]
566     fn bits() -> uint { 64 }
567
568     #[inline(always)]
569     fn bytes() -> uint { Primitive::bits::<f64>() / 8 }
570 }
571
572 impl Float for f64 {
573     #[inline(always)]
574     fn NaN() -> f64 { 0.0 / 0.0 }
575
576     #[inline(always)]
577     fn infinity() -> f64 { 1.0 / 0.0 }
578
579     #[inline(always)]
580     fn neg_infinity() -> f64 { -1.0 / 0.0 }
581
582     #[inline(always)]
583     fn neg_zero() -> f64 { -0.0 }
584
585     #[inline(always)]
586     fn is_NaN(&self) -> bool { *self != *self }
587
588     /// Returns `true` if the number is infinite
589     #[inline(always)]
590     fn is_infinite(&self) -> bool {
591         *self == Float::infinity() || *self == Float::neg_infinity()
592     }
593
594     /// Returns `true` if the number is finite
595     #[inline(always)]
596     fn is_finite(&self) -> bool {
597         !(self.is_NaN() || self.is_infinite())
598     }
599
600     #[inline(always)]
601     fn mantissa_digits() -> uint { 53 }
602
603     #[inline(always)]
604     fn digits() -> uint { 15 }
605
606     #[inline(always)]
607     fn epsilon() -> f64 { 2.2204460492503131e-16 }
608
609     #[inline(always)]
610     fn min_exp() -> int { -1021 }
611
612     #[inline(always)]
613     fn max_exp() -> int { 1024 }
614
615     #[inline(always)]
616     fn min_10_exp() -> int { -307 }
617
618     #[inline(always)]
619     fn max_10_exp() -> int { 308 }
620
621     ///
622     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
623     /// produces a more accurate result with better performance than a separate multiplication
624     /// operation followed by an add.
625     ///
626     #[inline(always)]
627     fn mul_add(&self, a: f64, b: f64) -> f64 {
628         mul_add(*self, a, b)
629     }
630
631     /// Returns the next representable floating-point value in the direction of `other`
632     #[inline(always)]
633     fn next_after(&self, other: f64) -> f64 {
634         next_after(*self, other)
635     }
636 }
637
638 //
639 // Section: String Conversions
640 //
641
642 ///
643 /// Converts a float to a string
644 ///
645 /// # Arguments
646 ///
647 /// * num - The float value
648 ///
649 #[inline(always)]
650 pub fn to_str(num: f64) -> ~str {
651     let (r, _) = strconv::to_str_common(
652         &num, 10u, true, strconv::SignNeg, strconv::DigAll);
653     r
654 }
655
656 ///
657 /// Converts a float to a string in hexadecimal format
658 ///
659 /// # Arguments
660 ///
661 /// * num - The float value
662 ///
663 #[inline(always)]
664 pub fn to_str_hex(num: f64) -> ~str {
665     let (r, _) = strconv::to_str_common(
666         &num, 16u, true, strconv::SignNeg, strconv::DigAll);
667     r
668 }
669
670 ///
671 /// Converts a float to a string in a given radix
672 ///
673 /// # Arguments
674 ///
675 /// * num - The float value
676 /// * radix - The base to use
677 ///
678 /// # Failure
679 ///
680 /// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
681 /// possible misinterpretation of the result at higher bases. If those values
682 /// are expected, use `to_str_radix_special()` instead.
683 ///
684 #[inline(always)]
685 pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
686     let (r, special) = strconv::to_str_common(
687         &num, rdx, true, strconv::SignNeg, strconv::DigAll);
688     if special { fail!(~"number has a special value, \
689                       try to_str_radix_special() if those are expected") }
690     r
691 }
692
693 ///
694 /// Converts a float to a string in a given radix, and a flag indicating
695 /// whether it's a special value
696 ///
697 /// # Arguments
698 ///
699 /// * num - The float value
700 /// * radix - The base to use
701 ///
702 #[inline(always)]
703 pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
704     strconv::to_str_common(&num, rdx, true,
705                            strconv::SignNeg, strconv::DigAll)
706 }
707
708 ///
709 /// Converts a float to a string with exactly the number of
710 /// provided significant digits
711 ///
712 /// # Arguments
713 ///
714 /// * num - The float value
715 /// * digits - The number of significant digits
716 ///
717 #[inline(always)]
718 pub fn to_str_exact(num: f64, dig: uint) -> ~str {
719     let (r, _) = strconv::to_str_common(
720         &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
721     r
722 }
723
724 ///
725 /// Converts a float to a string with a maximum number of
726 /// significant digits
727 ///
728 /// # Arguments
729 ///
730 /// * num - The float value
731 /// * digits - The number of significant digits
732 ///
733 #[inline(always)]
734 pub fn to_str_digits(num: f64, dig: uint) -> ~str {
735     let (r, _) = strconv::to_str_common(
736         &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
737     r
738 }
739
740 impl to_str::ToStr for f64 {
741     #[inline(always)]
742     fn to_str(&self) -> ~str { to_str_digits(*self, 8) }
743 }
744
745 impl num::ToStrRadix for f64 {
746     #[inline(always)]
747     fn to_str_radix(&self, rdx: uint) -> ~str {
748         to_str_radix(*self, rdx)
749     }
750 }
751
752 ///
753 /// Convert a string in base 10 to a float.
754 /// Accepts a optional decimal exponent.
755 ///
756 /// This function accepts strings such as
757 ///
758 /// * '3.14'
759 /// * '+3.14', equivalent to '3.14'
760 /// * '-3.14'
761 /// * '2.5E10', or equivalently, '2.5e10'
762 /// * '2.5E-10'
763 /// * '.' (understood as 0)
764 /// * '5.'
765 /// * '.5', or, equivalently,  '0.5'
766 /// * '+inf', 'inf', '-inf', 'NaN'
767 ///
768 /// Leading and trailing whitespace represent an error.
769 ///
770 /// # Arguments
771 ///
772 /// * num - A string
773 ///
774 /// # Return value
775 ///
776 /// `none` if the string did not represent a valid number.  Otherwise,
777 /// `Some(n)` where `n` is the floating-point number represented by `num`.
778 ///
779 #[inline(always)]
780 pub fn from_str(num: &str) -> Option<f64> {
781     strconv::from_str_common(num, 10u, true, true, true,
782                              strconv::ExpDec, false, false)
783 }
784
785 ///
786 /// Convert a string in base 16 to a float.
787 /// Accepts a optional binary exponent.
788 ///
789 /// This function accepts strings such as
790 ///
791 /// * 'a4.fe'
792 /// * '+a4.fe', equivalent to 'a4.fe'
793 /// * '-a4.fe'
794 /// * '2b.aP128', or equivalently, '2b.ap128'
795 /// * '2b.aP-128'
796 /// * '.' (understood as 0)
797 /// * 'c.'
798 /// * '.c', or, equivalently,  '0.c'
799 /// * '+inf', 'inf', '-inf', 'NaN'
800 ///
801 /// Leading and trailing whitespace represent an error.
802 ///
803 /// # Arguments
804 ///
805 /// * num - A string
806 ///
807 /// # Return value
808 ///
809 /// `none` if the string did not represent a valid number.  Otherwise,
810 /// `Some(n)` where `n` is the floating-point number represented by `[num]`.
811 ///
812 #[inline(always)]
813 pub fn from_str_hex(num: &str) -> Option<f64> {
814     strconv::from_str_common(num, 16u, true, true, true,
815                              strconv::ExpBin, false, false)
816 }
817
818 ///
819 /// Convert a string in an given base to a float.
820 ///
821 /// Due to possible conflicts, this function does **not** accept
822 /// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
823 /// does it recognize exponents of any kind.
824 ///
825 /// Leading and trailing whitespace represent an error.
826 ///
827 /// # Arguments
828 ///
829 /// * num - A string
830 /// * radix - The base to use. Must lie in the range [2 .. 36]
831 ///
832 /// # Return value
833 ///
834 /// `none` if the string did not represent a valid number. Otherwise,
835 /// `Some(n)` where `n` is the floating-point number represented by `num`.
836 ///
837 #[inline(always)]
838 pub fn from_str_radix(num: &str, rdx: uint) -> Option<f64> {
839     strconv::from_str_common(num, rdx, true, true, false,
840                              strconv::ExpNone, false, false)
841 }
842
843 impl from_str::FromStr for f64 {
844     #[inline(always)]
845     fn from_str(val: &str) -> Option<f64> { from_str(val) }
846 }
847
848 impl num::FromStrRadix for f64 {
849     #[inline(always)]
850     fn from_str_radix(val: &str, rdx: uint) -> Option<f64> {
851         from_str_radix(val, rdx)
852     }
853 }
854
855 #[cfg(test)]
856 mod tests {
857     use f64::*;
858     use super::*;
859     use prelude::*;
860
861     macro_rules! assert_fuzzy_eq(
862         ($a:expr, $b:expr) => ({
863             let a = $a, b = $b;
864             if !((a - b).abs() < 1.0e-6) {
865                 fail!(fmt!("The values were not approximately equal. \
866                             Found: %? and expected %?", a, b));
867             }
868         })
869     )
870
871     #[test]
872     fn test_num() {
873         num::test_num(10f64, 2f64);
874     }
875
876     #[test]
877     fn test_min() {
878         assert_eq!(1f64.min(&2f64), 1f64);
879         assert_eq!(2f64.min(&1f64), 1f64);
880         assert!(1f64.min(&Float::NaN::<f64>()).is_NaN());
881         assert!(Float::NaN::<f64>().min(&1f64).is_NaN());
882     }
883
884     #[test]
885     fn test_max() {
886         assert_eq!(1f64.max(&2f64), 2f64);
887         assert_eq!(2f64.max(&1f64), 2f64);
888         assert!(1f64.max(&Float::NaN::<f64>()).is_NaN());
889         assert!(Float::NaN::<f64>().max(&1f64).is_NaN());
890     }
891
892     #[test]
893     fn test_clamp() {
894         assert_eq!(1f64.clamp(&2f64, &4f64), 2f64);
895         assert_eq!(8f64.clamp(&2f64, &4f64), 4f64);
896         assert_eq!(3f64.clamp(&2f64, &4f64), 3f64);
897         assert!(3f64.clamp(&Float::NaN::<f64>(), &4f64).is_NaN());
898         assert!(3f64.clamp(&2f64, &Float::NaN::<f64>()).is_NaN());
899         assert!(Float::NaN::<f64>().clamp(&2f64, &4f64).is_NaN());
900     }
901
902     #[test]
903     fn test_floor() {
904         assert_fuzzy_eq!(1.0f64.floor(), 1.0f64);
905         assert_fuzzy_eq!(1.3f64.floor(), 1.0f64);
906         assert_fuzzy_eq!(1.5f64.floor(), 1.0f64);
907         assert_fuzzy_eq!(1.7f64.floor(), 1.0f64);
908         assert_fuzzy_eq!(0.0f64.floor(), 0.0f64);
909         assert_fuzzy_eq!((-0.0f64).floor(), -0.0f64);
910         assert_fuzzy_eq!((-1.0f64).floor(), -1.0f64);
911         assert_fuzzy_eq!((-1.3f64).floor(), -2.0f64);
912         assert_fuzzy_eq!((-1.5f64).floor(), -2.0f64);
913         assert_fuzzy_eq!((-1.7f64).floor(), -2.0f64);
914     }
915
916     #[test]
917     fn test_ceil() {
918         assert_fuzzy_eq!(1.0f64.ceil(), 1.0f64);
919         assert_fuzzy_eq!(1.3f64.ceil(), 2.0f64);
920         assert_fuzzy_eq!(1.5f64.ceil(), 2.0f64);
921         assert_fuzzy_eq!(1.7f64.ceil(), 2.0f64);
922         assert_fuzzy_eq!(0.0f64.ceil(), 0.0f64);
923         assert_fuzzy_eq!((-0.0f64).ceil(), -0.0f64);
924         assert_fuzzy_eq!((-1.0f64).ceil(), -1.0f64);
925         assert_fuzzy_eq!((-1.3f64).ceil(), -1.0f64);
926         assert_fuzzy_eq!((-1.5f64).ceil(), -1.0f64);
927         assert_fuzzy_eq!((-1.7f64).ceil(), -1.0f64);
928     }
929
930     #[test]
931     fn test_round() {
932         assert_fuzzy_eq!(1.0f64.round(), 1.0f64);
933         assert_fuzzy_eq!(1.3f64.round(), 1.0f64);
934         assert_fuzzy_eq!(1.5f64.round(), 2.0f64);
935         assert_fuzzy_eq!(1.7f64.round(), 2.0f64);
936         assert_fuzzy_eq!(0.0f64.round(), 0.0f64);
937         assert_fuzzy_eq!((-0.0f64).round(), -0.0f64);
938         assert_fuzzy_eq!((-1.0f64).round(), -1.0f64);
939         assert_fuzzy_eq!((-1.3f64).round(), -1.0f64);
940         assert_fuzzy_eq!((-1.5f64).round(), -2.0f64);
941         assert_fuzzy_eq!((-1.7f64).round(), -2.0f64);
942     }
943
944     #[test]
945     fn test_trunc() {
946         assert_fuzzy_eq!(1.0f64.trunc(), 1.0f64);
947         assert_fuzzy_eq!(1.3f64.trunc(), 1.0f64);
948         assert_fuzzy_eq!(1.5f64.trunc(), 1.0f64);
949         assert_fuzzy_eq!(1.7f64.trunc(), 1.0f64);
950         assert_fuzzy_eq!(0.0f64.trunc(), 0.0f64);
951         assert_fuzzy_eq!((-0.0f64).trunc(), -0.0f64);
952         assert_fuzzy_eq!((-1.0f64).trunc(), -1.0f64);
953         assert_fuzzy_eq!((-1.3f64).trunc(), -1.0f64);
954         assert_fuzzy_eq!((-1.5f64).trunc(), -1.0f64);
955         assert_fuzzy_eq!((-1.7f64).trunc(), -1.0f64);
956     }
957
958     #[test]
959     fn test_fract() {
960         assert_fuzzy_eq!(1.0f64.fract(), 0.0f64);
961         assert_fuzzy_eq!(1.3f64.fract(), 0.3f64);
962         assert_fuzzy_eq!(1.5f64.fract(), 0.5f64);
963         assert_fuzzy_eq!(1.7f64.fract(), 0.7f64);
964         assert_fuzzy_eq!(0.0f64.fract(), 0.0f64);
965         assert_fuzzy_eq!((-0.0f64).fract(), -0.0f64);
966         assert_fuzzy_eq!((-1.0f64).fract(), -0.0f64);
967         assert_fuzzy_eq!((-1.3f64).fract(), -0.3f64);
968         assert_fuzzy_eq!((-1.5f64).fract(), -0.5f64);
969         assert_fuzzy_eq!((-1.7f64).fract(), -0.7f64);
970     }
971
972     #[test]
973     fn test_real_consts() {
974         assert_fuzzy_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>());
975         assert_fuzzy_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64);
976         assert_fuzzy_eq!(Real::frac_pi_3::<f64>(), Real::pi::<f64>() / 3f64);
977         assert_fuzzy_eq!(Real::frac_pi_4::<f64>(), Real::pi::<f64>() / 4f64);
978         assert_fuzzy_eq!(Real::frac_pi_6::<f64>(), Real::pi::<f64>() / 6f64);
979         assert_fuzzy_eq!(Real::frac_pi_8::<f64>(), Real::pi::<f64>() / 8f64);
980         assert_fuzzy_eq!(Real::frac_1_pi::<f64>(), 1f64 / Real::pi::<f64>());
981         assert_fuzzy_eq!(Real::frac_2_pi::<f64>(), 2f64 / Real::pi::<f64>());
982         assert_fuzzy_eq!(Real::frac_2_sqrtpi::<f64>(), 2f64 / Real::pi::<f64>().sqrt());
983         assert_fuzzy_eq!(Real::sqrt2::<f64>(), 2f64.sqrt());
984         assert_fuzzy_eq!(Real::frac_1_sqrt2::<f64>(), 1f64 / 2f64.sqrt());
985         assert_fuzzy_eq!(Real::log2_e::<f64>(), Real::e::<f64>().log2());
986         assert_fuzzy_eq!(Real::log10_e::<f64>(), Real::e::<f64>().log10());
987         assert_fuzzy_eq!(Real::log_2::<f64>(), 2f64.log());
988         assert_fuzzy_eq!(Real::log_10::<f64>(), 10f64.log());
989     }
990
991     #[test]
992     pub fn test_signed() {
993         assert_eq!(infinity.abs(), infinity);
994         assert_eq!(1f64.abs(), 1f64);
995         assert_eq!(0f64.abs(), 0f64);
996         assert_eq!((-0f64).abs(), 0f64);
997         assert_eq!((-1f64).abs(), 1f64);
998         assert_eq!(neg_infinity.abs(), infinity);
999         assert_eq!((1f64/neg_infinity).abs(), 0f64);
1000         assert!(NaN.abs().is_NaN());
1001
1002         assert_eq!(infinity.signum(), 1f64);
1003         assert_eq!(1f64.signum(), 1f64);
1004         assert_eq!(0f64.signum(), 1f64);
1005         assert_eq!((-0f64).signum(), -1f64);
1006         assert_eq!((-1f64).signum(), -1f64);
1007         assert_eq!(neg_infinity.signum(), -1f64);
1008         assert_eq!((1f64/neg_infinity).signum(), -1f64);
1009         assert!(NaN.signum().is_NaN());
1010
1011         assert!(infinity.is_positive());
1012         assert!(1f64.is_positive());
1013         assert!(0f64.is_positive());
1014         assert!(!(-0f64).is_positive());
1015         assert!(!(-1f64).is_positive());
1016         assert!(!neg_infinity.is_positive());
1017         assert!(!(1f64/neg_infinity).is_positive());
1018         assert!(!NaN.is_positive());
1019
1020         assert!(!infinity.is_negative());
1021         assert!(!1f64.is_negative());
1022         assert!(!0f64.is_negative());
1023         assert!((-0f64).is_negative());
1024         assert!((-1f64).is_negative());
1025         assert!(neg_infinity.is_negative());
1026         assert!((1f64/neg_infinity).is_negative());
1027         assert!(!NaN.is_negative());
1028     }
1029
1030     #[test]
1031     fn test_primitive() {
1032         assert_eq!(Primitive::bits::<f64>(), sys::size_of::<f64>() * 8);
1033         assert_eq!(Primitive::bytes::<f64>(), sys::size_of::<f64>());
1034     }
1035 }
1036
1037 //
1038 // Local Variables:
1039 // mode: rust
1040 // fill-column: 78;
1041 // indent-tabs-mode: nil
1042 // c-basic-offset: 4
1043 // buffer-file-coding-system: utf-8-unix
1044 // End:
1045 //