From 39f82764279a2d1804087b19ea83bd4a25efa529 Mon Sep 17 00:00:00 2001 From: Kirpal Grewal Date: Fri, 29 Dec 2023 16:16:57 +0000 Subject: [PATCH 1/8] add finite math functions --- c-scape/src/math/mod.rs | 69 +++++++++++++++++++++++++++++++++++++++++ c-scape/src/todo.rs | 5 +-- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/c-scape/src/math/mod.rs b/c-scape/src/math/mod.rs index 655ecb1..2a5a48f 100644 --- a/c-scape/src/math/mod.rs +++ b/c-scape/src/math/mod.rs @@ -728,6 +728,35 @@ unsafe extern "C" fn nearbyintf(x: f32) -> f32 { libm::rintf(x) } +#[no_mangle] +unsafe extern "C" fn finite(x: f64) -> i32 { + return x.is_finite() as i32; +} +#[no_mangle] +unsafe extern "C" fn finitef(x: f32) -> i32 { + return x.is_finite() as i32; +} + +#[no_mangle] +unsafe extern "C" fn isnan(x: f64) -> i32 { + return x.is_nan() as i32; +} + +#[no_mangle] +unsafe extern "C" fn isnanf(x: f32) -> i32 { + return x.is_nan() as i32; +} + +#[no_mangle] +unsafe extern "C" fn isinf(x: f64) -> i32 { + return (x.is_infinite() as i32) * x.signum() as i32; +} + +#[no_mangle] +unsafe extern "C" fn isinff(x: f32) -> i32 { + return (x.is_infinite() as i32) * x.signum() as i32; +} + // Enable support for complex numbers only on architectures where the builtin // C complex type has the same calling convention rules as a struct containing // two scalars. Notably, this excludes 32-bit "x86". @@ -738,3 +767,43 @@ unsafe extern "C" fn nearbyintf(x: f32) -> f32 { target_arch = "x86_64" ))] mod complex; + +#[cfg(test)] +mod tests { + + use super::*; + #[test] + fn is_finite_test() { + unsafe { + assert_eq!(finite(1.), 1); + assert_eq!(finite(f64::NAN), 0); + assert_eq!(finite(f64::INFINITY), 0); + assert_eq!(finite(f64::NEG_INFINITY), 0); + + assert_eq!(isnan(1.), 0); + assert_eq!(isnan(f64::NAN), 1); + assert_eq!(isnan(f64::INFINITY), 0); + assert_eq!(isnan(f64::NEG_INFINITY), 0); + + assert_eq!(isinf(1.), 0); + assert_eq!(isinf(f64::NAN), 0); + assert_eq!(isinf(f64::INFINITY), 1); + assert_eq!(isinf(f64::NEG_INFINITY), -1); + + assert_eq!(finitef(1.), 1); + assert_eq!(finitef(f32::NAN), 0); + assert_eq!(finitef(f32::INFINITY), 0); + assert_eq!(finitef(f32::NEG_INFINITY), 0); + + assert_eq!(isnanf(1.), 0); + assert_eq!(isnanf(f32::NAN), 1); + assert_eq!(isnanf(f32::INFINITY), 0); + assert_eq!(isnanf(f32::NEG_INFINITY), 0); + + assert_eq!(isinff(1.), 0); + assert_eq!(isinff(f32::NAN), 0); + assert_eq!(isinff(f32::INFINITY), 1); + assert_eq!(isinff(f32::NEG_INFINITY), -1); + } + } +} diff --git a/c-scape/src/todo.rs b/c-scape/src/todo.rs index 96191f0..eaf9014 100644 --- a/c-scape/src/todo.rs +++ b/c-scape/src/todo.rs @@ -1378,10 +1378,7 @@ unsafe extern "C" fn register_printf_function() { unsafe extern "C" fn adjtime() { todo!("adjtime") } -#[no_mangle] -unsafe extern "C" fn isnanf() { - todo!("isnanf") -} + #[no_mangle] unsafe extern "C" fn gamma() { todo!("gamma") From 45a1a4b1f682b28e215596648b5362ee7d525b49 Mon Sep 17 00:00:00 2001 From: Kirpal Grewal Date: Fri, 29 Dec 2023 16:22:40 +0000 Subject: [PATCH 2/8] remove some branching in string comparison --- c-scape/src/mem/ntbs.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/c-scape/src/mem/ntbs.rs b/c-scape/src/mem/ntbs.rs index 6873348..dce0f56 100644 --- a/c-scape/src/mem/ntbs.rs +++ b/c-scape/src/mem/ntbs.rs @@ -99,11 +99,7 @@ unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char { unsafe extern "C" fn strcmp(mut s1: *const c_char, mut s2: *const c_char) -> c_int { libc!(libc::strcmp(s1, s2)); - while *s1 != NUL && *s2 != NUL { - if *s1 != *s2 { - break; - } - + while *s1 == *s2 && *s1 != NUL { s1 = s1.add(1); s2 = s2.add(1); } @@ -216,10 +212,7 @@ impl StrverscmpState { unsafe extern "C" fn strverscmp(mut s1: *const c_char, mut s2: *const c_char) -> c_int { // libc!(libc::strverscmp(s1, s2)); let mut state = StrverscmpState::Normal; - while *s1 != NUL && *s2 != NUL { - if *s1 != *s2 { - return state.exit(s1, s2); - } + while *s1 == *s2 && *s1 != NUL { state.transition(CharType::from_char(*s1)); s1 = s1.add(1); s2 = s2.add(1); @@ -632,13 +625,9 @@ unsafe extern "C" fn strlcat(dst: *mut c_char, src: *const c_char, limit: size_t #[cfg(test)] mod tests { - // use candle_core::test_utils::{to_vec0_round, to_vec2_round}; use super::*; #[test] fn strverscmp_test() { - extern "C" { - fn strverscmp(a: *const libc::c_char, b: *const libc::c_char) -> libc::c_int; - } unsafe { assert!(strverscmp("000\0".as_ptr().cast(), "00\0".as_ptr().cast()) < 0); assert!(strverscmp("00\0".as_ptr().cast(), "01\0".as_ptr().cast()) < 0); From 48189b2dcdd9d31dc5510d9b0815f257001a1a28 Mon Sep 17 00:00:00 2001 From: Kirpal Grewal Date: Fri, 29 Dec 2023 16:37:22 +0000 Subject: [PATCH 3/8] remove signnum from isinf --- c-scape/src/math/mod.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/c-scape/src/math/mod.rs b/c-scape/src/math/mod.rs index 2a5a48f..0199ec8 100644 --- a/c-scape/src/math/mod.rs +++ b/c-scape/src/math/mod.rs @@ -749,12 +749,24 @@ unsafe extern "C" fn isnanf(x: f32) -> i32 { #[no_mangle] unsafe extern "C" fn isinf(x: f64) -> i32 { - return (x.is_infinite() as i32) * x.signum() as i32; + if x == f64::INFINITY { + return 1; + } else if x == f64::NEG_INFINITY { + return -1; + } else { + return 0; + } } #[no_mangle] unsafe extern "C" fn isinff(x: f32) -> i32 { - return (x.is_infinite() as i32) * x.signum() as i32; + if x == f32::INFINITY { + return 1; + } else if x == f32::NEG_INFINITY { + return -1; + } else { + return 0; + } } // Enable support for complex numbers only on architectures where the builtin From 35c43076b5363ff79d16aca8b319b7023f6543cd Mon Sep 17 00:00:00 2001 From: Kirpal Grewal Date: Fri, 29 Dec 2023 17:44:38 +0000 Subject: [PATCH 4/8] change isinf return style --- c-scape/src/math/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/c-scape/src/math/mod.rs b/c-scape/src/math/mod.rs index 0199ec8..8d80901 100644 --- a/c-scape/src/math/mod.rs +++ b/c-scape/src/math/mod.rs @@ -750,22 +750,22 @@ unsafe extern "C" fn isnanf(x: f32) -> i32 { #[no_mangle] unsafe extern "C" fn isinf(x: f64) -> i32 { if x == f64::INFINITY { - return 1; + 1 } else if x == f64::NEG_INFINITY { - return -1; + -1 } else { - return 0; + 0 } } #[no_mangle] unsafe extern "C" fn isinff(x: f32) -> i32 { if x == f32::INFINITY { - return 1; + 1 } else if x == f32::NEG_INFINITY { - return -1; + -1 } else { - return 0; + 0 } } From 096b203168894732026dd8c7237f140ae38669b5 Mon Sep 17 00:00:00 2001 From: Kirpal Grewal Date: Fri, 29 Dec 2023 17:53:20 +0000 Subject: [PATCH 5/8] shift all to implicit return --- c-scape/src/math/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/c-scape/src/math/mod.rs b/c-scape/src/math/mod.rs index 8d80901..ef6f189 100644 --- a/c-scape/src/math/mod.rs +++ b/c-scape/src/math/mod.rs @@ -730,21 +730,21 @@ unsafe extern "C" fn nearbyintf(x: f32) -> f32 { #[no_mangle] unsafe extern "C" fn finite(x: f64) -> i32 { - return x.is_finite() as i32; + x.is_finite() as i32 } #[no_mangle] unsafe extern "C" fn finitef(x: f32) -> i32 { - return x.is_finite() as i32; + x.is_finite() as i32 } #[no_mangle] unsafe extern "C" fn isnan(x: f64) -> i32 { - return x.is_nan() as i32; + x.is_nan() as i32 } #[no_mangle] unsafe extern "C" fn isnanf(x: f32) -> i32 { - return x.is_nan() as i32; + x.is_nan() as i32 } #[no_mangle] From 6580c28d50caab0dbc48c98972f54fe3d78813de Mon Sep 17 00:00:00 2001 From: Kirpal Grewal Date: Fri, 29 Dec 2023 18:12:12 +0000 Subject: [PATCH 6/8] add lgamma --- c-scape/src/math/mod.rs | 10 ++++++++++ c-scape/src/todo.rs | 8 -------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/c-scape/src/math/mod.rs b/c-scape/src/math/mod.rs index ef6f189..3c09f2a 100644 --- a/c-scape/src/math/mod.rs +++ b/c-scape/src/math/mod.rs @@ -769,6 +769,16 @@ unsafe extern "C" fn isinff(x: f32) -> i32 { } } +#[no_mangle] +unsafe extern "C" fn lgamma(x: f64) -> f64 { + libm::lgamma(x) +} + +#[no_mangle] +unsafe extern "C" fn lgammaf(x: f32) -> f32 { + libm::lgammaf(x) +} + // Enable support for complex numbers only on architectures where the builtin // C complex type has the same calling convention rules as a struct containing // two scalars. Notably, this excludes 32-bit "x86". diff --git a/c-scape/src/todo.rs b/c-scape/src/todo.rs index eaf9014..67ef98d 100644 --- a/c-scape/src/todo.rs +++ b/c-scape/src/todo.rs @@ -1388,14 +1388,6 @@ unsafe extern "C" fn gammaf() { todo!("gammaf") } #[no_mangle] -unsafe extern "C" fn lgamma() { - todo!("lgamma") -} -#[no_mangle] -unsafe extern "C" fn lgammaf() { - todo!("lgammaf") -} -#[no_mangle] unsafe extern "C" fn strfromf() { todo!("strfromf") } From dd6f5c91d5f8a1c488578725696f3e1dcc99e127 Mon Sep 17 00:00:00 2001 From: Kirpal Grewal Date: Sat, 30 Dec 2023 00:11:24 +0000 Subject: [PATCH 7/8] add signgam signal flag --- c-scape/src/math/mod.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/c-scape/src/math/mod.rs b/c-scape/src/math/mod.rs index 3c09f2a..234a01e 100644 --- a/c-scape/src/math/mod.rs +++ b/c-scape/src/math/mod.rs @@ -769,14 +769,21 @@ unsafe extern "C" fn isinff(x: f32) -> i32 { } } +#[no_mangle] +pub static mut signgam: i32 = 0; + #[no_mangle] unsafe extern "C" fn lgamma(x: f64) -> f64 { - libm::lgamma(x) + let (a, b) = libm::lgamma_r(x); + signgam = b; + a } #[no_mangle] unsafe extern "C" fn lgammaf(x: f32) -> f32 { - libm::lgammaf(x) + let (res, sgn) = libm::lgammaf_r(x); + signgam = sgn; + res } // Enable support for complex numbers only on architectures where the builtin From 78d25c702c390b9c1f4e3ed0cb7fbd83fa1cdcb1 Mon Sep 17 00:00:00 2001 From: Kirpal Grewal Date: Sat, 30 Dec 2023 00:36:15 +0000 Subject: [PATCH 8/8] remove pub --- c-scape/src/math/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c-scape/src/math/mod.rs b/c-scape/src/math/mod.rs index 234a01e..1827bbb 100644 --- a/c-scape/src/math/mod.rs +++ b/c-scape/src/math/mod.rs @@ -770,7 +770,7 @@ unsafe extern "C" fn isinff(x: f32) -> i32 { } #[no_mangle] -pub static mut signgam: i32 = 0; +static mut signgam: i32 = 0; #[no_mangle] unsafe extern "C" fn lgamma(x: f64) -> f64 {