How can I express the following codes written in C++ using IVF ?

How can I express the following codes written in C++ using IVF ?

Hi,

....

int *n1, b; 

float **n2, **n3;

n1= new float [b];

n2= new float *[b];

n3= new float *[b];

for(int j=0;j<b;j++)

{

ge>>n1[j];

n2[j]= new float [n1[j]];

n3[j]= new float [n1[j]];

for(int i=0;i<n[j];i++)

{

ge>>n2[j][i]>>n3[j][i];

}

}

...

I understand the code, it is the indirection and multiple indirection and allocation, right  ? I try to translate these codes into Fortran. Thanks

13 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

No, there's no indirection. You do have allocation of arrays of size read from input, and may have difficulty finding a textbook example.

A sane implementation might use a rank 1 array for ni, and rank 2 (double subscripted) arrays for n2 and n3. Depending on the requirements, those might be declared allocatable and the new[] operators which make arrays replaced by allocate. You don't need to create an array of pointers to make a rank 2 array in Fortran. If Insanity is a goal, it's certainly possible to adhere more literally to the model, using Fortran or even C pointers.

The data file might be opened as a stream file, if that seems appropriate. You would bear in mind the reversed order of double subscripts, and take your choice whether to allocate your arrays 0-based or default 1-based.

So, you mean that there is no indirection in these codes, then what is the indirection in C++ and fortran, is it -> and =>symbols, respectively ?

If I understand your comments, is the following trans-code my answer ?

....

integer b

type n_
integer,pointer,dimension(:) :: n1 !
end type n_

type(n_),allocatable,dimension(:,:) :: n1, n2

open(2,file='ge.dat',action='read')

read(2,*) b

allocate(n1(b))
allocate(n2(n1(b),n1(b)))
allocate(n3(n1(b),n1(b)))

do j=1,b

read(2,*) n1(j)

allocate(n2(n1(j),n1(j)))
allocate(n3(n1(j),n1(j)))

do i=1,n1(j)
read(2,*) n2(j,i), n3(j,i)
end do

end do

......

deallocate(n3)
deallocate(n2)
deallocate(n1)

But when I use these codes, I have errors:

Related to n1:

-An allocate/deallocate object must have the ALLOCATABLE or POINTER attribute.
-An ALLOCATE shape must not be given for a scalar object.
-This name has not been declared as an array or a function.
-The highest data type rank permitted is INTEGER(KIND=8).
-Constants and expressions are invalid in read-only I/O lists.

Related to n2:

-An object of a derived type that ultimately contains a pointer component must not appear in an input item list.

Related to n3:
-An object of a derived type that ultimately contains a pointer component must not appear in an input item list.

I do not expect that much errors, what is wrong with the code ?? Thanks.

Waiting for any idea, thanks...

jimdempseyatthecove's picture

Your array dimensions are not consistent. Possibly due to name typed incorrectly.
In your first allocate you have:
allocate(n1(b)) ! error
! The n1 above refers to the two dimensional array of type n_ and you are requesting an allocation using only one of the dimensions of:
! type(n_),allocatable,dimension(:,:) :: n1

The second and third allocations are referencing the same n1 using one dimension.

I suggest you rename one of the n1's then diagram (flow chart) what you want to do.
When the diagram is correct, then write the program to impliment the diagram.

Jim Dempsey

www.quickthreadprogramming.com
jimdempseyatthecove's picture

Quote:

emreka82 wrote:

Hi,

....

int *n1, b; 

float **n2, **n3;

n1= new float [b];

n2= new float *[b];

n3= new float *[b];

for(int j=0;j<b;j++)

{

ge>>n1[j];

n2[j]= new float [n1[j]];

n3[j]= new float [n1[j]];

for(int i=0;i<n[j];i++)

{

ge>>n2[j][i]>>n3[j][i];

}

}

...

I understand the code, it is the indirection and multiple indirection and allocation, right  ? I try to translate these codes into Fortran. Thanks

The above program is in error. "n1= new float [b];" is allocating an array of floats and assigning its pointer to the int* n1.

Jim Dempsey

www.quickthreadprogramming.com

Quote:

jimdempseyatthecove wrote:

Quote:

emreka82 wrote:

Hi,

....

int *n1, b; 

float **n2, **n3;

n1= new float [b];

n2= new float *[b];

n3= new float *[b];

for(int j=0;j<b;j++)

