Override subsasgn of MATLABs double?

4 views (last 30 days)
Jan Siegmund
Jan Siegmund on 23 Apr 2020
Edited: Jan Siegmund on 30 Apr 2020
Consider the following statement:
x = [1 2;3 4];
y = myclass([5 6]);
x(1:2) = y
MATLABs default behavior is:
  1. x(1:2) = ... returns a double
However what I want is:
  1. x(1:2) = ... returns a myclass
How can I exchange subsasgn in MATLABs default double class?
  5 Comments
Jan Siegmund
Jan Siegmund on 23 Apr 2020
Edited: Jan Siegmund on 23 Apr 2020
Ok now it gets even more strange. If i call
x = subsasgn(x,'1:2',y)
my function is called and prints an error, because it expects the standard subs struct.
Subscript argument to SUBSREF and SUBSASGN must be a structure.
If I call
x = subsasgn(x,struct('type','()','subs',{{[1 2]}}),y);
x is assigned normal, but my function is not called. Instead MATLABs internal double function is called.
This behavior is also represented by which:
>> which subsasgn(x,struct('type','()','subs',{{[1 2]}}),y);
built-in (/usr/local/MATLAB/R2020a/toolbox/matlab/ops/subsasgn)
>> which subsasgn(x,'1:2',y);
/home/<user>/workspace/MATLAB/<prjname>/@double/subsasgn.m % double method
Since when does MATLAB run functions based on its signature (its input parameters)???
Jan Siegmund
Jan Siegmund on 23 Apr 2020
Edited: Jan Siegmund on 23 Apr 2020
I have the fear, that this cannot be changed and x(1:2) = ... always has to return the type of x.
Please no, this would kill my project.
Can a STAFF member confirm the statement?

Sign in to comment.

Answers (2)

James Tursa
James Tursa on 23 Apr 2020
Overriding subasgn for a native class like double is a very bad idea, because it affects everything, not just the code that you wrote. If you want a myclass object, then use myclass( ) method explicitly to create it. That is how the language is set up to work.
  4 Comments
James Tursa
James Tursa on 23 Apr 2020
Instead of working with code snippets, can you describe the behavior you are after at a higher level, maybe with some pseudo-code examples? Then maybe we can steer you in the right direction to acheive your overall objective.
Jan Siegmund
Jan Siegmund on 23 Apr 2020
I try to rebuild the project stated in this paper. https://dl.acm.org/doi/pdf/10.1145/774789.774797 Basically estimating FPGA resources by counting primitive operations (+,-,*,/) in the code. I tried using the Matlab HDL coders ressource estimation but found it to be extremely inaccurate so I decided to write a similar util myself.

Sign in to comment.


Steven Lord
Steven Lord on 23 Apr 2020
As James Tursa stated, overriding methods for the double class is a Bad Idea, and trying to override indexing for double is a Very Bad Idea.
If you want all the variables in your function to be of the same class as the input (double for a double precision input, myclass for a myclass input, etc.) I would instead initialize all the variables in your function based on the class of the input. One way to do this is to liberally sprinkle cast calls throughout your code. A different way, since I'm hoping you're already preallocating the variables in your code using functions like ones, zeros, eye, etc. is to specify the class input to those functions. MATLAB already knows how create variables of built-in types this way (and will do so without first creating a larger double array and casting it to the selected type.)
A = ones(4, 5, 'int8')
B = eye(6, 'uint64')
C = rand(3, 3, 'single')
x = int32(5);
D = zeros(2, 6, class(x)) % or
E = zeros(2, 6, 'like', x)
To enable this for your class, you need to define a few methods on your class. If you can't or don't want to define those methods, you could cast. All of the following examples showing this use the sym object from Symbolic Math Toolbox.
F = inf(5, 5, 'sym') % sym defines a static inf method
G = randi(5, [4 4], 'sym') % Fails because sym doesn't define a randi method
H = cast(randi(5, [4 4]), 'sym') % works
  3 Comments
Steven Lord
Steven Lord on 23 Apr 2020
Possible? Yes. Maybe not to do what you want your overload to do (I'd need to think a bit more about that) but possible.
But if you were to do that, you are invalidating an assumption about how MATLAB works, that the type of the left-hand side of an assignment statement doesn't change when you assign into a piece of it. Is that an important or often-used assumption? I don't know offhand. Would invalidating it lead to bugs in functions that were working perfectly fine before? Possibly.
When or if you update your code to preallocate variables to the class of the input argument, you won't need to adjust it again based on whether the input is a double, single, myclass, etc.
f = @(x) ones(2, 3, 'like', x);
outputDouble = f(5)
outputUint64 = f(uint64(5))
outputSym = f(sym(5))
whos output*
The body of f doesn't change but because it's called with different input arguments the class of the output is different.
And of course those construction methods aren't the only ones that you can overload. You can overload the operators for myclass to count how many times they're called.
Jan Siegmund
Jan Siegmund on 30 Apr 2020
Edited: Jan Siegmund on 30 Apr 2020
Well problem is, i don't want to edit the code to which my class is handed. It should work on every code part, not just some I created.
And as for overriding subsasgn. I don't think it is possible because If I put a file @double/subasgn.m in my local path, It is only executed on x = subsasgn(x,"1:2",y), never on x = subsagn(x,substruct('()',{[1 2]}),y). And as the matlab parser does not produce invalid syntax on x(1:2) = y, it is not possible to override subsasgn of double.
But I got one ace up my sleeve and turned it into an overengineered solution. Matlab always calls the double() function on myclass when calling x(1:2) = y (x is a double, y is myclass). This function throws an Exception which is caught in my toplevel script. As the stacktrace is attached to the exception, I add x = myclass(x) one line above the one-working statement and rerun the function. Voila, myclass' subsasgn is called.
The perks of a language that can rewrite itself during execution.
Another possibility that was promising is stopping always in myclass' double() with dbstop() and then going up the callstack with dbup, casting and dbcont from the caller. But this is also not possible as MATLAB can't skip a statement in debugger.
Finally I would have liked it a lot more to override subsasgn of double. I have no clue why this is not permitted.

Sign in to comment.

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!