From 5ededa8848a5aa9ce7d2ac55b9a831b68cbd08d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Adjemian=20=28Charybdis=29?= Date: Mon, 1 Jul 2013 16:24:17 +0200 Subject: [PATCH] Rewrote @dynSeries/subsasgn. The following syntaxes are now allowed: ts{'VARIABLE_NAME'}(range) = data; where range is a dynDates object and data is an array of doubles, or ts{'VARIABLE_NAME'}(range) = TS{'OTHER_VARIABLE_NAME'}(range) where ts and TS are dynSeries objects. --- matlab/@dynSeries/subsasgn.m | 231 ++++++++++++++++++++++------------- 1 file changed, 148 insertions(+), 83 deletions(-) diff --git a/matlab/@dynSeries/subsasgn.m b/matlab/@dynSeries/subsasgn.m index 724ca0a51..82db27b7a 100644 --- a/matlab/@dynSeries/subsasgn.m +++ b/matlab/@dynSeries/subsasgn.m @@ -25,102 +25,167 @@ function A = subsasgn(A,S,B) % You should have received a copy of the GNU General Public License % along with Dynare. If not, see . -switch S(1).type - case '{}' % Multiple variable selection. - if ~isequal(numel(S(1).subs),numel(unique(S(1).subs))) - error('dynSeries::subsasgn: Wrong syntax!') - end - for i=1:numel(S(1).subs) - element = S(1).subs{i}; - idArobase = strfind(element,'@'); - if ~isempty(idArobase) - switch length(idArobase) - case 2 - idComma = strfind(element(idArobase(1)+1:idArobase(2)-1),','); - if ~isempty(idComma) - elements = cell(1,numel(idComma)+1); j = 1; - expression = element(idArobase(1)+1:idArobase(2)-1); - while ~isempty(expression) - [token, expression] = strtok(expression,','); - elements(j) = {[element(1:idArobase(1)-1), token, element(idArobase(2)+1:end)]}; - j = j + 1; +merge_dynSeries_objects = 1; + +switch length(S) + case 1 + switch S(1).type + case '{}' % Multiple variable selection. + if ~isequal(numel(S(1).subs),numel(unique(S(1).subs))) + error('dynSeries::subsasgn: Wrong syntax!') + end + for i=1:numel(S(1).subs) + element = S(1).subs{i}; + idArobase = strfind(element,'@'); + if ~isempty(idArobase) + switch length(idArobase) + case 2 + idComma = strfind(element(idArobase(1)+1:idArobase(2)-1),','); + if ~isempty(idComma) + elements = cell(1,numel(idComma)+1); j = 1; + expression = element(idArobase(1)+1:idArobase(2)-1); + while ~isempty(expression) + [token, expression] = strtok(expression,','); + elements(j) = {[element(1:idArobase(1)-1), token, element(idArobase(2)+1:end)]}; + j = j + 1; + end + S(1).subs = replace_object_in_a_one_dimensional_cell_array(S(1).subs, elements(:), i); + else + error('dynSeries::subsasgn: Wrong syntax, matlab''s regular expressions cannot be used here!') + end + case 4 + idComma_1 = strfind(element(idArobase(1)+1:idArobase(2)-1),','); + idComma_2 = strfind(element(idArobase(3)+1:idArobase(4)-1),','); + if ~isempty(idComma_1) + elements = cell(1,(numel(idComma_1)+1)*(numel(idComma_2)+1)); j = 1; + expression_1 = element(idArobase(1)+1:idArobase(2)-1); + while ~isempty(expression_1) + [token_1, expression_1] = strtok(expression_1,','); + expression_2 = element(idArobase(3)+1:idArobase(4)-1); + while ~isempty(expression_2) + [token_2, expression_2] = strtok(expression_2,','); + elements(j) = {[element(1:idArobase(1)-1), token_1, element(idArobase(2)+1:idArobase(3)-1), token_2, element(idArobase(4)+1:end)]}; + j = j+1; + end + end + S(1).subs = replace_object_in_a_one_dimensional_cell_array(S(1).subs, elements(:), i); + else + error('dynSeries::subsasgn: Wrong syntax, matlab''s regular expressions cannot be used here!') + end + otherwise + error('dynSeries::subsasgn: Wrong syntax!') + end + end + end + if ~isequal(length(S(1).subs),B.vobs) + error('dynSeries::subsasgn: Wrong syntax!') + end + if ~isequal(S(1).subs(:),B.name) + for i = 1:B.vobs + if ~isequal(S(1).subs{i},B.name{i}) + % Rename a variable. + id = strmatch(S(1).subs{i},A.name); + if isempty(id) + % Add a new variable a change its name. + B.name(i) = {S(1).subs{i}}; + B.tex(i) = {name2tex(S(1).subs{i})}; + else + % Rename variable and change its content. + B.name(i) = A.name(id); + B.tex(i) = A.tex(id); + end + end + end + end + case '.' % Single variable selection. + if ~isequal(S(1).subs,B.name) + if ~isequal(S(1).subs,B.name{1}) + % Rename a variable. + id = strmatch(S(1).subs,A.name); + if isempty(id) + % Add a new variable a change its name. + B.name(1) = {S(1).subs}; + B.tex(1) = {name2tex(S(1).subs)}; + else + % Rename variable and change its content. + B.name(1) = A.name(id); + B.tex(1) = A.tex(id); + end + end + end + case '()' % Date(s) selection + if isa(S(1).subs{1},'dynDates') || isa(S(1).subs{1},'dynDate') + [junk, tdx] = intersect(A.time.time,S(1).subs{1}.time,'rows'); + if isa(B,'dynSeries') + [junk, tdy] = intersect(B.time.time,S(1).subs{1}.time,'rows'); + if isempty(tdy) + error('dynSeries::subsasgn: Periods of the dynSeries objects on the left and right hand sides must intersect!') + end + if ~isequal(A.vobs,B.vobs) + error('dynSeries::subsasgn: Dimension error! The number of variables on the left and right hand side must match.') + end + A.data(tdx,:) = B.data(tdy,:); + elseif isnumeric(B) + merge_dynSeries_objects = 0; + if isequal(length(tdx),rows(B)) + if isequal(columns(A.data),columns(B)) + A.data(tdx,:) = B; + else + error('dynSeries::subsasgn: Dimension error! The number of variables on the left and right hand side must match.') + end + else + error('dynSeries::subsassgn: Dimension error! The number of periods on the left and right hand side must match.') + end + else + error('dynSeries::subsasgn: The object on the right hand side must be a dynSeries object or a numeric array!') + end + else + error('dynSeries::subsasgn: Wrong syntax!') + end + otherwise + error('dynSeries::subsasgn: Wrong syntax!') + end + case 2 + merge_dynSeries_objects = 0; + if ((isequal(S(1).type,'{}') || isequal(S(1).type,'.')) && isequal(S(2).type,'()')) + sA = extract(A,S(1).subs{:}); + if (isa(B,'dynSeries') && isequal(sA.vobs,B.vobs)) || (isnumeric(B) && isequal(sA.vobs,columns(B))) + if isa(S(2).subs{1},'dynDates') || isa(S(2).subs{1},'dynDate') + [junk, tdx] = intersect(sA.time.time,S(2).subs{1}.time,'rows'); + if isa(B,'dynSeries') + [junk, tdy] = intersect(B.time.time,S(2).subs{1}.time,'rows'); + if isempty(tdy) + error('dynSeries::subsasgn: Periods of the dynSeries objects on the left and right hand sides must intersect!') end - S(1).subs = replace_object_in_a_one_dimensional_cell_array(S(1).subs, elements(:), i); - else - error('dynSeries::subsasgn: Wrong syntax, matlab''s regular expressions cannot be used here!') - end - case 4 - idComma_1 = strfind(element(idArobase(1)+1:idArobase(2)-1),','); - idComma_2 = strfind(element(idArobase(3)+1:idArobase(4)-1),','); - if ~isempty(idComma_1) - elements = cell(1,(numel(idComma_1)+1)*(numel(idComma_2)+1)); j = 1; - expression_1 = element(idArobase(1)+1:idArobase(2)-1); - while ~isempty(expression_1) - [token_1, expression_1] = strtok(expression_1,','); - expression_2 = element(idArobase(3)+1:idArobase(4)-1); - while ~isempty(expression_2) - [token_2, expression_2] = strtok(expression_2,','); - elements(j) = {[element(1:idArobase(1)-1), token_1, element(idArobase(2)+1:idArobase(3)-1), token_2, element(idArobase(4)+1:end)]}; - j = j+1; + sA.data(tdx,:) = B.data(tdy,:); + elseif isnumeric(B) + merge_dynSeries_objects = 0; + if isequal(length(tdx),rows(B)) + if isequal(columns(sA.data),columns(B)) + sA.data(tdx,:) = B; + else + error('dynSeries::subsasgn: Dimension error! The number of variables on the left and right hand side must match.') end + else + error('dynSeries::subsassgn: Dimension error! The number of periods on the left and right hand side must match.') end - S(1).subs = replace_object_in_a_one_dimensional_cell_array(S(1).subs, elements(:), i); else - error('dynSeries::subsasgn: Wrong syntax, matlab''s regular expressions cannot be used here!') + error('dynSeries::subsasgn: The object on the right hand side must be a dynSeries object or a numeric array!') end - otherwise + else error('dynSeries::subsasgn: Wrong syntax!') end + A = merge(A,sA); + else + error('dynSeries::subsasgn: Dimension error! The number of variables on the left and right hand side must match.') end end - if ~isequal(length(S(1).subs),B.vobs) - error('dynSeries::subsasgn: Wrong syntax!') - end - if ~isequal(S(1).subs(:),B.name) - for i = 1:B.vobs - if ~isequal(S(1).subs{i},B.name{i}) - % Rename a variable. - id = strmatch(S(1).subs{i},A.name); - if isempty(id) - % Add a new variable a change its name. - B.name(i) = {S(1).subs{i}}; - B.tex(i) = {name2tex(S(1).subs{i})}; - else - % Rename variable and change its content. - B.name(i) = A.name(id); - B.tex(i) = A.tex(id); - end - end - end - end - case '.' % Single variable selection. - if ~isequal(S(1).subs,B.name) - if ~isequal(S(1).subs,B.name{1}) - % Rename a variable. - id = strmatch(S(1).subs,A.name); - if isempty(id) - % Add a new variable a change its name. - B.name(1) = {S(1).subs}; - B.tex(1) = {name2tex(S(1).subs)}; - else - % Rename variable and change its content. - B.name(1) = A.name(id); - B.tex(1) = A.tex(id); - end - end - end - case '()' % Date(s) selection - error('Not yet implemented!') otherwise error('dynSeries::subsasgn: Wrong syntax!') end - -A = merge(A,B); -S = shiftS(S); -if ~isempty(S) - error('dynSeries::subsasgn: Wrong syntax!') - A = subsasgn(A, S, B); +if merge_dynSeries_objects + A = merge(A,B); end %@test:1