Automatic array length in Fortran and Visual Studio debug - arrays

I got a question concerning the debugging of a fortran file. Thus I declared it with d(*) automaticaly. However during the debugging and the supervision of the array it just shows the first number of the according array and not the 60 others.
(I use Fortran 95 compiler and Visual Studio 2010)
How can I still view all variables of the array?
Okay here comes one example for the code:
ia is a variable integer from the main routine depending on some input parameters.
subroutine abc(ia,a,b,c)
dimension d(*)
a = d(ia+1)
b = d(ia+2)
c = d(ia+3)
return
end
However for debugging it is useful to know the endities of d(*)

The only way I've found to do this is to use the Watch window and add a watch for the array elements. Suppose your array is called d, then I've found that watching the following expressions shows the values in the array:
d(2) ! which just shows the 2nd element in the array
d(1:10) ! which shows the first 10 elements of the array
d(1:12:2) ! which shows the odd numbered elements of the array from 1 to 11
And of course, for an array of length 60 such as you suggest you have, then the expression
d(61)
will show you what value is in the memory location to which that array address points.
Of course, you should really be declaring your array as d(:). If you do, then the VS debugger shows the entire array in the usual Locals window.

Related

Determine the actual used size of an array

I have found the usual answer for determining the size on an array - 'variable = sizeof buffer/sizeof *buffer;' or similar which gives the declared size
Other than passing a counter variable around when an array is 'filled', is there a way (a command or function - something similar to the above 1 liner) to find the used number of elements in a given array?
And I don't mean searching for an end of line character or implementing a circular buffer. I only expect between 5 and 25 Bytes in any given transaction.
Edit:- for omissions in original post (as requested)
Language C (via Atmel Studio)
8bit Bytes (non characters)
I don't know the meaning of 'strong-typed' and 'associative', but eventually it will be semi random bytes from a device and not fixed numbers like in a string
Fixed size declared array (ultimately volatile)
Thanks
The C standard generally does not provide any way for tracking or determining which or how many elements of an array are used.

How do I generate a string array in MatLab 2016b? [duplicate]

When trying to run my code, for example
for ii= 1:10
output(ii)=rand(3);
end
I get the error
In an assignment A(:) = B, the number of elements in A and B must be the same
or
In an assignment A(I) = B, the number of elements in B and I must be the same.
What does this error mean? What is the approach to get rid of it?
This error comes because you are trying to fill a variable chunk with more (or less) values than its size. In other words, you have a statement A(:)=B on where size(A(:)) is different to size(B).
In the example in the question, rand(3) returns a 3x3 matrix, however, output(ii) is just a single value (even if output may be bigger, output(ii) is just a single value of output), thus the value returned by rand(3) does not fit inside output.
In order to solve this problem, you need to change the the size of the output variable, so you have space to fit all the result.
There are 2 ways of doing this. One of them is by creating a Matrix that fits the return, e.g. output=zeros(3,3,10).
Then we can change the code to
for ii= 1:10
output(:,:,ii)=rand(3);
end
Alternatively, you can fill the output as a cell array. This is particularly useful when the return of the function changes sizes each time, e.g. rand(ii);
In that case, the following would work
for ii= 1:10
output{ii}=rand(ii);
end
It is probable that unlike in the example in the question, in the real case you do not know the size of what the output returns, thus you do not know which of the two options to use to fix your code.
On possible way of learning that, is activating debugging help when the code errors, by typing dbstop if error in your command line. This will trigger a debugging stop when MATLAB throws an error, and you can type size(rand(ii)) and size(output(ii)) to see the sizes of both.
Often, reading the documentation of the function being used also helps, to see if different sizes are possible.
That said, the second option, cell arrays, will always ensure everything will fit. However matrices are generally a faster and easier to use in MATLAB, thus you should aim for the matrix based solution if you can.

Initilalising an array with a sequence in Fortran

I am currently working on translating some legacy fortran code and I am having a hard time understanding a particular line in the code. The compiler also seems to find this line weird and throws out an error. From what I understand it is trying to initialize an array by sequencing 1 to 9 by increments of 1 and filling up the array matrix with this sequence in column major form.
program arrayProg
integer :: matrix(3,3), i , j !two dimensional real array
matrix = reshape((/1:9:1/), (/3,3/))
end program arrayProg
Is this syntax acceptable in fortran? (It has to be because it comes from the legacy code)
Am I misunderstanding what the line does?
The syntax is incorrect and such code cannot be compiled by a Fortran compiler, unless it implements some non-standard extension.
Intel Fortran accepts this:
A colon-separated triplet (instead of an implied-DO loop) to specify a range of values and a stride; for example, the following two array constructors are equivalent:
1 INTEGER D(3)
2 D = (/1:5:2/) ! Triplet form - also [1:5:2]
3 D = (/(I, I=1, 5, 2)/) ! implied-DO loop form
from Development Reference Guides:Array Constructors
(note: The links to Intel Documentation change frequently, if the link is dead, please notify me in the comment and try searching for "triplet form" and "array constructors")
To generate a sequence in a standard way one uses an implied do loop like
(/ (i, i=1,9) /)
the reshape then just changes the 1D array into a 2D one in column major order as you guessed.

