classdef MatrixObj
%MATRIXOBJ - a class for on-the-fly creation of customized matrix objects.
%
% For full details and examples see the UserGuide.
%
% Objects of the MatrixObj class (and its subclass DataObj) are capable of
% behaving as matrices, but with math operators (+,-,*,\,.*,<,>,etc...) that
% can be defined/redefined in any Mfile context, or even at the command line. This
% removes the restriction of writing a dedicated classdef file or class directory
% for every new matrix-type object that a user might wish to create.
%
% The class works by storing function handles to the various matrix
% operator functions like plus, minus, mtimes, mldivide, etc... in a property
% of MatrixObj called Ops, which is a structure variable. Hence, one can set
% the matrix operators as desired simply by setting the fields of Ops to an
% appropriate function handle.
%
%
%DETAILS OF USAGE:
%
% The following constructs a default MatrixObj object M,
%
% M=MatrixObj;
%
% This is probably the simplest way to construct the object.
% The two main properties of MatrixObj are "Params" and "Ops". The
% properties can be populated with non-default values by dot-indexing
% assignment statements.
%
% M.Params=...
% M.Ops.methodname1=...
%
% Another construction syntax is
%
% M=MatrixObj(Params,Ops)
%
% which can be used to set these properties directly.
%
% The Params property can be any MATLAB variable - numeric, struct, or
% otherwise - and is meant for holding object parameters of any kind.
% Its default/initial value is [].
%
% The Ops property is a structure whose field names include all of the math
% operator functions, plus a few more such as as sum(), inv(), conj(), size(),
% and display:
%
% and horzcat mpower power sum
% colon inv mrdivide rdivide times
% ctranspose ldivide mtimes size transpose
% end le ne subsasgn uminus
% eq lt not subsindex uplus
% ge minus or subsref vertcat
% gt mldivide plus display conj
%
% By assigning appropriate function handles to these fields, any/all of the
% corresponding class methods can be implemented on-the-fly. The fields of
% Ops also default to [].
%
% Although M.Ops is in most ways manipulable as a structure using dot-indexing
% syntax, any attempt to assign a field to Ops which is not in methods(MatrixObj)
% will result in an error. However, advanced users, if they wish, can add more
% methods to the MatrixObj classdef, and these methods will then automatically
% join the list of manipulable fields of Ops.
%
%
%Copyright 2010-01-22, Matt Jacobson, Xoran Technologies, http://www.xorantech.com
%
%based on the "Fatrix" class by Jeff Fessler, Copyright 2004-6-29, The University of Michigan
%properties (Access=protected, Hidden=false)
properties (Constant=true, Hidden=true);
OpsTemplate=MatrixObj.InitOpsTemplate;
end
methods (Access=protected, Hidden=true);
function Name=TemplateName(obj)
Name='OpsTemplate';
end
end
properties (Access=private)
Params;
end
properties
Ops;
Trans;
end
methods
function obj=MatrixObj(varargin)
if nargin>=1
obj.Params=varargin{1};
end
if nargin>1,
if isstruct(varargin{2})
f=fieldnames(varargin{2});
c=struct2cell(varargin{2});
Pairs=[f(:), c(:)].';
elseif mod(length(varargin),2)
error 'Methods must be specified either as struct or string/value pairs'
else
Pairs=varargin;
end
obj.Ops=struct(Pairs{:});
else
obj.Ops=struct(obj.OpsTemplate{:});
end
end
function obj=set.Ops(obj,Ops)
if isempty(Ops),
error 'Setting Ops property to empty not allowed'
end
template=obj.(obj.TemplateName);
%template=obj.OpsTemplate;
f=fieldnames(Ops);
[map,loc]=ismember(f,template(1,:));
if map,
template(2,loc)=struct2cell(Ops);
obj.Ops=struct(template{:});
else
BadFields=f(~map),
error(['Possible spelling mistake. The above fields assigned to MatrixObj.Ops do not correspond to existing methods of the MatrixObj class.'])
end
end
function obj=set.Trans(obj,Ops)
if isempty(Ops), obj.Trans=[]; return; end
template=obj.(obj.TemplateName);
f=fieldnames(Ops);
[map,loc]=ismember(f,template(1,:));
if map,
template(2,loc)=struct2cell(Ops);
obj.Trans=struct(template{:});
else
BadFields=f(~map),
error(['Possible spelling mistake. The above fields assigned to MatrixObj.Trans do not correspond to existing methods of the MatrixObj class.'])
end
end
end
methods (Static, Hidden, Access=protected)
function template=InitOpsTemplate
m=methods('MatrixObj');
[idx,loc]=ismember({'MatrixObj','get','set','loadobj'},m);
m(loc)=[];
template=[m(:).' ; repmat({[]},1,length(m)) ];
end
end
end