Skip to content
/ rust Public
forked from rust-lang/rust

Commit 8838c73

Browse files
committed
Auto merge of rust-lang#99747 - ankane:float_gamma, r=workingjubilee
Add gamma function to f32 and f64 Adds the [gamma function](https://en.wikipedia.org/wiki/Gamma_function) to `f32` and `f64` (`tgamma` and `tgammaf` from C). Refs: - rust-lang/rfcs#864 - rust-lang#18271
2 parents a946c1e + a75e228 commit 8838c73

File tree

9 files changed

+161
-4
lines changed

9 files changed

+161
-4
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -641,9 +641,9 @@ dependencies = [
641641

642642
[[package]]
643643
name = "compiler_builtins"
644-
version = "0.1.98"
644+
version = "0.1.100"
645645
source = "registry+https://github.com/rust-lang/crates.io-index"
646-
checksum = "dfbefa16407456e5cad1ad066c84dfcb980afe4437103a0007d1c2f136130210"
646+
checksum = "d6c0f24437059853f0fa64afc51f338f93647a3de4cf3358ba1bb4171a199775"
647647
dependencies = [
648648
"cc",
649649
"rustc-std-workspace-core",

library/std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
1818
panic_abort = { path = "../panic_abort" }
1919
core = { path = "../core", public = true }
2020
libc = { version = "0.2.146", default-features = false, features = ['rustc-dep-of-std'], public = true }
21-
compiler_builtins = { version = "0.1.98" }
21+
compiler_builtins = { version = "0.1.100" }
2222
profiler_builtins = { path = "../profiler_builtins", optional = true }
2323
unwind = { path = "../unwind" }
2424
hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }

library/std/src/f32.rs

+42
Original file line numberDiff line numberDiff line change
@@ -957,4 +957,46 @@ impl f32 {
957957
pub fn atanh(self) -> f32 {
958958
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
959959
}
960+
961+
/// Gamma function.
962+
///
963+
/// # Examples
964+
///
965+
/// ```
966+
/// #![feature(float_gamma)]
967+
/// let x = 5.0f32;
968+
///
969+
/// let abs_difference = (x.gamma() - 24.0).abs();
970+
///
971+
/// assert!(abs_difference <= f32::EPSILON);
972+
/// ```
973+
#[rustc_allow_incoherent_impl]
974+
#[must_use = "method returns a new number and does not mutate the original value"]
975+
#[unstable(feature = "float_gamma", issue = "99842")]
976+
#[inline]
977+
pub fn gamma(self) -> f32 {
978+
unsafe { cmath::tgammaf(self) }
979+
}
980+
981+
/// Returns the natural logarithm of the gamma function.
982+
///
983+
/// # Examples
984+
///
985+
/// ```
986+
/// #![feature(float_gamma)]
987+
/// let x = 2.0f32;
988+
///
989+
/// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
990+
///
991+
/// assert!(abs_difference <= f32::EPSILON);
992+
/// ```
993+
#[rustc_allow_incoherent_impl]
994+
#[must_use = "method returns a new number and does not mutate the original value"]
995+
#[unstable(feature = "float_gamma", issue = "99842")]
996+
#[inline]
997+
pub fn ln_gamma(self) -> (f32, i32) {
998+
let mut signgamp: i32 = 0;
999+
let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) };
1000+
(x, signgamp)
1001+
}
9601002
}

library/std/src/f32/tests.rs

+32
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,38 @@ fn test_atanh() {
652652
assert_approx_eq!((-0.5f32).atanh(), -0.54930614433405484569762261846126285f32);
653653
}
654654

