Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  libm_tests.rs   Sprache: unbekannt

 
#![cfg(all(not(feature = "std"), feature = "compact"))]

// These are adapted from libm, a port of musl libc's libm to Rust.
// libm can be found online [here](https://github.com/rust-lang/libm),
// and is similarly licensed under an Apache2.0/MIT license

use core::f64;
use minimal_lexical::libm;

#[test]
fn fabsf_sanity_test() {
    assert_eq!(libm::fabsf(-1.0), 1.0);
    assert_eq!(libm::fabsf(2.8), 2.8);
}

/// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
#[test]
fn fabsf_spec_test() {
    assert!(libm::fabsf(f32::NAN).is_nan());
    for f in [0.0, -0.0].iter().copied() {
        assert_eq!(libm::fabsf(f), 0.0);
    }
    for f in [f32::INFINITY, f32::NEG_INFINITY].iter().copied() {
        assert_eq!(libm::fabsf(f), f32::INFINITY);
    }
}

#[test]
fn sqrtf_sanity_test() {
    assert_eq!(libm::sqrtf(100.0), 10.0);
    assert_eq!(libm::sqrtf(4.0), 2.0);
}

/// The spec: https://en.cppreference.com/w/cpp/numeric/math/sqrt
#[test]
fn sqrtf_spec_test() {
    // Not Asserted: FE_INVALID exception is raised if argument is negative.
    assert!(libm::sqrtf(-1.0).is_nan());
    assert!(libm::sqrtf(f32::NAN).is_nan());
    for f in [0.0, -0.0, f32::INFINITY].iter().copied() {
        assert_eq!(libm::sqrtf(f), f);
    }
}

const POS_ZERO: &[f64] = &[0.0];
const NEG_ZERO: &[f64] = &[-0.0];
const POS_ONE: &[f64] = &[1.0];
const NEG_ONE: &[f64] = &[-1.0];
const POS_FLOATS: &[f64] = &[99.0 / 70.0, f64::consts::E, f64::consts::PI];
const NEG_FLOATS: &[f64] = &[-99.0 / 70.0, -f64::consts::E, -f64::consts::PI];
const POS_SMALL_FLOATS: &[f64] = &[(1.0 / 2.0), f64::MIN_POSITIVE, f64::EPSILON];
const NEG_SMALL_FLOATS: &[f64] = &[-(1.0 / 2.0), -f64::MIN_POSITIVE, -f64::EPSILON];
const POS_EVENS: &[f64] = &[2.0, 6.0, 8.0, 10.0, 22.0, 100.0, f64::MAX];
const NEG_EVENS: &[f64] = &[f64::MIN, -100.0, -22.0, -10.0, -8.0, -6.0, -2.0];
const POS_ODDS: &[f64] = &[3.0, 7.0];
const NEG_ODDS: &[f64] = &[-7.0, -3.0];
const NANS: &[f64] = &[f64::NAN];
const POS_INF: &[f64] = &[f64::INFINITY];
const NEG_INF: &[f64] = &[f64::NEG_INFINITY];

const ALL: &[&[f64]] = &[
    POS_ZERO,
    NEG_ZERO,
    NANS,
    NEG_SMALL_FLOATS,
    POS_SMALL_FLOATS,
    NEG_FLOATS,
    POS_FLOATS,
    NEG_EVENS,
    POS_EVENS,
    NEG_ODDS,
    POS_ODDS,
    NEG_INF,
    POS_INF,
    NEG_ONE,
    POS_ONE,
];
const POS: &[&[f64]] = &[POS_ZERO, POS_ODDS, POS_ONE, POS_FLOATS, POS_EVENS, POS_INF];
const NEG: &[&[f64]] = &[NEG_ZERO, NEG_ODDS, NEG_ONE, NEG_FLOATS, NEG_EVENS, NEG_INF];

fn powd(base: f64, exponent: f64, expected: f64) {
    let res = libm::powd(base, exponent);
    assert!(
        if expected.is_nan() {
            res.is_nan()
        } else {
            libm::powd(base, exponent) == expected
        },
        "{} ** {} was {} instead of {}",
        base,
        exponent,
        res,
        expected
    );
}