In an assignment A(:) = B, the number of elements in A and B must be the same

When trying to run my code, for example
for ii= 1:10
output(ii)=rand(3);
end
I get the error
In an assignment A(:) = B, the number of elements in A and B must be the same
or
In an assignment A(I) = B, the number of elements in B and I must be the same.
What does this error mean? What is the approach to get rid of it?
This error comes because you are trying to fill a variable chunk with more (or less) values than its size. In other words, you have a statement A(:)=B on where size(A(:)) is different to size(B).
In the example in the question, rand(3) returns a 3x3 matrix, however, output(ii) is just a single value (even if output may be bigger, output(ii) is just a single value of output), thus the value returned by rand(3) does not fit inside output.
In order to solve this problem, you need to change the the size of the output variable, so you have space to fit all the result.
There are 2 ways of doing this. One of them is by creating a Matrix that fits the return, e.g. output=zeros(3,3,10).
Then we can change the code to
for ii= 1:10
output(:,:,ii)=rand(3);
end
Alternatively, you can fill the output as a cell array. This is particularly useful when the return of the function changes sizes each time, e.g. rand(ii);
In that case, the following would work
for ii= 1:10
output{ii}=rand(ii);
end
It is probable that unlike in the example in the question, in the real case you do not know the size of what the output returns, thus you do not know which of the two options to use to fix your code.
On possible way of learning that, is activating debugging help when the code errors, by typing dbstop if error in your command line. This will trigger a debugging stop when MATLAB throws an error, and you can type size(rand(ii)) and size(output(ii)) to see the sizes of both.
Often, reading the documentation of the function being used also helps, to see if different sizes are possible.
That said, the second option, cell arrays, will always ensure everything will fit. However matrices are generally a faster and easier to use in MATLAB, thus you should aim for the matrix based solution if you can.

Passing c arrays into fortran as a variable sized matrix

So, i've been commissioned to translate some fortran subroutines into C. These subroutines are being called as part of the control flow of a large porgram based primarily in C.
I am translating the functions one at a time, starting with the functions that are found at the top of call stacks.
The problem I am facing is the hand-off of array data from C to fortran.
Suppose we have declared an array in c as
int* someCArray = (int*)malloc( 50 * 4 * sizeof(int) );
Now, this array needs to be passed down into a fortran subroutine to be filled with data
someFortranFunc( someCArray, someOtherParams );
when the array arrives in fortran land, it is declared as a variable sized matrix as such:
subroutine somefortranfunc(somecarray,someotherparams)
integer somefarray(50,*)
The problem is that fortran doesn't seem to size the array correctly, becuase the program seg-faults. When I debug the program, I find that indexing to
somefarray(1,2)
reports that this is an invalid index. Any references to any items in the first column work fine, but there is only one available column in the array when it arrives in fortran.
I can't really change the fact that this is a variable sized array in fortran. Can anyone explain what is happening here, and is there a way that I can mitigate the problem from the C side of things?
[edit]
By the way, the fortran subroutine is being called from the replaced fortran code as
integer somedatastorage(plentybignumber)
integer someindex
...
call somefarray(somedatastorage(someindex))
where the data storage is a large 1d array. There isn't a problem with overrunning the size of the data storage. Somehow, though, the difference between passing the C array and the fortran (sub)array is causing a difference in the fortran subroutine.
Thanks!
Have you considered the Fortran ISO C Binding? I've had very good results with it to interface Fortran and C in both directions. My preference is to avoid rewriting existing, tested code. There are a few types that can't be transferred with the current version of the ISO C Binding, so a translation might be necessary.
What it shouldn't be that others suggested:
1. Size of int vs. size of Integer. Since the first column has the right values.
2. Row vs. column ordering. Would just get values in wrong order not segmentation faulted.
3. Reference vs value passing. Since the first column has the right values. Unless the compiler is doing something evil behind your back.
Are you sure you don't do this in some secret way?:
someCArray++
print out the value of the someCArray pointer right after you make it and right before you pass it. You also should print it out using the debugger in the fortran code just to verify that the compiler is not generating some temporary copies to help you.

Resources