shape intrinsic function in fortran - matlab

I am playing around with the shape() intrinsic function in fortran:
program test
integer, dimension(5,3) :: A
integer, dimension(2) :: ShapeA
ShapeA = shape(A)
print *, ShapeA(1)
print *, ShapeA(2)
end program test
I understand the shape function returns a 2 element vector containing the length and width of array A. In the above code, the output of shape(A) is passed to the predefined variable ShapeA. Then the contents of ShapeA are printed out, namely 5 and 3.
I would like to find a way to refer to the contents of the output of shape(A) without having to assign it to an intermediate variable ShapeA.
This would be similar to the matlab size function which enables looping constructs like this:
A = [1 2 3 5 4; 2 3 5 4 5]
for i = 1:size(A,2)
A(2,i)
end
Which means the user need not assign another variable like so:
A = [1 2 3 5 4; 2 3 5 4 5]
sizeA = size(A,2)
for i = 1:sizeA
A(2,i)
end
In fortran it is necessary to both declare the variable, assign it a value using size statement then include that variable in the loop. I would like to remove the first two steps and see if it can be done like in matlab. Any ideas? Thanks.

From the fortran manual page for shape there is a link to SIZE, specifically (emphasis mine)
Description:
Determine the extent of ARRAY along a specified dimension DIM, or the total number of elements in ARRAY if DIM is absent.
program test
integer, dimension(5,3) :: A
print *, size(A,1)
print *, size(A,2)
end program test

Related

Can you explain what this line does in Matlab

I'm new to Matlab and I'm just stuck with this line of code:
[r,c] = find(abs(fh) <= 2 );
Beware: ironically it was easy for me understanding what the right part of the assignment is.
The left part however (which is maybe the definition of a variable)... I don't know how to search because I have too generic results by googling just square brackets with something inside.
My assumption is this line of code is creating some a matrix with r rows and c columns but r and c are nowhere to be found in the rest of the code.... or maybe it's a simple array with two elements... but it doesn't make much sense to me honestly.
Can you guys help me please?
Whenever you see that syntax, it means that the function being called is returning more than one output argument (two in this case).
The best way to learn about the function output arguments is to check the documentation:
https://www.mathworks.com/help/matlab/ref/find.html#d120e368337
[row,col] = find(___) returns the row and column subscripts of each
nonzero element in array X using any of the input arguments in
previous syntaxes.
The output arguments are positional, so r is row, c is col.
Take a look in Matlab find() docs.
If X is a vector, then find returns a vector with the same orientation as X.
If X is a multidimensional array, then find returns a column vector of the linear indices of the result.
If X contains no nonzero elements or is empty, then find returns an empty array.
If you call
X = [18 3 1 11;
8 10 11 3;
9 14 6 1;
4 3 15 21 ]
[row,col] = find(X>0 & X<10,3)
You will get:
row = 3×1
2
3
4
col = 3×1
1
1
1
Which represents the index (row number and column number) of each elements that satifies the condition you defined. Since it returns more than 1 value, you can divide the output in two different variables and that is what the left side represents.

How do I assign the output from a Matlab function to a variable in a single line?

