1 % NANTEST checks several mathematical operations and a few
2 % statistical functions for their correctness related to NaN's.
3 % e.g. it checks norminv, normcdf, normpdf, sort, matrix division and multiplication.
6 % see also: NANINSTTEST
9 % [1] W. Kahan (1996) Lecture notes on the Status of "IEEE Standard 754 for
10 % Binary Floating-point Arithmetic.
14 % This program is free software; you can redistribute it and/or modify
15 % it under the terms of the GNU General Public License as published by
16 % the Free Software Foundation; either version 2 of the License, or
17 % (at your option) any later version.
19 % This program is distributed in the hope that it will be useful,
20 % but WITHOUT ANY WARRANTY; without even the implied warranty of
21 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 % GNU General Public License for more details.
24 % You should have received a copy of the GNU General Public License
25 % along with this program; If not, see <http://www.gnu.org/licenses/>.
27 % $Id: nantest.m 8223 2011-04-20 09:16:06Z schloegl $
28 % Copyright (C) 2000-2004,2009 by Alois Schloegl <alois.schloegl@gmail.com>
29 % This script is part of the NaN-toolbox
30 % http://pub.ist.ac.at/~schloegl/matlab/NaN/
32 %FLAG_WARNING = warning;
39 fprintf(1,'WARNING: NANTEST fails for 3-DIM matrices. \n');
42 [s,n] = sumskipnan([nan,1,4,5]);
44 fprintf(1,'WARNING: SUMSKIPNAN is not avaible. \n');
47 % check NORMPDF, NORMCDF, NORMINV
48 x = [-inf,-2,-1,-.5,0,.5,1,2,3,inf,nan]';
49 if exist('normpdf','file')==2,
50 q(1) = sum(isnan(normpdf(x,2,0)))>sum(isnan(x));
52 fprintf(1,'NORMPDF cannot handle v=0.\n');
53 fprintf(1,'-> NORMPDF should be replaced\n');
57 if exist('normcdf','file')==2,
58 q(2) = sum(isnan(normcdf(x,2,0)))>sum(isnan(x));
60 fprintf(1,'NORMCDF cannot handle v=0.\n');
61 fprintf(1,'-> NORMCDF should be replaced\n');
65 if exist('norminv','file')==2,
66 p = [-inf,-.2,0,.2,.5,1,2,inf,nan];
67 q(3) = sum(~isnan(norminv(p,2,0)))<4;
69 fprintf(1,'NORMINV cannot handle correctly v=0.\n');
70 fprintf(1,'-> NORMINV should be replaced\n');
72 q(4) = ~isnan(norminv(0,NaN,0));
73 q(5) = any(norminv(0.5,[1 2 3],0)~=(1:3));
76 if exist('tpdf','file')==2,
77 q(6) = ~isnan(tpdf(nan,4));
79 fprintf(1,'TPDF(NaN,4) does not return NaN\n');
80 fprintf(1,'-> TPDF should be replaced\n');
84 if exist('tcdf','file')==2,
86 q(7) = ~isnan(tcdf(nan,4));
91 fprintf(1,'TCDF(NaN,4) does not return NaN\n');
92 fprintf(1,'-> TCDF should be replaced\n');
96 if exist('tinv','file')==2,
98 q(8) = ~isnan(tinv(nan,4));
103 fprintf(1,'TINV(NaN,4) does not return NaN\n');
104 fprintf(1,'-> TINV should be replaced\n');
108 q(9) = isreal(double(2+3i));
110 printf('DOUBLE rejects imaginary part\n-> this can affect SUMSKIPNAN\n');
114 x = reshape(1:6,3,2);
115 [cc,nn] = covm(x+i*x,'e');
125 fprintf(1,'WARNING: MOD(x,0) does not return 0.\n');
128 fprintf(1,'WARNING: MOD(x,0) returns NaN.\n');
130 if isnan(mod(5,inf)),
131 fprintf(1,'WARNING: MOD(x,INF) returns NaN.\n');
137 fprintf(1,'WARNING: REM(x,0) does not return 0.\n');
140 fprintf(1,'WARNING: REM(x,0) returns NaN.\n');
142 if isnan(mod(5,inf)),
143 fprintf(1,'WARNING: REM(x,INF) returns NaN.\n');
148 %%%%% NANSUM(NAN) - this test addresses a problem in Matlab 5.3, 6.1 & 6.5
149 if exist('nansum','file'),
150 if isnan(nansum(nan)),
151 fprintf(1,'Warning: NANSUM(NaN) returns NaN instead of 0\n');
152 fprintf(1,'-> NANSUM should be replaced\n');
155 %%%%% NANSUM(NAN) - this test addresses a problem in Matlab 5.3, 6.1 & 6.5
156 if exist('nanstd','file'),
157 if ~isnan(nanstd(0)),
158 fprintf(1,'Warning: NANSTD(x) with isscalar(x) returns 0 instead of NaN\n');
159 fprintf(1,'-> NANSTD should be replaced\n');
162 %%%%% GEOMEAN - this test addresses a problem in Octave
163 if exist('geomean','file'),
164 if isnan(geomean((0:3)')),
165 fprintf(1,'Warning: GEOMEAN([0,1,2,3]) NaN instead of 0\n');
166 fprintf(1,'-> GEOMEAN should be replaced\n');
169 %%%%% HARMMEAN - this test addresses a problem in Octave
170 if exist('harmmean','file'),
171 if isnan(harmmean(0:3)),
172 fprintf(1,'Warning: HARMMEAN([0,1,2,3]) NaN instead of 0\n');
173 fprintf(1,'-> HARMMEAN should be replaced\n');
176 %%%%% BITAND - this test addresses a problem in Octave
177 if exist('bitand')>1,
178 if isnan(bitand(2^33-1,13)),
179 fprintf(1,'BITAND can return NaN. \n');
182 %%%%% BITSHIFT - this test addresses a problem in Octave
183 if exist('bitshift','file'),
184 if isnan(bitshift(5,30,32)),
185 fprintf(1,'BITSHIFT can return NaN.\n');
188 %%%%% ALL - this test addresses a problem in some old Octave and FreeMat v3.5
190 fprintf(1,'WARNING: ANY(NaN) returns 1 instead of 0\n');
193 fprintf(1,'WARNING: ANY([]) returns 1 instead of 0\n');
195 %%%%% ALL - this test addresses a problem in some old Octave and FreeMat v3.5
197 fprintf(1,'WARNING: ALL(NaN) returns 0 instead of 1\n');
200 fprintf(1,'WARNING: ALL([]) returns 0 instead of 1\n');
203 %%%%% SORT - this was once a problem in Octave Version < 2.1.36 %%%%
204 if ~all(isnan(sort([3,4,NaN,3,4,NaN]))==[0,0,0,0,1,1]),
205 warning('Warning: SORT does not handle NaN.');
208 %%%%% commutativity of 0*NaN %%% This test adresses a problem in Octave
210 y=x;y(2,1)=nan;y(4,2)=nan;
212 if ~all(all(isnan(y*B)==isnan(B'*y')')),
213 fprintf(2,'WARNING: 0*NaN within matrix multiplication is not commutative\n');
219 fprintf(2,'WARNING: (0-3*i)/inf results in NaN instead of 0.\n');
222 %(roots([5,0,0])-[0;0])
223 %(roots([2,-10,12])-[3;2])
224 %(roots([2e-37,-2,2])-[1e37;1])
225 %%%%% check nan/nan %% this test addresses a problem in Matlab 5.3, 6.1 & 6.5
227 tmp1 = repmat(nan,p)/repmat(nan,p);
228 tmp2 = repmat(nan,p)\repmat(nan,p);
229 tmp3 = repmat(0,p)/repmat(0,p);
230 tmp4 = repmat(0,p)\repmat(0,p);
231 tmp5 = repmat(0,p)*repmat(inf,p);
232 tmp6 = repmat(inf,p)*repmat(0,p);
233 x = randn(100,1)*ones(1,p); y=x'*x;
237 if ~all(isnan(tmp1(:))),
238 fprintf(1,'WARNING: matrix division NaN/NaN does not result in NaN\n');
240 if ~all(isnan(tmp2(:))),
241 fprintf(1,'WARNING: matrix division NaN\\NaN does not result in NaN\n');
243 if ~all(isnan(tmp3(:))),
244 fprintf(2,'WARNING: matrix division 0/0 does not result in NaN\n');
246 if ~all(isnan(tmp4(:))),
247 fprintf(2,'WARNING: matrix division 0\\0 does not result in NaN\n');
249 if ~all(isnan(tmp5(:))),
250 fprintf(2,'WARNING: matrix multiplication 0*inf does not result in NaN\n');
252 if ~all(isnan(tmp6(:))),
253 fprintf(2,'WARNING: matrix multiplication inf*0 does not result in NaN\n');
255 if any(any(tmp7==inf));
256 fprintf(2,'WARNING: right division of two singulare matrices return INF\n');
258 if any(any(tmp8==inf));
259 fprintf(2,'WARNING: left division of two singulare matrices return INF\n');
262 tmp = [tmp1;tmp2;tmp3;tmp4;tmp5;tmp6;tmp7;tmp8];
266 %warning(FLAG_WARNING);
270 d = [1 1 2 2 4 4 10 700];
271 q = [-1,0,.05,.1,.25,.49,.5,.51,.75,.8, .999999,1,2];
272 r = [ NaN, 1, 1, 1, 1.5, 2, 3, 4, 7, 10, 700, 700, NaN];
273 if any( quantile(d, q) - r>0)
274 fprintf(1,'Quantile(1): failed\n');
276 fprintf(1,'Quantile(1): OK\n');
278 if exist('histo3','file')
281 H.X = [1;2;4;10;700];
283 H.datatype = 'HISTOGRAM';
285 if any( quantile(H, q)' - r>0)
286 fprintf(1,'Quantile(2): failed\n');
288 fprintf(1,'Quantile(2): OK\n');