From 28414a6af81ccb8bca32b1854cb35aca50d905da Mon Sep 17 00:00:00 2001 From: reuk Date: Thu, 23 Mar 2023 12:02:38 +0000 Subject: [PATCH] Global: Avoid floating-point equality checks where possible --- examples/Audio/AudioPlaybackDemo.h | 2 +- examples/Audio/AudioSynthesiserDemo.h | 6 +- examples/Audio/MPEDemo.h | 8 +- examples/DSP/FIRFilterDemo.h | 2 +- examples/DSP/IIRFilterDemo.h | 2 +- examples/DSP/OverdriveDemo.h | 2 +- examples/DSP/SIMDRegisterDemo.h | 2 +- examples/DSP/StateVariableFilterDemo.h | 2 +- examples/GUI/VideoDemo.h | 2 +- examples/Plugins/AudioPluginDemo.h | 6 +- examples/Plugins/DSPModulePluginDemo.h | 2 +- examples/Plugins/SamplerPluginDemo.h | 4 +- .../Source/Plugins/InternalPlugins.cpp | 6 +- extras/Build/CMake/JUCEHelperTargets.cmake | 4 +- .../Components/jucer_SliderHandler.h | 2 +- .../PaintElements/jucer_FillType.h | 4 +- .../PaintElements/jucer_PaintElementImage.cpp | 2 +- .../jucer_PaintElementRoundedRectangle.h | 2 +- .../Properties/jucer_FontPropertyComponent.h | 2 +- .../UI/jucer_PaintRoutineEditor.cpp | 2 +- .../UI/jucer_RelativePositionedRectangle.h | 10 +- .../ComponentEditor/jucer_JucerDocument.cpp | 2 +- .../Project/UI/jucer_ContentViewComponents.h | 2 +- .../ProjectSaving/jucer_ProjectExporter.h | 23 ++- .../buffers/juce_AudioDataConverters.cpp | 4 +- .../buffers/juce_AudioProcessLoadMeasurer.cpp | 2 +- .../buffers/juce_AudioSampleBuffer.h | 12 +- .../buffers/juce_FloatVectorOperations.cpp | 2 +- .../juce_audio_basics/midi/juce_MidiFile.cpp | 6 +- .../midi/juce_MidiMessageSequence.cpp | 4 +- .../mpe/juce_MPESynthesiserBase.cpp | 4 +- .../native/juce_CoreAudioLayouts_mac.h | 8 +- .../sources/juce_BufferingAudioSource.cpp | 2 +- .../sources/juce_MemoryAudioSource.cpp | 4 +- .../sources/juce_ResamplingAudioSource.cpp | 2 +- .../sources/juce_ToneGeneratorAudioSource.cpp | 2 +- .../synthesisers/juce_Synthesiser.cpp | 4 +- .../utilities/juce_Interpolators.h | 2 +- .../utilities/juce_SmoothedValue.h | 8 +- .../midi_io/juce_MidiMessageCollector.cpp | 2 +- .../native/juce_Audio_ios.cpp | 4 +- .../native/juce_CoreAudio_mac.cpp | 8 +- .../codecs/juce_FlacAudioFormat.cpp | 13 +- .../codecs/juce_OggVorbisAudioFormat.cpp | 23 ++- .../detail/juce_VSTWindowUtilities.h | 2 +- .../juce_audio_plugin_client_AAX.cpp | 17 +- .../juce_audio_plugin_client_AAX_utils.cpp | 9 +- .../juce_audio_plugin_client_AU_1.mm | 27 +-- .../juce_audio_plugin_client_AU_2.mm | 29 +-- .../juce_audio_plugin_client_AUv3.mm | 4 +- .../juce_audio_plugin_client_LV2.cpp | 4 +- .../juce_audio_plugin_client_VST2.cpp | 8 +- .../juce_audio_plugin_client_VST3.cpp | 16 +- .../juce_AudioUnitPluginFormat.mm | 4 +- .../format_types/juce_LADSPAPluginFormat.cpp | 2 +- .../format_types/juce_LV2PluginFormat.cpp | 2 +- .../format_types/juce_LV2SupportLibs.cpp | 5 +- .../format_types/juce_VST3Headers.h | 61 +++--- .../format_types/juce_VST3PluginFormat.cpp | 6 +- .../juce_VST3PluginFormat_test.cpp | 6 +- .../format_types/juce_VSTPluginFormat.cpp | 8 +- .../processors/juce_AudioProcessorGraph.h | 2 +- .../juce_GenericAudioProcessorEditor.cpp | 2 +- .../utilities/juce_AudioParameterFloat.cpp | 4 +- .../juce_AudioProcessorValueTreeState.cpp | 18 +- .../utilities/juce_ParameterAttachments.cpp | 2 +- .../gui/juce_AudioDeviceSelectorComponent.cpp | 2 +- .../gui/juce_AudioThumbnail.cpp | 4 +- .../gui/juce_KeyboardComponentBase.cpp | 10 +- modules/juce_box2d/juce_box2d.cpp | 13 +- modules/juce_box2d/juce_box2d.h | 7 +- modules/juce_core/containers/juce_Array.h | 2 +- modules/juce_core/containers/juce_ArrayBase.h | 2 +- modules/juce_core/containers/juce_Variant.cpp | 4 +- .../juce_core/javascript/juce_Javascript.cpp | 8 +- modules/juce_core/maths/juce_MathsFunctions.h | 35 +++- .../juce_core/maths/juce_NormalisableRange.h | 8 +- modules/juce_core/maths/juce_Random.cpp | 2 +- modules/juce_core/maths/juce_Range.h | 11 +- .../streams/juce_MemoryInputStream.cpp | 4 +- .../juce_core/system/juce_CompilerWarnings.h | 23 ++- .../text/juce_CharacterFunctions.cpp | 2 +- modules/juce_core/text/juce_String.cpp | 14 +- modules/juce_core/text/juce_String.h | 2 +- modules/juce_core/threads/juce_Thread.cpp | 14 +- modules/juce_core/time/juce_RelativeTime.cpp | 12 +- modules/juce_core/unit_tests/juce_UnitTest.h | 4 +- .../values/juce_CachedValue.h | 2 +- .../containers/juce_AudioBlock_test.cpp | 173 ++++++++-------- .../containers/juce_SIMDRegister_test.cpp | 17 +- .../filter_design/juce_FilterDesign.cpp | 11 +- .../juce_dsp/frequency/juce_Convolution.cpp | 2 +- .../frequency/juce_Convolution_test.cpp | 4 +- modules/juce_dsp/maths/juce_LogRampedValue.h | 2 +- modules/juce_dsp/maths/juce_Matrix.cpp | 10 +- modules/juce_dsp/processors/juce_DelayLine.h | 2 +- .../juce_dsp/processors/juce_IIRFilter_Impl.h | 5 +- .../juce_dsp/processors/juce_Oversampling.cpp | 2 +- .../juce_dsp/processors/juce_ProcessContext.h | 9 +- .../processors/juce_ProcessorChain_test.cpp | 2 +- modules/juce_dsp/widgets/juce_Bias.h | 2 +- modules/juce_dsp/widgets/juce_Gain.h | 2 +- .../colour/juce_ColourGradient.cpp | 11 +- .../contexts/juce_GraphicsContext.cpp | 4 +- .../fonts/juce_CustomTypeface.cpp | 2 +- modules/juce_graphics/fonts/juce_Font.cpp | 22 +- .../fonts/juce_GlyphArrangement.cpp | 8 +- .../juce_graphics/fonts/juce_TextLayout.cpp | 2 +- modules/juce_graphics/fonts/juce_Typeface.cpp | 2 +- .../geometry/juce_AffineTransform.cpp | 29 ++- modules/juce_graphics/geometry/juce_Line.h | 12 +- modules/juce_graphics/geometry/juce_Path.cpp | 9 +- modules/juce_graphics/geometry/juce_Path.h | 10 +- .../geometry/juce_PathIterator.cpp | 20 +- .../geometry/juce_PathStrokeType.cpp | 191 +++++++++--------- modules/juce_graphics/geometry/juce_Point.h | 11 +- .../juce_graphics/geometry/juce_Rectangle.h | 8 +- .../image_formats/juce_PNGLoader.cpp | 11 +- .../native/juce_CoreGraphicsContext_mac.mm | 4 +- .../juce_DirectWriteTypeLayout_windows.cpp | 2 +- .../juce_graphics/native/juce_Fonts_mac.mm | 2 +- .../native/juce_RenderingHelpers.h | 6 +- .../placement/juce_RectanglePlacement.cpp | 2 +- .../juce_gui_basics/desktop/juce_Desktop.cpp | 2 +- .../juce_gui_basics/desktop/juce_Displays.cpp | 12 +- .../detail/juce_ScalingHelpers.h | 36 ++-- .../drawables/juce_DrawableText.cpp | 4 +- .../drawables/juce_SVGParser.cpp | 4 +- .../layout/juce_AnimatedPosition.h | 2 +- .../layout/juce_AnimatedPositionBehaviours.h | 2 +- .../layout/juce_ComponentAnimator.cpp | 4 +- .../juce_gui_basics/layout/juce_FlexBox.cpp | 16 +- modules/juce_gui_basics/layout/juce_Grid.cpp | 10 +- .../juce_gui_basics/layout/juce_Viewport.cpp | 2 +- .../native/juce_NSViewComponentPeer_mac.mm | 2 +- .../native/juce_UIViewComponentPeer_ios.mm | 5 +- .../native/juce_Windowing_mac.mm | 2 +- .../native/juce_Windowing_windows.cpp | 2 +- .../juce_SliderPropertyComponent.cpp | 2 +- .../juce_gui_basics/widgets/juce_ComboBox.cpp | 2 +- .../juce_gui_basics/widgets/juce_Label.cpp | 2 +- .../juce_gui_basics/widgets/juce_ListBox.cpp | 4 +- .../widgets/juce_ProgressBar.cpp | 2 +- .../juce_gui_basics/widgets/juce_Slider.cpp | 26 +-- .../code_editor/juce_CodeEditorComponent.cpp | 6 +- .../misc/juce_ColourSelector.cpp | 6 +- .../juce_opengl/opengl/juce_OpenGLContext.cpp | 2 +- modules/juce_osc/osc/juce_OSCArgument.cpp | 2 +- modules/juce_osc/osc/juce_OSCBundle.cpp | 4 +- modules/juce_video/native/juce_Video_mac.h | 8 +- 150 files changed, 756 insertions(+), 666 deletions(-) diff --git a/examples/Audio/AudioPlaybackDemo.h b/examples/Audio/AudioPlaybackDemo.h index 955fa60af4..211fadd1e1 100644 --- a/examples/Audio/AudioPlaybackDemo.h +++ b/examples/Audio/AudioPlaybackDemo.h @@ -188,7 +188,7 @@ public: if (canMoveTransport()) setRange ({ newStart, newStart + visibleRange.getLength() }); - if (wheel.deltaY != 0.0f) + if (! approximatelyEqual (wheel.deltaY, 0.0f)) zoomSlider.setValue (zoomSlider.getValue() - wheel.deltaY); repaint(); diff --git a/examples/Audio/AudioSynthesiserDemo.h b/examples/Audio/AudioSynthesiserDemo.h index bd8d7cf38b..a70b3d7e84 100644 --- a/examples/Audio/AudioSynthesiserDemo.h +++ b/examples/Audio/AudioSynthesiserDemo.h @@ -88,8 +88,8 @@ struct SineWaveVoice : public SynthesiserVoice // start a tail-off by setting this flag. The render callback will pick up on // this and do a fade out, calling clearCurrentNote() when it's finished. - if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the - tailOff = 1.0; // stopNote method could be called more than once. + if (approximatelyEqual (tailOff, 0.0)) // we only need to begin a tail-off if it's not already doing so - the + tailOff = 1.0; // stopNote method could be called more than once. } else { @@ -104,7 +104,7 @@ struct SineWaveVoice : public SynthesiserVoice void renderNextBlock (AudioBuffer& outputBuffer, int startSample, int numSamples) override { - if (angleDelta != 0.0) + if (! approximatelyEqual (angleDelta, 0.0)) { if (tailOff > 0.0) { diff --git a/examples/Audio/MPEDemo.h b/examples/Audio/MPEDemo.h index 2479272886..dfb2a4c08c 100644 --- a/examples/Audio/MPEDemo.h +++ b/examples/Audio/MPEDemo.h @@ -499,8 +499,8 @@ public: // start a tail-off by setting this flag. The render callback will pick up on // this and do a fade out, calling clearCurrentNote() when it's finished. - if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the - // stopNote method could be called more than once. + if (approximatelyEqual (tailOff, 0.0)) // we only need to begin a tail-off if it's not already doing so - the + // stopNote method could be called more than once. tailOff = 1.0; } else @@ -530,7 +530,7 @@ public: void setCurrentSampleRate (double newRate) override { - if (currentSampleRate != newRate) + if (! approximatelyEqual (currentSampleRate, newRate)) { noteStopped (false); currentSampleRate = newRate; @@ -546,7 +546,7 @@ public: int startSample, int numSamples) override { - if (phaseDelta != 0.0) + if (! approximatelyEqual (phaseDelta, 0.0)) { if (tailOff > 0.0) { diff --git a/examples/DSP/FIRFilterDemo.h b/examples/DSP/FIRFilterDemo.h index a0fa4148d0..ffbf386676 100644 --- a/examples/DSP/FIRFilterDemo.h +++ b/examples/DSP/FIRFilterDemo.h @@ -77,7 +77,7 @@ struct FIRFilterDemoDSP void updateParameters() { - if (sampleRate != 0.0) + if (! approximatelyEqual (sampleRate, 0.0)) { auto cutoff = static_cast (cutoffParam.getCurrentValue()); auto windowingMethod = static_cast::WindowingMethod> (typeParam.getCurrentSelectedID() - 1); diff --git a/examples/DSP/IIRFilterDemo.h b/examples/DSP/IIRFilterDemo.h index b12f0e70a9..92c8e0730f 100644 --- a/examples/DSP/IIRFilterDemo.h +++ b/examples/DSP/IIRFilterDemo.h @@ -76,7 +76,7 @@ struct IIRFilterDemoDSP void updateParameters() { - if (sampleRate != 0.0) + if (! approximatelyEqual (sampleRate, 0.0)) { auto cutoff = static_cast (cutoffParam.getCurrentValue()); auto qVal = static_cast (qParam.getCurrentValue()); diff --git a/examples/DSP/OverdriveDemo.h b/examples/DSP/OverdriveDemo.h index c00f700ec0..84f0242ecb 100644 --- a/examples/DSP/OverdriveDemo.h +++ b/examples/DSP/OverdriveDemo.h @@ -90,7 +90,7 @@ struct OverdriveDemoDSP void updateParameters() { - if (sampleRate != 0.0) + if (! approximatelyEqual (sampleRate, 0.0)) { overdrive.get<0>().setGainDecibels (static_cast (inGainParam.getCurrentValue())); overdrive.get<4>().setGainDecibels (static_cast (outGainParam.getCurrentValue())); diff --git a/examples/DSP/SIMDRegisterDemo.h b/examples/DSP/SIMDRegisterDemo.h index f1ba7cde2b..a4ccd4cd78 100644 --- a/examples/DSP/SIMDRegisterDemo.h +++ b/examples/DSP/SIMDRegisterDemo.h @@ -124,7 +124,7 @@ struct SIMDRegisterDemoDSP void updateParameters() { - if (sampleRate != 0.0) + if (! approximatelyEqual (sampleRate, 0.0)) { auto cutoff = static_cast (cutoffParam.getCurrentValue()); auto qVal = static_cast (qParam.getCurrentValue()); diff --git a/examples/DSP/StateVariableFilterDemo.h b/examples/DSP/StateVariableFilterDemo.h index e9b97b5424..d92479cdca 100644 --- a/examples/DSP/StateVariableFilterDemo.h +++ b/examples/DSP/StateVariableFilterDemo.h @@ -74,7 +74,7 @@ struct StateVariableFilterDemoDSP void updateParameters() { - if (sampleRate != 0.0) + if (! approximatelyEqual (sampleRate, 0.0)) { filter.setCutoffFrequency (static_cast (cutoffParam.getCurrentValue())); filter.setResonance (static_cast (qParam.getCurrentValue())); diff --git a/examples/GUI/VideoDemo.h b/examples/GUI/VideoDemo.h index 4fd79408e8..569ea6f92c 100644 --- a/examples/GUI/VideoDemo.h +++ b/examples/GUI/VideoDemo.h @@ -630,7 +630,7 @@ private: currentPositionLabel.setText (getPositionString (position, duration), sendNotification); if (! positionSliderDragging) - positionSlider.setValue (duration != 0 ? (position / duration) : 0.0, dontSendNotification); + positionSlider.setValue (approximatelyEqual (duration, 0.0) ? 0.0 : (position / duration), dontSendNotification); } void seekVideoToStart() diff --git a/examples/Plugins/AudioPluginDemo.h b/examples/Plugins/AudioPluginDemo.h index da12a3da59..189f090154 100644 --- a/examples/Plugins/AudioPluginDemo.h +++ b/examples/Plugins/AudioPluginDemo.h @@ -97,8 +97,8 @@ public: // start a tail-off by setting this flag. The render callback will pick up on // this and do a fade out, calling clearCurrentNote() when it's finished. - if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the - // stopNote method could be called more than once. + if (approximatelyEqual (tailOff, 0.0)) // we only need to begin a tail-off if it's not already doing so - the + // stopNote method could be called more than once. tailOff = 1.0; } else @@ -122,7 +122,7 @@ public: void renderNextBlock (AudioBuffer& outputBuffer, int startSample, int numSamples) override { - if (angleDelta != 0.0) + if (! approximatelyEqual (angleDelta, 0.0)) { if (tailOff > 0.0) { diff --git a/examples/Plugins/DSPModulePluginDemo.h b/examples/Plugins/DSPModulePluginDemo.h index 6e5c9c3691..004753132e 100644 --- a/examples/Plugins/DSPModulePluginDemo.h +++ b/examples/Plugins/DSPModulePluginDemo.h @@ -969,7 +969,7 @@ private: //============================================================================== static String getPanningTextForValue (float value) { - if (value == 0.5f) + if (approximatelyEqual (value, 0.5f)) return "center"; if (value < 0.5f) diff --git a/examples/Plugins/SamplerPluginDemo.h b/examples/Plugins/SamplerPluginDemo.h index 9f2a3428b0..6e6d15c02d 100644 --- a/examples/Plugins/SamplerPluginDemo.h +++ b/examples/Plugins/SamplerPluginDemo.h @@ -291,7 +291,7 @@ public: { jassert (currentlyPlayingNote.keyState == MPENote::off); - if (allowTailOff && tailOff == 0.0) + if (allowTailOff && approximatelyEqual (tailOff, 0.0)) tailOff = 1.0; else stopNote(); @@ -422,7 +422,7 @@ private: bool isTailingOff() const { - return tailOff != 0.0; + return ! approximatelyEqual (tailOff, 0.0); } void stopNote() diff --git a/extras/AudioPluginHost/Source/Plugins/InternalPlugins.cpp b/extras/AudioPluginHost/Source/Plugins/InternalPlugins.cpp index 6edfc6510a..61f065f33c 100644 --- a/extras/AudioPluginHost/Source/Plugins/InternalPlugins.cpp +++ b/extras/AudioPluginHost/Source/Plugins/InternalPlugins.cpp @@ -262,8 +262,8 @@ private: // start a tail-off by setting this flag. The render callback will pick up on // this and do a fade out, calling clearCurrentNote() when it's finished. - if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the - // stopNote method could be called more than once. + if (approximatelyEqual (tailOff, 0.0)) // we only need to begin a tail-off if it's not already doing so - the + // stopNote method could be called more than once. tailOff = 1.0; } else @@ -287,7 +287,7 @@ private: void renderNextBlock (AudioBuffer& outputBuffer, int startSample, int numSamples) override { - if (angleDelta != 0.0) + if (! approximatelyEqual (angleDelta, 0.0)) { if (tailOff > 0) { diff --git a/extras/Build/CMake/JUCEHelperTargets.cmake b/extras/Build/CMake/JUCEHelperTargets.cmake index a377864039..9c770877a4 100644 --- a/extras/Build/CMake/JUCEHelperTargets.cmake +++ b/extras/Build/CMake/JUCEHelperTargets.cmake @@ -34,7 +34,7 @@ elseif((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQU -Wsign-conversion -Wbool-conversion -Wextra-semi -Wunreachable-code -Wcast-align -Wshift-sign-overflow -Wmissing-prototypes -Wnullable-to-nonnull-conversion -Wno-ignored-qualifiers -Wswitch-enum - -Wpedantic -Wdeprecated + -Wpedantic -Wdeprecated -Wfloat-equal $<$,$>: -Wzero-as-null-pointer-constant -Wunused-private-field -Woverloaded-virtual -Wreorder @@ -47,7 +47,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") -Wunused-parameter -Wsign-compare -Wsign-conversion -Wunreachable-code -Wcast-align -Wno-implicit-fallthrough -Wno-maybe-uninitialized -Wno-ignored-qualifiers -Wswitch-enum - -Wredundant-decls -Wno-strict-overflow -Wshadow + -Wredundant-decls -Wno-strict-overflow -Wshadow -Wfloat-equal $<$: -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant>) endif() diff --git a/extras/Projucer/Source/ComponentEditor/Components/jucer_SliderHandler.h b/extras/Projucer/Source/ComponentEditor/Components/jucer_SliderHandler.h index 5e04d934f9..56704e73c6 100644 --- a/extras/Projucer/Source/ComponentEditor/Components/jucer_SliderHandler.h +++ b/extras/Projucer/Source/ComponentEditor/Components/jucer_SliderHandler.h @@ -145,7 +145,7 @@ struct SliderHandler : public ComponentTypeHandler if (needsSliderListener (component)) r << memberVariableName << "->addListener (this);\n"; - if (s->getSkewFactor() != 1.0) + if (! approximatelyEqual (s->getSkewFactor(), 1.0)) r << memberVariableName << "->setSkewFactor (" << s->getSkewFactor() << ");\n"; r << '\n'; diff --git a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h index 105f3f2739..6c791fa106 100644 --- a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h +++ b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h @@ -77,7 +77,7 @@ public: && gradPos1 == other.gradPos1 && gradPos2 == other.gradPos2 && imageResourceName == other.imageResourceName - && imageOpacity == other.imageOpacity + && approximatelyEqual (imageOpacity, other.imageOpacity) && imageAnchor == other.imageAnchor; } @@ -320,7 +320,7 @@ public: return gradCol1.isTransparent() && gradCol2.isTransparent(); case imageBrush: - return imageOpacity == 0.0; + return approximatelyEqual (imageOpacity, 0.0); default: jassertfalse; diff --git a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementImage.cpp b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementImage.cpp index 9aaa0d0b2c..5441440cf6 100644 --- a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementImage.cpp +++ b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementImage.cpp @@ -244,7 +244,7 @@ void PaintElementImage::setOpacity (double newOpacity, const bool undoable) { newOpacity = jlimit (0.0, 1.0, newOpacity); - if (opacity != newOpacity) + if (! approximatelyEqual (opacity, newOpacity)) { if (undoable) { diff --git a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementRoundedRectangle.h b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementRoundedRectangle.h index aa21079e7f..48ddcb6f31 100644 --- a/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementRoundedRectangle.h +++ b/extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementRoundedRectangle.h @@ -95,7 +95,7 @@ public: void setCornerSize (const double newSize, const bool undoable) { - if (newSize != cornerSize) + if (! approximatelyEqual (newSize, cornerSize)) { if (undoable) { diff --git a/extras/Projucer/Source/ComponentEditor/Properties/jucer_FontPropertyComponent.h b/extras/Projucer/Source/ComponentEditor/Properties/jucer_FontPropertyComponent.h index 0cb8f7f5ce..d1fe26469d 100644 --- a/extras/Projucer/Source/ComponentEditor/Properties/jucer_FontPropertyComponent.h +++ b/extras/Projucer/Source/ComponentEditor/Properties/jucer_FontPropertyComponent.h @@ -132,7 +132,7 @@ public: s << getFontStyleCode (font) << ")"; - if (font.getExtraKerningFactor() != 0.0f) + if (! approximatelyEqual (font.getExtraKerningFactor(), 0.0f)) s << ".withExtraKerningFactor (" << CodeHelpers::floatLiteral (font.getExtraKerningFactor(), 3) << ")"; diff --git a/extras/Projucer/Source/ComponentEditor/UI/jucer_PaintRoutineEditor.cpp b/extras/Projucer/Source/ComponentEditor/UI/jucer_PaintRoutineEditor.cpp index 586e9eab50..109a6c8c06 100644 --- a/extras/Projucer/Source/ComponentEditor/UI/jucer_PaintRoutineEditor.cpp +++ b/extras/Projucer/Source/ComponentEditor/UI/jucer_PaintRoutineEditor.cpp @@ -184,7 +184,7 @@ void PaintRoutineEditor::refreshAllElements() repaint(); } - if (componentOverlayOpacity != document.getComponentOverlayOpacity()) + if (! approximatelyEqual (componentOverlayOpacity, document.getComponentOverlayOpacity())) { componentOverlay = Image(); componentOverlayOpacity = document.getComponentOverlayOpacity(); diff --git a/extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h b/extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h index 314dd7dee7..3e4299e289 100644 --- a/extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h +++ b/extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h @@ -420,10 +420,12 @@ public: /** Compares two objects. */ bool operator== (const PositionedRectangle& other) const noexcept { - return x == other.x && y == other.y - && w == other.w && h == other.h - && xMode == other.xMode && yMode == other.yMode - && wMode == other.wMode && hMode == other.hMode; + const auto tie = [] (const PositionedRectangle& r) + { + return std::tie (r.x, r.y, r.xMode, r.yMode, r.wMode, r.hMode); + }; + + return tie (*this) == tie (other); } /** Compares two objects. */ diff --git a/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp b/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp index 9c4b1eec3c..4dcccad23b 100644 --- a/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp +++ b/extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp @@ -245,7 +245,7 @@ void JucerDocument::setSnappingGrid (const int numPixels, const bool active, con void JucerDocument::setComponentOverlayOpacity (const float alpha) { - if (alpha != componentOverlayOpacity) + if (! approximatelyEqual (alpha, componentOverlayOpacity)) { componentOverlayOpacity = alpha; changed(); diff --git a/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h b/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h index ba618d06a3..79598849ca 100644 --- a/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h +++ b/extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h @@ -136,7 +136,7 @@ private: for (auto w : widths) total += w; - if (total == 1.0f) + if (approximatelyEqual (total, 1.0f)) return; auto diff = 1.0f - total; diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h index 4a896ecdb0..be0c0796a7 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h @@ -320,10 +320,25 @@ public: static CompilerWarningFlags getRecommendedForGCCAndLLVM() { CompilerWarningFlags result; - result.common = { "-Wall", "-Wstrict-aliasing", "-Wuninitialized", "-Wunused-parameter", - "-Wswitch-enum", "-Wsign-conversion", "-Wsign-compare", - "-Wunreachable-code", "-Wcast-align", "-Wno-ignored-qualifiers" }; - result.cpp = { "-Woverloaded-virtual", "-Wreorder", "-Wzero-as-null-pointer-constant" }; + result.common = { + "-Wall", + "-Wcast-align", + "-Wfloat-equal", + "-Wno-ignored-qualifiers", + "-Wsign-compare", + "-Wsign-conversion", + "-Wstrict-aliasing", + "-Wswitch-enum", + "-Wuninitialized", + "-Wunreachable-code", + "-Wunused-parameter" + }; + + result.cpp = { + "-Woverloaded-virtual", + "-Wreorder", + "-Wzero-as-null-pointer-constant" + }; return result; } diff --git a/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp b/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp index c72e3e3c93..f5e9c668fc 100644 --- a/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp +++ b/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp @@ -599,7 +599,7 @@ public: for (int ch = 0; ch < numChannels; ++ch) for (int i = 0; i < numSamples; ++i) - expect (destBuffer.getSample (0, ch + (i * numChannels)) == sourceBuffer.getSample (ch, i)); + expectEquals (destBuffer.getSample (0, ch + (i * numChannels)), sourceBuffer.getSample (ch, i)); } beginTest ("Deinterleaving"); @@ -620,7 +620,7 @@ public: for (int ch = 0; ch < numChannels; ++ch) for (int i = 0; i < numSamples; ++i) - expect (sourceBuffer.getSample (0, ch + (i * numChannels)) == destBuffer.getSample (ch, i)); + expectEquals (sourceBuffer.getSample (0, ch + (i * numChannels)), destBuffer.getSample (ch, i)); } } }; diff --git a/modules/juce_audio_basics/buffers/juce_AudioProcessLoadMeasurer.cpp b/modules/juce_audio_basics/buffers/juce_AudioProcessLoadMeasurer.cpp index 2144fa66b5..98ce1a592d 100644 --- a/modules/juce_audio_basics/buffers/juce_AudioProcessLoadMeasurer.cpp +++ b/modules/juce_audio_basics/buffers/juce_AudioProcessLoadMeasurer.cpp @@ -60,7 +60,7 @@ void AudioProcessLoadMeasurer::registerRenderTime (double milliseconds, int numS void AudioProcessLoadMeasurer::registerRenderTimeLocked (double milliseconds, int numSamples) { - if (msPerSample == 0) + if (approximatelyEqual (msPerSample, 0.0)) return; const auto maxMilliseconds = numSamples * msPerSample; diff --git a/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h b/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h index 60c75c48ca..fce45ba1d5 100644 --- a/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h +++ b/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h @@ -686,11 +686,11 @@ public: jassert (isPositiveAndBelow (channel, numChannels)); jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size); - if (gain != Type (1) && ! isClear) + if (! approximatelyEqual (gain, Type (1)) && ! isClear) { auto* d = channels[channel] + startSample; - if (gain == Type()) + if (approximatelyEqual (gain, Type())) FloatVectorOperations::clear (d, numSamples); else FloatVectorOperations::multiply (d, gain, numSamples); @@ -728,7 +728,7 @@ public: { if (! isClear) { - if (startGain == endGain) + if (approximatelyEqual (startGain, endGain)) { applyGain (channel, startSample, numSamples, startGain); } @@ -798,7 +798,7 @@ public: jassert (isPositiveAndBelow (sourceChannel, source.numChannels)); jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size); - if (gainToApplyToSource != 0 && numSamples > 0 && ! source.isClear) + if (! approximatelyEqual (gainToApplyToSource, (Type) 0) && numSamples > 0 && ! source.isClear) { auto* d = channels[destChannel] + destStartSample; auto* s = source.channels[sourceChannel] + sourceStartSample; @@ -809,14 +809,14 @@ public: { isClear = false; - if (gainToApplyToSource != Type (1)) + if (! approximatelyEqual (gainToApplyToSource, Type (1))) FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples); else FloatVectorOperations::copy (d, s, numSamples); } else { - if (gainToApplyToSource != Type (1)) + if (! approximatelyEqual (gainToApplyToSource, Type (1))) FloatVectorOperations::addWithMultiply (d, s, gainToApplyToSource, numSamples); else FloatVectorOperations::add (d, s, numSamples); diff --git a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp index 2a576dc989..1079e872a9 100644 --- a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp +++ b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp @@ -1676,7 +1676,7 @@ public: static bool areAllValuesEqual (const ValueType* d, int num, ValueType target) { while (--num >= 0) - if (*d++ != target) + if (! exactlyEqual (*d++, target)) return false; return true; diff --git a/modules/juce_audio_basics/midi/juce_MidiFile.cpp b/modules/juce_audio_basics/midi/juce_MidiFile.cpp index 67795b45c4..51bfcdda3a 100644 --- a/modules/juce_audio_basics/midi/juce_MidiFile.cpp +++ b/modules/juce_audio_basics/midi/juce_MidiFile.cpp @@ -160,7 +160,7 @@ namespace MidiFileHelpers for (int i = 0; i < numEvents; ++i) { - auto& m = tempoEvents.getEventPointer(i)->message; + auto& m = tempoEvents.getEventPointer (i)->message; auto eventTime = m.getTimeStamp(); if (eventTime >= time) @@ -174,9 +174,9 @@ namespace MidiFileHelpers while (i + 1 < numEvents) { - auto& m2 = tempoEvents.getEventPointer(i + 1)->message; + auto& m2 = tempoEvents.getEventPointer (i + 1)->message; - if (m2.getTimeStamp() != eventTime) + if (! approximatelyEqual (m2.getTimeStamp(), eventTime)) break; if (m2.isTempoMetaEvent()) diff --git a/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp b/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp index 129ad9e085..95d0122201 100644 --- a/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp +++ b/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp @@ -266,7 +266,7 @@ void MidiMessageSequence::updateMatchedPairs() noexcept void MidiMessageSequence::addTimeToMessages (double delta) noexcept { - if (delta != 0) + if (! approximatelyEqual (delta, 0.0)) for (auto* m : list) m->message.addToTimeStamp (delta); } @@ -554,7 +554,7 @@ struct MidiMessageSequenceTest : public UnitTest { const auto isEqual = [this] (const ControlValue& cv, const MidiMessage& msg) { - return msg.getTimeStamp() == time + return exactlyEqual (msg.getTimeStamp(), time) && msg.isController() && msg.getChannel() == channel && msg.getControllerNumber() == cv.control diff --git a/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp b/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp index 4f1c2afc3f..455555586e 100644 --- a/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp +++ b/modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp @@ -107,7 +107,7 @@ void MPESynthesiserBase::renderNextBlock (AudioBuffer& outputAudio, int numSamples) { // you must set the sample rate before using this! - jassert (sampleRate != 0); + jassert (! approximatelyEqual (sampleRate, 0.0)); const ScopedLock sl (noteStateLock); @@ -144,7 +144,7 @@ template void MPESynthesiserBase::renderNextBlock (AudioBuffer&, //============================================================================== void MPESynthesiserBase::setCurrentPlaybackSampleRate (const double newRate) { - if (sampleRate != newRate) + if (! approximatelyEqual (sampleRate, newRate)) { const ScopedLock sl (noteStateLock); instrument.releaseAllNotes(); diff --git a/modules/juce_audio_basics/native/juce_CoreAudioLayouts_mac.h b/modules/juce_audio_basics/native/juce_CoreAudioLayouts_mac.h index afd0e00173..44ebd4d93c 100644 --- a/modules/juce_audio_basics/native/juce_CoreAudioLayouts_mac.h +++ b/modules/juce_audio_basics/native/juce_CoreAudioLayouts_mac.h @@ -263,13 +263,13 @@ public: } } - auto numChannels = tag & 0xffff; + const auto numChannels = tag & 0xffff; + if (tag >= coreAudioHOASN3DLayoutTag && tag <= (coreAudioHOASN3DLayoutTag | 0xffff)) { - auto sqrtMinusOne = std::sqrt (static_cast (numChannels)) - 1.0f; - auto ambisonicOrder = jmax (0, static_cast (std::floor (sqrtMinusOne))); + const auto ambisonicOrder = AudioChannelSet::getAmbisonicOrderForNumChannels (static_cast (numChannels)); - if (static_cast (ambisonicOrder) == sqrtMinusOne) + if (ambisonicOrder != -1) return AudioChannelSet::ambisonic (ambisonicOrder).getChannelTypes(); } diff --git a/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp b/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp index b0593bb349..cda04184c7 100644 --- a/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp +++ b/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp @@ -51,7 +51,7 @@ void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double ne { auto bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer); - if (newSampleRate != sampleRate + if (! approximatelyEqual (newSampleRate, sampleRate) || bufferSizeNeeded != buffer.getNumSamples() || ! isPrepared) { diff --git a/modules/juce_audio_basics/sources/juce_MemoryAudioSource.cpp b/modules/juce_audio_basics/sources/juce_MemoryAudioSource.cpp index 2c8387f5bf..605534aceb 100644 --- a/modules/juce_audio_basics/sources/juce_MemoryAudioSource.cpp +++ b/modules/juce_audio_basics/sources/juce_MemoryAudioSource.cpp @@ -184,7 +184,7 @@ struct MemoryAudioSourceTests : public UnitTest play (source, channelInfo); for (int sample = 0; sample < buffer.getNumSamples(); ++sample) - expect (bufferToFill.getSample (0, sample + buffer.getNumSamples()) == buffer.getSample (0, sample)); + expectEquals (bufferToFill.getSample (0, sample + buffer.getNumSamples()), buffer.getSample (0, sample)); expect (! isSilent (bufferToFill)); } @@ -219,7 +219,7 @@ struct MemoryAudioSourceTests : public UnitTest for (int i = 0; i < 100; ++i) { play (source, channelInfo); - expect (bufferToFill.getSample (0, 0) == buffer.getSample (0, (i * blockSize) % buffer.getNumSamples())); + expectEquals (bufferToFill.getSample (0, 0), buffer.getSample (0, (i * blockSize) % buffer.getNumSamples())); } } } diff --git a/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp b/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp index e4887270f4..e936ae2ac4 100644 --- a/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp +++ b/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp @@ -88,7 +88,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf localRatio = ratio; } - if (lastRatio != localRatio) + if (! approximatelyEqual (lastRatio, localRatio)) { createLowPass (localRatio); lastRatio = localRatio; diff --git a/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp b/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp index 0ad3e0b97d..4b9aef4a4b 100644 --- a/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp +++ b/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp @@ -62,7 +62,7 @@ void ToneGeneratorAudioSource::releaseResources() void ToneGeneratorAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info) { - if (phasePerSample == 0.0) + if (approximatelyEqual (phasePerSample, 0.0)) phasePerSample = MathConstants::twoPi / (sampleRate / frequency); for (int i = 0; i < info.numSamples; ++i) diff --git a/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp b/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp index f9aaff23f0..f6e611e1ce 100644 --- a/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp +++ b/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp @@ -153,7 +153,7 @@ void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples, bool shoul //============================================================================== void Synthesiser::setCurrentPlaybackSampleRate (const double newRate) { - if (sampleRate != newRate) + if (! approximatelyEqual (sampleRate, newRate)) { const ScopedLock sl (lock); allNotesOff (0, false); @@ -171,7 +171,7 @@ void Synthesiser::processNextBlock (AudioBuffer& outputAudio, int numSamples) { // must set the sample rate before using this! - jassert (sampleRate != 0); + jassert (! exactlyEqual (sampleRate, 0.0)); const int targetChannels = outputAudio.getNumChannels(); auto midiIterator = midiData.findNextSamplePosition (startSample); diff --git a/modules/juce_audio_basics/utilities/juce_Interpolators.h b/modules/juce_audio_basics/utilities/juce_Interpolators.h index 0b2d454cdb..ccee0fcdf6 100644 --- a/modules/juce_audio_basics/utilities/juce_Interpolators.h +++ b/modules/juce_audio_basics/utilities/juce_Interpolators.h @@ -73,7 +73,7 @@ private: sign = (sincPosition < 0 ? -1 : 1); } - if (sincPosition == 0.0f) + if (approximatelyEqual (sincPosition, 0.0f)) result += inputs[samplePosition]; else if (sincPosition < floatCrossings && sincPosition > -floatCrossings) result += inputs[samplePosition] * windowedSinc (firstFrac, index); diff --git a/modules/juce_audio_basics/utilities/juce_SmoothedValue.h b/modules/juce_audio_basics/utilities/juce_SmoothedValue.h index e210705ebd..4c0b21197b 100644 --- a/modules/juce_audio_basics/utilities/juce_SmoothedValue.h +++ b/modules/juce_audio_basics/utilities/juce_SmoothedValue.h @@ -237,7 +237,8 @@ public: SmoothedValue (FloatType initialValue) noexcept { // Multiplicative smoothed values cannot ever reach 0! - jassert (! (std::is_same_v && initialValue == 0)); + jassert (! (std::is_same_v + && approximatelyEqual (initialValue, (FloatType) 0))); // Visual Studio can't handle base class initialisation with CRTP this->currentValue = initialValue; @@ -270,7 +271,7 @@ public: */ void setTargetValue (FloatType newValue) noexcept { - if (newValue == this->target) + if (approximatelyEqual (newValue, this->target)) return; if (stepsToTarget <= 0) @@ -280,7 +281,8 @@ public: } // Multiplicative smoothed values cannot ever reach 0! - jassert (! (std::is_same_v && newValue == 0)); + jassert (! (std::is_same_v + && approximatelyEqual (newValue, (FloatType) 0))); this->target = newValue; this->countdown = stepsToTarget; diff --git a/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp b/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp index 8eced815da..2fea9724d8 100644 --- a/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp +++ b/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp @@ -56,7 +56,7 @@ void MidiMessageCollector::addMessageToQueue (const MidiMessage& message) // the messages that come in here need to be time-stamped correctly - see MidiInput // for details of what the number should be. - jassert (message.getTimeStamp() != 0); + jassert (! approximatelyEqual (message.getTimeStamp(), 0.0)); auto sampleNumber = (int) ((message.getTimeStamp() - 0.001 * lastCallbackTime) * sampleRate); diff --git a/modules/juce_audio_devices/native/juce_Audio_ios.cpp b/modules/juce_audio_devices/native/juce_Audio_ios.cpp index 8d971a2f1e..4c94a1655d 100644 --- a/modules/juce_audio_devices/native/juce_Audio_ios.cpp +++ b/modules/juce_audio_devices/native/juce_Audio_ios.cpp @@ -938,7 +938,7 @@ struct iOSAudioIODevice::Pimpl : public AsyncUpdater { if (! firstHostTime) { - if ((time->mSampleTime - lastSampleTime) != lastNumFrames) + if (! approximatelyEqual ((time->mSampleTime - lastSampleTime), (double) lastNumFrames)) xrun++; } else @@ -1159,7 +1159,7 @@ struct iOSAudioIODevice::Pimpl : public AsyncUpdater &desc, &dataSize); - if (desc.mSampleRate != 0 && desc.mSampleRate != sampleRate) + if (! approximatelyEqual (desc.mSampleRate, 0.0) && ! approximatelyEqual (desc.mSampleRate, sampleRate)) { JUCE_IOS_AUDIO_LOG ("Stream format has changed: Sample rate " << desc.mSampleRate); triggerAsyncUpdate(); diff --git a/modules/juce_audio_devices/native/juce_CoreAudio_mac.cpp b/modules/juce_audio_devices/native/juce_CoreAudio_mac.cpp index 2c13a85385..abec5bf3a5 100644 --- a/modules/juce_audio_devices/native/juce_CoreAudio_mac.cpp +++ b/modules/juce_audio_devices/native/juce_CoreAudio_mac.cpp @@ -966,7 +966,7 @@ public: jassert (timestamp == nullptr || (((timestamp->mFlags & kAudioTimeStampSampleTimeValid) != 0) && ((timestamp->mFlags & kAudioTimeStampHostTimeValid) != 0))); - if (previousSampleTime == invalidSampleTime) + if (exactlyEqual (previousSampleTime, invalidSampleTime)) previousSampleTime = timestamp != nullptr ? timestamp->mSampleTime : 0.0; if (timestamp != nullptr && std::fabs (previousSampleTime - timestamp->mSampleTime) >= 1.0) @@ -1091,7 +1091,7 @@ private: if (! updateDetailsFromDevice()) owner.stopInternal(); - else if ((oldBufferSize != bufferSize || oldSampleRate != sampleRate) && owner.shouldRestartDevice()) + else if ((oldBufferSize != bufferSize || ! approximatelyEqual (oldSampleRate, sampleRate)) && owner.shouldRestartDevice()) owner.restart(); } @@ -1577,7 +1577,7 @@ public: { auto deviceSampleRate = d->getCurrentSampleRate(); - if (deviceSampleRate != sampleRateRequested) + if (! approximatelyEqual (deviceSampleRate, sampleRateRequested)) { if (! getAvailableSampleRates().contains (deviceSampleRate)) return; @@ -1912,7 +1912,7 @@ private: for (auto& d : getDeviceWrappers()) { - if (d->getCurrentSampleRate() != currentSampleRate) + if (! approximatelyEqual (d->getCurrentSampleRate(), currentSampleRate)) { d->setCurrentSampleRate (currentSampleRate); anySampleRateChanges = true; diff --git a/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp b/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp index e743ae6682..3fed533790 100644 --- a/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp +++ b/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp @@ -111,15 +111,16 @@ namespace FlacNamespace #endif JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion", - "-Wshadow", "-Wdeprecated-register", - "-Wswitch-enum", - "-Wswitch-default", + "-Wfloat-equal", "-Wimplicit-fallthrough", - "-Wzero-as-null-pointer-constant", - "-Wsign-conversion", + "-Wlanguage-extension-token", "-Wredundant-decls", - "-Wlanguage-extension-token") + "-Wshadow", + "-Wsign-conversion", + "-Wswitch-default", + "-Wswitch-enum", + "-Wzero-as-null-pointer-constant") #if JUCE_INTEL #if JUCE_32BIT diff --git a/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp b/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp index cf105e9bbe..fb13398828 100644 --- a/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp +++ b/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp @@ -37,20 +37,21 @@ namespace OggVorbisNamespace #if JUCE_INCLUDE_OGGVORBIS_CODE || ! defined (JUCE_INCLUDE_OGGVORBIS_CODE) JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4305 4189 4706 4995 4365 4456 4457 4459 6297 6011 6001 6308 6255 6386 6385 6246 6387 6263 6262 28182) - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion", - "-Wshadow", - "-Wfloat-conversion", - "-Wdeprecated-register", + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align", + "-Wconversion", "-Wdeprecated-declarations", - "-Wswitch-enum", - "-Wzero-as-null-pointer-constant", - "-Wsign-conversion", - "-Wswitch-default", - "-Wredundant-decls", + "-Wdeprecated-register", + "-Wfloat-conversion", + "-Wfloat-equal", + "-Wmaybe-uninitialized", "-Wmisleading-indentation", "-Wmissing-prototypes", - "-Wcast-align", - "-Wmaybe-uninitialized") + "-Wredundant-decls", + "-Wshadow", + "-Wsign-conversion", + "-Wswitch-default", + "-Wswitch-enum", + "-Wzero-as-null-pointer-constant") JUCE_BEGIN_NO_SANITIZE ("undefined") #include "oggvorbis/vorbisenc.h" diff --git a/modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h b/modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h index 7eb88a2d9a..38e800695e 100644 --- a/modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h +++ b/modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h @@ -50,7 +50,7 @@ struct VSTWindowUtilities comp->addToDesktop (desktopFlags | defaultFlags, parentView); // (this workaround is because Wavelab provides a zero-size parent view..) - if ([parentView frame].size.height == 0) + if (approximatelyEqual ([parentView frame].size.height, 0.0)) [((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint]; comp->setVisible (true); diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp index e89309d79f..8b033278f9 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp @@ -35,16 +35,17 @@ #include JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4127 4512 4996) -JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wnon-virtual-dtor", - "-Wsign-conversion", +JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations", "-Wextra-semi", - "-Wshift-sign-overflow", - "-Wpragma-pack", - "-Wzero-as-null-pointer-constant", - "-Winconsistent-missing-destructor-override", + "-Wfloat-equal", "-Wfour-char-constants", + "-Winconsistent-missing-destructor-override", + "-Wnon-virtual-dtor", + "-Wpragma-pack", + "-Wshift-sign-overflow", + "-Wsign-conversion", "-Wtautological-overlap-compare", - "-Wdeprecated-declarations") + "-Wzero-as-null-pointer-constant") #include @@ -1004,7 +1005,7 @@ namespace AAXClasses { auto newValue = static_cast (value); - if (newValue != param->getValue()) + if (! approximatelyEqual (newValue, param->getValue())) { param->setValue (newValue); diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp index 8eef0dc85d..0db3c76e5a 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp @@ -40,12 +40,13 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wzero-as-null-pointer-constant") #include JUCE_END_IGNORE_WARNINGS_GCC_LIKE -JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wunused-parameter", - "-Wshift-sign-overflow", +JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations", "-Wextra-semi", - "-Wzero-as-null-pointer-constant", + "-Wfloat-equal", "-Winconsistent-missing-destructor-override", - "-Wdeprecated-declarations") + "-Wshift-sign-overflow", + "-Wunused-parameter", + "-Wzero-as-null-pointer-constant") JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6001 6053 4996 5033 4068 4996) #include diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm index 63b25421eb..68f761cb3e 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm @@ -29,21 +29,22 @@ #if JucePlugin_Build_AU -JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wshorten-64-to-32", - "-Wunused-parameter", - "-Wdeprecated-declarations", - "-Wsign-conversion", +JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align", "-Wconversion", - "-Woverloaded-virtual", + "-Wdeprecated-anon-enum-enum-conversion", + "-Wdeprecated-declarations", "-Wextra-semi", - "-Wcast-align", + "-Wfloat-equal", + "-Wformat-pedantic", + "-Wgnu-zero-variadic-macro-arguments", + "-Wnullable-to-nonnull-conversion", + "-Woverloaded-virtual", "-Wshadow", + "-Wshorten-64-to-32", + "-Wsign-conversion", "-Wswitch-enum", - "-Wzero-as-null-pointer-constant", - "-Wnullable-to-nonnull-conversion", - "-Wgnu-zero-variadic-macro-arguments", - "-Wformat-pedantic", - "-Wdeprecated-anon-enum-enum-conversion") + "-Wunused-parameter", + "-Wzero-as-null-pointer-constant") #include @@ -1066,7 +1067,7 @@ public: { auto value = inValue / getMaximumParameterValue (param); - if (value != param->getValue()) + if (! approximatelyEqual (value, param->getValue())) { inParameterChangedCallback = true; param->setValueNotifyingHost (value); @@ -1634,7 +1635,7 @@ public: static NSTimeInterval lastEventTime = 0; // check we're not recursively sending the same event NSTimeInterval eventTime = [[NSApp currentEvent] timestamp]; - if (lastEventTime != eventTime) + if (! approximatelyEqual (lastEventTime, eventTime)) { lastEventTime = eventTime; diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm index ef4ff9dea3..bf11de1ae2 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm @@ -29,28 +29,29 @@ #include -JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wparentheses", - "-Wextra-tokens", +JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wambiguous-reversed-operator", + "-Wc99-extensions", + "-Wcast-align", "-Wcomment", "-Wconversion", - "-Wunused-parameter", - "-Wunused", + "-Wdeprecated-anon-enum-enum-conversion", "-Wextra-semi", + "-Wextra-tokens", + "-Wfloat-equal", "-Wformat-pedantic", + "-Wfour-char-constants", "-Wgnu-zero-variadic-macro-arguments", - "-Wshadow-all", - "-Wcast-align", - "-Wswitch-enum", - "-Wimplicit-fallthrough", - "-Wzero-as-null-pointer-constant", - "-Wnullable-to-nonnull-conversion", "-Wignored-qualifiers", - "-Wfour-char-constants", + "-Wimplicit-fallthrough", "-Wmissing-prototypes", - "-Wdeprecated-anon-enum-enum-conversion", - "-Wambiguous-reversed-operator", + "-Wnullable-to-nonnull-conversion", + "-Wparentheses", + "-Wshadow-all", + "-Wswitch-enum", "-Wunknown-attributes", - "-Wc99-extensions") + "-Wunused", + "-Wunused-parameter", + "-Wzero-as-null-pointer-constant") // From MacOS 10.13 and iOS 11 Apple has (sensibly!) stopped defining a whole // set of functions with rather generic names. However, we still need a couple diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm index 3cbc21ae79..4c57621a5b 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm @@ -1350,7 +1350,7 @@ private: void setAudioProcessorParameter (AudioProcessorParameter* juceParam, float value) { - if (value != juceParam->getValue()) + if (! approximatelyEqual (value, juceParam->getValue())) { juceParam->setValue (value); @@ -1458,7 +1458,7 @@ private: const auto numProcessorBusesOut = AudioUnitHelpers::getBusCount (processor, false); - if (lastTimeStamp.mSampleTime != timestamp->mSampleTime) + if (! approximatelyEqual (lastTimeStamp.mSampleTime, timestamp->mSampleTime)) { // process params and incoming midi (only once for a given timestamp) midiMessages.clear(); diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp b/modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp index 16d14a3365..9bc4b0be1a 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp @@ -156,7 +156,7 @@ public: return value; }(); - if (scaledValue != param->getValue()) + if (! approximatelyEqual (scaledValue, param->getValue())) { ScopedValueSetter scope (ignoreCallbacks, true); param->setValueNotifyingHost (scaledValue); @@ -326,7 +326,7 @@ public: info->setBpm (parser.parseNumericAtom (atomBeatsPerMinute)); info->setPpqPosition (parser.parseNumericAtom (atomBeat)); - info->setIsPlaying (parser.parseNumericAtom (atomSpeed).orFallback (0.0f) != 0.0f); + info->setIsPlaying (! approximatelyEqual (parser.parseNumericAtom (atomSpeed).orFallback (0.0f), 0.0f)); info->setBarCount (parser.parseNumericAtom (atomBar)); if (const auto parsed = parser.parseNumericAtom (atomFrame)) diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp index 487b356b6f..2b5bf335df 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp @@ -552,7 +552,7 @@ public: if (detail::PluginUtilities::getHostType().isAbletonLive() && hostCallback != nullptr - && processor->getTailLengthSeconds() == std::numeric_limits::infinity()) + && std::isinf (processor->getTailLengthSeconds())) { AbletonLiveHostSpecific hostCmd; @@ -645,7 +645,7 @@ public: }()); const auto effectiveRate = info.getFrameRate().hasValue() ? info.getFrameRate()->getEffectiveRate() : 0.0; - info.setEditOriginTime (effectiveRate != 0.0 ? makeOptional (ti->smpteOffset / (80.0 * effectiveRate)) : nullopt); + info.setEditOriginTime (! approximatelyEqual (effectiveRate, 0.0) ? makeOptional (ti->smpteOffset / (80.0 * effectiveRate)) : nullopt); } info.setIsRecording ((ti->flags & Vst2::kVstTransportRecording) != 0); @@ -1395,7 +1395,7 @@ private: void setValueAndNotifyIfChanged (AudioProcessorParameter& param, float newValue) { - if (param.getValue() == newValue) + if (approximatelyEqual (param.getValue(), newValue)) return; inParameterChangedCallback = true; @@ -1896,7 +1896,7 @@ private: auto tailSeconds = processor->getTailLengthSeconds(); - if (tailSeconds == std::numeric_limits::infinity()) + if (std::isinf (tailSeconds)) result = std::numeric_limits::max(); else result = static_cast (tailSeconds * sampleRate); diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp index 3226ff9bd3..648fb4ea52 100644 --- a/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp +++ b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp @@ -701,7 +701,7 @@ static thread_local bool inParameterChangedCallback = false; static void setValueAndNotifyIfChanged (AudioProcessorParameter& param, float newValue) { - if (param.getValue() == newValue) + if (approximatelyEqual (param.getValue(), newValue)) return; const InParameterChangedCallbackSetter scopedSetter { inParameterChangedCallback }; @@ -830,7 +830,7 @@ public: { v = jlimit (0.0, 1.0, v); - if (v != valueNormalized) + if (! approximatelyEqual (v, valueNormalized)) { valueNormalized = v; @@ -910,7 +910,7 @@ public: if (programValue != owner.getCurrentProgram()) owner.setCurrentProgram (programValue); - if (valueNormalized != v) + if (! approximatelyEqual (valueNormalized, v)) { valueNormalized = v; changed(); @@ -1931,7 +1931,7 @@ private: auto aspectRatio = (float) constrainer->getFixedAspectRatio(); - if (aspectRatio != 0.0) + if (! approximatelyEqual (aspectRatio, 0.0f)) { bool adjustWidth = (width / height > aspectRatio); @@ -1939,9 +1939,9 @@ private: { auto currentEditorBounds = editor->getBounds().toFloat(); - if (currentEditorBounds.getWidth() == width && currentEditorBounds.getHeight() != height) + if (approximatelyEqual (currentEditorBounds.getWidth(), width) && ! approximatelyEqual (currentEditorBounds.getHeight(), height)) adjustWidth = true; - else if (currentEditorBounds.getHeight() == height && currentEditorBounds.getWidth() != width) + else if (approximatelyEqual (currentEditorBounds.getHeight(), height) && ! approximatelyEqual (currentEditorBounds.getWidth(), width)) adjustWidth = false; } @@ -2322,7 +2322,7 @@ private: { const auto previous = std::exchange (scaleFactor, newFactor).get(); - if (previous == scaleFactor.get()) + if (approximatelyEqual (previous, scaleFactor.get())) return; if (owner != nullptr) @@ -3422,7 +3422,7 @@ public: if (tailLengthSeconds <= 0.0 || processSetup.sampleRate <= 0.0) return Vst::kNoTail; - if (tailLengthSeconds == std::numeric_limits::infinity()) + if (std::isinf (tailLengthSeconds)) return Vst::kInfiniteTail; return (Steinberg::uint32) roundToIntAccurate (tailLengthSeconds * processSetup.sampleRate); diff --git a/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm b/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm index f125569f68..6540a88213 100644 --- a/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm +++ b/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm @@ -1247,7 +1247,7 @@ public: AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, scope, static_cast (i), &sampleRate, &sampleRateSize); - if (sampleRate != sr) + if (! approximatelyEqual (sampleRate, sr)) { if (isAUv3) // setting kAudioUnitProperty_SampleRate fails on AUv3s { @@ -2739,7 +2739,7 @@ private: if (@available (macOS 10.11, *)) size = [controller preferredContentSize]; - if (size.width == 0 || size.height == 0) + if (approximatelyEqual (size.width, 0.0) || approximatelyEqual (size.height, 0.0)) size = controller.view.frame.size; return CGSizeMake (jmax ((CGFloat) 20.0f, size.width), diff --git a/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp index 6121dd84e8..275f2be8a8 100644 --- a/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp @@ -457,7 +457,7 @@ private: { const ScopedLock sl (pluginInstance.lock); - if (paramValue.unscaled != newValue) + if (! approximatelyEqual (paramValue.unscaled, newValue)) paramValue = ParameterValue (getNewParamScaled (interface->PortRangeHints [paramID], newValue), newValue); } } diff --git a/modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp index 00a017567c..78eb016c14 100644 --- a/modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp @@ -3287,7 +3287,7 @@ private: { if (auto* r = ref.getComponent()) { - if (std::exchange (r->nativeScaleFactor, platformScale) == platformScale) + if (approximatelyEqual (std::exchange (r->nativeScaleFactor, platformScale), platformScale)) return; r->nativeScaleFactor = platformScale; diff --git a/modules/juce_audio_processors/format_types/juce_LV2SupportLibs.cpp b/modules/juce_audio_processors/format_types/juce_LV2SupportLibs.cpp index f5e7880af2..d6459e33f9 100644 --- a/modules/juce_audio_processors/format_types/juce_LV2SupportLibs.cpp +++ b/modules/juce_audio_processors/format_types/juce_LV2SupportLibs.cpp @@ -31,6 +31,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wc99-extensions", "-Wdeprecated-declarations", "-Wextra-semi", "-Wfloat-conversion", + "-Wfloat-equal", + "-Wformat-overflow", "-Wimplicit-float-conversion", "-Wimplicit-int-conversion", "-Wmicrosoft-include", @@ -44,8 +46,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wc99-extensions", "-Wsign-conversion", "-Wswitch-enum", "-Wunused-parameter", - "-Wzero-as-null-pointer-constant", - "-Wformat-overflow") + "-Wzero-as-null-pointer-constant") JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4100 4200 4244 4267 4389 4702 4706 4800 4996 6308 28182 28183 6385 6386 6387 6011 6282 6323 6330 6001 6031) extern "C" diff --git a/modules/juce_audio_processors/format_types/juce_VST3Headers.h b/modules/juce_audio_processors/format_types/juce_VST3Headers.h index cd757c3962..72fb0c1e23 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3Headers.h +++ b/modules/juce_audio_processors/format_types/juce_VST3Headers.h @@ -32,44 +32,45 @@ // Wow, those Steinberg guys really don't worry too much about compiler warnings. JUCE_BEGIN_IGNORE_WARNINGS_LEVEL_MSVC (0, 4505 4702 6011 6031 6221 6386 6387 6330 6001 28199) -JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-copy-dtor", - "-Wnon-virtual-dtor", - "-Wdeprecated", - "-Wreorder", - "-Wunsequenced", - "-Wint-to-pointer-cast", - "-Wunused-parameter", +JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-W#warnings", + "-Wcast-align", + "-Wclass-memaccess", + "-Wcomma", "-Wconversion", - "-Woverloaded-virtual", - "-Wshadow", - "-Wdeprecated-register", - "-Wunused-function", - "-Wsign-conversion", - "-Wsign-compare", + "-Wcpp", "-Wdelete-non-virtual-dtor", + "-Wdeprecated", + "-Wdeprecated-copy-dtor", "-Wdeprecated-declarations", + "-Wdeprecated-register", + "-Wextra", "-Wextra-semi", - "-Wmissing-braces", - "-Wswitch-default", - "-Wshadow-field", - "-Wpragma-pack", - "-Wcomma", - "-Wzero-as-null-pointer-constant", - "-Winconsistent-missing-destructor-override", - "-Wcast-align", + "-Wfloat-equal", + "-Wformat", + "-Wformat=", "-Wignored-qualifiers", + "-Winconsistent-missing-destructor-override", + "-Wint-to-pointer-cast", + "-Wmaybe-uninitialized", + "-Wmissing-braces", "-Wmissing-field-initializers", - "-Wformat=", - "-Wformat", - "-Wpedantic", - "-Wextra", - "-Wclass-memaccess", "-Wmissing-prototypes", + "-Wnon-virtual-dtor", + "-Woverloaded-virtual", + "-Wpedantic", + "-Wpragma-pack", + "-Wreorder", + "-Wshadow", + "-Wshadow-field", + "-Wsign-compare", + "-Wsign-conversion", + "-Wswitch-default", "-Wtype-limits", - "-Wcpp", - "-W#warnings", - "-Wmaybe-uninitialized", - "-Wunused-but-set-variable") + "-Wunsequenced", + "-Wunused-but-set-variable", + "-Wunused-function", + "-Wunused-parameter", + "-Wzero-as-null-pointer-constant") #undef DEVELOPMENT #define DEVELOPMENT 0 // This avoids a Clang warning in Steinberg code about unused values diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index 81ec00d690..e5d2f78313 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -2498,7 +2498,7 @@ public: // Avoid redundantly calling things like setActive, which can be a heavy-duty call for some plugins: if (isActive - && getSampleRate() == newSampleRate + && approximatelyEqual (getSampleRate(), newSampleRate) && getBlockSize() == estimatedSamplesPerBlock) return; @@ -3432,7 +3432,7 @@ private: // call was processBlockBypassed, otherwise do nothing if (processBlockBypassedCalled) { - if (bypassParam != nullptr && (bypassParam->getValue() == 0.0f || ! lastProcessBlockCallWasBypass)) + if (bypassParam != nullptr && (approximatelyEqual (bypassParam->getValue(), 0.0f) || ! lastProcessBlockCallWasBypass)) bypassParam->setValue (1.0f); } else @@ -3618,7 +3618,7 @@ tresult VST3HostContext::performEdit (Vst::ParamID paramID, Vst::ParamValue valu param->setValueNotifyingHost ((float) valueNormalised); // did the plug-in already update the parameter internally - if (plugin->editController->getParamNormalized (paramID) != (float) valueNormalised) + if (! approximatelyEqual (plugin->editController->getParamNormalized (paramID), valueNormalised)) return plugin->editController->setParamNormalized (paramID, valueNormalised); return kResultTrue; diff --git a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat_test.cpp b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat_test.cpp index 305a705cba..15b420501e 100644 --- a/modules/juce_audio_processors/format_types/juce_VST3PluginFormat_test.cpp +++ b/modules/juce_audio_processors/format_types/juce_VST3PluginFormat_test.cpp @@ -584,7 +584,7 @@ private: bool allMatch (int channel, float value) const { const auto& buf = buffers[(size_t) channel]; - return std::all_of (buf.begin(), buf.end(), [&] (auto x) { return x == value; }); + return std::all_of (buf.begin(), buf.end(), [&] (auto x) { return exactlyEqual (x, value); }); } bool isClear (int channel) const @@ -607,13 +607,13 @@ private: static bool channelStartsWithValue (Steinberg::Vst::AudioBusBuffers& bus, size_t index, float value) { - return bus.channelBuffers32[index][0] == value; + return exactlyEqual (bus.channelBuffers32[index][0], value); } static bool allMatch (const AudioBuffer& buf, int index, float value) { const auto* ptr = buf.getReadPointer (index); - return std::all_of (ptr, ptr + buf.getNumSamples(), [&] (auto x) { return x == value; }); + return std::all_of (ptr, ptr + buf.getNumSamples(), [&] (auto x) { return exactlyEqual (x, value); }); } struct MultiBusBuffers diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index dd3b17b42b..893d244f12 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -904,7 +904,7 @@ struct VSTPluginInstance final : public AudioPluginInstance, { const ScopedLock sl (pluginInstance.lock); - if (effect->getParameter (effect, getParameterIndex()) != newValue) + if (! approximatelyEqual (effect->getParameter (effect, getParameterIndex()), newValue)) effect->setParameter (effect, getParameterIndex(), newValue); } } @@ -2004,7 +2004,7 @@ private: void setValue (float newValue) override { - currentValue = (newValue != 0.0f); + currentValue = (! approximatelyEqual (newValue, 0.0f)); if (parent.vstSupportsBypass) parent.dispatch (Vst2::effSetBypass, 0, currentValue ? 1 : 0, nullptr, 0.0f); @@ -2028,7 +2028,7 @@ private: float getValue() const override { return currentValue; } float getDefaultValue() const override { return 0.0f; } String getName (int /*maximumStringLength*/) const override { return "Bypass"; } - String getText (float value, int) const override { return (value != 0.0f ? TRANS("On") : TRANS("Off")); } + String getText (float value, int) const override { return (! approximatelyEqual (value, 0.0f) ? TRANS("On") : TRANS("Off")); } bool isAutomatable() const override { return true; } bool isDiscrete() const override { return true; } bool isBoolean() const override { return true; } @@ -2740,7 +2740,7 @@ private: { if (processBlockBypassedCalled) { - if (bypassParam->getValue() == 0.0f || ! lastProcessBlockCallWasBypass) + if (approximatelyEqual (bypassParam->getValue(), 0.0f) || ! lastProcessBlockCallWasBypass) bypassParam->setValue (1.0f); } else diff --git a/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h b/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h index 2234d2c5ae..b6b6054678 100644 --- a/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h +++ b/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h @@ -127,7 +127,7 @@ public: if (processor != nullptr) { if (auto* bypassParam = processor->getBypassParameter()) - return (bypassParam->getValue() != 0.0f); + return ! approximatelyEqual (bypassParam->getValue(), 0.0f); } return bypassed; diff --git a/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp b/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp index d67be5b857..7e32b8b776 100644 --- a/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp +++ b/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp @@ -378,7 +378,7 @@ private: { auto newVal = (float) slider.getValue(); - if (getParameter().getValue() != newVal) + if (! approximatelyEqual (getParameter().getValue(), newVal)) { if (! isDragging) getParameter().beginChangeGesture(); diff --git a/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp b/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp index a9f84d3a69..5ac42137c3 100644 --- a/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp +++ b/modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp @@ -44,7 +44,7 @@ AudioParameterFloat::AudioParameterFloat (const ParameterID& idToUse, { int numDecimalPlaces = 7; - if (range.interval != 0.0f) + if (! approximatelyEqual (range.interval, 0.0f)) { if (approximatelyEqual (std::abs (range.interval - std::floor (range.interval)), 0.0f)) return 0; @@ -95,7 +95,7 @@ void AudioParameterFloat::valueChanged (float) {} AudioParameterFloat& AudioParameterFloat::operator= (float newValue) { - if (value != newValue) + if (! approximatelyEqual ((float) value, newValue)) setValueNotifyingHost (convertTo0to1 (newValue)); return *this; diff --git a/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp b/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp index 7e75bc1458..fa9f91ab99 100644 --- a/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp +++ b/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp @@ -52,13 +52,11 @@ bool AudioProcessorValueTreeState::Parameter::isBoolean() const { return void AudioProcessorValueTreeState::Parameter::valueChanged (float newValue) { - if (lastValue == newValue) + if (approximatelyEqual ((float) lastValue, newValue)) return; lastValue = newValue; - - if (onValueChanged != nullptr) - onValueChanged(); + NullCheckedInvocation::invoke (onValueChanged); } //============================================================================== @@ -93,10 +91,8 @@ public: void setDenormalisedValue (float value) { - if (value == unnormalisedValue) - return; - - setNormalisedValue (normalise (value)); + if (! approximatelyEqual (value, (float) unnormalisedValue)) + setNormalisedValue (normalise (value)); } float getDenormalisedValueForText (const String& text) const @@ -119,9 +115,9 @@ public: if (! needsUpdate.compare_exchange_strong (needsUpdateTestValue, false)) return false; - if (auto valueProperty = tree.getPropertyPointer (key)) + if (auto* valueProperty = tree.getPropertyPointer (key)) { - if ((float) *valueProperty != unnormalisedValue) + if (! approximatelyEqual ((float) *valueProperty, unnormalisedValue.load())) { ScopedValueSetter svs (ignoreParameterChangedCallbacks, true); tree.setProperty (key, unnormalisedValue.load(), um); @@ -144,7 +140,7 @@ private: { const auto newValue = denormalise (parameter.getValue()); - if (unnormalisedValue == newValue && ! listenersNeedCalling) + if (! listenersNeedCalling && approximatelyEqual ((float) unnormalisedValue, newValue)) return; unnormalisedValue = newValue; diff --git a/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp b/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp index 73edfe010a..3c092a16ec 100644 --- a/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp +++ b/modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp @@ -84,7 +84,7 @@ void ParameterAttachment::callIfParameterValueChanged (float newDenormalisedValu { const auto newValue = normalise (newDenormalisedValue); - if (parameter.getValue() != newValue) + if (! approximatelyEqual (parameter.getValue(), newValue)) callback (newValue); } diff --git a/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp b/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp index 8dfb6d6588..fcf922ee15 100644 --- a/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp +++ b/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp @@ -722,7 +722,7 @@ private: auto currentRate = currentDevice->getCurrentSampleRate(); - if (currentRate == 0) + if (exactlyEqual (currentRate, 0.0)) currentRate = 48000.0; for (auto bs : currentDevice->getAvailableBufferSizes()) diff --git a/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp b/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp index 377b70edcd..31b13de0f9 100644 --- a/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp +++ b/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp @@ -501,8 +501,8 @@ private: if (numSamples == numSamplesCached && numChannelsCached == numChans - && startTime == cachedStart - && timePerPixel == cachedTimePerPixel + && approximatelyEqual (startTime, cachedStart) + && approximatelyEqual (timePerPixel, cachedTimePerPixel) && ! cacheNeedsRefilling) { return ! cacheNeedsRefilling; diff --git a/modules/juce_audio_utils/gui/juce_KeyboardComponentBase.cpp b/modules/juce_audio_utils/gui/juce_KeyboardComponentBase.cpp index 64db4b6056..048a53b41c 100644 --- a/modules/juce_audio_utils/gui/juce_KeyboardComponentBase.cpp +++ b/modules/juce_audio_utils/gui/juce_KeyboardComponentBase.cpp @@ -79,7 +79,7 @@ void KeyboardComponentBase::setKeyWidth (float widthInPixels) { jassert (widthInPixels > 0); - if (keyWidth != widthInPixels) // Prevent infinite recursion if the width is being computed in a 'resized()' callback + if (! approximatelyEqual (keyWidth, widthInPixels)) // Prevent infinite recursion if the width is being computed in a 'resized()' callback { keyWidth = widthInPixels; resized(); @@ -130,7 +130,7 @@ void KeyboardComponentBase::setLowestVisibleKeyFloat (float noteNumber) { noteNumber = jlimit ((float) rangeStart, (float) rangeEnd, noteNumber); - if (noteNumber != firstKey) + if (! approximatelyEqual (noteNumber, firstKey)) { bool hasMoved = (((int) firstKey) != (int) noteNumber); firstKey = noteNumber; @@ -151,7 +151,7 @@ void KeyboardComponentBase::setBlackNoteLengthProportion (float ratio) noexcept { jassert (ratio >= 0.0f && ratio <= 1.0f); - if (blackNoteLengthRatio != ratio) + if (! approximatelyEqual (blackNoteLengthRatio, ratio)) { blackNoteLengthRatio = ratio; resized(); @@ -168,7 +168,7 @@ void KeyboardComponentBase::setBlackNoteWidthProportion (float ratio) noexcept { jassert (ratio >= 0.0f && ratio <= 1.0f); - if (blackNoteWidthRatio != ratio) + if (! approximatelyEqual (blackNoteWidthRatio, ratio)) { blackNoteWidthRatio = ratio; resized(); @@ -452,7 +452,7 @@ void KeyboardComponentBase::resized() //============================================================================== void KeyboardComponentBase::mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel) { - auto amount = (orientation == horizontalKeyboard && wheel.deltaX != 0) + auto amount = (orientation == horizontalKeyboard && ! approximatelyEqual (wheel.deltaX, 0.0f)) ? wheel.deltaX : (orientation == verticalKeyboardFacingLeft ? wheel.deltaY : -wheel.deltaY); diff --git a/modules/juce_box2d/juce_box2d.cpp b/modules/juce_box2d/juce_box2d.cpp index c73151e38a..bd5181a756 100644 --- a/modules/juce_box2d/juce_box2d.cpp +++ b/modules/juce_box2d/juce_box2d.cpp @@ -35,15 +35,16 @@ #include "juce_box2d.h" JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011) -JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion", - "-Wsign-conversion", +JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align", + "-Wconversion", "-Wfloat-conversion", - "-Wcast-align", - "-Wswitch-enum", + "-Wfloat-equal", + "-Wmaybe-uninitialized", + "-Wsign-conversion", "-Wswitch-default", + "-Wswitch-enum", "-Wunused-but-set-variable", - "-Wzero-as-null-pointer-constant", - "-Wmaybe-uninitialized") + "-Wzero-as-null-pointer-constant") #include diff --git a/modules/juce_box2d/juce_box2d.h b/modules/juce_box2d/juce_box2d.h index 64593859ae..a1a2249cbe 100644 --- a/modules/juce_box2d/juce_box2d.h +++ b/modules/juce_box2d/juce_box2d.h @@ -56,11 +56,12 @@ #include JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion", + "-Wdeprecated", + "-Wfloat-equal", + "-Wmaybe-uninitialized", "-Wshadow-field", - "-Wzero-as-null-pointer-constant", "-Wsign-conversion", - "-Wdeprecated", - "-Wmaybe-uninitialized") + "-Wzero-as-null-pointer-constant") #include #include diff --git a/modules/juce_core/containers/juce_Array.h b/modules/juce_core/containers/juce_Array.h index 316e54526f..33f1e58b2b 100644 --- a/modules/juce_core/containers/juce_Array.h +++ b/modules/juce_core/containers/juce_Array.h @@ -404,7 +404,7 @@ public: auto endPtr = values.end(); for (; e != endPtr; ++e) - if (elementToLookFor == *e) + if (exactlyEqual (elementToLookFor, *e)) return true; return false; diff --git a/modules/juce_core/containers/juce_ArrayBase.h b/modules/juce_core/containers/juce_ArrayBase.h index 353fcfae50..d24d562160 100644 --- a/modules/juce_core/containers/juce_ArrayBase.h +++ b/modules/juce_core/containers/juce_ArrayBase.h @@ -123,7 +123,7 @@ public: auto* e = begin(); for (auto& o : other) - if (! (*e++ == o)) + if (! exactlyEqual (*e++, o)) return false; return true; diff --git a/modules/juce_core/containers/juce_Variant.cpp b/modules/juce_core/containers/juce_Variant.cpp index e84baa02af..12b1394f83 100644 --- a/modules/juce_core/containers/juce_Variant.cpp +++ b/modules/juce_core/containers/juce_Variant.cpp @@ -201,7 +201,7 @@ struct var::VariantType static int64 doubleToInt64 (const ValueUnion& data) noexcept { return (int64) data.doubleValue; } static double doubleToDouble (const ValueUnion& data) noexcept { return data.doubleValue; } static String doubleToString (const ValueUnion& data) { return serialiseDouble (data.doubleValue); } - static bool doubleToBool (const ValueUnion& data) noexcept { return data.doubleValue != 0.0; } + static bool doubleToBool (const ValueUnion& data) noexcept { return ! exactlyEqual (data.doubleValue, 0.0); } static bool doubleEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept { @@ -645,7 +645,7 @@ static int compare (const var& v1, const var& v2) return v1.toString().compare (v2.toString()); auto diff = static_cast (v1) - static_cast (v2); - return diff == 0 ? 0 : (diff < 0 ? -1 : 1); + return exactlyEqual (diff, 0.0) ? 0 : (diff < 0 ? -1 : 1); } bool operator== (const var& v1, const var& v2) { return v1.equals (v2); } diff --git a/modules/juce_core/javascript/juce_Javascript.cpp b/modules/juce_core/javascript/juce_Javascript.cpp index e1a8f6c0f9..3a1f9ba8b9 100644 --- a/modules/juce_core/javascript/juce_Javascript.cpp +++ b/modules/juce_core/javascript/juce_Javascript.cpp @@ -520,7 +520,7 @@ struct JavascriptEngine::RootObject : public DynamicObject { EqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::equals) {} var getWithUndefinedArg() const override { return true; } - var getWithDoubles (double a, double b) const override { return a == b; } + var getWithDoubles (double a, double b) const override { return exactlyEqual (a, b); } var getWithInts (int64 a, int64 b) const override { return a == b; } var getWithStrings (const String& a, const String& b) const override { return a == b; } var getWithArrayOrObject (const var& a, const var& b) const override { return a == b; } @@ -530,7 +530,7 @@ struct JavascriptEngine::RootObject : public DynamicObject { NotEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::notEquals) {} var getWithUndefinedArg() const override { return false; } - var getWithDoubles (double a, double b) const override { return a != b; } + var getWithDoubles (double a, double b) const override { return ! exactlyEqual (a, b); } var getWithInts (int64 a, int64 b) const override { return a != b; } var getWithStrings (const String& a, const String& b) const override { return a != b; } var getWithArrayOrObject (const var& a, const var& b) const override { return a != b; } @@ -593,14 +593,14 @@ struct JavascriptEngine::RootObject : public DynamicObject struct DivideOp : public BinaryOperator { DivideOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {} - var getWithDoubles (double a, double b) const override { return b != 0 ? a / b : std::numeric_limits::infinity(); } + var getWithDoubles (double a, double b) const override { return exactlyEqual (b, 0.0) ? std::numeric_limits::infinity() : a / b; } var getWithInts (int64 a, int64 b) const override { return b != 0 ? var ((double) a / (double) b) : var (std::numeric_limits::infinity()); } }; struct ModuloOp : public BinaryOperator { ModuloOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {} - var getWithDoubles (double a, double b) const override { return b != 0 ? fmod (a, b) : std::numeric_limits::infinity(); } + var getWithDoubles (double a, double b) const override { return exactlyEqual (b, 0.0) ? std::numeric_limits::infinity() : fmod (a, b); } var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a % b) : var (std::numeric_limits::infinity()); } }; diff --git a/modules/juce_core/maths/juce_MathsFunctions.h b/modules/juce_core/maths/juce_MathsFunctions.h index cc61820ec7..f47ea1154c 100644 --- a/modules/juce_core/maths/juce_MathsFunctions.h +++ b/modules/juce_core/maths/juce_MathsFunctions.h @@ -86,6 +86,29 @@ 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. +*/ +template +bool approximatelyEqual (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(); +} + +/** 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 + semantics. +*/ +template +constexpr bool exactlyEqual (Type a, Type b) +{ + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wfloat-equal") + return a == b; + JUCE_END_IGNORE_WARNINGS_GCC_LIKE +} + //============================================================================== // Some indispensable min/max functions @@ -126,7 +149,7 @@ constexpr Type jmap (Type value0To1, Type targetRangeMin, Type targetRangeMax) template Type jmap (Type sourceValue, Type sourceRangeMin, Type sourceRangeMax, Type targetRangeMin, Type targetRangeMax) { - jassert (sourceRangeMax != sourceRangeMin); // mapping from a range of zero will produce NaN! + jassert (! approximatelyEqual (sourceRangeMax, sourceRangeMin)); // mapping from a range of zero will produce NaN! return targetRangeMin + ((targetRangeMax - targetRangeMin) * (sourceValue - sourceRangeMin)) / (sourceRangeMax - sourceRangeMin); } @@ -317,16 +340,6 @@ bool isWithin (Type a, Type b, Type tolerance) noexcept return std::abs (a - b) <= tolerance; } -/** Returns true if the two numbers are approximately equal. This is useful for floating-point - and double comparisons. -*/ -template -bool approximatelyEqual (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(); -} - //============================================================================== /** Handy function for avoiding unused variables warning. */ template diff --git a/modules/juce_core/maths/juce_NormalisableRange.h b/modules/juce_core/maths/juce_NormalisableRange.h index 2909a5dc52..d2eafa0bbe 100644 --- a/modules/juce_core/maths/juce_NormalisableRange.h +++ b/modules/juce_core/maths/juce_NormalisableRange.h @@ -128,7 +128,7 @@ public: auto proportion = clampTo0To1 ((v - start) / (end - start)); - if (skew == static_cast (1)) + if (exactlyEqual (skew, static_cast (1))) return proportion; if (! symmetricSkew) @@ -154,7 +154,7 @@ public: if (! symmetricSkew) { - if (skew != static_cast (1) && proportion > ValueType()) + if (! exactlyEqual (skew, static_cast (1)) && proportion > ValueType()) proportion = std::exp (std::log (proportion) / skew); return start + (end - start) * proportion; @@ -162,7 +162,7 @@ public: auto distanceFromMiddle = static_cast (2) * proportion - static_cast (1); - if (skew != static_cast (1) && distanceFromMiddle != static_cast (0)) + if (! exactlyEqual (skew, static_cast (1)) && ! exactlyEqual (distanceFromMiddle, static_cast (0))) distanceFromMiddle = std::exp (std::log (std::abs (distanceFromMiddle)) / skew) * (distanceFromMiddle < ValueType() ? static_cast (-1) : static_cast (1)); @@ -250,7 +250,7 @@ private: // If you hit this assertion then either your normalisation function is not working // correctly or your input is out of the expected bounds. - jassert (clampedValue == value); + jassert (exactlyEqual (clampedValue, value)); return clampedValue; } diff --git a/modules/juce_core/maths/juce_Random.cpp b/modules/juce_core/maths/juce_Random.cpp index df9b266526..b98dc5e6f2 100644 --- a/modules/juce_core/maths/juce_Random.cpp +++ b/modules/juce_core/maths/juce_Random.cpp @@ -103,7 +103,7 @@ float Random::nextFloat() noexcept { auto result = static_cast (static_cast (nextInt())) / (static_cast (std::numeric_limits::max()) + 1.0f); - return result == 1.0f ? 1.0f - std::numeric_limits::epsilon() : result; + return jmin (result, 1.0f - std::numeric_limits::epsilon()); } double Random::nextDouble() noexcept diff --git a/modules/juce_core/maths/juce_Range.h b/modules/juce_core/maths/juce_Range.h index 9a71195999..f5eb531815 100644 --- a/modules/juce_core/maths/juce_Range.h +++ b/modules/juce_core/maths/juce_Range.h @@ -86,7 +86,7 @@ public: constexpr inline ValueType getEnd() const noexcept { return end; } /** Returns true if the range has a length of zero. */ - constexpr inline bool isEmpty() const noexcept { return start == end; } + constexpr inline bool isEmpty() const noexcept { return exactlyEqual (start, end); } //============================================================================== /** Changes the start position of the range, leaving the end position unchanged. @@ -198,8 +198,13 @@ public: return Range (start - amountToSubtract, end - amountToSubtract); } - constexpr bool operator== (Range other) const noexcept { return start == other.start && end == other.end; } - constexpr bool operator!= (Range other) const noexcept { return start != other.start || end != other.end; } + constexpr bool operator== (Range other) const noexcept + { + const auto tie = [] (const Range& r) { return std::tie (r.start, r.end); }; + return tie (*this) == tie (other); + } + + constexpr bool operator!= (Range other) const noexcept { return ! operator== (other); } //============================================================================== /** Returns true if the given position lies inside this range. diff --git a/modules/juce_core/streams/juce_MemoryInputStream.cpp b/modules/juce_core/streams/juce_MemoryInputStream.cpp index 5e60dd612d..800646731e 100644 --- a/modules/juce_core/streams/juce_MemoryInputStream.cpp +++ b/modules/juce_core/streams/juce_MemoryInputStream.cpp @@ -138,8 +138,8 @@ public: expectEquals (mi.readString(), randomString); expect (mi.readInt64() == randomInt64); expect (mi.readInt64BigEndian() == randomInt64); - expect (mi.readDouble() == randomDouble); - expect (mi.readDoubleBigEndian() == randomDouble); + expectEquals (mi.readDouble(), randomDouble); + expectEquals (mi.readDoubleBigEndian(), randomDouble); const MemoryBlock data ("abcdefghijklmnopqrstuvwxyz", 26); MemoryInputStream stream (data, true); diff --git a/modules/juce_core/system/juce_CompilerWarnings.h b/modules/juce_core/system/juce_CompilerWarnings.h index 05845903f3..e13af095d6 100644 --- a/modules/juce_core/system/juce_CompilerWarnings.h +++ b/modules/juce_core/system/juce_CompilerWarnings.h @@ -31,7 +31,8 @@ #define JUCE_NTH_ARG_(_00, _01, _02, _03, _04, _05, _06, _07, _08, _09, \ _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \ _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ - _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, N, ...)\ + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, N, ...)\ N #define JUCE_EACH_00_(FN) @@ -74,10 +75,30 @@ #define JUCE_EACH_37_(FN, X, ...) FN(X) JUCE_EACH_36_(FN, __VA_ARGS__) #define JUCE_EACH_38_(FN, X, ...) FN(X) JUCE_EACH_37_(FN, __VA_ARGS__) #define JUCE_EACH_39_(FN, X, ...) FN(X) JUCE_EACH_38_(FN, __VA_ARGS__) +#define JUCE_EACH_40_(FN, X, ...) FN(X) JUCE_EACH_39_(FN, __VA_ARGS__) +#define JUCE_EACH_41_(FN, X, ...) FN(X) JUCE_EACH_40_(FN, __VA_ARGS__) +#define JUCE_EACH_42_(FN, X, ...) FN(X) JUCE_EACH_41_(FN, __VA_ARGS__) +#define JUCE_EACH_43_(FN, X, ...) FN(X) JUCE_EACH_42_(FN, __VA_ARGS__) +#define JUCE_EACH_44_(FN, X, ...) FN(X) JUCE_EACH_43_(FN, __VA_ARGS__) +#define JUCE_EACH_45_(FN, X, ...) FN(X) JUCE_EACH_44_(FN, __VA_ARGS__) +#define JUCE_EACH_46_(FN, X, ...) FN(X) JUCE_EACH_45_(FN, __VA_ARGS__) +#define JUCE_EACH_47_(FN, X, ...) FN(X) JUCE_EACH_46_(FN, __VA_ARGS__) +#define JUCE_EACH_48_(FN, X, ...) FN(X) JUCE_EACH_47_(FN, __VA_ARGS__) +#define JUCE_EACH_49_(FN, X, ...) FN(X) JUCE_EACH_48_(FN, __VA_ARGS__) /** Apply the macro FN to each of the other arguments. */ #define JUCE_EACH(FN, ...) \ JUCE_NTH_ARG_(, __VA_ARGS__, \ + JUCE_EACH_49_, \ + JUCE_EACH_48_, \ + JUCE_EACH_47_, \ + JUCE_EACH_46_, \ + JUCE_EACH_45_, \ + JUCE_EACH_44_, \ + JUCE_EACH_43_, \ + JUCE_EACH_42_, \ + JUCE_EACH_41_, \ + JUCE_EACH_40_, \ JUCE_EACH_39_, \ JUCE_EACH_38_, \ JUCE_EACH_37_, \ diff --git a/modules/juce_core/text/juce_CharacterFunctions.cpp b/modules/juce_core/text/juce_CharacterFunctions.cpp index f1b466ffbb..407e70a688 100644 --- a/modules/juce_core/text/juce_CharacterFunctions.cpp +++ b/modules/juce_core/text/juce_CharacterFunctions.cpp @@ -134,7 +134,7 @@ double CharacterFunctions::mulexp10 (const double value, int exponent) noexcept if (exponent == 0) return value; - if (value == 0.0) + if (exactlyEqual (value, 0.0)) return 0; const bool negative = (exponent < 0); diff --git a/modules/juce_core/text/juce_String.cpp b/modules/juce_core/text/juce_String.cpp index 02c2c8f8a1..4675f1ec78 100644 --- a/modules/juce_core/text/juce_String.cpp +++ b/modules/juce_core/text/juce_String.cpp @@ -2266,7 +2266,7 @@ static String serialiseDouble (double input) int intInput = (int) input; - if ((double) intInput == input) + if (exactlyEqual ((double) intInput, input)) return { input, 1 }; auto numberOfDecimalPlaces = [absInput] @@ -2567,16 +2567,16 @@ public: beginTest ("Numeric conversions"); expect (String().getIntValue() == 0); - expect (String().getDoubleValue() == 0.0); - expect (String().getFloatValue() == 0.0f); + expectEquals (String().getDoubleValue(), 0.0); + expectEquals (String().getFloatValue(), 0.0f); expect (s.getIntValue() == 12345678); expect (s.getLargeIntValue() == (int64) 12345678); - expect (s.getDoubleValue() == 12345678.0); - expect (s.getFloatValue() == 12345678.0f); + expectEquals (s.getDoubleValue(), 12345678.0); + expectEquals (s.getFloatValue(), 12345678.0f); expect (String (-1234).getIntValue() == -1234); expect (String ((int64) -1234).getLargeIntValue() == -1234); - expect (String (-1234.56).getDoubleValue() == -1234.56); - expect (String (-1234.56f).getFloatValue() == -1234.56f); + expectEquals (String (-1234.56).getDoubleValue(), -1234.56); + expectEquals (String (-1234.56f).getFloatValue(), -1234.56f); expect (String (std::numeric_limits::max()).getIntValue() == std::numeric_limits::max()); expect (String (std::numeric_limits::min()).getIntValue() == std::numeric_limits::min()); expect (String (std::numeric_limits::max()).getLargeIntValue() == std::numeric_limits::max()); diff --git a/modules/juce_core/text/juce_String.h b/modules/juce_core/text/juce_String.h index e24f79ba5f..f7f72906f0 100644 --- a/modules/juce_core/text/juce_String.h +++ b/modules/juce_core/text/juce_String.h @@ -1117,7 +1117,7 @@ public: { jassert (numberOfSignificantFigures > 0); - if (number == 0) + if (exactlyEqual (number, DecimalType())) { if (numberOfSignificantFigures > 1) { diff --git a/modules/juce_core/threads/juce_Thread.cpp b/modules/juce_core/threads/juce_Thread.cpp index 5b870311c4..cae9308695 100644 --- a/modules/juce_core/threads/juce_Thread.cpp +++ b/modules/juce_core/threads/juce_Thread.cpp @@ -417,7 +417,7 @@ public: class AtomicTester { public: - AtomicTester() {} + AtomicTester() = default; static void testInteger (UnitTest& test) { @@ -460,17 +460,17 @@ public: /* These are some simple test cases to check the atomics - let me know if any of these assertions fail on your system! */ - test.expect (a.get() == (Type) 101); + test.expect (exactlyEqual (a.get(), (Type) 101)); test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200)); - test.expect (a.get() == (Type) 101); + test.expect (exactlyEqual (a.get(), (Type) 101)); test.expect (a.compareAndSetBool ((Type) 200, a.get())); - test.expect (a.get() == (Type) 200); + test.expect (exactlyEqual (a.get(), (Type) 200)); - test.expect (a.exchange ((Type) 300) == (Type) 200); - test.expect (a.get() == (Type) 300); + test.expect (exactlyEqual (a.exchange ((Type) 300), (Type) 200)); + test.expect (exactlyEqual (a.get(), (Type) 300)); b = a; - test.expect (b.get() == a.get()); + test.expect (exactlyEqual (b.get(), a.get())); } }; }; diff --git a/modules/juce_core/time/juce_RelativeTime.cpp b/modules/juce_core/time/juce_RelativeTime.cpp index 60b1a1e9a5..bd8c233d86 100644 --- a/modules/juce_core/time/juce_RelativeTime.cpp +++ b/modules/juce_core/time/juce_RelativeTime.cpp @@ -54,8 +54,16 @@ RelativeTime RelativeTime::operator-= (double secs) noexcept { numSeconds JUCE_API RelativeTime JUCE_CALLTYPE operator+ (RelativeTime t1, RelativeTime t2) noexcept { return t1 += t2; } JUCE_API RelativeTime JUCE_CALLTYPE operator- (RelativeTime t1, RelativeTime t2) noexcept { return t1 -= t2; } -JUCE_API bool JUCE_CALLTYPE operator== (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() == t2.inSeconds(); } -JUCE_API bool JUCE_CALLTYPE operator!= (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() != t2.inSeconds(); } +JUCE_API bool JUCE_CALLTYPE operator== (RelativeTime t1, RelativeTime t2) noexcept +{ + return exactlyEqual (t1.inSeconds(), t2.inSeconds()); +} + +JUCE_API bool JUCE_CALLTYPE operator!= (RelativeTime t1, RelativeTime t2) noexcept +{ + return ! (t1 == t2); +} + JUCE_API bool JUCE_CALLTYPE operator> (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() > t2.inSeconds(); } JUCE_API bool JUCE_CALLTYPE operator< (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() < t2.inSeconds(); } JUCE_API bool JUCE_CALLTYPE operator>= (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() >= t2.inSeconds(); } diff --git a/modules/juce_core/unit_tests/juce_UnitTest.h b/modules/juce_core/unit_tests/juce_UnitTest.h index 1685f5bcf0..96c5fb884c 100644 --- a/modules/juce_core/unit_tests/juce_UnitTest.h +++ b/modules/juce_core/unit_tests/juce_UnitTest.h @@ -150,7 +150,7 @@ public: template void expectEquals (ValueType actual, ValueType expected, String failureMessage = String()) { - bool result = actual == expected; + bool result = exactlyEqual (actual, expected); expectResultAndPrint (actual, expected, result, "", failureMessage); } @@ -160,7 +160,7 @@ public: template void expectNotEquals (ValueType value, ValueType valueToCompareTo, String failureMessage = String()) { - bool result = value != valueToCompareTo; + bool result = ! exactlyEqual (value, valueToCompareTo); expectResultAndPrint (value, valueToCompareTo, result, "unequal to", failureMessage); } diff --git a/modules/juce_data_structures/values/juce_CachedValue.h b/modules/juce_data_structures/values/juce_CachedValue.h index 0ce17a863b..38cd2ad928 100644 --- a/modules/juce_data_structures/values/juce_CachedValue.h +++ b/modules/juce_data_structures/values/juce_CachedValue.h @@ -245,7 +245,7 @@ inline CachedValue& CachedValue::operator= (const Type& newValue) template inline void CachedValue::setValue (const Type& newValue, UndoManager* undoManagerToUse) { - if (cachedValue != newValue || isUsingDefault()) + if (! exactlyEqual (cachedValue, newValue) || isUsingDefault()) { cachedValue = newValue; targetTree.setProperty (targetProperty, VariantConverter::toVar (newValue), undoManagerToUse); diff --git a/modules/juce_dsp/containers/juce_AudioBlock_test.cpp b/modules/juce_dsp/containers/juce_AudioBlock_test.cpp index 17ffad601f..bfd2f8aa48 100644 --- a/modules/juce_dsp/containers/juce_AudioBlock_test.cpp +++ b/modules/juce_dsp/containers/juce_AudioBlock_test.cpp @@ -28,6 +28,9 @@ namespace juce namespace dsp { +template +String& operator<< (String& str, SIMDRegister) { return str; } + template class AudioBlockUnitTests : public UnitTest { @@ -79,25 +82,25 @@ public: resetBlocks(); expect (block != otherBlock); - expect (block.getSample (0, 0) == SampleType (1.0)); - expect (block.getSample (0, 4) == SampleType (5.0)); - expect (otherBlock.getSample (0, 0) == SampleType (-1.0)); - expect (otherBlock.getSample (0, 3) == SampleType (-4.0)); + expectEquals (block.getSample (0, 0), SampleType (1.0)); + expectEquals (block.getSample (0, 4), SampleType (5.0)); + expectEquals (otherBlock.getSample (0, 0), SampleType (-1.0)); + expectEquals (otherBlock.getSample (0, 3), SampleType (-4.0)); block.swap (otherBlock); expect (block != otherBlock); - expect (otherBlock.getSample (0, 0) == SampleType (1.0)); - expect (otherBlock.getSample (0, 4) == SampleType (5.0)); - expect (block.getSample (0, 0) == SampleType (-1.0)); - expect (block.getSample (0, 3) == SampleType (-4.0)); + expectEquals (otherBlock.getSample (0, 0), SampleType (1.0)); + expectEquals (otherBlock.getSample (0, 4), SampleType (5.0)); + expectEquals (block.getSample (0, 0), SampleType (-1.0)); + expectEquals (block.getSample (0, 3), SampleType (-4.0)); block.swap (otherBlock); - expect (block.getSample (0, 0) == SampleType (1.0)); - expect (block.getSample (0, 4) == SampleType (5.0)); - expect (otherBlock.getSample (0, 0) == SampleType (-1.0)); - expect (otherBlock.getSample (0, 3) == SampleType (-4.0)); + expectEquals (block.getSample (0, 0), SampleType (1.0)); + expectEquals (block.getSample (0, 4), SampleType (5.0)); + expectEquals (otherBlock.getSample (0, 0), SampleType (-1.0)); + expectEquals (otherBlock.getSample (0, 3), SampleType (-4.0)); } beginTest ("Getters and setters"); @@ -107,49 +110,49 @@ public: expectEquals ((int) block.getNumChannels(), (int) data.size()); expectEquals ((int) block.getNumSamples(), numSamples); - expect (block.getChannelPointer (0)[2] == SampleType (3.0)); + expectEquals (block.getChannelPointer (0)[2], SampleType (3.0)); block.getChannelPointer (0)[2] = SampleType (999.0); - expect (block.getChannelPointer (0)[2] == SampleType (999.0)); + expectEquals (block.getChannelPointer (0)[2], SampleType (999.0)); - expect (block.getSample (0, 4) == SampleType (5.0)); - expect (block.getSample (1, 4) == SampleType (11.0)); + expectEquals (block.getSample (0, 4), SampleType (5.0)); + expectEquals (block.getSample (1, 4), SampleType (11.0)); - expect (block.getSingleChannelBlock (1).getSample (0, 3) == block.getSample (1, 3)); + expectEquals (block.getSingleChannelBlock (1).getSample (0, 3), block.getSample (1, 3)); - expect (block.getSubsetChannelBlock (0, 2).getSample (1, 3) == block.getSample (1, 3)); - expect (block.getSubsetChannelBlock (1, 1).getSample (0, 3) == block.getSample (1, 3)); + expectEquals (block.getSubsetChannelBlock (0, 2).getSample (1, 3), block.getSample (1, 3)); + expectEquals (block.getSubsetChannelBlock (1, 1).getSample (0, 3), block.getSample (1, 3)); block.setSample (1, 1, SampleType (777.0)); - expect (block.getSample (1, 1) == SampleType (777.0)); + expectEquals (block.getSample (1, 1), SampleType (777.0)); block.addSample (1, 1, SampleType (1.0)); - expect (block.getSample (1, 1) == SampleType (778.0)); + expectEquals (block.getSample (1, 1), SampleType (778.0)); } beginTest ("Basic copying"); { block.clear(); - expect (block.getSample (0, 2) == SampleType (0.0)); - expect (block.getSample (1, 4) == SampleType (0.0)); + expectEquals (block.getSample (0, 2), SampleType (0.0)); + expectEquals (block.getSample (1, 4), SampleType (0.0)); block.fill ((NumericType) 456.0); - expect (block.getSample (0, 2) == SampleType (456.0)); - expect (block.getSample (1, 4) == SampleType (456.0)); + expectEquals (block.getSample (0, 2), SampleType (456.0)); + expectEquals (block.getSample (1, 4), SampleType (456.0)); block.copyFrom (otherBlock); expect (block != otherBlock); - expect (block.getSample (0, 2) == otherBlock.getSample (0, 2)); - expect (block.getSample (1, 4) == otherBlock.getSample (1, 4)); + expectEquals (block.getSample (0, 2), otherBlock.getSample (0, 2)); + expectEquals (block.getSample (1, 4), otherBlock.getSample (1, 4)); resetBlocks(); SampleType testSample1 = block.getSample (0, 2); SampleType testSample2 = block.getSample (1, 3); - expect (testSample1 != block.getSample (0, 4)); - expect (testSample2 != block.getSample (1, 5)); + expectNotEquals (testSample1, block.getSample (0, 4)); + expectNotEquals (testSample2, block.getSample (1, 5)); block.move (0, 2); - expect (block.getSample (0, 4) == testSample1); - expect (block.getSample (1, 5) == testSample2); + expectEquals (block.getSample (0, 4), testSample1); + expectEquals (block.getSample (1, 5), testSample2); } beginTest ("Addition"); @@ -157,22 +160,22 @@ public: resetBlocks(); block.add ((NumericType) 15.0); - expect (block.getSample (0, 4) == SampleType (20.0)); - expect (block.getSample (1, 4) == SampleType (26.0)); + expectEquals (block.getSample (0, 4), SampleType (20.0)); + expectEquals (block.getSample (1, 4), SampleType (26.0)); block.add (otherBlock); - expect (block.getSample (0, 4) == SampleType (15.0)); - expect (block.getSample (1, 4) == SampleType (15.0)); + expectEquals (block.getSample (0, 4), SampleType (15.0)); + expectEquals (block.getSample (1, 4), SampleType (15.0)); block.replaceWithSumOf (otherBlock, (NumericType) 9.0); - expect (block.getSample (0, 4) == SampleType (4.0)); - expect (block.getSample (1, 4) == SampleType (-2.0)); + expectEquals (block.getSample (0, 4), SampleType (4.0)); + expectEquals (block.getSample (1, 4), SampleType (-2.0)); resetBlocks(); block.replaceWithSumOf (block, otherBlock); - expect (block.getSample (0, 4) == SampleType (0.0)); - expect (block.getSample (1, 4) == SampleType (0.0)); + expectEquals (block.getSample (0, 4), SampleType (0.0)); + expectEquals (block.getSample (1, 4), SampleType (0.0)); } beginTest ("Subtraction"); @@ -180,22 +183,22 @@ public: resetBlocks(); block.subtract ((NumericType) 15.0); - expect (block.getSample (0, 4) == SampleType (-10.0)); - expect (block.getSample (1, 4) == SampleType (-4.0)); + expectEquals (block.getSample (0, 4), SampleType (-10.0)); + expectEquals (block.getSample (1, 4), SampleType (-4.0)); block.subtract (otherBlock); - expect (block.getSample (0, 4) == SampleType (-5.0)); - expect (block.getSample (1, 4) == SampleType (7.0)); + expectEquals (block.getSample (0, 4), SampleType (-5.0)); + expectEquals (block.getSample (1, 4), SampleType (7.0)); block.replaceWithDifferenceOf (otherBlock, (NumericType) 9.0); - expect (block.getSample (0, 4) == SampleType (-14.0)); - expect (block.getSample (1, 4) == SampleType (-20.0)); + expectEquals (block.getSample (0, 4), SampleType (-14.0)); + expectEquals (block.getSample (1, 4), SampleType (-20.0)); resetBlocks(); block.replaceWithDifferenceOf (block, otherBlock); - expect (block.getSample (0, 4) == SampleType (10.0)); - expect (block.getSample (1, 4) == SampleType (22.0)); + expectEquals (block.getSample (0, 4), SampleType (10.0)); + expectEquals (block.getSample (1, 4), SampleType (22.0)); } beginTest ("Multiplication"); @@ -203,22 +206,22 @@ public: resetBlocks(); block.multiplyBy ((NumericType) 10.0); - expect (block.getSample (0, 4) == SampleType (50.0)); - expect (block.getSample (1, 4) == SampleType (110.0)); + expectEquals (block.getSample (0, 4), SampleType (50.0)); + expectEquals (block.getSample (1, 4), SampleType (110.0)); block.multiplyBy (otherBlock); - expect (block.getSample (0, 4) == SampleType (-250.0)); - expect (block.getSample (1, 4) == SampleType (-1210.0)); + expectEquals (block.getSample (0, 4), SampleType (-250.0)); + expectEquals (block.getSample (1, 4), SampleType (-1210.0)); block.replaceWithProductOf (otherBlock, (NumericType) 3.0); - expect (block.getSample (0, 4) == SampleType (-15.0)); - expect (block.getSample (1, 4) == SampleType (-33.0)); + expectEquals (block.getSample (0, 4), SampleType (-15.0)); + expectEquals (block.getSample (1, 4), SampleType (-33.0)); resetBlocks(); block.replaceWithProductOf (block, otherBlock); - expect (block.getSample (0, 4) == SampleType (-25.0)); - expect (block.getSample (1, 4) == SampleType (-121.0)); + expectEquals (block.getSample (0, 4), SampleType (-25.0)); + expectEquals (block.getSample (1, 4), SampleType (-121.0)); } beginTest ("Multiply add"); @@ -226,12 +229,12 @@ public: resetBlocks(); block.addProductOf (otherBlock, (NumericType) -1.0); - expect (block.getSample (0, 4) == SampleType (10.0)); - expect (block.getSample (1, 4) == SampleType (22.0)); + expectEquals (block.getSample (0, 4), SampleType (10.0)); + expectEquals (block.getSample (1, 4), SampleType (22.0)); block.addProductOf (otherBlock, otherBlock); - expect (block.getSample (0, 4) == SampleType (35.0)); - expect (block.getSample (1, 4) == SampleType (143.0)); + expectEquals (block.getSample (0, 4), SampleType (35.0)); + expectEquals (block.getSample (1, 4), SampleType (143.0)); } beginTest ("Negative abs min max"); @@ -240,68 +243,68 @@ public: otherBlock.negate(); block.add (otherBlock); - expect (block.getSample (0, 4) == SampleType (10.0)); - expect (block.getSample (1, 4) == SampleType (22.0)); + expectEquals (block.getSample (0, 4), SampleType (10.0)); + expectEquals (block.getSample (1, 4), SampleType (22.0)); block.replaceWithNegativeOf (otherBlock); - expect (block.getSample (0, 4) == SampleType (-5.0)); - expect (block.getSample (1, 4) == SampleType (-11.0)); + expectEquals (block.getSample (0, 4), SampleType (-5.0)); + expectEquals (block.getSample (1, 4), SampleType (-11.0)); block.clear(); otherBlock.negate(); block.replaceWithAbsoluteValueOf (otherBlock); - expect (block.getSample (0, 4) == SampleType (5.0)); - expect (block.getSample (1, 4) == SampleType (11.0)); + expectEquals (block.getSample (0, 4), SampleType (5.0)); + expectEquals (block.getSample (1, 4), SampleType (11.0)); resetBlocks(); block.replaceWithMinOf (block, otherBlock); - expect (block.getSample (0, 4) == SampleType (-5.0)); - expect (block.getSample (1, 4) == SampleType (-11.0)); + expectEquals (block.getSample (0, 4), SampleType (-5.0)); + expectEquals (block.getSample (1, 4), SampleType (-11.0)); resetBlocks(); block.replaceWithMaxOf (block, otherBlock); - expect (block.getSample (0, 4) == SampleType (5.0)); - expect (block.getSample (1, 4) == SampleType (11.0)); + expectEquals (block.getSample (0, 4), SampleType (5.0)); + expectEquals (block.getSample (1, 4), SampleType (11.0)); resetBlocks(); auto range = block.findMinAndMax(); - expect (SampleType (range.getStart()) == SampleType (1.0)); - expect (SampleType (range.getEnd()) == SampleType (12.0)); + expectEquals (SampleType (range.getStart()), SampleType (1.0)); + expectEquals (SampleType (range.getEnd()), SampleType (12.0)); } beginTest ("Operators"); { resetBlocks(); block += (NumericType) 10.0; - expect (block.getSample (0, 4) == SampleType (15.0)); - expect (block.getSample (1, 4) == SampleType (21.0)); + expectEquals (block.getSample (0, 4), SampleType (15.0)); + expectEquals (block.getSample (1, 4), SampleType (21.0)); block += otherBlock; - expect (block.getSample (0, 4) == SampleType (10.0)); - expect (block.getSample (1, 4) == SampleType (10.0)); + expectEquals (block.getSample (0, 4), SampleType (10.0)); + expectEquals (block.getSample (1, 4), SampleType (10.0)); resetBlocks(); block -= (NumericType) 10.0; - expect (block.getSample (0, 4) == SampleType (-5.0)); - expect (block.getSample (1, 4) == SampleType (1.0)); + expectEquals (block.getSample (0, 4), SampleType (-5.0)); + expectEquals (block.getSample (1, 4), SampleType (1.0)); block -= otherBlock; - expect (block.getSample (0, 4) == SampleType (0.0)); - expect (block.getSample (1, 4) == SampleType (12.0)); + expectEquals (block.getSample (0, 4), SampleType (0.0)); + expectEquals (block.getSample (1, 4), SampleType (12.0)); resetBlocks(); block *= (NumericType) 10.0; - expect (block.getSample (0, 4) == SampleType (50.0)); - expect (block.getSample (1, 4) == SampleType (110.0)); + expectEquals (block.getSample (0, 4), SampleType (50.0)); + expectEquals (block.getSample (1, 4), SampleType (110.0)); block *= otherBlock; - expect (block.getSample (0, 4) == SampleType (-250.0)); - expect (block.getSample (1, 4) == SampleType (-1210.0)); + expectEquals (block.getSample (0, 4), SampleType (-250.0)); + expectEquals (block.getSample (1, 4), SampleType (-1210.0)); } beginTest ("Process"); { resetBlocks(); AudioBlock::process (block, otherBlock, [] (SampleType x) { return x + (NumericType) 1.0; }); - expect (otherBlock.getSample (0, 4) == SampleType (6.0)); - expect (otherBlock.getSample (1, 4) == SampleType (12.0)); + expectEquals (otherBlock.getSample (0, 4), SampleType (6.0)); + expectEquals (otherBlock.getSample (1, 4), SampleType (12.0)); } beginTest ("Copying"); diff --git a/modules/juce_dsp/containers/juce_SIMDRegister_test.cpp b/modules/juce_dsp/containers/juce_SIMDRegister_test.cpp index a8881fcb77..7b2bcbc506 100644 --- a/modules/juce_dsp/containers/juce_SIMDRegister_test.cpp +++ b/modules/juce_dsp/containers/juce_SIMDRegister_test.cpp @@ -117,19 +117,12 @@ public: template static bool allValuesEqualTo (const SIMDRegister& vec, const type scalar) { - #ifdef _MSC_VER - __declspec(align(sizeof (SIMDRegister))) type elements[SIMDRegister::SIMDNumElements]; - #else - type elements[SIMDRegister::SIMDNumElements] __attribute__((aligned(sizeof (SIMDRegister)))); - #endif + alignas (sizeof (SIMDRegister)) type elements[SIMDRegister::SIMDNumElements]; vec.copyToRawArray (elements); // as we do not want to rely on the access operator we cast this to a primitive pointer - for (size_t i = 0; i < SIMDRegister::SIMDNumElements; ++i) - if (elements[i] != scalar) return false; - - return true; + return std::all_of (std::begin (elements), std::end (elements), [scalar] (const auto x) { return exactlyEqual (x, scalar); }); } template @@ -307,7 +300,7 @@ public: const SIMDRegister& b = a; for (size_t i = 0; i < SIMDRegister::SIMDNumElements; ++i) - u.expect (b[i] == array[i]); + u.expect (exactlyEqual (b[i], array[i])); } }; @@ -539,8 +532,8 @@ public: // do check for (size_t j = 0; j < SIMDRegister::SIMDNumElements; ++j) { - array_eq [j] = (array_a[j] == array_b[j]) ? static_cast (-1) : 0; - array_neq [j] = (array_a[j] != array_b[j]) ? static_cast (-1) : 0; + array_eq [j] = ( exactlyEqual (array_a[j], array_b[j])) ? static_cast (-1) : 0; + array_neq [j] = (! exactlyEqual (array_a[j], array_b[j])) ? static_cast (-1) : 0; array_lt [j] = (array_a[j] < array_b[j]) ? static_cast (-1) : 0; array_le [j] = (array_a[j] <= array_b[j]) ? static_cast (-1) : 0; array_gt [j] = (array_a[j] > array_b[j]) ? static_cast (-1) : 0; diff --git a/modules/juce_dsp/filter_design/juce_FilterDesign.cpp b/modules/juce_dsp/filter_design/juce_FilterDesign.cpp index efea14d272..5bd99b798c 100644 --- a/modules/juce_dsp/filter_design/juce_FilterDesign.cpp +++ b/modules/juce_dsp/filter_design/juce_FilterDesign.cpp @@ -145,6 +145,11 @@ typename FIR::Coefficients::Ptr auto* result = new typename FIR::Coefficients (static_cast (N)); auto* c = result->getRawCoefficients(); + auto sinc = [] (double x) + { + return approximatelyEqual (x, 0.0) ? 1 : std::sin (x * MathConstants::pi) / (MathConstants::pi * x); + }; + if (N % 2 == 1) { // Type I @@ -153,9 +158,6 @@ typename FIR::Coefficients::Ptr Matrix b (M + 1, 1), q (2 * M + 1, 1); - auto sinc = [] (double x) { return x == 0 ? 1 : std::sin (x * MathConstants::pi) - / (MathConstants::pi * x); }; - auto factorp = wp / MathConstants::pi; auto factors = ws / MathConstants::pi; @@ -191,9 +193,6 @@ typename FIR::Coefficients::Ptr Matrix qp (2 * M, 1); Matrix qs (2 * M, 1); - auto sinc = [] (double x) { return x == 0 ? 1 : std::sin (x * MathConstants::pi) - / (MathConstants::pi * x); }; - auto factorp = wp / MathConstants::pi; auto factors = ws / MathConstants::pi; diff --git a/modules/juce_dsp/frequency/juce_Convolution.cpp b/modules/juce_dsp/frequency/juce_Convolution.cpp index dbcaa64cc3..ef44a2cec9 100644 --- a/modules/juce_dsp/frequency/juce_Convolution.cpp +++ b/modules/juce_dsp/frequency/juce_Convolution.cpp @@ -647,7 +647,7 @@ static AudioBuffer resampleImpulseResponse (const AudioBuffer& buf const double srcSampleRate, const double destSampleRate) { - if (srcSampleRate == destSampleRate) + if (approximatelyEqual (srcSampleRate, destSampleRate)) return buf; const auto factorReading = srcSampleRate / destSampleRate; diff --git a/modules/juce_dsp/frequency/juce_Convolution_test.cpp b/modules/juce_dsp/frequency/juce_Convolution_test.cpp index ab676f44bb..2096d47758 100644 --- a/modules/juce_dsp/frequency/juce_Convolution_test.cpp +++ b/modules/juce_dsp/frequency/juce_Convolution_test.cpp @@ -97,7 +97,7 @@ class ConvolutionTest : public UnitTest expect (std::any_of (channel, channel + block.getNumSamples(), [] (float sample) { - return sample != 0.0f; + return ! approximatelyEqual (sample, 0.0f); })); } } @@ -193,7 +193,7 @@ class ConvolutionTest : public UnitTest processBlocksWithDiracImpulse(); // Check if the impulse response was loaded - if (block.getSample (0, 1) != 0.0f) + if (! approximatelyEqual (block.getSample (0, 1), 0.0f)) break; } } diff --git a/modules/juce_dsp/maths/juce_LogRampedValue.h b/modules/juce_dsp/maths/juce_LogRampedValue.h index 998e249413..821e07e2ee 100644 --- a/modules/juce_dsp/maths/juce_LogRampedValue.h +++ b/modules/juce_dsp/maths/juce_LogRampedValue.h @@ -108,7 +108,7 @@ public: */ void setTargetValue (FloatType newValue) noexcept { - if (newValue == this->target) + if (approximatelyEqual (newValue, this->target)) return; if (stepsToTarget <= 0) diff --git a/modules/juce_dsp/maths/juce_Matrix.cpp b/modules/juce_dsp/maths/juce_Matrix.cpp index 56c460cd30..6d5c8acd67 100644 --- a/modules/juce_dsp/maths/juce_Matrix.cpp +++ b/modules/juce_dsp/maths/juce_Matrix.cpp @@ -176,7 +176,7 @@ bool Matrix::solve (Matrix& b) const noexcept { auto denominator = A (0,0); - if (denominator == 0) + if (approximatelyEqual (denominator, (ElementType) 0)) return false; b (0, 0) /= denominator; @@ -187,7 +187,7 @@ bool Matrix::solve (Matrix& b) const noexcept { auto denominator = A (0, 0) * A (1, 1) - A (0, 1) * A (1, 0); - if (denominator == 0) + if (approximatelyEqual (denominator, (ElementType) 0)) return false; auto factor = (1 / denominator); @@ -204,7 +204,7 @@ bool Matrix::solve (Matrix& b) const noexcept + A (0, 1) * (A (1, 2) * A (2, 0) - A (1, 0) * A (2, 2)) + A (0, 2) * (A (1, 0) * A (2, 1) - A (1, 1) * A (2, 0)); - if (denominator == 0) + if (approximatelyEqual (denominator, (ElementType) 0)) return false; auto factor = 1 / denominator; @@ -231,10 +231,10 @@ bool Matrix::solve (Matrix& b) const noexcept for (size_t j = 0; j < n; ++j) { - if (M (j, j) == 0) + if (approximatelyEqual (M (j, j), (ElementType) 0)) { auto i = j; - while (i < n && M (i, j) == 0) + while (i < n && approximatelyEqual (M (i, j), (ElementType) 0)) ++i; if (i == n) diff --git a/modules/juce_dsp/processors/juce_DelayLine.h b/modules/juce_dsp/processors/juce_DelayLine.h index 0d92237606..1b9de4c875 100644 --- a/modules/juce_dsp/processors/juce_DelayLine.h +++ b/modules/juce_dsp/processors/juce_DelayLine.h @@ -271,7 +271,7 @@ private: auto value1 = bufferData.getSample (channel, index1); auto value2 = bufferData.getSample (channel, index2); - auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]); + auto output = approximatelyEqual (delayFrac, (SampleType) 0) ? value1 : value2 + alpha * (value1 - v[(size_t) channel]); v[(size_t) channel] = output; return output; diff --git a/modules/juce_dsp/processors/juce_IIRFilter_Impl.h b/modules/juce_dsp/processors/juce_IIRFilter_Impl.h index 150ab429e9..b30caf7cd7 100644 --- a/modules/juce_dsp/processors/juce_IIRFilter_Impl.h +++ b/modules/juce_dsp/processors/juce_IIRFilter_Impl.h @@ -39,8 +39,9 @@ Coefficients& Coefficients::assignImpl (const NumericT static_assert (Num % 2 == 0, "Must supply an even number of coefficients"); const auto a0Index = Num / 2; const auto a0 = values[a0Index]; - const auto a0Inv = a0 != NumericType() ? static_cast (1) / values[a0Index] - : NumericType(); + const auto a0Inv = ! approximatelyEqual (a0, NumericType()) + ? static_cast (1) / values[a0Index] + : NumericType(); coefficients.clearQuick(); coefficients.ensureStorageAllocated ((int) jmax ((size_t) 8, Num)); diff --git a/modules/juce_dsp/processors/juce_Oversampling.cpp b/modules/juce_dsp/processors/juce_Oversampling.cpp index f79c432851..8600b18e52 100644 --- a/modules/juce_dsp/processors/juce_Oversampling.cpp +++ b/modules/juce_dsp/processors/juce_Oversampling.cpp @@ -755,7 +755,7 @@ void Oversampling::updateDelayLine() auto latency = getUncompensatedLatency(); fractionalDelay = static_cast (1.0) - (latency - std::floor (latency)); - if (fractionalDelay == static_cast (1.0)) + if (approximatelyEqual (fractionalDelay, static_cast (1.0))) fractionalDelay = static_cast (0.0); else if (fractionalDelay < static_cast (0.618)) fractionalDelay += static_cast (1.0); diff --git a/modules/juce_dsp/processors/juce_ProcessContext.h b/modules/juce_dsp/processors/juce_ProcessContext.h index 983dd53634..6da17bb766 100644 --- a/modules/juce_dsp/processors/juce_ProcessContext.h +++ b/modules/juce_dsp/processors/juce_ProcessContext.h @@ -48,9 +48,12 @@ struct ProcessSpec constexpr bool operator== (const ProcessSpec& a, const ProcessSpec& b) { - return a.sampleRate == b.sampleRate - && a.maximumBlockSize == b.maximumBlockSize - && a.numChannels == b.numChannels; + const auto tie = [] (const ProcessSpec& p) + { + return std::tie (p.sampleRate, p.maximumBlockSize, p.numChannels); + }; + + return tie (a) == tie (b); } constexpr bool operator!= (const ProcessSpec& a, const ProcessSpec& b) { return ! (a == b); } diff --git a/modules/juce_dsp/processors/juce_ProcessorChain_test.cpp b/modules/juce_dsp/processors/juce_ProcessorChain_test.cpp index c820581005..80ff01fee4 100644 --- a/modules/juce_dsp/processors/juce_ProcessorChain_test.cpp +++ b/modules/juce_dsp/processors/juce_ProcessorChain_test.cpp @@ -39,7 +39,7 @@ class ProcessorChainTest : public UnitTest template void process (const Context& context) noexcept { - bufferWasClear = context.getInputBlock().getSample (0, 0) == 0; + bufferWasClear = approximatelyEqual (context.getInputBlock().getSample (0, 0), 0.0f); if (! context.isBypassed) context.getOutputBlock().add (AddValue); diff --git a/modules/juce_dsp/widgets/juce_Bias.h b/modules/juce_dsp/widgets/juce_Bias.h index cc255dad85..cbd68b86fc 100644 --- a/modules/juce_dsp/widgets/juce_Bias.h +++ b/modules/juce_dsp/widgets/juce_Bias.h @@ -64,7 +64,7 @@ public: /** Sets the length of the ramp used for smoothing gain changes. */ void setRampDurationSeconds (double newDurationSeconds) noexcept { - if (rampDurationSeconds != newDurationSeconds) + if (! approximatelyEqual (rampDurationSeconds, newDurationSeconds)) { rampDurationSeconds = newDurationSeconds; updateRamp(); diff --git a/modules/juce_dsp/widgets/juce_Gain.h b/modules/juce_dsp/widgets/juce_Gain.h index c43c240fdc..1e98dc6922 100644 --- a/modules/juce_dsp/widgets/juce_Gain.h +++ b/modules/juce_dsp/widgets/juce_Gain.h @@ -55,7 +55,7 @@ public: /** Sets the length of the ramp used for smoothing gain changes. */ void setRampDurationSeconds (double newDurationSeconds) noexcept { - if (rampDurationSeconds != newDurationSeconds) + if (! approximatelyEqual (rampDurationSeconds, newDurationSeconds)) { rampDurationSeconds = newDurationSeconds; reset(); diff --git a/modules/juce_graphics/colour/juce_ColourGradient.cpp b/modules/juce_graphics/colour/juce_ColourGradient.cpp index 4a5444e4ad..c5bf134263 100644 --- a/modules/juce_graphics/colour/juce_ColourGradient.cpp +++ b/modules/juce_graphics/colour/juce_ColourGradient.cpp @@ -30,7 +30,7 @@ ColourGradient::ColourGradient() noexcept : isRadial (false) { #if JUCE_DEBUG point1.setX (987654.0f); - #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED jassert (point1.x != 987654.0f); + #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED jassert (! exactlyEqual (point1.x, 987654.0f)); #else #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED #endif @@ -174,7 +174,7 @@ void ColourGradient::setColour (int index, Colour newColour) noexcept Colour ColourGradient::getColourAtPosition (double position) const noexcept { - jassert (colours.getReference(0).position == 0.0); // the first colour specified has to go at position 0 + jassert (approximatelyEqual (colours.getReference (0).position, 0.0)); // the first colour specified has to go at position 0 if (position <= 0 || colours.size() <= 1) return colours.getReference(0).colour; @@ -199,7 +199,7 @@ void ColourGradient::createLookupTable (PixelARGB* const lookupTable, const int JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates? jassert (colours.size() >= 2); jassert (numEntries > 0); - jassert (colours.getReference(0).position == 0.0); // The first colour specified has to go at position 0 + jassert (approximatelyEqual (colours.getReference(0).position, 0.0)); // The first colour specified has to go at position 0 int index = 0; @@ -258,12 +258,13 @@ bool ColourGradient::isInvisible() const noexcept bool ColourGradient::ColourPoint::operator== (ColourPoint other) const noexcept { - return position == other.position && colour == other.colour; + const auto tie = [] (const ColourPoint& p) { return std::tie (p.position, p.colour); }; + return tie (*this) == tie (other); } bool ColourGradient::ColourPoint::operator!= (ColourPoint other) const noexcept { - return position != other.position || colour != other.colour; + return ! operator== (other); } } // namespace juce diff --git a/modules/juce_graphics/contexts/juce_GraphicsContext.cpp b/modules/juce_graphics/contexts/juce_GraphicsContext.cpp index 640ac3b599..225145fdfe 100644 --- a/modules/juce_graphics/contexts/juce_GraphicsContext.cpp +++ b/modules/juce_graphics/contexts/juce_GraphicsContext.cpp @@ -627,7 +627,7 @@ void Graphics::drawEllipse (Rectangle area, float lineThickness) const { Path p; - if (area.getWidth() == area.getHeight()) + if (approximatelyEqual (area.getWidth(), area.getHeight())) { // For a circle, we can avoid having to generate a stroke p.addEllipse (area.expanded (lineThickness * 0.5f)); @@ -781,7 +781,7 @@ void Graphics::drawDashedLine (Line line, const float* dashLengths, const Line segment (line.getStart() + (delta * lastAlpha).toFloat(), line.getStart() + (delta * jmin (1.0, alpha)).toFloat()); - if (lineThickness != 1.0f) + if (! approximatelyEqual (lineThickness, 1.0f)) drawLine (segment, lineThickness); else context.drawLine (segment); diff --git a/modules/juce_graphics/fonts/juce_CustomTypeface.cpp b/modules/juce_graphics/fonts/juce_CustomTypeface.cpp index 11d37b084b..8e5ff75739 100644 --- a/modules/juce_graphics/fonts/juce_CustomTypeface.cpp +++ b/modules/juce_graphics/fonts/juce_CustomTypeface.cpp @@ -189,7 +189,7 @@ void CustomTypeface::addGlyph (juce_wchar character, const Path& path, float wid void CustomTypeface::addKerningPair (juce_wchar char1, juce_wchar char2, float extraAmount) noexcept { - if (extraAmount != 0.0f) + if (! approximatelyEqual (extraAmount, 0.0f)) { if (auto* g = findGlyph (char1, true)) g->addKerningPair (char2, extraAmount); diff --git a/modules/juce_graphics/fonts/juce_Font.cpp b/modules/juce_graphics/fonts/juce_Font.cpp index b6a6ec00a8..8eb2c9d372 100644 --- a/modules/juce_graphics/fonts/juce_Font.cpp +++ b/modules/juce_graphics/fonts/juce_Font.cpp @@ -291,7 +291,7 @@ public: { const ScopedLock lock (mutex); - if (ascent == 0.0f) + if (approximatelyEqual (ascent, 0.0f)) ascent = getTypefacePtr (f)->getAscent(); return height * ascent; @@ -569,7 +569,7 @@ void Font::setHeight (float newHeight) { newHeight = FontValues::limitFontHeight (newHeight); - if (font->getHeight() != newHeight) + if (! approximatelyEqual (font->getHeight(), newHeight)) { dupeInternalIfShared(); font->setHeight (newHeight); @@ -581,7 +581,7 @@ void Font::setHeightWithoutChangingWidth (float newHeight) { newHeight = FontValues::limitFontHeight (newHeight); - if (font->getHeight() != newHeight) + if (! approximatelyEqual (font->getHeight(), newHeight)) { dupeInternalIfShared(); font->setHorizontalScale (font->getHorizontalScale() * (font->getHeight() / newHeight)); @@ -626,9 +626,9 @@ void Font::setSizeAndStyle (float newHeight, { newHeight = FontValues::limitFontHeight (newHeight); - if (font->getHeight() != newHeight - || font->getHorizontalScale() != newHorizontalScale - || font->getKerning() != newKerningAmount) + if (! approximatelyEqual (font->getHeight(), newHeight) + || ! approximatelyEqual (font->getHorizontalScale(), newHorizontalScale) + || ! approximatelyEqual (font->getKerning(), newKerningAmount)) { dupeInternalIfShared(); font->setHeight (newHeight); @@ -647,9 +647,9 @@ void Font::setSizeAndStyle (float newHeight, { newHeight = FontValues::limitFontHeight (newHeight); - if (font->getHeight() != newHeight - || font->getHorizontalScale() != newHorizontalScale - || font->getKerning() != newKerningAmount) + if (! approximatelyEqual (font->getHeight(), newHeight) + || ! approximatelyEqual (font->getHorizontalScale(), newHorizontalScale) + || ! approximatelyEqual (font->getKerning(), newKerningAmount)) { dupeInternalIfShared(); font->setHeight (newHeight); @@ -748,7 +748,7 @@ float Font::getStringWidthFloat (const String& text) const { auto w = getTypefacePtr()->getStringWidth (text); - if (font->getKerning() != 0.0f) + if (! approximatelyEqual (font->getKerning(), 0.0f)) w += font->getKerning() * (float) text.length(); return w * font->getHeight() * font->getHorizontalScale(); @@ -763,7 +763,7 @@ void Font::getGlyphPositions (const String& text, Array& glyphs, ArraygetHeight() * font->getHorizontalScale(); auto* x = xOffsets.getRawDataPointer(); - if (font->getKerning() != 0.0f) + if (! approximatelyEqual (font->getKerning(), 0.0f)) { for (int i = 0; i < num; ++i) x[i] = (x[i] + (float) i * font->getKerning()) * scale; diff --git a/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp b/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp index 648acfcc25..93571e1d41 100644 --- a/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp +++ b/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp @@ -312,7 +312,7 @@ void GlyphArrangement::addFittedText (const Font& f, const String& text, Justification layout, int maximumLines, float minimumHorizontalScale) { - if (minimumHorizontalScale == 0.0f) + if (approximatelyEqual (minimumHorizontalScale, 0.0f)) minimumHorizontalScale = Font::getDefaultMinimumHorizontalScaleFactor(); // doesn't make much sense if this is outside a sensible range of 0.5 to 1.0 @@ -363,7 +363,7 @@ void GlyphArrangement::moveRangeOfGlyphs (int startIndex, int num, const float d { jassert (startIndex >= 0); - if (dx != 0.0f || dy != 0.0f) + if (! approximatelyEqual (dx, 0.0f) || ! approximatelyEqual (dy, 0.0f)) { if (num < 0 || startIndex + num > glyphs.size()) num = glyphs.size() - startIndex; @@ -491,7 +491,7 @@ void GlyphArrangement::justifyGlyphs (int startIndex, int num, { auto glyphY = glyphs.getReference (startIndex + i).getBaselineY(); - if (glyphY != baseY) + if (! approximatelyEqual (glyphY, baseY)) { spreadOutLine (startIndex + lineStart, i - lineStart, width); @@ -695,7 +695,7 @@ void GlyphArrangement::drawGlyphUnderline (const Graphics& g, const PositionedGl auto lineThickness = (pg.font.getDescent()) * 0.3f; auto nextX = pg.x + pg.w; - if (i < glyphs.size() - 1 && glyphs.getReference (i + 1).y == pg.y) + if (i < glyphs.size() - 1 && approximatelyEqual (glyphs.getReference (i + 1).y, pg.y)) nextX = glyphs.getReference (i + 1).x; Path p; diff --git a/modules/juce_graphics/fonts/juce_TextLayout.cpp b/modules/juce_graphics/fonts/juce_TextLayout.cpp index 817d5ec32c..da09e575d7 100644 --- a/modules/juce_graphics/fonts/juce_TextLayout.cpp +++ b/modules/juce_graphics/fonts/juce_TextLayout.cpp @@ -294,7 +294,7 @@ void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& te maxWidth -= 10.0f; } - if (bestWidth != maxWidth) + if (! approximatelyEqual (bestWidth, maxWidth)) createLayout (text, bestWidth, maxHeight); } diff --git a/modules/juce_graphics/fonts/juce_Typeface.cpp b/modules/juce_graphics/fonts/juce_Typeface.cpp index cc1fef4702..5c14043778 100644 --- a/modules/juce_graphics/fonts/juce_Typeface.cpp +++ b/modules/juce_graphics/fonts/juce_Typeface.cpp @@ -148,7 +148,7 @@ struct Typeface::HintingParams void applyVerticalHintingTransform (float fontSize, Path& path) { - if (cachedSize != fontSize) + if (! approximatelyEqual (cachedSize, fontSize)) { cachedSize = fontSize; cachedScale = Scaling (top, middle, bottom, fontSize); diff --git a/modules/juce_graphics/geometry/juce_AffineTransform.cpp b/modules/juce_graphics/geometry/juce_AffineTransform.cpp index d2aa599b33..ddc55c291e 100644 --- a/modules/juce_graphics/geometry/juce_AffineTransform.cpp +++ b/modules/juce_graphics/geometry/juce_AffineTransform.cpp @@ -35,12 +35,12 @@ AffineTransform::AffineTransform (float m00, float m01, float m02, bool AffineTransform::operator== (const AffineTransform& other) const noexcept { - return mat00 == other.mat00 - && mat01 == other.mat01 - && mat02 == other.mat02 - && mat10 == other.mat10 - && mat11 == other.mat11 - && mat12 == other.mat12; + const auto tie = [] (const AffineTransform& a) + { + return std::tie (a.mat00, a.mat01, a.mat02, a.mat10, a.mat11, a.mat12); + }; + + return tie (*this) == tie (other); } bool AffineTransform::operator!= (const AffineTransform& other) const noexcept @@ -51,12 +51,7 @@ bool AffineTransform::operator!= (const AffineTransform& other) const noexcept //============================================================================== bool AffineTransform::isIdentity() const noexcept { - return mat01 == 0.0f - && mat02 == 0.0f - && mat10 == 0.0f - && mat12 == 0.0f - && mat00 == 1.0f - && mat11 == 1.0f; + return operator== (AffineTransform()); } const AffineTransform AffineTransform::identity (1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); @@ -207,7 +202,7 @@ AffineTransform AffineTransform::inverted() const noexcept bool AffineTransform::isSingularity() const noexcept { - return (mat00 * mat11 - mat10 * mat01) == 0.0f; + return exactlyEqual (mat00 * mat11 - mat10 * mat01, 0.0f); } AffineTransform AffineTransform::fromTargetPoints (float x00, float y00, @@ -229,10 +224,10 @@ AffineTransform AffineTransform::fromTargetPoints (float sx1, float sy1, float t bool AffineTransform::isOnlyTranslation() const noexcept { - return mat01 == 0.0f - && mat10 == 0.0f - && mat00 == 1.0f - && mat11 == 1.0f; + return exactlyEqual (mat01, 0.0f) + && exactlyEqual (mat10, 0.0f) + && exactlyEqual (mat00, 1.0f) + && exactlyEqual (mat11, 1.0f); } float AffineTransform::getDeterminant() const noexcept diff --git a/modules/juce_graphics/geometry/juce_Line.h b/modules/juce_graphics/geometry/juce_Line.h index 940b095599..7e03191662 100644 --- a/modules/juce_graphics/geometry/juce_Line.h +++ b/modules/juce_graphics/geometry/juce_Line.h @@ -204,7 +204,7 @@ public: Point getPointAlongLine (ValueType distanceFromStart) const noexcept { const auto length = getLength(); - return length == 0 ? start : start + (end - start) * (distanceFromStart / length); + return approximatelyEqual (length, (ValueType) 0) ? start : start + (end - start) * (distanceFromStart / length); } /** Returns a point which is a certain distance along and to the side of this line. @@ -391,32 +391,32 @@ private: auto d2 = p4 - p3; auto divisor = d1.x * d2.y - d2.x * d1.y; - if (divisor == 0) + if (approximatelyEqual (divisor, 0.0f)) { if (! (d1.isOrigin() || d2.isOrigin())) { - if (d1.y == 0 && d2.y != 0) + if (approximatelyEqual (d1.y, 0.0f) && ! approximatelyEqual (d2.y, 0.0f)) { auto along = (p1.y - p3.y) / d2.y; intersection = p1.withX (p3.x + along * d2.x); return isZeroToOne (along); } - if (d2.y == 0 && d1.y != 0) + if (approximatelyEqual (d2.y, 0.0f) && ! approximatelyEqual (d1.y, 0.0f)) { auto along = (p3.y - p1.y) / d1.y; intersection = p3.withX (p1.x + along * d1.x); return isZeroToOne (along); } - if (d1.x == 0 && d2.x != 0) + if (approximatelyEqual (d1.x, 0.0f) && ! approximatelyEqual (d2.x, 0.f)) { auto along = (p1.x - p3.x) / d2.x; intersection = p1.withY (p3.y + along * d2.y); return isZeroToOne (along); } - if (d2.x == 0 && d1.x != 0) + if (approximatelyEqual (d2.x, 0.0f) && ! approximatelyEqual (d1.x, 0.0f)) { auto along = (p3.x - p1.x) / d1.x; intersection = p3.withY (p1.y + along * d1.y); diff --git a/modules/juce_graphics/geometry/juce_Path.cpp b/modules/juce_graphics/geometry/juce_Path.cpp index cf692570d7..a0ab1b3171 100644 --- a/modules/juce_graphics/geometry/juce_Path.cpp +++ b/modules/juce_graphics/geometry/juce_Path.cpp @@ -28,7 +28,7 @@ namespace juce // tests that some coordinates aren't NaNs #define JUCE_CHECK_COORDS_ARE_VALID(x, y) \ - jassert (x == x && y == y); + jassert (! std::isnan (x) && ! std::isnan (y)); //============================================================================== namespace PathHelpers @@ -58,18 +58,13 @@ namespace PathHelpers } //============================================================================== -const float Path::lineMarker = 100001.0f; -const float Path::moveMarker = 100002.0f; -const float Path::quadMarker = 100003.0f; -const float Path::cubicMarker = 100004.0f; -const float Path::closeSubPathMarker = 100005.0f; const float Path::defaultToleranceForTesting = 1.0f; const float Path::defaultToleranceForMeasurement = 0.6f; static bool isMarker (float value, float marker) noexcept { - return value == marker; + return exactlyEqual (value, marker); } //============================================================================== diff --git a/modules/juce_graphics/geometry/juce_Path.h b/modules/juce_graphics/geometry/juce_Path.h index 62dd72a18b..849dad2c26 100644 --- a/modules/juce_graphics/geometry/juce_Path.h +++ b/modules/juce_graphics/geometry/juce_Path.h @@ -827,11 +827,11 @@ private: PathBounds bounds; bool useNonZeroWinding = true; - static const float lineMarker; - static const float moveMarker; - static const float quadMarker; - static const float cubicMarker; - static const float closeSubPathMarker; + static constexpr float lineMarker = 100001.0f; + static constexpr float moveMarker = 100002.0f; + static constexpr float quadMarker = 100003.0f; + static constexpr float cubicMarker = 100004.0f; + static constexpr float closeSubPathMarker = 100005.0f; JUCE_LEAK_DETECTOR (Path) }; diff --git a/modules/juce_graphics/geometry/juce_PathIterator.cpp b/modules/juce_graphics/geometry/juce_PathIterator.cpp index 1239de232b..e883914216 100644 --- a/modules/juce_graphics/geometry/juce_PathIterator.cpp +++ b/modules/juce_graphics/geometry/juce_PathIterator.cpp @@ -138,9 +138,9 @@ bool PathFlatteningIterator::next() closesSubPath = stackPos == stackBase.get() && source != path.data.end() - && *source == Path::closeSubPathMarker - && x2 == subPathCloseX - && y2 == subPathCloseY; + && isMarker (*source, Path::closeSubPathMarker) + && approximatelyEqual (x2, subPathCloseX) + && approximatelyEqual (y2, subPathCloseY); return true; } @@ -167,8 +167,8 @@ bool PathFlatteningIterator::next() auto errorY = m3y - y2; auto outsideTolerance = errorX * errorX + errorY * errorY > toleranceSquared; - auto canBeSubdivided = (m3x != m1x && m3x != m2x) - || (m3y != m1y && m3y != m2y); + auto canBeSubdivided = (! approximatelyEqual (m3x, m1x) && ! approximatelyEqual (m3x, m2x)) + || (! approximatelyEqual (m3y, m1y) && ! approximatelyEqual (m3y, m2y)); if (outsideTolerance && canBeSubdivided) { @@ -226,10 +226,10 @@ bool PathFlatteningIterator::next() auto outsideTolerance = error1X * error1X + error1Y * error1Y > toleranceSquared || error2X * error2X + error2Y * error2Y > toleranceSquared; - auto canBeSubdivided = (m4x != m1x && m4x != m2x) - || (m4y != m1y && m4y != m2y) - || (m5x != m3x && m5x != m2x) - || (m5y != m3y && m5y != m2y); + auto canBeSubdivided = (! approximatelyEqual (m4x, m1x) && ! approximatelyEqual (m4x, m2x)) + || (! approximatelyEqual (m4y, m1y) && ! approximatelyEqual (m4y, m2y)) + || (! approximatelyEqual (m5x, m3x) && ! approximatelyEqual (m5x, m2x)) + || (! approximatelyEqual (m5y, m3y) && ! approximatelyEqual (m5y, m2y)); if (outsideTolerance && canBeSubdivided) { @@ -266,7 +266,7 @@ bool PathFlatteningIterator::next() } else if (isMarker (type, Path::closeSubPathMarker)) { - if (x2 != subPathCloseX || y2 != subPathCloseY) + if (! approximatelyEqual (x2, subPathCloseX) || ! approximatelyEqual (y2, subPathCloseY)) { x1 = x2; y1 = y2; diff --git a/modules/juce_graphics/geometry/juce_PathStrokeType.cpp b/modules/juce_graphics/geometry/juce_PathStrokeType.cpp index fae0391abc..8bfcf9de50 100644 --- a/modules/juce_graphics/geometry/juce_PathStrokeType.cpp +++ b/modules/juce_graphics/geometry/juce_PathStrokeType.cpp @@ -57,9 +57,8 @@ PathStrokeType::~PathStrokeType() noexcept bool PathStrokeType::operator== (const PathStrokeType& other) const noexcept { - return thickness == other.thickness - && jointStyle == other.jointStyle - && endStyle == other.endStyle; + const auto tie = [] (const PathStrokeType& p) { return std::tie (p.thickness, p.jointStyle, p.endStyle); }; + return tie (*this) == tie (other); } bool PathStrokeType::operator!= (const PathStrokeType& other) const noexcept @@ -70,122 +69,128 @@ bool PathStrokeType::operator!= (const PathStrokeType& other) const noexcept //============================================================================== namespace PathStrokeHelpers { - static bool lineIntersection (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3, - const float x4, const float y4, - float& intersectionX, - float& intersectionY, - float& distanceBeyondLine1EndSquared) noexcept + struct LineIntersection { - if (x2 != x3 || y2 != y3) + Point point; + float distanceBeyondLine1EndSquared; + bool intersects; + }; + + static LineIntersection lineIntersection (const float x1, const float y1, + const float x2, const float y2, + const float x3, const float y3, + const float x4, const float y4) + { + if (! approximatelyEqual (x2, x3) || ! approximatelyEqual (y2, y3)) { - auto dx1 = x2 - x1; - auto dy1 = y2 - y1; - auto dx2 = x4 - x3; - auto dy2 = y4 - y3; - auto divisor = dx1 * dy2 - dx2 * dy1; + const auto dx1 = x2 - x1; + const auto dy1 = y2 - y1; + const auto dx2 = x4 - x3; + const auto dy2 = y4 - y3; + const auto divisor = dx1 * dy2 - dx2 * dy1; - if (divisor == 0.0f) + if (approximatelyEqual (divisor, 0.0f)) { - if (! ((dx1 == 0.0f && dy1 == 0.0f) || (dx2 == 0.0f && dy2 == 0.0f))) + if (! ((approximatelyEqual (dx1, 0.0f) && approximatelyEqual (dy1, 0.0f)) + || (approximatelyEqual (dx2, 0.0f) && approximatelyEqual (dy2, 0.0f)))) { - if (dy1 == 0.0f && dy2 != 0.0f) + if (approximatelyEqual (dy1, 0.0f) && ! approximatelyEqual (dy2, 0.0f)) { - auto along = (y1 - y3) / dy2; - intersectionX = x3 + along * dx2; - intersectionY = y1; - - distanceBeyondLine1EndSquared = intersectionX - x2; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - if ((x2 > x1) == (intersectionX < x2)) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; - - return along >= 0 && along <= 1.0f; + const auto along = (y1 - y3) / dy2; + const auto intersectionX = x3 + along * dx2; + const auto intersectionY = y1; + + const auto distance = square (intersectionX - x2); + const auto distanceBeyondLine1EndSquared = (x2 > x1) == (intersectionX < x2) + ? -distance + : distance; + + return { { intersectionX, intersectionY }, + distanceBeyondLine1EndSquared, + along >= 0 && along <= 1.0f }; } - if (dy2 == 0.0f && dy1 != 0.0f) + if (approximatelyEqual (dy2, 0.0f) && ! approximatelyEqual (dy1, 0.0f)) { - auto along = (y3 - y1) / dy1; - intersectionX = x1 + along * dx1; - intersectionY = y3; + const auto along = (y3 - y1) / dy1; + const auto intersectionX = x1 + along * dx1; + const auto intersectionY = y3; - distanceBeyondLine1EndSquared = (along - 1.0f) * dx1; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - if (along < 1.0f) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; + const auto distance = square ((along - 1.0f) * dx1); + const auto distanceBeyondLine1EndSquared = along < 1.0f ? -distance : distance; - return along >= 0 && along <= 1.0f; + return { { intersectionX, intersectionY }, + distanceBeyondLine1EndSquared, + along >= 0 && along <= 1.0f }; } - if (dx1 == 0.0f && dx2 != 0.0f) + if (approximatelyEqual (dx1, 0.0f) && ! approximatelyEqual (dx2, 0.0f)) { - auto along = (x1 - x3) / dx2; - intersectionX = x1; - intersectionY = y3 + along * dy2; - - distanceBeyondLine1EndSquared = intersectionY - y2; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - - if ((y2 > y1) == (intersectionY < y2)) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; - - return along >= 0 && along <= 1.0f; + const auto along = (x1 - x3) / dx2; + const auto intersectionX = x1; + const auto intersectionY = y3 + along * dy2; + + const auto distance = square (intersectionY - y2); + const auto distanceBeyondLine1EndSquared = (y2 > y1) == (intersectionY < y2) + ? -distance + : distance; + + return { { intersectionX, intersectionY }, + distanceBeyondLine1EndSquared, + along >= 0 && along <= 1.0f }; } - if (dx2 == 0.0f && dx1 != 0.0f) + if (approximatelyEqual (dx2, 0.0f) && ! approximatelyEqual (dx1, 0.0f)) { - auto along = (x3 - x1) / dx1; - intersectionX = x3; - intersectionY = y1 + along * dy1; + const auto along = (x3 - x1) / dx1; + const auto intersectionX = x3; + const auto intersectionY = y1 + along * dy1; - distanceBeyondLine1EndSquared = (along - 1.0f) * dy1; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - if (along < 1.0f) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; + const auto distance = square ((along - 1.0f) * dy1); + const auto distanceBeyondLine1EndSquared = along < 1.0f ? -distance : distance; - return along >= 0 && along <= 1.0f; + return { { intersectionX, intersectionY }, + distanceBeyondLine1EndSquared, + along >= 0 && along <= 1.0f }; } } - intersectionX = 0.5f * (x2 + x3); - intersectionY = 0.5f * (y2 + y3); + const auto intersectionX = 0.5f * (x2 + x3); + const auto intersectionY = 0.5f * (y2 + y3); + + const auto distanceBeyondLine1EndSquared = 0.0f; - distanceBeyondLine1EndSquared = 0.0f; - return false; + return { { intersectionX, intersectionY }, + distanceBeyondLine1EndSquared, + false }; } - auto along1 = ((y1 - y3) * dx2 - (x1 - x3) * dy2) / divisor; + const auto along = ((y1 - y3) * dx2 - (x1 - x3) * dy2) / divisor; - intersectionX = x1 + along1 * dx1; - intersectionY = y1 + along1 * dy1; + const auto intersectionX = x1 + along * dx1; + const auto intersectionY = y1 + along * dy1; - if (along1 >= 0 && along1 <= 1.0f) + if (along >= 0 && along <= 1.0f) { - auto along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1) / divisor; + const auto along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1) / divisor; if (along2 >= 0 && along2 <= 1.0f) { - distanceBeyondLine1EndSquared = 0.0f; - return true; + return { { intersectionX, intersectionY }, + 0.0f, + true }; } } - distanceBeyondLine1EndSquared = along1 - 1.0f; - distanceBeyondLine1EndSquared *= distanceBeyondLine1EndSquared; - distanceBeyondLine1EndSquared *= (dx1 * dx1 + dy1 * dy1); + const auto distance = square (along - 1.0f) * (dx1 * dx1 + dy1 * dy1); + const auto distanceBeyondLine1EndSquared = along < 1.0f ? -distance : distance; - if (along1 < 1.0f) - distanceBeyondLine1EndSquared = -distanceBeyondLine1EndSquared; - - return false; + return { { intersectionX, intersectionY }, + distanceBeyondLine1EndSquared, + false }; } - intersectionX = x2; - intersectionY = y2; - - distanceBeyondLine1EndSquared = 0.0f; - return true; + return { Point { x2, y2 }, 0.0f, true }; } static void addEdgeAndJoint (Path& destPath, @@ -198,31 +203,29 @@ namespace PathStrokeHelpers const float midX, const float midY) { if (style == PathStrokeType::beveled - || (x3 == x4 && y3 == y4) - || (x1 == x2 && y1 == y2)) + || (approximatelyEqual (x3, x4) && approximatelyEqual (y3, y4)) + || (approximatelyEqual (x1, x2) && approximatelyEqual (y1, y2))) { destPath.lineTo (x2, y2); destPath.lineTo (x3, y3); } else { - float jx, jy, distanceBeyondLine1EndSquared; + const auto intersection = lineIntersection (x1, y1, x2, y2, x3, y3, x4, y4); // if they intersect, use this point.. - if (lineIntersection (x1, y1, x2, y2, - x3, y3, x4, y4, - jx, jy, distanceBeyondLine1EndSquared)) + if (intersection.intersects) { - destPath.lineTo (jx, jy); + destPath.lineTo (intersection.point); } else { if (style == PathStrokeType::mitered) { - if (distanceBeyondLine1EndSquared < maxMiterExtensionSquared - && distanceBeyondLine1EndSquared > 0.0f) + if (0.0f < intersection.distanceBeyondLine1EndSquared + && intersection.distanceBeyondLine1EndSquared < maxMiterExtensionSquared) { - destPath.lineTo (jx, jy); + destPath.lineTo (intersection.point); } else { @@ -301,7 +304,7 @@ namespace PathStrokeHelpers auto dy = y2 - y1; auto len = juce_hypot (dx, dy); - if (len == 0.0f) + if (approximatelyEqual (len, 0.0f)) { offx1 = offx2 = x1; offy1 = offy2 = y1; @@ -610,7 +613,7 @@ namespace PathStrokeHelpers { auto len = std::sqrt (hypotSquared); - if (len == 0.0f) + if (approximatelyEqual (len, 0.0f)) { l.rx1 = l.rx2 = l.lx1 = l.lx2 = l.x1; l.ry1 = l.ry2 = l.ly1 = l.ly2 = l.y1; diff --git a/modules/juce_graphics/geometry/juce_Point.h b/modules/juce_graphics/geometry/juce_Point.h index 5525328855..6fc88b4a9e 100644 --- a/modules/juce_graphics/geometry/juce_Point.h +++ b/modules/juce_graphics/geometry/juce_Point.h @@ -54,11 +54,16 @@ public: /** Copies this point from another one. */ Point& operator= (const Point&) = default; - constexpr inline bool operator== (Point other) const noexcept { return x == other.x && y == other.y; } - constexpr inline bool operator!= (Point other) const noexcept { return x != other.x || y != other.y; } + constexpr inline bool operator== (Point other) const noexcept + { + const auto tie = [] (const Point& p) { return std::tie (p.x, p.y); }; + return tie (*this) == tie (other); + } + + constexpr inline bool operator!= (Point other) const noexcept { return ! operator== (other); } /** Returns true if the point is (0, 0). */ - constexpr bool isOrigin() const noexcept { return x == ValueType() && y == ValueType(); } + 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); } diff --git a/modules/juce_graphics/geometry/juce_Rectangle.h b/modules/juce_graphics/geometry/juce_Rectangle.h index 9789f7ee27..2e7bf03f2f 100644 --- a/modules/juce_graphics/geometry/juce_Rectangle.h +++ b/modules/juce_graphics/geometry/juce_Rectangle.h @@ -613,10 +613,14 @@ public: //============================================================================== /** Returns true if the two rectangles are identical. */ - bool operator== (const Rectangle& other) const noexcept { return pos == other.pos && w == other.w && h == other.h; } + bool operator== (const Rectangle& other) const noexcept + { + const auto tie = [] (const Rectangle& r) { return std::tie (r.pos, r.w, r.h); }; + return tie (*this) == tie (other); + } /** Returns true if the two rectangles are not identical. */ - bool operator!= (const Rectangle& other) const noexcept { return pos != other.pos || w != other.w || h != other.h; } + bool operator!= (const Rectangle& other) const noexcept { return ! operator== (other); } /** Returns true if this coordinate is inside the rectangle. */ bool contains (ValueType xCoord, ValueType yCoord) const noexcept diff --git a/modules/juce_graphics/image_formats/juce_PNGLoader.cpp b/modules/juce_graphics/image_formats/juce_PNGLoader.cpp index 137e47ce45..fe40b14532 100644 --- a/modules/juce_graphics/image_formats/juce_PNGLoader.cpp +++ b/modules/juce_graphics/image_formats/juce_PNGLoader.cpp @@ -58,13 +58,14 @@ namespace pnglibNamespace using std::free; #endif - JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wsign-conversion", + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcomma", + "-Wfloat-equal", "-Wimplicit-fallthrough", - "-Wtautological-constant-out-of-range-compare", - "-Wzero-as-null-pointer-constant", - "-Wcomma", "-Wmaybe-uninitialized", - "-Wnull-pointer-subtraction") + "-Wnull-pointer-subtraction", + "-Wsign-conversion", + "-Wtautological-constant-out-of-range-compare", + "-Wzero-as-null-pointer-constant") #undef check using std::abs; diff --git a/modules/juce_graphics/native/juce_CoreGraphicsContext_mac.mm b/modules/juce_graphics/native/juce_CoreGraphicsContext_mac.mm index 74bd072825..8496147b0a 100644 --- a/modules/juce_graphics/native/juce_CoreGraphicsContext_mac.mm +++ b/modules/juce_graphics/native/juce_CoreGraphicsContext_mac.mm @@ -744,8 +744,8 @@ static CGGradientRef createGradient (const ColourGradient& g, CGColorSpaceRef co locations[i] = (CGFloat) g.getColourPosition (i); // There's a bug (?) in the way the CG renderer works where it seems - // to go wrong if you have two colour stops both at position 0.. - jassert (i == 0 || locations[i] != 0); + // to go wrong if you have two colour stops both at position 0. + jassert (i == 0 || ! approximatelyEqual (locations[i], (CGFloat) 0.0)); } return CGGradientCreateWithColorComponents (colourSpace, components, locations, (size_t) numColours); diff --git a/modules/juce_graphics/native/juce_DirectWriteTypeLayout_windows.cpp b/modules/juce_graphics/native/juce_DirectWriteTypeLayout_windows.cpp index f565a58321..18f6a91ca0 100644 --- a/modules/juce_graphics/native/juce_DirectWriteTypeLayout_windows.cpp +++ b/modules/juce_graphics/native/juce_DirectWriteTypeLayout_windows.cpp @@ -108,7 +108,7 @@ namespace DirectWriteTypeLayout if (! (baselineOriginY >= -1.0e10f && baselineOriginY <= 1.0e10f)) baselineOriginY = 0; // DirectWrite sometimes sends NaNs in this parameter - if (baselineOriginY != lastOriginY) + if (! approximatelyEqual (baselineOriginY, lastOriginY)) { lastOriginY = baselineOriginY; ++currentLine; diff --git a/modules/juce_graphics/native/juce_Fonts_mac.mm b/modules/juce_graphics/native/juce_Fonts_mac.mm index ed96d2a80d..5fa2f0e965 100644 --- a/modules/juce_graphics/native/juce_Fonts_mac.mm +++ b/modules/juce_graphics/native/juce_Fonts_mac.mm @@ -295,7 +295,7 @@ namespace CoreTextTypeLayout auto extraKerning = attr.font.getExtraKerningFactor(); - if (extraKerning != 0) + if (! approximatelyEqual (extraKerning, 0.0f)) { extraKerning *= attr.font.getHeight(); diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index 716236a7f6..d9fd8c9965 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -86,8 +86,10 @@ public: complexTransform = getTransformWith (t); isOnlyTranslated = false; - isRotated = (complexTransform.mat01 != 0.0f || complexTransform.mat10 != 0.0f - || complexTransform.mat00 < 0 || complexTransform.mat11 < 0); + isRotated = (! approximatelyEqual (complexTransform.mat01, 0.0f) + || ! approximatelyEqual (complexTransform.mat10, 0.0f) + || complexTransform.mat00 < 0 + || complexTransform.mat11 < 0); } float getPhysicalPixelScaleFactor() const noexcept diff --git a/modules/juce_graphics/placement/juce_RectanglePlacement.cpp b/modules/juce_graphics/placement/juce_RectanglePlacement.cpp index 9459bfbcad..6a1319ef01 100644 --- a/modules/juce_graphics/placement/juce_RectanglePlacement.cpp +++ b/modules/juce_graphics/placement/juce_RectanglePlacement.cpp @@ -39,7 +39,7 @@ bool RectanglePlacement::operator!= (const RectanglePlacement& other) const noex void RectanglePlacement::applyTo (double& x, double& y, double& w, double& h, const double dx, const double dy, const double dw, const double dh) const noexcept { - if (w == 0.0 || h == 0.0) + if (approximatelyEqual (w, 0.0) || approximatelyEqual (h, 0.0)) return; if ((flags & stretchToFit) != 0) diff --git a/modules/juce_gui_basics/desktop/juce_Desktop.cpp b/modules/juce_gui_basics/desktop/juce_Desktop.cpp index d1c2212e1b..9c4e7517c5 100644 --- a/modules/juce_gui_basics/desktop/juce_Desktop.cpp +++ b/modules/juce_gui_basics/desktop/juce_Desktop.cpp @@ -353,7 +353,7 @@ void Desktop::setGlobalScaleFactor (float newScaleFactor) noexcept { JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED - if (masterScaleFactor != newScaleFactor) + if (! approximatelyEqual (masterScaleFactor, newScaleFactor)) { masterScaleFactor = newScaleFactor; displays->refresh(); diff --git a/modules/juce_gui_basics/desktop/juce_Displays.cpp b/modules/juce_gui_basics/desktop/juce_Displays.cpp index f42550b1b7..5b7189f632 100644 --- a/modules/juce_gui_basics/desktop/juce_Displays.cpp +++ b/modules/juce_gui_basics/desktop/juce_Displays.cpp @@ -260,10 +260,10 @@ static void processDisplay (DisplayNode* currentNode, Array& allNod Rectangle logicalArea (0.0, 0.0, logicalWidth, logicalHeight); - if (physicalArea.getRight() == physicalParentArea.getX()) logicalArea.setPosition ({ logicalParentArea.getX() - logicalWidth, physicalArea.getY() / parentScale }); // on left - else if (physicalArea.getX() == physicalParentArea.getRight()) logicalArea.setPosition ({ logicalParentArea.getRight(), physicalArea.getY() / parentScale }); // on right - else if (physicalArea.getBottom() == physicalParentArea.getY()) logicalArea.setPosition ({ physicalArea.getX() / parentScale, logicalParentArea.getY() - logicalHeight }); // on top - else if (physicalArea.getY() == physicalParentArea.getBottom()) logicalArea.setPosition ({ physicalArea.getX() / parentScale, logicalParentArea.getBottom() }); // on bottom + if (approximatelyEqual (physicalArea.getRight(), physicalParentArea.getX())) logicalArea.setPosition ({ logicalParentArea.getX() - logicalWidth, physicalArea.getY() / parentScale }); // on left + else if (approximatelyEqual (physicalArea.getX(), physicalParentArea.getRight())) logicalArea.setPosition ({ logicalParentArea.getRight(), physicalArea.getY() / parentScale }); // on right + else if (approximatelyEqual (physicalArea.getBottom(), physicalParentArea.getY())) logicalArea.setPosition ({ physicalArea.getX() / parentScale, logicalParentArea.getY() - logicalHeight }); // on top + else if (approximatelyEqual (physicalArea.getY(), physicalParentArea.getBottom())) logicalArea.setPosition ({ physicalArea.getX() / parentScale, logicalParentArea.getBottom() }); // on bottom else jassertfalse; currentNode->logicalArea = logicalArea; @@ -286,8 +286,8 @@ static void processDisplay (DisplayNode* currentNode, Array& allNod const auto otherPhysicalArea = node.display->totalArea.toDouble(); // If the displays are touching on any side - if (otherPhysicalArea.getX() == physicalArea.getRight() || otherPhysicalArea.getRight() == physicalArea.getX() - || otherPhysicalArea.getY() == physicalArea.getBottom() || otherPhysicalArea.getBottom() == physicalArea.getY()) + if (approximatelyEqual (otherPhysicalArea.getX(), physicalArea.getRight()) || approximatelyEqual (otherPhysicalArea.getRight(), physicalArea.getX()) + || approximatelyEqual (otherPhysicalArea.getY(), physicalArea.getBottom()) || approximatelyEqual (otherPhysicalArea.getBottom(), physicalArea.getY())) { node.parent = currentNode; children.add (&node); diff --git a/modules/juce_gui_basics/detail/juce_ScalingHelpers.h b/modules/juce_gui_basics/detail/juce_ScalingHelpers.h index 528cdaa6e4..81b25af292 100644 --- a/modules/juce_gui_basics/detail/juce_ScalingHelpers.h +++ b/modules/juce_gui_basics/detail/juce_ScalingHelpers.h @@ -31,47 +31,47 @@ struct ScalingHelpers template static PointOrRect unscaledScreenPosToScaled (float scale, PointOrRect pos) noexcept { - return scale != 1.0f ? pos / scale : pos; + return ! approximatelyEqual (scale, 1.0f) ? pos / scale : pos; } template static PointOrRect scaledScreenPosToUnscaled (float scale, PointOrRect pos) noexcept { - return scale != 1.0f ? pos * scale : pos; + return ! approximatelyEqual (scale, 1.0f) ? pos * scale : pos; } // For these, we need to avoid getSmallestIntegerContainer being used, which causes // judder when moving windows static Rectangle unscaledScreenPosToScaled (float scale, Rectangle pos) noexcept { - return scale != 1.0f ? Rectangle (roundToInt ((float) pos.getX() / scale), - roundToInt ((float) pos.getY() / scale), - roundToInt ((float) pos.getWidth() / scale), - roundToInt ((float) pos.getHeight() / scale)) : pos; + return ! approximatelyEqual (scale, 1.0f) ? Rectangle (roundToInt ((float) pos.getX() / scale), + roundToInt ((float) pos.getY() / scale), + roundToInt ((float) pos.getWidth() / scale), + roundToInt ((float) pos.getHeight() / scale)) : pos; } static Rectangle scaledScreenPosToUnscaled (float scale, Rectangle pos) noexcept { - return scale != 1.0f ? Rectangle (roundToInt ((float) pos.getX() * scale), - roundToInt ((float) pos.getY() * scale), - roundToInt ((float) pos.getWidth() * scale), - roundToInt ((float) pos.getHeight() * scale)) : pos; + return ! approximatelyEqual (scale, 1.0f) ? Rectangle (roundToInt ((float) pos.getX() * scale), + roundToInt ((float) pos.getY() * scale), + roundToInt ((float) pos.getWidth() * scale), + roundToInt ((float) pos.getHeight() * scale)) : pos; } static Rectangle unscaledScreenPosToScaled (float scale, Rectangle pos) noexcept { - return scale != 1.0f ? Rectangle (pos.getX() / scale, - pos.getY() / scale, - pos.getWidth() / scale, - pos.getHeight() / scale) : pos; + return ! approximatelyEqual (scale, 1.0f) ? Rectangle (pos.getX() / scale, + pos.getY() / scale, + pos.getWidth() / scale, + pos.getHeight() / scale) : pos; } static Rectangle scaledScreenPosToUnscaled (float scale, Rectangle pos) noexcept { - return scale != 1.0f ? Rectangle (pos.getX() * scale, - pos.getY() * scale, - pos.getWidth() * scale, - pos.getHeight() * scale) : pos; + return ! approximatelyEqual (scale, 1.0f) ? Rectangle (pos.getX() * scale, + pos.getY() * scale, + pos.getWidth() * scale, + pos.getHeight() * scale) : pos; } template diff --git a/modules/juce_gui_basics/drawables/juce_DrawableText.cpp b/modules/juce_gui_basics/drawables/juce_DrawableText.cpp index 361aad61e8..9bf865aec7 100644 --- a/modules/juce_gui_basics/drawables/juce_DrawableText.cpp +++ b/modules/juce_gui_basics/drawables/juce_DrawableText.cpp @@ -108,7 +108,7 @@ void DrawableText::setBoundingBox (Parallelogram newBounds) void DrawableText::setFontHeight (float newHeight) { - if (fontHeight != newHeight) + if (! approximatelyEqual (fontHeight, newHeight)) { fontHeight = newHeight; refreshBounds(); @@ -117,7 +117,7 @@ void DrawableText::setFontHeight (float newHeight) void DrawableText::setFontHorizontalScale (float newScale) { - if (fontHScale != newScale) + if (! approximatelyEqual (fontHScale, newScale)) { fontHScale = newScale; refreshBounds(); diff --git a/modules/juce_gui_basics/drawables/juce_SVGParser.cpp b/modules/juce_gui_basics/drawables/juce_SVGParser.cpp index c96a86227a..756e232919 100644 --- a/modules/juce_gui_basics/drawables/juce_SVGParser.cpp +++ b/modules/juce_gui_basics/drawables/juce_SVGParser.cpp @@ -189,8 +189,8 @@ public: } else { - if (viewBoxW == 0.0f) newState.viewBoxW = newState.width; - if (viewBoxH == 0.0f) newState.viewBoxH = newState.height; + if (approximatelyEqual (viewBoxW, 0.0f)) newState.viewBoxW = newState.width; + if (approximatelyEqual (viewBoxH, 0.0f)) newState.viewBoxH = newState.height; } newState.parseSubElements (xml, *drawable); diff --git a/modules/juce_gui_basics/layout/juce_AnimatedPosition.h b/modules/juce_gui_basics/layout/juce_AnimatedPosition.h index 20d9f9f67c..8560780719 100644 --- a/modules/juce_gui_basics/layout/juce_AnimatedPosition.h +++ b/modules/juce_gui_basics/layout/juce_AnimatedPosition.h @@ -179,7 +179,7 @@ private: { newPosition = range.clipValue (newPosition); - if (position != newPosition) + if (! approximatelyEqual (position, newPosition)) { position = newPosition; listeners.call ([this, newPosition] (Listener& l) { l.positionChanged (*this, newPosition); }); diff --git a/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h b/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h index 107138c779..5786d780bf 100644 --- a/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h +++ b/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h @@ -89,7 +89,7 @@ namespace AnimatedPositionBehaviours */ bool isStopped (double /*position*/) const noexcept { - return velocity == 0.0; + return approximatelyEqual (velocity, 0.0); } private: diff --git a/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp b/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp index 3095bde9b1..42732fbdc2 100644 --- a/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp +++ b/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp @@ -49,7 +49,7 @@ public: destAlpha = finalAlpha; isMoving = (finalBounds != component->getBounds()); - isChangingAlpha = (finalAlpha != component->getAlpha()); + isChangingAlpha = ! approximatelyEqual (finalAlpha, component->getAlpha()); left = component->getX(); top = component->getY(); @@ -273,7 +273,7 @@ void ComponentAnimator::fadeOut (Component* component, int millisecondsToTake) void ComponentAnimator::fadeIn (Component* component, int millisecondsToTake) { - if (component != nullptr && ! (component->isVisible() && component->getAlpha() == 1.0f)) + if (component != nullptr && ! (component->isVisible() && approximatelyEqual (component->getAlpha(), 1.0f))) { component->setAlpha (0.0f); component->setVisible (true); diff --git a/modules/juce_gui_basics/layout/juce_FlexBox.cpp b/modules/juce_gui_basics/layout/juce_FlexBox.cpp index 9a7a2469ae..ed5443b68f 100644 --- a/modules/juce_gui_basics/layout/juce_FlexBox.cpp +++ b/modules/juce_gui_basics/layout/juce_FlexBox.cpp @@ -84,8 +84,16 @@ struct FlexBoxLayoutCalculation ItemWithState& getItem (int x, int y) const noexcept { return *lineItems[y * numItems + x]; } - static bool isAuto (Coord value) noexcept { return value == FlexItem::autoValue; } - static bool isAssigned (Coord value) noexcept { return value != FlexItem::notAssigned; } + static bool isAuto (Coord value) noexcept + { + return exactlyEqual (value, static_cast (FlexItem::autoValue)); + } + + static bool isAssigned (Coord value) noexcept + { + return ! exactlyEqual (value, static_cast (FlexItem::notAssigned)); + } + static Coord getValueOrZeroIfAuto (Coord value) noexcept { return isAuto (value) ? Coord() : value; } //============================================================================== @@ -604,12 +612,12 @@ private: if (positiveFlexibility) { - if (totalFlexGrow != 0.0) + if (! approximatelyEqual (totalFlexGrow, 0.0)) changeUnit = difference / totalFlexGrow; } else { - if (totalFlexShrink != 0.0) + if (! approximatelyEqual (totalFlexShrink, 0.0)) changeUnit = difference / totalFlexShrink; } diff --git a/modules/juce_gui_basics/layout/juce_Grid.cpp b/modules/juce_gui_basics/layout/juce_Grid.cpp index b012520d5f..4ef0454ca5 100644 --- a/modules/juce_gui_basics/layout/juce_Grid.cpp +++ b/modules/juce_gui_basics/layout/juce_Grid.cpp @@ -62,7 +62,7 @@ struct Grid::SizeCalculation if (trackInfo.isFractional()) factorsSum += trackInfo.getSize(); - jassert (factorsSum != 0.0f); + jassert (! approximatelyEqual (factorsSum, 0.0f)); return totalRelative / factorsSum; } @@ -945,11 +945,11 @@ struct Grid::BoxAlignment // align and justify auto r = area; - if (item.width != (float) GridItem::notAssigned) r.setWidth (item.width); - if (item.height != (float) GridItem::notAssigned) r.setHeight (item.height); - if (item.maxWidth != (float) GridItem::notAssigned) r.setWidth (jmin (item.maxWidth, r.getWidth())); + if (! approximatelyEqual (item.width, (float) GridItem::notAssigned)) r.setWidth (item.width); + if (! approximatelyEqual (item.height, (float) GridItem::notAssigned)) r.setHeight (item.height); + if (! approximatelyEqual (item.maxWidth, (float) GridItem::notAssigned)) r.setWidth (jmin (item.maxWidth, r.getWidth())); if (item.minWidth > 0.0f) r.setWidth (jmax (item.minWidth, r.getWidth())); - if (item.maxHeight != (float) GridItem::notAssigned) r.setHeight (jmin (item.maxHeight, r.getHeight())); + if (! approximatelyEqual (item.maxHeight, (float) GridItem::notAssigned)) r.setHeight (jmin (item.maxHeight, r.getHeight())); if (item.minHeight > 0.0f) r.setHeight (jmax (item.minHeight, r.getHeight())); if (alignType == AlignItems::start && justifyType == JustifyItems::start) diff --git a/modules/juce_gui_basics/layout/juce_Viewport.cpp b/modules/juce_gui_basics/layout/juce_Viewport.cpp index e79c10dece..0abbc4f1a6 100644 --- a/modules/juce_gui_basics/layout/juce_Viewport.cpp +++ b/modules/juce_gui_basics/layout/juce_Viewport.cpp @@ -539,7 +539,7 @@ void Viewport::mouseDown (const MouseEvent& e) static int rescaleMouseWheelDistance (float distance, int singleStepSize) noexcept { - if (distance == 0.0f) + if (approximatelyEqual (distance, 0.0f)) return 0; distance *= 14.0f * (float) singleStepSize; diff --git a/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm b/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm index e1b6158721..ea20aa10f9 100644 --- a/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm +++ b/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm @@ -339,7 +339,7 @@ public: display: isPre10_11]; } - if (oldViewSize.width != r.size.width || oldViewSize.height != r.size.height) + if (! CGSizeEqualToSize (oldViewSize, r.size)) [view setNeedsDisplay: true]; } diff --git a/modules/juce_gui_basics/native/juce_UIViewComponentPeer_ios.mm b/modules/juce_gui_basics/native/juce_UIViewComponentPeer_ios.mm index 0390234ced..2d1168b618 100644 --- a/modules/juce_gui_basics/native/juce_UIViewComponentPeer_ios.mm +++ b/modules/juce_gui_basics/native/juce_UIViewComponentPeer_ios.mm @@ -1766,8 +1766,11 @@ void UIViewComponentPeer::setBounds (const Rectangle& newBounds, const bool { CGRect r = convertToCGRect (newBounds); - if (view.frame.size.width != r.size.width || view.frame.size.height != r.size.height) + if (! approximatelyEqual (view.frame.size.width, r.size.width) + || ! approximatelyEqual (view.frame.size.height, r.size.height)) + { [view setNeedsDisplay]; + } view.frame = r; } diff --git a/modules/juce_gui_basics/native/juce_Windowing_mac.mm b/modules/juce_gui_basics/native/juce_Windowing_mac.mm index 3e129ea706..828bc4421c 100644 --- a/modules/juce_gui_basics/native/juce_Windowing_mac.mm +++ b/modules/juce_gui_basics/native/juce_Windowing_mac.mm @@ -432,7 +432,7 @@ static Displays::Display getDisplayFromScreen (NSScreen* s, CGFloat& mainScreenB { Displays::Display d; - d.isMain = (mainScreenBottom == 0); + d.isMain = (approximatelyEqual (mainScreenBottom, 0.0)); if (d.isMain) mainScreenBottom = [s frame].size.height; diff --git a/modules/juce_gui_basics/native/juce_Windowing_windows.cpp b/modules/juce_gui_basics/native/juce_Windowing_windows.cpp index 0e9f0a8824..38240fa02f 100644 --- a/modules/juce_gui_basics/native/juce_Windowing_windows.cpp +++ b/modules/juce_gui_basics/native/juce_Windowing_windows.cpp @@ -5075,7 +5075,7 @@ void Displays::findDisplays (float masterScale) d.isMain = monitor.isMain; d.dpi = monitor.dpi; - if (d.dpi == 0) + if (approximatelyEqual (d.dpi, 0.0)) { d.dpi = globalDPI; d.scale = masterScale; diff --git a/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp b/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp index 8ceca7e06f..17ee42bc85 100644 --- a/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp +++ b/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp @@ -42,7 +42,7 @@ SliderPropertyComponent::SliderPropertyComponent (const String& name, slider.onValueChange = [this] { - if (getValue() != slider.getValue()) + if (! approximatelyEqual (getValue(), slider.getValue())) setValue (slider.getValue()); }; } diff --git a/modules/juce_gui_basics/widgets/juce_ComboBox.cpp b/modules/juce_gui_basics/widgets/juce_ComboBox.cpp index f36007f0cf..21d64a4e11 100644 --- a/modules/juce_gui_basics/widgets/juce_ComboBox.cpp +++ b/modules/juce_gui_basics/widgets/juce_ComboBox.cpp @@ -586,7 +586,7 @@ void ComboBox::mouseUp (const MouseEvent& e2) void ComboBox::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel) { - if (! menuActive && scrollWheelEnabled && e.eventComponent == this && wheel.deltaY != 0.0f) + if (! menuActive && scrollWheelEnabled && e.eventComponent == this && ! approximatelyEqual (wheel.deltaY, 0.0f)) { mouseWheelAccumulator += wheel.deltaY * 5.0f; diff --git a/modules/juce_gui_basics/widgets/juce_Label.cpp b/modules/juce_gui_basics/widgets/juce_Label.cpp index 9f24a20b20..438c8d23bf 100644 --- a/modules/juce_gui_basics/widgets/juce_Label.cpp +++ b/modules/juce_gui_basics/widgets/juce_Label.cpp @@ -389,7 +389,7 @@ void Label::colourChanged() void Label::setMinimumHorizontalScale (const float newScale) { - if (minimumHorizontalScale != newScale) + if (! approximatelyEqual (minimumHorizontalScale, newScale)) { minimumHorizontalScale = newScale; repaint(); diff --git a/modules/juce_gui_basics/widgets/juce_ListBox.cpp b/modules/juce_gui_basics/widgets/juce_ListBox.cpp index f0e3e8365d..2212fdb4b9 100644 --- a/modules/juce_gui_basics/widgets/juce_ListBox.cpp +++ b/modules/juce_gui_basics/widgets/juce_ListBox.cpp @@ -997,13 +997,13 @@ void ListBox::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& whee { bool eventWasUsed = false; - if (wheel.deltaX != 0.0f && getHorizontalScrollBar().isVisible()) + if (! approximatelyEqual (wheel.deltaX, 0.0f) && getHorizontalScrollBar().isVisible()) { eventWasUsed = true; getHorizontalScrollBar().mouseWheelMove (e, wheel); } - if (wheel.deltaY != 0.0f && getVerticalScrollBar().isVisible()) + if (! approximatelyEqual (wheel.deltaY, 0.0f) && getVerticalScrollBar().isVisible()) { eventWasUsed = true; getVerticalScrollBar().mouseWheelMove (e, wheel); diff --git a/modules/juce_gui_basics/widgets/juce_ProgressBar.cpp b/modules/juce_gui_basics/widgets/juce_ProgressBar.cpp index 05ff6eab34..7fe373cf65 100644 --- a/modules/juce_gui_basics/widgets/juce_ProgressBar.cpp +++ b/modules/juce_gui_basics/widgets/juce_ProgressBar.cpp @@ -97,7 +97,7 @@ void ProgressBar::timerCallback() const int timeSinceLastCallback = (int) (now - lastCallbackTime); lastCallbackTime = now; - if (currentValue != newProgress + if (! approximatelyEqual (currentValue, newProgress) || newProgress < 0 || newProgress >= 1.0 || currentMessage != displayedMessage) { diff --git a/modules/juce_gui_basics/widgets/juce_Slider.cpp b/modules/juce_gui_basics/widgets/juce_Slider.cpp index b72fe47757..e3c88ef388 100644 --- a/modules/juce_gui_basics/widgets/juce_Slider.cpp +++ b/modules/juce_gui_basics/widgets/juce_Slider.cpp @@ -30,8 +30,8 @@ static double getStepSize (const Slider& slider) { const auto interval = slider.getInterval(); - return interval != 0.0 ? interval - : slider.getRange().getLength() * 0.01; + return ! approximatelyEqual (interval, 0.0) ? interval + : slider.getRange().getLength() * 0.01; } class Slider::Pimpl : public AsyncUpdater, // this needs to be public otherwise it will cause an @@ -141,7 +141,7 @@ public: // interval setting. numDecimalPlaces = 7; - if (normRange.interval != 0.0) + if (! approximatelyEqual (normRange.interval, 0.0)) { int v = std::abs (roundToInt (normRange.interval * 10000000)); @@ -206,7 +206,7 @@ public: newValue); } - if (newValue != lastCurrentValue) + if (! approximatelyEqual (newValue, lastCurrentValue)) { if (valueBox != nullptr) valueBox->hideEditor (true); @@ -216,7 +216,7 @@ public: // Need to do this comparison because the Value will use equalsWithSameType to compare // the new and old values, so will generate unwanted change events if the type changes. // Cast to double before comparing, to prevent comparing as another type (e.g. String). - if (static_cast (currentValue.getValue()) != newValue) + if (! approximatelyEqual (static_cast (currentValue.getValue()), newValue)) currentValue = newValue; updateText(); @@ -249,7 +249,7 @@ public: newValue = jmin (lastCurrentValue, newValue); } - if (lastValueMin != newValue) + if (! approximatelyEqual (lastValueMin, newValue)) { lastValueMin = newValue; valueMin = newValue; @@ -283,7 +283,7 @@ public: newValue = jmax (lastCurrentValue, newValue); } - if (lastValueMax != newValue) + if (! approximatelyEqual (lastValueMax, newValue)) { lastValueMax = newValue; valueMax = newValue; @@ -306,7 +306,7 @@ public: newMinValue = constrainedValue (newMinValue); newMaxValue = constrainedValue (newMaxValue); - if (lastValueMax != newMaxValue || lastValueMin != newMinValue) + if (! approximatelyEqual (lastValueMax, newMaxValue) || ! approximatelyEqual (lastValueMin, newMinValue)) { lastValueMax = newMaxValue; lastValueMin = newMinValue; @@ -437,7 +437,7 @@ public: { auto newValue = owner.snapValue (owner.getValueFromText (valueBox->getText()), notDragging); - if (newValue != static_cast (currentValue.getValue())) + if (! approximatelyEqual (newValue, static_cast (currentValue.getValue()))) { ScopedDragNotification drag (owner); setValue (newValue, sendNotificationSync); @@ -817,7 +817,7 @@ public: auto maxSpeed = jmax (200.0, (double) sliderRegionSize); auto speed = jlimit (0.0, maxSpeed, (double) std::abs (mouseDiff)); - if (speed != 0.0) + if (! approximatelyEqual (speed, 0.0)) { speed = 0.2 * velocityModeSensitivity * (1.0 + std::sin (MathConstants::pi * (1.5 + jmin (0.5, velocityModeOffset @@ -970,7 +970,7 @@ public: { restoreMouseIfHidden(); - if (sendChangeOnlyOnRelease && valueOnMouseDown != static_cast (currentValue.getValue())) + if (sendChangeOnlyOnRelease && ! approximatelyEqual (valueOnMouseDown, static_cast (currentValue.getValue()))) triggerChangeMessage (sendNotificationAsync); currentDrag.reset(); @@ -1042,7 +1042,7 @@ public: return 0.0; }(); - if (valueChange == 0.0) + if (approximatelyEqual (valueChange, 0.0)) return false; setValue (getValue() + valueChange, sendNotificationSync); @@ -1148,7 +1148,7 @@ public: auto delta = getMouseWheelDelta (value, (std::abs (wheel.deltaX) > std::abs (wheel.deltaY) ? -wheel.deltaX : wheel.deltaY) * (wheel.isReversed ? -1.0f : 1.0f)); - if (delta != 0.0) + if (! approximatelyEqual (delta, 0.0)) { auto newValue = value + jmax (normRange.interval, std::abs (delta)) * (delta < 0 ? -1.0 : 1.0); diff --git a/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp b/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp index 5ca12315a4..33ab977d09 100644 --- a/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp +++ b/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp @@ -797,7 +797,7 @@ void CodeEditorComponent::scrollToColumnInternal (double column) { const double newOffset = jlimit (0.0, document.getMaximumLineLength() + 3.0, column); - if (xOffset != newOffset) + if (! approximatelyEqual (xOffset, newOffset)) { xOffset = newOffset; updateCaretPosition(); @@ -1596,8 +1596,8 @@ void CodeEditorComponent::mouseDoubleClick (const MouseEvent& e) void CodeEditorComponent::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel) { - if ((verticalScrollBar.isVisible() && wheel.deltaY != 0.0f) - || (horizontalScrollBar.isVisible() && wheel.deltaX != 0.0f)) + if ((verticalScrollBar.isVisible() && ! approximatelyEqual (wheel.deltaY, 0.0f)) + || (horizontalScrollBar.isVisible() && ! approximatelyEqual (wheel.deltaX, 0.0f))) { { MouseWheelDetails w (wheel); diff --git a/modules/juce_gui_extra/misc/juce_ColourSelector.cpp b/modules/juce_gui_extra/misc/juce_ColourSelector.cpp index 91d014335b..c885d0e3c3 100644 --- a/modules/juce_gui_extra/misc/juce_ColourSelector.cpp +++ b/modules/juce_gui_extra/misc/juce_ColourSelector.cpp @@ -100,7 +100,7 @@ public: void updateIfNeeded() { - if (lastHue != h) + if (! approximatelyEqual (lastHue, h)) { lastHue = h; colours = {}; @@ -454,7 +454,7 @@ void ColourSelector::setHue (float newH) { newH = jlimit (0.0f, 1.0f, newH); - if (h != newH) + if (! approximatelyEqual (h, newH)) { h = newH; colour = Colour (h, s, v, colour.getFloatAlpha()); @@ -467,7 +467,7 @@ void ColourSelector::setSV (float newS, float newV) newS = jlimit (0.0f, 1.0f, newS); newV = jlimit (0.0f, 1.0f, newV); - if (s != newS || v != newV) + if (! approximatelyEqual (s, newS) || ! approximatelyEqual (v, newV)) { s = newS; v = newV; diff --git a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp index 0ec9a1031d..2c999c1298 100644 --- a/modules/juce_opengl/opengl/juce_OpenGLContext.cpp +++ b/modules/juce_opengl/opengl/juce_OpenGLContext.cpp @@ -1062,7 +1062,7 @@ public: const auto newRefreshPeriod = sharedDisplayLinks->getNominalVideoRefreshPeriodSForScreen (display); - if (newRefreshPeriod != 0.0 && std::exchange (refreshPeriod, newRefreshPeriod) != newRefreshPeriod) + if (newRefreshPeriod != 0.0 && ! approximatelyEqual (std::exchange (refreshPeriod, newRefreshPeriod), newRefreshPeriod)) nativeContext->setNominalVideoRefreshPeriodS (newRefreshPeriod); updateColourSpace(); diff --git a/modules/juce_osc/osc/juce_OSCArgument.cpp b/modules/juce_osc/osc/juce_OSCArgument.cpp index fd3a24bfaf..7e7a9e7ed7 100644 --- a/modules/juce_osc/osc/juce_OSCArgument.cpp +++ b/modules/juce_osc/osc/juce_OSCArgument.cpp @@ -138,7 +138,7 @@ public: expect (! arg.isBlob()); expect (! arg.isColour()); - expect (arg.getFloat32() == value); + expectEquals (arg.getFloat32(), value); } beginTest ("String"); diff --git a/modules/juce_osc/osc/juce_OSCBundle.cpp b/modules/juce_osc/osc/juce_OSCBundle.cpp index aa47d536af..a80447e7d0 100644 --- a/modules/juce_osc/osc/juce_OSCBundle.cpp +++ b/modules/juce_osc/osc/juce_OSCBundle.cpp @@ -210,7 +210,7 @@ private: expect (e[0].getMessage().size() == 1); expect (e[0].getMessage().begin()->getInt32() == testInt); expect (e[1].getMessage().size() == 2); - expect (e[1].getMessage()[1].getFloat32() == testFloat); + expectEquals (e[1].getMessage()[1].getFloat32(), testFloat); } }; @@ -237,7 +237,7 @@ public: expect (element.isMessage()); expect (element.getMessage().size() == 1); expect (element.getMessage()[0].getType() == OSCTypes::float32); - expect (element.getMessage()[0].getFloat32() == testFloat); + expectEquals (element.getMessage()[0].getFloat32(), testFloat); } } }; diff --git a/modules/juce_video/native/juce_Video_mac.h b/modules/juce_video/native/juce_Video_mac.h index 7c1db8fac8..9e4e788292 100644 --- a/modules/juce_video/native/juce_Video_mac.h +++ b/modules/juce_video/native/juce_Video_mac.h @@ -109,7 +109,7 @@ struct VideoComponent::Pimpl : public Base } bool isOpen() const noexcept { return playerController.getPlayer() != nil; } - bool isPlaying() const noexcept { return getSpeed() != 0; } + bool isPlaying() const noexcept { return ! approximatelyEqual (getSpeed(), 0.0); } void play() noexcept { [playerController.getPlayer() play]; setSpeed (playSpeedMult); } void stop() noexcept { [playerController.getPlayer() pause]; } @@ -236,9 +236,9 @@ private: auto oldRate = [[change objectForKey: NSKeyValueChangeOldKey] floatValue]; auto newRate = [[change objectForKey: NSKeyValueChangeNewKey] floatValue]; - if (oldRate == 0 && newRate != 0) + if (approximatelyEqual (oldRate, 0.0f) && ! approximatelyEqual (newRate, 0.0f)) owner.playbackStarted(); - else if (oldRate != 0 && newRate == 0) + else if (! approximatelyEqual (oldRate, 0.0f) && approximatelyEqual (newRate, 0.0f)) owner.playbackStopped(); } else if ([keyPath isEqualToString: nsStringLiteral ("status")]) @@ -299,7 +299,9 @@ private: void loadAsync (URL url) { auto nsUrl = [NSURL URLWithString: juceStringToNS (url.toString (true))]; + JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wnullable-to-nonnull-conversion") asset.reset ([[AVURLAsset alloc] initWithURL: nsUrl options: nil]); + JUCE_END_IGNORE_WARNINGS_GCC_LIKE [asset.get() loadValuesAsynchronouslyForKeys: assetKeys.get() completionHandler: ^() { checkAllKeysReadyFor (asset.get(), url); }];