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

boolean/integer(bool)/logical

wkramer
Beginner
4,782 Views
Under issue number 279810 I reported to premier support that according to "Help Win32* Routines" the equivalent fortran data type for Win32 BOOL or BOOLEAN is LOGICAL(4), the passage can be found in the documentation:"Intel Visual Fortran CompilerUser's GuideUsing LibrariesUsing the Win32 RoutinesCalling Win32* Routines"
Issue status is "reproduced(escalated)", but nothing has been done since (issue submitted dec 2004), the same passage can still be found now under:"Intel Visual Fortran CompilerBuilding ApplicationsUsing LibrariesUsing the Windows API RoutinesCalling Windows API Routines"
Walter Kramer
I did press reply to get this meessage in the IVF versus CVF thread, but something must have gone wrong????

Message Edited by WKRAMER on 10-19-2005 02:06 PM

0 Kudos
24 Replies
Paul_Curtis
Valued Contributor I
3,677 Views

This question is related to another current thread in this forum:

http://softwareforums.intel.com/ids/board/message?board.id=5&message.id=15406

I have been creating Win32-F90 code for years, in CVF and now IVF, and have never encountered a situation where a Fortran LOGICAL type isused as an argument to a Win32 API function. AllWin32 API arguments (those which are not large structures)are of Fortran type INTEGER*4, whether the intended Win32 context/meaning will be integer, logical or LOC().
The OP's referenced documentation might be misleading or wrong, but F90-Win32 function call linkages with I*4 arguments work perfectly. As noted in the other thread, IVF has lately become very picky about precise argument agreement, disallowing Logical when Integer is required, whereas CVF mostly didn't enforce such requirements.
0 Kudos
Steven_L_Intel1
Employee
3,677 Views
I'll check out the reported issue. If the docs say LOGICAL is appropriate for a BOOL, I'll have it fixed.
0 Kudos
Steven_L_Intel1
Employee
3,677 Views
Ok, found the doc error and also why you haven't had a response. Please accept my apologies for that. I'll have this taken care of.
0 Kudos
jim_dempsey
Beginner
3,677 Views

I would be careful about passing LOGICAL in Fortran to a windows routine that expects a bool. The reason being that the internal representation of what is .true. or .false. is left up to the implimentators of the FORTRAN compiler as well as to the C++ compiler. You are not guaranteed that the internal storage format is the same between F90 and C++ less alone between F90 vendor A and F90 vendor B or F90 V9.0.024 vendor A and F90 V10.0.1 vendor A.

Common values are 0, 1, -1, .ne. 0, .lt. 0, .gt. 0 and the interpritation of what is true or false is up to the implimentation.

You will often find that "(x .eq. .true.)" and "(.not. (x .eq. .false.))" don't agree with each other when going mixed language.

Words of caution.

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
3,677 Views
That's exactly why I say that BOOL is not LOGICAL.
0 Kudos
jim_dempsey
Beginner
3,677 Views

I would suggest thattwo C++ subroutines that are callable from FORTRAN, one that returns the boolian true and one that returns the boolian false. If C++ calls FORTRAN then create two FORTRAN routines callable from C++, one that returns .true. as integer(4)and one that returns .false. as integer(4). Take care in the issue of wether you pass by value or by reference. You may also want to create a FORTRAN function, callable from FORTRAN that has for input a LOGICAL and which returns the appropriateC++ boolian. With these little wrapper frunctions your code will be portable and it won't break should something change in the future.

Jim Dempsey

0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,677 Views
I plead guilty for (ab)using logical/integer mismatch for years. However, (provided that the compiler swallows it) it is virtually impossible that you get a wrong outcome; underlying implementations (a double-word having value 0 for .FALSE. and -1/1 for .TRUE.) are so much natural choices for any sane compiler write that they are interoperable (and C standard, unlike Fortran one, does define that 0 has "false" semantics and anything else "true" semantics).

An attention should be paid though that CVF (and probably IVF as well) checks only the LSB of a logical expression to evaluate it. Thus, e.g. 0x00000002 has value .FALSE. in VF. However, I've never seen an API documented to return a BOOL returning anything other than 0x00000000 and 0x00000001.

So, my conclusion is that integer(BOOL) should be used in new codes but "old style" codes (using logical) don't have to be fixed (if the compiler does not complain, of course.)

