diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 4769b17fb2b84..f9fd21253faf8 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -308,8 +308,34 @@ pub fn float_to_str_bytes_common (num.abs().log2().floor(), cast::(2.0f64).unwrap()), ExpNone => unreachable!() }; + let iexp = cast::(exp).unwrap(); + + // For subnormal floats, powi and powf behave differently + // depending on the platform/compiler. For example, consider: + // + // 2f64.pow(-1074) [where pow = powf or powi] + // + // - On Mingw (vanilla), powf returns zero whereas powi + // returns a subnormal. + // + // - On Mingw-w64, both powi and powf return subnormals. + // + // - On Linux, powi returns zero whereas powf returns a + // subnormal. + // + // This workaround accounts for the difference in behavior and + // fixes part of issue #13439. + #[cfg(windows)] + fn pow(exp_base: T, _: T, iexp: i32) -> T { + exp_base.powi(iexp) + } + + #[cfg(not(windows))] + fn pow(exp_base: T, exp: T, _: i32) -> T { + exp_base.powf(exp) + } - (num / exp_base.powf(exp), cast::(exp).unwrap()) + (num / pow(exp_base, exp, iexp), iexp) } } };