Fortran multidimensional array syntax - fortran

Two quick syntax question
Would
real(4), ALLOCATABLE:: thing1(:,:)
Create a 2D array with 2 columns, an as of yet undefined number of rows, where each element is an array of 4 reals?
Secondly, would
real(4) box(3,3),versions,revert
Create two arrays of length 4, and 2D array of size 3x3 where each element is an array of length 4.

The short answer is no to both.
REAL(4) does not create an array of reals, it determines the KIND of REAL. I refer you to this question: Fortran 90 kind parameter to explain this.
Secondly, thing1(:,:) does not declare two columns, it declares two dimensions. The first being rows, the second being columns.
Your second would create a 3x3 array "box" of reals of kind == 4, which is typically precision "float" in C language.
I'm not sure what versions,revert is supposed to be.
Also, when creating an array, it is typical, and a little more explicit, to use the DIMENSION parameter as such:
REAL(4),ALLOCATABLE,DIMENSION(:,:,:) :: thing1
which can then be allocated later on as:
ALLOCATE(thing1(x,2,4)) Assuming you still wanted 2 columns, x rows, and an array of 4 in each location.

Related

How to create a n-dims array with unknown n and unknown length of dims in C++?

I have an array, int dims[n], where n means dims, for example n=3 means there are 3 dims.
dims[i] stores the corresponding length of the dim.
I want to create an array, arr[dims[0]][dims[1]][...][dims[n]], is there any good methods?
(dims[n] is not sure when the code is compiled, I am not able to define a certain format of arr)
I need the array for a function with argument double*, the function will read an n-dimensional array from file and could not put data into a 1-dimensional array (in this case, it will report an memory error and I am not able to reconfigure the function).

Strange parameter recuperation of an array

