diff --git a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt index 4d6a392ab2..101611c253 100644 --- a/examples/DemoRunner/Builds/Android/app/CMakeLists.txt +++ b/examples/DemoRunner/Builds/Android/app/CMakeLists.txt @@ -1018,6 +1018,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_core/maths/juce_Expression.cpp" "../../../../../modules/juce_core/maths/juce_Expression.h" "../../../../../modules/juce_core/maths/juce_MathsFunctions.h" + "../../../../../modules/juce_core/maths/juce_MathsFunctions_test.cpp" "../../../../../modules/juce_core/maths/juce_NormalisableRange.h" "../../../../../modules/juce_core/maths/juce_Random.cpp" "../../../../../modules/juce_core/maths/juce_Random.h" @@ -3075,6 +3076,7 @@ set_source_files_properties( "../../../../../modules/juce_core/maths/juce_Expression.cpp" "../../../../../modules/juce_core/maths/juce_Expression.h" "../../../../../modules/juce_core/maths/juce_MathsFunctions.h" + "../../../../../modules/juce_core/maths/juce_MathsFunctions_test.cpp" "../../../../../modules/juce_core/maths/juce_NormalisableRange.h" "../../../../../modules/juce_core/maths/juce_Random.cpp" "../../../../../modules/juce_core/maths/juce_Random.h" diff --git a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj index 8ee6b9d4f9..490890f14c 100644 --- a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj @@ -1316,6 +1316,9 @@ true + + true + true diff --git a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters index 4a99297aac..3e516cf817 100644 --- a/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters @@ -1930,6 +1930,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj index 4543b0a551..17060885e4 100644 --- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj @@ -1316,6 +1316,9 @@ true + + true + true diff --git a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters index 2f118afbfa..57d886986f 100644 --- a/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters @@ -1930,6 +1930,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj index 8b2054b1b9..cdfe1ccb5c 100644 --- a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj +++ b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj @@ -1316,6 +1316,9 @@ true + + true + true diff --git a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters index 0090613495..e93c1f373a 100644 --- a/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters +++ b/examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters @@ -1930,6 +1930,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt index 91ebd84ab0..786016a054 100644 --- a/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt +++ b/extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt @@ -894,6 +894,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_core/maths/juce_Expression.cpp" "../../../../../modules/juce_core/maths/juce_Expression.h" "../../../../../modules/juce_core/maths/juce_MathsFunctions.h" + "../../../../../modules/juce_core/maths/juce_MathsFunctions_test.cpp" "../../../../../modules/juce_core/maths/juce_NormalisableRange.h" "../../../../../modules/juce_core/maths/juce_Random.cpp" "../../../../../modules/juce_core/maths/juce_Random.h" @@ -2649,6 +2650,7 @@ set_source_files_properties( "../../../../../modules/juce_core/maths/juce_Expression.cpp" "../../../../../modules/juce_core/maths/juce_Expression.h" "../../../../../modules/juce_core/maths/juce_MathsFunctions.h" + "../../../../../modules/juce_core/maths/juce_MathsFunctions_test.cpp" "../../../../../modules/juce_core/maths/juce_NormalisableRange.h" "../../../../../modules/juce_core/maths/juce_Random.cpp" "../../../../../modules/juce_core/maths/juce_Random.h" diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj index 16a3054c71..dcf2ccbd15 100644 --- a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj +++ b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj @@ -1156,6 +1156,9 @@ true + + true + true diff --git a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters index 0c8a0e1ed8..3e89495e2b 100644 --- a/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters +++ b/extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters @@ -1639,6 +1639,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt index dcc9366d03..e2f90a4ed1 100644 --- a/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt +++ b/extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt @@ -927,6 +927,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_core/maths/juce_Expression.cpp" "../../../../../modules/juce_core/maths/juce_Expression.h" "../../../../../modules/juce_core/maths/juce_MathsFunctions.h" + "../../../../../modules/juce_core/maths/juce_MathsFunctions_test.cpp" "../../../../../modules/juce_core/maths/juce_NormalisableRange.h" "../../../../../modules/juce_core/maths/juce_Random.cpp" "../../../../../modules/juce_core/maths/juce_Random.h" @@ -2837,6 +2838,7 @@ set_source_files_properties( "../../../../../modules/juce_core/maths/juce_Expression.cpp" "../../../../../modules/juce_core/maths/juce_Expression.h" "../../../../../modules/juce_core/maths/juce_MathsFunctions.h" + "../../../../../modules/juce_core/maths/juce_MathsFunctions_test.cpp" "../../../../../modules/juce_core/maths/juce_NormalisableRange.h" "../../../../../modules/juce_core/maths/juce_Random.cpp" "../../../../../modules/juce_core/maths/juce_Random.h" diff --git a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj index 6b9b8868db..d5fc25189b 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj @@ -1164,6 +1164,9 @@ true + + true + true diff --git a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters index 4fcfcdf62c..21606bf9ae 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters @@ -1714,6 +1714,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj index 1e39fc5d10..fc660c3969 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj @@ -1164,6 +1164,9 @@ true + + true + true diff --git a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters index 2c0ff11d93..b377ad122b 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters @@ -1714,6 +1714,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj index c92f9b3be4..1ace548d2b 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj +++ b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj @@ -1164,6 +1164,9 @@ true + + true + true diff --git a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters index d6a55b0f33..1291e712dc 100644 --- a/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters +++ b/extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters @@ -1714,6 +1714,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj b/extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj index 99120550ae..8365f8a7ba 100644 --- a/extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj +++ b/extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj @@ -226,6 +226,9 @@ true + + true + true diff --git a/extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj.filters b/extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj.filters index 77902d1382..6967555eab 100644 --- a/extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj.filters +++ b/extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj.filters @@ -163,6 +163,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt index 14a8efabfe..827da1f1f1 100644 --- a/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt +++ b/extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt @@ -898,6 +898,7 @@ add_library( ${BINARY_NAME} "../../../../../modules/juce_core/maths/juce_Expression.cpp" "../../../../../modules/juce_core/maths/juce_Expression.h" "../../../../../modules/juce_core/maths/juce_MathsFunctions.h" + "../../../../../modules/juce_core/maths/juce_MathsFunctions_test.cpp" "../../../../../modules/juce_core/maths/juce_NormalisableRange.h" "../../../../../modules/juce_core/maths/juce_Random.cpp" "../../../../../modules/juce_core/maths/juce_Random.h" @@ -2733,6 +2734,7 @@ set_source_files_properties( "../../../../../modules/juce_core/maths/juce_Expression.cpp" "../../../../../modules/juce_core/maths/juce_Expression.h" "../../../../../modules/juce_core/maths/juce_MathsFunctions.h" + "../../../../../modules/juce_core/maths/juce_MathsFunctions_test.cpp" "../../../../../modules/juce_core/maths/juce_NormalisableRange.h" "../../../../../modules/juce_core/maths/juce_Random.cpp" "../../../../../modules/juce_core/maths/juce_Random.h" diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj index 3a31c059f6..eb75d0e7e8 100644 --- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj +++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj @@ -1156,6 +1156,9 @@ true + + true + true diff --git a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters index 910f7564c6..8f75cfd8a0 100644 --- a/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters +++ b/extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters @@ -1669,6 +1669,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj index 56236a5e16..703e635c97 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj @@ -362,6 +362,9 @@ true + + true + true diff --git a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters index b0fc221c32..259ebdcaca 100644 --- a/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters @@ -640,6 +640,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj index f36375c919..0444ca02e4 100644 --- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj @@ -362,6 +362,9 @@ true + + true + true diff --git a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters index bf6b52ad66..4a976f8376 100644 --- a/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters @@ -640,6 +640,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj index 151e70b76a..907655c3c1 100644 --- a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj +++ b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj @@ -362,6 +362,9 @@ true + + true + true diff --git a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters index 15c39f8c7e..663fe31f35 100644 --- a/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters +++ b/extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters @@ -640,6 +640,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj index 97955ae31e..e51eba141b 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj @@ -1172,6 +1172,9 @@ true + + true + true diff --git a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters index b7e10e429d..16bc7c745b 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -1738,6 +1738,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj index 74e020bb64..3e4e42ce35 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj @@ -1172,6 +1172,9 @@ true + + true + true diff --git a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters index 52c631f8f8..939d8d5fe2 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -1738,6 +1738,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj index 18f5f96ec4..cc21666e94 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj +++ b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj @@ -1172,6 +1172,9 @@ true + + true + true diff --git a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters index 635d74841f..bb7217c9ff 100644 --- a/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters +++ b/extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters @@ -1738,6 +1738,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj index 39f10c4446..7a4db94484 100644 --- a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj +++ b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj @@ -1155,6 +1155,9 @@ true + + true + true diff --git a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters index 43806d2f2f..4a13cce29d 100644 --- a/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters +++ b/extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters @@ -1666,6 +1666,9 @@ JUCE Modules\juce_core\maths + + JUCE Modules\juce_core\maths + JUCE Modules\juce_core\maths diff --git a/modules/juce_core/juce_core.cpp b/modules/juce_core/juce_core.cpp index 6ed8bd9c0e..788c74b027 100644 --- a/modules/juce_core/juce_core.cpp +++ b/modules/juce_core/juce_core.cpp @@ -276,8 +276,8 @@ //============================================================================== #if JUCE_UNIT_TESTS #include "containers/juce_HashMap_test.cpp" - #include "containers/juce_Optional_test.cpp" + #include "maths/juce_MathsFunctions_test.cpp" #include "misc/juce_EnumHelpers_test.cpp" #endif diff --git a/modules/juce_core/maths/juce_MathsFunctions.h b/modules/juce_core/maths/juce_MathsFunctions.h index f47ea1154c..186693af01 100644 --- a/modules/juce_core/maths/juce_MathsFunctions.h +++ b/modules/juce_core/maths/juce_MathsFunctions.h @@ -86,16 +86,112 @@ using uint32 = unsigned int; using ssize_t = pointer_sized_int; #endif -/** Returns true if the two numbers are approximately equal. This is useful for floating-point - and double comparisons. +//============================================================================== +/** Handy function for avoiding unused variables warning. */ +template +void ignoreUnused (Types&&...) noexcept {} + +/** Handy function for getting the number of elements in a simple const C array. + E.g. + @code + static int myArray[] = { 1, 2, 3 }; + + int numElements = numElementsInArray (myArray) // returns 3 + @endcode */ +template +constexpr int numElementsInArray (Type (&)[N]) noexcept { return N; } + +//============================================================================== +// Some useful maths functions that aren't always present with all compilers and build settings. + +/** Using juce_hypot is easier than dealing with the different types of hypot function + that are provided by the various platforms and compilers. */ template -bool approximatelyEqual (Type a, Type b) noexcept +Type juce_hypot (Type a, Type b) noexcept { - return std::abs (a - b) <= (std::numeric_limits::epsilon() * std::max (a, b)) - || std::abs (a - b) < std::numeric_limits::min(); + #if JUCE_MSVC + return static_cast (_hypot (a, b)); + #else + return static_cast (hypot (a, b)); + #endif } +#ifndef DOXYGEN +template <> +inline float juce_hypot (float a, float b) noexcept +{ + #if JUCE_MSVC + return _hypotf (a, b); + #else + return hypotf (a, b); + #endif +} +#endif + +//============================================================================== +/** Commonly used mathematical constants + + @tags{Core} +*/ +template +struct MathConstants +{ + /** A predefined value for Pi */ + static constexpr FloatType pi = static_cast (3.141592653589793238L); + + /** A predefined value for 2 * Pi */ + static constexpr FloatType twoPi = static_cast (2 * 3.141592653589793238L); + + /** A predefined value for Pi / 2 */ + static constexpr FloatType halfPi = static_cast (3.141592653589793238L / 2); + + /** A predefined value for Euler's number */ + static constexpr FloatType euler = static_cast (2.71828182845904523536L); + + /** A predefined value for sqrt(2) */ + static constexpr FloatType sqrt2 = static_cast (1.4142135623730950488L); +}; + +#ifndef DOXYGEN +/** A double-precision constant for pi. */ +[[deprecated ("This is deprecated in favour of MathConstants::pi.")]] +const constexpr double double_Pi = MathConstants::pi; + +/** A single-precision constant for pi. */ +[[deprecated ("This is deprecated in favour of MathConstants::pi.")]] +const constexpr float float_Pi = MathConstants::pi; +#endif + +/** Converts an angle in degrees to radians. */ +template +constexpr FloatType degreesToRadians (FloatType degrees) noexcept { return degrees * (MathConstants::pi / FloatType (180)); } + +/** Converts an angle in radians to degrees. */ +template +constexpr FloatType radiansToDegrees (FloatType radians) noexcept { return radians * (FloatType (180) / MathConstants::pi); } + +//============================================================================== +/** The isfinite() method seems to vary between platforms, so this is a + platform-independent function for it. +*/ +template +bool juce_isfinite (NumericType value) noexcept +{ + if constexpr (std::numeric_limits::has_infinity + || std::numeric_limits::has_quiet_NaN + || std::numeric_limits::has_signaling_NaN) + { + return std::isfinite (value); + } + else + { + ignoreUnused (value); + return true; + } +} + +//============================================================================== /** Equivalent to operator==, but suppresses float-equality warnings. This allows code to be explicit about float-equality checks that are known to have the correct @@ -109,6 +205,128 @@ constexpr bool exactlyEqual (Type a, Type b) JUCE_END_IGNORE_WARNINGS_GCC_LIKE } +/** A class encapsulating both relative and absolute tolerances for use in floating-point comparisons. + + @see approximatelyEqual, absoluteTolerance, relativeTolerance +*/ +template +class Tolerance +{ +public: + Tolerance() = default; + + /** Returns a copy of this Tolerance object with a new absolute tolerance. + + If you just need a Tolerance object with an absolute tolerance, it might be worth using the + absoluteTolerance() function. + + @see getAbsolute, absoluteTolerance + */ + [[nodiscard]] Tolerance withAbsolute (Type newAbsolute) + { + return withMember (*this, &Tolerance::absolute, std::abs (newAbsolute)); + } + + /** Returns a copy of this Tolerance object with a new relative tolerance. + + If you just need a Tolerance object with a relative tolerance, it might be worth using the + relativeTolerance() function. + + @see getRelative, relativeTolerance + */ + [[nodiscard]] Tolerance withRelative (Type newRelative) + { + return withMember (*this, &Tolerance::relative, std::abs (newRelative)); + } + + [[nodiscard]] Type getAbsolute() const { return absolute; } + [[nodiscard]] Type getRelative() const { return relative; } + +private: + Type absolute{}; + Type relative{}; +}; + +/** Returns a type deduced Tolerance object containing only an absolute tolerance. + + @see Tolerance::withAbsolute, approximatelyEqual + */ +template +static Tolerance absoluteTolerance (Type tolerance) +{ + return Tolerance{}.withAbsolute (tolerance); +} + +/** Returns a type deduced Tolerance object containing only a relative tolerance. + + @see Tolerance::withRelative, approximatelyEqual + */ +template +static Tolerance relativeTolerance (Type tolerance) +{ + return Tolerance{}.withRelative (tolerance); +} + + +/** Returns true if the two numbers are approximately equal. This is useful for floating-point + comparisons. + + If a and b are not floating-point types, returns a == b. + + If either a or b are not finite, returns exactlyEqual (a, b). + + The default absolute tolerance is equal to the minimum normal value. This ensures + differences that are subnormal are always considered equal. It is highly recommend this + value is reviewed depending on the calculation being carried out. In general specifying an + absolute value is useful when considering values close to zero. For example you might + expect sin(pi) to return 0, but what it actually returns is close to the error of the value pi. + Therefore, in this example it might be better to set the absolute tolerance to sin(pi). + + The default relative tolerance is equal to the machine epsilon which is the difference between + 1.0 and the next floating-point value that can be represented by Type. In most cases this value + is probably reasonable. This value is multiplied by the largest absolute value of a and b so as + to scale relatively according to the input parameters. For example, specifying a relative value + of 0.05 will ensure values return equal if the difference between them is less than or equal to + 5% of the larger of the two absolute values. + + @param tolerance An object that represents both absolute and relative tolerances + when evaluating if a and b are equal. + + @see exactlyEqual +*/ +template +constexpr bool approximatelyEqual (Type a, Type b, + Tolerance tolerance = Tolerance{} + .withAbsolute (std::numeric_limits::min()) + .withRelative (std::numeric_limits::epsilon())) +{ + if constexpr (! std::is_floating_point_v) + return a == b; + + if (! (juce_isfinite (a) && juce_isfinite (b))) + return exactlyEqual (a, b); + + const auto diff = std::abs (a - b); + + return diff <= tolerance.getAbsolute() + || diff <= tolerance.getRelative() * std::max (std::abs (a), std::abs (b)); +} + +//============================================================================== +/** Returns the next representable value by FloatType in the direction of the largest representable value. */ +template +FloatType nextFloatUp (FloatType value) noexcept +{ + return std::nextafter (value, std::numeric_limits::max()); +} + +/** Returns the next representable value by FloatType in the direction of the lowest representable value. */ +template +FloatType nextFloatDown (FloatType value) noexcept +{ + return std::nextafter (value, std::numeric_limits::lowest()); +} + //============================================================================== // Some indispensable min/max functions @@ -340,122 +558,6 @@ bool isWithin (Type a, Type b, Type tolerance) noexcept return std::abs (a - b) <= tolerance; } -//============================================================================== -/** Handy function for avoiding unused variables warning. */ -template -void ignoreUnused (Types&&...) noexcept {} - -/** Handy function for getting the number of elements in a simple const C array. - E.g. - @code - static int myArray[] = { 1, 2, 3 }; - - int numElements = numElementsInArray (myArray) // returns 3 - @endcode -*/ -template -constexpr int numElementsInArray (Type (&)[N]) noexcept { return N; } - -//============================================================================== -// Some useful maths functions that aren't always present with all compilers and build settings. - -/** Using juce_hypot is easier than dealing with the different types of hypot function - that are provided by the various platforms and compilers. */ -template -Type juce_hypot (Type a, Type b) noexcept -{ - #if JUCE_MSVC - return static_cast (_hypot (a, b)); - #else - return static_cast (hypot (a, b)); - #endif -} - -#ifndef DOXYGEN -template <> -inline float juce_hypot (float a, float b) noexcept -{ - #if JUCE_MSVC - return _hypotf (a, b); - #else - return hypotf (a, b); - #endif -} -#endif - -//============================================================================== -/** Commonly used mathematical constants - - @tags{Core} -*/ -template -struct MathConstants -{ - /** A predefined value for Pi */ - static constexpr FloatType pi = static_cast (3.141592653589793238L); - - /** A predefined value for 2 * Pi */ - static constexpr FloatType twoPi = static_cast (2 * 3.141592653589793238L); - - /** A predefined value for Pi / 2 */ - static constexpr FloatType halfPi = static_cast (3.141592653589793238L / 2); - - /** A predefined value for Euler's number */ - static constexpr FloatType euler = static_cast (2.71828182845904523536L); - - /** A predefined value for sqrt(2) */ - static constexpr FloatType sqrt2 = static_cast (1.4142135623730950488L); -}; - -#ifndef DOXYGEN -/** A double-precision constant for pi. */ -[[deprecated ("This is deprecated in favour of MathConstants::pi.")]] -const constexpr double double_Pi = MathConstants::pi; - -/** A single-precision constant for pi. */ -[[deprecated ("This is deprecated in favour of MathConstants::pi.")]] -const constexpr float float_Pi = MathConstants::pi; -#endif - -/** Converts an angle in degrees to radians. */ -template -constexpr FloatType degreesToRadians (FloatType degrees) noexcept { return degrees * (MathConstants::pi / FloatType (180)); } - -/** Converts an angle in radians to degrees. */ -template -constexpr FloatType radiansToDegrees (FloatType radians) noexcept { return radians * (FloatType (180) / MathConstants::pi); } - - -//============================================================================== -/** The isfinite() method seems to vary between platforms, so this is a - platform-independent function for it. -*/ -template -bool juce_isfinite (NumericType) noexcept -{ - return true; // Integer types are always finite -} - -template <> -inline bool juce_isfinite (float value) noexcept -{ - #if JUCE_WINDOWS && ! JUCE_MINGW - return _finite (value) != 0; - #else - return std::isfinite (value); - #endif -} - -template <> -inline bool juce_isfinite (double value) noexcept -{ - #if JUCE_WINDOWS && ! JUCE_MINGW - return _finite (value) != 0; - #else - return std::isfinite (value); - #endif -} - //============================================================================== #if JUCE_MSVC #pragma optimize ("t", off) diff --git a/modules/juce_core/maths/juce_MathsFunctions_test.cpp b/modules/juce_core/maths/juce_MathsFunctions_test.cpp new file mode 100644 index 0000000000..1dbed3d63d --- /dev/null +++ b/modules/juce_core/maths/juce_MathsFunctions_test.cpp @@ -0,0 +1,483 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2022 - Raw Material Software Limited + + JUCE is an open source library subject to commercial or open-source + licensing. + + The code included in this file is provided under the terms of the ISC license + http://www.isc.org/downloads/software-support-policy/isc-license. Permission + To use, copy, modify, and/or distribute this software for any purpose with or + without fee is hereby granted provided that the above copyright notice and + this permission notice appear in all copies. + + JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +//============================================================================== +template +String getTemplatedMathsFunctionUnitTestName (const String& functionName) +{ + const auto getTypeName = []() -> String + { + if constexpr (std::is_same_v) + return "float"; + + if constexpr (std::is_same_v) + return "double"; + + if constexpr (std::is_same_v) + return "long double"; + }; + + return functionName + "<" + getTypeName() + ">"; +} + +template +class ApproximatelyEqualTests final : public UnitTest +{ +public: + ApproximatelyEqualTests() + : UnitTest { getTemplatedMathsFunctionUnitTestName ("approximatelyEqual"), UnitTestCategories::maths } + {} + + void runTest() final + { + using limits = std::numeric_limits; + + constexpr auto zero = T{}; + constexpr auto one = T (1); + constexpr auto min = limits::min(); + constexpr auto max = limits::max(); + constexpr auto epsilon = limits::epsilon(); + constexpr auto oneThird = one / (T) 3; + + beginTest ("Equal values are always equal"); + { + expect (approximatelyEqual (zero, zero)); + expect (approximatelyEqual (zero, -zero)); + expect (approximatelyEqual (-zero, -zero)); + + expect (approximatelyEqual (min, min)); + expect (approximatelyEqual (-min, -min)); + + expect (approximatelyEqual (one, one)); + expect (approximatelyEqual (-one, -one)); + + expect (approximatelyEqual (max, max)); + expect (approximatelyEqual (-max, -max)); + + const Tolerance zeroTolerance{}; + + expect (approximatelyEqual (zero, zero, zeroTolerance)); + expect (approximatelyEqual (zero, -zero, zeroTolerance)); + expect (approximatelyEqual (-zero, -zero, zeroTolerance)); + + expect (approximatelyEqual (min, min, zeroTolerance)); + expect (approximatelyEqual (-min, -min, zeroTolerance)); + + expect (approximatelyEqual (one, one, zeroTolerance)); + expect (approximatelyEqual (-one, -one, zeroTolerance)); + + expect (approximatelyEqual (max, max, zeroTolerance)); + expect (approximatelyEqual (-max, -max, zeroTolerance)); + } + + beginTest ("Comparing subnormal values to zero, returns true"); + { + expect (! exactlyEqual (zero, nextFloatUp (zero))); + expect (approximatelyEqual (zero, nextFloatUp (zero))); + + expect (! exactlyEqual (zero, nextFloatDown (zero))); + expect (approximatelyEqual (zero, nextFloatDown (zero))); + + expect (! exactlyEqual (zero, nextFloatDown (min))); + expect (approximatelyEqual (zero, nextFloatDown (min))); + + expect (! exactlyEqual (zero, nextFloatUp (-min))); + expect (approximatelyEqual (zero, nextFloatUp (-min))); + } + + beginTest ("Comparing the minimum normal value to zero, returns true"); + { + expect (approximatelyEqual (zero, min)); + expect (approximatelyEqual (zero, -min)); + } + + beginTest ("Comparing normal values greater than the minimum to zero, returns true"); + { + expect (! approximatelyEqual (zero, one)); + expect (! approximatelyEqual (zero, epsilon)); + expect (! approximatelyEqual (zero, nextFloatUp (min))); + expect (! approximatelyEqual (zero, nextFloatDown (-min))); + } + + beginTest ("Values with large ranges can be compared"); + { + expect (! approximatelyEqual (zero, max)); + expect ( approximatelyEqual (zero, max, absoluteTolerance (max))); + expect ( approximatelyEqual (zero, max, relativeTolerance (one))); + expect (! approximatelyEqual (-one, max)); + expect (! approximatelyEqual (-max, max)); + } + + beginTest ("Larger values have a boundary that is a factor of the epsilon"); + { + for (auto exponent = 0; exponent < 127; ++exponent) + { + const auto value = std::pow ((T) 2, (T) exponent); + const auto boundaryValue = value * (one + epsilon); + + expect (juce_isfinite (value)); + expect (juce_isfinite (boundaryValue)); + + expect ( approximatelyEqual (value, boundaryValue)); + expect (! approximatelyEqual (value, nextFloatUp (boundaryValue))); + + expect ( approximatelyEqual (-value, -boundaryValue)); + expect (! approximatelyEqual (-value, nextFloatDown (-boundaryValue))); + } + } + + beginTest ("Tolerances scale with the values being compared"); + { + + expect (approximatelyEqual ((T) 100'000'000'000'000.01, + (T) 100'000'000'000'000.011)); + + expect (! approximatelyEqual ((T) 100.01, + (T) 100.011)); + + expect (! approximatelyEqual ((T) 123'000, (T) 121'000, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 123'000, (T) 122'000, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 123'000, (T) 123'000, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 123'000, (T) 124'000, relativeTolerance ((T) 1e-2))); + expect (! approximatelyEqual ((T) 123'000, (T) 125'000, relativeTolerance ((T) 1e-2))); + + expect (! approximatelyEqual ((T) 123, (T) 121, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 123, (T) 122, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 123, (T) 123, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 123, (T) 124, relativeTolerance ((T) 1e-2))); + expect (! approximatelyEqual ((T) 123, (T) 125, relativeTolerance ((T) 1e-2))); + + expect (! approximatelyEqual ((T) 12.3, (T) 12.1, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 12.3, (T) 12.2, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 12.3, (T) 12.3, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 12.3, (T) 12.4, relativeTolerance ((T) 1e-2))); + expect (! approximatelyEqual ((T) 12.3, (T) 12.5, relativeTolerance ((T) 1e-2))); + + expect (! approximatelyEqual ((T) 1.23, (T) 1.21, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 1.23, (T) 1.22, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 1.23, (T) 1.23, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 1.23, (T) 1.24, relativeTolerance ((T) 1e-2))); + expect (! approximatelyEqual ((T) 1.23, (T) 1.25, relativeTolerance ((T) 1e-2))); + + expect (! approximatelyEqual ((T) 0.123, (T) 0.121, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 0.123, (T) 0.122, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 0.123, (T) 0.123, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 0.123, (T) 0.124, relativeTolerance ((T) 1e-2))); + expect (! approximatelyEqual ((T) 0.123, (T) 0.125, relativeTolerance ((T) 1e-2))); + + expect (! approximatelyEqual ((T) 0.000123, (T) 0.000121, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 0.000123, (T) 0.000122, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 0.000123, (T) 0.000123, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual ((T) 0.000123, (T) 0.000124, relativeTolerance ((T) 1e-2))); + expect (! approximatelyEqual ((T) 0.000123, (T) 0.000125, relativeTolerance ((T) 1e-2))); + } + + beginTest ("The square of the square root of 2 is approximately 2"); + { + constexpr auto two = (T) 2; + const auto sqrtOfTwo = std::sqrt (two); + + expect (approximatelyEqual (sqrtOfTwo * sqrtOfTwo, two)); + expect (approximatelyEqual (-sqrtOfTwo * sqrtOfTwo, -two)); + expect (approximatelyEqual (two / sqrtOfTwo, sqrtOfTwo)); + } + + if constexpr (limits::has_quiet_NaN) + { + beginTest ("Values are never equal to NaN"); + { + const auto nan = limits::quiet_NaN(); + + expect (! approximatelyEqual (nan, nan)); + + const auto expectNotEqualTo = [&](auto value) + { + expect (! approximatelyEqual (value, nan)); + expect (! approximatelyEqual (nan, value)); + }; + + expectNotEqualTo (zero); + expectNotEqualTo (-zero); + expectNotEqualTo (min); + expectNotEqualTo (-min); + expectNotEqualTo (one); + expectNotEqualTo (-one); + expectNotEqualTo (max); + expectNotEqualTo (-max); + } + } + + if constexpr (limits::has_infinity) + { + beginTest ("Only infinity is equal to infinity"); + { + const auto inf = limits::infinity(); + expect (approximatelyEqual (inf, inf)); + expect (approximatelyEqual (-inf, -inf)); + expect (! approximatelyEqual (inf, -inf)); + expect (! approximatelyEqual (-inf, inf)); + + const auto expectNotEqualTo = [&](auto value) + { + expect (! approximatelyEqual (value, inf)); + expect (! approximatelyEqual (value, -inf)); + expect (! approximatelyEqual (inf, value)); + expect (! approximatelyEqual (-inf, value)); + }; + + expectNotEqualTo (zero); + expectNotEqualTo (-zero); + expectNotEqualTo (min); + expectNotEqualTo (-min); + expectNotEqualTo (one); + expectNotEqualTo (-one); + expectNotEqualTo (max); + expectNotEqualTo (-max); + } + } + + beginTest ("Can set an absolute tolerance"); + { + constexpr std::array negativePowersOfTwo + { + (T) 0.5 /* 2^-1 */, + (T) 0.25 /* 2^-2 */, + (T) 0.125 /* 2^-3 */, + (T) 0.0625 /* 2^-4 */, + (T) 0.03125 /* 2^-5 */, + (T) 0.015625 /* 2^-6 */, + (T) 0.0078125 /* 2^-7 */ + }; + + const auto testTolerance = [&](auto tolerance) + { + const auto t = Tolerance{}.withAbsolute ((T) tolerance); + + const auto testValue= [&](auto value) + { + const auto boundary = value + tolerance; + + expect (approximatelyEqual (value, boundary, t)); + expect (! approximatelyEqual (value, nextFloatUp (boundary), t)); + + expect (approximatelyEqual (-value, -boundary, t)); + expect (! approximatelyEqual (-value, nextFloatDown (-boundary), t)); + }; + + testValue (zero); + testValue (min); + testValue (epsilon); + testValue (one); + + for (const auto value : negativePowersOfTwo) + testValue (value); + }; + + for (const auto toleranceValue : negativePowersOfTwo) + testTolerance (toleranceValue); + } + + beginTest ("Can set a relative tolerance"); + { + expect (! approximatelyEqual (oneThird, (T) 0.34, relativeTolerance ((T) 1e-2))); + expect ( approximatelyEqual (oneThird, (T) 0.334, relativeTolerance ((T) 1e-2))); + + expect (! approximatelyEqual (oneThird, (T) 0.334, relativeTolerance ((T) 1e-3))); + expect ( approximatelyEqual (oneThird, (T) 0.3334, relativeTolerance ((T) 1e-3))); + + expect (! approximatelyEqual (oneThird, (T) 0.3334, relativeTolerance ((T) 1e-4))); + expect ( approximatelyEqual (oneThird, (T) 0.33334, relativeTolerance ((T) 1e-4))); + + expect (! approximatelyEqual (oneThird, (T) 0.33334, relativeTolerance ((T) 1e-5))); + expect ( approximatelyEqual (oneThird, (T) 0.333334, relativeTolerance ((T) 1e-5))); + + expect (! approximatelyEqual (oneThird, (T) 0.333334, relativeTolerance ((T) 1e-6))); + expect ( approximatelyEqual (oneThird, (T) 0.3333334, relativeTolerance ((T) 1e-6))); + + expect (! approximatelyEqual (oneThird, (T) 0.3333334, relativeTolerance ((T) 1e-7))); + expect ( approximatelyEqual (oneThird, (T) 0.33333334, relativeTolerance ((T) 1e-7))); + + expect ( approximatelyEqual ((T) 1e6, (T) 1e6 + (T) 1, relativeTolerance ((T) 1e-6))); + expect (! approximatelyEqual ((T) 1e6, (T) 1e6 + (T) 1, relativeTolerance ((T) 1e-7))); + + expect ( approximatelyEqual ((T) -1e-6, (T) -1.0000009e-6, relativeTolerance ((T) 1e-6))); + expect (! approximatelyEqual ((T) -1e-6, (T) -1.0000009e-6, relativeTolerance ((T) 1e-7))); + + const auto a = (T) 1.234567; + const auto b = (T) 1.234568; + + for (auto exponent = 0; exponent < 39; ++exponent) + { + const auto m = std::pow ((T) 10, (T) exponent); + expect ( approximatelyEqual (a * m, b * m, relativeTolerance ((T) 1e-6))); + expect (! approximatelyEqual (a * m, b * m, relativeTolerance ((T) 1e-7))); + } + } + + beginTest ("A relative tolerance is always scaled by the maximum value"); + { + expect ( approximatelyEqual ((T) 9, (T) 10, absoluteTolerance ((T) 10.0 * (T) 0.1))); + expect (! approximatelyEqual ((T) 9, (T) 10, absoluteTolerance ((T) 9.0 * (T) 0.1))); + + expect (approximatelyEqual ((T) 9, (T) 10, relativeTolerance ((T) 0.1))); + expect (approximatelyEqual ((T) 10, (T) 9, relativeTolerance ((T) 0.1))); + } + + beginTest ("Documentation examples"); + { + constexpr auto pi = MathConstants::pi; + + expect (! approximatelyEqual (zero, std::sin (pi))); + expect ( approximatelyEqual (zero, std::sin (pi), absoluteTolerance (std::sin (pi)))); + + expect ( approximatelyEqual ((T) 100, (T) 95, relativeTolerance ((T) 0.05))); + expect (! approximatelyEqual ((T) 100, (T) 94, relativeTolerance ((T) 0.05))); + } + } +}; + +template +class IsFiniteTests final : public UnitTest +{ +public: + IsFiniteTests() + : UnitTest { getTemplatedMathsFunctionUnitTestName ("juce_isfinite"), UnitTestCategories::maths } + {} + + void runTest() final + { + using limits = std::numeric_limits; + + constexpr auto zero = T{}; + constexpr auto one = (T) 1; + constexpr auto max = limits::max(); + constexpr auto inf = limits::infinity(); + constexpr auto nan = limits::quiet_NaN(); + + beginTest ("Zero is finite"); + { + expect (juce_isfinite (zero)); + expect (juce_isfinite (-zero)); + } + + beginTest ("Subnormals are finite"); + { + expect (juce_isfinite (nextFloatUp (zero))); + expect (juce_isfinite (nextFloatDown (zero))); + } + + beginTest ("One is finite"); + { + expect (juce_isfinite (one)); + expect (juce_isfinite (-one)); + } + + beginTest ("Max is finite"); + { + expect (juce_isfinite (max)); + expect (juce_isfinite (-max)); + } + + beginTest ("Infinity is not finite"); + { + expect (! juce_isfinite (inf)); + expect (! juce_isfinite (-inf)); + } + + beginTest ("NaN is not finite"); + { + expect (! juce_isfinite (nan)); + expect (! juce_isfinite (-nan)); + expect (! juce_isfinite (std::sqrt ((T) -1))); + expect (! juce_isfinite (inf * zero)); + } + } +}; + +template +class NextFloatTests final : public UnitTest +{ +public: + NextFloatTests() + : UnitTest { getTemplatedMathsFunctionUnitTestName ("nextFloat"), UnitTestCategories::maths } + {} + + void runTest() final + { + using limits = std::numeric_limits; + + constexpr auto zero = T{}; + constexpr auto one = T (1); + constexpr auto min = limits::min(); + constexpr auto epsilon = limits::epsilon(); + + beginTest ("nextFloat from zero is subnormal"); + { + expect (juce_isfinite (nextFloatUp (zero))); + expect (! exactlyEqual (zero, nextFloatUp (zero))); + expect (! std::isnormal (nextFloatUp (zero))); + + expect (juce_isfinite (nextFloatDown (zero))); + expect (! exactlyEqual (zero, nextFloatDown (zero))); + expect (! std::isnormal (nextFloatDown (zero))); + } + + beginTest ("nextFloat from min, towards zero, is subnormal"); + { + expect (std::isnormal (min)); + expect (std::isnormal (-min)); + expect (! std::isnormal (nextFloatDown (min))); + expect (! std::isnormal (nextFloatUp (-min))); + } + + beginTest ("nextFloat from one matches epsilon"); + { + expect (! exactlyEqual (one, nextFloatUp (one))); + expect ( exactlyEqual (one + epsilon, nextFloatUp (one))); + + expect (! exactlyEqual (-one, nextFloatDown (-one))); + expect ( exactlyEqual (-one - epsilon, nextFloatDown (-one))); + } + } +}; + +template +struct MathsFloatingPointFunctionsTests +{ + IsFiniteTests isFiniteTests; + NextFloatTests nextFloatTests; + ApproximatelyEqualTests approximatelyEqualTests; +}; + +struct MathsFunctionsTests +{ + MathsFloatingPointFunctionsTests floatFunctionTests; + MathsFloatingPointFunctionsTests doubleFunctionTests; + MathsFloatingPointFunctionsTests longDoubleFunctionTests; +}; + +static MathsFunctionsTests mathsFunctionsTests; + +} // namespace juce diff --git a/modules/juce_graphics/colour/juce_Colour.cpp b/modules/juce_graphics/colour/juce_Colour.cpp index 572084c3dc..47c343ec3c 100644 --- a/modules/juce_graphics/colour/juce_Colour.cpp +++ b/modules/juce_graphics/colour/juce_Colour.cpp @@ -44,7 +44,7 @@ namespace ColourHelpers float hue = 0.0f; - if (hi > 0 && ! approximatelyEqual (hi, lo)) + if (hi > 0 && ! exactlyEqual (hi, lo)) { auto invDiff = 1.0f / (float) (hi - lo); diff --git a/modules/juce_graphics/geometry/juce_Point.h b/modules/juce_graphics/geometry/juce_Point.h index 6fc88b4a9e..9e6117f066 100644 --- a/modules/juce_graphics/geometry/juce_Point.h +++ b/modules/juce_graphics/geometry/juce_Point.h @@ -66,7 +66,7 @@ public: constexpr bool isOrigin() const noexcept { return operator== (Point()); } /** Returns true if the coordinates are finite values. */ - constexpr inline bool isFinite() const noexcept { return juce_isfinite(x) && juce_isfinite(y); } + constexpr inline bool isFinite() const noexcept { return juce_isfinite (x) && juce_isfinite (y); } /** Returns the point's x coordinate. */ constexpr inline ValueType getX() const noexcept { return x; }