Skip to content

Commit c53f2d7

Browse files
bors[bot]cuviper
andcommitted
Merge #48
48: Let new_raw, numer, and denom be const in Rust 1.31+ r=cuviper a=cuviper Fixes #32. Co-authored-by: Josh Stone <[email protected]>
2 parents ebebba9 + 81b4edc commit c53f2d7

File tree

2 files changed

+57
-21
lines changed

2 files changed

+57
-21
lines changed

build.rs

+6
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@ use std::env;
44

55
fn main() {
66
let ac = autocfg::new();
7+
78
if ac.probe_type("i128") {
89
println!("cargo:rustc-cfg=has_i128");
910
} else if env::var_os("CARGO_FEATURE_I128").is_some() {
1011
panic!("i128 support was not detected!");
1112
}
1213

14+
// autocfg doesn't have a direct way to probe for `const fn` yet.
15+
if ac.probe_rustc_version(1, 31) {
16+
autocfg::emit("has_const_fn");
17+
}
18+
1319
autocfg::rerun_path(file!());
1420
}

src/lib.rs

+51-21
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,42 @@ pub type Rational64 = Ratio<i64>;
6868
/// Alias for arbitrary precision rationals.
6969
pub type BigRational = Ratio<BigInt>;
7070

71+
macro_rules! maybe_const {
72+
($( $(#[$attr:meta])* pub fn $name:ident $args:tt -> $ret:ty $body:block )*) => {$(
73+
#[cfg(has_const_fn)]
74+
$(#[$attr])* pub const fn $name $args -> $ret $body
75+
76+
#[cfg(not(has_const_fn))]
77+
$(#[$attr])* pub fn $name $args -> $ret $body
78+
)*}
79+
}
80+
81+
/// These method are `const` for Rust 1.31 and later.
82+
impl<T> Ratio<T> {
83+
maybe_const! {
84+
/// Creates a `Ratio` without checking for `denom == 0` or reducing.
85+
#[inline]
86+
pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
87+
Ratio {
88+
numer: numer,
89+
denom: denom,
90+
}
91+
}
92+
93+
/// Gets an immutable reference to the numerator.
94+
#[inline]
95+
pub fn numer(&self) -> &T {
96+
&self.numer
97+
}
98+
99+
/// Gets an immutable reference to the denominator.
100+
#[inline]
101+
pub fn denom(&self) -> &T {
102+
&self.denom
103+
}
104+
}
105+
}
106+
71107
impl<T: Clone + Integer> Ratio<T> {
72108
/// Creates a new `Ratio`. Fails if `denom` is zero.
73109
#[inline]
@@ -86,33 +122,12 @@ impl<T: Clone + Integer> Ratio<T> {
86122
Ratio::new_raw(t, One::one())
87123
}
88124

89-
/// Creates a `Ratio` without checking for `denom == 0` or reducing.
90-
#[inline]
91-
pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
92-
Ratio {
93-
numer: numer,
94-
denom: denom,
95-
}
96-
}
97-
98125
/// Converts to an integer, rounding towards zero.
99126
#[inline]
100127
pub fn to_integer(&self) -> T {
101128
self.trunc().numer
102129
}
103130

104-
/// Gets an immutable reference to the numerator.
105-
#[inline]
106-
pub fn numer<'a>(&'a self) -> &'a T {
107-
&self.numer
108-
}
109-
110-
/// Gets an immutable reference to the denominator.
111-
#[inline]
112-
pub fn denom<'a>(&'a self) -> &'a T {
113-
&self.denom
114-
}
115-
116131
/// Returns true if the rational number is an integer (denominator is 1).
117132
#[inline]
118133
pub fn is_integer(&self) -> bool {
@@ -2071,4 +2086,19 @@ mod test {
20712086
r.set_one();
20722087
assert!(r.is_one());
20732088
}
2089+
2090+
#[cfg(has_const_fn)]
2091+
#[test]
2092+
fn test_const() {
2093+
const N: Ratio<i32> = Ratio::new_raw(123, 456);
2094+
const N_NUMER: &i32 = N.numer();
2095+
const N_DENOM: &i32 = N.denom();
2096+
2097+
assert_eq!(N_NUMER, &123);
2098+
assert_eq!(N_DENOM, &456);
2099+
2100+
let r = N.reduced();
2101+
assert_eq!(r.numer(), &(123 / 3));
2102+
assert_eq!(r.denom(), &(456 / 3));
2103+
}
20742104
}

0 commit comments

Comments
 (0)