Fix problems with f64 and DirEntry on Illumos

This commit is contained in:
Nikita Baksalyar 2016-01-27 05:46:28 +03:00
parent ebab24059a
commit 6d07b68f5e
No known key found for this signature in database
GPG Key ID: 3EEA378A0EA758DA
2 changed files with 37 additions and 67 deletions

View File

@ -511,28 +511,7 @@ pub fn exp2(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn ln(self) -> f64 {
if !cfg!(target_os = "sunos") {
unsafe { intrinsics::logf64(self) }
} else {
// Illumos requires a wrapper around log, log2, and log10 functions
// because of their non-standard behavior (e.g. log(-n) returns -Inf instead
// of expected NaN).
if self.is_finite() {
if self > 0.0 {
unsafe { intrinsics::logf64(self) }
} else if self == 0.0 {
NEG_INFINITY // log(0) = -Inf
} else {
NAN // log(-n) = NaN
}
} else if self.is_nan() {
self // log(NaN) = NaN
} else if self > 0.0 {
self // log(Inf) = Inf
} else {
NAN // log(-Inf) = NaN
}
}
self.log_wrapper(|n| { unsafe { intrinsics::logf64(n) } })
}
/// Returns the logarithm of the number with respect to an arbitrary base.
@ -567,27 +546,7 @@ pub fn log(self, base: f64) -> f64 { self.ln() / base.ln() }
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn log2(self) -> f64 {
if !cfg!(target_os = "sunos") {
unsafe { intrinsics::log2f64(self) }
} else {
// Illumos requires a wrapper around the log2 function because of
// its non-standard behavior
if self.is_finite() {
if self > 0.0 {
unsafe { intrinsics::log2f64(self) }
} else if self == 0.0 {
NEG_INFINITY // log2(0) = -Inf
} else {
NAN // log2(-n) = NaN
}
} else if self.is_nan() {
self // log2(NaN) = NaN
} else if self > 0.0 {
self // log2(Inf) = Inf
} else {
NAN // log2(-Inf) = NaN
}
}
self.log_wrapper(|n| { unsafe { intrinsics::log2f64(n) } })
}
/// Returns the base 10 logarithm of the number.
@ -603,27 +562,7 @@ pub fn log2(self) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn log10(self) -> f64 {
if !cfg!(target_os = "sunos") {
unsafe { intrinsics::log10f64(self) }
} else {
// Illumos requires a wrapper around the log10 function because of
// its non-standard behavior.
if self.is_finite() {
if self > 0.0 {
unsafe { intrinsics::log10f64(self) }
} else if self == 0.0 {
NEG_INFINITY // log10(0) = -Inf
} else {
NAN // log10(-n) = NaN
}
} else if self.is_nan() {
self // log10(NaN) = NaN
} else if self > 0.0 {
self // log10(Inf) = Inf
} else {
NAN // log10(-Inf) = NaN
}
}
self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } })
}
/// Converts radians to degrees.
@ -1126,6 +1065,31 @@ pub fn acosh(self) -> f64 {
pub fn atanh(self) -> f64 {
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
}
// Illumos requires a wrapper around log, log2, and log10 functions
// because of their non-standard behavior (e.g. log(-n) returns -Inf instead
// of expected NaN).
fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
if !cfg!(target_os = "sunos") {
log_fn(self)
} else {
if self.is_finite() {
if self > 0.0 {
log_fn(self)
} else if self == 0.0 {
NEG_INFINITY // log(0) = -Inf
} else {
NAN // log(-n) = NaN
}
} else if self.is_nan() {
self // log(NaN) = NaN
} else if self > 0.0 {
self // log(Inf) = Inf
} else {
NAN // log(-Inf) = NaN
}
}
}
}
#[cfg(test)]

View File

@ -26,6 +26,8 @@
use vec::Vec;
#[cfg(target_os = "sunos")]
use core_collections::borrow::ToOwned;
#[cfg(target_os = "sunos")]
use boxed::Box;
pub struct File(FileDesc);
@ -52,7 +54,7 @@ pub struct DirEntry {
// store the name, b) its lifetime between readdir calls
// is not guaranteed.
#[cfg(target_os = "sunos")]
name: Arc<Vec<u8>>
name: Box<[u8]>
}
#[derive(Clone)]
@ -143,6 +145,10 @@ impl Iterator for ReadDir {
fn next(&mut self) -> Option<io::Result<DirEntry>> {
unsafe {
loop {
// Although readdir_r(3) would be a correct function to use here because
// of the thread safety, on Illumos the readdir(3C) function is safe to use
// in threaded applications and it is generally preferred over the
// readdir_r(3C) function.
let entry_ptr = libc::readdir(self.dirp.0);
if entry_ptr.is_null() {
return None
@ -153,8 +159,8 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
let ret = DirEntry {
entry: *entry_ptr,
name: Arc::new(::slice::from_raw_parts(name as *const u8,
namelen as usize).to_owned()),
name: ::slice::from_raw_parts(name as *const u8,
namelen as usize).to_owned().into_boxed_slice(),
root: self.root.clone()
};
if ret.name_bytes() != b"." && ret.name_bytes() != b".." {