Skip to content

Commit b6f46a7

Browse files
rothmichaelsclaude
andcommitted
fix: enable runtime usage of inverse function by using compile-time unit extraction
Replace runtime unit access (q.unit) with compile-time type extraction (get_unit(R)) in the inverse function implementation. This prevents the function from becoming an immediate function when consteval unit operators are used, allowing inverse to work with runtime variables. Key changes: - math.h: Use get_unit(R) instead of q.unit in both code paths - test: Add comprehensive runtime inverse tests This surgical fix preserves maximum compile-time optimization while enabling DSP applications that need runtime inverse calculations. Fixes compilation error with Clang: "call to immediate function 'inverse' is not a constant expression" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a6a5b61 commit b6f46a7

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

src/core/include/mp-units/math.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,12 +414,12 @@ template<Unit auto To, auto R, typename Rep>
414414
{
415415
#if MP_UNITS_API_NATURAL_UNITS
416416
if constexpr (!MP_UNITS_ASSOCIATED_UNIT<MP_UNITS_REMOVE_CONST(decltype(To))>)
417-
return (representation_values<Rep>::one() * one).force_in(To * q.unit) / q;
417+
return (representation_values<Rep>::one() * one).force_in(To * get_unit(R)) / q;
418418
else
419419
#endif
420420
{
421421
constexpr QuantitySpec auto qs = get_quantity_spec(To) * quantity<R, Rep>::quantity_spec;
422-
return qs(representation_values<Rep>::one() * one).force_in(To * q.unit) / q;
422+
return qs(representation_values<Rep>::one() * one).force_in(To * get_unit(R)) / q;
423423
}
424424
}
425425

test/runtime/math_test.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,4 +589,31 @@ TEST_CASE("math operations", "[math]")
589589
REQUIRE_THAT(atan2(1. * isq::length[km], 1000. * isq::length[m]), AlmostEquals(45. * angle[deg]));
590590
}
591591
}
592+
593+
SECTION("inverse functions")
594+
{
595+
SECTION("inverse of time quantity returns frequency")
596+
{
597+
auto period = 2.0 * isq::time[s];
598+
auto frequency = inverse<si::hertz>(period);
599+
REQUIRE(frequency == 0.5 * isq::frequency[Hz]);
600+
}
601+
602+
SECTION("inverse works with runtime values")
603+
{
604+
// Test the specific case that fails with consteval
605+
double runtime_value = 3.0;
606+
auto period = runtime_value * isq::time[s];
607+
auto frequency = inverse<si::hertz>(period);
608+
auto expected = (1.0 / 3.0) * isq::frequency[Hz];
609+
REQUIRE_THAT(frequency, AlmostEquals(expected));
610+
}
611+
612+
SECTION("inverse with different input units")
613+
{
614+
auto period_ms = 500.0 * isq::time[ms];
615+
auto frequency = inverse<si::hertz>(period_ms);
616+
REQUIRE(frequency == 2.0 * isq::frequency[Hz]);
617+
}
618+
}
592619
}

0 commit comments

Comments
 (0)