Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 6f6b0e1

Browse files
committed
Add numeric traits
These traits are simplified versions of what we have in `compiler_builtins` and will be used for tests.
1 parent a2d555f commit 6f6b0e1

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed

crates/libm-test/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1+
mod num_traits;
2+
3+
pub use num_traits::{Float, Hex, Int};
4+
15
// List of all files present in libm's source
26
include!(concat!(env!("OUT_DIR"), "/all_files.rs"));

crates/libm-test/src/num_traits.rs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
use std::fmt;
2+
3+
/// Common types and methods for floating point numbers.
4+
pub trait Float: Copy + fmt::Display + fmt::Debug + PartialEq<Self> {
5+
type Int: Int<OtherSign = Self::SignedInt, Unsigned = Self::Int>;
6+
type SignedInt: Int + Int<OtherSign = Self::Int, Unsigned = Self::Int>;
7+
8+
const ZERO: Self;
9+
const ONE: Self;
10+
11+
/// The bitwidth of the float type
12+
const BITS: u32;
13+
14+
/// The bitwidth of the significand
15+
const SIGNIFICAND_BITS: u32;
16+
17+
/// The bitwidth of the exponent
18+
const EXPONENT_BITS: u32 = Self::BITS - Self::SIGNIFICAND_BITS - 1;
19+
20+
fn is_nan(self) -> bool;
21+
fn is_infinite(self) -> bool;
22+
fn to_bits(self) -> Self::Int;
23+
fn from_bits(bits: Self::Int) -> Self;
24+
fn signum(self) -> Self;
25+
}
26+
27+
macro_rules! impl_float {
28+
($($fty:ty, $ui:ty, $si:ty, $significand_bits:expr;)+) => {
29+
$(
30+
impl Float for $fty {
31+
type Int = $ui;
32+
type SignedInt = $si;
33+
34+
const ZERO: Self = 0.0;
35+
const ONE: Self = 1.0;
36+
37+
const BITS: u32 = <$ui>::BITS;
38+
const SIGNIFICAND_BITS: u32 = $significand_bits;
39+
40+
fn is_nan(self) -> bool {
41+
self.is_nan()
42+
}
43+
fn is_infinite(self) -> bool {
44+
self.is_infinite()
45+
}
46+
fn to_bits(self) -> Self::Int {
47+
self.to_bits()
48+
}
49+
fn from_bits(bits: Self::Int) -> Self {
50+
Self::from_bits(bits)
51+
}
52+
fn signum(self) -> Self {
53+
self.signum()
54+
}
55+
}
56+
57+
impl Hex for $fty {
58+
fn hex(self) -> String {
59+
self.to_bits().hex()
60+
}
61+
}
62+
)+
63+
}
64+
}
65+
66+
impl_float!(
67+
f32, u32, i32, 23;
68+
f64, u64, i64, 52;
69+
);
70+
71+
/// Common types and methods for integers.
72+
pub trait Int: Copy + fmt::Display + fmt::Debug + PartialEq<Self> {
73+
type OtherSign: Int;
74+
type Unsigned: Int;
75+
const BITS: u32;
76+
const SIGNED: bool;
77+
78+
fn signed(self) -> <Self::Unsigned as Int>::OtherSign;
79+
fn unsigned(self) -> Self::Unsigned;
80+
fn checked_sub(self, other: Self) -> Option<Self>;
81+
fn abs(self) -> Self;
82+
}
83+
84+
macro_rules! impl_int {
85+
($($ui:ty, $si:ty ;)+) => {
86+
$(
87+
impl Int for $ui {
88+
type OtherSign = $si;
89+
type Unsigned = Self;
90+
const BITS: u32 = <$ui>::BITS;
91+
const SIGNED: bool = false;
92+
fn signed(self) -> Self::OtherSign {
93+
self as $si
94+
}
95+
fn unsigned(self) -> Self {
96+
self
97+
}
98+
fn checked_sub(self, other: Self) -> Option<Self> {
99+
self.checked_sub(other)
100+
}
101+
fn abs(self) -> Self {
102+
unimplemented!()
103+
}
104+
}
105+
106+
impl Int for $si {
107+
type OtherSign = $ui;
108+
type Unsigned = $ui;
109+
const BITS: u32 = <$ui>::BITS;
110+
const SIGNED: bool = true;
111+
fn signed(self) -> Self {
112+
self
113+
}
114+
fn unsigned(self) -> $ui {
115+
self as $ui
116+
}
117+
fn checked_sub(self, other: Self) -> Option<Self> {
118+
self.checked_sub(other)
119+
}
120+
fn abs(self) -> Self {
121+
self.abs()
122+
}
123+
}
124+
125+
impl_int!(@for_both $si);
126+
impl_int!(@for_both $ui);
127+
128+
)+
129+
};
130+
131+
(@for_both $ty:ty) => {
132+
impl Hex for $ty {
133+
fn hex(self) -> String {
134+
format!("{self:#0width$x}", width = ((Self::BITS / 4) + 2) as usize)
135+
}
136+
}
137+
}
138+
}
139+
140+
impl_int!(
141+
u32, i32;
142+
u64, i64;
143+
);
144+
145+
/// A helper trait to print something as hex with the correct number of nibbles, e.g. a `u32`
146+
/// will always print with `0x` followed by 8 digits.
147+
///
148+
/// This is only used for printing errors so allocating is okay.
149+
pub trait Hex: Copy {
150+
fn hex(self) -> String;
151+
}
152+
153+
impl<T1> Hex for (T1,)
154+
where
155+
T1: Hex,
156+
{
157+
fn hex(self) -> String {
158+
format!("({},)", self.0.hex())
159+
}
160+
}
161+
162+
impl<T1, T2> Hex for (T1, T2)
163+
where
164+
T1: Hex,
165+
T2: Hex,
166+
{
167+
fn hex(self) -> String {
168+
format!("({}, {})", self.0.hex(), self.1.hex())
169+
}
170+
}
171+
172+
impl<T1, T2, T3> Hex for (T1, T2, T3)
173+
where
174+
T1: Hex,
175+
T2: Hex,
176+
T3: Hex,
177+
{
178+
fn hex(self) -> String {
179+
format!("({}, {}, {})", self.0.hex(), self.1.hex(), self.2.hex())
180+
}
181+
}

0 commit comments

Comments
 (0)