Returning an object of the same class from an overloaded method operation "plus" rather than struct? - matlab

I have a MATLAB class that has a simple overloaded plus function, and I can't get it to return an object. I want the function to add each field value together and output an object of the same class, with the field values being sums of the two inputs. When I add the two objects together, I get a struct, not an object. I am new to classes and am likely doing this wrong; any help would be great.
The code is as follows:
classdef Molar
properties
A = 0;
B = 0;
C = 0;
end
methods
function M = Molar(val)
M.A = val;
M.B = val+1;
M.C = val+2;
end
function M = plus(M1,M2)
M.A = M1.A + M2.A;
M.B = M1.B + M2.B;
M.C = M1.C + M2.C;
end
end
end
When it runs and I do:
>> x = Molar(2)
x =
Molar with properties:
A: 2
B: 3
C: 4
>> y = Molar(3)
y =
Molar with properties:
A: 3
B: 4
C: 5
Then I get a struct when I do the + operation. How can I get this to return another Molar object?
>> x+y
ans =
struct with fields:
A: 5
B: 7
C: 9
I wonder if it has to do with needing to use the constructor method differently?
Any help in this regard would be appreciated.

The first parameter should be the returned value:
function M = plus(M,M2)
M.A = M.A + M2.A;
M.B = M.B + M2.B;
M.C = M.C + M2.C;
end

Related

A Matlab class for Commutative Hypercomplex number: How to overload the basic Matlab function?

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.

In matlab, I got different values in a method of class and out

In the matlab, I defined a class and instantiated the class in another script, but I got different values in and out of the method. My matlab code are shown bellow:
test_add.m
classdef test_add
properties
a
b
end
methods
function obj = test_add(a, b)
obj.a = a;
obj.b = b;
end
function c = add_1(obj)
c = obj.a + 1;
end
function inter(obj, t)
for i = 1:t
obj.a = obj.add_1();
end
fprintf('In the method:\n');
fprintf('a = %d\n',obj.a);
fprintf('b = %d\n',obj.b);
disp('=======================');
end
end
end
main.m
tt = test_add(1,2);
tt.inter(3);
fprintf('Out of the method:\n');
fprintf('a = %d\n',tt.a);
fprintf('b = %d\n',tt.b);
output:
In the method:
a = 4
b = 2
=======================
Out of the method:
a = 1
b = 2
In Matlab there are two type of classes: handle class and Value class. If you said nothing you get the Value class. Most of the OO languages out there are using handle class semantic.
So, you have two options:
Change you class to handle class by inheriting from handle
classdef test_add < handle
Stay with Value class and change your inter function to return obj.
But then, in main call obj=tt.inter(3) to get the updated object.
function obj = inter(obj, t)
for i = 1:t
obj.a = obj.add_1();
end
fprintf('In the method:\n');
fprintf('a = %d\n',obj.a);
fprintf('b = %d\n',obj.b);
disp('=======================');
end
It's a problem of value class vs handle class, the solution is:
test_add.m
classdef test_add < handle
...
end
Then, the output is:
In the method:
a = 4
b = 2
=======================
Out of the method:
a = 4
b = 2

How to perfor subscripted assignment between dissimilar structures in Matlab?

I want to assign one structure A to another structure B indexed:
B(3) = A;
while A having different fields than B. I want non existing fields automatically created and absent fields automatically ignored.
Is this possible in Matlab?
Solution
You can use fieldnames function, and assign each field value using a loop. The other fields will remaine unchanged.
Example
%defines input stract
a.f1 = 2; a.f2 = 3; a.f3 = 'str';
temp.f2=5; temp.f3 = 7; temp.f4 =1;
b(1) = temp; b(2) = temp; b(3) = temp;
%iterates over the fields of a and assigns their values into b
fields = fieldnames(a);
for ii = 1:numel(fields)
b(3).(fields{ii}) = a.(fields{ii});
end
Results
before
a =
f1: 2
f2: 3
f3: 'str'
b(3) =
f2: 5
f3: 7
f4: 1
after
b(3)=
f2: 3
f3: 'str'
f4: 1
f1: 2
EDIT: Ibezito beat me to pretty much the same answer by a minute or so...
I've done something similar with a function like this:
function B = mergeStruct(B,A,bIdx)
aFields = fieldnames(A);
for af = aFields';
B(bIdx).(char(af)) = A.(char(af));
end
See this example:
>> B.a = 1;
>> B.b = 2;
>> A.b = 10;
>> A.c = 11;
>> B = mergeStruct(B,A,3)
>> B(1)
ans =
a: 1
b: 2
c: []
>> B(2)
ans =
a: []
b: []
c: []
>> B(3)
ans =
a: []
b: 10
c: 11

