From: <sv...@op...> - 2024-12-17 09:49:38
|
Author: manx Date: Tue Dec 17 10:49:25 2024 New Revision: 22561 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=22561 Log: [Ref] mpt/base/saturate_round.hpp: Rename floating point variants of saturate_cast to saturate_trunc in order to make mpt::saturate_cast as broken as C++26 std::saturate_cast. [Ref] mpt/base/saturate_cast.hpp: Use C++26 saturate_cast if available. Modified: trunk/OpenMPT/misc/mptColor.cpp trunk/OpenMPT/mptrack/CImageListEx.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/ResizableDialog.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/plugins/MidiInOut.cpp trunk/OpenMPT/soundlib/Load_symmod.cpp trunk/OpenMPT/soundlib/SampleFormatSFZ.cpp trunk/OpenMPT/src/mpt/base/saturate_cast.hpp trunk/OpenMPT/src/mpt/base/saturate_round.hpp trunk/OpenMPT/src/mpt/base/tests/tests_base_saturate_cast.hpp trunk/OpenMPT/src/mpt/base/tests/tests_base_saturate_round.hpp trunk/OpenMPT/src/mpt/base/utility.hpp trunk/OpenMPT/src/openmpt/soundbase/SampleConvert.hpp trunk/OpenMPT/src/openmpt/soundbase/SampleConvertFixedPoint.hpp Modified: trunk/OpenMPT/misc/mptColor.cpp ============================================================================== --- trunk/OpenMPT/misc/mptColor.cpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/misc/mptColor.cpp Tue Dec 17 10:49:25 2024 (r22561) @@ -20,7 +20,7 @@ uint8 GetLuma(uint8 r, uint8 g, uint8 b) noexcept { - return mpt::saturate_cast<uint8>(r * 0.299f + g * 0.587f + b * 0.114f); + return mpt::saturate_trunc<uint8>(r * 0.299f + g * 0.587f + b * 0.114f); } Modified: trunk/OpenMPT/mptrack/CImageListEx.cpp ============================================================================== --- trunk/OpenMPT/mptrack/CImageListEx.cpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/mptrack/CImageListEx.cpp Tue Dec 17 10:49:25 2024 (r22561) @@ -46,9 +46,9 @@ auto hsv = mpt::Color::RGB{pixel->r / 255.0f, pixel->g / 255.0f, pixel->b / 255.0f}.ToHSV(); hsv.v = (1.0f - hsv.v) * (1.0f - hsv.s) + (hsv.v) * hsv.s; const auto rgb = hsv.ToRGB(); - pixel->r = mpt::saturate_cast<uint8>(rgb.r * 255.0f); - pixel->g = mpt::saturate_cast<uint8>(rgb.g * 255.0f); - pixel->b = mpt::saturate_cast<uint8>(rgb.b * 255.0f); + pixel->r = mpt::saturate_trunc<uint8>(rgb.r * 255.0f); + pixel->g = mpt::saturate_trunc<uint8>(rgb.g * 255.0f); + pixel->b = mpt::saturate_trunc<uint8>(rgb.b * 255.0f); } } } Modified: trunk/OpenMPT/mptrack/Mainfrm.h ============================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/mptrack/Mainfrm.h Tue Dec 17 10:49:25 2024 (r22561) @@ -283,7 +283,7 @@ void UpdateTree(CModDoc *pModDoc, UpdateHint hint, CObject *pHint = nullptr); void RefreshDlsBanks(); static CInputHandler *GetInputHandler(); - void SetElapsedTime(double t) { m_dwTimeSec = mpt::saturate_cast<samplecount_t>(t * 10.0); } + void SetElapsedTime(double t) { m_dwTimeSec = mpt::saturate_trunc<samplecount_t>(t * 10.0); } #if defined(MPT_ENABLE_UPDATE) bool ShowUpdateIndicator(const UpdateCheckResult &result, const CString &releaseVersion, const CString &infoURL, bool showHighlight); Modified: trunk/OpenMPT/mptrack/ResizableDialog.cpp ============================================================================== --- trunk/OpenMPT/mptrack/ResizableDialog.cpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/mptrack/ResizableDialog.cpp Tue Dec 17 10:49:25 2024 (r22561) @@ -119,15 +119,15 @@ CPoint move; if(item.moveSettings.IsHorizontal()) - move.x = mpt::saturate_cast<int>(ratioX * item.moveSettings.m_nXRatio); + move.x = mpt::saturate_trunc<int>(ratioX * item.moveSettings.m_nXRatio); if(item.moveSettings.IsVertical()) - move.y = mpt::saturate_cast<int>(ratioY * item.moveSettings.m_nYRatio); + move.y = mpt::saturate_trunc<int>(ratioY * item.moveSettings.m_nYRatio); CSize size; if(item.sizeSettings.IsHorizontal()) - size.cx = mpt::saturate_cast<int>(ratioX * item.sizeSettings.m_nXRatio); + size.cx = mpt::saturate_trunc<int>(ratioX * item.sizeSettings.m_nXRatio); if(item.sizeSettings.IsVertical()) - size.cy = mpt::saturate_cast<int>(ratioY * item.sizeSettings.m_nYRatio); + size.cy = mpt::saturate_trunc<int>(ratioY * item.sizeSettings.m_nYRatio); auto itemPoint = item.initialPoint + move; auto itemSize = item.initialSize + size; Modified: trunk/OpenMPT/mptrack/View_smp.cpp ============================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/mptrack/View_smp.cpp Tue Dec 17 10:49:25 2024 (r22561) @@ -296,7 +296,7 @@ m_timelineUnit = mpt::saturate_round<int>(std::log(static_cast<double>(timelineInterval)) / std::log(power)); if(m_timelineUnit < 1) m_timelineUnit = 0; - m_timelineUnit = mpt::saturate_cast<int>(std::pow(power, m_timelineUnit)); + m_timelineUnit = mpt::saturate_trunc<int>(std::pow(power, m_timelineUnit)); timelineInterval = std::max(1.0, std::round(timelineInterval / m_timelineUnit)) * m_timelineUnit; if(format == TimelineFormat::Seconds) timelineInterval *= sampleRate / 1000.0; Modified: trunk/OpenMPT/mptrack/plugins/MidiInOut.cpp ============================================================================== --- trunk/OpenMPT/mptrack/plugins/MidiInOut.cpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/mptrack/plugins/MidiInOut.cpp Tue Dec 17 10:49:25 2024 (r22561) @@ -444,7 +444,7 @@ if(m_sendTimingInfo && !m_positionChanged && m_SndFile.m_PlayState.m_ppqPosFract == 0.0) { // Send Song Position on every pattern change or start of new measure - uint16 ppq = mpt::saturate_cast<uint16>((m_SndFile.m_PlayState.m_ppqPosBeat + m_SndFile.m_PlayState.m_ppqPosFract) * 4.0); + uint16 ppq = mpt::saturate_trunc<uint16>((m_SndFile.m_PlayState.m_ppqPosBeat + m_SndFile.m_PlayState.m_ppqPosFract) * 4.0); if(ppq < 16384) { uint32 midiCode = MIDIEvents::SongPosition(ppq); @@ -574,7 +574,7 @@ if(m_sendTimingInfo && !m_SndFile.IsPaused()) { MidiSend(0xFC); // Stop - uint16 ppq = mpt::saturate_cast<uint16>((m_SndFile.m_PlayState.m_ppqPosBeat + m_SndFile.m_PlayState.m_ppqPosFract) * 4.0); + uint16 ppq = mpt::saturate_trunc<uint16>((m_SndFile.m_PlayState.m_ppqPosBeat + m_SndFile.m_PlayState.m_ppqPosFract) * 4.0); if(ppq < 16384) MidiSend(MIDIEvents::SongPosition(ppq)); MidiSend(0xFA); // Start Modified: trunk/OpenMPT/soundlib/Load_symmod.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_symmod.cpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/soundlib/Load_symmod.cpp Tue Dec 17 10:49:25 2024 (r22561) @@ -282,8 +282,8 @@ std::pair<SmpLength, SmpLength> ConvertLoop(const ModSample &mptSmp) const { const double loopScale = static_cast<double>(mptSmp.nLength) / (100 << 16); - const SmpLength start = mpt::saturate_cast<SmpLength>(loopScale * std::min(uint32(100 << 16), loopStart.get())); - const SmpLength length = mpt::saturate_cast<SmpLength>(loopScale * std::min(uint32(100 << 16), loopLen.get())); + const SmpLength start = mpt::saturate_trunc<SmpLength>(loopScale * std::min(uint32(100 << 16), loopStart.get())); + const SmpLength length = mpt::saturate_trunc<SmpLength>(loopScale * std::min(uint32(100 << 16), loopLen.get())); return {start, std::min(mptSmp.nLength - start, length)}; } }; @@ -670,8 +670,8 @@ loopLen = (loopLen << 16) + loopLenFine; const double loopScale = static_cast<double>(mptSmp.nLength) / (100 << 16); - loopStart = std::min(mptSmp.nLength, mpt::saturate_cast<SmpLength>(loopStart * loopScale)); - loopLen = std::min(mptSmp.nLength - loopStart, mpt::saturate_cast<SmpLength>(loopLen * loopScale)); + loopStart = std::min(mptSmp.nLength, mpt::saturate_trunc<SmpLength>(loopStart * loopScale)); + loopLen = std::min(mptSmp.nLength - loopStart, mpt::saturate_trunc<SmpLength>(loopLen * loopScale)); } else if(mptSmp.HasSampleData()) { // The order of operations here may seem weird as it reduces precision, but it's taken directly from the original assembly source (UpdateRecalcLoop) Modified: trunk/OpenMPT/soundlib/SampleFormatSFZ.cpp ============================================================================== --- trunk/OpenMPT/soundlib/SampleFormatSFZ.cpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/soundlib/SampleFormatSFZ.cpp Tue Dec 17 10:49:25 2024 (r22561) @@ -901,7 +901,7 @@ if(region.ampEnv.release > 0) { const double tickDuration = m_PlayState.m_nSamplesPerTick / static_cast<double>(GetSampleRate()); - pIns->nFadeOut = std::min(mpt::saturate_cast<uint32>(32768.0 * tickDuration / region.ampEnv.release), uint32(32767)); + pIns->nFadeOut = std::min(mpt::saturate_trunc<uint32>(32768.0 * tickDuration / region.ampEnv.release), uint32(32767)); if(GetType() == MOD_TYPE_IT) pIns->nFadeOut = std::min((pIns->nFadeOut + 16u) & ~31u, uint32(8192)); } Modified: trunk/OpenMPT/src/mpt/base/saturate_cast.hpp ============================================================================== --- trunk/OpenMPT/src/mpt/base/saturate_cast.hpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/src/mpt/base/saturate_cast.hpp Tue Dec 17 10:49:25 2024 (r22561) @@ -5,10 +5,14 @@ +#include "mpt/base/detect.hpp" #include "mpt/base/namespace.hpp" #include <algorithm> #include <limits> +#if MPT_CXX_AT_LEAST(26) +#include <numeric> +#endif @@ -16,6 +20,12 @@ inline namespace MPT_INLINE_NS { +#if MPT_CXX_AT_LEAST(26) + +using std::saturate_cast; + +#else + // Saturate the value of src to the domain of Tdst template <typename Tdst, typename Tsrc> constexpr Tdst saturate_cast(Tsrc src) noexcept { @@ -51,27 +61,7 @@ } } -template <typename Tdst> -constexpr Tdst saturate_cast(double src) { - if (src >= static_cast<double>(std::numeric_limits<Tdst>::max())) { - return std::numeric_limits<Tdst>::max(); - } - if (src <= static_cast<double>(std::numeric_limits<Tdst>::min())) { - return std::numeric_limits<Tdst>::min(); - } - return static_cast<Tdst>(src); -} - -template <typename Tdst> -constexpr Tdst saturate_cast(float src) { - if (src >= static_cast<float>(std::numeric_limits<Tdst>::max())) { - return std::numeric_limits<Tdst>::max(); - } - if (src <= static_cast<float>(std::numeric_limits<Tdst>::min())) { - return std::numeric_limits<Tdst>::min(); - } - return static_cast<Tdst>(src); -} +#endif } // namespace MPT_INLINE_NS Modified: trunk/OpenMPT/src/mpt/base/saturate_round.hpp ============================================================================== --- trunk/OpenMPT/src/mpt/base/saturate_round.hpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/src/mpt/base/saturate_round.hpp Tue Dec 17 10:49:25 2024 (r22561) @@ -8,7 +8,6 @@ #include "mpt/base/namespace.hpp" #include "mpt/base/math.hpp" -#include "mpt/base/saturate_cast.hpp" #include <limits> @@ -18,25 +17,49 @@ inline namespace MPT_INLINE_NS { + +template <typename Tdst> +constexpr Tdst saturate_trunc(double src) { + if (src >= static_cast<double>(std::numeric_limits<Tdst>::max())) { + return std::numeric_limits<Tdst>::max(); + } + if (src <= static_cast<double>(std::numeric_limits<Tdst>::min())) { + return std::numeric_limits<Tdst>::min(); + } + return static_cast<Tdst>(src); +} + +template <typename Tdst> +constexpr Tdst saturate_trunc(float src) { + if (src >= static_cast<float>(std::numeric_limits<Tdst>::max())) { + return std::numeric_limits<Tdst>::max(); + } + if (src <= static_cast<float>(std::numeric_limits<Tdst>::min())) { + return std::numeric_limits<Tdst>::min(); + } + return static_cast<Tdst>(src); +} + + // Rounds given double value to nearest integer value of type T. // Out-of-range values are saturated to the specified integer type's limits. template <typename T> inline T saturate_round(float val) { static_assert(std::numeric_limits<T>::is_integer); - return mpt::saturate_cast<T>(mpt::round(val)); + return mpt::saturate_trunc<T>(mpt::round(val)); } template <typename T> inline T saturate_round(double val) { static_assert(std::numeric_limits<T>::is_integer); - return mpt::saturate_cast<T>(mpt::round(val)); + return mpt::saturate_trunc<T>(mpt::round(val)); } template <typename T> inline T saturate_round(long double val) { static_assert(std::numeric_limits<T>::is_integer); - return mpt::saturate_cast<T>(mpt::round(val)); + return mpt::saturate_trunc<T>(mpt::round(val)); } Modified: trunk/OpenMPT/src/mpt/base/tests/tests_base_saturate_cast.hpp ============================================================================== --- trunk/OpenMPT/src/mpt/base/tests/tests_base_saturate_cast.hpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/src/mpt/base/tests/tests_base_saturate_cast.hpp Tue Dec 17 10:49:25 2024 (r22561) @@ -95,7 +95,6 @@ MPT_TEST_EXPECT_EQUAL(mpt::saturate_cast<int32>(std::numeric_limits<uint64>::max() - 1), std::numeric_limits<int32>::max()); - MPT_TEST_EXPECT_EQUAL(mpt::saturate_cast<uint32>(static_cast<double>(std::numeric_limits<int64>::max())), std::numeric_limits<uint32>::max()); } } // namespace saturate_cast Modified: trunk/OpenMPT/src/mpt/base/tests/tests_base_saturate_round.hpp ============================================================================== --- trunk/OpenMPT/src/mpt/base/tests/tests_base_saturate_round.hpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/src/mpt/base/tests/tests_base_saturate_round.hpp Tue Dec 17 10:49:25 2024 (r22561) @@ -34,6 +34,8 @@ #pragma clang diagnostic pop #endif { + MPT_TEST_EXPECT_EQUAL(mpt::saturate_trunc<uint32>(static_cast<double>(std::numeric_limits<int64>::max())), std::numeric_limits<uint32>::max()); + MPT_TEST_EXPECT_EQUAL(mpt::saturate_round<int32>(std::numeric_limits<int32>::max() + 0.1), std::numeric_limits<int32>::max()); MPT_TEST_EXPECT_EQUAL(mpt::saturate_round<int32>(std::numeric_limits<int32>::max() - 0.4), std::numeric_limits<int32>::max()); MPT_TEST_EXPECT_EQUAL(mpt::saturate_round<int32>(std::numeric_limits<int32>::min() + 0.1), std::numeric_limits<int32>::min()); Modified: trunk/OpenMPT/src/mpt/base/utility.hpp ============================================================================== --- trunk/OpenMPT/src/mpt/base/utility.hpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/src/mpt/base/utility.hpp Tue Dec 17 10:49:25 2024 (r22561) @@ -11,6 +11,7 @@ #if MPT_CXX_BEFORE(20) #include "mpt/base/saturate_cast.hpp" +#include "mpt/base/saturate_round.hpp" #endif #if MPT_CXX_BEFORE(23) && !MPT_COMPILER_MSVC && !MPT_COMPILER_GCC && !MPT_COMPILER_CLANG @@ -42,11 +43,30 @@ #else +namespace detail { + +template <typename Tdst, typename Tsrc> +constexpr Tdst saturate_cast(Tsrc src) noexcept { + return mpt::saturate_cast<Tdst>(src); +} + +template <typename Tdst> +constexpr Tdst saturate_cast(double src) { + return mpt::saturate_trunc<Tdst>(src); +} + +template <typename Tdst> +constexpr Tdst saturate_cast(float src) { + return mpt::saturate_trunc<Tdst>(src); +} + +} + // Returns true iff Tdst can represent the value val. // Use as if(mpt::in_range<uint8>(-1)). template <typename Tdst, typename Tsrc> constexpr bool in_range(Tsrc val) { - return (static_cast<Tsrc>(mpt::saturate_cast<Tdst>(val)) == val); + return (static_cast<Tsrc>(mpt::detail::saturate_cast<Tdst>(val)) == val); } #endif Modified: trunk/OpenMPT/src/openmpt/soundbase/SampleConvert.hpp ============================================================================== --- trunk/OpenMPT/src/openmpt/soundbase/SampleConvert.hpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/src/openmpt/soundbase/SampleConvert.hpp Tue Dec 17 10:49:25 2024 (r22561) @@ -10,6 +10,7 @@ #include "mpt/base/macros.hpp" #include "mpt/base/math.hpp" #include "mpt/base/saturate_cast.hpp" +#include "mpt/base/saturate_round.hpp" #include "openmpt/base/Int24.hpp" #include "openmpt/base/Types.hpp" #include "openmpt/soundbase/SampleConvert.hpp" @@ -566,7 +567,7 @@ { val = mpt::safe_clamp(val, -1.0f, 1.0f); val *= static_cast<float>(uint64(1) << 63); - return mpt::saturate_cast<int64>(SC::fastround(val)); + return mpt::saturate_trunc<int64>(SC::fastround(val)); } }; @@ -579,7 +580,7 @@ { val = std::clamp(val, -1.0, 1.0); val *= static_cast<double>(uint64(1) << 63); - return mpt::saturate_cast<int64>(SC::fastround(val)); + return mpt::saturate_trunc<int64>(SC::fastround(val)); } }; Modified: trunk/OpenMPT/src/openmpt/soundbase/SampleConvertFixedPoint.hpp ============================================================================== --- trunk/OpenMPT/src/openmpt/soundbase/SampleConvertFixedPoint.hpp Tue Dec 17 10:27:32 2024 (r22560) +++ trunk/OpenMPT/src/openmpt/soundbase/SampleConvertFixedPoint.hpp Tue Dec 17 10:49:25 2024 (r22561) @@ -232,7 +232,7 @@ { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1); val = mpt::sanitize_nan(val); - return mpt::saturate_cast<output_t>(SC::fastround(val * factor)); + return mpt::saturate_trunc<output_t>(SC::fastround(val * factor)); } }; @@ -251,7 +251,7 @@ { static_assert(fractionalBits >= 0 && fractionalBits <= sizeof(input_t) * 8 - 1); val = mpt::sanitize_nan(val); - return mpt::saturate_cast<output_t>(SC::fastround(val * factor)); + return mpt::saturate_trunc<output_t>(SC::fastround(val * factor)); } }; |