I am trying to understand some code that passes a multi dimension array to a function. But the prototype of this function intrigues me.
The program creates this "tab" variable:
#define N 8
float tab[N][N];
tab[0][0] = 2; tab[0][1] = 3; tab[0][2] = -1;
tab[1][0] = 3; tab[1][1] = 1; tab[1][2] = -4;
tab[2][0] = 1; tab[2][1] = 2; tab[2][2] = 3;
hello(tab);
And we have this function:
function hello(float mat[][N]) {
I dont understand why the hello function gets the tab variable with an empty [] and then with [N]. What does it change ? I don't understand... Why not tab[][] ?
The code seems to have been made by a good developer so I don't think that the N variable is here for no reason.
If you can explain me this, thanks for your time !
The original code
float tab[N][N];
defines an array of N by N. I'm not going to use row or column because how the array is oriented to the program logic may have no bearing on how the array is represented in memory. Just know that it will be a block of memory N*N long that can be access with mat[0..N-1][0..N-1]. The sizes are known and constant. When you define an array, it must know its size and this size cannot change. If you do not know the size, use a std::vector or a std::vector<std::vector<YOUR TYPE HERE>>
float tab[][];
is illegal because the size of the array is unknown. The compiler has no clue how much storage to allocate to the array and cannot produce a functional (even if flawed) program.
When you pass an array to a function such as
function hello(float mat[][N])
the array decays into a pointer. More info: What is array decaying? Once the array has decayed, the size of the first dimension is lost. To safely use the array you must either already know the size of the array or provide it as another parameter. Example:
function hello(float mat[][N], size_t matLen)
In question, the size is given as N. You know it's N and you can safely call
hello(mat);
without providing any sizing and simply use N inside the function as the bounds. N is not a devious magic number, but it could be given a more descriptive name.
You can also be totally explicit and
function hello(float mat[N][N])
and remove any ambiguity along with the ability to use the function with arrays of size M by N. Sometimes it's a trade-off worth making.
Let me explain a little bit "untechnically", but probably comprehensive:
Think float tab[ROW][COL] as a two dimensional array of floats, where "ROW" stands for the rows, and "COL" stands for the columns, and think that the array is mapped to memory one complete row following the other, i.e.
r0c0,r0c1,r0c2
r1c0,r1c1,r1c2
r2c0,r2c1,r2c2
for ROW=3 and COL=3. Then, if the compiler would have to find out where to write tab[2][1], it would have to take 2 times the size of a row + 1 (where row size is actually the number of columns COL). So for addressing a cell, it is relevant to know the size of the row, whereas within a row one has just to add the column index. Hence, a declaration like tab[][N] is sufficient, as N defines the number of columns - i.e. the size of a row - and lets the compiler address each cell correctly.
Hope it helps somehow.

Why is a hard coded width required when declaring a two dimensional array?

Pointers to pointers seem to be the only way to dynamically declare a two dimensional (or multidimensional) array besides doing the leg work myself and coding the pointer arithmetic to create a "fake" multidimensional array out of a one dimensional array. I understand this is the way it is but why?!
First of all, a two dimensional array is not the same as a pointer to a pointer.
While the latter is a pointer to an array of pointers (to arrays), the former looks like this in memory:
char v[2][3] = {{1,3,5},{5,10,2}};
Content: | 1 | 3 | 5 | 5 | 10 | 2
Address: v v+1 v+2 v+3 v+4 v+5
To access v[x][y], the compiler rewrites it as: *(v + y * WIDTH + x)
So as you can see, WIDTH (the second dimension specified) is needed to do the calculation.
You can omit the first dimension in function parameters since they are adjusted to pointers:
int f (int v[3][10])
is the same as
int f (int v[][10])
and the same as
int f (int (*v)[100])
(Since arrays are adjusted to pointers in function parameters)
but not the same as
int f (int *v[100])
(Since this is an array[100] (that is
adjusted to a pointer) of pointers)
Anyway I suggest you to use std::vector<std::vector<Type>> if you need a two-dimensional array.
Why is a hard coded width required when declaring a two dimensional array?
C++ arrays require their dimensions to be constant expressions. For 2D arrays (really arrays of arrays), this applies to both dimensions. There is no exception for the "width" or the "height".

How to convert one-dimensional array into two-dimensional without memory allocating?

I have a filled one-dimensional array double *vals as a class component with sizes Nn[0]*Nn[1]. I need to get 2-dimensional array **w (w[Nn[1]][Nn[0]]) without allocating new memory for it, e.g. i need to represent vals as 2-dimensional array.
Using g++ compiler i can make
double (* w)[Nn[0]] = (double (*)[Nn[0]])val;
But VS compiler or intel compiler don't allow to use non-constant expression as dimension array.
In general, I can just use element in initial vals array converting 2 int indices (i,j) of w[i][j] element into global index and do not declare w at all. But it would be great if it's possible to get 2-dimensional array w on initial memory (with compiling with intel compiler too). So is there any way to do it?
If wals is a class, you can implement your access operator to function as if it were 2D array.
walsdataType walsclass::operator()(int i, int j){return walsdata[i*N+j]};
with walsdata being the class member for storing data and N being the row length. You should do the bound checking as well.

Passing 2D array as an argument to a function which takes 1D array

Might sound like a stupid question:
Is it possible to pass 2D array as an argument to a function which takes 1D array
For example:
I have an array players[4][5] and also a function bestCard(), the header for that function looks something like this void bestCard(int arr[5]) <- this 5 is referring to the second dimension of array players
I want to pass players[4][...] in the function bestCard() in a way that the only last dimension is considered to be as an array i.e players[5]
Not sure if my question is comprehensive.
A 2D array is an array of 1D arrays.
In your case, that means player[i] is an array of five elements, for i between 0 and 3. So passing player[i] to your function will pass an array of 5 elements (or more strictly, a pointer to the first element of an array of 5 elements).
I am a beginner at C++, but as far as I know, it would not be possible to pass a 2-d array to your function bestCard(), assuming that you have not overloaded your bestCard() function to take different types of parameters.
Based on the information you have given to me in your question, I am guessing that there are 4 players, and each holds a hand of 5 cards.
If you want to pass bestCard() a single player's hand, you will have to write something like this:
bestCard(players[0]) // Determine the bestCard for the first player.
bestCard(players[1]) // Determine the bestCard for the second player.
...
bestCard(players[3]) // Determine the bestCard for the fourth player.
Even though players is in fact a 2-d array, each of the players[i] (for 0 < i < 4) evaluate to 1-dimensional arrays. Thus, bestCard() ought to be able to accept them as an argument.