-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Compare floating point containers #760
Comments
I would like to second this request. Any thoughts on how to implement it? |
I once used something like this; not with Approx, but known expected values of any custom class work the same: auto expected = { Approx(1.), 2., 3., 4., ... }; // initializer_list<Approx>
CHECK(computed == std::vector<Approx>(expected)); I also wanted to avoid the construction of the temporary vector, so I wrote a function template comparing two sequences: template <typename C1, typename C2>
size_t count_differences(C1& c1, C2& c2);
CHECK(0 == count_differences(computed, expected)); |
For the time being I've resorted to a kind of workaround. I created the following two functions to be used wherever you want to check two vectors. (i.e. bool compareVectors(std::vector<double> a, std::vector<double> b) {
if (a.size() != b.size()) return false;
for (size_t i = 0; i < a.size(); i++) {
if (a[i] != Approx(b[i])) {
std::cout << a[i] << " Should == " << b[i] << std::endl;
return false;
}
}
return true;
}
bool compare2dVectors(std::vector<std::vector<double>> a,
std::vector<std::vector<double>> b) {
if (a.size() != b.size()) return false;
for (size_t i = 0; i < a.size(); i++) {
if (! compareVectors(a[i], b[i])) return false;
}
return true;
} That way you'll at least be able to see the name of the vector that failed, and the first values that differed. It's not the ideal solution, so I'm still hoping someone will be able to come up with something better, but I thought I'd at least share what I've come up with so far in case it helps somebody. |
I'd like this functionality for comparing vectors and matrices from the glm library. If this issue gets resolved, I hope that the solution is general enough to handle container types such as these as well, even if requires some work from the user to make it work for their particular containers. |
@tgnottingham I might at some point create a convenience wrapper that would use iterators to try and compare containers, but Catch already contains a generic mechanism for smarter assertions in matchers. |
I also had the problem especially in conjunction with the command line flag --success. The flag prints out every successful REQUIRE statement. When using REQUIRE inside of a loop over a vector of many elements this can lead to a long console output. I created this helper function for vectors of T: template <typename T>
void RequireVectorEquals(const vector<T>& a, const vector<T>& b,
T max_error = 0.000001) {
REQUIRE(a.size() == b.size());
const auto first_mismatch = std::mismatch(
a.begin(), a.end(), b.begin(), [max_error](T val_a, T val_b) {
return val_a == val_b || std::abs(val_a - val_b) < max_error;
});
if (first_mismatch.first != a.end()) {
FAIL("Difference at index " +
std::to_string(std::distance(a.begin(), first_mismatch.first)) +
" values=(" + std::to_string(*first_mismatch.first) + "," +
std::to_string(*first_mismatch.second) + ")");
}
} and this for arrays template <typename T>
void RequireArrayEquals(const T* a, const T* b, size_t len,
T max_error = 0.000001) {
size_t i = 0;
while (i < len) {
const auto val_a = a[i];
const auto val_b = b[i];
if (val_a == val_b || std::abs(val_a - val_b) < max_error) {
++i;
continue;
}
FAIL("Difference at index " + std::to_string(i) + " values=(" +
std::to_string(val_a) + "," + std::to_string(val_b) + ")");
return;
}
} |
This has been implemented in #1499 |
Will there be nice way to use Approx method for comparing floating point values stored in containers, e.g. std::vector, as it is for integral types?
For integral types I can write:
But for double value container I have to write loop for use Approx:
or make ugly looking comparison with std::equal:
The best it would be to do:
The text was updated successfully, but these errors were encountered: