Mentions légales du service

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

Implement matfaust LazyLinearOpKron and matfaust.lazylinop.kron.

parent 0abe924e
No related branches found
No related tags found
No related merge requests found
......@@ -10,7 +10,7 @@
%> @warning This code is in a beta status.
% ======================================================================
classdef LazyLinearOp
properties (SetAccess = private, Hidden = true)
properties (SetAccess = protected, Hidden = true)
lambda_stack;
root_obj;
shape;
......@@ -57,7 +57,7 @@ classdef LazyLinearOp
import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'transpose');
Ls = size(L);
LT = LazyLinearOp(@() transpose(L.lambda_stack()), [Ls(2), Ls(1)], L.root_obj);
LT = LazyLinearOp(@() transpose(eval(L)), [Ls(2), Ls(1)], L.root_obj);
end
%=============================================================
......@@ -67,7 +67,7 @@ classdef LazyLinearOp
import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'ctranspose');
Ls = size(L);
LCT = LazyLinearOp(@() ctranspose(L.lambda_stack()), [Ls(2), Ls(1)], L.root_obj);
LCT = LazyLinearOp(@() ctranspose(eval(L)), [Ls(2), Ls(1)], L.root_obj);
end
%=============================================================
......@@ -77,7 +77,7 @@ classdef LazyLinearOp
import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'conj');
Ls = size(L);
LC = LazyLinearOp(@() conj(L.lambda_stack()), Ls, L.root_obj);
LC = LazyLinearOp(@() conj(eval(L)), Ls, L.root_obj);
end
%=============================================================
......@@ -91,7 +91,7 @@ classdef LazyLinearOp
if ~ all(size(op) == [1, 1]) && ~ all(size(L) == size(op))
error('Dimensions must agree')
end
Lp = LazyLinearOp(@() L.lambda_stack() + LazyLinearOp.eval_if_lazy(op), size(L), L.root_obj);
Lp = LazyLinearOp(@() eval(L) + LazyLinearOp.eval_if_lazy(op), size(L), L.root_obj);
end
%=============================================================
......@@ -112,7 +112,7 @@ classdef LazyLinearOp
if ~ all(size(op) == [1, 1]) && ~ all(size(L) == size(op))
error('Dimensions must agree')
end
Lm = LazyLinearOp(@() L.lambda_stack() - LazyLinearOp.eval_if_lazy(op), size(L), L.root_obj);
Lm = LazyLinearOp(@() eval(L) - LazyLinearOp.eval_if_lazy(op), size(L), L.root_obj);
end
%=============================================================
......@@ -185,7 +185,7 @@ classdef LazyLinearOp
% 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);
Lm = LazyLinearOp(@() eval(L) * LazyLinearOp.eval_if_lazy(op), new_size, L.root_obj);
end
end
......@@ -197,7 +197,7 @@ classdef LazyLinearOp
%> @b See @b also: mrdivide matlab built-in.
%=============================================================
function Lm = mrdivide(L, op)
Lm = LazyLinearOp(@() mrdivide(L.lambda_stack() * LazyLinearOp.eval_if_lazy(op), new_size, L.root_obj));
Lm = LazyLinearOp(@() mrdivide(eval(L) * LazyLinearOp.eval_if_lazy(op), new_size, L.root_obj));
end
%=============================================================
......@@ -292,7 +292,7 @@ classdef LazyLinearOp
end
end
SUB = LazyLinearOp(@() subsref(L.lambda_stack(), S) , new_shape, L.root_obj);
SUB = LazyLinearOp(@() subsref(eval(L), S) , new_shape, L.root_obj);
end
%=============================================================
......@@ -340,7 +340,7 @@ classdef LazyLinearOp
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);
LC = LazyLinearOp(@() cat(dim, eval(L), LazyLinearOp.eval_if_lazy(O)), new_size, L.root_obj);
L = LC;
end
end
......@@ -353,7 +353,7 @@ classdef LazyLinearOp
function LR = real(L)
import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'real');
LR = LazyLinearOp(@() real(L.lambda_stack()) , L.shape, L.root_obj);
LR = LazyLinearOp(@() real(eval(L)) , L.shape, L.root_obj);
end
%=============================================================
......@@ -364,7 +364,7 @@ classdef LazyLinearOp
function LI = imag(L)
import matfaust.lazylinop.LazyLinearOp
check_meth(L, 'real');
LI = LazyLinearOp(@() imag(L.lambda_stack()) , L.shape, L.root_obj);
LI = LazyLinearOp(@() imag(eval(L)) , L.shape, L.root_obj);
end
end
......@@ -410,7 +410,7 @@ classdef LazyLinearOp
B = isa(obj, 'matfaust.lazylinop.LazyLinearOp');
end
end
methods(Static, Access = private)
methods(Static, Access = protected)
function O = eval_if_lazy(obj)
import matfaust.lazylinop.LazyLinearOp
if LazyLinearOp.isLazyLinearOp(obj)
......@@ -420,7 +420,7 @@ classdef LazyLinearOp
end
end
end
methods(Access = private)
methods(Access = protected)
function check_meth(obj, meth)
if ~ is_meth(obj, meth)
error(meth+' is not supported by the root object of this LazyLinearOp')
......
classdef LazyLinearOpKron < matfaust.lazylinop.LazyLinearOp
properties (SetAccess = private, Hidden = true)
A;
B;
end
methods
function LK = LazyLinearOpKron(A, B)
shape = [size(A, 1) * size(B, 1), size(A, 2) * size(B, 2)];
LK = LK@matfaust.lazylinop.LazyLinearOp(@() A, shape, A);
LK.A = A;
LK.B = B;
end
function CLK = conj(LK)
import matfaust.lazylinop.*
CLK = LazyLinearOpKron(conj(asLazyLinearOp(LK.A)), conj(asLazyLinearOp(LK.B)));
end
function CLK = transpose(LK)
import matfaust.lazylinop.*
CLK = LazyLinearOpKron(transpose(asLazyLinearOp(LK.A)), transpose(asLazyLinearOp((LK.B))));
end
function CTLK = ctranspose(LK)
import matfaust.lazylinop.*
CTLK = LazyLinearOpKron(ctranspose(asLazyLinearOp(LK.A)), ctranspose(asLazyLinearOp((LK.B))));
end
function LmK = mtimes(LK, op)
import matfaust.lazylinop.LazyLinearOp
if isscalar(LK) && LazyLinearOp.isLazyLinearOp(op)
LmK = mtimes(op, LK);
return;
end
check_meth(LK, 'mtimes');
op_is_scalar = all(size(op) == [1, 1]);
if ~ op_is_scalar && ~ all(size(LK, 2) == size(op, 1))
error('Dimensions must agree')
end
if op_is_scalar
new_size = LK.shape;
else
new_size = [size(LK, 1), size(op, 2)];
end
if ~ LazyLinearOp.isLazyLinearOp(op) && ismatrix(op) && isnumeric(op) && ~ issparse(op) && any(size(op) ~= [1, 1]) && any(ismember(methods(op), 'reshape')) && any(ismember(methods(op), 'mtimes')) %&& any(ismember(methods(op), 'subsref'))
% op is a dense matrix that is not limited to one element
LmK = zeros(new_size);
A = LK.A;
B = LK.B;
for j=1:new_size(2)
op_mat = reshape(op(:, j), [size(B, 2), size(A, 2)]);
LmK(:, j) = reshape(LazyLinearOp.eval_if_lazy(B) * op_mat * transpose(LazyLinearOp.eval_if_lazy(A)), [new_size(1), 1]);
end
else
LmK = LazyLinearOp(@() LK.eval() * LazyLinearOp.eval_if_lazy(op), new_size, LK.root_obj);
end
end
function E = eval(LK)
A = LK.A;
B = LK.B;
if any(ismember(methods(A), 'full'))
A = full(A);
end
if any(ismember(methods(B), 'full'))
B = full(B);
end
E = kron(A, B);
end
end
end
%=============================================================
%> @brief Creates a LazyLinearOp based on the object obj which must be of a linear operator compatible type.
%>
%> @note obj must support operations and attributes defined in this class.
%> @note obj must support operations and attributes defined in the LazyLinearOp class.
%> Any operation not supported would raise an exception at the evaluation time.
%> @param obj: the root object on which the LazyLinearOp is based (it could
%> be a dense matrix, a sparse matrix, a Faust object or almost any
......
function KL = kron(A, B)
import matfaust.lazylinop.LazyLinearOpKron
KL = LazyLinearOpKron(A, B);
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment