From 117f338effd2dd64021666a3f1bc610058c0b7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Adjemian=20=28Charybdis=29?= Date: Wed, 15 Jan 2014 18:22:32 +0100 Subject: [PATCH] Implement broadcasting for operations (+,-,* and /) between dseries and scalar or vectors. Efficiency and cosmetic changes. --- matlab/@dseries/minus.m | 40 ++++++------------- matlab/@dseries/mrdivide.m | 50 +++++++++-------------- matlab/@dseries/mtimes.m | 77 ++++++++++++++++++++--------------- matlab/@dseries/plus.m | 82 +++++++++++++++++++++++++++----------- 4 files changed, 133 insertions(+), 116 deletions(-) diff --git a/matlab/@dseries/minus.m b/matlab/@dseries/minus.m index 90ab2a1e2..6f7c47dbc 100644 --- a/matlab/@dseries/minus.m +++ b/matlab/@dseries/minus.m @@ -23,7 +23,7 @@ function A = minus(B,C) % --*-- Unitary tests --*-- %! @end deftypefn %@eod: -% Copyright (C) 2012-2013 Dynare Team +% Copyright (C) 2012-2014, Dynare Team % % This file is part of Dynare. % @@ -40,38 +40,22 @@ function A = minus(B,C) % --*-- Unitary tests --*-- % You should have received a copy of the GNU General Public License % along with Dynare. If not, see . -if isnumeric(B) && isreal(B) && isequal(length(B),1) && isdseries(C) - A = dseries(); - A.freq = C.freq; - A.init = C.init; - A.dates = C.dates; - A.nobs = C.nobs; - A.vobs = C.vobs; - A.name = cell(A.vobs,1); - A.tex = cell(A.vobs,1); - for i=1:A.vobs - A.name(i) = {['minus(' num2str(B) ',' C.name{i} ')']}; - A.tex(i) = {['(' num2str(B) '-' C.tex{i} ')']}; +if isnumeric(B) && (isscalar(B) || isvector(B)) + if ~isdseries(C) + error('dseries::minus: Second input argument must be a dseries object!') end - A.data = bsxfun(@minus, B, C.data); + A = C; + A.data = bsxfun(@minus,C.data,B); return; end -if isnumeric(C) && isreal(C) && isequal(length(C),1) && isdseries(B) - A = dseries(); - A.freq = B.freq; - A.init = B.init; - A.dates = B.dates; - A.nobs = B.nobs; - A.vobs = B.vobs; - A.name = cell(A.vobs,1); - A.tex = cell(A.vobs,1); - for i=1:A.vobs - A.name(i) = {['minus(' B.name{i} ',' num2str(C) ')']}; - A.tex(i) = {['(' B.tex{i} '-' num2str(C) ')']}; +if isnumeric(C) && (isscalar(C) || isvector(C)) + if ~isdseries(B) + error('dseries::minus: First input argument must be a dseries object!') end - A.data = bsxfun(@minus, B.data, C); - return; + A = B; + A.data = bsxfun(@minus,B.data,C); + return end if ~isequal(B.vobs,C.vobs) && ~(isequal(B.vobs,1) || isequal(C.vobs,1)) diff --git a/matlab/@dseries/mrdivide.m b/matlab/@dseries/mrdivide.m index ba01826a3..e42b47aa9 100644 --- a/matlab/@dseries/mrdivide.m +++ b/matlab/@dseries/mrdivide.m @@ -23,7 +23,7 @@ function A = mrdivide(B,C) % --*-- Unitary tests --*-- %! @end deftypefn %@eod: -% Copyright (C) 2012-2013 Dynare Team +% Copyright (C) 2012-2014 Dynare Team % % This file is part of Dynare. % @@ -39,6 +39,24 @@ function A = mrdivide(B,C) % --*-- Unitary tests --*-- % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see . + +if isnumeric(B) && (isscalar(B) || isvector(B)) + if ~isdseries(C) + error('dseries::mrdivide: Second input argument must be a dseries object!') + end + A = C; + A.data = bsxfun(@rdivide,B,C.data); + return; +end + +if isnumeric(C) && (isscalar(C) || isvector(C)) + if ~isdseries(B) + error('dseries::mrdivide: First input argument must be a dseries object!') + end + A = B; + A.data = bsxfun(@rdivide,B.data,C); + return +end if isdseries(B) && isdseries(C) % Element by element divisions of two dseries object @@ -75,36 +93,6 @@ if isdseries(B) && isdseries(C) A.tex(i) = {['(' B.tex{idB(i)} '/' C.tex{idC(i)} ')']}; end A.data = bsxfun(@rdivide,B.data,C.data); -elseif isnumeric(C) && isreal(C) && isequal(length(C),1) && isdseries(B) - % division of a dseries object by a real scalar. - A = dseries(); - A.freq = B.freq; - A.dates = B.dates; - A.init = B.init; - A.nobs = B.nobs; - A.vobs = B.vobs; - A.name = cell(A.vobs,1); - A.tex = cell(A.vobs,1); - for i=1:A.vobs - A.name(i) = {['divide(' B.name{i} ',' num2str(C) ')']}; - A.tex(i) = {['(' B.tex{i} '/' num2str(C) ')']}; - end - A.data = B.data/C; -elseif isnumeric(B) && isreal(B) && isequal(length(B),1) && isdseries(C) - % division of a real scalar by a dseries object. - A = dseries(); - A.freq = C.freq; - A.dates = C.dates; - A.init = C.init; - A.nobs = C.nobs; - A.vobs = C.vobs; - A.name = cell(A.vobs,1); - A.tex = cell(A.vobs,1); - for i=1:A.vobs - A.name(i) = {['divide(' num2str(B) ',' C.name{i} ')']}; - A.tex(i) = {['(' num2str(B) '/' C.tex{i} ')']}; - end - A.data = B./C.data; else error() end diff --git a/matlab/@dseries/mtimes.m b/matlab/@dseries/mtimes.m index 7308388f9..79f2019c2 100644 --- a/matlab/@dseries/mtimes.m +++ b/matlab/@dseries/mtimes.m @@ -23,7 +23,7 @@ function A = mtimes(B,C) % --*-- Unitary tests --*-- %! @end deftypefn %@eod: -% Copyright (C) 2012-2013 Dynare Team +% Copyright (C) 2012-2014 Dynare Team % % This file is part of Dynare. % @@ -40,6 +40,24 @@ function A = mtimes(B,C) % --*-- Unitary tests --*-- % You should have received a copy of the GNU General Public License % along with Dynare. If not, see . +if isnumeric(B) && (isscalar(B) || isvector(B)) + if ~isdseries(C) + error('dseries::mtimes: Second input argument must be a dseries object!') + end + A = C; + A.data = bsxfun(@times,C.data,B); + return; +end + +if isnumeric(C) && (isscalar(C) || isvector(C)) + if ~isdseries(B) + error('dseries::mtimes: First input argument must be a dseries object!') + end + A = B; + A.data = bsxfun(@times,B.data,C); + return +end + if isdseries(B) && isdseries(C) % Element by element multiplication of two dseries object if ~isequal(B.vobs,C.vobs) && ~(isequal(B.vobs,1) || isequal(C.vobs,1)) @@ -75,36 +93,6 @@ if isdseries(B) && isdseries(C) A.tex(i) = {['(' B.tex{idB(i)} '*' C.tex{idC(i)} ')']}; end A.data = bsxfun(@times,B.data,C.data); -elseif isnumeric(C) && isreal(C) && isequal(length(C),1) && isdseries(B) - % Multiplication of a dseries object by a real scalar. - A = dseries(); - A.freq = B.freq; - A.init = B.init; - A.dates = B.dates; - A.nobs = B.nobs; - A.vobs = B.vobs; - A.name = cell(A.vobs,1); - A.tex = cell(A.vobs,1); - for i=1:A.vobs - A.name(i) = {['multiply(' B.name{i} ',' num2str(C) ')']}; - A.tex(i) = {['(' B.tex{i} '*' num2str(C) ')']}; - end - A.data = B.data*C; -elseif isnumeric(B) && isreal(B) && isequal(length(B),1) && isdseries(C) - % Multiplication of a dseries object by a real scalar. - A = dseries(); - A.freq = C.freq; - A.init = C.init; - A.dates = C.dates; - A.nobs = C.nobs; - A.vobs = C.vobs; - A.name = cell(A.vobs,1); - A.tex = cell(A.vobs,1); - for i=1:A.vobs - A.name(i) = {['multiply(' num2str(B) ',' C.name{i} ')']}; - A.tex(i) = {['(' num2str(B) '*' C.tex{i} ')']}; - end - A.data = C.data*B; else error() end @@ -157,7 +145,6 @@ end %$ t(2) = dyn_assert(ts2.vobs,2); %$ t(3) = dyn_assert(ts2.nobs,10); %$ t(4) = dyn_assert(ts2.data,A*B,1e-15); -%$ t(5) = dyn_assert(ts2.name,{['multiply(A1,' num2str(pi) ')'];['multiply(A2,' num2str(pi) ')']}); %$ end %$ T = all(t); %@eof:2 @@ -183,7 +170,31 @@ end %$ t(2) = dyn_assert(ts2.vobs,2); %$ t(3) = dyn_assert(ts2.nobs,10); %$ t(4) = dyn_assert(ts2.data,A*B,1e-15); -%$ t(5) = dyn_assert(ts2.name,{['multiply(' num2str(pi) ',A1)'];['multiply(' num2str(pi) ',A2)']}); %$ end %$ T = all(t); %@eof:3 + +%@test:4 +%$ % Define a datasets. +%$ A = rand(10,2); B = A(1,:); +%$ +%$ % Define names +%$ A_name = {'A1';'A2'}; +%$ +%$ +%$ % Instantiate a time series object. +%$ try +%$ ts1 = dseries(A,[],A_name,[]); +%$ ts2 = B*ts1; +%$ t = 1; +%$ catch +%$ t = 0; +%$ end +%$ +%$ if t(1) +%$ t(2) = dyn_assert(ts2.vobs,2); +%$ t(3) = dyn_assert(ts2.nobs,10); +%$ t(4) = dyn_assert(ts2.data,bsxfun(@times,A,B),1e-15); +%$ end +%$ T = all(t); +%@eof:4 diff --git a/matlab/@dseries/plus.m b/matlab/@dseries/plus.m index 5f74c897a..b9d20a798 100644 --- a/matlab/@dseries/plus.m +++ b/matlab/@dseries/plus.m @@ -23,7 +23,7 @@ function A = plus(B,C) % --*-- Unitary tests --*-- %! @end deftypefn %@eod: -% Copyright (C) 2011-2013 Dynare Team +% Copyright (C) 2011-2014 Dynare Team % % This file is part of Dynare. % @@ -40,37 +40,21 @@ function A = plus(B,C) % --*-- Unitary tests --*-- % You should have received a copy of the GNU General Public License % along with Dynare. If not, see . -if isnumeric(B) && isscalar(B) +if isnumeric(B) && (isscalar(B) || isvector(B)) if ~isdseries(C) error('dseries::plus: Second input argument must be a dseries object!') end - b(1:size(C)) = B; - BB = dseries(b, C.dates(1)); - BB.freq = C.freq; - BB.dates = C.dates; - BB.nobs = C.nobs; - BB.vobs = C.vobs; - BB.name = cell(BB.vobs,1); - BB.tex = cell(BB.vobs,1); - BB.name(1) = {num2str(B)}; - A = BB + C; + A = C; + A.data = bsxfun(@plus,C.data,B); return; end -if isnumeric(C) && isscalar(C) +if isnumeric(C) && (isscalar(C) || isvector(C)) if ~isdseries(B) error('dseries::plus: First input argument must be a dseries object!') end - c(1:size(C)) = C; - CC = dseries(C, B.dates(1)); - CC.freq = B.freq; - CC.dates = B.dates; - CC.nobs = B.nobs; - CC.vobs = B.vobs; - CC.name = cell(CC.vobs,1); - CC.tex = cell(CC.vobs,1); - CC.name(1) = {num2str(C)}; - A = B + CC; + A = B; + A.data = bsxfun(@plus,B.data,C); return end @@ -254,4 +238,54 @@ A.dates = A.init:A.init+(A.nobs-1); %$ end %$ %$ T = all(t); -%@eof:5 \ No newline at end of file +%@eof:5 + +%@test:6 +%$ t = zeros(8,1); +%$ +%$ try +%$ ts = dseries(transpose(1:5),'1950q1',{'Output'}, {'Y_t'}); +%$ us = dseries(transpose(1:7),'1950q1',{'Consumption'}, {'C_t'}); +%$ vs = ts+us('1950q1').data; +%$ t(1) = 1; +%$ catch +%$ t = 0; +%$ end +%$ +%$ if length(t)>1 +%$ t(2) = dyn_assert(ts.freq,4); +%$ t(3) = dyn_assert(us.freq,4); +%$ t(4) = dyn_assert(ts.init.time,[1950, 1]); +%$ t(5) = dyn_assert(us.init.time,[1950, 1]); +%$ t(6) = dyn_assert(vs.init.time,[1950, 1]); +%$ t(7) = dyn_assert(vs.nobs,5); +%$ t(8) = dyn_assert(vs.data,ts.data+1); +%$ end +%$ +%$ T = all(t); +%@eof:6 + +%@test:7 +%$ t = zeros(8,1); +%$ +%$ try +%$ ts = dseries([transpose(1:5), transpose(1:5)],'1950q1'); +%$ us = dseries([transpose(1:7),2*transpose(1:7)],'1950q1'); +%$ vs = ts+us('1950q1').data; +%$ t(1) = 1; +%$ catch +%$ t = 0; +%$ end +%$ +%$ if length(t)>1 +%$ t(2) = dyn_assert(ts.freq,4); +%$ t(3) = dyn_assert(us.freq,4); +%$ t(4) = dyn_assert(ts.init.time,[1950, 1]); +%$ t(5) = dyn_assert(us.init.time,[1950, 1]); +%$ t(6) = dyn_assert(vs.init.time,[1950, 1]); +%$ t(7) = dyn_assert(vs.nobs,5); +%$ t(8) = dyn_assert(vs.data,bsxfun(@plus,ts.data,[1, 2])); +%$ end +%$ +%$ T = all(t); +%@eof:7 \ No newline at end of file