Suppose a is defined as the struct below. I tried to find equivalent command to R's dput but errs here. For example, I know that the below must be of the form struct('const',1,'terms',{{struct(),struct()}}) but I don't know what is stored inside the structure without going to check it with commands like here, time-consuming.
So by which command I can see the original command to generate a struct in Matlab?
>> a
a =
const: 1
terms: {[1x1 struct] [1x1 struct]}
Comment
Is it possible for you to switch from using a structure to a class? If so you could make one that mimics the struct, and each time it is modified call stack = dbstack to get the stack - then store the stack along with the change. The command that made the change could then be retrieved automatically later from the line numbers in the stack.
As a follow-up request to this in the comment, here is an example of a class that provides struct functionality and also keeps a record of its assignments:
classdef utstruct
properties (SetAccess = private)
modifications
end
properties (Dependent, SetAccess = private)
myStruct
end
properties (Access = private)
m_struct
end
methods
function self = utstruct(varargin)
if nargin > 0
self.m_struct = builtin('struct', varargin{:});
else
self.m_struct = builtin('struct');
end
% Should update self.modifications here
end
function B = subsref(self, s)
if any(strcmp(s(1).subs, properties(self)))
B = builtin('subsref', self, s);
else
B = subsref(self.m_struct, s);
end
end
function A = subsasgn(self, s, b)
self.m_struct = subsasgn(self.m_struct, s, b);
newMod = builtin('struct');
newMod.type = 'subsasgn';
newMod.modData = {s b};
newMod.stack = dbstack;
self.modifications = [self.modifications; newMod];
A = self;
end
function disp(self)
disp(self.m_struct);
end
function names = fieldnames(self, varargin)
names = fieldnames(self.m_struct, varargin{:});
end
function C = cat(self, dim, varargin)
uts = cellfun(#(x)isa(x, 'utstruct'), varargin);
varargin{uts} = cellfun(#(x)x.m_struct, varargin(uts));
varargin = [{self.m_struct} varargin];
self.m_struct = cat(dim, varargin{:});
% Should update self.modifications here
C = self;
end
function C = horzcat(self, varargin)
C = self.cat(1, varargin{:});
end
function C = vertcat(self, varargin)
C = self.cat(2, varargin{:});
end
function value = get.myStruct(self)
value = self.m_struct;
end
end
end
You should add some code to update the modifications array when initialisation / concatenation operations occur.
The subsref and subsasgn overrides are the key points here that make it behave like a struct (by deferring all their activity to an actual struct), but other overrides like fieldnames and disp do the same thing. In subsasgn a record of all the assignments to the struct is kept, along with the stack that generated the assignment.
Note: for this to be fully compatible with the built-in struct you probably should override a few more methods, but this should be enough to get you started. See Subclassing MATLAB Built-In Types.
Edit: I made the example a bit more robust. It's now a value class - as it should be - and works with concatenation.
Edit: You can avoid using a find-and-replace to refactor existing struct(...) calls by redefining the function struct:
function s = struct(varargin)
% STRUCT Overrides default struct function to provide unit-testable structs
%
% Set global variable unitTestStructEnabled to true to enable this
% function.
%
global unitTestStructEnabled;
if isempty(unitTestStructEnabled)
unitTestStructEnabled = false;
end
if unitTestStructEnabled
s = utstruct(varargin{:});
else
s = builtin('struct', varargin{:});
end
You probably don't want that hanging around on your path the whole time, as you will get a warning when you first create a struct (you could turn it off, but that might hide other problems), so you should probably put it in a folder that's not normally in the path, and temporarily add it to the path for unit testing (addpath / rmpath).
Here's the skeleton of a dumpvar function, i.e. something along the idea of tashuhka
function str = dumpvar(a)
switch class(a)
case 'double'
if isempty(a)
str = '[]'; % bug when "a" is multidimensional and empty
elseif isscalar(a)
str = num2str(a);
elseif isrow(a)
str = strcat('[', dumpvar(a(1)));
for k = 2:size(a,2)
str = strcat(str,',',dumpvar(a(k)));
end;
str = strcat(str, ']');
elseif numel(size(a)) == 2
str = strcat('[', dumpvar(a(1,:)));
for k = 2:size(a,1)
str = strcat(str,';',dumpvar(a(k,:)));
end;
str = strcat(str, ']');
else
do_what_i_mean();
end;
case 'struct'
fn = fieldnames(a);
if isempty(fn)
str = 'struct()';
elseif isscalar(a)
str = strcat('struct(''', fn{1},''',', dumpvar(a.(fn{1})));
for k=2:numel(fn)
str = strcat(str,',''',fn{k},''',', dumpvar(a.(fn{k})));
end;
str = strcat(str, ')');
else
do_what_i_mean();
end;
otherwise
do_what_i_mean();
end;
function do_what_i_mean()
throwAsCaller(MException(...
'beingLazy:onSaturday:Fault', ...
'Storage of class "%s" and arity %d is not implemented yet. Would you?', ...
class(a), numel(size(a))...
));
end;
end
Save it in a dumpvar.m file somewhere in Matlab's path, then test it with this code snippet:
a = struct(...
'field1', 1,...
'field2', [],...
'field10', struct(...
'field3', [1 2;2 3;3 4],...
'field4', struct()...
)...
);
disp(dumpvar(a));
eval(sprintf('b=%s;', dumpvar(a)));
Please note that this function is still in a toy stage: it's anywhere near exhaustive (lacks treatment of struct arrays, cells, char, logical and other fundamental types, not to mention user-defined classes --- hehe, those would be a pickle) and it is meant to be completed by you with whatever functionality you need.
Although it does not answer completely your question, vsize() by Urs can help you:
% Create some complicated variable
v(1).a{1}=sparse(magic(3)+2i*magic(3));
v(2).a{2}={struct('FA',{'a','bb'},'FB',{magic(5),{}})};
v(2).b{2}=#(x) sind(x);
% Dissect
P = vsize(v);
% -------------------------
% 1998 1998 B * v = 2:1x2:struct.(2)
% CELL ----- 360 B v[].a = 2:1x1:cell
% 1750 248 B - v[].a{} = 2:3x3:double.sparse.complex
% CELL ----- 1014 B v[].a = 2:1x2:cell
% 1750 0 B - v[].a{} = 2:0x0:double
% CELL ----- 894 B v[].a{} = 2:1x1:cell
% STRUCT --- 782 B v[].a{}{} = 2:1x2:struct.(2)
% 1748 2 B - v[].a{}{}[].FA = 2:1x1:char
% 1744 4 B - v[].a{}{}[].FA = 2:1x2:char
% 1544 200 B - v[].a{}{}[].FB = 2:5x5:double
% CELL ----- 0 B v[].a{}{}[].FB = 2:0x0:cell
% 1544 0 B - v[].b = 2:0x0:double
% CELL ----- 152 B v[].b = 2:1x2:cell
% 1544 0 B - v[].b{} = 2:0x0:double
% 1512 32 B - v[].b{} = 2:1x1:function_handle
Related
I am programming commutative hypercomplex number class.
First of all: If that already exist, please tell. I have not found.
PS: Quaternion exists but are not commutative.
I am trying to reproduce all that Matlab can do with real and complex, but with hypercomplex. The solution that I am working on is to define a class. If a more smart method may be used, please tell.
Many codes with complex numbers exist, the idea is to overload smartly to make working all existing program with Hypercomplex. This work might be used by many users.
please see at the end of the post the main maths principle found in Ablamowicz1996 _ Clifford Algebras with Numeric and Symbolic Computations
My Hypercomplex class works for basic operation: I have overloaded the mtimes(a,b) = a*b operation.
For instance, I can do:
A = MyClass(1);
B = MyClass(2);
A*B; % ->that works
As a main problem, for instance in 2D, I would like to be able to use
[A B C].*[D ; E]
while using the element-wise behavior of Matlab, and for any dimension , and with my definition of *. For instance, while dealing with matrices of compatible size but not identical:
A = [1 2 3]; B = [1;2]
Matlab gives
A.*B
ans =
1 2 3
2 4 6
That works also for N dimension when compatible.
How can I overload times(a,b) = a.*b , power, rdivide.. in order to have the element-wise behavior of Matlab?
Here is my Class
classdef Hypercomplex < handle
properties (SetAccess = public, GetAccess = public)
A
end
properties (SetAccess = private, GetAccess = private)
eps,nu,e1,e2
end
methods
function s = Hypercomplex(Z) %% Conctruc
% Z might be real, complex or hypercomplex
if isa(Z,'Hypercomplex') % is HyperComplex
s = Z;
elseif ~isreal(Z) && length(Z) == 1 % is Complex
s = Hypercomplex([real(Z) imag(Z) 0 0]);
elseif isreal(Z) && length(Z) < 5
s.A = zeros(1,4);
for ii = 1:length(Z) % is vecteur
s.A(ii) = Z(ii);
end
end
end
function s = epsnu(s)
s.eps = (s.A(1) - s.A(4)) + 1i*(s.A(2)+s.A(3));
s.nu = (s.A(1) + s.A(4)) + 1i*(s.A(2)-s.A(3));
end
function s = e1e2(s)
s.e1 = Hypercomplex([0.5 0 0 -0.5]);
s.e2 = Hypercomplex([0.5 0 0 0.5]);
end
%% Overload
function out = cos(a)
a.epsnu.e1e2;
out = cos(a.eps)*a.e1 + cos(a.nu)*a.e2;
% I might also do for sin exp sqrt ...
end
function out = mtimes(a,b) % '*'
a = Hypercomplex(a).epsnu;
b = Hypercomplex(b).epsnu;
eps12 = 0.5*(a.eps * b.eps);% produit complex
nu12 = 0.5*(a.nu * b.nu );% produit complex
h1 = Hypercomplex([real(eps12) imag(eps12) imag(eps12) -real(eps12)]);
h2 = Hypercomplex([real(nu12) imag(nu12) -imag(nu12) real(nu12) ]);
out = h1+h2;
end
function out = mrdivide(a,b)
a = Hypercomplex(a);
b = Hypercomplex(b);
out = a * b.inverse;
end
function s = inverse(s)
s = Hypercomplex(s).epsnu.e1e2;
s = 1/(s.eps)*s.e1 + 1/(s.nu)*s.e2;
end
function out = plus(a,b)
a = Hypercomplex(a);
b = Hypercomplex(b);
out = Hypercomplex(a.A + b.A);
end
function out = minus(a,b)
a = Hypercomplex(a);
b = Hypercomplex(b);
out = Hypercomplex(a.A - b.A);
end
end
end
Example i^2 = -1 :
>> Ni = Hypercomplex([0 1 0 0]) ;
>> Ni*Ni
Hypercomplex with properties:
A: [-1 0 0 0]
I would think you need to loop over your arrays, and have a special case where, if for one dimension one of the inputs has size 1 and the other doesn't, then the same element for that array is used. A simple way to accomplish this is to index with (i-1)*step + 1, where step is 0 if the array has size 1, and 1 otherwise.
One thing to note is that, in your overloaded method, indexing doesn't use your custom indexing definition (subsref and subsasgn), but the built-in one.
For example, assuming you only allow 2D arrays of your class:
function C = times(A, B)
szA = size(A);
szB = size(B);
if numel(szA)~=2 || numel(szB)~=2
error('Only 2D arrays are supported')
end
szC = max(szA, szB);
stepA = [matchSizes(szA(1), szC(1)), matchSizes(szA(2), szC(2))];
stepB = [matchSizes(szB(1), szC(1)), matchSizes(szB(2), szC(2))];
C = MyClass.empty(szC);
for jj = 1:szC(2)
for ii = 1:szC(1)
C(ii,jj) = A((ii-1)*stepA(1)+1,(jj-1)*stepA(2)+1) * B((ii-1)*stepB(1)+1,(jj-1)*stepB(2)+1);
end
end
% private helper function, keep in the same file
function step = matchSizes(szIn, szOut)
step = 1;
if szIn ~= szOut
if szIn == 1
step = 0;
else
error('Sizes not compatible')
end
end
NOTE: Code not tested.
NOTE2: This is one of the cases where 0-based indexing is more convenient!
If MyClass has a property val to store numeric values I think (hope) that this should be possible (not tested):
function obj = times(A, B)
r = reshape([A.val], size(A)) .* reshape([B.val], size(B));
obj = arrayfun(#MyClass, r);
end
EDIT (because question is edited):
You can follow two ways to implement array of those numbers:
Array of objects
In this method each object just contains a hypercomplex number. It is the way that you have tried. As #CrisLuengo pointed out you can use loops to create the desired result or you can use a combination of vectorization and use of functions like arrayfun and cellfun. You need to know how to work with cell arrays and comma separated list and be familiar with verctorization operations like implicit expansion. Here I implemented plus and epsnu using vectorization and cellfun. They can work with both scalar and object arrays:
function out = plus(a,b)
a = Hypercomplex(a);
b = Hypercomplex(b);
AA = reshape([a.A], [4, size(a)]);
BB = reshape([b.A], [4, size(b)]])
CC = AA + BB;
A1 = reshape()
out = cellfun(#Hypercomplex, num2cell(reshape(CC, 4, []).', 2));
end
function s = epsnu(s)
AA = reshape([s.A], 4, []);
eps = num2cell(AA(1, :) - AA(4, :) + 1i.*(AA(2, :) + AA(3, :)));
nu = num2cell(AA(1, :) + AA(4, :) + 1i.*(AA(2, :) - AA(3, :)));
[s.eps] = eps{:};
[s.nu] = nu{:};
end
Object containing array of numbers
Instead of defining A as a [4 x 1] array you can define each coordinate (x,y,z,et) as a separate property of class each can contain array of numbers. you need to overload the cat operator to concatenate objects. As a result no object array is created but the underlying verctors are concatenated. You need tooverload subsref and subsasgn if you want to simulate element access. I think this method is simpler to implement than the first method.
If I have a value class like this:
classdef MyVal
properties
foo
end
methods
function self = MyVal(varargin)
if nargin > 0
self.foo = varargin{1};
end
end
end
end
and use it in a table:
foo(1) = MyVal(1); foo(2) = MyVal(2);
t = table(foo')
the output is:
t =
2×1 table
Var1
___________
[1×1 MyVal]
[1×1 MyVal]
Is there any method which has to be defined in MyVal (or any property of the table) which allows to change the representation of the value in the table? I do not want to convert the data passed to table since I'd like to retrieve instances of MyVal when I index in the table.
You could create a custom wrapper for table. This is slightly pokey because MATLAB doesn't let you inherit from the table class, but by overloading the subsref and subsasgn operators you can get most of the functionality anyway...
I've included the class at the bottom of this answer since it's a bit long, usage would look like this:
>> foo(1) = MyVal(1); foo(2) = MyVal(2);
>> t = MyTable(foo') % Omitting the ";" calls our overloaded "disp" function
t =
Var1
____
1
2
You can also use this to extract the numeric data (i.e. the foo property alongside other data) by using t.numeric, although I suspect you will need to use table2array on this for use with uitable, as you would with a normal table.
classdef MyTable
properties ( Access = private )
table_
end
properties ( Dependent = true )
numeric
end
methods % Constructor and getter
function obj = MyTable( varargin )
% Store as a normal table internally
obj.table_ = table( varargin{:} );
end
function num = get.numeric( obj )
% By calling obj.numeric, output the table but with MyVal
% objects replaced by their "foo" property.
% This could be passed into a uitable, and is used in disp()
cls = varfun( #(x)isa(x,'MyVal'), obj.table_, 'OutputFormat', 'uniform' );
num = obj.table_;
for ii = find(cls)
num.(num.Properties.VariableNames{ii}) = [num.(num.Properties.VariableNames{ii}).foo].';
end
end
end
methods % Overloaded to emulate table behaviour
function disp( obj )
% Overload the disp function (also called when semi colon is
% omitted) to output the numeric version of the table
disp( obj.numeric );
end
% Overload subsref and subsasgn for table indexing
function varargout = subsref( obj, s )
[varargout{1:nargout}] = builtin( 'subsref', obj.table_, s );
end
function obj = subsasgn( obj, s, varargin )
obj.table_ = builtin( 'subsasgn', obj.table_, s, varargin{:} );
end
% Have to overload size and isa for workspace preview
function sz = size( obj, varargin )
sz = size( obj.table_, varargin{:} );
end
function b = isa( obj, varargin )
% This is only OK to do because we overloaded subsref/subsasgn
b = isa( obj.table_, varargin{:} );
end
end
end
Only a half answer
I couldn't find the way to customise the display of the table of object, but if you can get by by using arrays of object there is a way, described in Customize Object Display for Classes.
For your example, you have to derive your class with: matlab.mixin.CustomDisplay, then override the displayNonScalarObject method:
classdef MyVal < matlab.mixin.CustomDisplay
properties
foo
end
methods
function self = MyVal(varargin)
if nargin > 0
self.foo = varargin{1};
end
end
end
methods (Access = protected)
function displayNonScalarObject(objAry)
dimStr = matlab.mixin.CustomDisplay.convertDimensionsToString(objAry);
cName = matlab.mixin.CustomDisplay.getClassNameForHeader(objAry);
headerStr = [dimStr,' ',cName,' members:'];
header = sprintf('%s\n',headerStr);
disp(header)
for ix = 1:length(objAry)
o = objAry(ix);
% OPTION 1:
% For a class with a sinle property, no need to call the
% big guns, just build your own display:
disp( [num2str(ix) ': foo = ' num2str(o.foo) ] ) ;
% OR OPTION 2: (comment option1 if you use this)
% If your class had multiple properties and you want to
% display several of them, use the MATLAB built-in functions:
% create a structure with the property names you need
% displayed:
% propList = struct('foo',o.foo,'prop2',o.prop2,'prop3',o.prop3);
% Then let MATLAB handle the display
% propgrp = matlab.mixin.util.PropertyGroup(propList);
% matlab.mixin.CustomDisplay.displayPropertyGroups(o,propgrp);
end
end
end
end
Now if you build an array of your class, the display will look like:
>> foo(1) = MyVal(1); foo(2) = MyVal(2);
>> foo
foo =
1x2 MyVal members:
1: foo = 1
2: foo = 2
Of course this is just an example and is highly customizable. Unfortunately, I couldn't find a way to make that work for table objects.
Suppose we have a loop:
for i = 1:1000
A
B
C
end
... and I wish to find out the CPU usage spread.
A, B, C are MatLab statements not functions, so (IIUC) I can't use the profiler.
Also in reality I have a dozen lines to cover.
The obvious long-winded way would be:
s = zeros(50, 1);
t = cputime;
for ...
A
s(1) = s(1) + (cputime-t); t = cputime;
B
s(2) = s(2) + (cputime-t); t = cputime;
:
... which isn't too bad, I suppose.
But can it be improved upon?
I thought of doing:
t = zeros(50, 1);
e(t,0); % reset
for i = 1:1000
A
e(1);
B
e(2);
C
e(3);
end
... with:
function e(t, k)
if k==0
last_cputime = cputime;
return
end
t(k) = t(k) + (cputime-last_cputime);
last_cputime = cputime;
end
But it doesn't see t, so I have to pass that.
Also it doesn't remember last_cputime between invocations, so I need to pass that as well.
So e(last_cputime,t,1)
It's rather ugly. I experimented with using an in-line function:
e = #(k) eval( 't(k) = t(k) + (cputime-last_cputime); cputime = last_cputime;' );
But I couldn't get this working either:
K>> t = zeros(3,1)
t =
0
0
0
K>> eval( 't(1) = 3' )
t =
3
0
0
K>> e = #(k) eval( 't(k) = 3;' )
e =
function_handle with value:
#(k)eval('t(k) = 3;')
K>> e(1)
Attempt to add "t" to a static workspace.
See Variables in Nested and Anonymous Functions.
Error in pi_test>#(k)eval('t(k) = 3;')
I wonder if another option might be:
for i = 1:1000
e('A');
e('B');
e('C');
end
But then how to code up e?
Is there any way to do avoid horrible ugliness-through-duplication?
How about a classdef that handles this?
You can save this as mtime.m
classdef mtime < handle
properties
times
end
properties (Access = private)
t
end
methods
function obj = mtime() %initialize
obj.t=cputime;
obj.times=[];
end
function time(obj)
obj.times(end+1) = cputime-obj.t;
obj.t = cputime;
end
end
end
You can then intialize with T=mtime(); and time your code by calling time(T); After the code is finished the timings can be found in T.times.
I am writing a function and I need some help.
This is my function:
function [varargout] = myfunc(x, y, z, optional)
There are two possible outputs: A and B. By setting the compulsory input variables (x,y,z), you get A. If you also set the optional argument, you should get A and B as well.
So, this is the way I am trying to do it:
if (nargin == 4)
varargout{1} = A;
varargout{2} = B;
else
varargout{1} = A;
end
This is not working... Where am I making the mistake?
Thank you in advance!
I don't see a problem with it. The only problem will come if you attempt:
[a,b] = myfunc(1,2,3)
in which case your function will complain that you're trying to assign to a second variable that hasn't been defined. So you need to have some more input / output checking (e.g. via nargout) and act accordingly. (i.e. either specify a custom error, or return b=[], etc.
PS. I'm assuming your function is defined something like:
function varargout = myfunc(x, y, z, optional)
if (nargin == 4); varargout{1} = 1; varargout{2} = 2;
else varargout{1} = 1;
end
end
You need two outputs with varargout. Try this:
[A,varargout] = myfunc(x, y, z, optional)
and
if (nargin > 3)
varargout{1} = B;
end
There are a couple of issues with this code:
First, you haven't put the keyword "function" before declaring
myfunc.
Second, optional is set as the 4th argument. However, this way you
cannot include more than 4 arguments.
Third, you have to be careful with varargout, since it increases the
number of output argument, but it doesn't change the first one
(which is always equal to one).
I don't know which of the above was your main concern, however, the following code should be working:
function varargout = myfunc2(x, y, z, varargin)
if nargin == 4
varargout{1} = 1; % where A=1 and B = 2
varargout{2} = 2;
else
varargout{1} = 1;
end
end
Please have a look to the attached links for more details about varargin and varargout:
http://uk.mathworks.com/help/matlab/ref/varargin.html
http://uk.mathworks.com/help/matlab/ref/varargout.html
I solved it! I'll post here the solution, it could be useful for others. Thank you all!
function [A, varargout] = myfunc(x, y, z, optional)
A = somefunction(x,y,z)
if nargout == 2 && nargin == 4
i = find(A > optional);
B = somefunction(A,i);
varargout{1} = B;
end
In this way, you have an optional output associated to an optional input variable. It works :)
I have a class in MATLAB that represents an imaginary number. I have a constructor and two data members: real and imag. I am playing with overloading operator in a class and I want to make it work with matrices:
function obj = plus(o1, o2)
if (any(size(o1) ~= size(o2)))
error('dimensions must match');
end
[n,m] = size(o1);
obj(n,m) = mycomplex();
for i=1:n
for j=1:m
obj(i,j).real = o1(i,j).real + o2(i,j).real;
obj(i,j).imag = o1(i,j).imag + o2(i,j).imag;
end
end
end
But I don't want to use for loops. I want to do something like:
[obj.real] = [o1.real] + [o2.real]
But I don't understand why it does not work... the error says:
"Error in + Too many output arguments".
I know that in MATLAB it is good to avoid for loops for speed up... Can someone explain me why this does not work, and the right way to think about vectorization in MATLAB with an example for my function?
Thanks in advance.
EDIT: definition of my complex class:
classdef mycomplex < handle & matlab.mixin.CustomDisplay
properties (Access = public)
real;
imag;
end
methods (Access = public)
function this = mycomplex(varargin)
switch (nargin)
case 0
this.real = 0;
this.imag = 0;
case 1
this.real = varargin{1};
this.imag = 0;
case 2
this.real = varargin{1};
this.imag = varargin{2};
otherwise
error('Can''t have more than two arguments');
end
obj = this;
end
end
end
Consider the implementation below. First some notes:
the constructor can be called with no parameters. This is important to allow preallocating object arrays: obj(m,n) = MyComplex()
for convenience, the constructor accepts either scalar of array arguments. So we can call: c_scalar = MyComplex(1,1) or c_array = MyComplex(rand(3,1), rand(3,1))
the plus operator uses a for-loop for now (we will later change this).
(Note that I skipped some validations in the code, like checking that o1 and o2 are of the same size, similarly for a and b in the constructor).
classdef MyComplex < handle
properties
real
imag
end
methods
function obj = MyComplex(a,b)
% default values
if nargin < 2, b = 0; end
if nargin < 1, a = 0; end
% accepts scalar/array inputs
if isscalar(a) && isscalar(b)
obj.real = a;
obj.imag = b;
else
[m,n] = size(a);
obj(m,n) = MyComplex();
for i=1:m*n
obj(i).real = a(i);
obj(i).imag = b(i);
end
end
end
function obj = plus(o1, o2)
[m,n] = size(o1);
obj(m,n) = MyComplex(); % preallocate object array
for i=1:m*n % linear indexing
obj(i).real = o1(i).real + o2(i).real;
obj(i).imag = o1(i).imag + o2(i).imag;
end
end
end
end
An example of using the class:
% scalar objects
>> c1 = MyComplex(1,2);
>> c2 = MyComplex(3,4);
>> c3 = c1 + c2
c3 =
MyComplex with properties:
real: 4
imag: 6
% array of objects
>> c4 = [c1;c1] + [c2;c2]
c4 =
2x1 MyComplex array with properties:
real
imag
Now here is a vectorized version of the plus method:
function obj = plus(o1, o2)
[m,n] = size(o1);
obj(m,n) = MyComplex();
x = num2cell([o1.real] + [o2.real]);
[obj.real] = deal(x{:});
x = num2cell([o1.imag] + [o2.imag]);
[obj.imag] = deal(x{:});
end
I'm using the syntax: [objarray.propName] to reference a property in object arrays, this return the values as a vector.
For the opposite of assigning a property in an object array, I use comma-separated lists, thus I had to convert to a cell array to get the x{:} convenient syntax.
Note that the deal call is not strictly needed, we could write the assignment without it:
[obj.real] = x{:};
The line obj(n,m) = mycomplex() looks very suspicious. I think what you want to do there is obj = mycomplex(n,m) instead.
I can't see the rest of your code, but it's miraculous to me that this line even works. I suspect that you have an obj variable stored somewhere already, and this code simply overwrites one entry of that variable. I predict that if you clear all variables, it's going to fail on that line.
Again, it's very difficult to understand what happens without knowing what mycomplex() actually does.