diff --git a/API/controlsClass.m b/API/controlsClass.m index 48e3bbe0b..df2ed10a8 100644 --- a/API/controlsClass.m +++ b/API/controlsClass.m @@ -84,7 +84,7 @@ end function set.updatePlotFreq(obj, val) - validateNumber(val, 'updatePlotFreq must be a number'); + validateNumber(val, 'updatePlotFreq must be a whole number', true); if val < 1 throw(exceptions.invalidValue('updatePlotFreq must be greater or equal to 1')); end @@ -117,16 +117,16 @@ end function set.maxFuncEvals(obj, val) - obj.maxFuncEvals = validateNumber(val, 'maxFuncEvals must be a number'); + obj.maxFuncEvals = validateNumber(val, 'maxFuncEvals must be a whole number', true); end function set.maxIterations(obj, val) - obj.maxIterations = validateNumber(val, 'maxIterations must be a number'); + obj.maxIterations = validateNumber(val, 'maxIterations must be a whole number', true); end % DE controls methods function set.populationSize(obj, val) - validateNumber(val, 'populationSize must be a number'); + validateNumber(val, 'populationSize must be a whole number', true); if val < 1 throw(exceptions.invalidValue('populationSize must be greater or equal to 1')); end @@ -161,7 +161,7 @@ end function set.numGenerations(obj, val) - validateNumber(val, 'numGenerations value must be a number'); + validateNumber(val, 'numGenerations value must be a whole number', true); if val < 1 throw(exceptions.invalidValue('numGenerations must be greater or equal to 1')); end @@ -170,7 +170,7 @@ % NS control methods function set.nLive(obj, val) - validateNumber(val, 'nLive must be a number'); + validateNumber(val, 'nLive must be a whole number', true); if val < 1 throw(exceptions.invalidValue('nLive must be greater or equal to 1')); end @@ -178,7 +178,7 @@ end function set.nMCMC(obj, val) - validateNumber(val, 'nMCMC must be a number'); + validateNumber(val, 'nMCMC must be a whole number', true); if val < 0 throw(exceptions.invalidValue('nMCMC must be greater or equal than 0')); end @@ -203,7 +203,7 @@ % DREAM methods function set.nSamples(obj,val) - validateNumber(val, 'nSample must be a number '); + validateNumber(val, 'nSamples must be a whole number', true); if val < 0 throw(exceptions.invalidValue('nSample must be greater or equal to 0')); end @@ -211,8 +211,8 @@ end function set.nChains(obj,val) - validateNumber(val, 'nChains must be a number '); - if (~(round(val) == val) || val <= 0 || isnan(val) || isinf(val)) + validateNumber(val, 'nChains must be a whole number', true); + if val <= 0 throw(exceptions.invalidValue('nChains must be a finite integer greater than 0')); end obj.nChains = val; diff --git a/tests/testControlsClass.m b/tests/testControlsClass.m index 0808fdfd2..c0ca2cfe4 100644 --- a/tests/testControlsClass.m +++ b/tests/testControlsClass.m @@ -94,6 +94,7 @@ function testUpdatePlotFreq(testCase) testCase.verifyEqual(testCase.controls.updatePlotFreq, 5, 'set.updatePlotFreq method is not working') % bad updatePlotFreq type testCase.verifyError(@() setUpdatePlotFreq('a'), exceptions.invalidType.errorID); + testCase.verifyError(@() setUpdatePlotFreq(1.5), exceptions.invalidValue.errorID); testCase.verifyError(@() setUpdatePlotFreq(0), exceptions.invalidValue.errorID); function setUpdatePlotFreq(value) testCase.controls.updatePlotFreq = value; @@ -118,16 +119,18 @@ function testSimplexArguments(testCase) testCase.controls.maxFuncEvals = 123; testCase.verifyEqual(testCase.controls.maxFuncEvals, 123, 'set.maxFuncEvals method is not working') - testCase.verifyError(@setMaxFuncEvals, exceptions.invalidType.errorID); % bad maxFuncEvals type - function setMaxFuncEvals - testCase.controls.maxFuncEvals = 'a'; + testCase.verifyError(@() setMaxFuncEvals('a'), exceptions.invalidType.errorID); % bad maxFuncEvals type + testCase.verifyError(@() setMaxFuncEvals(1.5), exceptions.invalidValue.errorID); + function setMaxFuncEvals(value) + testCase.controls.maxFuncEvals = value; end testCase.controls.maxIterations = 456; testCase.verifyEqual(testCase.controls.maxIterations, 456, 'set.maxIterations method is not working') - testCase.verifyError(@setMaxIterations, exceptions.invalidType.errorID); % bad maxIterations type - function setMaxIterations - testCase.controls.maxIterations = 'a'; + testCase.verifyError(@() setMaxIterations('a'), exceptions.invalidType.errorID); % bad maxIterations type + testCase.verifyError(@() setMaxIterations(1.5), exceptions.invalidValue.errorID); + function setMaxIterations(value) + testCase.controls.maxIterations = value; end end @@ -138,6 +141,7 @@ function testDEArguments(testCase) % bad populationSize type testCase.verifyError(@() setPopulationSize('a'), exceptions.invalidType.errorID); testCase.verifyError(@() setPopulationSize(0), exceptions.invalidValue.errorID); + testCase.verifyError(@() setPopulationSize(1.5), exceptions.invalidValue.errorID); function setPopulationSize(value) testCase.controls.populationSize = value; end @@ -186,6 +190,7 @@ function setTargetValue(value) % bad numGenerations type testCase.verifyError(@() setNumGenerations('a'), exceptions.invalidType.errorID); testCase.verifyError(@() setNumGenerations(0), exceptions.invalidValue.errorID); + testCase.verifyError(@() setNumGenerations(1.5), exceptions.invalidValue.errorID); function setNumGenerations(value) testCase.controls.numGenerations = value; end @@ -198,6 +203,7 @@ function testNSArguments(testCase) % bad nLive type testCase.verifyError(@() setnLive('a'), exceptions.invalidType.errorID); testCase.verifyError(@() setnLive(0), exceptions.invalidValue.errorID); + testCase.verifyError(@() setnLive(1.5), exceptions.invalidValue.errorID); function setnLive(value) testCase.controls.nLive = value; end @@ -207,6 +213,7 @@ function setnLive(value) % bad nMCMC type testCase.verifyError(@() setnMCMC('a'), exceptions.invalidType.errorID); testCase.verifyError(@() setnMCMC(-1), exceptions.invalidValue.errorID); + testCase.verifyError(@() setnMCMC(1.5), exceptions.invalidValue.errorID); function setnMCMC(value) testCase.controls.nMCMC = value; end @@ -238,6 +245,7 @@ function testDreamArguments(testCase) % bad nSamples type testCase.verifyError(@() setNSamples('a'), exceptions.invalidType.errorID); testCase.verifyError(@() setNSamples(-1), exceptions.invalidValue.errorID); + testCase.verifyError(@() setNSamples(1.5), exceptions.invalidValue.errorID); function setNSamples(value) testCase.controls.nSamples = value; end @@ -605,6 +613,5 @@ function testSetProcedureWithCalculate(testCase) end - end end diff --git a/tests/testUtilities.m b/tests/testUtilities.m index afc11ed3b..3967491af 100644 --- a/tests/testUtilities.m +++ b/tests/testUtilities.m @@ -22,6 +22,8 @@ function testValidateNumber(testCase) testCase.verifyEqual(validateNumber([1, 2, 3]), [1, 2, 3], 'validateNumber function is not working'); testCase.verifyError(@() validateNumber('a'), exceptions.invalidType.errorID); testCase.verifyError(@() validateNumber(false), exceptions.invalidType.errorID); + testCase.verifyEqual(validateNumber(-1.6, '', false), -1.6, 'validateNumber function is not working'); + testCase.verifyError(@() validateNumber(-1.6, '', true), exceptions.invalidValue.errorID); end function testValidateOption(testCase) diff --git a/utilities/validateNumber.m b/utilities/validateNumber.m index b5643c7ff..b620b9511 100644 --- a/utilities/validateNumber.m +++ b/utilities/validateNumber.m @@ -1,13 +1,19 @@ -function input = validateNumber(input, message) +function input = validateNumber(input, message, validateInt) % Checks input is a number and throws an exception with given message. % + % If validateInt is true, also check that input is a whole number. + % % validateNumber(2, 'This is not a number'); + % validateNumber(2.5, 'This is not a whole number', true); arguments input message {mustBeTextScalar} = 'The input is not a number' + validateInt {mustBeA(validateInt,'logical')} = false end if ~isnumeric(input) throw(exceptions.invalidType(message)); + elseif validateInt && mod(input, 1) ~= 0 + throw(exceptions.invalidValue(message)); end end \ No newline at end of file