Jugoslav
0 Kudos
Steven_L_Intel1
Employee
3,677 Views
I have seen codes that compare Win32 call returns explicitly against .TRUE. - this worked in MS Fortran but does not work in CVF/IVF unless you specify /fpscomp:logical (and then only if the API returned 1.)
0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,677 Views
To be precise:
if (aLogical) then          !is fine
if (aLogical .eqv. .true.) then !is fine as well (is it?)
if (aLogical .eq. .true.) then !is NOT fine
I'm not sure if the last expression is allowed in standard F95, or it's just a FPS/CVF extension?

Jugoslav
0 Kudos
jim_dempsey
Beginner
3,677 Views
if (aLogical .eq. .true.) then...
Has to be permitted. How is it different from
if (aLogical .eq. bLogical) then
0 Kudos
jim_dempsey
Beginner
3,677 Views
if (aLogical .eq. .true.) then...
Has to be permitted. How is it different from
if (aLogical .eq. bLogical) then
0 Kudos
jim_dempsey
Beginner
3,677 Views
if (aLogical .eq. .true.) then...
Has to be permitted. How is it different from
if (aLogical .eq. bLogical) then
0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,677 Views
Simply, operator .eq. is not defined for LOGICALs in F95. One is supposed to use .eqv. instead:

CVF program with /stand:f95:
program BoolTest

logical:: b1 = .true., b2 = .true., b3 = .true.

if (b1.eq.b2) b3 = .false.

end program BoolTest
...
BoolTest.f90(5) : Warning: Fortran 95 does not allow a LOGICAL
data type in this context. [B1]

BoolTest.f90(5) : Warning: Fortran 95 does not allow a LOGICAL
data type in this context. [B2]
Jugoslav
0 Kudos
jim_dempsey
Beginner
3,677 Views

Someone needs to work on the Reply to Message system. As you can see by the multiple posts. This occured because when I wanted to indent some text I pressed the Tab key and the focus went to the Submit Message button. Then when I noticed the indentating did not occure I pressed the spacebar several times toindent the text (focus still on Submit Message)... this poped in several copies of the unfinished message.

0 Kudos
jim_dempsey
Beginner
3,677 Views

What I wanted to say is illustrated by the Dissassembly Window snippette below

logical fooEQV, a, b

fooEQV = (a .eqv. b)

0040110F 8B 00 mov eax,dword ptr [eax]

00401111 33 02 xor eax,dword ptr [edx]

00401113 F7 D0 not eax

end function fooEQV

F90 using standard .true. -1, .false. 0
(0,0) returns -1 standard .true.
(-1,-1) returns -1 standard .true.
(-1,0) returns 0 standard .false.
Non-F90 standard true of 1
(1,0) returns -2 non-standard .false. (lsb 0 other bits not zero)
(1,1) returns -1 standard .true.
(1,-1) returns 1 non-standard .true.
Other C/C++ where true is !=0
(2,0) returns -3 non-standard false in F90
There are other examples. When non-standard false is returned and then subsequently passed back to the C++ program, or to older C, or to assembleryou run the risk of the code using false is 0 and not lsb=0.
When this occures it usualy results in a much longer than normal debugging session because the source code reads correctly but due to the inconsistancy the underlaying assembler code doing what it is supposed to do does not produce the results you assume to be the desired result.
This is why a 'tidy-up' filter between language translations can be important. Note, if made into a function call then you can conditional compile such that the Debug configuration Asserts when not standard input and when in Release version the assert is removed and function inlined permitting no performance hit.
Jim Dempsey
0 Kudos
jim_dempsey
Beginner
3,677 Views
Bad typing
(2,0) returns -3 non-standardtrue in F90
0 Kudos
Jugoslav_Dujic
Valued Contributor II
3,677 Views
Uh, assembly is not exactly my first language. Lemme see if I follow you:

- VF evaluates (a.eqv.b) as NOT(IEOR(a,b)) (bitwise)
- the bit-pattern of the result is correct according to VF logical semantics, i.e. LSB is correctly set or cleared.
- however, the resulting bit-pattern need not conform to C semantics, i.e. it can happen that a VF .FALSE. evaluates to C TRUE, i.e. a value different than 0.

If so, point taken. Thanks for the exercise.

Jugoslav
0 Kudos
Steven_L_Intel1
Employee
3,677 Views
(From the VF Newsletter, April 2000)



