Skip to content

Commit 7f90abe

Browse files
committed
Auto merge of #61635 - ecstatic-morse:const-signum, r=oli-obk
Make `i*::signum` a `const fn`. Ticks a box in #53718. This uses a well-known branchless implementation of `signum`: `(n > 0) as i32 - (n < 0) as i32`. Here's a [playground](https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=747cf191c4974bf66c9d75e509ae6e6e) comparing the two techniques. On x86 in release mode, the branchless implementation is able to replace a `mov` and `cmov` with a `sar` and `add`, so this should be a bit faster as well. ~~This is marked as a draft since I think I'll need to add `#[rustc_const_unstable]` somewhere. Perhaps the reviewer can point me in the right direction.~~
2 parents 6312b89 + f6611db commit 7f90abe

File tree

2 files changed

+15
-8
lines changed

2 files changed

+15
-8
lines changed

src/libcore/num/mod.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -1993,13 +1993,10 @@ assert_eq!((-10", stringify!($SelfT), ").signum(), -1);",
19931993
$EndFeature, "
19941994
```"),
19951995
#[stable(feature = "rust1", since = "1.0.0")]
1996+
#[rustc_const_unstable(feature = "const_int_sign")]
19961997
#[inline]
1997-
pub fn signum(self) -> Self {
1998-
match self {
1999-
n if n > 0 => 1,
2000-
0 => 0,
2001-
_ => -1,
2002-
}
1998+
pub const fn signum(self) -> Self {
1999+
(self > 0) as Self - (self < 0) as Self
20032000
}
20042001
}
20052002

src/test/run-pass/const-int-sign.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1+
#![feature(const_int_sign)]
2+
13
const NEGATIVE_A: bool = (-10i32).is_negative();
24
const NEGATIVE_B: bool = 10i32.is_negative();
3-
const POSITIVE_A: bool= (-10i32).is_positive();
4-
const POSITIVE_B: bool= 10i32.is_positive();
5+
const POSITIVE_A: bool = (-10i32).is_positive();
6+
const POSITIVE_B: bool = 10i32.is_positive();
7+
8+
const SIGNUM_POS: i32 = 10i32.signum();
9+
const SIGNUM_NIL: i32 = 0i32.signum();
10+
const SIGNUM_NEG: i32 = (-42i32).signum();
511

612
fn main() {
713
assert!(NEGATIVE_A);
814
assert!(!NEGATIVE_B);
915
assert!(!POSITIVE_A);
1016
assert!(POSITIVE_B);
17+
18+
assert_eq!(SIGNUM_POS, 1);
19+
assert_eq!(SIGNUM_NIL, 0);
20+
assert_eq!(SIGNUM_NEG, -1);
1121
}

0 commit comments

Comments
 (0)