Reputation: 11
I have some Fortran code that contains the following line:
IF((IFIX(X).AND.6).NE.0)
THEN
The value of X is specified using NAMELIST and READ statements:
NAMELIST/XYZ/ ….,X,……
.
.
.
READ(5,XYZ)
The variable X can take on the following values:
0.0
1.0
2.0
3.0
4.0
6.0
Attempting to compile this program (filename abcd.f) using GCC Fortran (gfortran), thus:
$gfortran -o abcd abcd.f
generates the following error:
IF((IFIX(X).AND.6).NE.0)
1
Error: Operands of logical operator '.and.' at (1) are INTEGER(4)/INTEGER(4)
My understanding of LOGICAL variables and operators is that a numerical value of 0 translates to FALSE and non-zero values translate to TRUE. If both values of the .AND. comparison are TRUE, then the result is TRUE, otherwise the result is FALSE.
Therefore, I have come up with the following value table:
X IFIX(X) IFIX(X).AND.6 (IFIX(X).AND.6).NE.0) result
0.0 0 -> FALSE FALSE -> =0 FALSE exit IF without executing THEN
1.0 1 -> TRUE TRUE -> ≠0 TRUE execute THEN
2.0 2 -> TRUE TRUE -> ≠0 TRUE execute THEN
3.0 3 -> TRUE TRUE -> ≠0 TRUE execute THEN
4.0 4 -> TRUE TRUE -> ≠0 TRUE execute THEN
6.0 6 -> TRUE TRUE -> ≠0 TRUE execute THEN
So, I do not see any fault with the logic (leaving aside the question of whether or not this is the best way to accomplish the intended result - I am dealing with legacy code to which I want to make the minimum of changes).
Can anyone explain why I am getting this error message?
Upvotes: 0
Views: 4244
Reputation: 11
This problem was finally solved as follows:
LOGICAL IX,VAL0,VAL6
.
.
.
IX = IFIX(X)
VAL0 = 0
VAL6 = 6
IF((IX .AND. VAL6) .NEQV. VAL0) THEN
This seems rather convoluted and unnecessary, but it preserves the basic structure of the original code. It does give warning messages regarding the conversion from integer to logical, but it does compile successfully.
This is a good illustration of the looser requirements in earlier versions of Fortran, which were tightened up in later standards.
Thanks to all for your suggestions.
Upvotes: 0
Reputation:
The problem in this case is the non-standard use of .AND.
In the standard, this is only defined if both operators are LOGICAL
; in your case, they are both INTEGER
, which is what the compiler tells you.
There are a couple of gotchas to watch out for:
First, can you be really sure that the floating point values are exactly 0.0, 1.0, ... etc? If they were not obtained by setting a variable, but by a calculation with potential roundoff error, a result could be e.g. 0.999999. IFIX
(an archaic form of INT
) will then round down, which may or may not be what was intended.
Second, check the documentation of the old compiler (if still available) or try to follow the logic of the program to understand what the non-standard use of .AND.
signified. Did it mean logical or bitwise and (in C parlance, was it &&
or &
)? If it was bitwise, the program logic would be different from what you outlined above. You can use the standard IAND
intrinsic for bitwise operations.
Upvotes: 1
Reputation: 732
IFIX returns integers if greater than 1, if less than 1 then returns 0.
Would (X.EQV.0).NE.1 do what you want?
Upvotes: 0