655+
#[test]
656+
fn test_gamma() {
657+
// precision can differ between platforms
658+
assert_approx_eq!(1.0f32.gamma(), 1.0f32);
659+
assert_approx_eq!(2.0f32.gamma(), 1.0f32);
660+
assert_approx_eq!(3.0f32.gamma(), 2.0f32);
661+
assert_approx_eq!(4.0f32.gamma(), 6.0f32);
662+
assert_approx_eq!(5.0f32.gamma(), 24.0f32);
663+
assert_approx_eq!(0.5f32.gamma(), consts::PI.sqrt());
664+
assert_approx_eq!((-0.5f32).gamma(), -2.0 * consts::PI.sqrt());
665+
assert_eq!(0.0f32.gamma(), f32::INFINITY);
666+
assert_eq!((-0.0f32).gamma(), f32::NEG_INFINITY);
667+
assert!((-1.0f32).gamma().is_nan());
668+
assert!((-2.0f32).gamma().is_nan());
669+
assert!(f32::NAN.gamma().is_nan());
670+
assert!(f32::NEG_INFINITY.gamma().is_nan());
671+
assert_eq!(f32::INFINITY.gamma(), f32::INFINITY);
672+
assert_eq!(171.71f32.gamma(), f32::INFINITY);
673+
}
674+
675+
#[test]
676+
fn test_ln_gamma() {
677+
assert_approx_eq!(1.0f32.ln_gamma().0, 0.0f32);
678+
assert_eq!(1.0f32.ln_gamma().1, 1);
679+
assert_approx_eq!(2.0f32.ln_gamma().0, 0.0f32);
680+
assert_eq!(2.0f32.ln_gamma().1, 1);
681+
assert_approx_eq!(3.0f32.ln_gamma().0, 2.0f32.ln());
682+
assert_eq!(3.0f32.ln_gamma().1, 1);
683+
assert_approx_eq!((-0.5f32).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln());
684+
assert_eq!((-0.5f32).ln_gamma().1, -1);
685+
}
686+
655687
#[test]
656688
fn test_real_consts() {
657689
use super::consts;

library/std/src/f64.rs

+42
Original file line numberDiff line numberDiff line change
@@ -957,4 +957,46 @@ impl f64 {
957957
pub fn atanh(self) -> f64 {
958958
0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
959959
}
960+
961+
/// Gamma function.
962+
///
963+
/// # Examples
964+
///
965+
/// ```
966+
/// #![feature(float_gamma)]
967+
/// let x = 5.0f64;
968+
///
969+
/// let abs_difference = (x.gamma() - 24.0).abs();
970+
///
971+
/// assert!(abs_difference <= f64::EPSILON);
972+
/// ```
973+
#[rustc_allow_incoherent_impl]
974+
#[must_use = "method returns a new number and does not mutate the original value"]
975+
#[unstable(feature = "float_gamma", issue = "99842")]
976+
#[inline]
977+
pub fn gamma(self) -> f64 {
978+
unsafe { cmath::tgamma(self) }
979+
}
980+
981+
/// Returns the natural logarithm of the gamma function.
982+
///
983+
/// # Examples
984+
///
985+
/// ```
986+
/// #![feature(float_gamma)]
987+
/// let x = 2.0f64;
988+
///
989+
/// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
990+
///
991+
/// assert!(abs_difference <= f64::EPSILON);
992+
/// ```
993+
#[rustc_allow_incoherent_impl]
994+
#[must_use = "method returns a new number and does not mutate the original value"]
995+
#[unstable(feature = "float_gamma", issue = "99842")]
996+
#[inline]
997+
pub fn ln_gamma(self) -> (f64, i32) {
998+
let mut signgamp: i32 = 0;
999+
let x = unsafe { cmath::lgamma_r(self, &mut signgamp) };
1000+
(x, signgamp)
1001+
}
9601002
}

library/std/src/f64/tests.rs

+32
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,38 @@ fn test_atanh() {
635635
assert_approx_eq!((-0.5f64).atanh(), -0.54930614433405484569762261846126285f64);
636636
}
637637

638+
#[test]
639+
fn test_gamma() {
640+
// precision can differ between platforms
641+
assert_approx_eq!(1.0f64.gamma(), 1.0f64);
642+
assert_approx_eq!(2.0f64.gamma(), 1.0f64);
643+
assert_approx_eq!(3.0f64.gamma(), 2.0f64);
644+
assert_approx_eq!(4.0f64.gamma(), 6.0f64);
645+
assert_approx_eq!(5.0f64.gamma(), 24.0f64);
646+
assert_approx_eq!(0.5f64.gamma(), consts::PI.sqrt());
647+
assert_approx_eq!((-0.5f64).gamma(), -2.0 * consts::PI.sqrt());
648+
assert_eq!(0.0f64.gamma(), f64::INFINITY);
649+
assert_eq!((-0.0f64).gamma(), f64::NEG_INFINITY);
650+
assert!((-1.0f64).gamma().is_nan());
651+
assert!((-2.0f64).gamma().is_nan());
652+
assert!(f64::NAN.gamma().is_nan());
653+
assert!(f64::NEG_INFINITY.gamma().is_nan());
654+
assert_eq!(f64::INFINITY.gamma(), f64::INFINITY);
655+
assert_eq!(171.71f64.gamma(), f64::INFINITY);
656+
}
657+
658+
#[test]
659+
fn test_ln_gamma() {
660+
assert_approx_eq!(1.0f64.ln_gamma().0, 0.0f64);
661+
assert_eq!(1.0f64.ln_gamma().1, 1);
662+
assert_approx_eq!(2.0f64.ln_gamma().0, 0.0f64);
663+
assert_eq!(2.0f64.ln_gamma().1, 1);
664+
assert_approx_eq!(3.0f64.ln_gamma().0, 2.0f64.ln());
665+
assert_eq!(3.0f64.ln_gamma().1, 1);
666+
assert_approx_eq!((-0.5f64).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln());
667+
assert_eq!((-0.5f64).ln_gamma().1, -1);
668+
}
669+
638670
#[test]
639671
fn test_real_consts() {
640672
use super::consts;

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@
288288
#![feature(exact_size_is_empty)]
289289
#![feature(exclusive_wrapper)]
290290
#![feature(extend_one)]
291+
#![feature(float_gamma)]
291292
#![feature(float_minimum_maximum)]
292293
#![feature(float_next_up_down)]
293294
#![feature(hasher_prefixfree_extras)]

library/std/src/sys/unix/cmath.rs

+4
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,8 @@ extern "C" {
3030
pub fn tanf(n: f32) -> f32;
3131
pub fn tanh(n: f64) -> f64;
3232
pub fn tanhf(n: f32) -> f32;
33+
pub fn tgamma(n: f64) -> f64;
34+
pub fn tgammaf(n: f32) -> f32;
35+
pub fn lgamma_r(n: f64, s: &mut i32) -> f64;
36+
pub fn lgammaf_r(n: f32, s: &mut i32) -> f32;
3337
}

library/std/src/sys/windows/cmath.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![cfg(not(test))]
22

3-
use libc::{c_double, c_float};
3+
use libc::{c_double, c_float, c_int};
44

55
extern "C" {
66
pub fn acos(n: c_double) -> c_double;
@@ -23,6 +23,10 @@ extern "C" {
2323
pub fn sinh(n: c_double) -> c_double;
2424
pub fn tan(n: c_double) -> c_double;
2525
pub fn tanh(n: c_double) -> c_double;
26+
pub fn tgamma(n: c_double) -> c_double;
27+
pub fn tgammaf(n: c_float) -> c_float;
28+
pub fn lgamma_r(n: c_double, s: &mut c_int) -> c_double;
29+
pub fn lgammaf_r(n: c_float, s: &mut c_int) -> c_float;
2630
}
2731

2832
pub use self::shims::*;

0 commit comments

Comments
 (0)