I discovered that a colleague had used a non-standard logical expression in a program, but that it had compiled and run without complaint (whether it ran correctly is another matter).
The logical expression was of the form: i > j > k
So I wrote the code fragment below and it compiled and ran successfully (CVF 6.6B) with the annotated results:
I can see that it is well worth avoiding such expressions, but I am concerned that the compiler does not pick them up as illegal. Could somebody please explain this?
The
Alan
The logical expression was of the form: i > j > k
So I wrote the code fragment below and it compiled and ran successfully (CVF 6.6B) with the annotated results:
integer*4 i, j, k logical*1 Result ! Result i = 2; j = 3; k = 4 ! Expected Actual Result = i < j < k ! .TRUE. .TRUE. Result = i > j > k ! .FALSE. .FALSE. i = 2; j = 3; k = 2 Result = i < j < k ! .FALSE. .TRUE. Result = i > j > k ! .FALSE. .FALSE. i = 4; j = 3; k = 4 Result = i < j < k ! .FALSE. .TRUE. Result = i > j > k ! .FALSE. .FALSE.
I can see that it is well worth avoiding such expressions, but I am concerned that the compiler does not pick them up as illegal. Could somebody please explain this?
The
CodeHTML tags (with square brackets) do not seem to work for me today, so apologies if the code is not so easy to read.
Alan
链接已复制
15 回复数
This is a CVF extension which allows free mixing of LOGICALs and INTEGERs. If you switch on "Fortran Standards Checking:f95" in "Compilation Diagnostics" category of Project Settings, these statements will be tagged as illegal.
HOWEVER, these statements do not even mean the obvious. Numerical value of .TRUE. in CVF is 0xFFFFFFFF (=-1), and value of .FALSE. is zero. Thus, e.g:
i = 4; j = 3; k = 4
Result = iResult = i>j>k = (i>j)> k = (-1)> 4 = .FALSE.
HTH
Jugoslav
HOWEVER, these statements do not even mean the obvious. Numerical value of .TRUE. in CVF is 0xFFFFFFFF (=-1), and value of .FALSE. is zero. Thus, e.g:
i = 4; j = 3; k = 4
Result = i
HTH
Jugoslav
It's fine for bitwise operations, e.g.
iWindowStyle = (WS_OVERLAPPEDWINDOW .or. WS_CLIPCHILDREN .or. WS_BORDER .or. WS_WHATEVER) .and..not. WS_THICKFRAME
is much more succinct and readable than
iWindowStyle = IAND (IOR(WS_OVERLAPPEDWINDOW, IOR(WS_CLIPCHILDREN, IOR(WS_BORDER,WS_WHATEVER)))), NOT( WS_THICKFRAME))
Also, I abuse it when API functions return a LOGICAL but the result is not of interest -- I usually assign it to a dummy integer, so that I don't have to remember whether the function returns a LOGICAL or an INTEGER. Other than that, the usability of extensions looks doubtful.
Jugoslav
iWindowStyle = (WS_OVERLAPPEDWINDOW .or. WS_CLIPCHILDREN .or. WS_BORDER .or. WS_WHATEVER) .and..not. WS_THICKFRAME
is much more succinct and readable than
iWindowStyle = IAND (IOR(WS_OVERLAPPEDWINDOW, IOR(WS_CLIPCHILDREN, IOR(WS_BORDER,WS_WHATEVER)))), NOT( WS_THICKFRAME))
Also, I abuse it when API functions return a LOGICAL but the result is not of interest -- I usually assign it to a dummy integer, so that I don't have to remember whether the function returns a LOGICAL or an INTEGER. Other than that, the usability of extensions looks doubtful.
Jugoslav
1) It's more or less the same thing. C++ "bool" was introduced relatively recently (IIRC in 90s). IIRC true has value 1 and false has value 0. Fortran standard defines the behaviour, but not the contents of LOGICALs. CVF implementation is that only LSB is checked for evaluating the logical-valued expression:
It is as good as any (another way, IMHO bit more logical, could be that 0=.FALSE. and everything else =.TRUE.).
2) Well, they are of four different byte sizes, aren't they? You can spare space by using smaller sizes, but the performance will be slightly improved, and compatibility issues smaller, if you stick to default LOGICAL (4 bytes).
Jugoslav
LOGICAL:: b1, b2 b1 = 6 !Forbidden by the standard as explained above b2 = 7 WRITE(*,*) b1, b2 !Outputs "F T"
It is as good as any (another way, IMHO bit more logical, could be that 0=.FALSE. and everything else =.TRUE.).
2) Well, they are of four different byte sizes, aren't they? You can spare space by using smaller sizes, but the performance will be slightly improved, and compatibility issues smaller, if you stick to default LOGICAL (4 bytes).
Jugoslav
> 1) It's more or less the same thing. C++ "bool" was
> introduced relatively recently (IIRC in 90s). IIRC
> true has value 1 and false has value 0.
> Fortran standard defines the behaviour, but not the
> contents of LOGICALs. CVF implementation is that only
> LSB is checked for evaluating the logical-valued
> expression:
> LOGICAL:: b1, b2
> b1 = 6 !Forbidden by the standard as explained
> above
> b2 = 7
> WRITE(*,*) b1, b2 !Outputs "F T"
But in CVF, .true.=-1 and .false.=0 whereas with LSB one would expect .true.=1 like C++.
> It is as good as any (another way, IMHO bit more
> logical, could be that 0=.FALSE. and everything else
> =.TRUE.).
I agree.
>
> 2) Well, they are of four different byte sizes,
> aren't they? You can spare space by using smaller
> sizes, but the performance will be slightly improved,
> and compatibility issues smaller, if you stick to
> default LOGICAL (4 bytes).
Byte, like Dave, a a 4-letter word in Fortran. No matter, as LOGICAL is T or F, I see why there's no SELECTED_LOGICAL_KIND like the corresponding _INT_, _REAL_, and _CHAR_ intrinsics. I guess the default LOGICAL is fine whatever its KIND.
Thanks for the clarification.
Gerry T.
>
> Jugoslav
> introduced relatively recently (IIRC in 90s). IIRC
> true has value 1 and false has value 0.
> Fortran standard defines the behaviour, but not the
> contents of LOGICALs. CVF implementation is that only
> LSB is checked for evaluating the logical-valued
> expression:
> LOGICAL:: b1, b2
> b1 = 6 !Forbidden by the standard as explained
> above
> b2 = 7
> WRITE(*,*) b1, b2 !Outputs "F T"
But in CVF, .true.=-1 and .false.=0 whereas with LSB one would expect .true.=1 like C++.
> It is as good as any (another way, IMHO bit more
> logical, could be that 0=.FALSE. and everything else
> =.TRUE.).
I agree.
>
> 2) Well, they are of four different byte sizes,
> aren't they? You can spare space by using smaller
> sizes, but the performance will be slightly improved,
> and compatibility issues smaller, if you stick to
> default LOGICAL (4 bytes).
Byte, like Dave, a a 4-letter word in Fortran. No matter, as LOGICAL is T or F, I see why there's no SELECTED_LOGICAL_KIND like the corresponding _INT_, _REAL_, and _CHAR_ intrinsics. I guess the default LOGICAL is fine whatever its KIND.
Thanks for the clarification.
Gerry T.
>
> Jugoslav
CVF's implementation of LOGICALs derives from VAX Fortran - the VAX had instructions for branching on low bit clear (or set), making the test easy. (A test for zero or non-zero would require two instructions.)
-1 is used as it is ".NOT. 0"
Steve
-1 is used as it is ".NOT. 0"
Steve
To Gerry: SELECTED_LOGICAL_KIND appears to be an ommission in F95 standard. It was mentioned in c.l.f. recently (I found it in a Jan Vorbrueggen's post of Jan 16). I think it is added in F2k, but at the moment I don't have the draft at hand to check it.
Steve, I'm not familiar with PC assembly, but I'd expect that zero/non-zero test takes one instruction, but LSB test takes two. Am I right?
Jugoslav
Steve, I'm not familiar with PC assembly, but I'd expect that zero/non-zero test takes one instruction, but LSB test takes two. Am I right?
Jugoslav
> Steve, I'm not familiar with PC assembly, but I'd
> expect that zero/non-zero test takes one instruction,
> but LSB test takes two. Am I right?
Yes. We had some conflicting goals with CVF, in that we wanted to be compatible with PowerStation but also with our existing Fortran compilers and applications written for them. CVF supports the zero-nonzero definition of LOGICAL if you specify /fpscomp:logicals - but I have a hard time believing you could notice the performance difference in a typical application.
Six years later, there are some decisions we wish we had made differently, but, as they say, hindsight is 20/20. (Meaning, if you're not familiar with the term, that you can see the past with perfect vision.) Some of these decisions will be "revisited" for Intel Visual Fortran, the most notable of which is the default of the STDCALL convention, which has, overall, been more trouble than benefit.
Steve
> expect that zero/non-zero test takes one instruction,
> but LSB test takes two. Am I right?
Yes. We had some conflicting goals with CVF, in that we wanted to be compatible with PowerStation but also with our existing Fortran compilers and applications written for them. CVF supports the zero-nonzero definition of LOGICAL if you specify /fpscomp:logicals - but I have a hard time believing you could notice the performance difference in a typical application.
Six years later, there are some decisions we wish we had made differently, but, as they say, hindsight is 20/20. (Meaning, if you're not familiar with the term, that you can see the past with perfect vision.) Some of these decisions will be "revisited" for Intel Visual Fortran, the most notable of which is the default of the STDCALL convention, which has, overall, been more trouble than benefit.
Steve
Personally, I've never had problems with stdcall. It has the slight advantage over cdecl that you cannot mismatch number of arguments in "f77" style of programming (no explicit interface). I have a bad feeling that many of mixed-language projects where !DEC$ATTRIBUTES STDCALL wasn't specified will break with the new IVF. Well, the price must be paid somewhere... At least, you should include "default calling convention" compiler switch as in VC++ (I guess it is in IFC7 already - /Gm?).
Jugoslav
Jugoslav
Well, you haven't had to deal with the zillions of customers who complain that their code, which works "everywhere else" (read "Unix"), doesn't build with CVF because of deliberate argument mismatches....
Steve
Steve
Ahhh... I see now ;-). IIRC the very possibility of mismatch was mentioned in small print somewhere deep in Kernighan&Ritchie, and nowhere in Fortran books that I recall, but apparently when after someone had discovered it was possible it spread like a plague :-(. Oh well.
Jugoslav
Jugoslav
