blob: 1cefe4e8c7ed447a4985f9b0de90ca78446f51f4 [file] [log] [blame]
/* List of all functions that is shared between `libm-macros` and `libm-test`. */
use std::fmt;
use std::sync::LazyLock;
struct NestedOp {
float_ty: FloatTy,
rust_sig: Signature,
c_sig: Option<Signature>,
fn_list: &'static [&'static str],
public: bool,
}
/// We need a flat list to work with most of the time, but define things as a more convenient
/// nested list.
const ALL_OPERATIONS_NESTED: &[NestedOp] = &[
NestedOp {
// `fn(f16) -> f16`
float_ty: FloatTy::F16,
rust_sig: Signature {
args: &[Ty::F16],
returns: &[Ty::F16],
},
c_sig: None,
fn_list: &[
"ceilf16",
"fabsf16",
"floorf16",
"rintf16",
"roundevenf16",
"roundf16",
"sqrtf16",
"truncf16",
],
public: true,
},
NestedOp {
// `fn(f32) -> f32`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32],
returns: &[Ty::F32],
},
c_sig: None,
fn_list: &[
"acosf",
"acoshf",
"asinf",
"asinhf",
"atanf",
"atanhf",
"cbrtf",
"ceilf",
"cosf",
"coshf",
"erfcf",
"erff",
"exp10f",
"exp2f",
"expf",
"expm1f",
"fabsf",
"floorf",
"j0f",
"j1f",
"lgammaf",
"log10f",
"log1pf",
"log2f",
"logf",
"rintf",
"roundevenf",
"roundf",
"sinf",
"sinhf",
"sqrtf",
"tanf",
"tanhf",
"tgammaf",
"truncf",
"y0f",
"y1f",
],
public: true,
},
NestedOp {
// `(f64) -> f64`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64],
returns: &[Ty::F64],
},
c_sig: None,
fn_list: &[
"acos",
"acosh",
"asin",
"asinh",
"atan",
"atanh",
"cbrt",
"ceil",
"cos",
"cosh",
"erf",
"erfc",
"exp",
"exp10",
"exp2",
"expm1",
"fabs",
"floor",
"j0",
"j1",
"lgamma",
"log",
"log10",
"log1p",
"log2",
"rint",
"round",
"roundeven",
"sin",
"sinh",
"sqrt",
"tan",
"tanh",
"tgamma",
"trunc",
"y0",
"y1",
],
public: true,
},
NestedOp {
// `fn(f128) -> f128`
float_ty: FloatTy::F128,
rust_sig: Signature {
args: &[Ty::F128],
returns: &[Ty::F128],
},
c_sig: None,
fn_list: &[
"ceilf128",
"fabsf128",
"floorf128",
"rintf128",
"roundevenf128",
"roundf128",
"sqrtf128",
"truncf128",
],
public: true,
},
NestedOp {
// `(f16, f16) -> f16`
float_ty: FloatTy::F16,
rust_sig: Signature {
args: &[Ty::F16, Ty::F16],
returns: &[Ty::F16],
},
c_sig: None,
fn_list: &[
"copysignf16",
"fdimf16",
"fmaxf16",
"fmaximum_numf16",
"fmaximumf16",
"fminf16",
"fminimum_numf16",
"fminimumf16",
"fmodf16",
],
public: true,
},
NestedOp {
// `(f32, f32) -> f32`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32, Ty::F32],
returns: &[Ty::F32],
},
c_sig: None,
fn_list: &[
"atan2f",
"copysignf",
"fdimf",
"fmaxf",
"fmaximum_numf",
"fmaximumf",
"fminf",
"fminimum_numf",
"fminimumf",
"fmodf",
"hypotf",
"nextafterf",
"powf",
"remainderf",
],
public: true,
},
NestedOp {
// `(f64, f64) -> f64`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64, Ty::F64],
returns: &[Ty::F64],
},
c_sig: None,
fn_list: &[
"atan2",
"copysign",
"fdim",
"fmax",
"fmaximum",
"fmaximum_num",
"fmin",
"fminimum",
"fminimum_num",
"fmod",
"hypot",
"nextafter",
"pow",
"remainder",
],
public: true,
},
NestedOp {
// `(f128, f128) -> f128`
float_ty: FloatTy::F128,
rust_sig: Signature {
args: &[Ty::F128, Ty::F128],
returns: &[Ty::F128],
},
c_sig: None,
fn_list: &[
"copysignf128",
"fdimf128",
"fmaxf128",
"fmaximum_numf128",
"fmaximumf128",
"fminf128",
"fminimum_numf128",
"fminimumf128",
"fmodf128",
],
public: true,
},
NestedOp {
// `(f32, f32, f32) -> f32`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32, Ty::F32, Ty::F32],
returns: &[Ty::F32],
},
c_sig: None,
fn_list: &["fmaf"],
public: true,
},
NestedOp {
// `(f64, f64, f64) -> f64`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64, Ty::F64, Ty::F64],
returns: &[Ty::F64],
},
c_sig: None,
fn_list: &["fma"],
public: true,
},
NestedOp {
// `(f128, f128, f128) -> f128`
float_ty: FloatTy::F128,
rust_sig: Signature {
args: &[Ty::F128, Ty::F128, Ty::F128],
returns: &[Ty::F128],
},
c_sig: None,
fn_list: &["fmaf128"],
public: true,
},
NestedOp {
// `(f32) -> i32`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32],
returns: &[Ty::I32],
},
c_sig: None,
fn_list: &["ilogbf"],
public: true,
},
NestedOp {
// `(f64) -> i32`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64],
returns: &[Ty::I32],
},
c_sig: None,
fn_list: &["ilogb"],
public: true,
},
NestedOp {
// `(i32, f32) -> f32`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::I32, Ty::F32],
returns: &[Ty::F32],
},
c_sig: None,
fn_list: &["jnf", "ynf"],
public: true,
},
NestedOp {
// `(i32, f64) -> f64`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::I32, Ty::F64],
returns: &[Ty::F64],
},
c_sig: None,
fn_list: &["jn", "yn"],
public: true,
},
NestedOp {
// `(f16, i32) -> f16`
float_ty: FloatTy::F16,
rust_sig: Signature {
args: &[Ty::F16, Ty::I32],
returns: &[Ty::F16],
},
c_sig: None,
fn_list: &["ldexpf16", "scalbnf16"],
public: true,
},
NestedOp {
// `(f32, i32) -> f32`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32, Ty::I32],
returns: &[Ty::F32],
},
c_sig: None,
fn_list: &["ldexpf", "scalbnf"],
public: true,
},
NestedOp {
// `(f64, i64) -> f64`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64, Ty::I32],
returns: &[Ty::F64],
},
c_sig: None,
fn_list: &["ldexp", "scalbn"],
public: true,
},
NestedOp {
// `(f128, i32) -> f128`
float_ty: FloatTy::F128,
rust_sig: Signature {
args: &[Ty::F128, Ty::I32],
returns: &[Ty::F128],
},
c_sig: None,
fn_list: &["ldexpf128", "scalbnf128"],
public: true,
},
NestedOp {
// `(f32, &mut f32) -> f32` as `(f32) -> (f32, f32)`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32],
returns: &[Ty::F32, Ty::F32],
},
c_sig: Some(Signature {
args: &[Ty::F32, Ty::MutF32],
returns: &[Ty::F32],
}),
fn_list: &["modff"],
public: true,
},
NestedOp {
// `(f64, &mut f64) -> f64` as `(f64) -> (f64, f64)`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64],
returns: &[Ty::F64, Ty::F64],
},
c_sig: Some(Signature {
args: &[Ty::F64, Ty::MutF64],
returns: &[Ty::F64],
}),
fn_list: &["modf"],
public: true,
},
NestedOp {
// `(f32, &mut c_int) -> f32` as `(f32) -> (f32, i32)`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32],
returns: &[Ty::F32, Ty::I32],
},
c_sig: Some(Signature {
args: &[Ty::F32, Ty::MutCInt],
returns: &[Ty::F32],
}),
fn_list: &["frexpf", "lgammaf_r"],
public: true,
},
NestedOp {
// `(f64, &mut c_int) -> f64` as `(f64) -> (f64, i32)`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64],
returns: &[Ty::F64, Ty::I32],
},
c_sig: Some(Signature {
args: &[Ty::F64, Ty::MutCInt],
returns: &[Ty::F64],
}),
fn_list: &["frexp", "lgamma_r"],
public: true,
},
NestedOp {
// `(f32, f32, &mut c_int) -> f32` as `(f32, f32) -> (f32, i32)`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32, Ty::F32],
returns: &[Ty::F32, Ty::I32],
},
c_sig: Some(Signature {
args: &[Ty::F32, Ty::F32, Ty::MutCInt],
returns: &[Ty::F32],
}),
fn_list: &["remquof"],
public: true,
},
NestedOp {
// `(f64, f64, &mut c_int) -> f64` as `(f64, f64) -> (f64, i32)`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64, Ty::F64],
returns: &[Ty::F64, Ty::I32],
},
c_sig: Some(Signature {
args: &[Ty::F64, Ty::F64, Ty::MutCInt],
returns: &[Ty::F64],
}),
fn_list: &["remquo"],
public: true,
},
NestedOp {
// `(f32, &mut f32, &mut f32)` as `(f32) -> (f32, f32)`
float_ty: FloatTy::F32,
rust_sig: Signature {
args: &[Ty::F32],
returns: &[Ty::F32, Ty::F32],
},
c_sig: Some(Signature {
args: &[Ty::F32, Ty::MutF32, Ty::MutF32],
returns: &[],
}),
fn_list: &["sincosf"],
public: true,
},
NestedOp {
// `(f64, &mut f64, &mut f64)` as `(f64) -> (f64, f64)`
float_ty: FloatTy::F64,
rust_sig: Signature {
args: &[Ty::F64],
returns: &[Ty::F64, Ty::F64],
},
c_sig: Some(Signature {
args: &[Ty::F64, Ty::MutF64, Ty::MutF64],
returns: &[],
}),
fn_list: &["sincos"],
public: true,
},
];
/// A type used in a function signature.
#[allow(dead_code)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Ty {
F16,
F32,
F64,
F128,
I32,
CInt,
MutF16,
MutF32,
MutF64,
MutF128,
MutI32,
MutCInt,
}
/// A subset of [`Ty`] representing only floats.
#[allow(dead_code)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum FloatTy {
F16,
F32,
F64,
F128,
}
impl fmt::Display for Ty {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Ty::F16 => "f16",
Ty::F32 => "f32",
Ty::F64 => "f64",
Ty::F128 => "f128",
Ty::I32 => "i32",
Ty::CInt => "::core::ffi::c_int",
Ty::MutF16 => "&mut f16",
Ty::MutF32 => "&mut f32",
Ty::MutF64 => "&mut f64",
Ty::MutF128 => "&mut f128",
Ty::MutI32 => "&mut i32",
Ty::MutCInt => "&mut ::core::ffi::c_int",
};
f.write_str(s)
}
}
impl fmt::Display for FloatTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
FloatTy::F16 => "f16",
FloatTy::F32 => "f32",
FloatTy::F64 => "f64",
FloatTy::F128 => "f128",
};
f.write_str(s)
}
}
/// Representation of e.g. `(f32, f32) -> f32`
#[derive(Debug, Clone)]
pub struct Signature {
pub args: &'static [Ty],
pub returns: &'static [Ty],
}
/// Combined information about a function implementation.
#[derive(Debug, Clone)]
pub struct MathOpInfo {
pub name: &'static str,
pub float_ty: FloatTy,
/// Function signature for C implementations
pub c_sig: Signature,
/// Function signature for Rust implementations
pub rust_sig: Signature,
/// True if part of libm's public API
pub public: bool,
}
/// A flat representation of `ALL_FUNCTIONS`.
pub static ALL_OPERATIONS: LazyLock<Vec<MathOpInfo>> = LazyLock::new(|| {
let mut ret = Vec::new();
for op in ALL_OPERATIONS_NESTED {
let fn_names = op.fn_list;
for name in fn_names {
let api = MathOpInfo {
name,
float_ty: op.float_ty,
rust_sig: op.rust_sig.clone(),
c_sig: op.c_sig.clone().unwrap_or_else(|| op.rust_sig.clone()),
public: op.public,
};
ret.push(api);
}
if !fn_names.is_sorted() {
let mut sorted = (*fn_names).to_owned();
sorted.sort_unstable();
panic!("names list is not sorted: {fn_names:?}\nExpected: {sorted:?}");
}
}
ret.sort_by_key(|item| item.name);
ret
});