fn powd_test_sets_as_base(sets: &[&[f64]], exponent: f64, expected: f64) {
    sets.iter().for_each(|s| s.iter().for_each(|val| powd(*val, exponent, expected)));
}

fn powd_test_sets_as_exponent(base: f64, sets: &[&[f64]], expected: f64) {
    sets.iter().for_each(|s| s.iter().for_each(|val| powd(base, *val, expected)));
}

fn powd_test_sets(sets: &[&[f64]], computed: &dyn Fn(f64) -> f64, expected: &dyn Fn(f64) -> f64) {
    sets.iter().for_each(|s| {
        s.iter().for_each(|val| {
            let exp = expected(*val);
            let res = computed(*val);

            assert!(
                if exp.is_nan() {
                    res.is_nan()
                } else {
                    exp == res
                },
                "test for {} was {} instead of {}",
                val,
                res,
                exp
            );
        })
    });
}

#[test]
fn powd_zero_as_exponent() {
    powd_test_sets_as_base(ALL, 0.0, 1.0);
    powd_test_sets_as_base(ALL, -0.0, 1.0);
}

#[test]
fn powd_one_as_base() {
    powd_test_sets_as_exponent(1.0, ALL, 1.0);
}

#[test]
fn powd_nan_inputs() {
    // NAN as the base:
    // (NAN ^ anything *but 0* should be NAN)
    powd_test_sets_as_exponent(f64::NAN, &ALL[2..], f64::NAN);

    // NAN as the exponent:
    // (anything *but 1* ^ NAN should be NAN)
    powd_test_sets_as_base(&ALL[..(ALL.len() - 2)], f64::NAN, f64::NAN);
}

#[test]
fn powd_infinity_as_base() {
    // Positive Infinity as the base:
    // (+Infinity ^ positive anything but 0 and NAN should be +Infinity)
    powd_test_sets_as_exponent(f64::INFINITY, &POS[1..], f64::INFINITY);

    // (+Infinity ^ negative anything except 0 and NAN should be 0.0)
    powd_test_sets_as_exponent(f64::INFINITY, &NEG[1..], 0.0);

    // Negative Infinity as the base:
    // (-Infinity ^ positive odd ints should be -Infinity)
    powd_test_sets_as_exponent(f64::NEG_INFINITY, &[POS_ODDS], f64::NEG_INFINITY);

    // (-Infinity ^ anything but odd ints should be == -0 ^ (-anything))
    // We can lump in pos/neg odd ints here because they don't seem to
    // cause panics (div by zero) in release mode (I think).
    powd_test_sets(ALL, &|v: f64| libm::powd(f64::NEG_INFINITY, v), &|v: f64| libm::powd(-0.0, -v));
}

#[test]
fn infinity_as_exponent() {
    // Positive/Negative base greater than 1:
    // (pos/neg > 1 ^ Infinity should be Infinity - note this excludes NAN as the base)
    powd_test_sets_as_base(&ALL[5..(ALL.len() - 2)], f64::INFINITY, f64::INFINITY);

    // (pos/neg > 1 ^ -Infinity should be 0.0)
    powd_test_sets_as_base(&ALL[5..ALL.len() - 2], f64::NEG_INFINITY, 0.0);

    // Positive/Negative base less than 1:
    let base_below_one = &[POS_ZERO, NEG_ZERO, NEG_SMALL_FLOATS, POS_SMALL_FLOATS];

    // (pos/neg < 1 ^ Infinity should be 0.0 - this also excludes NAN as the base)
    powd_test_sets_as_base(base_below_one, f64::INFINITY, 0.0);

    // (pos/neg < 1 ^ -Infinity should be Infinity)
    powd_test_sets_as_base(base_below_one, f64::NEG_INFINITY, f64::INFINITY);

    // Positive/Negative 1 as the base:
    // (pos/neg 1 ^ Infinity should be 1)
    powd_test_sets_as_base(&[NEG_ONE, POS_ONE], f64::INFINITY, 1.0);

    // (pos/neg 1 ^ -Infinity should be 1)
    powd_test_sets_as_base(&[NEG_ONE, POS_ONE], f64::NEG_INFINITY, 1.0);
}

