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

Support for slices? #58

Open
bluenote10 opened this issue Oct 6, 2020 · 4 comments
Open

Support for slices? #58

bluenote10 opened this issue Oct 6, 2020 · 4 comments

Comments

@bluenote10
Copy link

In data science use cases, the most frequent test is to assert approximate equality of entire float data vectors. For instance in Numpy based code, testing with assert_allclose is ubiquitous. I'm looking for the equivalent in Rust.

As far as I can see, the macros currently doesn't support slices. Is there an interest to support them?

@brendanzab
Copy link
Owner

brendanzab commented Oct 12, 2020

Yeah, this seems like it would be really useful! I'm pretty sure this should work, seeing as slices implement the approx traits? Perhaps the documentation should be improved?

@bluenote10
Copy link
Author

bluenote10 commented Oct 12, 2020

If they do, it would certainly help to mention it ;)

I concluded from the docs that they don't, and rolled my own (totally not configurable):

#[macro_export]
macro_rules! assert_allclose {
    ($a:expr, $b:expr) => {
        use approx::ulps_eq;
        assert_eq!(
            $a.len(),
            $b.len(),
            "Data lengths differ: {} != {}",
            $a.len(),
            $b.len()
        );
        for i in 0 .. $a.len() {
            assert!(
                ulps_eq!($a[i], $b[i], max_ulps = 7),
                "Values at index {} differ: {} != {}\na = {:?}\nb = {:?}",
                i,
                $a[i],
                $b[i],
                $a,
                $b
            );
        }
    };
}

This indeed looks like it should do the job, but in practice I'm getting:

image

What may be a bit of a problem with the trait based approach is that a failed assert probably cannot output information to explain why it failed -- which can be quite a time safer. I'm wondering if this could be solved in a combination with the great pretty assertion crate.

@brendanzab
Copy link
Owner

brendanzab commented Oct 13, 2020

Ahh - once we have const generics we can implement it for fixed size arrays. We could also do what the standard library used to do and implement the traits for fixed size arrays of length 0 to 32. In the mean time you might be able to do:

assert_abs_diff_eq!([1.0, 2.0, 3.0].as_ref(), [1.0, 2.0, 3.0].as_ref());

This converts both sides to `&[{float}].

@CGMossa
Copy link

CGMossa commented Mar 3, 2022

I ran into this today.
Your solution @brendanzab works! But I ended up writing this:

use approx::assert_abs_diff_eq;
    use std::fmt::Debug;

    fn array_assert_eq<A: approx::AbsDiffEq<A> + Debug, const N: usize>(a: [A; N], b: [A; N]) {
        a.into_iter()
            .zip_eq(b.into_iter())
            .for_each(|(x, y)| assert_abs_diff_eq!(x, y));
    }

which is super-bad, but it means that const-generics are present enough to support slices finally?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants