Skip to content

Commit 9265d78

Browse files
authored
🐛 use fuzzy comparison for floating point in const evaluation equality check (#809)
## Description This PR fixes another small bug observed as part of #803, which only surfaced under macOS when using GCC as the compiler. Turns out that GitHub's CodeQL was right after all and exact equality checks on floating point values can come back to bite you. In this case, two computations of `std::tan(1.0)` resulted in values that were off by a single ULP. Although I am not 100% certain how this can even happen, this PR works around any such errors by using a fuzzy floating point comparison with an epsilon on the order of `10-12`. ## Checklist: <!--- This checklist serves as a reminder of a couple of things that ensure your pull request will be merged swiftly. --> - [x] The pull request only contains commits that are related to it. - [x] I have added appropriate tests and documentation. - [x] I have made sure that all CI jobs on GitHub pass. - [x] The pull request introduces no new warnings and follows the project's style guidelines.
2 parents cefedf2 + 32f0a47 commit 9265d78

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

include/mqt-core/ir/parsers/qasm3_parser/passes/ConstEvalPass.hpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
#include "ir/parsers/qasm3_parser/NestedEnvironment.hpp"
1717
#include "ir/parsers/qasm3_parser/Statement.hpp"
1818

19+
#include <cmath>
1920
#include <cstddef>
2021
#include <cstdint>
22+
#include <limits>
2123
#include <memory>
2224
#include <optional>
2325
#include <string>
@@ -65,7 +67,8 @@ struct ConstEvalValue {
6567
case ConstUint:
6668
return std::get<0>(value) == std::get<0>(rhs.value);
6769
case ConstFloat:
68-
return std::get<1>(value) == std::get<1>(rhs.value);
70+
return std::abs(std::get<1>(value) - std::get<1>(rhs.value)) <
71+
std::numeric_limits<double>::epsilon() * 1024;
6972
case ConstBool:
7073
return std::get<2>(value) == std::get<2>(rhs.value);
7174
}

test/ir/test_qfr_functionality.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -714,10 +714,10 @@ TEST_F(QFRFunctionality, addControlStandardOperation) {
714714
op.addControl(1);
715715
op.addControl(2);
716716
ASSERT_EQ(op.getNcontrols(), 2);
717-
const auto expectedControls = Controls{1, 2};
717+
const auto expectedControls = Controls{1U, 2U};
718718
EXPECT_EQ(op.getControls(), expectedControls);
719719
op.removeControl(1);
720-
const auto expectedControlsAfterRemove = Controls{2};
720+
const auto expectedControlsAfterRemove = Controls{2U};
721721
EXPECT_EQ(op.getControls(), expectedControlsAfterRemove);
722722
op.clearControls();
723723
EXPECT_EQ(op.getNcontrols(), 0);
@@ -735,10 +735,10 @@ TEST_F(QFRFunctionality, addControlSymbolicOperation) {
735735
op.addControl(2);
736736

737737
ASSERT_EQ(op.getNcontrols(), 2);
738-
auto expectedControls = Controls{1, 2};
738+
auto expectedControls = Controls{1U, 2U};
739739
EXPECT_EQ(op.getControls(), expectedControls);
740740
op.removeControl(1);
741-
auto expectedControlsAfterRemove = Controls{2};
741+
auto expectedControlsAfterRemove = Controls{2U};
742742
EXPECT_EQ(op.getControls(), expectedControlsAfterRemove);
743743
op.clearControls();
744744
EXPECT_EQ(op.getNcontrols(), 0);
@@ -757,10 +757,10 @@ TEST_F(QFRFunctionality, addControlClassicControlledOperation) {
757757
op.addControl(2);
758758

759759
ASSERT_EQ(op.getNcontrols(), 2);
760-
auto expectedControls = Controls{1, 2};
760+
auto expectedControls = Controls{1U, 2U};
761761
EXPECT_EQ(op.getControls(), expectedControls);
762762
op.removeControl(1);
763-
auto expectedControlsAfterRemove = Controls{2};
763+
auto expectedControlsAfterRemove = Controls{2U};
764764
EXPECT_EQ(op.getControls(), expectedControlsAfterRemove);
765765
op.clearControls();
766766
EXPECT_EQ(op.getNcontrols(), 0);

0 commit comments

Comments
 (0)