www.gusucode.com > mbcmodels 工具箱 matlab 源码程序 > mbcmodels/mbcCheckInput.m
function [OK,msg] = mbcCheckInput(Value,Type,Options,Property,ThrowError) %MBCCHECKINPUT type checking for new input values % % OK = mbcCheckInput(Value,Type,Property) % [OK,msg] = mbcCheckInput(Value,Type,Property,ThrowError) % % Inputs % Value: % Type : Check Type Details % Property: Property name (Default = 'Property') % ThrowError: throw an error if Value is not correct (default = true) % % List of supported types for mbcCheckInput % % % +---------------+-------------------------+----------+------------------- % |Type | Identifier | Options | Criteria % +---------------+-------------------------+----------+------------------- % |Scalar numbers |'real','numeric','double'|range | Scalar, not complex, not NaN % |Scalar integers|'int' |range | Scalar integer, Not complex, not NaN % |Ranges |'range' |range | Two element numeric range [min,max] % | | | | Min < Max % | | | | There is also a one element range! % |Vectors |'vector','vector int' | range | A vector has numeric elements and is row vector % | |'vector real' | length | % |Matrices |'matrix','matrix int' | range | A matrix has numeric elements % | |'matrix real' | size | % |Logical |'boolean','bool','logical' | % |Cell String |'cellstr' | | % |Eval String |'evalstr', | | {TryExpressionString,CatchExpressionString} % | |'MATLAB Callback' | | or ExpressionString % |Enumerated |'enum','vector enum' |EnumList |The old enumerated type with a | separated list % | | | length | is still supported. % |Sparse |'sparse' | | issparse - sparse is no longer a class in MATLAB % |Class |'ClassName' | | isa(Value,'ClassName') % |Function | function_handle |Cell array| msg = F(Property,Value,Options{:}); % | | |of extra | % | | |arguments | % +---------------+-------------------------+----------+------------------- % % All the above numeric types (numbers, integers, ranges, vectors) support a range option % % {'Type',[min,max]} user-defined range % {'Type','positive'} strictly positive numbers % {'Type','negative'} strictly negative numbers % % The length and range options can be used together or separately for vector options % {'vector',{[min,max},Length}} % {'vector',[min,max]} % {'vector',Length} % The length and range options can be used together or separately for vector options % {'matrix',{[min,max},Size}} % {'matrix',[min,max]} % {'matrix',Size} % The vector enum type does not require the Length option but does require the EnumList % {'vector enum',{EnumList,Length}} % {'vector enum',EnumList} % Copyright 2006-2011 The MathWorks, Inc. and Ford Global Technologies, Inc. persistent CHECKFCNS if isempty(CHECKFCNS) % supported types % msg = CHECKFCNS{cind,2}(Property,Value,Options); CHECKFCNS= {'numeric',@iCheckNumeric 'real',@iCheckNumeric 'double',@iCheckNumeric 'int',@iCheckInteger 'boolean',@iCheckLogical 'bool',@iCheckLogical 'range',@iCheckRange 'vector',@iCheckVector 'vector real',@iCheckVector 'vector int',@iCheckVectorInt 'vector enum',@iCheckVectorEnumerated 'matrix',@iCheckMatrix 'cellstr',@iCheckCellStr 'evalstr',@iCheckEvalStr 'MATLAB Callback',@iCheckEvalStr 'enum',@iCheckEnumerated 'sparse',@iCheckSparse}; end if nargin<4 Property = 'Property'; end if nargin<5 ThrowError = true; end if ~isempty(Type) && ischar(Type) pbar = strfind(Type,'|'); if ~isempty(pbar) % options are emnumerated strings separated by |'s msg = iCheckEnumeratedBar(Property,Value,Type); else % look in one of the predefined check function cind= strcmpi(Type,CHECKFCNS(:,1)); if any(cind) msg = CHECKFCNS{cind,2}(Property,Value,Options); else % check the class msg = iCheckClass(Property,Value,Type); end end elseif isa(Type,'function_handle') msg = Type(Value,Options{:}); else % no checking msg = ''; end OK = isempty(msg); if ~OK && ~ischar(msg) % we might get here with an old function handle call OK = msg; if ~OK msg = 'Unknown Error'; end end if ~OK && ThrowError error('mbc:mbcCheckInput:InvalidValue',msg); end % range checker function msg= iRange(Property,Value,Options) OK = true; if isempty(Options) msg = ''; elseif isnumeric(Options) && numel(Options)==2 OK = ~(any(Value<Options(1)) || any(Value>Options(2))); msg = sprintf('All numeric inputs must be in the range [%g,%g].', Options(1), Options(2) ); elseif ischar(Options) switch lower(Options) case 'positive' OK = ~any(Value<=0); msg = 'All numeric inputs must be positive'; case 'negative' OK = ~any(Value>=0); msg = 'All numeric inputs must be negative'; otherwise OK = false; msg = 'Unknown range option'; end else OK = false; msg = 'Unknown range option'; end if OK % empty message if all OK msg = ''; end % Enumerated with | Separators function msg = iCheckEnumeratedBar(Property,Value,Type) % options are emnumerated strings separated by |'s TextStrings = textscan( Type,'%s','delimiter','|' ); c = TextStrings{1}; valid_strings = ['''',strrep(Type, '|', ''','''),'''']; msg = ''; if ~ischar(Value) msg = sprintf('Enumerated type for %s must be one of {%s}.', Property, valid_strings ); else optind = strcmpi(Value, c); if ~any(optind) msg = sprintf('Enumerated type for %s must be one of {%s}.', Property, valid_strings ); end end % Enumerated with list in Options function msg = iCheckVectorEnumerated(Property,Value,Options) [Options,RequiredLength] = iVectorOptions(Options); List = sprintf('''%s'',',Options{:}); List(end)= ''; msg = ''; if ~iscellstr(Value) msg = sprintf('Enumerated type for %s must be cell array of {%s}.', Property, List ); else optind = ismember(Value, Options); if ~all(optind) msg = sprintf('Enumerated type for %s must be a cell array of {%s}.', Property, List ); end end if isempty(msg) && ~isempty(RequiredLength) && length(Value)~=RequiredLength msg = sprintf('A row vector with %d elements is required for %s.', RequiredLength,Property ); end % iCheckEnumerated function msg = iCheckEnumerated(Property,Value,Options) List = sprintf('''%s'',',Options{:}); List(end)= ''; msg = ''; if ~ischar(Value) msg = sprintf('Enumerated type for %s must be one of {%s}.', Property, List); else optind = ismember(Value, Options); if ~all(optind) msg = sprintf('Enumerated type for %s must be one of {%s}.', Property, List); end end % Basic numeric function msg = iCheckNumeric(Property,Value,Options) if ~isscalar(Value) || ~isnumeric(Value) msg = sprintf('A scalar numeric input is required for %s', Property); elseif isnan(Value) msg = sprintf('NaN is not supported for %s.', Property ); elseif ~isreal(Value) msg = sprintf('Complex numbers are not supported for %s.', Property); else msg = iRange(Property,Value,Options); end % Integer function msg = iCheckInteger(Property,Value,Options) msg = iCheckNumeric(Property,Value,Options); if isempty(msg) && Value~=fix(Value) msg = sprintf('Integer input is required for %s.',Property); end % Logical function msg = iCheckLogical(Property,Value,Options) msg = ''; if ~isscalar(Value) || (~islogical(Value) && ~(isnumeric(Value) && any(Value == [0 1]))) msg = sprintf('Scalar boolean input is required for %s.', Property); end % Range function msg = iCheckRange(Property,Value,Options) if ~isnumeric(Value) msg = sprintf('The range for %s must be numeric.', Property ); elseif ~isreal(Value) || any(isnan(Value)) msg = sprintf('Ranges with complex numbers or NaN''s are not supported for %s.',Property ); elseif any(numel(Value) == [1 2]) msg = iRange(Property,Value,Options); if isempty(msg) && numel(Value)==2 && Value(1) >= Value(2) msg = sprintf('The range of %s must be strictly increasing.', Property); end else msg = sprintf('One or two numeric values are required for %s.',Property); end % iVectorOptions function [MainOption,RequiredLength] = iVectorOptions(Options) MainOption = []; RequiredLength = []; if iscell(Options) && numel(Options)==2 && (isnumeric(Options{2}) && isscalar(Options{2})) % cell array with main option as first element MainOption = Options{1}; RequiredLength = Options{2}; elseif isnumeric(Options) && isscalar(Options) RequiredLength =Options; else MainOption = Options; end % Vector function msg = iCheckVector(Property,Value,Options) [RangeOpts,RequiredLength] = iVectorOptions(Options); msg = ''; if any(~isnumeric(Value)) msg = sprintf('Numeric values are required for %s.', Property); elseif ~isreal(Value) || ~all(isfinite(Value)) msg = sprintf('Complex numbers, NaN''s and Inf''s are not supported for %s.', Property ); elseif ~isempty(Options) msg= iRange(Property,Value,RangeOpts); end if isempty(msg) && size(Value, 1) > 1 msg = sprintf('A row vector is required for %s.', Property ); end if isempty(msg) && ~isempty(RequiredLength) && length(Value)~=RequiredLength msg = sprintf('A row vector with %d elements is required for %s.', RequiredLength,Property ); end % iMatrixOptions function [MainOption,RequiredSize] = iMatrixOptions(Options) MainOption = []; RequiredSize = []; if iscell(Options) && numel(Options)==2 && (isnumeric(Options{2}) && isscalar(Options{2})) % cell array with main option as first element MainOption = Options{2}; RequiredSize = Options{1}; elseif isnumeric(Options) && numel(Options)==2 RequiredSize =Options; else MainOption = Options; end % Matrix function msg = iCheckMatrix(Property,Value,Options) [RangeOpts,RequiredSize] = iMatrixOptions(Options); msg = ''; if any(~isnumeric(Value)) msg = sprintf('Numeric values are required for %s.', Property); elseif ~isreal(Value) || ~all(isfinite(Value(:))) msg = sprintf('Complex numbers, NaN''s and Inf''s are not supported for %s.', Property ); elseif ~isempty(Options) msg= iRange(Property,Value,RangeOpts); end if isempty(msg) && ~isempty(RequiredSize) && any(size(Value)~=RequiredSize) msg = sprintf('A %dx%d matrix is required for %s.', RequiredSize,Property ); end % Vector Int function msg = iCheckVectorInt(Property,Value,Options) msg = iCheckVector(Property,Value,Options); if isempty(msg) && (any(Value~=fix(Value)) || any(~isreal(Value)) || any(isnan(Value))) msg = sprintf('A vector of integers is required for %s.',Property); end % Cell String function msg = iCheckCellStr(Property,Value,Options) if ~iscellstr(Value) msg = sprintf('A cell array of strings is required for %s.',Property); else msg = ''; end % EvalStr function msg = iCheckEvalStr(Property,Value,Options) msg = ''; if isnumeric(Value) % check input is a valid number msg = iCheckNumeric(Property,Value,[]); if isempty(msg) Value = num2str(Value); end end if isempty(msg) && ~ischar(Value) && ~(iscellstr(Value) && numel(Value)==2) msg = sprintf('Evalstr must either be ExpressionString or {TryExpression,CatchExpression}'); end % Sparse function msg = iCheckSparse(Property,Value,Options) if ~issparse(Value) % sparse is no longer a class msg = sprintf('Input for %s must be sparse.', Property); else msg = ''; end % Class function msg = iCheckClass(Property,Value,cls) if isa(Value,cls) msg = ''; else % check class msg = sprintf('Input for %s must be a %s.', Property, cls); end