From: <man...@us...> - 2013-05-22 15:56:27
|
Revision: 2170 http://sourceforge.net/p/modplug/code/2170 Author: manxorist Date: 2013-05-22 15:56:18 +0000 (Wed, 22 May 2013) Log Message: ----------- [Ref] Add saturate_cast<T>(Tsrc) add start using it. Modified Paths: -------------- trunk/OpenMPT/common/misc_util.h trunk/OpenMPT/mptrack/test/test.cpp trunk/OpenMPT/soundlib/ITTools.cpp trunk/OpenMPT/soundlib/XMTools.cpp Modified: trunk/OpenMPT/common/misc_util.h =================================================================== --- trunk/OpenMPT/common/misc_util.h 2013-05-21 23:42:33 UTC (rev 2169) +++ trunk/OpenMPT/common/misc_util.h 2013-05-22 15:56:18 UTC (rev 2170) @@ -94,6 +94,50 @@ } +namespace mpt { + +// Saturate the value of src to the domain of Tdst +template <typename Tdst, typename Tsrc> +inline Tdst saturate_cast(Tsrc src) +//------------------------------------- +{ + // This code tries not only to obviously avoid overflows but also to avoid signed/unsigned comparison warnings and type truncation warnings (which in fact would be safe here) by explicit casting. + STATIC_ASSERT(std::numeric_limits<Tdst>::is_integer); + STATIC_ASSERT(std::numeric_limits<Tsrc>::is_integer); + if(std::numeric_limits<Tdst>::is_signed && std::numeric_limits<Tsrc>::is_signed) + { + if(sizeof(Tdst) >= sizeof(Tsrc)) + { + return static_cast<Tdst>(src); + } + return static_cast<Tdst>(std::max<Tsrc>(std::numeric_limits<Tdst>::min(), std::min<Tsrc>(src, std::numeric_limits<Tdst>::max()))); + } else if(!std::numeric_limits<Tdst>::is_signed && !std::numeric_limits<Tsrc>::is_signed) + { + if(sizeof(Tdst) >= sizeof(Tsrc)) + { + return static_cast<Tdst>(src); + } + return static_cast<Tdst>(std::min<Tsrc>(src, std::numeric_limits<Tdst>::max())); + } else if(std::numeric_limits<Tdst>::is_signed && !std::numeric_limits<Tsrc>::is_signed) + { + if(sizeof(Tdst) >= sizeof(Tsrc)) + { + return static_cast<Tdst>(std::min<Tsrc>(src, static_cast<Tsrc>(std::numeric_limits<Tdst>::max()))); + } + return static_cast<Tdst>(std::max<Tsrc>(std::numeric_limits<Tdst>::min(), std::min<Tsrc>(src, std::numeric_limits<Tdst>::max()))); + } else // Tdst unsigned, Tsrc signed + { + if(sizeof(Tdst) >= sizeof(Tsrc)) + { + return static_cast<Tdst>(std::max<Tsrc>(0, src)); + } + return static_cast<Tdst>(std::max<Tsrc>(0, std::min<Tsrc>(src, std::numeric_limits<Tdst>::max()))); + } +} + +} // namespace mpt + + // Limits 'val' to given range. If 'val' is less than 'lowerLimit', 'val' is set to value 'lowerLimit'. // Similarly if 'val' is greater than 'upperLimit', 'val' is set to value 'upperLimit'. // If 'lowerLimit' > 'upperLimit', 'val' won't be modified. @@ -133,7 +177,7 @@ #define CLAMP(number, low, high) MIN(high, MAX(low, number)) #endif - + #ifdef MODPLUG_TRACKER LPCCH LoadResource(LPCTSTR lpName, LPCTSTR lpType, LPCCH& pData, size_t& nSize, HGLOBAL& hglob); std::string GetErrorMessage(DWORD nErrorCode); Modified: trunk/OpenMPT/mptrack/test/test.cpp =================================================================== --- trunk/OpenMPT/mptrack/test/test.cpp 2013-05-21 23:42:33 UTC (rev 2169) +++ trunk/OpenMPT/mptrack/test/test.cpp 2013-05-22 15:56:18 UTC (rev 2170) @@ -255,6 +255,38 @@ VERIFY_EQUAL( Util::Round<int8>(110.1), 110 ); VERIFY_EQUAL( Util::Round<int8>(-110.1), -110 ); + // trivials + VERIFY_EQUAL( mpt::saturate_cast<int>(-1), -1 ); + VERIFY_EQUAL( mpt::saturate_cast<int>(0), 0 ); + VERIFY_EQUAL( mpt::saturate_cast<int>(1), 1 ); + VERIFY_EQUAL( mpt::saturate_cast<int>(std::numeric_limits<int>::min()), std::numeric_limits<int>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<int>(std::numeric_limits<int>::max()), std::numeric_limits<int>::max() ); + + // signed / unsigned + VERIFY_EQUAL( mpt::saturate_cast<int16>(std::numeric_limits<uint16>::min()), std::numeric_limits<uint16>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<int16>(std::numeric_limits<uint16>::max()), std::numeric_limits<int16>::max() ); + VERIFY_EQUAL( mpt::saturate_cast<int32>(std::numeric_limits<uint32>::min()), std::numeric_limits<uint32>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<int32>(std::numeric_limits<uint32>::max()), std::numeric_limits<int32>::max() ); + VERIFY_EQUAL( mpt::saturate_cast<int64>(std::numeric_limits<uint64>::min()), std::numeric_limits<uint64>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<int64>(std::numeric_limits<uint64>::max()), std::numeric_limits<int64>::max() ); + VERIFY_EQUAL( mpt::saturate_cast<uint16>(std::numeric_limits<int16>::min()), std::numeric_limits<uint16>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<uint16>(std::numeric_limits<int16>::max()), std::numeric_limits<int16>::max() ); + VERIFY_EQUAL( mpt::saturate_cast<uint32>(std::numeric_limits<int32>::min()), std::numeric_limits<uint32>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<uint32>(std::numeric_limits<int32>::max()), std::numeric_limits<int32>::max() ); + VERIFY_EQUAL( mpt::saturate_cast<uint64>(std::numeric_limits<int64>::min()), std::numeric_limits<uint64>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<uint64>(std::numeric_limits<int64>::max()), std::numeric_limits<int64>::max() ); + + // overflow + VERIFY_EQUAL( mpt::saturate_cast<int16>(std::numeric_limits<int16>::min() - 1), std::numeric_limits<int16>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<int16>(std::numeric_limits<int16>::max() + 1), std::numeric_limits<int16>::max() ); + VERIFY_EQUAL( mpt::saturate_cast<int32>(std::numeric_limits<int32>::min() - int64(1)), std::numeric_limits<int32>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<int32>(std::numeric_limits<int32>::max() + int64(1)), std::numeric_limits<int32>::max() ); + + VERIFY_EQUAL( mpt::saturate_cast<uint16>(std::numeric_limits<int16>::min() - 1), std::numeric_limits<uint16>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<uint16>(std::numeric_limits<int16>::max() + 1), (uint16)std::numeric_limits<int16>::max() + 1 ); + VERIFY_EQUAL( mpt::saturate_cast<uint32>(std::numeric_limits<int32>::min() - int64(1)), std::numeric_limits<uint32>::min() ); + VERIFY_EQUAL( mpt::saturate_cast<uint32>(std::numeric_limits<int32>::max() + int64(1)), (uint32)std::numeric_limits<int32>::max() + 1 ); + // These should fail to compile //Util::Round<std::string>(1.0); //Util::Round<int64>(1.0); Modified: trunk/OpenMPT/soundlib/ITTools.cpp =================================================================== --- trunk/OpenMPT/soundlib/ITTools.cpp 2013-05-21 23:42:33 UTC (rev 2169) +++ trunk/OpenMPT/soundlib/ITTools.cpp 2013-05-22 15:56:18 UTC (rev 2170) @@ -521,11 +521,11 @@ C5Speed = mptSmp.nC5Speed ? mptSmp.nC5Speed : 8363; // Size and loops - length = std::min(mptSmp.nLength, (SmpLength)uint32_max); - loopbegin = std::min(mptSmp.nLoopStart, (SmpLength)uint32_max); - loopend = std::min(mptSmp.nLoopEnd, (SmpLength)uint32_max); - susloopbegin = std::min(mptSmp.nSustainStart, (SmpLength)uint32_max); - susloopend = std::min(mptSmp.nSustainEnd, (SmpLength)uint32_max); + length = mpt::saturate_cast<uint32>(mptSmp.nLength); + loopbegin = mpt::saturate_cast<uint32>(mptSmp.nLoopStart); + loopend = mpt::saturate_cast<uint32>(mptSmp.nLoopEnd); + susloopbegin = mpt::saturate_cast<uint32>(mptSmp.nSustainStart); + susloopend = mpt::saturate_cast<uint32>(mptSmp.nSustainEnd); // Auto Vibrato settings static const uint8 autovibxm2it[8] = { 0, 2, 4, 1, 3, 0, 0, 0 }; // OpenMPT VibratoType -> IT Vibrato Modified: trunk/OpenMPT/soundlib/XMTools.cpp =================================================================== --- trunk/OpenMPT/soundlib/XMTools.cpp 2013-05-21 23:42:33 UTC (rev 2169) +++ trunk/OpenMPT/soundlib/XMTools.cpp 2013-05-22 15:56:18 UTC (rev 2170) @@ -392,9 +392,9 @@ } // Sample Length and Loops - length = std::min(mptSmp.nLength, (SmpLength)uint32_max); - loopStart = std::min(mptSmp.nLoopStart, (SmpLength)uint32_max); - loopLength = std::min(mptSmp.nLoopEnd - mptSmp.nLoopStart, (SmpLength)uint32_max); + length = mpt::saturate_cast<uint32>(mptSmp.nLength); + loopStart = mpt::saturate_cast<uint32>(mptSmp.nLoopStart); + loopLength = mpt::saturate_cast<uint32>(mptSmp.nLoopEnd - mptSmp.nLoopStart); if(mptSmp.uFlags[CHN_16BIT]) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |