Fixed subsasgn method (when calling merge).

It was no more possible to fill a variable with NaNs, after the switch
to the new behaviour of the merge method (see test #5 in
@dseries/merge.m). Added a legacy mode to the merge method to
circumvent the issue (@dseries/subsasgn sets legacy equal to true when
calling the merge method).
parent c5b190d8
function q = merge(o, p) % --*-- Unitary tests --*--
function q = merge(o, p, legacy) % --*-- Unitary tests --*--
% Merge method for dseries objects.
%
% INPUTS
% - o [dseries]
% - p [dseries]
% - legacy [logical] revert to legacy behaviour if `true` (default is `false`),
%
% OUTPUTS
% - q [dseries]
%
% REMARKS
% If dseries objects o and p have common variables, the variables
% in p take precedence except if rewritewithnans is false and p has
% nans.
% in p take precedence except if p has NaNs (the exception can be
% removed by setting the third argument, legacy, equal to true).
% Copyright © 2013-2019 Dynare Team
% Copyright © 2013-2020 Dynare Team
%
% This file is part of Dynare.
%
......@@ -46,6 +47,10 @@ elseif isempty(o) && isempty(p)
return
end
if nargin<3
legacy = false;
end
if ~isequal(frequency(o), frequency(p))
if isempty(inputname(1))
error('dseries::merge: Cannot merge dseries objects (frequencies are different)!')
......@@ -58,7 +63,9 @@ q = dseries();
[q.name, IBC, ~] = unique([o.name; p.name], 'last');
[list_of_common_variables, iO, iP] = intersect(o.name, p.name);
if ~legacy
[list_of_common_variables, iO, iP] = intersect(o.name, p.name);
end
tex = [o.tex; p.tex];
q.tex = tex(IBC);
......@@ -104,13 +111,15 @@ elseif firstdate(o) >= firstdate(p)
end
Z = [Z1 Z2];
q.data = Z(:,IBC);
if ~isempty(list_of_common_variables)
for i=1:length(iP)
jO = iO(i);
jP = iP(i);
jQ = find(strcmp(o.name{jO}, q.name));
id = isnan(q.data(:,jQ)) & ~isnan(Z1(:,jO)) & isnan(Z2(:,jP));
q.data(id, jQ) = Z1(id,jO);
if ~legacy
if ~isempty(list_of_common_variables)
for i=1:length(iP)
jO = iO(i);
jP = iP(i);
jQ = find(strcmp(o.name{jO}, q.name));
id = isnan(q.data(:,jQ)) & ~isnan(Z1(:,jO)) & isnan(Z2(:,jP));
q.data(id, jQ) = Z1(id,jO);
end
end
end
q_init = firstdate(p);
......@@ -128,13 +137,15 @@ else
end
Z = [Z2 Z1];
q.data = Z(:,IBC);
if ~isempty(list_of_common_variables)
for i=1:length(iP)
jO = iO(i);
jP = iP(i);
jQ = find(strcmp(o.name{jO}, q.name));
id = isnan(q.data(:,jQ)) & isnan(Z1(:,jP)) & ~isnan(Z2(:,jO));
q.data(id, jQ) = Z2(id,jO);
if ~legacy
if ~isempty(list_of_common_variables)
for i=1:length(iP)
jO = iO(i);
jP = iP(i);
jQ = find(strcmp(o.name{jO}, q.name));
id = isnan(q.data(:,jQ)) & isnan(Z1(:,jP)) & ~isnan(Z2(:,jO));
q.data(id, jQ) = Z2(id,jO);
end
end
end
q_init = firstdate(o);
......@@ -247,4 +258,27 @@ q.dates = q_init:q_init+(nobs(q)-1);
%$ t(5) = all(x.dates==dates('1989Q1'):dates('1990Q4'));
%$ end
%$ T = all(t);
%@eof:4
\ No newline at end of file
%@eof:4
%@test:5
%$ % Define two dseries objects.
%$ y = dseries(ones(8,1),'1938Q4', 'u');
%$ z = dseries(NaN(8,1),'1938Q4', 'u');
%$
%$ % Inderectly call merge method via subsasgn.
%$ try
%$ y.u = z.u;
%$ t(1) = true;
%$ catch
%$ t = false;
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(y.vobs, 1);
%$ t(3) = dassert(y.name{1}, 'u');
%$ t(4) = all(isnan(y.data));
%$ t(5) = dassert(y.nobs, z.nobs);
%$ t(6) = dassert(y.dates(1), z.dates(1));
%$ end
%$ T = all(t);
%@eof:5
\ No newline at end of file
......@@ -8,7 +8,7 @@ function A = subsasgn(A,S,B) % --*-- Unitary tests --*--
%! @end deftypefn
%@eod:
% Copyright (C) 2012-2017 Dynare Team
% Copyright © 2012-2020 Dynare Team
%
% This file is part of Dynare.
%
......@@ -25,7 +25,7 @@ function A = subsasgn(A,S,B) % --*-- Unitary tests --*--
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
merge_dseries_objects = 1;
merge_dseries_objects = true;
switch length(S)
case 1
......@@ -130,9 +130,9 @@ switch length(S)
error('dseries::subsasgn: Dimension error! The number of variables on the left and right hand side must match.')
end
A.data(tdx,:) = B.data(tdy,:);
merge_dseries_objects = 0;
merge_dseries_objects = false;
elseif isnumeric(B)
merge_dseries_objects = 0;
merge_dseries_objects = false;
if isequal(length(tdx),rows(B))
if isequal(columns(A.data),columns(B))
A.data(tdx,:) = B;
......@@ -174,7 +174,7 @@ switch length(S)
error('dseries::subsasgn: Wrong syntax!')
end
case 2
merge_dseries_objects = 0;
merge_dseries_objects = false;
if ((isequal(S(1).type,'{}') || isequal(S(1).type,'.')) && isequal(S(2).type,'()'))
if isequal(S(1).type,'{}')
sA = extract(A,S(1).subs{:});
......@@ -191,7 +191,7 @@ switch length(S)
end
sA.data(tdx,:) = B.data(tdy,:);
elseif isnumeric(B)
merge_dseries_objects = 0;
merge_dseries_objects = false;
if isequal(length(tdx),rows(B))
if isequal(columns(sA.data),columns(B))
sA.data(tdx,:) = B;
......@@ -215,7 +215,7 @@ switch length(S)
else
error('dseries::subsasgn: Wrong syntax!')
end
A = merge(A,sA);
A = merge(A, sA, true);
else
error('dseries::subsasgn: Dimension error! The number of variables on the left and right hand side must match.')
end
......@@ -231,7 +231,7 @@ if isempty(A)
end
if merge_dseries_objects
A = merge(A,B);
A = merge(A, B, true);
end
%@test:1
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment