I have defined an abstract base class measurementHandler < handle which defines the interface for all inherited classes. Two subclasses of this class are a < measurementHandler and b < measurementHandler.
I now have a function which should return a handle to an instance of either of these subclasses (depending on the function arguments) to it's caller. Consider something like this:
function returnValue = foobar(index)
if index == 0
returnValue = a();
else
returnValue = b();
end
end
This function is enclosed in a MATLAB Function block in Simulink (2013a). When I try to simulate the system, I get the following error:
Type name mismatch (a ~= b).
Can anybody suggest a workaround for this which still allows me to take advantage of OOP & inheritance when using Simulink?
This kind of pattern is possible in MATLAB Function block only if the "if" condition can be evaluated at compile time. The types cannot be switched at run-time. Can you make the index value a constant at the call site?
The main reason to use this pattern was to iterate over a measurementHandler Array, while these all can have custom implementations. I was able to do this by unrolling the loop with the coder.unroll directive. Example for the enclosing MTALAB Function block:
function result = handleAllTheMeasurements(someInputs)
%#codegen
for index = coder.unroll(1:2)
measurementHandler = foobar(index);
measurementHandler.handleMeasurement(someInputs);
end
result = something;
end
This way, the for loop gets unrolled at compile time and the return type of the function is well defined for each separate call.
Related
I am having some trouble with matlab. I am working with b-splines. Sometimes I want to work with the actual spline, while other times I only want to use the so-called basis functions. Without diving into the theory of b-splines, the practical difference is that the when I want to work with the b-spline, I need an extra method and property. I want this property to be initialized by passing it in the constructor.
What I have so far (with most irrelevant methods and properties removed) hopefully roughly demonstrates the behavior that I want:
bsplinespace.m:
classdef bsplinespace < handle
properties
p % polynomial degree
end
methods
function result = bsplinespace(p)
result.p = p;
end
end
end
bspline.m:
classdef bspline < bsplinespace
properties
controlpoints
end
methods
function result = bspline(p, controlpoints)
result.controlpoints = controlpoints;
end
function result = getp(this)
result = this.p;
end
end
end
However, in this scenario the bspline constructor calls the bsplinespace constructor without passing any arguments, causing it to crash:
Not enough input arguments.
Error in bsplinespace (line 8)
result.p = p;
Error in bspline (line 7)
function result = bspline(p, controlpoints)
To be more explicit, what I want is:
One class bsplinespace, which has a constructor which accepts one parameter p
A class bspline, which is the same, but has an extra property and method
Is there an elegant way to implement this?
In your constructor method for bspline, you need to explicitly call the superclass constructor with input argument p:
function result = bspline(p, controlpoints)
result#bsplinespace(p)
result.controlpoints = controlpoints;
end
Otherwise MATLAB will call the superclass constructor with zero input arguments, and you'll get the error you're seeing.
It's a perfectly sensible design, and allows you to control the details of how arguments to the subclass constructor are passed through to the superclass constructor (or not, if you'd like to provide default arguments instead).
I use 16a. I found overloading subsref makes any function calls to an object call (). I am not sure if this is the correct use of subsref. For example,
classdef A < handle
methods
function obj = A(varargin)
end
function v = subsref(obj, S) %#ok<STOUT,INUSD>
assert(false);
end
function c = foo(obj) %#ok<MANU>
c = 1;
end
end
end
Then I god the following errors when using foo.
>> a = A()
a =
A with no properties.
>> a.foo()
Error using A/subsref (line 6)
Assertion failed.
8 assert(false);
If I removed subsref, it works fine. In terms of
http://www.mathworks.com/help/matlab/ref/subsref.html
subsref is called only when A{i}, A(i) or A.field. Since foo is a method, why is subsref still called?
This is completely expected behavior, because to MATLAB, A.field and A.method both use the dot referencing and therefore are processed by subsref. The typical way of getting around this is to instead call your class methods using the standard function call rather than a dot referenced method call.
method(A)
%// Rather than
A.method()
This usage is also superior as it can operate on arrays of objects rather than only scalars. Also, it is more performant.
I come from a Java background. I am having issues with classes in Matlab particularly getters and setters. getting a message saying conflict between handle and value class I'm a little lost with what to do so any help for lack of a better word will be helpful.
classdef Person
properties(Access = private)
name;
age;
end
methods
% class constructor
function obj = Person(age,name)
obj.age = age;
obj.name = name;
end
%getters
function name = get.name(obj)
end
function age = get.age(obj)
end
%setters
function value = set.name(obj,name)
end
function value = set.age(obj,age)
end
end
end
Implementation
Since your class is currently a subclass of the default Value class, your setters need to return the modified object:
function obj = set.name(obj,name)
end
function obj = set.age(obj,age)
end
From the documention: "If you pass [a value class] to a function, the function must return the modified object." And in particular: "In value classes, methods ... that modify the object must return a modified object to copy over the existing object variable".
Handle classes (classdef Person < handle) do not need to return the modified object (like returning void):
function [] = set.name(obj,name)
end
function [] = set.age(obj,age)
end
Value vs. Handle
Going a bit deeper, the difference between a Value class and a Handle class lies mostly in assignment:
Assigning a Value class instance to a variable creates a copy of that class.
Assigning a Handle class instance to a variable create a reference (alias) to that instance.
The Mathworks has a good rundown on this topic.
To paraphrase their illustration, the behavior of a Value class is
% p is an instance of Polynomial
p = Polynomial();
% p2 is also an instance of Polynomial with p's state at assignment
p2 = p;
and of a Handle class is
% db is an instance of Database
db = Database();
% db2 is a reference to the db instance
db2 = db;
Quick'n Dirty from the Java perspective:
- "handle" classes are what your mind is set to. proper object instances with pointers to them. use them.
- "value" classes are always returning a full clone of whatever object (which has been modified by what you just did, e.g. setting a name).
the reason they have both in Matlab is that in Matlab you would expect the "value" behaviour natively. Imagine you have a matrix A = [1 2; 3 4], then assign that via B = A. if you now set B(1) = -1 you'd hope that A(1) is still 1, right? this is because matlab keeps track of "copies" and truly creates them as you modify different variables initially set to the same matrix. in OOP you'd have A(1)=-1 now as everythings an object reference.
furthermore, "native" matlab routines dont have a "this/self/me" variable that contains the instance reference to access from within functions. instead, the convention is that the class instance will be prepended to the function's argument list.
so for a function call myclass.mymethod(arg1,arg1), the declaration must be
function mymethod(this, arg1, arg2)
% Note that the name you choose for "this" is arbitrary!
end
mind you, this is the java-perspective (and also my favourite one), the above function call is equivalent to mymethod(myclass,arg1,arg1). this is more native to matlab-style, but somehow makes it harder to see you're calling an objects method.
now, regarding setters/getters: for handle classes, everything feels java-ish now:
classdef MyClass < handle
properties
MyProp;
end
methods
function set.MyProp(this, value) %Note: setMyProp is also valid!
... % do checks etc, trigger calls,
this.MyProp = value;
end
function value = get.MyProp(this)
... % notify, update, triggers etc
value = this.MyProp;
end
end
Of course it goes without saying that you dont need to define a getter if you just want to return the value, i.e. myclassinstance.MyProp will work without any just as well.
Finally, getters/setters for value classes are something that [never encountered me/i never needed] in my 7 years of matlab oop, so my advise would be to go with handle classes and enjoy happy matlab coding :-)
otherwise, the above explanation & official matlab docs is doing the job for value class getter/setters.
I'm trying to constrain an entire object (not just the fields of an object) based on some other object. Here is a stripped down version of my production code:
I have the following class:
class some_class;
bit[7:0] some_field;
bit[3:0] some_other_field;
// this function would do some complex procedural
// operations on the fields of the object
function void do_some_op();
bit[3:0] tmp = some_field[3:0];
some_field[3:0] = some_other_field;
some_other_field = some_field[7:4];
some_field[7:4] = tmp;
endfunction
function some_class some_function(bit some_param);
some_function = new this;
$display("foo"); // this print here to see that method is executed
if (some_param)
some_function.do_some_op();
endfunction
function void print();
$display("some_field = %x", some_field);
$display("some_other_field = %x", some_other_field);
endfunction
endclass // some_class
This class contains some integral fields. It also has a method that does some complex procedural on the fields of that class. In the example I've simplified it. I also have another class that returns a new object on which the operation has been performed.
I have another class that operates with some_class instances. As per Dave's input I have made it create the objects first (as randomize() does not create objects).
class some_shuffler;
rand bit params[];
rand some_class objects[];
constraint size_c {
params.size() == objects.size() - 1;
params.size() <= 10;
};
constraint shuffle_c {
// not allowed by standard
// foreach (params[i])
// objects[i+1].some_field == objects[i].some_function(params[i]);
foreach (params[i])
objects[i+1].some_field ==
objects[i].some_function(params[i]).some_field &&
objects[i+1].some_other_field ==
objects[i].some_function(params[i]).some_other_field;
};
function new();
objects = new[10]; // create more objects than needed
foreach (objects[i])
objects[i] = new();
// initialize first object
objects[0].some_field = 8'hA5;
endfunction // new
function void post_randomize();
foreach (objects[i]) begin
$display("objects[%0d]:", i);
objects[i].print();
$display("");
end
endfunction
endclass
This class has two arrays, one of operations performed and one of the intermediate states. There is an initial object. On this one, some_function is performed and it results in the next object.
This is how I wanted to test it:
module top;
import some_pkg::*;
initial begin
static some_shuffler shuffler = new();
bit rand_ok;
rand_ok = shuffler.randomize() with {
params.size() == 1;
};
assert (rand_ok);
end
endmodule
When trying to constrain the objects directly I immediately get a constraint violation. The simulator seems to try to make the 2 handles equal. This is anyway forbidden by the standard and I'm not doing it anymore (though a compile failure would have been nice). I've unraveled the constraints as suggested by Dave and Greg (I think doing some_function().some_field is non-standard, but it compiles in Questa).
Even now, the foo print does not appear on the command line (some_function() is not getting executed). What I see is that objects[1] contains the initial value (all 0s for both fields).
I can't just generate the list of params and then procedurally randomize the objects for each iteration, because I want to be able to constrain the last object to have a certain value - basically giving the constraint solver the start and the end points and let it figure out the way to get there.
Object vs. object constraints are not allowed in SystemVerilog because they are not integral types. See IEEE Std 1800-2012 § 18.3:
Constraints can be any SystemVerilog expression with variables and constants of integral type (e.g., bit, reg, logic, integer, enum, packed struct).
You can constrain the integral components of class object if the component is a rand (ex obj[1].value == obj[0].value+1;).
Functions are allowed in constraints, but there limitation. See IEEE Std 1800-2012 § 18.5.12 Functions in constraints for full details. Limitations include:
Functions cannot contain output or ref arguments
Functions should be automatic and leave no side effects
The functions arguments have an implicit priority (ex x<=F(y) infers solve y before x)
Circular dependencies will result in an error
Update:
Looks like the only thing truly being randomized is params. The values of some_field and some_other_fieldare calculations. So it makes more sense to move the loop for shuffling into thepost_randomize` function.
constraint size_c {
params.size() == objects.size() - 1;
params.size() <= 10;
};
function void postrand_shuffle();
foreach (params[i])
objects[i+1] = objects[i].some_function(params[i]);
endfunction
function void post_randomize();
postrand_shuffle();
// ... your other post_rand code...
endfunction
SystemVerilog's random constraint solver will work when there is at least one solution. However when the solution space is small and difficult to determine or a long chain, simulator performance drops. For these scenarios it is better move the one-to-one sequential calculations into post_randomize.
A couple of problems with your example code.
Objects must be constructed first before calling randomize(). If
you know the exact size before calling randomize (like in your
example), just new[n] the dynamic arrays constructing each object
element first, and remove the size constraints. If the size will be
random, you need an upper limit constraint on the size. construct the max
number of objects before calling randomize(), and after randomizing the array, the unused objects will be eliminated.
Constraint expressions must be integral. You can do objects[i+1].some_field == objects[i].some_field but the solver cannot manipulate class handles.
The return values of functions are treated as state variables. Move these to post_randomize
My mate is trying to do this on matlab (Please excuse the terminology. I am not super sure with matlab.)
He is entering two structures which are polynomials into a class as parameters in methods but it will only accept doubles for some reason. hOW do you fix this?
classdef dostuff
properties
polyn %not really sure what this does
end
methods
function r = plus(struct1, struct2)
r = dostuff(addthem(struct1,struct2)); %adds the two polynomials
end
end
end
The error is Undefined function 'dostuff' for input arguments of type 'struct'.
How do you get the class to accept structures (polynomials) as parameters?
The class dostuff does not have a constructor that will accept a struct. So the call to
dostuff(addthem(struct1,struct2))
is trying to call a constructor that doesn't exist. You would need a constructor like
methods
function obj = dostuff(mystruct)
obj = <...>
end
end