Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 81cd2ea8 authored by hhakim's avatar hhakim
Browse files

Update matfaust LazyLinearOp.

- Add is_meth and refactor check_meth.
- Fix ctranspose.
- Fix mtimes: handling scalar mul and don't create a LazyLinearOp if multiplying a dense matrix or a vector (evaluate the calculation).
- Fix full: if the result of evaluation is not a dense matrix, call full.
- Handle arbiratry number of input arguments in cat, horzcat and vertcat.
parent ed1ad836
No related branches found
No related tags found
No related merge requests found
...@@ -10,10 +10,10 @@ ...@@ -10,10 +10,10 @@
% ====================================================================== % ======================================================================
classdef LazyLinearOp classdef LazyLinearOp
properties (SetAccess = private, Hidden = true) properties (SetAccess = private, Hidden = true)
lambda_stack lambda_stack;
root_obj root_obj;
shape shape;
class % reserved but not used class; % reserved but not used
end end
methods methods
function L = LazyLinearOp(init_lambda, shape, root_obj) function L = LazyLinearOp(init_lambda, shape, root_obj)
...@@ -24,12 +24,15 @@ classdef LazyLinearOp ...@@ -24,12 +24,15 @@ classdef LazyLinearOp
end end
function check_meth(obj, meth) function check_meth(obj, meth)
b = any(ismember(methods(obj), meth)); if ~ is_meth(obj, meth)
if ~ b
error(meth+' is not supported by the rootobject of this LazyLinearOp') error(meth+' is not supported by the rootobject of this LazyLinearOp')
end end
end end
function b = is_meth(obj, meth)
b = any(ismember(methods(obj), meth));
end
function s = size(L, varargin) function s = size(L, varargin)
if length(varargin) == 0 if length(varargin) == 0
s = L.shape; s = L.shape;
...@@ -49,7 +52,7 @@ classdef LazyLinearOp ...@@ -49,7 +52,7 @@ classdef LazyLinearOp
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'ctranspose'); check_meth(L, 'ctranspose');
Ls = size(L); Ls = size(L);
LT = LazyLinearOp(@() ctranspose(L.lambda_stack()), [Ls(2), Ls(1)], L.root_obj); LCT = LazyLinearOp(@() ctranspose(L.lambda_stack()), [Ls(2), Ls(1)], L.root_obj);
end end
function LC = conj(L) function LC = conj(L)
...@@ -61,20 +64,20 @@ classdef LazyLinearOp ...@@ -61,20 +64,20 @@ classdef LazyLinearOp
function Lp = plus(L, op) function Lp = plus(L, op)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'plus') check_meth(L, 'plus');
if ~ all(size(op) == [1, 1]) && ~ all(size(L) == size(op)) if ~ all(size(op) == [1, 1]) && ~ all(size(L) == size(op))
error('Dimensions must agree') error('Dimensions must agree')
end end
Lp = LazyLinearOp(@() L.lambda_stack() + LazyLinearOp.eval_if_lazy(op), size(L), L.root_obj); Lp = LazyLinearOp(@() L.lambda_stack() + LazyLinearOp.eval_if_lazy(op), size(L), L.root_obj);
end end
function LUP = uplus(L) function LUP = uplus(L)
LUP = L; LUP = L;
end end
function Lm = minus(L, op) function Lm = minus(L, op)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'minus') check_meth(L, 'minus');
if ~ all(size(op) == [1, 1]) && ~ all(size(L) == size(op)) if ~ all(size(op) == [1, 1]) && ~ all(size(L) == size(op))
error('Dimensions must agree') error('Dimensions must agree')
end end
...@@ -87,7 +90,11 @@ classdef LazyLinearOp ...@@ -87,7 +90,11 @@ classdef LazyLinearOp
function Lm = mtimes(L, op) function Lm = mtimes(L, op)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'mtimes') if isscalar(L) && LazyLinearOp.isLazyLinearOp(op)
Lm = mtimes(op, L);
return;
end
check_meth(L, 'mtimes');
op_is_scalar = all(size(op) == [1, 1]); op_is_scalar = all(size(op) == [1, 1]);
if ~ op_is_scalar && ~ all(size(L, 2) == size(op, 1)) if ~ op_is_scalar && ~ all(size(L, 2) == size(op, 1))
error('Dimensions must agree') error('Dimensions must agree')
...@@ -97,7 +104,12 @@ classdef LazyLinearOp ...@@ -97,7 +104,12 @@ classdef LazyLinearOp
else else
new_size = [size(L, 1), size(op, 2)]; new_size = [size(L, 1), size(op, 2)];
end end
Lm = LazyLinearOp(@() L.lambda_stack() * LazyLinearOp.eval_if_lazy(op), new_size, L.root_obj); if ~ LazyLinearOp.isLazyLinearOp(op) && ismatrix(op) && isnumeric(op) && ~ issparse(op) && any(size(op) ~= [1, 1])
% op is a dense matrix that is not limited to one element
Lm = eval(L) * op;
else
Lm = LazyLinearOp(@() L.lambda_stack() * LazyLinearOp.eval_if_lazy(op), new_size, L.root_obj);
end
end end
function Lm = mrdivide(L, s) function Lm = mrdivide(L, s)
...@@ -109,12 +121,17 @@ classdef LazyLinearOp ...@@ -109,12 +121,17 @@ classdef LazyLinearOp
function D = full(L) function D = full(L)
D = eval(L); D = eval(L);
if is_meth(L, 'full');
D = full(D);
else
error('full is not available on the result of eval')
end
end end
function SUB = subsref(L, S) function SUB = subsref(L, S)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'subsref') check_meth(L, 'subsref');
if (~isfield(S,'type')) | (~isfield(S,'subs')) if (~isfield(S,'type')) | (~isfield(S,'subs'))
error(' subsref invalid structure S missing field type or subs'); error(' subsref invalid structure S missing field type or subs');
...@@ -192,42 +209,49 @@ classdef LazyLinearOp ...@@ -192,42 +209,49 @@ classdef LazyLinearOp
SUB = LazyLinearOp(@() subsref(L.lambda_stack(), S) , new_shape, L.root_obj); SUB = LazyLinearOp(@() subsref(L.lambda_stack(), S) , new_shape, L.root_obj);
end end
function LH = horzcat(L, O) function LH = horzcat(varargin)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'horzcat') check_meth(varargin{1}, 'horzcat');
LH = cat(2, L, O) LH = cat(2, varargin{1}, varargin{2:end});
end end
function LV = vertcat(L, O) function LV = vertcat(varargin)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'vertcat') check_meth(varargin{1}, 'vertcat');
LV = cat(1, L, O) LV = cat(1, varargin{1}, varargin{2:end});
end end
function LC = cat(dim, L, O) function LC = cat(varargin)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
if dim == 1 dim = varargin{1};
odim = 2; L = varargin{2};
new_size = [size(L, 1) + size(O, 1), size(L, 2)]; check_meth(L, 'cat');
elseif dim == 2 for i=3:nargin
odim = 1; O = varargin{i};
new_size = [size(L, 1), size(L, 2) + size(O, 2)]; if dim == 1
end odim = 2;
if ~ all(size(L, odim) == size(O, odim)) new_size = [size(L, 1) + size(O, 1), size(L, 2)];
error('Dimensions must agree') elseif dim == 2
odim = 1;
new_size = [size(L, 1), size(L, 2) + size(O, 2)];
end
if ~ all(size(L, odim) == size(O, odim))
error('Dimensions must agree')
end
LC = LazyLinearOp(@() cat(dim, L.lambda_stack(), LazyLinearOp.eval_if_lazy(O)), new_size, L.root_obj);
L = LC;
end end
LC = LazyLinearOp(@() cat(dim, L.lambda_stack(), LazyLinearOp.eval_if_lazy(O)), new_size, L.root_obj);
end end
function LR = real(L) function LR = real(L)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'real') check_meth(L, 'real');
LR = LazyLinearOp(@() real(L.lambda_stack()) , L.shape, L.root_obj); LR = LazyLinearOp(@() real(L.lambda_stack()) , L.shape, L.root_obj);
end end
function LI = imag(L) function LI = imag(L)
import matfaust.lazylinop.LazyLinearOp import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'real') check_meth(L, 'real');
LI = LazyLinearOp(@() imag(L.lambda_stack()) , L.shape, L.root_obj); LI = LazyLinearOp(@() imag(L.lambda_stack()) , L.shape, L.root_obj);
end end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment