]> Creatis software - CreaPhase.git/blob - octave_packages/nan-2.5.5/sumskipnan.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / nan-2.5.5 / sumskipnan.m
1 function [o,count,SSQ] = sumskipnan(x, DIM, W)
2 % SUMSKIPNAN adds all non-NaN values. 
3 %
4 % All NaN's are skipped; NaN's are considered as missing values. 
5 % SUMSKIPNAN of NaN's only  gives O; and the number of valid elements is return. 
6 % SUMSKIPNAN is also the elementary function for calculating 
7 % various statistics (e.g. MEAN, STD, VAR, RMS, MEANSQ, SKEWNESS, 
8 % KURTOSIS, MOMENT, STATISTIC etc.) from data with missing values.  
9 % SUMSKIPNAN implements the DIMENSION-argument for data with missing values.
10 % Also the second output argument return the number of valid elements (not NaNs) 
11
12 % Y = sumskipnan(x [,DIM])
13 % [Y,N,SSQ] = sumskipnan(x [,DIM])
14 % [...] = sumskipnan(x, DIM, W)
15
16 % x     input data      
17 % DIM   dimension (default: [])
18 %       empty DIM sets DIM to first non singleton dimension     
19 % W     weight vector for weighted sum, numel(W) must fit size(x,DIM)
20 % Y     resulting sum
21 % N     number of valid (not missing) elements
22 % SSQ   sum of squares
23 %
24 % the function FLAG_NANS_OCCURED() returns whether any value in x
25 %  is a not-a-number (NaN)
26 %
27 % features:
28 % - can deal with NaN's (missing values)
29 % - implements dimension argument. 
30 % - computes weighted sum 
31 % - compatible with Matlab and Octave
32 %
33 % see also: FLAG_NANS_OCCURED, SUM, NANSUM, MEAN, STD, VAR, RMS, MEANSQ, 
34 %      SSQ, MOMENT, SKEWNESS, KURTOSIS, SEM
35
36
37 %    This program is free software; you can redistribute it and/or modify
38 %    it under the terms of the GNU General Public License as published by
39 %    the Free Software Foundation; either version 3 of the License, or
40 %    (at your option) any later version.
41 %
42 %    This program is distributed in the hope that it will be useful,
43 %    but WITHOUT ANY WARRANTY; without even the implied warranty of
44 %    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
45 %    GNU General Public License for more details.
46 %
47 %    You should have received a copy of the GNU General Public License
48 %    along with this program; If not, see <http://www.gnu.org/licenses/>.
49
50 %       $Id: sumskipnan.m 9033 2011-11-08 20:58:07Z schloegl $
51 %       Copyright (C) 2000-2005,2009,2011 by Alois Schloegl <alois.schloegl@gmail.com>  
52 %       This function is part of the NaN-toolbox
53 %       http://pub.ist.ac.at/~schloegl/matlab/NaN/
54
55
56 global FLAG_NANS_OCCURED;
57
58 if nargin<2,
59         DIM = [];
60 end;
61 if nargin<3,
62         W = [];
63 end;
64
65 % an efficient implementation in C of the following lines 
66 % could significantly increase performance 
67 % only one loop and only one check for isnan is needed
68 % An MEX-Implementation is available in sumskipnan.cpp
69 %
70 % Outline of the algorithm: 
71 % for { k=1,o=0,count=0; k++; k<N} 
72 %       if ~isnan(i(k)) 
73 %       {       o     += x(k);
74 %               count += 1;
75 %               tmp    = x(k)*x(k)
76 %               o2    += tmp;
77 %               o3    += tmp.*tmp;
78 %       }; 
79
80 if isempty(DIM),
81         DIM = find(size(x)>1,1);
82         if isempty(DIM), DIM = 1; end;
83 end
84 if (DIM<1), DIM = 1; end; %% Hack, because min([])=0 for FreeMat v3.5
85
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 % non-float data 
88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 if  (isempty(W) && (~(isa(x,'float') || isa(x,'double')))) || ~flag_implicit_skip_nan(), %%% skip always NaN's
90         if ~isempty(W)
91                 error('SUMSKIPNAN: weighted sum of integers not supported, yet');
92         end; 
93         x = double(x); 
94         o = sum(x,DIM);
95         if nargout>1
96                 sz = size(x);
97                 N  = sz(DIM); 
98                 sz(DIM) = 1;    
99                 count = repmat(N,sz);
100                 if nargout>2
101                         x = x.*x; 
102                         SSQ = sum(x,DIM);
103                 end; 
104         end;    
105         return; 
106 end;    
107
108 if (length(size(x))<DIM)
109         error('SUMSKIPNAN: DIM argument larger than number of dimensions of x');
110 elseif ~isempty(W) && (size(x,DIM)~=numel(W))
111         error('SUMSKIPNAN: size of weight vector does not match size(x,DIM)');
112 end; 
113
114 %% mex and oct files expect double
115 x = double(x);
116
117 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
118 % use Matlab-MEX function when available  
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 %if 1,  
121 try
122         
123         %% using sumskipnan_mex.mex
124
125         %% !!! hack: FLAG_NANS_OCCURED is an output argument, reserve memory !!!
126         if isempty(FLAG_NANS_OCCURED),
127                 FLAG_NANS_OCCURED = logical(0);  % default value 
128         end;
129
130         if (nargout<2),
131                 o = sumskipnan_mex(real(x),DIM,FLAG_NANS_OCCURED,W);
132                 if (~isreal(x))
133                         io = sumskipnan_mex(imag(x),DIM,FLAG_NANS_OCCURED,W);
134                         o  = o + i*io;
135                 end; 
136                 return; 
137         elseif (nargout==2),
138                 [o,count] = sumskipnan_mex(real(x),DIM,FLAG_NANS_OCCURED,W);
139                 if (~isreal(x))
140                         [io,icount] = sumskipnan_mex(imag(x),DIM,FLAG_NANS_OCCURED,W);
141                         if any(count(:)-icount(:))
142                                 error('Number of NaNs differ for REAL and IMAG part');
143                         else
144                                 o  = o+i*io;
145                         end; 
146                 end; 
147                 return; 
148         elseif (nargout>=3),
149                 [o,count,SSQ] = sumskipnan_mex(real(x),DIM,FLAG_NANS_OCCURED,W);
150                 if (~isreal(x))
151                         [io,icount,iSSQ] = sumskipnan_mex(imag(x),DIM,FLAG_NANS_OCCURED,W);
152                         if any(count(:)-icount(:))
153                                 error('Number of NaNs differ for REAL and IMAG part');
154                         else
155                                 o  = o+i*io;
156                                 SSQ = SSQ+iSSQ;
157                         end; 
158                 end; 
159                 return; 
160         end;    
161 end; 
162
163 if ~isempty(W) 
164         error('weighted sumskipnan requires sumskipnan_mex');
165 end;    
166
167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
168 % count non-NaN's
169 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 if nargout>1,
171         count = sum(x==x,DIM); 
172         FLAG_NANS_OCCURED = any(count(:)<size(x,DIM));
173 end;
174
175 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
176 % replace NaN's with zero 
177 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
178 x(x~=x) = 0;    
179 o = sum(x,DIM);
180
181 if nargout>2,
182         x = real(x).^2 + imag(x).^2;
183         SSQ = sum(x,DIM);
184 end;
185
186 %!assert(sumskipnan([1,2],1),[1,2])
187 %!assert(sumskipnan([1,NaN],2),1)
188 %!assert(sumskipnan([1,NaN],2),1)
189 %!assert(sumskipnan([nan,1,4,5]),10)
190 %!assert(sumskipnan([nan,1,4,5]',1,[3;2;1;0]),6)
191
192
193