- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The examples of how to define your own binary operator in the
language reference (example operators .BAR. and "+") omit to show
where you put the executable lines of code that perform the
function (section 8.9.4). I have tried placing the executable lines of
code in every conceivable place
(e.g. between "FUNCTION MYFUNC(A,B)"
and "END FUNCTION MYFUNC" , which seems logical)
but the compiler kicks it out or says I haven't defined the operator.
Lets look at the .BAR. example provided:
INTERFACE OPERATOR(.BAR.)
FUNCTION BAR(A_1)
INTEGER, INTENT(IN) :: A_1
INTEGER :: BAR
END FUNCTION BAR
END INTERFACE
Then it is said you invoke the function when you write
I=4 + (.BAR.B)
But nowhere is it defined what .BAR. does!
Does it square B? Does it do a 1's complement of B?
There has a place to put the executable code that defines what it
does, but the compiler will not accept executable code in an
INTERFACE block, only declarations.
Can anyone provide a clue?
Thanks,
Paul Dent
language reference (example operators .BAR. and "+") omit to show
where you put the executable lines of code that perform the
function (section 8.9.4). I have tried placing the executable lines of
code in every conceivable place
(e.g. between "FUNCTION MYFUNC(A,B)"
and "END FUNCTION MYFUNC" , which seems logical)
but the compiler kicks it out or says I haven't defined the operator.
Lets look at the .BAR. example provided:
INTERFACE OPERATOR(.BAR.)
FUNCTION BAR(A_1)
INTEGER, INTENT(IN) :: A_1
INTEGER :: BAR
END FUNCTION BAR
END INTERFACE
Then it is said you invoke the function when you write
I=4 + (.BAR.B)
But nowhere is it defined what .BAR. does!
Does it square B? Does it do a 1's complement of B?
There has a place to put the executable code that defines what it
does, but the compiler will not accept executable code in an
INTERFACE block, only declarations.
Can anyone provide a clue?
Thanks,
Paul Dent
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Paul,
INTERFACE block is function declaration, i.e. the place where you tell compiler how the specific function is called; the same holds for INTERFACE OPERATOR - you tell compiler to "replace" operator .BAR. in the current procedure with a specific function. The definition, i.e. the body of the function is somewhere else.
So, in non-MODULE style of programming, INTERFACE OPERATOR should be placed in the declaration part of the routine that uses the operator .BAR.
If it's needed in several places, you can put it in an INCLUDE (.fi) file.
FUNCTION BAR itself can be placed in any source file of the project.
Otherwise, if you put function BAR in a module, the INTERFACE OPERATOR should be placed in declaration part of the module (above CONTAINS statement). The full description in the INTERFACE is not needed; use MODULE PROCEDURE instead:
HTH
Jugoslav
INTERFACE block is function declaration, i.e. the place where you tell compiler how the specific function is called; the same holds for INTERFACE OPERATOR - you tell compiler to "replace" operator .BAR. in the current procedure with a specific function. The definition, i.e. the body of the function is somewhere else.
So, in non-MODULE style of programming, INTERFACE OPERATOR should be placed in the declaration part of the routine that uses the operator .BAR.
If it's needed in several places, you can put it in an INCLUDE (.fi) file.
FUNCTION BAR itself can be placed in any source file of the project.
Otherwise, if you put function BAR in a module, the INTERFACE OPERATOR should be placed in declaration part of the module (above CONTAINS statement). The full description in the INTERFACE is not needed; use MODULE PROCEDURE instead:
MODULE FOO INTERFACE OPERATOR (.BAR.) MODULE PROCEDURE BAR END INTERFACE CONTAINS FUNCTION BAR(A_1) ...(do something) END FUNCTION BAR END MODULE FOO
HTH
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your input Jugoslav. What you suggest does work, but only
when the function and the operator are defined to operate on standard
variable types, and does not work for user-defined variable type.
I e-mailed you the following example, where all I did was change the
variable type from REAL A(2) to
TYPE ARRAY2
REAL C(2)
END TYPE ARRAY2
TYPE(ARRAY2) A,B
Here is the programme that works:
C*************MAIN PROGRAM********************
C****DEFINE OPERATOR INTERFACE*****
INTERFACE OPERATOR(.MULT.)
FUNCTION MUL(A,B)
REAL,INTENT(IN) :: A(2),B(2)
REAL MUL(2)
END FUNCTION MUL
END INTERFACE
REAL A(2),B(2),X(2)
A(1)=1.0
A(2)=0.5
B(1)=2.0
B(2)=0.6
C USE THE OPERATOR
X=A.MULT.B
C AND PRINT THE RESULT WHICH SHOULD BE 2.0, -0.3
WRITE(*,*)X
STOP
END
C**CODE THAT IMPLEMENTS THE OPERATOR .MULT.***
FUNCTION MUL(A,B)
REAL A(2),B(2),MUL(2),X(2)
X(1)=A(1)*B(1)
X(2)=-A(2)*B(2)
MUL=X
END FUNCTION MUL
and here is the version that does not compile:
C*******************MAIN PROGRAM********************
C**DECLARE SOME VARIABLES OF A USER-DEFINED TYPE**
TYPE ARRAY2
REAL C(2)
END TYPE ARRAY2
TYPE(ARRAY2) A,B,X
C**DECLARE THE INTERFACE FOR THE OEPRATOR .MULT.***
INTERFACE OPERATOR(.MULT.)
FUNCTION MUL(A,B)
TYPE ARRAY2
REAL C(2)
END TYPE ARRAY2
TYPE(ARRAY2),INTENT(IN) :: A,B
TYPE(ARRAY2) MUL
END FUNCTION MUL
END INTERFACE
C***NOW TRY TO USE THE DEFINED OPERATOR***
A.C(1)=1.0
A.C(2)=0.5
B.C(1)=2.0
B.C(2)=0.6
X=A.MULT.B
WRITE(*,*)X
STOP
END
C**CODE THAT IMPLEMENTS THE OPERATOR .MULT.***
FUNCTION MUL(A,B)
TYPE ARRAY2
REAL C(2)
END TYPE ARRAY2
TYPE(ARRAY2) A,B,MUL,X
X.C(1)=A.C(1)*B.C(1)
X.C(2)=-A.C(2)*B.C(2)
MUL=X
END FUNCTION MUL
Surely the compiler lets us define operators for operating on user
defined types? That's the whole point! What am I missing?
Paul
when the function and the operator are defined to operate on standard
variable types, and does not work for user-defined variable type.
I e-mailed you the following example, where all I did was change the
variable type from REAL A(2) to
TYPE ARRAY2
REAL C(2)
END TYPE ARRAY2
TYPE(ARRAY2) A,B
Here is the programme that works:
C*************MAIN PROGRAM********************
C****DEFINE OPERATOR INTERFACE*****
INTERFACE OPERATOR(.MULT.)
FUNCTION MUL(A,B)
REAL,INTENT(IN) :: A(2),B(2)
REAL MUL(2)
END FUNCTION MUL
END INTERFACE
REAL A(2),B(2),X(2)
A(1)=1.0
A(2)=0.5
B(1)=2.0
B(2)=0.6
C USE THE OPERATOR
X=A.MULT.B
C AND PRINT THE RESULT WHICH SHOULD BE 2.0, -0.3
WRITE(*,*)X
STOP
END
C**CODE THAT IMPLEMENTS THE OPERATOR .MULT.***
FUNCTION MUL(A,B)
REAL A(2),B(2),MUL(2),X(2)
X(1)=A(1)*B(1)
X(2)=-A(2)*B(2)
MUL=X
END FUNCTION MUL
and here is the version that does not compile:
C*******************MAIN PROGRAM********************
C**DECLARE SOME VARIABLES OF A USER-DEFINED TYPE**
TYPE ARRAY2
REAL C(2)
END TYPE ARRAY2
TYPE(ARRAY2) A,B,X
C**DECLARE THE INTERFACE FOR THE OEPRATOR .MULT.***
INTERFACE OPERATOR(.MULT.)
FUNCTION MUL(A,B)
TYPE ARRAY2
REAL C(2)
END TYPE ARRAY2
TYPE(ARRAY2),INTENT(IN) :: A,B
TYPE(ARRAY2) MUL
END FUNCTION MUL
END INTERFACE
C***NOW TRY TO USE THE DEFINED OPERATOR***
A.C(1)=1.0
A.C(2)=0.5
B.C(1)=2.0
B.C(2)=0.6
X=A.MULT.B
WRITE(*,*)X
STOP
END
C**CODE THAT IMPLEMENTS THE OPERATOR .MULT.***
FUNCTION MUL(A,B)
TYPE ARRAY2
REAL C(2)
END TYPE ARRAY2
TYPE(ARRAY2) A,B,MUL,X
X.C(1)=A.C(1)*B.C(1)
X.C(2)=-A.C(2)*B.C(2)
MUL=X
END FUNCTION MUL
Surely the compiler lets us define operators for operating on user
defined types? That's the whole point! What am I missing?
Paul
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Paul,
The source you posted is almost good; I thought it would have worked, but it didn't. The problem is in the scope of declaration of type ARRAY2; it isn't "seen" the same within PROGRAM and INTERFACE. Here's the correct code that works (it looks as if the MODULEs have to be involved; but then, generic operators are also Fortran-90 stuff). Perhaps someone more versed in standards issues might explain why the code you posted does not work:
Regards
Jugoslav
The source you posted is almost good; I thought it would have worked, but it didn't. The problem is in the scope of declaration of type ARRAY2; it isn't "seen" the same within PROGRAM and INTERFACE. Here's the correct code that works (it looks as if the MODULEs have to be involved; but then, generic operators are also Fortran-90 stuff). Perhaps someone more versed in standards issues might explain why the code you posted does not work:
MODULE OVRMOD TYPE ARRAY2 REAL C(2) END TYPE ARRAY2 END MODULE OVRMOD !=============================== PROGRAM OVERLOAD USE OVRMOD TYPE(ARRAY2) A,B,X !**DECLARE THE INTERFACE FOR THE OEPRATOR .MULT.*** INTERFACE OPERATOR (.MULT.) FUNCTION MUL(A,B) RESULT(F) USE OVRMOD TYPE(ARRAY2),INTENT(IN) :: A,B TYPE(ARRAY2) F END FUNCTION MUL END INTERFACE !***NOW TRY TO USE THE DEFINED OPERATOR*** A.C(1)=1.0 A.C(2)=0.5 B.C(1)=2.0 B.C(2)=0.6 X=A.MULT.B WRITE(*,*)X STOP END !=============================== FUNCTION MUL(A,B) RESULT(F) USE OVRMOD TYPE(ARRAY2),INTENT(IN) :: A,B TYPE(ARRAY2) F DO I=1,2 F.C(I)=A.C(I)*B.C(I) END DO END FUNCTION MUL
Regards
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your help, Jugoslav. It works now - why it is essential to use
the MODULE construction is a puzzle, and it is very fussy about the order
of things.
My next problem is that I can write user defined operators for doing
arithmetic on user defined types that work one a time, i.e I can write
F=A*B
F=A+B
F=A-B
F=F+A etc
and they all work according to the function definitions I have provided
However, if I write
F=A*B+C
which I hoped to do, or even
F = (A*B)+C
I get garbage, and the reason seems to be that the compiler is not
allocating the right "shape" of storage for the intermediate result of A*B
Do you know if one is supposed to be able to write expressions of
any complexity, with nested parentheses etc with user-defined
operators, or not?
Thanks,
Paul
the MODULE construction is a puzzle, and it is very fussy about the order
of things.
My next problem is that I can write user defined operators for doing
arithmetic on user defined types that work one a time, i.e I can write
F=A*B
F=A+B
F=A-B
F=F+A etc
and they all work according to the function definitions I have provided
However, if I write
F=A*B+C
which I hoped to do, or even
F = (A*B)+C
I get garbage, and the reason seems to be that the compiler is not
allocating the right "shape" of storage for the intermediate result of A*B
Do you know if one is supposed to be able to write expressions of
any complexity, with nested parentheses etc with user-defined
operators, or not?
Thanks,
Paul
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Derived type definitions have to either come from the same source (USE or host association) or be SEQUENCE derived types and be otherwise identical. It seems to me much simpler to define the type in a module and use the module where the type is required; you don't have to maintain several identical derived type definitions throughout your code. Look in the online docs under Derived type statement, Rules and Behavior. The problem you may be having with statements like F = A*B+C is that the output of your binary multiplication operator isn't the same as the left input to your addition operator. This should give you errors at compile time rather than garbage, however. Now, if the object in question are arrays rather than derived types, you could have a problem if the lengths aren't conformable. You could check this possibility by making the inputs assumed shape arrays and then comparing their lengths within the function.
![](/skins/images/7B0AB6865064EAE32B30EC9A4E94B48A/responsive_peak/images/icon_anonymous_message.png)
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page