#[test]
fn powd_zero_as_base() {
    // Positive Zero as the base:
    // (+0 ^ anything positive but 0 and NAN should be +0)
    powd_test_sets_as_exponent(0.0, &POS[1..], 0.0);

    // (+0 ^ anything negative but 0 and NAN should be Infinity)
    // (this should panic because we're dividing by zero)
    powd_test_sets_as_exponent(0.0, &NEG[1..], f64::INFINITY);

    // Negative Zero as the base:
    // (-0 ^ anything positive but 0, NAN, and odd ints should be +0)
    powd_test_sets_as_exponent(-0.0, &POS[3..], 0.0);

    // (-0 ^ anything negative but 0, NAN, and odd ints should be Infinity)
    // (should panic because of divide by zero)
    powd_test_sets_as_exponent(-0.0, &NEG[3..], f64::INFINITY);

    // (-0 ^ positive odd ints should be -0)
    powd_test_sets_as_exponent(-0.0, &[POS_ODDS], -0.0);

    // (-0 ^ negative odd ints should be -Infinity)
    // (should panic because of divide by zero)
    powd_test_sets_as_exponent(-0.0, &[NEG_ODDS], f64::NEG_INFINITY);
}

#[test]
fn special_cases() {
    // One as the exponent:
    // (anything ^ 1 should be anything - i.e. the base)
    powd_test_sets(ALL, &|v: f64| libm::powd(v, 1.0), &|v: f64| v);

    // Negative One as the exponent:
    // (anything ^ -1 should be 1/anything)
    powd_test_sets(ALL, &|v: f64| libm::powd(v, -1.0), &|v: f64| 1.0 / v);

    // Factoring -1 out:
    // (negative anything ^ integer should be (-1 ^ integer) * (positive anything ^ integer))
    [POS_ZERO, NEG_ZERO, POS_ONE, NEG_ONE, POS_EVENS, NEG_EVENS].iter().for_each(|int_set| {
        int_set.iter().for_each(|int| {
            powd_test_sets(ALL, &|v: f64| libm::powd(-v, *int), &|v: f64| {
                libm::powd(-1.0, *int) * libm::powd(v, *int)
            });
        })
    });

    // Negative base (imaginary results):
    // (-anything except 0 and Infinity ^ non-integer should be NAN)
    NEG[1..(NEG.len() - 1)].iter().for_each(|set| {
        set.iter().for_each(|val| {
            powd_test_sets(&ALL[3..7], &|v: f64| libm::powd(*val, v), &|_| f64::NAN);
        })
    });
}

#[test]
fn normal_cases() {
    assert_eq!(libm::powd(2.0, 20.0), (1 << 20) as f64);
    assert_eq!(libm::powd(-1.0, 9.0), -1.0);
    assert!(libm::powd(-1.0, 2.2).is_nan());
    assert!(libm::powd(-1.0, -1.14).is_nan());
}

#[test]
fn fabsd_sanity_test() {
    assert_eq!(libm::fabsd(-1.0), 1.0);
    assert_eq!(libm::fabsd(2.8), 2.8);
}

/// The spec: https://en.cppreference.com/w/cpp/numeric/math/fabs
#[test]
fn fabsd_spec_test() {
    assert!(libm::fabsd(f64::NAN).is_nan());
    for f in [0.0, -0.0].iter().copied() {
        assert_eq!(libm::fabsd(f), 0.0);
    }
    for f in [f64::INFINITY, f64::NEG_INFINITY].iter().copied() {
        assert_eq!(libm::fabsd(f), f64::INFINITY);
    }
}

#[test]
fn sqrtd_sanity_test() {
    assert_eq!(libm::sqrtd(100.0), 10.0);
    assert_eq!(libm::sqrtd(4.0), 2.0);
}

/// The spec: https://en.cppreference.com/w/cpp/numeric/math/sqrt
#[test]
fn sqrtd_spec_test() {
    // Not Asserted: FE_INVALID exception is raised if argument is negative.
    assert!(libm::sqrtd(-1.0).is_nan());
    assert!(libm::sqrtd(f64::NAN).is_nan());
    for f in [0.0, -0.0, f64::INFINITY].iter().copied() {
        assert_eq!(libm::sqrtd(f), f);
    }
}

[ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge