1function o = cumsum_(varargin) % --*-- Unitary tests --*--
2
3% Overloads matlab's cumsum function for dseries objects.
4%
5% INPUTS
6% - o     dseries object [mandatory].
7% - d     dates object [optional]
8% - v     dseries object with one observation [optional]
9%
10% OUTPUTS
11% - o     dseries object.
12
13% Copyright (C) 2013-2017 Dynare Team
14%
15% This file is part of Dynare.
16%
17% Dynare is free software: you can redistribute it and/or modify
18% it under the terms of the GNU General Public License as published by
19% the Free Software Foundation, either version 3 of the License, or
20% (at your option) any later version.
21%
22% Dynare is distributed in the hope that it will be useful,
23% but WITHOUT ANY WARRANTY; without even the implied warranty of
24% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25% GNU General Public License for more details.
26%
27% You should have received a copy of the GNU General Public License
28% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
29
30% Get the firt observation number where all the variables are observed (ie without NaNs)
31idx = find(all(~isnan(varargin{1}.data), 2),1);
32if isempty(idx)
33    idx = 0;
34end
35
36% Is the first period where variables are observed common?
37common_first_period_witout_nan = true;
38if ~idx
39    if any(~isnan(varargin{1}.data(:)))
40        common_first_period_witout_nan = false;
41    end
42else
43    if idx>1
44        if any(any(~isnan(varargin{1}.data(1:idx-1,:))))
45            common_first_period_witout_nan = false;
46        end
47    end
48end
49
50switch nargin
51  case 1
52    % Initialize the output.
53    o = varargin{1};
54    % Perform the cumulated sum
55    if isequal(idx, 1)
56        o.data = cumsum(o.data);
57    else
58        if common_first_period_witout_nan
59            o.data(idx:end,:) = cumsum(o.data(idx:end,:));
60        else
61            o.data = cumsumnan(o.data);
62        end
63    end
64    for i=1:vobs(o)
65        if isempty(o.ops{i})
66            o.ops(i) = {['cumsum(' o.name{i} ')']};
67        else
68            o.ops(i) = {['cumsum(' o.ops{i} ')']};
69        end
70    end
71  case 2
72    if isdseries(varargin{2})
73        if ~isequal(vobs(varargin{1}), vobs(varargin{2}))
74            error('dseries::cumsum: First and second input arguments must be dseries objects with the same number of variables!')
75        end
76        if ~isequal(varargin{1}.name, varargin{2}.name)
77            warning('dseries::cumsum: First and second input arguments must be dseries objects do not have the same variables!')
78        end
79        if ~isequal(nobs(varargin{2}),1)
80            error('dseries::cumsum: Second input argument must be a dseries object with only one observation!')
81        end
82        o = cumsum_(varargin{1});
83        o.data = bsxfun(@plus,o.data,varargin{2}.data);
84    elseif isdates(varargin{2})
85        o = cumsum_(varargin{1});
86        t = find(o.dates==varargin{2});
87        if isempty(t)
88            if varargin{2}==(firstdate(o)-1)
89                return
90            else
91                error(['dseries::cumsum: date ' date2string(varargin{2}) ' is not in the sample!'])
92            end
93        end
94        o.data = bsxfun(@minus,o.data,o.data(t,:));
95    else
96        error('dseries::cumsum: Second input argument must be a dseries object or a dates object!')
97    end
98  case 3
99    if ~isdates(varargin{2})
100        error('dseries::cumsum: Second input argument must be a dates object!')
101    end
102    if ~isdseries(varargin{3})
103        error('dseries::cumsum: Third input argument must be a dseries object!')
104    end
105    if ~isequal(vobs(varargin{1}), vobs(varargin{3}))
106        error('dseries::cumsum: First and third input arguments must be dseries objects with the same number of variables!')
107    end
108    if ~isequal(varargin{1}.name, varargin{3}.name)
109        warning('dseries::cumsum: First and third input arguments must be dseries objects do not have the same variables!')
110    end
111    if ~isequal(nobs(varargin{3}),1)
112        error('dseries::cumsum: Third input argument must be a dseries object with only one observation!')
113    end
114    o = cumsum_(varargin{1});
115    t = find(o.dates==varargin{2});
116    if isempty(t)
117        if varargin{2}==(firstdate(o)-1)
118            o.data = bsxfun(@plus, o.data, varargin{3}.data);
119            return
120        else
121            error(['dseries::cumsum: date ' date2string(varargin{2}) ' is not in the sample!'])
122        end
123    end
124    o.data = bsxfun(@plus, o.data,varargin{3}.data-o.data(t,:));
125  otherwise
126    error('dseries::cumsum: Wrong number of input arguments!')
127end
128
129%@test:1
130%$ % Define a data set.
131%$ A = ones(10,1);
132%$
133%$ % Define names
134%$ A_name = {'A1'};
135%$
136%$ % Instantiate a time series object.
137%$ ts1 = dseries(A,[],A_name,[]);
138%$
139%$ % Call the tested method.
140%$ try
141%$   ts1.cumsum_();
142%$   t(1) = 1;
143%$ catch
144%$   t(1) = 0;
145%$ end
146%$
147%$ % Expected results.
148%$ ts2 = dseries(transpose(1:10), [], A_name, []);
149%$
150%$ % Check the results.
151%$ if t(1)
152%$   t(2) = dassert(ts1.data, ts2.data);
153%$ end
154%$ T = all(t);
155%@eof:1
156
157%@test:2
158%$ % Define a data set.
159%$ A = ones(10,1);
160%$
161%$ % Define names
162%$ A_name = {'A1'};
163%$
164%$ % Instantiate a time series object.
165%$ ts1 = dseries(A,[],A_name,[]);
166%$
167%$ % Call the tested method.
168%$ try
169%$   cumsum_(ts1);
170%$   t(1) = 1;
171%$ catch
172%$   t(1) = 0;
173%$ end
174%$
175%$ % Expected results.
176%$ ts2 = dseries(transpose(1:10), [], A_name, []);
177%$
178%$ % Check the results.
179%$ if t(1)
180%$   t(2) = dassert(ts1.data, ts2.data);
181%$ end
182%$ T = all(t);
183%@eof:2
184
185%@test:3
186%$ % Define a data set.
187%$ A = ones(10,1);
188%$
189%$ % Define names
190%$ A_name = {'A1'};
191%$
192%$ % Instantiate a time series object.
193%$ ts1 = dseries(A,[],A_name,[]);
194%$
195%$ % Call the tested method.
196%$ try
197%$   ts1.cumsum_(dates('3Y'));
198%$   t(1) = 1;
199%$ catch
200%$   t(1) = 0;
201%$ end
202%$
203%$ % Expected results.
204%$ ts2 = dseries([-2; -1; 0; 1; 2; 3; 4; 5; 6; 7], [], A_name, []);
205%$
206%$ % Check the results.
207%$ if t(1)
208%$   t(2) = dassert(ts1.data, ts2.data);
209%$ end
210%$ T = all(t);
211%@eof:3
212
213%@test:4
214%$ % Define a data set.
215%$ A = ones(10,1);
216%$
217%$ % Define names
218%$ A_name = {'A1'};
219%$
220%$ % Instantiate a time series object.
221%$ ts1 = dseries(A,[],A_name,[]);
222%$ ts2 = dseries(pi, [], A_name, []);
223%$
224%$ % Call the tested method.
225%$ try
226%$   ts1.cumsum_(dates('3Y'), ts2);
227%$   t(1) = 1;
228%$ catch
229%$   t(1) = 0;
230%$ end
231%$
232%$ % Expected results.
233%$ ts3 = dseries([-2; -1; 0; 1; 2; 3; 4; 5; 6; 7]+pi, [], A_name, []);
234%$
235%$ % Check the results.
236%$ if t(1)
237%$   t(2) = dassert(ts1.data, ts3.data);
238%$ end
239%$ T = all(t);
240%@eof:4
241
242%@test:5
243%$ % Define a data set.
244%$ A = ones(10,1);
245%$
246%$ % Define names
247%$ A_name = {'A1'};
248%$
249%$ % Instantiate a time series object.
250%$ ts1 = dseries(A,[],A_name,[]);
251%$ ts2 = dseries(pi, [], A_name, []);
252%$
253%$ % Call the tested method.
254%$ try
255%$   ts1.cumsum_(dates('3Y'), ts2);
256%$   t(1) = 1;
257%$ catch
258%$   t(1) = 0;
259%$ end
260%$
261%$ % Expected results.
262%$ ts3 = dseries([-2; -1; 0; 1; 2; 3; 4; 5; 6; 7]+pi, [], A_name, []);
263%$
264%$ % Check the results.
265%$ if t(1)
266%$   t(2) = dassert(ts1.data, ts3.data);
267%$ end
268%$ T = all(t);
269%@eof:5
270
271%@test:6
272%$ % Define a data set.
273%$ A = [NaN, NaN; 1 NaN; 1 1; 1 1; 1 NaN];
274%$
275%$ % Instantiate a time series object.
276%$ ts0 = dseries(A);
277%$
278%$ % Call the tested method.
279%$ try
280%$   ts0.cumsum_();
281%$   t(1) = 1;
282%$ catch
283%$   t(1) = 0;
284%$ end
285%$
286%$ % Expected results.
287%$ A = [NaN   NaN; 1   NaN; 2     1; 3     2; 4   NaN];
288%$
289%$ % Check the results.
290%$ if t(1)
291%$   t(2) = dassert(ts0.data, A);
292%$ end
293%$ T = all(t);
294%@eof:6