Is there a way in matlab to assign the output from a function in matlab to a vector within a single line?
For example, this function should assign a perimeter and an area value
function [p,a] = square_geom(side)
p = perimeter_square(side)
a = side.^2
[p,a]
however when I try to store the data like this
v = square_geom(3)
It doesn't work. However it is possible to do it like this
[p,a] = square_geom(3)
v=[p,a]
But that just doesn't look as good as keeping it to a single line. Any ideas?
You can change the definition of your function by using varargout as output variable:
Edit
Updated the definition of the function to include the check on the number of output
function varargout = square_geom(side)
p = 3;% %perimeter_square(side)
a = side.^2;
v=[p,a];
switch(nargout)
case 0 disp('No output specified, array [p,a] returned')
varargout{1}=v;
case 1 varargout{1}=v;
case 2 varargout{1}=p;
varargout{2}=a;
case 3 varargout{1}=v;
varargout{2}=p;
varargout{3}=a;
otherwise disp(['Error: too many (' num2str(nargout) ') output specified'])
disp('array [p,a,NaN, NaN ...] returned (NaN for each extra output)')
varargout{1}=v;
varargout{2}=p;
varargout{3}=a;
for i=4:nargout
varargout{i}=NaN
end
end
This allows you either calling your function in several ways
square_geom(3)
v=square_geom(3)
[a,b]=square_geom(3)
[a,b,d]=square_geom(3)
[a,b,d,e,f,g]=square_geom(3)
In the first case you get the array v as the automatic variable ans
square_geom(3)
No output specified, array [p,a] returned
ans =
3 9
In the second case, you get the array v
v=square_geom(3)
v =
3 9
In the third case, you get the two variables
[a,b]=square_geom(3)
a = 3
b = 9
In the fourth case, you get the array v and the two sigle variables a and b
[v,b,d]=square_geom(3)
v =
3 9
b = 3
d = 9
In the latter case (too many output specified), you get the array v, the two single variables a and b and the exceeding variables (e, f and g) set to NaN
[v,b,d,e,f,g]=square_geom(3)
Error: too many (6) output specified
array [p,a,NaN, NaN ...] returned (NaN for each extra output)
v =
3 9
b = 3
d = 9
e = NaN
f = NaN
g = NaN
Notice, to thest the code I've modified the function byh replacing the call toperimeter_square with 3
The value outputted by the function are two different variables, not an array.
So the output should be stored as two cells.
[v(1),v(2)]=fn(val)
Here, the value is stored in two different cell v(1) and v(2) of the same array 'v'.
The simplest solution that comes into my mind is:
c = test();
function result = test()
a = ...; % complex computation
b = ...; % complex computation
result = [a b];
end
The C variable will then be a column vector containing two values. But this solution is only suitable if your function output doesn't need to be flexible.
You can get your multiple outputs in a cell array.
In your case:
v=cell(1,2);
[v{:}]=square_geom(3)

MATLAB Incorrect number of right hand side elements

