Various improvements to subsasgn and subsref.

 + Code factorization.
 + Allows regular expressions in subsasgn method.
parent 441acb50
......@@ -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
......@@ -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)
......
......@@ -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
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
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
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