diff --git a/src/@dseries/extract.m b/src/@dseries/extract.m index 05b2d22a1c4682d16b7a6dd7b74d860767a582d5..af479fdefcbe76f4d92866cf7e7b483e5ec3bad6 100644 --- a/src/@dseries/extract.m +++ b/src/@dseries/extract.m @@ -25,87 +25,26 @@ A = dseries(); VariableName_ = {}; for i=1:nargin-1 VariableName = varargin{i}; + % Implicit loop. idArobase = strfind(VariableName,'@'); if mod(length(idArobase),2) error('dseries::extract: (Implicit loops) The number of @ symbols must be even!') end + % Regular expression idBracket.open = strfind(VariableName,'['); idBracket.close = strfind(VariableName,']'); if ~isequal(length(idBracket.open),length(idBracket.open)) error('dseries::extract: (Matlab/Octave''s regular expressions) Check opening and closing square brackets!') end + % Loops and regular expressions are not compatible + if length(idArobase) && length(idBracket.open) + error(['dseries::extract: You cannot use implicit loops and regular expressions in the same rule!']) + end + % Update the list of variables. if length(idArobase) - NumberOfImplicitLoops = .5*length(idArobase); - idComma = cell(NumberOfImplicitLoops,1); - expressions = cell(NumberOfImplicitLoops,1); - for i=0:NumberOfImplicitLoops-1 - idComma(i+1) = { strfind(VariableName(idArobase(2*i+1)+1:idArobase(2*i+2)-1),',') }; - expressions(i+1) = { VariableName(idArobase(2*i+1)+1:idArobase(2*i+2)-1) }; - end - if any(cellfun(@isempty,idComma)) - error('dseries::extract: (Implicit loops) Wrong syntax!') - end - switch NumberOfImplicitLoops - case 1 - expression = expressions{1}; - idVariables_ = []; - while ~isempty(expression) - [token, expression] = strtok(expression,','); - candidate = [VariableName(1:idArobase(1)-1), token, VariableName(idArobase(2)+1:end)]; - id = find(strcmp(candidate,B.name)); - if isempty(id) - error(['dseries::extract: (Implicit loops) Variable ''' candidate ''' does not exist in dseries object ''' inputname(1) '''!']) - else - idVariables_ = [idVariables_; id]; - end - end - VariableName = B.name(idVariables_); - case 2 - idVariables_ = []; - expression_1 = expressions{1}; - while ~isempty(expression_1) - [token_1, expression_1] = strtok(expression_1,','); - expression_2 = expressions{2}; - while ~isempty(expression_2) - [token_2, expression_2] = strtok(expression_2,','); - candidate = [VariableName(1:idArobase(1)-1), token_1, VariableName(idArobase(2)+1:idArobase(3)-1), token_2, VariableName(idArobase(4)+1:end)]; - id = find(strcmp(candidate,B.name)); - if isempty(id) - error(['dseries::extract: (Implicit loops) Variable ''' candidate ''' does not exist in dseries object ''' inputname(1) '''!']) - else - idVariables_ = [idVariables_; id]; - end - end - end - VariableName = B.name(idVariables_); - otherwise - error('dseries::extract: (Implicit loops) Cannot unroll more than two implicit loops!') - end - VariableName_ = vertcat(VariableName_,VariableName); + VariableName_ = build_list_of_variables_with_loops(B.name, idArobase, VariableName, VariableName_); elseif length(idBracket.open) - % Matlab/Octave's regular expressions. - first_block_id = 0; - last_block_id = 0; - idVariables = find(isnotempty_cell(regexp(B.name,VariableName,'match'))); - if isempty(idVariables) - error(['dseries::extract: Can''t find any variable matching ' VariableName ' pattern!']) - end - idVariables_ = []; - for j = 1:length(idVariables) - first_block_flag = 0; - if (first_block_id && strcmp(B.name{idVariables(j)}(1:first_block_id),VariableName(1:first_block_id))) || ~first_block_id - first_block_flag = 1; - end - last_block_flag = 0; - if (last_block_id && strcmp(B.name{idVariables(j)}(end-last_block_id:end),VariableName(end-last_block_id:end))) || ~last_block_id - last_block_flag = 1; - end - if first_block_flag && last_block_flag - idVariables_ = [idVariables_; idVariables(j)]; - end - end - VariableName = B.name(idVariables_); - VariableName_ = vertcat(VariableName_,VariableName); + VariableName_ = build_list_of_variables_with_regexp(B.name, idBracket, VariableName, VariableName_); else VariableName_ = varargin(:); end @@ -128,15 +67,6 @@ A.data = B.data(:,idVariableName); A.dates = B.dates; A.name = B.name(idVariableName); A.tex = B.tex(idVariableName); - -function b = isnotempty_cell(CellArray) - CellArrayDimension = size(CellArray); - b = NaN(CellArrayDimension); - for i=1:CellArrayDimension(1) - for j = 1:CellArrayDimension(2) - b(i,j) = ~isempty(CellArray{i,j}); - end - end %@test:1 @@ -227,4 +157,4 @@ function b = isnotempty_cell(CellArray) %$ end %$ %$ T = all(t); -%@eof:3 +%@eof:3 \ No newline at end of file diff --git a/src/@dseries/subsasgn.m b/src/@dseries/subsasgn.m index e2c9ea0dd9bdc211b1dddf3938e96bc59a2cf6a0..2564e48283b9d03b57186c56a493509ad391fd3f 100644 --- a/src/@dseries/subsasgn.m +++ b/src/@dseries/subsasgn.m @@ -36,45 +36,28 @@ switch length(S) end for i=1:numel(S(1).subs) element = S(1).subs{i}; + % Implicit loop. idArobase = strfind(element,'@'); + if mod(length(idArobase),2) + error('dseries::subsasgn: (Implicit loops) The number of @ symbols must be even!') + end + % regular expression. + idBracket.open = strfind(element, '['); + idBracket.close = strfind(element, ']'); + if ~isequal(length(idBracket.open),length(idBracket.open)) + error('dseries::subsasgn: (Matlab/Octave''s regular expressions) Check opening and closing square brackets!') + end + % Loops and regular expressions are not compatible + if length(idArobase) && length(idBracket.open) + error(['dseries::subsasgn: You cannot use implicit loops and regular expressions in the same rule!']) + end 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('dseries::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('dseries::subsasgn: Wrong syntax, matlab''s regular expressions cannot be used here!') - end - otherwise - error('dseries::subsasgn: Wrong syntax!') - end + elements = build_list_of_variables_with_loops(A.name, idArobase, element, {}); + S(1).subs = replace_object_in_a_one_dimensional_cell_array(S(1).subs, elements(:), i); + end + if ~isempty(idBracket.open) + elements = build_list_of_variables_with_regexp(A.name, idBracket, element, {}); + S(1).subs = replace_object_in_a_one_dimensional_cell_array(S(1).subs, elements(:), i); end end if isempty(B) diff --git a/src/initialize_dseries_toolbox.m b/src/initialize_dseries_toolbox.m index 7ebb39025e8a7bb0b9a5179ddb10e961ceab9e4a..60719e3fc7b079c142c055a0f4666730b8d0457f 100644 --- a/src/initialize_dseries_toolbox.m +++ b/src/initialize_dseries_toolbox.m @@ -22,6 +22,7 @@ addpath([dseries_src_root '/utilities/str']) addpath([dseries_src_root '/utilities/insert']) addpath([dseries_src_root '/utilities/file']) addpath([dseries_src_root '/utilities/from']) +addpath([dseries_src_root '/utilities/variables']) % Add missing routines if dynare is not in the path if ~exist('demean','file') @@ -42,4 +43,4 @@ end if isoctave && ~exist('user_has_octave_forge_package','file') addpath([dseries_src_root '/utilities/missing/user_has_octave_forge_package']) -end \ No newline at end of file +end diff --git a/src/utilities/variables/build_list_of_variables_with_loops.m b/src/utilities/variables/build_list_of_variables_with_loops.m new file mode 100644 index 0000000000000000000000000000000000000000..b85e7991b81ec401464fa3bae33bb31e29511b04 --- /dev/null +++ b/src/utilities/variables/build_list_of_variables_with_loops.m @@ -0,0 +1,88 @@ +function list_of_variables = build_list_of_variables_with_loops(o_list_of_variables, idArobase, VariableName, list_of_variables) + +% Copyright (C) 2016 Dynare Team +% +% This file is part of Dynare. +% +% Dynare is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% Dynare is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTAoILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with Dynare. If not, see <http://www.gnu.org/licenses/>. + +checknames = isempty(o_list_of_variables); + +NumberOfImplicitLoops = .5*length(idArobase); + +idComma = cell(NumberOfImplicitLoops,1); + +expressions = cell(NumberOfImplicitLoops,1); + +for i=0:NumberOfImplicitLoops-1 + idComma(i+1) = { strfind(VariableName(idArobase(2*i+1)+1:idArobase(2*i+2)-1),',') }; + expressions(i+1) = { VariableName(idArobase(2*i+1)+1:idArobase(2*i+2)-1) }; +end + +if any(cellfun(@isempty,idComma)) + error('dseries::loops: (Implicit loops) Wrong syntax!') +end + +switch NumberOfImplicitLoops + case 1 + expression = expressions{1}; + idVariables_ = []; + while ~isempty(expression) + [token, expression] = strtok(expression,','); + candidate = [VariableName(1:idArobase(1)-1), token, VariableName(idArobase(2)+1:end)]; + if checknames + id = find(strcmp(candidate,o_list_of_variables)); + if isempty(id) + error(['dseries::loops: (Implicit loops) Variable ''' candidate ''' does not exist in dseries object ''' inputname(1) '''!']) + else + idVariables_ = [idVariables_; id]; + end + else + list_of_variables = vertcat(list_of_variables, candidate); + end + end + if checknames + VariableName = o_list_of_variables(idVariables_); + end + case 2 + idVariables_ = []; + expression_1 = expressions{1}; + while ~isempty(expression_1) + [token_1, expression_1] = strtok(expression_1,','); + expression_2 = expressions{2}; + while ~isempty(expression_2) + [token_2, expression_2] = strtok(expression_2,','); + candidate = [VariableName(1:idArobase(1)-1), token_1, VariableName(idArobase(2)+1:idArobase(3)-1), token_2, VariableName(idArobase(4)+1:end)]; + if checknames + id = find(strcmp(candidate,o_list_of_variables)); + if isempty(id) + error(['dseries::loops: (Implicit loops) Variable ''' candidate ''' does not exist in dseries object ''' inputname(1) '''!']) + else + idVariables_ = [idVariables_; id]; + end + else + list_of_variables = vertcat(list_of_variables, candidate); + end + end + end + if checknames + VariableName = o_list_of_variables(idVariables_); + end + otherwise + error('dseries::loops: (Implicit loops) Cannot unroll more than two implicit loops!') +end + +if checknames + list_of_variables = vertcat(list_of_variables, VariableName); +end \ No newline at end of file diff --git a/src/utilities/variables/build_list_of_variables_with_regexp.m b/src/utilities/variables/build_list_of_variables_with_regexp.m new file mode 100644 index 0000000000000000000000000000000000000000..90d76c93debbbd4481d1d96089f4f3f1ac843162 --- /dev/null +++ b/src/utilities/variables/build_list_of_variables_with_regexp.m @@ -0,0 +1,56 @@ +function list_of_variables = build_list_of_variables_with_regexp(o_list_of_variables, idBrackets, VariableName, list_of_variables) + +% Copyright (C) 2016 Dynare Team +% +% This file is part of Dynare. +% +% Dynare is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% Dynare is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTAoILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with Dynare. If not, see <http://www.gnu.org/licenses/>. + +first_block_id = 0; +last_block_id = 0; + +idVariables = find(isnotempty_cell(regexp(o_list_of_variables,VariableName,'match'))); + +if isempty(idVariables) + error(['dseries::regexp: Can''t find any variable matching ' VariableName ' pattern!']) +end + +idVariables_ = []; + +for j = 1:length(idVariables) + first_block_flag = 0; + if (first_block_id && strcmp(o_list_of_variables{idVariables(j)}(1:first_block_id),VariableName(1:first_block_id))) || ~first_block_id + first_block_flag = 1; + end + last_block_flag = 0; + if (last_block_id && strcmp(o_list_of_variables{idVariables(j)}(end-last_block_id:end),VariableName(end-last_block_id:end))) || ~last_block_id + last_block_flag = 1; + end + if first_block_flag && last_block_flag + idVariables_ = [idVariables_; idVariables(j)]; + end +end + +VariableName = o_list_of_variables(idVariables_); +list_of_variables = vertcat(list_of_variables, VariableName); + + +function b = isnotempty_cell(CellArray) + CellArrayDimension = size(CellArray); + b = NaN(CellArrayDimension); + for i=1:CellArrayDimension(1) + for j = 1:CellArrayDimension(2) + b(i,j) = ~isempty(CellArray{i,j}); + end + end