Matlab's syntax is infuriating, specifically with structs. In the Bioinformatics toolkit, there is a method called jcampread(File) which is described here.
In the description, the method jcampread() takes a Filepath and outputs into a struct called jcampStruct. From my understanding, in Matlab, you don't declare return variable types like you do in C: you just give the return variable a name and it somehow knows that the return of jcampread() method will be a jcampStruct. How it does, I have no idea, but it does.
I put in the code exactly how their example shows in step 4 of the Example section, and I get the following error message back from Matlab:
Incorrect number of right hand side elements in
dot name assignment. Missing [] around left hand
side is a likely cause.
Error in jcampread>ntupleRead (line 510)
dataBlock.ZName = name{Zidx};
Error in jcampread (line 192)
dataBlocks = ntupleRead(fid);
This site says the problem occurs "when f has more than one matrix element." Code is below:
»f.a = [1 0]
f =
a: [1 0]
»f.b = [1 2]
f =
a: [1 0]
b: [1 2]
»f = setfield(f,'a',[2 2])
f =
a: [2 2]
b: [1 2]
»f(2).a=1
f =
1x2 struct array with fields:
a
b
»f = setfield(f,'a',[2 2])
??? Error using ==> setfield
Incorrect number of right hand side elements in dot name assignment.
Missing [] around left hand side is a likely cause.
I assume this means the matrix f looks like this:
f = [ [a1; b1]; [a2; b2]; ]
f = [ [[2 2]; [1 2]]; [[1]; []]; ]
When they tried to update f.a which was set to
f.a = [[2 2]; [1]]
...to a single element [2 2], it doesn't like that because f.a is currently a matrix with 2 vector elements. Basically if you are going to reassign f.a (all elements of the attribute a of matrix f), you have to reassign f.a to have the same number of elements as it currently has.
I think that is why this error is occuring in the setfield example.
My question: how does this apply to jcampread()? jcampStruct is literally a structure with the same attributes, and those attributes are assigned only once. I do not understand:
a. How matlab knows the return value of jcampread() is a jcampStruct, and
b. Why (given that it knows (a)), the 'Incorrect number of right hand..' error message is firing here.
Can anyone clear this up for me?
You are creating a non scalar structure and there is no way to assign at once, i.e. without a loop, a different value to the same field of each sub-structure.What does it mean?
Scalar structure
s.a = 1;
size(s)
ans =
1 1
Now, adding fields doesn't change the size of the structure:
s.b = 2;
size(s)
ans =
1 1
Non-scalar structure
However, assigning a value to the same field, but into a position > 1 of the structure, will grow it a non-scalar one:
s(2).a = 3
size(s)
ans =
1 2
Also, notice how the sub-structure in position 2 replicates/pre-allocates the fields of the initial structure even though you assigned to a alone:
s(2)
ans =
a: 3
b: []
Pointers
Additionally, the field s(2).b is just an empty pointer:
whos s
Name Size Bytes Class
s 1x2 496 struct
and by adding a scalar double (8 bytes), we get
s(2).b = 4;
whos s
Name Size Bytes Class
s 1x2 608 struct
Pro of non-scalar structure
What you can do with a non-scalar structure, is retrieve one field across all sub-structure (considering you don't run into concatenation issues):
for ii = 1:100
s(ii).a = rand(1,2);
end
cat(1,s.a)
the last command will concatenate all values of a single field from all sub-structure into a 100 by 2 array.
Cons
To assign different values across the sub-structures, even if the same field, you need to loop (as above in the for loop).
At most you could deal() the same values into one field across all sub-structures:
clear s
[s(1:100)] = deal([1, 2]);

Combination of colon-operations in MATLAB

I have a question concerning the colon operator and expansion of vectors in MATLAB. My problem is to understand how the following line of code expands, to be able to use it for other sequences. The line of MATLAB code is:
a(1:2:5) = 1:-4:-7
Note that a is not defined before the expansion. This returns the vector
a = 1 0 3 0 -7
I know how the colon operator works with {start}:{step}:{stop}, my problem is to understand how and why the combination of a(1:2:5)and 1:-4:-7 returns a vector of five elements with zeros in position 2 and 5?
Whenever Matlab detects you're indecing to an element outside the current bounds of the matrix/array, it will automatically pad the missing elements with zeros:
>> clear b; b(10) = 5
b =
0 0 0 0 0 0 0 0 0 5
This feature is both very useful, and very dangerous. It is useful for the fact declarations can be made very easy, such as your own case. You can create a whole array of custom-made classes by issuing something like
myClassArray(500) = myClass(1, 2);
which is infinitely better than something like
% cannot pre-allocate (zeros() or ones() give double/uint8/..., not myClass)
for ii = 1:499
myClassArray(ii) = myClass; % so, growing array
end
myClassArray(500) = myClass(1,2);
But, growing arrays can be hard to spot:
a = zeros(10,1);
for ii = 1:10
a(ii+1) = rand;
end
which can make performance drop tremendously. Also, when you translate code prototyped in Matlab to a statically-typed language like C++, copying this code will result in buffer overflows and thus segfaults.
Now, going back to your case:
clear a; a(1:2:5) = 1:-4:-7
The 1:2:5 will expand to the array [1 3 5], and the 1:-4:-7 will give the values [1 -3 -7]. Since the variable a does not exist yet, Matlab will create a new one and fill the elements [1 3 5] with the values [1 -3 -7]. The indices that have been skipped in order to initialize variable a (namely, [2 4]) will then have been initialized automatically to zero.
If you're familiar with Python, it's a bit like the syntax to assign multiple values to multiple variables
x,y = 1,2
But in your Matlab case, these different variables are indices to a non-existent array, which requires "filling the holes with something" to make it a valid, consistent array.
Does this make things clear?
when you define a(1:2:5), it creates a size 5 vector (zero-valued), and selecting odd indexed(3 of them exists) cells. 1:-4:-7 creates three values (not five). Finally your selected three cells are filled with data of 3 values coming from 1:-4:-7

Can't output multidimensional matrix in Matlab function in Simulink

For example I have function that creates matrix 2x2 : [1 2; 3 4]
I have such simple function:
function[result] = Rho(x)
// I've tried and so:
result = [1 2; 3 4];
// And so:
result(1,1) = 1;
result(1,2) = 2;
result(2,1) = 3;
result(2,2) = 4;
In Matlab window i see right result:
>> Rho(1)
ans =
1 2
3 4
But in Simulink I always get [1;2;3;4]. Where is my mistake?
P.S. I forgot to remove argument x of function, because in real function I make matrix depending on argument x. But it doesn't play role in our example
The problem you are having is likely due to the parameter settings for your MATLAB Function block (now called an Interpreted MATLAB Function block in newer versions). Take a look at the Parameters Dialog Box for that block:
Note that you will want to set the Output dimensions to 2 and uncheck the Collapse 2-D results to 1-D check box. If this is left checked, then your 2-by-2 matrix will be turned into a 1-D array by extracting values along each column from left to right, which ends up being [1 3 2 4] in your example.
Once you apply the above changes, then all you should have to do is resize your Display block so that it shows your 2 rows and 2 columns.