Skip to content

Templatize ApproxEqualFailure and assert_approx_equal#51

Merged
thetic merged 4 commits into
mainfrom
float-approx-no-double-promotion
Apr 14, 2026
Merged

Templatize ApproxEqualFailure and assert_approx_equal#51
thetic merged 4 commits into
mainfrom
float-approx-no-double-promotion

Conversation

@thetic
Copy link
Copy Markdown
Owner

@thetic thetic commented Apr 14, 2026

Description

CHECK_APPROX(1.0f, 1.5f, 0.1f) was silently promoting all three float values to double on the failure-reporting path (passed to assert_approx_equal(double, double, double)). Similarly, CHECK_APPROX(110, 111, 10) was casting integers to double. This PR fixes the root cause by making the failure type itself generic.

ApproxEqualFailure<T> is now a class template. Its constructor:

  • formats values via string_from(T) (type-correct for int, float, double, etc.)
  • detects NaN using the IEEE 754 self-comparison trick (v != v), the same approach already used in approx_equal<T>
  • carries no double anywhere in its interface

Shell::assert_approx_equal becomes a non-virtual template method that constructs ApproxEqualFailure<T> directly. The virtual seam for observing failures is add_failure, as with every other assertion.

check_approx<T> now passes its T values straight through — no cast, no dispatch helper, no overload ambiguity.

As a secondary change, CHECK_EQUAL with float is explicitly covered by a passing test and a failing-message test (it was already correct, but untested).

Related Issues

Fixes # (issue number)

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I have written/updated documentation in docs/ for any user-facing changes.
  • My code follows the project's naming conventions (mu::tiny namespace, INCLUDED_MUTINY_ guards, mutiny_ C-prefix).
  • For new features, I have considered if a C-interface adapter (.h and .c.cpp) is required for parity.
  • I have reviewed the CONTRIBUTING.md file to ensure compliance with architectural guidelines.

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 14, 2026

Coverage Status

coverage: 98.953%. remained the same — float-approx-no-double-promotion into main

thetic added 4 commits April 13, 2026 19:22
Add ApproxEqualFailure(float, float, float) constructor and a virtual
assert_approx_equal(float, ...) overload so float values are never
implicitly promoted to double in the failure-reporting path.

Introduce check_approx_fail<T> as a dispatch template: the primary
form does static_cast<double> (making integral conversions explicit and
unambiguous), while the explicit float specialisation passes values
through as-is.  check_approx now delegates to check_approx_fail.

CHECK_EQUAL already handled float correctly via string_from(float).

Add FailureWithCHECK_EQUAL_Float and FloatsEqual{Expected,Actual,
Threshold}IsNaN tests to cover the new float paths.
ApproxEqualFailure becomes a class template ApproxEqualFailure<T>.
Its constructor uses string_from(T) for formatting and detects NaN via
the IEEE 754 self-comparison trick (v != v), the same approach used in
approx_equal — so no type-specific code, no hard-coded double, no
string matching.

Shell::assert_approx_equal becomes a non-virtual template method that
constructs ApproxEqualFailure<T> directly. check_approx<T> passes its
T values straight through, with no cast and no dispatch helper. The
virtual seam for overriding is add_failure, as with every other
assertion.
ApproxEqualFailure is a class template; explicit template argument
required in C++11/14 since CTAD is C++17-only. Also wrap long lines
to satisfy clang-format.
@thetic thetic force-pushed the float-approx-no-double-promotion branch from 792e49b to 26dd665 Compare April 14, 2026 02:23
@thetic thetic merged commit 18c2434 into main Apr 14, 2026
39 of 40 checks passed
@thetic thetic deleted the float-approx-no-double-promotion branch April 14, 2026 02:31
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

Successfully merging this pull request may close these issues.

2 participants