Class Initialization for Variables
A while ago, I wrote an article sharing some ideas for Programming for Multiple Datatypes. Recently, a colleague asked me a related question for writing some M-code to be used in an embedded MATLAB block in Simulink. He also wanted to be able to generate code from it, using https://www.mathworks.com/products/rtw/ Real-Time Workshop>, and not use it only for simulation. Together, we tried several ideas.
Contents
Conversion to a Known Class
It's typically straight-forward to convert data into a known class. Simply use the name of the class as the conversion method. If that particular conversion is supported, mission accomplished.
md = magic(3); class(md)
ans = double
md is a double precision magic square. Now convert md to uint16.
mu16 = uint16(md); class(mu16)
ans = uint16
Comparing the arrays, isequal says they are the same since isequal ignores class or type in comparison.
eqvals = isequal(md, mu16)
eqvals = 1
If you want to check the classes are also the same, you can do something like this.
sameclass = strcmp(class(md),class(mu16))
sameclass = 0
Conversion to the Class of Another Variable
If you want to write a generic algorithm and you need to be able to handle inputs of a variety of classes, there are some techniques you can use to ensure that the calculations are done in the class you want.
If you want to initialize some variables in your calculation to 0, but in the class of the input, you could use a switch statement and check all of the builtin types. This is tedious, error-prone, and does not scale well.
You could also use the zeros function with the final classname argument. This works for builtin numeric types.
valsaved = zeros(1,1,class(mu16));
Another method that also works for builtin types is using the function cast.
b = cast(0.0,class(mu16));
What do we do if we have an input that behaves like a builtin numeric clas but isn't built in? Some examples might be the sym object in the Symbolic Math Toolbox (assuming the variable contains values that can be converted to numeric ones) or the fi fixed-point object from the Fixed-Point Toolbox.
msym = sym(md); mfi = fi(md); whos
Name Size Bytes Class Attributes ans 1x6 12 char b 1x1 2 uint16 eqvals 1x1 1 logical fhfi 1x1 16 function_handle fhsym 1x1 16 function_handle md 3x3 72 double mfi 3x3 embedded.fi msym 3x3 622 sym mu16 3x3 18 uint16 sameclass 1x1 1 logical valsaved 1x1 2 uint16 zfi 1x1 embedded.fi zsym 1x1 126 sym zsym2 1x1 126 sym zsym3 1x1 126 sym
Here's a way to convert to an arbitrary class, using str2func
fhsym = str2func(class(msym)); zsym = fhsym(0.0); fhfi = str2func(class(mfi)); zfi = fhfi(0.0); whos
Name Size Bytes Class Attributes ans 1x6 12 char b 1x1 2 uint16 eqvals 1x1 1 logical fhfi 1x1 16 function_handle fhsym 1x1 16 function_handle md 3x3 72 double mfi 3x3 embedded.fi msym 3x3 622 sym mu16 3x3 18 uint16 sameclass 1x1 1 logical valsaved 1x1 2 uint16 zfi 1x1 embedded.fi zsym 1x1 126 sym zsym2 1x1 126 sym zsym3 1x1 126 sym
There is a limitation to this method for Simulink users who want to use embedded MATLAB in the generated code since str2func is not supported for that situation.
Methods that Should (Usually) Work for All Types
So, how to get that initial value to 0 in the right class? Do some arithmetic! Here are two possibilites, illustrated with the sym variable msym.
zsym2 = 0*msym(1); zsym3 = msym(1)-msym(1);
Why do I say "usually" in the title of this section? The calculations should be supported for classes that behave numerically.
Well, first, it allows me to refer you to a great numerical computing reference.
- Numerical Methods that [Usually] Work, Forman S. Acton, Harper & Row, Publishers, ISBN 0883854503 (first published in 1970. On my copy the words on the cover are embossed in gold ink, except the word "usually" which is simply impressed.
Second, I have to admit that these methods only work for finite values of the first input. What would you do if you had to guard against non-finite values?
Other Methods or Preferences
Do you have other methods that would work for the conversion to an unknown class? Or preferences on a method to use? If so, please post here.