keith@stellar.UUCP (Keith Crews @stellar) (04/26/89)
I have some questions about common fortran extensions to logical variables. Some fortrans (such as vms) have extended logicals so that they behave a lot like integers in most contexts. For example, you can assign them values other than 0 and -1 (or whatever the conventional values for false and true are) and you can do arithmetic on them. However if you have assigned values to them other than 0 or -1 you then get some strange results. You get logical variables that are neither true nor false (kind of like ieee nans) and you can have 2 non-zero logicals variables that don't have the same truth value. The basic problem I have with the vax implementation is that I think that a logical variable should always be true or false. You can do this by forcing a conversion to 0 or -1 when assigning to them (although this can be defeated by using equivalences) or you can treat all non-zero logicals as being true and only 0 as being false. However, the vax and other compilers seem to have extended logicals by allowing them to act like integers in many contexts while leaving the underlying implementation alone and the result is that using extensions to logicals can result in some surprising results. My questions are: 1) Do people depend on having logicals that are neither true nor false? 2) What would people consider a consistent set of semantic rules for these extensions to logicals? 3) Should .eq. and .eqv. behave identically with logical operands or should .eq. do integer comparisons and .eqv. check for both zero or both non-zero? If you allow 2 distinct non-zero logicals to not be equal (.eq. different from .eqv. in 3 above) then you have another problem where the 2 expressions below may evaluate differently: l1 = 3 l2 = .true. if (l1 .eq. .true.) ... if (l1 .eq. l2) ... However, if you evaluate them the same then you are incompatible with vms fortran which seems like a dubious idea. I guess the real issue is whether I have missed a unifying idea under- lying the vms implementation. Here are a couple of examples: This prints 0 on the vax: logical l1 l1 = 3 i = 0 if (l1 .eq. .true.) then i = 1 endif if (l1 .eq. .false.) then i = 2 endif print *, i end This prints 2 on the vax and 1 on the sun: logical l1, l2 l1 = 3 l2 = 4 i = 0 if (l1 .eqv. l2) then i = 1 endif if (l1 .neqv. l2) then i = i + 2 endif print *,i end -- Keith Crews Stellar Computer Inc. 95 Wells Avenue, Newton, MA 02159
mikel@pyramid.pyramid.com (Mike Lipsie) (04/27/89)
In article <31660@stellar.UUCP> keith@stellar.UUCP (Keith Crews @stellar) writes: >I have some questions about common fortran extensions to logical variables. > >The basic problem I have with the vax implementation is that I think that >a logical variable should always be true or false. You can do this by >forcing a conversion to 0 or -1 when assigning to them (although this can >be defeated by using equivalences) or you can treat all non-zero logicals >as being true and only 0 as being false. Not answering Keith's question but rather pointing out an erroneous assumption. People who come from the C world seem to have internalized false-true as zero-nonzero; those from Pascal as zero-one. Other implementations are possible. A relatively common method is even-odd because some machines had a fast low-order bit test; likewise, there is positive-negative because of a fast sign bit test. -- ----------- Mike Lipsie mikel@pyramid.com Pyramid Technology Corp, Mountain View, CA +1 415 965 7200 ext. 4980
calvin@dinkum.SGI.COM (Calvin H. Vu) (04/28/89)
In article <31660@stellar.UUCP>, keith@stellar.UUCP (Keith Crews @stellar) writes: > The basic problem I have with the vax implementation is that I think that > a logical variable should always be true or false. You can do this by > forcing a conversion to 0 or -1 when assigning to them This is what ANSI says and that's what most non-VMS people expect, but some people do want logicals to retains its integer value after the assignment so they can be used in the same way as integers :-(. Don't search me for the answer though. The only advantage in using extended logicals over integers, as far as I can see, is that they can do: logic = 3 IF (logic) ... instead of: int = 3 IF (and(int,1)) since TRUE/FALSE condition on the VAX is evaluated by examining the last bit. > 1) Do people depend on having logicals that are neither true nor false? Apparently so. But I surely hope that they are the last of a dying breed :-}. Nitpicking: they are neither .TRUE. nor .FALSE. but they do evaluate to true or false according to their own odd/eeven rule. > 2) What would people consider a consistent set of semantic rules for > these extensions to logicals? Implementational expectation for exact compatibility: Allow extended logicals have the same values as integers and evaluate conditional expression by testing the last bit of the result. For archaic processors which test TRUE/FALSE by looking at the last bit this is no problem. Nowaday, with the new processors which test for zero/non-zero value, I doubt if anybody would do an extra bit mask for each conditional expression evaluation just to allow this ridiculous extension. "How about my benchmarks ?", they'll say. > 3) Should .eq. and .eqv. behave identically with logical operands > or should .eq. do integer comparisons and .eqv. check for both zero or > both non-zero? .eq. is always implemented as integer comparison. I don't know how .eqv. is implemented on VMS. It would be interesting to test if l1=1 and l2=3 are .eqv. on VMS. > If you allow 2 distinct non-zero logicals to not be equal (.eq. different from > .eqv. in 3 above) then you have another problem where the 2 expressions below > may evaluate differently: > > l1 = 3 > l2 = .true. > if (l1 .eq. .true.) ... > if (l1 .eq. l2) ... > > However, if you evaluate them the same then you are incompatible with vms > fortran which seems like a dubious idea. > > I guess the real issue is whether I have missed a unifying idea under- > lying the vms implementation. The key is that VMS uses the odd/even concept of TRUE/FALSE so they can be liberal in the values their extended logical contains (i.e. all integer values). > > Here are a couple of examples: > > This prints 0 on the vax: > > logical l1 > l1 = 3 > i = 0 > if (l1 .eq. .true.) then > i = 1 > endif > if (l1 .eq. .false.) then > i = 2 > endif > print *, i > end .eq uses integer comparison so 3 is not equal to .TRUE. (which is either 1 or -1) > > This prints 2 on the vax and 1 on the sun: > > logical l1, l2 > l1 = 3 > l2 = 4 > i = 0 > if (l1 .eqv. l2) then > i = 1 > endif > if (l1 .neqv. l2) then > i = i + 2 > endif > print *,i > end SUN forces the logical values to either .TRUE. or .FALSE. so l1 and l2 are both .TRUE. whereas on the VAX an odd 3 is not equivalent to an even 4 no matter how you look at it. > -- > Keith Crews Stellar Computer Inc. > 95 Wells Avenue, Newton, MA 02159 Calvin Vu
maine@drynix.dfrf.nasa.gov (04/28/89)
In article <31660@stellar.UUCP>, keith@stellar.UUCP (Keith Crews @stellar) asks about the usage of logical variables as integers, particularly on VAXen. In article <31555@sgi.SGI.COM> calvin@dinkum.SGI.COM (Calvin H. Vu) writes: > This is what ANSI says and that's what most non-VMS people expect, > but some people do want logicals to retains its integer value after > the assignment so they can be used in the same way as integers :-(. > Don't search me for the answer though. The only advantage in using > extended logicals over integers, as far as I can see, is that they > can do: ... While acknowledging that this is all non-standard and non-portable and thus to be avoided unless there are good arguments otherwise, there is one usage of this construct that occasionally does seem justifiable. (I've even done it myself in one case, while arguing with myself over whether it was really the best approach). The VAX allows a logical*1, which can be used as an unsigned (I think) 8-bit integer. Oddly, the VAX does not recognize an integer*1 declaration, so if you want an 8-bit integer, you need to use logical*1 instead. You don't really care how .TRUE. and .FALSE. are represented because you are never really using these quantities as logicals. Declaring something logical so you can use it as an integer is confusing as well as non-standard, but if you really want an 8-bit integer, what's a guy to do? My "favorite" system, the Elxsi, allows an integer*1 type (signed), which is admitedly still non-standard, but is at least intuitively obvious. It is also possible to play games with character types and CHAR/ICHAR (assuming that you are on a system with 8-bit characters), but that is, if anything, more confusing than using logical. Probably the "safest" (most standard and portable) thing to do is to represent 4 (or more) of the 8-bit quantities in a single 32-bit (or more) integer as in "ipacked = ((i1*256+i2)*256+i3)*256+i4" (assuming here that the i1-i4 are unsigned). I've never yet seen a FORTRAN implementation with less than 32 bits in an integer. This approach is sometimes reasonable, but in other applications the performance hit is too large, particularly if you try to make the code more clear by hiding the packing/unpacking stuff in separate functions. I can think of 2 reasons for needing 8-bit integers. The most obvious is to save space if you have a big array of em. The other reason is to deal with binary files having such 8-bit integers. (TeX anyone? Yes, I wrote a TeX device driver in FORTRAN). I will make no attempt to argue what the "best" solution is to the 8-bit integer requirement. I just want to point this out as a reasonably defensible rationale for using the strange construct of putting integer values in logical variables on a VAX. Of course, not all cases use the construct in this way or for this purpose. In some cases it is incomprehensible to me why such a strange construct was used. (Should I draw parallels to strange do-loop structures? Nahh, better not:-)) P.S. Forgot to mention another way to handle 8-bit integers - code in Pascal or c, or maybe the 8x integer kind= construct, but that's a different discussion. Richard Maine maine@elxsi.dfrf.nasa.gov
brainerd@unmvax.unm.edu (Walt Brainerd) (04/29/89)
In article <MAINE.89Apr28085934@drynix.dfrf.nasa.gov>, maine@drynix.dfrf.nasa.gov writes: > > While acknowledging that this is all non-standard and non-portable and > ... > what's a guy to do? My "favorite" system, the Elxsi, allows > an integer*1 type (signed), which is admitedly still non-standard, but The kind parameter for logicals (and all other intrinsic data types) proposed for Fortran 8? will allow the implementor to do this according to standard, and if the programmer is careful, allow it to be used in a portable way. > "ipacked = ((i1*256+i2)*256+i3)*256+i4" This ain't gonna work too well on a decimal machine! Of course, the author acknowledged that this is nonstandard and nonportable. I hope there are fewer and fewer who know this, but I used to run into lots of Fortran programmers who didn't!
brainerd@unmvax.unm.edu (Walt Brainerd) (04/29/89)
In article <64@unmvax.unm.edu>, brainerd@unmvax.unm.edu (Walt Brainerd) writes: > Of course, the author acknowledged that this is nonstandard > and nonportable. I hope there are fewer and fewer who know this, > but I used to run into lots of Fortran programmers who didn't! Sorry, I left out a "don't" after "fewer and fewer" !