开发者

How do I handle logical statements being applied to integer values with gfortran?

开发者 https://www.devze.com 2023-02-03 03:16 出处:网络
I\'m rewriting some code to make a program compile with the gfortran compiler as opposed to ifort compiler I usually use.The code follows:

I'm rewriting some code to make a program compile with the gfortran compiler as opposed to ifort compiler I usually use. The code follows:

_Subroutine SlideBits (WORD, BITS, ADDR) 

Implicit None  
Integer(4) WORD  
Integer(4) BITS  
Integer(4) ADDR  
Integer(4) ADDR1 

ADDR1 = 32 - ADDR  
WORD = (WORD .And. (.Not.ISHFT(1,ADDR1))) .Or. ISHFT(BITS,ADDR1)  

End_ 

When I compile the above code using the gfortran compiler, I recieve this error:

WORD = (WORD .And. (.Not.ISHFT(1,ADDR1))) .Or. ISHFT(BITS,ADDR1) 

Error: Operand of .NOT. operator at (1) is INTEGER(4)  

All three of the variable开发者_高级运维s coming into the subroutine are integers. I've looked around a bit and the gfortran wiki states that the gfortran compiler should be able to handle logical statments being applied to integer values. Several other sites I've visited either quote from the gnu wiki or agree with it. This is the first time I've seen this error as the Intel Fortran compiler (ifort) I normally use compiles cleanly.


The comments/answers above "may .Not. be" the correct responses, depending on your ultimate objective.

The likely purpose of that "WORD = .." statement is .NOT. to arrive at a boolean/logical result, but rather to obtain a kind of integer enumerator.

To see this, first "ignore" the bit shifting (iShift() etc), and just look at something like IntR = Int1 .Or. Int2. This will produce a "proper" integer result. The value will depend on not only the values of the int's, but also on their declared "type" (e.g. Integer(1), Integer(2), etc)

That is, the resulting value of WORD will be a "proper" integer; something like "33504" .. or whatever, (likely) .NOT. a 0/1 or -1/0 or .True./.False. etc

If you replace = Int1 .Or. Int2 with = (Int1 /= 0) .Or. (Int2 /= 0) ... you will get an "integer logical" (i.e. 0/1 etc) and WILL NOT produce the desired enumerator ... if that is what you are looking for.

The .Or. on two Int's is a kind of bit-wise addition that produces a new num based on how the bits align/word size etc.

e.g. 3 == 011, 2 = 010 ... so, 3 .Or. 2 ==> 011 = 3
e.g. 3 == 011, 5 = 101 ... so, 3 .Or. 5 ==> 111 = 7
e.g. 5 == 101, 5 = 101 ... so, 5 .Or. 5 ==> 101 = 5

... similarly the .And. provides a kind of multiplication.

This technique is sometimes used to create enumerators somewhat like the use of powers of two (1,2,4,8...) are used to assign a value. Then, any sum of those values can be decomposed, for example, into its constituent elements. For instance, if a(1) = 2, and a(2) = 8, then the sum 10 can be decomposed to show the selections were the 1st and 4th elements of (1,2,4,8,...) etc.

It may help conceptualise this by noting that bit-shifting is like multiplying by 2 (for left shift) and dividing by 2 (for right shift).

BTW, you don't need to restrict to Fortran for this. Whack it into a VBA function and see the result in your spreadsheet VBA does not have bit shift intrinsics, but they are available ... in any case it will demonstrate the Int1 .Or. Int2 behaviour even without bit shifting, such as

Function TwoIntsOr(Int1 As Long, Int2 As Long) As Long
    '
    TwoIntsOr = Int1 Or Int2
    '
End Function

-- .Or. in Fortran

Function TwoIntsOr(Int1, Int2)
    Integer     :: TwoInstOr
    Integer, Intent(In) :: Int1, Int2
    !
    TwoIntsOr = Int1 .Or. Int2
    !
End Function

).


It is not standard Fortran to apply logical/boolean operators to integer variables. If the goal is a boolean result, the ideal solution would be to convert the types to logical. If, as it appears from casual examination, the code is really doing bit-wise operations, then it would be better to use the IAND and IOR intrinsic functions.


gfortran is expecting booleans for the logical operators and the code is providing integers. Use comparisons with zero instead of logical operators.

WORD = ((WORD /= 0) .And. (ISHFT(1,ADDR1) == 0)) .Or. (ISHFT(BITS,ADDR1) /= 0)

gfortran and ifort use different representations for .true. and .false. values, so it's best to stick to booleans when that's what the code needs. In a conversion from ifort to gfortran I got bit by the former representing .true. as -1 and the latter using 1 for the same purpose, instead of the traditional (C-like) not 0.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号