{

ge>>n1[j];

n2[j]= new float [n1[j]];

n3[j]= new float [n1[j]];

for(int i=0;i<n[j];i++)

{

ge>>n2[j][i]>>n3[j][i];

}

}

...

I understand the code, it is the indirection and multiple indirection and allocation, right  ? I try to translate these codes into Fortran. Thanks

The above program is in error. "n1= new float [b];" is allocating an array of floats and assigning its pointer to the int* n1.

Jim Dempsey

So, it is because the C code is wrong... The correct one is n1=new int[b];

Ah, I did not see your previous answer Jim. Let me quote a part of it:

>>>Your array dimensions are not consistent. Possibly due to name typed incorrectly.

b is an integer read from .dat file such as 1,2...

n1 refers to one dimensional array like n1[1]=50, n1[2]=65, in other words a scalar value.

n2 and n3 read data from a .dat file, for example x and y coordinates...

Am I missing something ?

Repeat Offender's picture

It's kind of late, but it seems to me that there was some indirection required because the program potentially created ragged arrays. Note that the row length of each row was read before the row data. Assuming unit number ge was opened beforehand and that we knew the number of rows, and further that the row length was on a separate line of input:

subroutine sub(ge,b)
use ISO_C_BINDING
implicit none
integer, intent(in) :: ge
integer(C_INT), intent(in) :: b
integer(C_INT) n1
type ragged
real(C_FLOAT), allocatable :: data(:)
end type ragged
type(ragged), allocatable :: n2(:), n3(:)
integer i, j

allocate(n2(0:b-1),n3(0:b-1))
do j = 0, b-1
read(ge,*) n1
allocate(n2(j)%data(0:n1-1),n3(j)%data(0:n1-1))
read(ge,*) (n2(j)%data(i),n3(j)%data(i),i=1,n1-1)
end do
end subroutine sub

Thanks for the reply, the solution you suggest is short and effective. But there are some questions in my mind about this coding:

Firstly, why do we need ISO_C_BINDING here ? Without C_INT, and C_FLOAT it runs the same, doesn't it ?

Secondly, when I see your ragged stype array, I thought of the "=>" sign and its use. Where can we use => ? I have an example in C++ for this:

1 class ccc {
2 ...
3 double *sq[2][4], *sff[2][4], ***stuff, ***sss, ***s_qo, s_a[2];
4
5 ccc *c[4];
6
7 ccc *nnn;
8
9 ...
10
11 }
12
13 double qd[4]={0.0, 0.0, 0.0, 0.0};
14 double s_qd[2][4];
15 int part, stp, stpm, stpnum;
16
17 delete nnn->sss;
18
19 for(int j=0;j<2;j++)
20 nnn->sss= new double **[2];
21
22
23 for(int j=0;j<2;j++)
24 nnn->sss[j]= new double *[stp];
25
26 for(int num=0;num<2;num++)
27 nnn->sss[j][i]= new double [4];
28
29
30 for(int i=0;i<4;i++)
31 nnn->sss[num][j][i]= 0.0;
32
33 for(int num=0; num<2; num++)
34 { for(int i=0; i<4; i++)
35 { nnn->sss[num][stpnum-1][i]=nnn->sss[num][stpnum-1][i] + *nnn->sss[num][i];
36 *nnn->sq[num][i]=nnn->sss[num][stpnum-1][i];
37
38 }
39 }
40
41 for(int num=0; num<2; num++)
42 { for(int i=0; i<4; i++) {
43 for(int j=0;j<2;j++){
44 nnn->sss[num][stpnum-1][i]=*nnn->sq[num][i];
45
46 ....
47
48 s_qd[part][i] =s_qd[part][i]+ nnn->c[j]->s_qo[num][stpnum-1][i] * *nnn->c[j]->s_a[num];
49
50
51
52 ......
53 *nnn->s_q[num][i]=nnn->s_qo[num][stpnum][i]-nnn->s_qo[num][stpnum-1][i];
54
55 }
56 }
57 }

I think that =>should be used in the lines 17, 20 such as:
17 deallocate(nnn=>sss)
20 allocate(nnn=>sss(0:1))

But in lines 24, 27 the arrays are the problem, I cannot figure them out in F90. Also the long lines 35, 36, 44, 48 and 53 are too complicated but once I figure out where to use % and => then I could solve the problem, right ? I will be glad if you answer my questions, thanks.

Repeat Offender's picture

