Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] Build musl for tests #300

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
5 changes: 5 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
name: Docker
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target:
- aarch64-unknown-linux-gnu
Expand All @@ -33,6 +34,8 @@ jobs:
- run: rustup target add ${{ matrix.target }}
- run: rustup target add x86_64-unknown-linux-musl
- run: cargo generate-lockfile
- name: Download MUSL source
run: ./ci/download-musl.sh
- run: ./ci/run-docker.sh ${{ matrix.target }}

rustfmt:
Expand All @@ -52,6 +55,8 @@ jobs:
- name: Install Rust
run: rustup update nightly && rustup default nightly
- run: rustup target add wasm32-unknown-unknown
- name: Download MUSL source
run: ./ci/download-musl.sh
- run: cargo build --target wasm32-unknown-unknown

cb:
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
**/*.rs.bk
**.bk
.#*
/bin
/math/src
/math/target
/target
/tests
Cargo.lock
musl/
**.tar.gz
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ name = "libm"
readme = "README.md"
repository = "https://github.com/rust-lang/libm"
version = "0.2.8"
edition = "2018"
edition = "2021"
exclude = ["/ci/", "/.github/workflows/"]

[features]
Expand All @@ -27,6 +27,7 @@ members = [
"crates/compiler-builtins-smoke-test",
"crates/libm-bench",
"crates/libm-test",
"crates/musl-math-sys",
]
default-members = [
".",
Expand Down
13 changes: 13 additions & 0 deletions ci/download-musl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh

set -eux

fname=musl-1.2.5.tar.gz
sha=a9a118bbe84d8764da0ea0d28b3ab3fae8477fc7e4085d90102b8596fc7c75e4

mkdir musl
curl "https://musl.libc.org/releases/$fname" -O
echo "$sha $fname" | shasum -a 256 --check || exit 1

tar -xzf "$fname" -C musl --strip-components 1
rm "$fname"
1 change: 1 addition & 0 deletions crates/compiler-builtins-smoke-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "cb"
version = "0.1.0"
authors = ["Jorge Aparicio <jorge@japaric.io>"]
edition = "2021"

[lib]
test = false
Expand Down
10 changes: 9 additions & 1 deletion crates/libm-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,22 @@ edition = "2021"
publish = false

[features]
default = []
default = ["musl-checks"]

# Do comparisons against
musl-checks = ["dep:musl-math-sys"]

# Generate tests which are random inputs and the outputs are calculated with
# musl libc.
musl-bitwise-tests = ["rand"]

[dependencies]
musl-math-sys = { path = "../musl-math-sys", optional = true }
libm = { path = "../.." }

[dev-dependencies]
rand = "0.8.5"
rand_chacha = "0.3.1"

[build-dependencies]
rand = { version = "0.8.5", optional = true }
31 changes: 29 additions & 2 deletions crates/libm-test/build.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
use std::fmt::Write;
use std::path::PathBuf;
use std::{env, fs};

fn main() {
list_all_tests();

#[cfg(feature = "musl-bitwise-tests")]
musl_reference_tests::generate();
}

fn list_all_tests() {
let root_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let math_src = root_dir.join("../../src/math");

let mut files = fs::read_dir(math_src)
.unwrap()
.map(|f| f.unwrap().path())
.filter(|entry| entry.is_file())
.map(|f| f.file_stem().unwrap().to_str().unwrap().to_owned())
.collect::<Vec<_>>();
files.sort();

let mut s = "const MATH_FILES: &[&str] = &[".to_owned();
for f in files {
write!(s, "\"{f}\",").unwrap();
}
write!(s, "];").unwrap();

let outfile = out_dir.join("all_files.rs");
fs::write(outfile, s).unwrap();
}

#[cfg(feature = "musl-bitwise-tests")]
mod musl_reference_tests {
use rand::seq::SliceRandom;
use rand::Rng;
use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

Expand Down
210 changes: 210 additions & 0 deletions crates/libm-test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,211 @@
use std::fmt;

// // List of all files present in libm's source
// include!(concat!(env!("OUT_DIR"), "/all_files.rs"));

pub trait Float {
type Int: Int;
const BITS: u32;
}

pub trait Int {
type OtherSign: Int;
type Unsigned: Int;
const BITS: u32;
const SIGNED: bool;

fn signed(self) -> <Self::Unsigned as Int>::OtherSign;
fn unsigned(self) -> Self::Unsigned;
}

impl Float for f32 {
type Int = u32;
const BITS: u32 = 32;
}

impl Float for f64 {
type Int = u64;
const BITS: u32 = 64;
}

impl Int for u32 {
type OtherSign = i32;
type Unsigned = Self;
const BITS: u32 = 32;
const SIGNED: bool = false;
fn signed(self) -> i32 {
self as i32
}
fn unsigned(self) -> Self {
self
}
}

impl Int for u64 {
type OtherSign = i64;
type Unsigned = Self;
const BITS: u32 = 64;
const SIGNED: bool = false;
fn signed(self) -> i64 {
self as i64
}
fn unsigned(self) -> Self {
self
}
}

impl Int for i32 {
type OtherSign = u32;
type Unsigned = u32;
const BITS: u32 = 32;
const SIGNED: bool = true;
fn signed(self) -> Self {
self
}
fn unsigned(self) -> u32 {
self as u32
}
}

impl Int for i64 {
type OtherSign = u64;
type Unsigned = u64;
const BITS: u32 = 64;
const SIGNED: bool = true;
fn signed(self) -> Self {
self
}
fn unsigned(self) -> u64 {
self as u64
}
}

pub trait TupleCall<F>: fmt::Debug {
type Output;
fn call(self, f: F) -> Self::Output;
}

impl TupleCall<fn(f32) -> f32> for (f32,) {
type Output = f32;

fn call(self, f: fn(f32) -> f32) -> Self::Output {
f(self.0)
}
}

impl TupleCall<fn(f64) -> f64> for (f64,) {
type Output = f64;

fn call(self, f: fn(f64) -> f64) -> Self::Output {
f(self.0)
}
}

impl TupleCall<fn(f32, f32) -> f32> for (f32, f32) {
type Output = f32;

fn call(self, f: fn(f32, f32) -> f32) -> Self::Output {
f(self.0, self.1)
}
}

impl TupleCall<fn(f64, f64) -> f64> for (f64, f64) {
type Output = f64;

fn call(self, f: fn(f64, f64) -> f64) -> Self::Output {
f(self.0, self.1)
}
}

#[derive(Clone, Copy)]
pub struct Hex<T>(pub T);

impl fmt::Display for Hex<u32> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:#010x}", self.0)
}
}

impl<T> fmt::Debug for Hex<T>
where
Hex<T>: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}

impl fmt::Display for Hex<u64> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:#018x}", self.0)
}
}

impl fmt::Display for Hex<f32> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Hex(self.0.to_bits()).fmt(f)
}
}

impl fmt::Display for Hex<f64> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Hex(self.0.to_bits()).fmt(f)
}
}

impl<T1> fmt::Display for Hex<(T1,)>
where
Hex<T1>: fmt::Debug,
T1: Copy,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Debug;
(Hex(self.0 .0),).fmt(f)
}
}

impl<T1, T2> fmt::Display for Hex<(T1, T2)>
where
Hex<T1>: fmt::Debug + Copy,
Hex<T2>: fmt::Debug + Copy,
T1: Copy,
T2: Copy,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Debug;
(Hex(self.0 .0), Hex(self.0 .1)).fmt(f)
}
}

#[derive(Debug, Default)]
pub struct TestCases {
pub inputs_f32: Vec<(f32,)>,
pub inputs_f64: Vec<(f64,)>,
pub inputs_f32_f32: Vec<(f32, f32)>,
pub inputs_f64_f64: Vec<(f64, f64)>,
}

pub trait GetVal: Sized {
fn get_cases(all: &TestCases) -> &[Self];
}

impl GetVal for (f32,) {
fn get_cases(all: &TestCases) -> &[Self] {
&all.inputs_f32
}
}
impl GetVal for (f32, f32) {
fn get_cases(all: &TestCases) -> &[Self] {
&all.inputs_f32_f32
}
}
impl GetVal for (f64,) {
fn get_cases(all: &TestCases) -> &[Self] {
&all.inputs_f64
}
}
impl GetVal for (f64, f64) {
fn get_cases(all: &TestCases) -> &[Self] {
&all.inputs_f64_f64
}
}
Loading
Loading