#![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] #![allow(clippy::unusual_byte_groupings)] // sometimes we group by sign_exp_sig pub mod domain; mod f8_impl; pub mod generate; #[cfg(feature = "build-mpfr")] pub mod mpfloat; mod num; pub mod op; mod precision; mod run_cfg; mod test_traits; use std::env; use std::fs::File; use std::io::Write; use std::path::PathBuf; use std::sync::LazyLock; use std::time::SystemTime; pub use f8_impl::{f8, hf8}; pub use libm::support::{Float, Int, IntTy, MinInt}; pub use num::{FloatExt, linear_ints, logspace}; pub use op::{ BaseName, FloatTy, Identifier, MathOp, OpCFn, OpCRet, OpFTy, OpRustArgs, OpRustFn, OpRustRet, Ty, }; pub use precision::{MaybeOverride, SpecialCase, default_ulp}; use run_cfg::extensive_max_iterations; pub use run_cfg::{ CheckBasis, CheckCtx, EXTENSIVE_ENV, GeneratorKind, bigint_fuzz_iteration_count, skip_extensive_test, }; pub use test_traits::{CheckOutput, Hex, TupleCall}; /// Result type for tests is usually from `anyhow`. Most times there is no success value to /// propagate. pub type TestResult = Result; /// True if `EMULATED` is set and nonempty. Used to determine how many iterations to run. pub const fn emulated() -> bool { match option_env!("EMULATED") { Some(s) if s.is_empty() => false, None => false, Some(_) => true, } } /// True if `CI` is set and nonempty. pub const fn ci() -> bool { match option_env!("CI") { Some(s) if s.is_empty() => false, None => false, Some(_) => true, } } /// Print to stderr and additionally log it to `target/test-log.txt`. This is useful for saving /// output that would otherwise be consumed by the test harness. pub fn test_log(s: &str) { // Handle to a file opened in append mode, unless a suitable path can't be determined. static OUTFILE: LazyLock> = LazyLock::new(|| { // If the target directory is overridden, use that environment variable. Otherwise, save // at the default path `{workspace_root}/target`. let target_dir = match env::var("CARGO_TARGET_DIR") { Ok(s) => PathBuf::from(s), Err(_) => { let Ok(x) = env::var("CARGO_MANIFEST_DIR") else { return None; }; PathBuf::from(x).join("../target") } }; let outfile = target_dir.join("test-log.txt"); let mut f = File::options() .create(true) .append(true) .open(outfile) .expect("failed to open logfile"); let now = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap(); writeln!(f, "\n\nTest run at {}", now.as_secs()).unwrap(); writeln!(f, "arch: {}", env::consts::ARCH).unwrap(); writeln!(f, "os: {}", env::consts::OS).unwrap(); writeln!(f, "bits: {}", usize::BITS).unwrap(); writeln!(f, "emulated: {}", emulated()).unwrap(); writeln!(f, "ci: {}", ci()).unwrap(); writeln!(f, "cargo features: {}", env!("CFG_CARGO_FEATURES")).unwrap(); writeln!(f, "opt level: {}", env!("CFG_OPT_LEVEL")).unwrap(); writeln!(f, "target features: {}", env!("CFG_TARGET_FEATURES")).unwrap(); writeln!(f, "extensive iterations {}", extensive_max_iterations()).unwrap(); Some(f) }); eprintln!("{s}"); if let Some(mut f) = OUTFILE.as_ref() { writeln!(f, "{s}").unwrap(); } }