The C++ code in your last post, besides being incomplete, has many errors, too many for me to discuss. But -> is an operator in C such that nnn->sss means (*nnn).sss, that is, dereference nnn so that we are now talking about the structure of type ccc that nnn points at rather than the address in memory of the structure, which is nnn's value, and look at the sss component of that structure, which is a pointer to a pointer to a pointer to double.
The => symbol in Fortran can be a rename operator in the sense of
use my_module, extra_crispy_name => original_name
or as the symbol in a pointer assignment,like
a => b
If b is a pointer, it means that pointer a points at the target of b; if b is a target, it means that pointer a points at b. Fortran needs a special symbol for this because
a = b
is already taken, meaning that the target a points at gets assigned the data of b (or the data of the target of b if b is a pointer).
So the -> operator should normally be replaced simply by % in Fortran because dereferencing is implict in most syntax containing a pointer, except for ALLOCATE, DEALLOCATE, ASSOCIATED, C_F_POINTER, pointer assignment(=>), and when passing a pointer as an actual argument to a pointer dummy argument. If your replacements for lines 17 and 20 don't cause your compiler to spit out a bunch of error messages, send in a bug report.

First of all, thank you for the quick answers Repeat Offender. Since I have a list of comments and questions about your comments, I numerize them:

1.

Quote:

Repeat Offender wrote:

The C++ code in your last post, besides being incomplete, has many errors........

I know, I only cut a part of a code and now I'm simply trying to understand the codes.

2.
Quote:

Repeat Offender wrote:

But -> is an operator in C such that nnn->sss means (*nnn).sss, that is, dereference nnn so that we are now talking about the structure of type ccc that nnn points at rather than the address in memory of the structure, which is nnn's value, and look at the sss component of that structure, which is a pointer to a pointer to a pointer to double.

The case between sss and nnn gives that:
class ccc {
double ***sss
}

7 ccc *nnn;

17 delete nnn->sss;
20 nnn->sss= new double **[2];
24 nnn->sss[j]= new double *[stp];
27 nnn->sss[j][i]= new double [4];
31 nnn->sss[num][j][i]= 0.0;
35 { nnn->sss[num][stpnum-1][i]=nnn->sss[num][stpnum-1][i] + *nnn->sss[num][i];
36 *nnn->sq[num][i]=nnn->sss[num][stpnum-1][i];
44 nnn->sss[num][stpnum-1][i]=*nnn->sq[num][i];

From the above, I understand that sss is a pointer inside a structure and nnn is the derived type of class ccc. Then when nnn->sss shows up then nnn points to the both sss inside the class and the sss's targets ?

In line 17 as I understand deallocate(nnn%sss) is the simple solution, but does it give the same answer when one of it is also an array ?

In lines 24, 27, 31 the problem can be solved with the n1 and data relation in the previous code, can it ?

The problem that really confuses me is the use of both * and -> inside a line such as in line 35, 36, and 44. I really messed up in here....

3.

Quote:

Repeat Offender wrote:

The => symbol in Fortran can be a rename operator in the sense of
use my_module, extra_crispy_name =>; original_name
or as the symbol in a pointer assignment,like
a => b
If b is a pointer, it means that pointer a points at the target of b; if b is a target, it means that pointer a points at b. Fortran needs a special symbol for this because
a = b
is already taken, meaning that the target a points at gets assigned the data of b (or the data of the target of b if b is a pointer).

Then C uses the equal (=) sign such as in lines 35, 36 and 53 right ? and Fortran should use the arrow (=>) in that cases.

Quote:

Repeat Offender wrote:

So the -> operator should normally be replaced simply by % in Fortran because dereferencing is implict in most syntax containing a pointer, except for ALLOCATE, DEALLOCATE, ASSOCIATED, C_F_POINTER, pointer assignment(=>), and when passing a pointer as an actual argument to a pointer dummy argument. If your replacements for lines 17 and 20 don't cause your compiler to spit out a bunch of error messages, send in a bug report.

They surely have bunch of errors, but I only write down here, sorry for that...The correct one must be %.

4. By the way I didn't understand the ISO_C_BINDING thing also...

Glad to have this discussion and learn lots of things, thanks again. Sincerely yours,

Emre

Quote:

Repeat Offender wrote:

..............

Also, as I saw in Metcalf's notes http://w3.pppl.gov/~hammett/comp/f90tut/f90.tut6.html , arrays of pointers in fortran are not the same as C pointers. I will try to handle the C codes (above mentioned) by defining a derived data type with a pointer as its sole component...Way too time consuming.

Login to leave a comment.