Doctor Fortran in "To .EQV. or to .NEQV., that is the question", or "It's only LOGICAL"



By Steve Lionel

Visual Fortran Engineering



Most Fortran programmers are familiar with the LOGICAL data type, or at least they think they are.... An object of type LOGICAL has one of only two values, true or false. The language also defines two LOGICAL constant literals .TRUE. and .FALSE., which have the values true and false, respectively. It seems so simple, doesn't it? Yes... and no.



The trouble begins when you start wondering about just what the binary representation of a LOGICAL value is. An object of type "default LOGICAL kind" has the same size as a "default INTEGER kind", which in Visual Fortran (and most current Fortran implementations) is 32 bits. Since true/false could be encoded in just one bit, what do the other 31 do? Which bit pattern(s) represent true, and which represent false? And what bit patterns do .TRUE. and .FALSE. have? On all of these questions, the Fortran standard is silent. Indeed, according to the standard, you shouldn't be able to tell! How is this?



According to the standard, LOGICAL is its own distinct data type unrelated to and not interchangeable with INTEGER. There is a restricted set of operators available for the LOGICAL type which are not defined for any other type: .AND., .OR., .NOT., .EQV. and .NEQV.. Furthermore, there is no implicit conversion defined between LOGICAL and any other type.



"But wait," you cry! "I use .AND. and .OR. on integers all the time!" And so you do - but doing so is non-standard, though it's an almost universal extension in today's compilers, generally implemented as a "bitwise" operation on each bit of the value, and generally harmless. What you really should be using instead is the intrinsics designed for this purpose: IAND, IOR and IEOR.



Not so harmless is another common extension of allowing implicit conversion between LOGICAL and numeric types. This is where you can start getting into trouble due to implementation dependencies on the binary representation of LOGICAL values. For example, if you have:



INTEGER I,J,K

I = J



just what is the value of I? The answer is "it depends", and the result may even vary within a single implementation. Compaq Fortran traditionally (since the 1970s, at least) considers LOGICAL values with the least significant bit (LSB) one to be true, and values with the LSB zero to be false. All the other bits are ignored when testing for true/false. Many other Fortran compilers adopt the C definition of zero being false and non-zero being true. (Visual Fortran offers the /fpscomp:logicals switch to select the C method, since PowerStation used it as well.) Either way, the result of the expression J


The real trouble with making assumptions about the internal value of LOGICALs is when you try testing them for "equality" against another logical expression. The way many Fortran programmers would naturally do this is as follows:



IF (LOGVAL1 .EQ. LOGVAL2) ...



but the results of this can vary depending on the internal representation. The Fortran language defines two operators exclusively for use on logical values, .EQV. ("equivalent to") and .NEQV. ("not equivalent to"). So the above test would be properly written as:



IF (LOGVAL1 .EQV. LOGVAL2) ...



In the Doctor's experience, not too many Fortran programmers use .EQV. and .NEQV. where they should, and get into trouble when porting software to other environments. Get in the habit of using the correct operators on LOGICAL values, and you'll avoid being snared by implementation differences.



However, there is one aspect of these operators you need to be aware of... A customer recently sent us a program that contained the following statement:



DO WHILE (K .LE. 2 .AND. FOUND .EQV. .FALSE.)



The complaint was that the compiler "generated bad code." What the programmer didn't realize was that the operators .EQV. and .NEQV. have lower precedence than any of the other predefined logical operators. This meant that the statement was treated as if it had been:



DO WHILE (((K .LE. 2) .AND. FOUND) .EQV. .FALSE.)



what was wanted instead was:



DO WHILE ((K .LE. 2) .AND. (.FOUND .EQV. .FALSE.))



