Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Need help with function definition

WSinc
New Contributor I
964 Views
Hello -

Mu understanding is that I can define a function with an ARRAY output.

However, I had trouble with this - - -
It wants an EXPLICIT interface, but the INTERFACE topic gives me no clue as to how to
set this up.

Here is an example of what I am trying to do:


integer*2 f(127),divis

f=divis(15625,127)

end

function divis(n,p)

! returns first P divisors of N

integer*2 divis(*)

integer*4 n

integer*2 P

ip=0

do ix=2,n-1

if(mod(n,ix) /=0 )cycle
ip=ip+1

ivis(ip)=ix
if(ip==p)return
enddo

end

I am BOT trying to FACTOR the number, just return divisors.
The actual thing is more complicated, but I just want a simple
example of how to set this up.

maybe you CANNOT have an array output?
Any clues?

0 Kudos
1 Solution
Steven_L_Intel1
Employee
964 Views
That's because 1 is a "default integer" (usually INTEGER(4)), and the rules of Fortran expression evaluation say that if you add two integers of different kinds, the lower kind is converted to the higher kind before addition and the result kind is the higher one. You could use N+1_2 or INT(N+1,2). Or decide not to use small integers if you don't need them.

Our compiler will not warn on integer literals such as 127 by default, when they don't match the associated dummy argument, but you'll get a standards warning if you have that enabled.

View solution in original post

0 Kudos
5 Replies
Steven_L_Intel1
Employee
964 Views
Yes, you can do this, as long as you can pull yourself away from F77. For example:

[plain]integer*2 f(127) f=divis(15625,127_2) print *, f contains function divis(n,p) ! returns first P divisors of N integer*2 P integer*2 divis(p) integer*4 n divis = 0 ip=0 do ix=2,n-1 if(mod(n,ix) /=0 )cycle ip=ip+1 divis(ip)=ix if(ip==p)return enddo end function divis end[/plain] Some things to note. I used CONTAINS here to make divis a contained procedure - this creates an explicit interface. You could also put divis in a module to the same effect. You don't declare the function in the caller as a variable, it has to have an explicit interface.

You can't use (*) as a function return dimension, it has to be an expression of some kind (could also be an allocatable array that gets allocated in the function). Here I made it an "adjustable" array whose dimension depends on the argument p, as that's what you wanted. I also moved the declaration of p up to before that of the result because otherwise it would not be legal Fortran (as p has implicit real type). I fixed a few typos, added inititialization of the result array and a PRINT of the result. Lastly, I gave the 127 a "kind" as otherwise you have a mismatch. Did you really want to use integer*2 here? Why?
0 Kudos
WSinc
New Contributor I
964 Views

I can see how this would work, given that you have the FUNCTION inside the same file as
the calling program. But I wanted to have it independent if possible so I can use it in more than one place.

The problem this causes: Is that DIVIS has to be typed separately in the calling routine, so now there is confusion between the OUTPUT type and the INPUT arguments. So I can't use a TYPE statement for DIVIS, at least not in the regular manner. Do I have to have an INTERFACE statement then, or some other trick?

I noticed that you only have one input argument when you type it inside the function. Why does that work?
This code does not compile, but I wanted to give an example of what I am trying to do.

How do I tell the calling routine how to interface with it, then?

Sorry for the typos, but the darn type face is so smal, sometimes I can't read it.


integer*2 f(127)

f=divis(10000,127_2)

print *, f

read(*,*)

end

! IN A SEPARATE PLACE

function divis(n,p)

! returns first P divisors of N

integer*2 P

integer*2 divis(p)

integer*4 n

divis = 0

ip=0

do ix=2,n-1

if(mod(n,ix) /=0 )cycle

ip=ip+1

divis(ip)=ix

if(ip==p)return

enddo

end function divis

0 Kudos
Steven_L_Intel1
Employee
964 Views
As I suggested, put divis in a module. So you would have:

[plain]module my_routines contains function divis .... ... end function divis end module my_routines[/plain] Then anywhere you want to call divis, add just after the SUBROUTINE, FUNCTION or PROGRAM statement:

use my_routines

You can of course change "my_routines" to anything you want that isn't the same as a routine or COMMON name.

The USE will establish the explicit interface.
0 Kudos
WSinc
New Contributor I
964 Views
OK, I will try that -

I did try putting it in a module, but I wasn't doing it right - - -
Incidentally, I noticed you matched up the literals, by
saying 127_2, but I thought the compiler was supposed to do that for us?

It does not match up expressions, however.

Example: if you say N, and N is is integer*2 it will match them, but if
you say N+1 it does NOT match the types.

Why wouldn't it be the same size integer?
0 Kudos
Steven_L_Intel1
Employee
965 Views
That's because 1 is a "default integer" (usually INTEGER(4)), and the rules of Fortran expression evaluation say that if you add two integers of different kinds, the lower kind is converted to the higher kind before addition and the result kind is the higher one. You could use N+1_2 or INT(N+1,2). Or decide not to use small integers if you don't need them.

Our compiler will not warn on integer literals such as 127 by default, when they don't match the associated dummy argument, but you'll get a standards warning if you have that enabled.
0 Kudos
Reply