diff --git a/v6/modules/math.cppm b/v6/modules/math.cppm index b27d0de..11f7b7f 100644 --- a/v6/modules/math.cppm +++ b/v6/modules/math.cppm @@ -207,6 +207,7 @@ export template return static_cast(difference); } } + /** * @ingroup Math * @brief Determines if two values are equal within a relative error. @@ -240,4 +241,45 @@ export [[nodiscard]] constexpr bool equals(std::floating_point auto p_value1, return relative_error < p_epsilon; } } + +/** + * @ingroup Math + * @brief Proportionally scale input value up to fill the desired output integer + * container. + * + * @tparam int_t - output integer storage to be filled with the proportional + * contents of p_value + * @tparam bit_width - width of the input value + * @param p_value - the number to scale to the size of the int_t container + * @return constexpr int_t - + */ +export template +[[nodiscard]] constexpr int_t upscale(int_t p_value) +{ + constexpr usize resultant_bit_width = sizeof(int_t) * CHAR_BIT; + static_assert(bit_width > 0 && bit_width <= resultant_bit_width, + "Bit width must be between 1 and 32"); + // If already 32 bits, return as-is + if constexpr (bit_width == resultant_bit_width) { + return p_value; + } + + // Create mask for the input bits + constexpr auto over_sized_mask = (1LL << bit_width) - 1LL; + constexpr auto mask = static_cast(over_sized_mask); + + // Calculate number of iterations needed (ceiling(32/bit_width) - 1) + constexpr auto iterations = + (resultant_bit_width + bit_width - 1) / bit_width - 1; + + // Place cleaned input value in MSB position + constexpr auto shift_distance = resultant_bit_width - bit_width; + int_t result = (p_value & mask) << shift_distance; + + // Replicate the pattern for the calculated number of iterations + for (auto i = 0U; i < iterations; ++i) { + result |= (result >> bit_width); + } + return result; +} } // namespace hal::inline v6 diff --git a/v6/modules/units.cppm b/v6/modules/units.cppm index dff04f0..c4af916 100644 --- a/v6/modules/units.cppm +++ b/v6/modules/units.cppm @@ -52,12 +52,10 @@ export [[nodiscard]] constexpr hal::u64 cycles_per( // hal::time_duration::period::num == 1 // hal::time_duration::period::den == 1,000,000 - auto const denominator = - static_cast(decltype(p_duration)::period::den); - auto const float_count = static_cast(p_duration.count()); - auto const source_hz = - static_cast(p_source.numerical_value_in(hertz::unit)); - auto const cycle_count = (float_count * source_hz) / denominator; + auto const denominator = decltype(p_duration)::period::den; + auto const count = p_duration.count(); + auto const source_hz = p_source.numerical_value_in(hertz::unit); + auto const cycle_count = (count * source_hz) / denominator; return static_cast(cycle_count); } diff --git a/v6/test_package/CMakeLists.txt b/v6/test_package/CMakeLists.txt index 5173449..5652dab 100644 --- a/v6/test_package/CMakeLists.txt +++ b/v6/test_package/CMakeLists.txt @@ -35,11 +35,6 @@ target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_23) target_compile_options(${PROJECT_NAME} PRIVATE -fno-rtti) target_link_libraries(${PROJECT_NAME} PRIVATE libhal::util) -if(NOT CMAKE_CROSSCOMPILING) - target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address) - target_link_options(${PROJECT_NAME} PRIVATE -g -fsanitize=address) -endif() - add_custom_target(copy_compile_commands ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/compile_commands.json diff --git a/v6/tests/units.test.cpp b/v6/tests/units.test.cpp index fac683c..5cebfaf 100644 --- a/v6/tests/units.test.cpp +++ b/v6/tests/units.test.cpp @@ -46,9 +46,7 @@ void units_test() expect(that % 192'000 == hal::cycles_per(12'000'000 * si::hertz, 16ms)); expect(that % 960'000'000 == hal::cycles_per(8'000'000 * si::hertz, 2min)); expect(that % 57'600'000 == hal::cycles_per(32'000 * si::hertz, 30min)); - // Should be 600'000'000'000 but due to floating point precision loss it - // cannot be represented - expect(that % 599'999'971'328 == + expect(that % 18'446'744'064'966'997'184ULL == hal::cycles_per(1'000'000'000 * si::hertz, 10min)); // Result of zero means that the time period is smaller than the