Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

programming challenge!

rahzan
New Contributor I
1,140 Views
I have three routines: call them R1, R2, and R3.
R1 needs to send data to R3 which processes them and returns results.
However, R2 is like a traffic cop and regulates the operation
(e.g. breaks the input data into small pieces and spoon-feeds it to R3, concatenates the
data output from R3 etc.).

The data are in the form of assumed shape arrays which go back and forth between routines.
This allows the interface to the routines to remain fixed.

What is desired is to allow arbitrary data types (whose components are arrays ) to be passed.
The size of arrays are also not known until run time which is currently handled by assumed sizing.

Now it gets wierd: R1 is in VB and is the client to R2 which is a CVF com-server. R3 is a CVF
dll whose source is written by R1 and compiled at runtime. So the type definition
can be declared in R3 but R2 will not know about it.

The question is: how should we design the interfaces?

A possible crude method is to have an interface for every native-type of component in the defined
type. But then how is one to tell which instance of a type and which element of the type is a
given input aimed at?

I wonder if there are clever ideas that anyone can think of, say by using pointers, etc.

Thanks in adv.
Tim
0 Kudos
5 Replies
Jugoslav_Dujic
Valued Contributor II
1,140 Views
Tim, could you post an example (even if it's syntactically incorrect or in pseudo-code)? I do follow you to a certain extent, but "One picture is worth a thousand words".

Jugoslav
0 Kudos
billaustralia
Beginner
1,140 Views
Any fee?
0 Kudos
rahzan
New Contributor I
1,140 Views
Thanks Jugoslav,
Here is a schematic of R2 and R3. remember that the sizes are known and passed by R1 which we explicitly set here. Also that R3 canbe written and compiled at runtime by R1.

I am only illustrating the extraction of the data from R3 by R2 which only is told how many of each type and the size of each array at run time.

R3 can refer to components of the each type by name nicely, and we index the arrays of each type, and use a pointer to do the book keeping and later to point to that
array to do the extraction.

The problem is that the compiler says the bookkeeping pointer array is NOT a pointer at(*) marks.

!Routine-3
!==============
Module R3
real(4),Pointer:: allReal4s(:,:)
integer(2),Pointer:: allInt2s(:,:)

type tester
real(4), allocatable:: rPart1(:),rPart2(:)
integer(2), allocatable:: iPart1(:)
end type tester
type(tester) sample

contains
subroutine declare
! the contents of this routine is written and compiled
! by R1 just before R1 calls R2
allocate(sample.rPart1(5)); sample.rPart1=0.
allReal4s(1,:)=>sample.rPart1(1:5) (*)
allocate(sample.rPart2(6)); sample.rPart2=0.
allReal4s(2,:)=>sample.rPart2(:) (*)
allocate(sample.iPart1(7)); sample.iPart1=0
allInt2s(1,:)=>sample.iPart1(:) (*)

!simulate computation
sample.rPart1=1.2
sample.rPart2=1.5
sample.iPart1=6
end subroutine declare

!generic extraction routines called by R2
!n is the "serial index" of the array whose name
!is not known by R2.
subroutine extractReal4 (x,xs,n)
integer, intent(in):: xs
real(4), intent(inout):: x(xs)
x(1:xs)=allReal4s(1:xs,n)
end subroutine extractReal4

subroutine extractInt2 (x,xs,n)
integer(4), intent(in):: xs
integer(2), intent(inout):: x(xs)
x(:)=allInt2s(:,n)
end subroutine extractInt2

end Module R3

!Routine-2
!==============
use R3
real(4):: FirstReal4(5),secondReal4(6)
integer(2):: firstInt2(7)

call declare
call extractReal4(FirstReal4,5,1)
call extractReal4(SecondReal4,6,2)
call extractInt2(FirstInt2,5,1)
pause
end

0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,140 Views
I (think I) see.

You cannot have an array of pointers in Fortran. However, you can emulate it using a derived type containing a pointer:
TYPE R4POINTER
   REAL, POINTER:: p
END TYPE R4POINTER
TYPE I2POINTER
   INTEGER(2), POINTER:: p
END TYPE I2POINTER

TYPE T_BOOKKEEPING
  TYPE(R4POINTER), POINTER:: r4Data(:)
  TYPE(I2POINTER), POINTER:: i2Data(:)
END TYPE T_BOOKKEEPING
TYPE T_BOOKKEEPING:: BK
...
ALLOCATE(BK%r4Data(7))
ALLOCATE(BK%i2Data(1))
!----------
SUBROUTINE Declare
...
allocate(sample.rPart1(5)); sample.rPart1=0.
BK%r4Data(1)%p => sample.rPart1(1:5)
allocate(sample.rPart2(5)); sample.rPart2=0.
BK%r4Data(2)%p => sample.rPart2(1:5)
...
END SUBROUTINE Declare
!----------
subroutine extractReal4 (x,xs,n)
integer, intent(in):: xs
real(4), intent(inout):: x(xs)
x(1:xs)=BK%rData(n)%p(1:xs)
end subroutine extractReal4


Jugoslav
0 Kudos
rahzan
New Contributor I
1,140 Views
Thanks,
That should work, the larger implementation will take some effort.

I have found another way using the "cvf pointer(ptr,ptr_val)" but it runs into a strange porblem in that integer values at ptr have a ptr_val of zero, but real4 work ok. e.g.

I will post the sample code in another thread so as to not clutter this one. If you get a chance look at it.

thanks again,
Tim
0 Kudos
Reply