matlab how to call a class method that changes prop from another class method

If I call a method (receiving and returning obj) it changes my property.
But if I call that method from another method it fails. I tried all kinds of ways but still failing.
classdef AClass
properties
A;
end
methods
function obj = ChangeA(obj, v)
obj.A = v;
end
function obj = CallChangeA(obj)
obj.ChangeA(4);
%obj = obj.ChangeA(4);
%ChangeA(obj, 4);
%obj = ChangeA(obj, 4);
% none of these works
end
end
end
% ------ script:
a1 = AClass;
a1.A = 1;
a1.ChangeA(2); % a1.A = 2
a2 = AClass;
a2.A = 3;
a2.CallChangeA(); % a2.A = 3 !!! not four
How do I write the code so calling from 1 method to the other updates the property?
Other than the obvious typos in your example code, as I commented above, I would highly suggest taking a look at the difference between MATLAB's Handle and Value classes. By default, MATLAB classes are value classes, so each time the object is passed to a function an independent copy is created. If you're making changes to this object then you need to return it as an output:
classdef AClass
properties
A;
end
methods
function obj = ChangeA(obj, a)
obj.A = a;
end
function obj = CallChangeA(obj)
obj = obj.ChangeA(4);
end
end
end
Which functions as expected:
>> a1 = AClass;
>> a1.A = 1
a1 =
AClass with properties:
A: 1
>> a1 = a1.CallChangeA()
a1 =
AClass with properties:
A: 4
Handle classes, on the other hand, are references to a single underlying object, allowing for (among other things) in place modification of the object:
classdef AClass < handle
properties
A;
end
methods
function ChangeA(obj, a)
obj.A = a;
end
function CallChangeA(obj)
obj.ChangeA(4);
end
end
end
Which also functions as expected:
>> a1 = AClass;
>> a1.A = 1;
>> a1.A
ans =
1
>> a1.CallChangeA()
>> a1.A
ans =
4

Matlab recursion

Need a little help understanding what is happening in this function particularly line 7 [Fnm1,Fnm2] = fibrecurmemo(N-1); I don't understand how a new variable can be declared here with in the array. an example of what is happening would be appreciated.
function [Fn,Fnm1] = fibrecurmemo(N)
% Computes the Fibonacci number, F(N), using a memoized recursion
if N <= 2
Fn = 1;
Fnm1 = 1;
else
[Fnm1,Fnm2] = fibrecurmemo(N-1);
Fn = Fnm1 + Fnm2;
end
end
Say we start with:
fibrecurmemo(3) %// N is 3
The else statements run (since N > 2):
[Fnm1,Fnm2] = fibrecurmemo(2); %//statement 1
Fn = Fnm1 + Fnm2; %//statement 2
Before statement 2 can run, fibrecurmemo(2) must first run.
The if statements in fibrecurmemo(2) run (since N <= 2):
Fn = 1;
Fnm1 = 1;
As a result, fibrecurmemo(2) returns 1, 1.
Contininuing from statement 1 above,
[1,1] = fibrecurmemo(2); %//statement 1
Fn = 1 + 1; %//statement 2
Finally,
[2, 1] = fibrecurmemo(3);
The function returns two values.
function [xFive,yFive] = addFive(x,y)
xFive = x + 5;
yFive = y + 5;
end
xx = (addFive(3,4))
xx will be equal to 8 in this example
the syntax for assignment for multiple return values is
[a,b,c,...] = someFunc();
where someFunc() has output of [a,b,c,...]
[aa,bb] = addFive(3,4);
cc = addFive(3,4);
if you do it this way you would get
aa == 8
bb == 9
cc == 8
in the case of cc instead of [aa,bb] Then you will just get the first return value.
i.e. you could do
x = fibrecurmemo(5)
[y,z] = fibrecurmemo(5)
in this case x == y