The Doctor's prescription here is to always use parentheses! That way you'll be sure that the compiler interprets the expression the way you meant it to! (And you therefore don't have to learn the operator precedence table you can find in chapter 4 of the Compaq Fortran Language Reference Manual!)

Message Edited by sblionel on 10-21-2005 08:35 AM

0 Kudos
Steven_L_Intel1
Employee
3,677 Views
(From Visual Fortran Newsletter, April 2000)

Doctor Fortran in "To .EQV. or to .NEQV., that is the question", or "It's only LOGICAL"

By Steve Lionel
Visual Fortran Engineering

Most Fortran programmers are familiar with the LOGICAL data type, or at least they think they are.... An object of type LOGICAL has one of only two values, true or false. The language also defines two LOGICAL constant literals .TRUE. and .FALSE., which have the values true and false, respectively. It seems so simple, doesn't it? Yes... and no.

The trouble begins when you start wondering about just what the binary representation of a LOGICAL value is. An object of type "default LOGICAL kind" has the same size as a "default INTEGER kind", which in Visual Fortran (and most current Fortran implementations) is 32 bits. Since true/false could be encoded in just one bit, what do the other 31 do? Which bit pattern(s) represent true, and which represent false? And what bit patterns do .TRUE. and .FALSE. have? On all of these questions, the Fortran standard is silent. Indeed, according to the standard, you shouldn't be able to tell! How is this?

According to the standard, LOGICAL is its own distinct data type unrelated to and not interchangeable with INTEGER. There is a restricted set of operators available for the LOGICAL type which are not defined for any other type: .AND., .OR., .NOT., .EQV. and .NEQV.. Furthermore, there is no implicit conversion defined between LOGICAL and any other type.

"But wait," you cry! "I use .AND. and .OR. on integers all the time!" And so you do - but doing so is non-standard, though it's an almost universal extension in today's compilers, generally implemented as a "bitwise" operation on each bit of the value, and generally harmless. What you really should be using instead is the intrinsics designed for this purpose: IAND, IOR and IEOR.

Not so harmless is another common extension of allowing implicit conversion between LOGICAL and numeric types. This is where you can start getting into trouble due to implementation dependencies on the binary representation of LOGICAL values. For example, if you have:

INTEGER I,J,K
I = J

just what is the value of I? The answer is "it depends", and the result may even vary within a single implementation. Compaq Fortran traditionally (since the 1970s, at least) considers LOGICAL values with the least significant bit (LSB) one to be true, and values with the LSB zero to be false. All the other bits are ignored when testing for true/false. Many other Fortran compilers adopt the C definition of zero being false and non-zero being true. (Visual Fortran offers the /fpscomp:logicals switch to select the C method, since PowerStation used it as well.) Either way, the result of the expression J
The real trouble with making assumptions about the internal value of LOGICALs is when you try testing them for "equality" against another logical expression. The way many Fortran programmers would naturally do this is as follows:

IF (LOGVAL1 .EQ. LOGVAL2) ...

but the results of this can vary d epending on the internal representation. The Fortran language defines two operators exclusively for use on logical values, .EQV. ("equivalent to") and .NEQV. ("not equivalent to"). So the above test would be properly written as:

IF (LOGVAL1 .EQV. LOGVAL2) ...

In the Doctor's experience, not too many Fortran programmers use .EQV. and .NEQV. where they should, and get into trouble when porting software to other environments. Get in the habit of using the correct operators on LOGICAL values, and you'll avoid being snared by implementation differences.

However, there is one aspect of these operators you need to be aware of... A customer recently sent us a program that contained the following statement:

DO WHILE (K .LE. 2 .AND. FOUND .EQV. .FALSE.)

The complaint was that the compiler "generated bad code." What the programmer didn't realize was that the operators .EQV. and .NEQV. have lower precedence than any of the other predefined logical operators. This meant that the statement was treated as if it had been:

DO WHILE (((K .LE. 2) .AND. FOUND) .EQV. .FALSE.)

what was wanted instead was:

DO WHILE ((K .LE. 2) .AND. (.FOUND .EQV. .FALSE.))

The Doctor's prescription here is to always use parentheses! That way you'll be sure that the compiler interprets the expression the way you meant it to! (And you therefore don't have to learn the operator precedence table you can find in chapter 4 of the Compaq Fortran Language Reference Manual!)

Message Edited by sblionel on 10-21-2005 08:41 AM

0 Kudos
jim_dempsey
Beginner
3,272 Views

Applause, applause...

Re: DO WHILE (((K .LE. 2) .AND. FOUND) .EQV. .FALSE.)

what was wanted instead was:

DO WHILE ((K .LE. 2) .AND. (.FOUND .EQV. .FALSE.))

With context sensitive editors and intelisensewouldn't it be nice to have the precidence depenent portions highlighted in some manner? Example: assume mouse pointer over .AND.

(K .LE. 2 .AND. FOUND .EQV. .FALSE.)

Even when used with the parens complex expressions might benifit from highlighting.

Jim

0 Kudos
Reply