Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

binary data

230 views
Skip to first unread message

Arjan

unread,
Aug 30, 2012, 5:40:13 AM8/30/12
to
Hi!

My dosimeters provide data ASCII data-files, providing the data in 16-bit hexadecimal words. Reading in these words goes well. I declared them as follows:

CHARACTER(4) :: MyWord

In SOME cases, the whole set of 16 bits is to be interpreted as, e.g., the temperature offset of the dosimeter. In those cases, I read the value like this:

READ(MyWord,'(z4)') TempOffset

This gives no problem. In MOST cases, however, the upper 4 bits in the word tell which kind of data is provided in the last 10 bits of that same word. Sometimes, these last 10 bits should be seen as 2 x 5 bits, each representing a different integer variable. Checking the upper 4 bits to find out the data type is easy, since that's just the first character of the character string. My problem is how to read the data values from the remaining bits:

--> How do I give an integer variable a value that is determined by either
(1) the last 10 bits in the word,
(2) or by bits 0-4
(3) or 5-9?

Regards,


Arjan

Rafik Zurob

unread,
Aug 30, 2012, 6:55:55 AM8/30/12
to
Hi

Instead of reading the 16-bit words into a character(4), why not read into
an integer(2)? You can then use bit masking and shifting instead of
internal file I/O to interpret the word and store the various parts into
their respective variables.

Regards

Rafik

"Arjan" <arjan.v...@rivm.nl> wrote in message
news:df30faea-79cf-4081...@googlegroups.com...

Louisa

unread,
Aug 30, 2012, 7:09:48 AM8/30/12
to
On Aug 30, 8:55 pm, "Rafik Zurob" <nos...@hotmail.com> wrote:

> Instead of reading the 16-bit words into a character(4), why not read into
> an integer(2)?

The bytes may be then in reverse order.

As they are now, the bytes can be extracted using TRANSFER or
ICHAR/IACHAR, and then manipulated.
The 5-bit fields can be extracted using IAND and ISHFT.

Arjan

unread,
Aug 30, 2012, 8:22:11 AM8/30/12
to
> The 5-bit fields can be extracted using IAND and ISHFT.


This seems to be the way! Thanks!

A.

James Van Buskirk

unread,
Aug 30, 2012, 11:33:45 AM8/30/12
to
"Arjan" <arjan.v...@rivm.nl> wrote in message
news:5060ab6b-d75e-44b2...@googlegroups.com...

>> The 5-bit fields can be extracted using IAND and ISHFT.

> This seems to be the way! Thanks!

Not in Fortran. Here we have a higher-level intrinsic, IBITS, for
extracting bit fields.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


dpb

unread,
Aug 30, 2012, 3:38:37 PM8/30/12
to
On 8/30/2012 10:33 AM, James Van Buskirk wrote:
> "Arjan"<arjan.v...@rivm.nl> wrote in message
> news:5060ab6b-d75e-44b2...@googlegroups.com...
>
>>> The 5-bit fields can be extracted using IAND and ISHFT.
>
>> This seems to be the way! Thanks!
>
> Not in Fortran. Here we have a higher-level intrinsic, IBITS, for
> extracting bit fields.

Ah...glad to see somebody else pointed out IBITS() -- I had missed this
thread earlier somehow.

Which indeed does go a long ways for mapping...I'm only sorry it wasn't
around as an intrinsic back when that was a much more prevalent
occupation in my daily occupation... :)

Still not quite as convenient as a bit field in a structure for multiple
items in a register but a big step forward nonetheless...

There's a plus and a minus on IBITS -- in what appears to be Arjan's
case of a short integer value that IBITS returns the value right-shifted
is _a_good_thing_ (tm) as it gives the numeric result directly from the
decoded bit field. When it's a hdwe control register, say, then it may
be more convenient if the values remain in their same relative location
so that control masks are consistent w/ the hardware description bit
locations instead of moving. As is so many other things, what's best
"all depends"...

--

Steve Lionel

unread,
Aug 30, 2012, 5:06:01 PM8/30/12
to
On 8/30/2012 3:38 PM, dpb wrote:
> Ah...glad to see somebody else pointed out IBITS() -- I had missed this
> thread earlier somehow.
>
> Which indeed does go a long ways for mapping...I'm only sorry it wasn't
> around as an intrinsic back when that was a much more prevalent
> occupation in my daily occupation... :)

But it was! See http://www.fortran.com/mil_std_1753.html This was
implemented in VAX FORTRAN, g77 and other compilers of the time. (I am
assuming your daily occupation didn't end before 1978, of course.)

--
Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran

Refer to http://software.intel.com/en-us/articles/optimization-notice
for more information regarding performance and optimization choices in
Intel software products.

dpb

unread,
Aug 30, 2012, 6:23:28 PM8/30/12
to
On 8/30/2012 4:06 PM, Steve Lionel wrote:
> On 8/30/2012 3:38 PM, dpb wrote:
>> Ah...glad to see somebody else pointed out IBITS() -- I had missed this
>> thread earlier somehow.
>>
>> Which indeed does go a long ways for mapping...I'm only sorry it wasn't
>> around as an intrinsic back when that was a much more prevalent
>> occupation in my daily occupation... :)
>
> But it was! See http://www.fortran.com/mil_std_1753.html This was
> implemented in VAX FORTRAN, g77 and other compilers of the time. (I am
> assuming your daily occupation didn't end before 1978, of course.)

I'm old, but not _THAT_ old, Steve! :)

I didn't do bit twiddling on VAX; I don't recall under RT-11 but I don't
recall it (won't say it wasn't there, just don't remember it
specifically). I'm almost positive it wasn't on HP-1000, either, the
other primary platform I used that did hardware interaction in those
days that supported FORTRAN.

Watcom that was the predominant compiler used when went to PC doesn't
have it to date, even. The environment I was in at the time did not use
open-source so I've never used g77 at all. Did transition eventually to
D(then C)VF, but that application didn't/doesn't do bit-twiddling even
though it does talk to plant control system computer; they're various
high-level things that have all the results already decoded into
floating point before ever sending them out. Most at the time I retired
were running on Sun Solaris; I'm not sure where they've gone since in
the last almost 15 yr now....(my! how time does go by!)

Is IBITS in F77 or just in the Mil-Std, maybe?

--

Richard Maine

unread,
Aug 30, 2012, 6:34:50 PM8/30/12
to
dpb <no...@non.net> wrote:

> Is IBITS in F77 or just in the Mil-Std, maybe?

Not in f77, but in the Mil-Std and subsequently adopted into f90.

The f90 version is pretty much lifted straight from the Mil Std, with
only the minimal changes to translate it into the terminology of the f90
standard. That's why it (and its kin) look so different from other
things added in f90. They were largely a case of just adopting an
existing standard (somewhat like the features from HPF adopted into
f95).

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain

glen herrmannsfeldt

unread,
Aug 30, 2012, 6:37:41 PM8/30/12
to
dpb <no...@non.net> wrote:

(snip)

> I didn't do bit twiddling on VAX; I don't recall under RT-11 but I don't
> recall it (won't say it wasn't there, just don't remember it
> specifically). I'm almost positive it wasn't on HP-1000, either, the
> other primary platform I used that did hardware interaction in those
> days that supported FORTRAN.

I don't remember specifically which compilers (Steve probably does)
but DEC tradition was to allow the use of the logical operators
(such as .AND. and .OR.) on in INTEGER expressions.

I remember that to the PDP-10/TOPS-10 compilers.

From AA-D034E-TE_VAX_FORTRAN_Language_Reference_Manual_Jun88.pdf
on bitsavers.org, it seems that VAX (in 1988) has both the
bitwise functions (IAND, etc.) and also allows the use of logical
operators on integer values.

-- glen

glen herrmannsfeldt

unread,
Aug 30, 2012, 7:04:35 PM8/30/12
to
dpb <no...@non.net> wrote:

(snip)

> I didn't do bit twiddling on VAX; I don't recall under RT-11 but I don't
> recall it (won't say it wasn't there, just don't remember it
> specifically). I'm almost positive it wasn't on HP-1000, either, the
> other primary platform I used that did hardware interaction in those
> days that supported FORTRAN.

From AA-R953A-TK_F4LangRef_Mar83.pdf the use of logical operators
on integer values (.AND., etc.) was allowed. I believe that is for
the compiler that RT-11 used. (In 1983).

As the HP 1000 was often used for what now would be embedded
control operations, I would have been very surprised if it didn't
have bitwise operations.

From:

http://www.hp.com/products1/rte/tech_support/documentation/documentation3/92836-90001.pdf

it seems that they also used the logical operators on integer
(and double integer) values as bitwise operators, and also
support the bit manipulation functions.

I don't see the Fortran IV manual on either bitsavers or hp.com,
but I might not have looked hard enough.

Early versions of the IBM OS/360 Fortran H compiler supported
the bitwise functions by default. As it wasn't part of the standard,
later versions required the XL compiler option to turn them on.
(They were needed to compile the compiler itself.)

-- glen

glen herrmannsfeldt

unread,
Aug 30, 2012, 7:10:27 PM8/30/12
to
Richard Maine <nos...@see.signature> wrote:
> dpb <no...@non.net> wrote:

>> Is IBITS in F77 or just in the Mil-Std, maybe?

> Not in f77, but in the Mil-Std and subsequently adopted into f90.

Were they required for F77 compilers sold to the government?

In a quick look, it seems that the VAX and HP1000 Fortran 77
compilers had them, in addition to the use of logical operators
that earlier DEC compilers used for bitwise operations.

-- glen

Richard Maine

unread,
Aug 30, 2012, 7:23:12 PM8/30/12
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

> Richard Maine <nos...@see.signature> wrote:
> > dpb <no...@non.net> wrote:
>
> >> Is IBITS in F77 or just in the Mil-Std, maybe?
>
> > Not in f77, but in the Mil-Std and subsequently adopted into f90.
>
> Were they required for F77 compilers sold to the government?

No. Certainly not in general. Perhaps, even probably, in special cases,
but that's not what you appear to have asked.

Since I worked in a government site that certainly bought plenty of
compilers without the Mil Std intrinsics, I'm pretty sure of that
answer.

dpb

unread,
Aug 30, 2012, 7:42:46 PM8/30/12
to
On 8/30/2012 5:37 PM, glen herrmannsfeldt wrote:
> dpb<no...@non.net> wrote:
>
> (snip)
>
>> I didn't do bit twiddling on VAX; I don't recall under RT-11 but I don't
>> recall it (won't say it wasn't there, just don't remember it
>> specifically). I'm almost positive it wasn't on HP-1000, either, the
>> other primary platform I used that did hardware interaction in those
>> days that supported FORTRAN.
>
> I don't remember specifically which compilers (Steve probably does)
> but DEC tradition was to allow the use of the logical operators
> (such as .AND. and .OR.) on in INTEGER expressions.
>
> I remember that to the PDP-10/TOPS-10 compilers.
...

I had some access to the ORNL PDP-10 but it essentially only used for
hosting editors and similar stuff as a front end to the
compute-intensive machines.

Should probably note that the HP-1000's I worked with were embedded in
the HP5451 Analyzer instruments and were not much related to the "real"
HP-1000 series other than the same CPU unit. The FORTRAN compiler was a
special version adapted to interact w/ the analyzer hardware and the
keyboard programming language that was a RPN-like syntax somewhat
similar to the calculators....very cool (and expensive) toys
(particularly when HP finally added a pizza-oven hard disk and were able
to ditch the multi-pass paper tape compiler).

--

dpb

unread,
Aug 30, 2012, 8:01:04 PM8/30/12
to
On 8/30/2012 6:04 PM, glen herrmannsfeldt wrote:
> dpb<no...@non.net> wrote:
>
> (snip)
>
>> I didn't do bit twiddling on VAX; I don't recall under RT-11 but I don't
>> recall it (won't say it wasn't there, just don't remember it
>> specifically). I'm almost positive it wasn't on HP-1000, either, the
>> other primary platform I used that did hardware interaction in those
>> days that supported FORTRAN.
>
> From AA-R953A-TK_F4LangRef_Mar83.pdf the use of logical operators
> on integer values (.AND., etc.) was allowed. I believe that is for
> the compiler that RT-11 used. (In 1983).

As I said, I just don't recall on RT-11; it wasn't one I did much on...

> As the HP 1000 was often used for what now would be embedded
> control operations, I would have been very surprised if it didn't
> have bitwise operations.
>
> From:
>
> http://www.hp.com/products1/rte/tech_support/documentation/documentation3/92836-90001.pdf
>
> it seems that they also used the logical operators on integer
> (and double integer) values as bitwise operators, and also
> support the bit manipulation functions.
>
> I don't see the Fortran IV manual on either bitsavers or hp.com,
> but I might not have looked hard enough.
...

As noted above, the HP1000s I used were embedded in a series of instruments

<http://www.computerhistory.org/collections/accession/102692715>

"Real" F77 wasn't available; it was called HP FORTRAN iirc. The
analyzer booted to a dedicated instrument that had access to Fortran but
wasn't actually RTE. You could boot RTE but then did not have access to
the analyzer functions; only the processor.

--

Arjan

unread,
Aug 31, 2012, 3:41:38 AM8/31/12
to
>>> The 5-bit fields can be extracted using IAND and ISHFT.

>> This seems to be the way! Thanks!

> Not in Fortran. Here we have a higher-level intrinsic, IBITS, for
> extracting bit fields.


You are completely right! My practical problem was already solved with the first hint, but I am glad that I have learned this shorter and to be honest neater solution!

I always get a smile from left ear to right ear when I see the subsequent avalanche that some discussions on this forum tend to generate after solving the original issue, with lots of references to PDP-machines and paper-tape! A few (less than 10) years ago, I had to review a scientific paper based on measurements collected with a newly built experimental set-up constructed around a PDP-11 and that laboratory was not even situated in a science museum! I immediately accepted the paper in respect to the machine!

Arjan

unread,
Aug 31, 2012, 5:16:42 AM8/31/12
to
> Here we have a higher-level intrinsic, IBITS, for extracting bit fields.



I am a bit surprised that IBITS only eats INTEGER arguements. Why this restriction?

Dan Nagle

unread,
Aug 31, 2012, 7:53:02 AM8/31/12
to
Hi,
The Mil Std was published a few months after f77, and got its
bit-fiddling stuff
from a earlier spec for something like "real-time fortran" published
by an industrial consortium intended, IIRC, for controlling robots.

(I don't know the sources of the other items in Mil Std 1753, that is,
end do, implicit none, do while, and requiring several files be supported
on one connection.)

Integers were the only reasonable portable type available pre-f77,
and there was never any serious move to widen the types AFAIK until the
bit type
that might have been part of f08.

--
Cheers!

Dan Nagle

Gary Scott

unread,
Aug 31, 2012, 9:08:30 AM8/31/12
to
On 8/31/2012 6:53 AM, Dan Nagle wrote:
> Hi,
>
> On 2012-08-31 09:16:42 +0000, Arjan said:
>
>> > Here we have a higher-level intrinsic, IBITS, for extracting bit
>> fields.
>>
>>
>>
>> I am a bit surprised that IBITS only eats INTEGER arguements. Why this
>> restriction?
>
> The Mil Std was published a few months after f77, and got its
> bit-fiddling stuff
> from a earlier spec for something like "real-time fortran" published
> by an industrial consortium intended, IIRC, for controlling robots.
>
> (I don't know the sources of the other items in Mil Std 1753, that is,
> end do, implicit none, do while, and requiring several files be supported
> on one connection.)

All or most were implemented in some compilers as the "Purdue
extensions", without reference to the MIL STD. I don't know if that is
the ultimate source for some or all of them.

glen herrmannsfeldt

unread,
Aug 31, 2012, 9:14:14 AM8/31/12
to
What other types would you suggest?

You might suggest LOGICAL, but many questions come up in that case.

Mixing of INTEGER and LOGICAL can be very confusing in the
implementations that allow it. (Many of the DEC compilers I
previously mentioned do allow it.)

Floating point types could give very interesting results.
In the Fortran 77 days, mixing floating point and integer data
was done using EQUIVALENCE in a non-standard way. (At least
partly non-standard as the floating point formats were
non-standard.)

Now there is TRANSFER to move bits. TRANSFER used with the bitwise
functions should allow any type to be used.

-- glen

glen herrmannsfeldt

unread,
Aug 31, 2012, 9:20:22 AM8/31/12
to
Gary Scott <garyl...@sbcglobal.net> wrote:

(snip on the bitwise logical functions)

>> (I don't know the sources of the other items in Mil Std 1753, that is,
>> end do, implicit none, do while, and requiring several files be supported
>> on one connection.)

> All or most were implemented in some compilers as the "Purdue
> extensions", without reference to the MIL STD. I don't know if that is
> the ultimate source for some or all of them.

Is there a reference to them from before OS/360 Fortran H?

They were needed there to compile the compiler, one of the few
Fortran compilers (mostly) written in Fortran.

-- glen

Ron Shepard

unread,
Aug 31, 2012, 9:43:28 AM8/31/12
to
In article <52aab483-04f5-4239...@googlegroups.com>,
There are various problems with the other data types, logical,
character, and real. With real data, for example, some hardware
uses different registers for real and general data, and the
operations on the real registers are limited to floating point
things. Also, some compilers at the time would normalize any item
as it was assigned to a REAL variable, so this would corrupt any bit
pattern that did not match an actual floating point value.

$.02 -Ron Shepard

Steve Lionel

unread,
Aug 31, 2012, 11:04:35 AM8/31/12
to
On 8/30/2012 7:10 PM, glen herrmannsfeldt wrote:
> Were they required for F77 compilers sold to the government?

In some cases, yes, but not all the time. I saw quite a few RFPs from
government contractors requiring MIL-STD-1753 support.

Steve Lionel

unread,
Aug 31, 2012, 11:09:47 AM8/31/12
to
On 8/30/2012 6:37 PM, glen herrmannsfeldt wrote:
> I don't remember specifically which compilers (Steve probably does)
> but DEC tradition was to allow the use of the logical operators
> (such as .AND. and .OR.) on in INTEGER expressions.

I am pretty sure it wasn't just DEC, but yes, free conversion between
numeric and logical has been in DEC compilers (and their successors) for
decades, including bitwise logical operators. Over the years we've
slowly backed off from this in default mode - nowadays in the Intel
compilers, you no longer can use T and F as valid input for
list-directed and namelist numeric items. I've asked that an optional
diagnostic be issued whenever conversion appears in code, but so far
that hasn't made it in. (It is diagnosed if you ask for standards
warnings, of course.)

glen herrmannsfeldt

unread,
Aug 31, 2012, 12:24:31 PM8/31/12
to
Steve Lionel <steve....@intel.invalid> wrote:
> On 8/30/2012 6:37 PM, glen herrmannsfeldt wrote:
>> I don't remember specifically which compilers (Steve probably does)
>> but DEC tradition was to allow the use of the logical operators
>> (such as .AND. and .OR.) on in INTEGER expressions.

> I am pretty sure it wasn't just DEC, but yes, free conversion between
> numeric and logical has been in DEC compilers (and their successors) for
> decades, including bitwise logical operators.

Other small computer companies might have done it to be DEC
compatible.

I never knew it in IBM compilers, though.

(The only one byte type in the OS/360 compilers is LOGICAL*1,
and you can't use relational operators on it. Otherwise, it
was convenient for character data, being the right size.)

-- glen

Dick Hendrickson

unread,
Aug 31, 2012, 12:59:33 PM8/31/12
to
On 8/31/12 11:24 AM, glen herrmannsfeldt wrote:
> Steve Lionel<steve....@intel.invalid> wrote:
>> On 8/30/2012 6:37 PM, glen herrmannsfeldt wrote:
>>> I don't remember specifically which compilers (Steve probably does)
>>> but DEC tradition was to allow the use of the logical operators
>>> (such as .AND. and .OR.) on in INTEGER expressions.
>
>> I am pretty sure it wasn't just DEC, but yes, free conversion between
>> numeric and logical has been in DEC compilers (and their successors) for
>> decades, including bitwise logical operators.
>
> Other small computer companies might have done it to be DEC
> compatible.
>
The CDC and Cray compilers allowed the logical operators to be used with
any single word type. They mapped directly to the hardware full-word
and, or, etc., instructions. At Cray the result was generally called
typeless. "Chameleon type" would have been a better name. The result
assumed whatever type it needed to be without any bit conversions.
Other companies in the Big Iron field had similar extensions.

Dick Hendrickson

Rafik Zurob

unread,
Aug 31, 2012, 6:54:44 PM8/31/12
to
> Other small computer companies might have done it to be DEC
> compatible.
>
> I never knew it in IBM compilers, though.
>

On AIX/Linux/BlueGene, XL Fortran supports this extension via the -qintlog
option
http://pic.dhe.ibm.com/infocenter/lnxpcomp/v111v131/topic/com.ibm.xlf131.linux.doc/compiler_ref/intlog.html

It's off by default though.

Regards

Rafik


James Van Buskirk

unread,
Aug 31, 2012, 7:44:25 PM8/31/12
to
"Steve Lionel" <steve....@intel.invalid> wrote in message
news:aac2dt...@mid.individual.net...

> On 8/30/2012 6:37 PM, glen herrmannsfeldt wrote:

>> I don't remember specifically which compilers (Steve probably does)
>> but DEC tradition was to allow the use of the logical operators
>> (such as .AND. and .OR.) on in INTEGER expressions.

> I am pretty sure it wasn't just DEC, but yes, free conversion between
> numeric and logical has been in DEC compilers (and their successors) for
> decades, including bitwise logical operators. Over the years we've slowly
> backed off from this in default mode - nowadays in the Intel compilers,
> you no longer can use T and F as valid input for list-directed and
> namelist numeric items. I've asked that an optional diagnostic be issued
> whenever conversion appears in code, but so far that hasn't made it in.
> (It is diagnosed if you ask for standards warnings, of course.)

As i have had occasion to point out previously, if the compiler
allows free mixing of logical and integer types, then, assuming that
0 is the canonical .FALSE. value and 1 is a .TRUE. value:

if x is .TRUE., then 1 .AND. x must be .TRUE. as well, so the
low bit of x must be set. Similarly, if x is .FALSE. then
1 .AND. x must be .FALSE., so the low bit of x must be clear.
Therefore the value of x depends only on its low bit.

Also .NOT. 0 is -1, so the canonical value of .TRUE. must be -1.

Now, this could be consistent with the C _Bool type provided the
C compiler considered only the low bit of an _Bool to contribute
to its value and set the high bits when creating the true _Bool
value. Unfortunately C compilers paradoxically examine all bits
of an _Bool when determining whether it is false (all bits zero)
or true (anything else). The C compiler could follow the extended
Fortran behavior and still conform to the standard, but this choice
is never made, so any Fortran compiler that permits mixing of real
and logical expressions must set C_BOOL to -1 unless it has a
special logical kind that doesn't obey the arithmetic rules of the
other logical kinds.

Richard Maine

unread,
Aug 31, 2012, 8:40:17 PM8/31/12
to
James Van Buskirk <not_...@comcast.net> wrote:
[stuff elided]
> Now, this could be consistent with the C _Bool type provided the
> C compiler considered only the low bit of an _Bool to contribute
> to its value and set the high bits when creating the true _Bool
> value. Unfortunately C compilers paradoxically examine all bits
> of an _Bool when determining whether it is false (all bits zero)
> or true (anything else). The C compiler could follow the extended
> Fortran behavior and still conform to the standard, but this choice
> is never made, so any Fortran compiler that permits mixing of real
> and logical expressions must set C_BOOL to -1 unless it has a
> special logical kind that doesn't obey the arithmetic rules of the
> other logical kinds.

I'm pretty sure I have disagreed with James on this before. I'm certain
I have disagreed with him on closely related points, but just in case,
I'll note (perhaps again) that I do disagree with this line of
reasoning.

Allowing the mixing of real (or integer) and logical expressions can be
a valid compiler extension. It can give surprising results, as James
explains. But the fact that an extension might give surprising results
does not change the requirements of the standard. As long as the
compiler gives the required results for standard conforming code, the
compiler is standard conforming. In particular, a compiler could set
C_BOOL to a positive value as long as it was interoperable within the
context of completely standard conforming code.

The fact that the compiler might also support an extension that gave
surprising results would not be grounds to say that the standard
required that C_BOOL be -1. I seem to recall the folk familliar with the
details of the C standard saying simillar things on that side - that
some of the previously proffered C code did not adhere to the C standard
and thus its failure to give the expected results could not be
considered as the compiler violating the standard.

I'll not argue about how desirable various behaviors might be or the
reasons that some compiler might do things other than what James
desires. That's a never-ending subject. I restrict my comments solely to
interpretation of what the standard requires - not of what someone might
like it to require. I do not interpret the standard as requiring that
C_BOOL be -1 in the cases that James describes.

James Van Buskirk

unread,
Aug 31, 2012, 9:36:41 PM8/31/12
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1kppcb2.8kbc981rhnj9oN%nos...@see.signature...
Allowing free mixing of integer and logical expressions as an
extension does have an effect on standard-conforming code. Just
start out with an expression valid under the extension and then
insert TRANSFER as necessary to make the expression standard-
conforming. Since the compiler makes no distinction between
integer and logical types as extension, the extra TRANSFERs do
nothing to the extended interpretation of the code, but the
code becomes standard-conforming so this fixes the internal
representation of logical variables.

> The fact that the compiler might also support an extension that gave
> surprising results would not be grounds to say that the standard
> required that C_BOOL be -1. I seem to recall the folk familliar with the
> details of the C standard saying simillar things on that side - that
> some of the previously proffered C code did not adhere to the C standard
> and thus its failure to give the expected results could not be
> considered as the compiler violating the standard.

My recollection is different, of course.

> I'll not argue about how desirable various behaviors might be or the
> reasons that some compiler might do things other than what James
> desires. That's a never-ending subject. I restrict my comments solely to
> interpretation of what the standard requires - not of what someone might
> like it to require. I do not interpret the standard as requiring that
> C_BOOL be -1 in the cases that James describes.

Maybe it's feasible to set C_BOOL /= -1, but it's quite a stretch
and requires just about tearing apart the compiler to make it
work out. My advice is never to attempt to make Fortran logical
types interoperate with _Bool in practice, but to interpret
the _Bool as C_INT8_T and use the documented behavior of the
C compiler to resolve what value is intended to be transmitted
or stored.

Richard Maine

unread,
Aug 31, 2012, 9:46:07 PM8/31/12
to
James Van Buskirk <not_...@comcast.net> wrote:

> "Richard Maine" <nos...@see.signature> wrote in message
> news:1kppcb2.8kbc981rhnj9oN%nos...@see.signature...
>
> > I'm pretty sure I have disagreed with James on this before. I'm certain
> > I have disagreed with him on closely related points, but just in case,
> > I'll note (perhaps again) that I do disagree with this line of
> > reasoning.
>
> > Allowing the mixing of real (or integer) and logical expressions can be
> > a valid compiler extension. It can give surprising results, as James
> > explains. But the fact that an extension might give surprising results
> > does not change the requirements of the standard. As long as the
> > compiler gives the required results for standard conforming code, the
> > compiler is standard conforming. In particular, a compiler could set
> > C_BOOL to a positive value as long as it was interoperable within the
> > context of completely standard conforming code.
>
> Allowing free mixing of integer and logical expressions as an
> extension does have an effect on standard-conforming code. Just
> start out with an expression valid under the extension and then
> insert TRANSFER as necessary to make the expression standard-
> conforming. Since the compiler makes no distinction between
> integer and logical types as extension, the extra TRANSFERs do
> nothing to the extended interpretation of the code, but the
> code becomes standard-conforming so this fixes the internal
> representation of logical variables.

I think I'll not reply further on the thread because I recall exactly
this kind of argument before. Obviously neither of our opinions changed
then, so they aren't likely to now.

If there is code *ANYWHERE* in the program that doesn't conform to the
standard, then the program doesn't conform to the standard. You don't
get to pick and choose which parts count and then say that the rest of
the code conforms to the standard and thus ought to work as you'd like.

glen herrmannsfeldt

unread,
Aug 31, 2012, 10:07:01 PM8/31/12
to
James Van Buskirk <not_...@comcast.net> wrote:

(snip on using logical operators on integer values)

> As i have had occasion to point out previously, if the compiler
> allows free mixing of logical and integer types, then, assuming that
> 0 is the canonical .FALSE. value and 1 is a .TRUE. value:

> if x is .TRUE., then 1 .AND. x must be .TRUE. as well, so the
> low bit of x must be set. Similarly, if x is .FALSE. then
> 1 .AND. x must be .FALSE., so the low bit of x must be clear.
> Therefore the value of x depends only on its low bit.

> Also .NOT. 0 is -1, so the canonical value of .TRUE. must be -1.

That is why C has separate logical (|| and &&) operators and
bitwise(|, &, ^) operators. Well, as I understand it, the
predecessors to C had only one set of operators. (The other
reason for the change is to allow for short circuit evaluation.)

A side effect of the late change is the confusing precedence
for the bitwise operators.

> Now, this could be consistent with the C _Bool type provided the
> C compiler considered only the low bit of an _Bool to contribute
> to its value and set the high bits when creating the true _Bool
> value. Unfortunately C compilers paradoxically examine all bits
> of an _Bool when determining whether it is false (all bits zero)
> or true (anything else). The C compiler could follow the extended
> Fortran behavior and still conform to the standard, but this choice
> is never made, so any Fortran compiler that permits mixing of real
> and logical expressions must set C_BOOL to -1 unless it has a
> special logical kind that doesn't obey the arithmetic rules of the
> other logical kinds.

-- glen

glen herrmannsfeldt

unread,
Aug 31, 2012, 10:12:39 PM8/31/12
to
Richard Maine <nos...@see.signature> wrote:
> James Van Buskirk <not_...@comcast.net> wrote:
> [stuff elided]
>> Now, this could be consistent with the C _Bool type provided the
>> C compiler considered only the low bit of an _Bool to contribute
>> to its value and set the high bits when creating the true _Bool
>> value. Unfortunately C compilers paradoxically examine all bits
>> of an _Bool when determining whether it is false (all bits zero)
>> or true (anything else). The C compiler could follow the extended
>> Fortran behavior and still conform to the standard, but this choice
>> is never made, so any Fortran compiler that permits mixing of real
>> and logical expressions must set C_BOOL to -1 unless it has a
>> special logical kind that doesn't obey the arithmetic rules of the
>> other logical kinds.

> I'm pretty sure I have disagreed with James on this before. I'm certain
> I have disagreed with him on closely related points, but just in case,
> I'll note (perhaps again) that I do disagree with this line of
> reasoning.

> Allowing the mixing of real (or integer) and logical expressions can be
> a valid compiler extension. It can give surprising results, as James
> explains. But the fact that an extension might give surprising results
> does not change the requirements of the standard.

Actually, I didn't completely figure out what he meant.

I know how the C operators work, and how they can go right
or go wrong. But remember, C has separate logical and bitwise
operators.

The logical operators accept zero (false) not zero (true)
as input, and always generate zero (false) one (true).

If you use bitwise operators, you can find two non-zero (true)
values that AND to false.

> As long as the
> compiler gives the required results for standard conforming code, the
> compiler is standard conforming. In particular, a compiler could set
> C_BOOL to a positive value as long as it was interoperable within the
> context of completely standard conforming code.

(snip)

-- glen

Tobias Burnus

unread,
Sep 1, 2012, 4:49:06 AM9/1/12
to
James Van Buskirk wrote:
> As i have had occasion to point out previously, if the compiler
> allows free mixing of logical and integer types, then, assuming that
> 0 is the canonical .FALSE. value and 1 is a .TRUE. value:

But you cannot assume that .false. is 0 and .true. is 1. I know at least
one compiler were .true. is -1.


> if x is .TRUE., then 1 .AND. x must be .TRUE. as well, so the
> low bit of x must be set. Similarly, if x is .FALSE. then
> 1 .AND. x must be .FALSE., so the low bit of x must be clear.

Well, you assume some bitwide handling of
<logical-expr> .AND. <integer-expr>
where one then looks afterwards only at a single bit (i.e. treats it as
logical). However, the compiler is not necessarily the case. For
instance, in C99 it is not possible as the resulting expression is "int"
and if you do "if(<int-expr>)" you may not look at a single bit.

By contrast, a Fortran compiler is completely free to handle it as it
wants, but technically there is no reason which rules out that
if (2 .or. .false.)
has the bit value of 2, 1 or -1. Some choices make more sense in
different contexts, but all are possible.


> Also .NOT. 0 is -1, so the canonical value of .TRUE. must be -1.

> Now, this could be consistent with the C _Bool type provided the
> C compiler considered only the low bit of an _Bool to contribute
> to its value and set the high bits when creating the true _Bool
> value. Unfortunately C compilers paradoxically examine all bits
> of an _Bool when determining whether it is false (all bits zero)
> or true (anything else).


I have to admit that I do not understand this part. But I disagree with
several items:

I don't see why .NOT. 0 should be -1. You could also flip only the other
bit such that .NOT. 0 is 1.

Of course, that assumes that you either always look only at the single
bit - for instance because you know that the variable only has the two
values.

That assumption you can do in Fortran for a chosen implementation.
(That's independent whether you support integer expressions in logical
expressions; the implementation itself then depends on this choice.)

But that assumption you can also do in C as you know that _Bool only has
two values: 0 and 1.

The reason that C compilers often look at more than a single bit is that
most "Boolean" operators return and "int", e.g.

"The result of the logical negation operator ! is 0 if the value of its
operand compares unequal to 0, 1 if the value of its operand compares
equal to 0. The result has type int. The expression !E is equivalent to
(0==E)." (C99, 6.5.3.3)

But if the compiler knows that "E" is always either 0 or 1, it can flip
a single bit. But that's actually the case for C99's Boolean type (6.3.1.2):

"When any scalar value is converted to _Bool, the result is 0 if the
value compares equal to 0; otherwise, the result is 1."


I think for conditions, it doesn't matter that much whether one checks
whether "%register is zero", however, for ".not.logical_var", flipping a
single bit is advantageous.


> The C compiler could follow the extended
> Fortran behavior and still conform to the standard, but this choice
> is never made, so any Fortran compiler that permits mixing of real
> and logical expressions must set C_BOOL to -1

I am lost again. Why should a compiler set C_Bool to -1? It just has to
comply to C99 by ensuring that only 0 and 1 are passed to the register.
Or alternatively, the same-vendor C compiler has to handle it in the
same way. My impression is that this works rather well.


However, it doesn't work well if one mixes compilers of two vendors. If
you take a compiler which returns -1 for .true. and another one which
flips the lower bit, then ".not. true()" will be "-2" which might be
regarded as .true.

That's actually a real-world problem. But I still maintain that this is
independent of supporting integers as logical. For instance, both
compilers do support "logical b; b = 2".

Tobias

Clive Page

unread,
Sep 1, 2012, 7:25:54 AM9/1/12
to
On 31/08/2012 12:53, Dan Nagle wrote:
> Hi,
>
> On 2012-08-31 09:16:42 +0000, Arjan said:
>
>> > Here we have a higher-level intrinsic, IBITS, for extracting bit fields.
>>
>>
>>
>> I am a bit surprised that IBITS only eats INTEGER arguements. Why this
>> restriction?
>
> Integers were the only reasonable portable type available pre-f77,
> and there was never any serious move to widen the types AFAIK until the
> bit type
> that might have been part of f08.
>

One thing I only noticed recently, is that F2008 allows B, O, and Z
format descriptors to be used on real as well as integer data items.
In earlier standards only integer type was valid. Maybe someone should
suggest extending IBITS etc to other data types, for Fortran201x or
maybe Fortran202x?


--
Clive Page

Dan Nagle

unread,
Sep 1, 2012, 7:57:29 AM9/1/12
to
Hi,

On 2012-09-01 08:49:06 +0000, Tobias Burnus said:

> James Van Buskirk wrote:
>> As i have had occasion to point out previously, if the compiler
>> allows free mixing of logical and integer types, then, assuming that
>> 0 is the canonical .FALSE. value and 1 is a .TRUE. value:
>
> But you cannot assume that .false. is 0 and .true. is 1. I know at
> least one compiler were .true. is -1.

Sound like you better use .true.**2 when using that compiler.

--
Cheers!

Dan Nagle

Robin Vowels

unread,
Sep 1, 2012, 11:06:56 AM9/1/12
to
On Sep 1, 9:44 am, "James Van Buskirk" <not_va...@comcast.net> wrote:
> "Steve Lionel" <steve.lio...@intel.invalid> wrote in message
>
> news:aac2dt...@mid.individual.net...
>
> > On 8/30/2012 6:37 PM, glen herrmannsfeldt wrote:
> >> I don't remember specifically which compilers (Steve probably does)
> >> but DEC tradition was to allow the use of the logical operators
> >> (such as .AND. and .OR.) on in INTEGER expressions.
> > I am pretty sure it wasn't just DEC, but yes, free conversion between
> > numeric and logical has been in DEC compilers (and their successors) for
> > decades, including bitwise logical operators.  Over the years we've slowly
> > backed off from this in default mode - nowadays in the Intel compilers,
> > you no longer can use T and F as valid input for list-directed and
> > namelist numeric items.  I've asked that an optional diagnostic be issued
> > whenever conversion appears in code, but so far that hasn't made it in.
> > (It is diagnosed if you ask for standards warnings, of course.)
>
> As i have had occasion to point out previously, if the compiler
> allows free mixing of logical and integer types, then, assuming that
> 0 is the canonical .FALSE. value and 1 is a .TRUE. value:
>
> if x is .TRUE., then 1 .AND. x must be .TRUE. as well, so the
> low bit of x must be set.  Similarly, if x is .FALSE. then
> 1 .AND. x must be .FALSE., so the low bit of x must be clear.
> Therefore the value of x depends only on its low bit.
>
> Also .NOT. 0 is -1, so the canonical value of .TRUE. must be -1.

That would depend on the compiler. I tried .not. 0 on one compiler,
and it gives exactly 1, not -1.

If the compiler of which you speak permits/permitted the intermixing
of logical and integer variables/values,
then I would expect it to use 0 for false and 1 for true.

> Now, this could be consistent with the C _Bool type provided the
> C compiler considered only the low bit of an _Bool to contribute
> to its value and set the high bits when creating the true _Bool
> value.  Unfortunately C compilers paradoxically examine all bits
> of an _Bool when determining whether it is false (all bits zero)
> or true (anything else).  The C compiler could follow the extended
> Fortran behavior and still conform to the standard, but this choice
> is never made, so any Fortran compiler that permits mixing of real
> and logical expressions must set C_BOOL to -1

And what if it doesn't?

Robin Vowels

unread,
Sep 1, 2012, 11:13:32 AM9/1/12
to
On Sep 1, 6:49 pm, Tobias Burnus <bur...@net-b.de> wrote:

> I don't see why .NOT. 0 should be -1. You could also flip only the other
> bit such that .NOT. 0 is 1.

There's no reason that .true. has to be 1.
There's no reason that the compiler can't set the most-significant
bit to 1 for true, and 0 otherwise.

Or any other bit.

The only requirement is that it can recognize true and false,
and that logical expressions evaluate correctly.

Dick Hendrickson

unread,
Sep 1, 2012, 3:34:20 PM9/1/12
to
Once again, Robin and I are in complete agreement!

The old Cray compiler used the sign bit for true (1) and false (0). The
other 63 bits were random. It turns out that it was always at least one
clock cycle faster to use the sign bit and not clear the remaining bits.
A standard confirming code couldn't tell the difference; other than by
looking at wall clock time ;) .

Later on, the newer compilers switched to 1 and 0, probably for C
compatibility.

Dick Hendrickson

Robin Vowels

unread,
Sep 1, 2012, 7:54:59 PM9/1/12
to
On Sep 1, 6:49 pm, Tobias Burnus <bur...@net-b.de> wrote:

> That's actually a real-world problem. But I still maintain that this is
> independent of supporting integers as logical. For instance, both
> compilers do support "logical b; b = 2".

And since the value of the logical 'b' is binary 2 [presumably],
what happens when you use 'b' the way in which it is intended,
namely, in a logical expression? Or in output?

James Van Buskirk

unread,
Sep 1, 2012, 10:07:48 PM9/1/12
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1kppfvx.1xbpy33124suimN%nos...@see.signature...

> I think I'll not reply further on the thread because I recall exactly
> this kind of argument before. Obviously neither of our opinions changed
> then, so they aren't likely to now.

> If there is code *ANYWHERE* in the program that doesn't conform to the
> standard, then the program doesn't conform to the standard. You don't
> get to pick and choose which parts count and then say that the rest of
> the code conforms to the standard and thus ought to work as you'd like.

The point was that one starts with a program that requires the
extension of freely mixing logical and integer expression and from
that deduces the internal representation of logical variables and
the properties of the operators under the extension. Later one can
use transfer on some of the operands to make the program conforming
but it should generate the same outputs because the compiler treats
logical and integer values the same, even though no mixed operations
actually exist in the final program.

You know, I said this the last time, but my message didn't seem to
get through. I was going to create an example that demonstrated
what I am talking about, but it was rather long-winded and the old
version of ifort I have is too buggy for me to even get started.

Here is what ifort does to my starting point (no, you don't have
to look at this because it's only the non-conforming starting
point, not the standard-conforming version that would demonstrate
the logic of my position.)

C:\gfortran\clf\logtest>type logtest.f90
module printout
implicit none
interface printall
module procedure printlog, printint
end interface printall
contains
subroutine printlog(op, x)
character(*) op
logical x

write(*,'(2a,i0,2a)') op, ' = ', transfer(x,0), &
' .EQV. ', trim(merge('.TRUE. ','.FALSE.',x))
end subroutine printlog

subroutine printint(op, x)
character(*) op
integer x

write(*,'(2a,i0,2a)') op, ' = ', x, &
' .EQV. ', trim(merge('.TRUE. ','.FALSE.', &
transfer(x,.FALSE.)))
end subroutine printint
end module printout

program logtest
use printout
implicit none
integer a, b
logical c, d
character(80) eqn

a = 1
b = 1
c = .TRUE.
d = .TRUE.

write(eqn,'(i0,a,i0)') a, ' + ', b
call printall(trim(eqn), a + b)
write(eqn,'(i0,a,a)') a, ' + ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a + d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' + ', b
call printall(trim(eqn), c + b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' + ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c + d)
write(*,'()')

write(eqn,'(i0,a,i0)') a, ' - ', b
call printall(trim(eqn), a - b)
write(eqn,'(i0,a,a)') a, ' - ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a - d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' - ', b
call printall(trim(eqn), c - b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' - ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c - d)
write(*,'()')

write(eqn,'(i0,a,i0)') a, ' * ', b
call printall(trim(eqn), a * b)
write(eqn,'(i0,a,a)') a, ' * ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a * d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' * ', b
call printall(trim(eqn), c * b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' * ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c * d)
write(*,'()')

write(eqn,'(i0,a,i0)') a, ' / ', b
call printall(trim(eqn), a / b)
write(eqn,'(i0,a,a)') a, ' / ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a / d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' / ', b
call printall(trim(eqn), c / b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' / ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c / d)
write(*,'()')

write(eqn,'(i0,a,i0)') a, ' ** ', b
call printall(trim(eqn), a ** b)
write(eqn,'(i0,a,a)') a, ' ** ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a ** d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' ** ', b
call printall(trim(eqn), c ** b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' ** ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c ** d)
write(*,'()')

write(eqn,'(i0,a,i0)') a, ' .OR. ', b
call printall(trim(eqn), a .OR. b)
write(eqn,'(i0,a,a)') a, ' .OR. ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a .OR. d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' .OR. ', b
call printall(trim(eqn), c .OR. b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' .OR. ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c .OR. d)
write(*,'()')

write(eqn,'(i0,a,i0)') a, ' .AND. ', b
call printall(trim(eqn), a .AND. b)
write(eqn,'(i0,a,a)') a, ' .AND. ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a .AND. d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' .AND. ', b
call printall(trim(eqn), c .AND. b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' .AND. ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c .AND. d)
write(*,'()')

write(eqn,'(i0,a,i0)') a, ' .NEQV. ', b
call printall(trim(eqn), a .NEQV. b)
write(eqn,'(i0,a,a)') a, ' .NEQV. ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a .NEQV. d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' .NEQV. ', b
call printall(trim(eqn), c .NEQV. b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' .NEQV. ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c .NEQV. d)
write(*,'()')

write(eqn,'(i0,a,i0)') a, ' .EQV. ', b
call printall(trim(eqn), a .EQV. b)
write(eqn,'(i0,a,a)') a, ' .EQV. ', &
trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), a .EQV. d)
write(eqn,'(a,a,i0)') trim(merge('.TRUE. ','.FALSE.',c)), &
' .EQV. ', b
call printall(trim(eqn), c .EQV. b)
write(eqn,'(a,a,a)') trim(merge('.TRUE. ','.FALSE.',c)), &
' .EQV. ', trim(merge('.TRUE. ','.FALSE.',d))
call printall(trim(eqn), c .EQV. d)
write(*,'()')

write(eqn,'(a,i0)') '+ ', a
call printall(trim(eqn), + a)
write(eqn,'(a,a)') '+ ', &
trim(merge('.TRUE. ','.FALSE.', c))
call printall(trim(eqn), + c)
write(*,'()')

write(eqn,'(a,i0)') '- ', a
call printall(trim(eqn), - a)
write(eqn,'(a,a)') '- ', &
trim(merge('.TRUE. ','.FALSE.', c))
call printall(trim(eqn), - c)
write(*,'()')

write(eqn,'(a,i0)') '.NOT. ', a
call printall(trim(eqn), .NOT. a)
write(eqn,'(a,a)') '.NOT. ', &
trim(merge('.TRUE. ','.FALSE.', c))
call printall(trim(eqn), .NOT. c)
end program logtest

C:\gfortran\clf\logtest>ifort /fpscomp:nologicals logtest.f90
Intel(R) Fortran Compiler for 32-bit applications, Version 9.1 Build
20061103
Z Package ID: W_FC_C_9.1.033
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 8.00.50727.363
Copyright (C) Microsoft Corporation. All rights reserved.

-out:logtest.exe
-subsystem:console
logtest.obj

C:\gfortran\clf\logtest>logtest
1 + 1 = 2 .EQV. .TRUE.
1 + .TRUE. = 0 .EQV. .FALSE.
.TRUE. + 1 = 0 .EQV. .FALSE.
.TRUE. + .TRUE. = -2 .EQV. .TRUE.

1 - 1 = 0 .EQV. .FALSE.
1 - .TRUE. = 2 .EQV. .TRUE.
.TRUE. - 1 = -2 .EQV. .TRUE.
.TRUE. - .TRUE. = 0 .EQV. .FALSE.

1 * 1 = 1 .EQV. .TRUE.
1 * .TRUE. = -1 .EQV. .TRUE.
.TRUE. * 1 = -1 .EQV. .TRUE.
.TRUE. * .TRUE. = 1 .EQV. .TRUE.

1 / 1 = 1 .EQV. .TRUE.
1 / .TRUE. = -1 .EQV. .TRUE.
.TRUE. / 1 = -1 .EQV. .TRUE.
.TRUE. / .TRUE. = 1 .EQV. .TRUE.

1 ** 1 = 1 .EQV. .TRUE.
1 ** .TRUE. = 1 .EQV. .TRUE.
.TRUE. ** 1 = -1 .EQV. .TRUE.
.TRUE. ** .TRUE. = -1 .EQV. .TRUE.

1 .OR. 1 = 1 .EQV. .TRUE.
1 .OR. .TRUE. = -1 .EQV. .TRUE.
.TRUE. .OR. 1 = -1 .EQV. .TRUE.
.TRUE. .OR. .TRUE. = -1 .EQV. .TRUE.

1 .AND. 1 = 1 .EQV. .TRUE.
1 .AND. .TRUE. = 1 .EQV. .TRUE.
.TRUE. .AND. 1 = 1 .EQV. .TRUE.
.TRUE. .AND. .TRUE. = -1 .EQV. .TRUE.

1 .NEQV. 1 = 0 .EQV. .FALSE.
1 .NEQV. .TRUE. = -2 .EQV. .TRUE.
.TRUE. .NEQV. 1 = -2 .EQV. .TRUE.
.TRUE. .NEQV. .TRUE. = 0 .EQV. .FALSE.

1 .EQV. 1 = -1 .EQV. .TRUE.
1 .EQV. .TRUE. = 1 .EQV. .TRUE.
.TRUE. .EQV. 1 = 1 .EQV. .TRUE.
.TRUE. .EQV. .TRUE. = -1 .EQV. .TRUE.

+ 1 = 1 .EQV. .TRUE.
+ .TRUE. = -1 .EQV. .TRUE.

- 1 = -1 .EQV. .TRUE.
- .TRUE. = 1 .EQV. .TRUE.

.NOT. 1 = -2 .EQV. .TRUE.
.NOT. .TRUE. = 0 .EQV. .FALSE.

The switch /fpscomp:nologicals should set the canonical value
of .TRUE. to -1 and make the value of logical variables follow
only the LSB, but alas on my ancient version of ifort it doesn't
work, as can be seen above.

James Van Buskirk

unread,
Sep 1, 2012, 10:41:19 PM9/1/12
to
"Tobias Burnus" <bur...@net-b.de> wrote in message
news:5041CC02...@net-b.de...

> James Van Buskirk wrote:

>> As i have had occasion to point out previously, if the compiler
>> allows free mixing of logical and integer types, then, assuming that
>> 0 is the canonical .FALSE. value and 1 is a .TRUE. value:

> But you cannot assume that .false. is 0 and .true. is 1. I know at least
> one compiler were .true. is -1.

You ignored the statement I made a little later that if the
canonical value of .FALSE. is 0, then the canonical value of .TRUE.
is .NOT. .FALSE. = NOT(0) = -1. This is the case with ifort and
/fpscomp:nologicals. Notice that I was careful to say above that
"1 is a .TRUE. value" not "1 is the .TRUE. value". Der vs. ein,
nicht?

>> if x is .TRUE., then 1 .AND. x must be .TRUE. as well, so the
>> low bit of x must be set. Similarly, if x is .FALSE. then
>> 1 .AND. x must be .FALSE., so the low bit of x must be clear.

> Well, you assume some bitwide handling of
> <logical-expr> .AND. <integer-expr>
> where one then looks afterwards only at a single bit (i.e. treats it as
> logical). However, the compiler is not necessarily the case. For instance,
> in C99 it is not possible as the resulting expression is "int" and if you
> do "if(<int-expr>)" you may not look at a single bit.

Yeah, but if you interpret mixed logical and integer operations as
&&, ||, ^^, !, instead of &, | ^, ~, then there is no point in
allowing the mixed operations in the first place. The reason mixed
operations were allowed in the first place was so that there was a
syntax for masking operations before MIL-STD 1753. Even since then
sometimes mixed logical operations were more readable before f2008.
For example, given:

integer, parameter :: this = int(Z'00000001')
integer, parameter :: that = int(Z'00000002')
integer, parameter :: the_other_thing = int(Z'00000004')

it's more readable to say:

integer, parameter :: flags = this .OR. that .OR. the_other_thing

than:

integer, parameter :: flags = ior(this,ior(that,the_other_thing))

but since f2008 we have:

integer, parameter :: flags = iany([this,that,the_other_thing])

which is readable and doesn't require mixed integer and logical
operations. But mixed operations are required for masking
expressions in old programs which is why it may make sense for a
compiler to allow them as extensions. But if the effect of
mixed operations isn't the bitwise logical result, then they
serve no purpose and only make it more difficult to catch
programming errors. A C example is:

if(x = 0)

which is conforming, but can be confusing. Without mixed logical
and integer expressions in Fortran you can't make mistakes quite
like this because the expression would be of the wrong type for
the context in which its use is attempted.

> By contrast, a Fortran compiler is completely free to handle it as it
> wants, but technically there is no reason which rules out that
> if (2 .or. .false.)
> has the bit value of 2, 1 or -1. Some choices make more sense in different
> contexts, but all are possible.

>> Also .NOT. 0 is -1, so the canonical value of .TRUE. must be -1.

As noted above you seemed to ignore this.

>> Now, this could be consistent with the C _Bool type provided the
>> C compiler considered only the low bit of an _Bool to contribute
>> to its value and set the high bits when creating the true _Bool
>> value. Unfortunately C compilers paradoxically examine all bits
>> of an _Bool when determining whether it is false (all bits zero)
>> or true (anything else).

> I have to admit that I do not understand this part. But I disagree with
> several items:

> I don't see why .NOT. 0 should be -1. You could also flip only the other
> bit such that .NOT. 0 is 1.

As I said above, if .NOT. 0 is 1, then there is no point in mixed
logical and integer expressions because they don't provide support
for old programs that need them for masking expressions.

> Of course, that assumes that you either always look only at the single
> bit - for instance because you know that the variable only has the two
> values.

> That assumption you can do in Fortran for a chosen implementation. (That's
> independent whether you support integer expressions in logical
> expressions; the implementation itself then depends on this choice.)

> But that assumption you can also do in C as you know that _Bool only has
> two values: 0 and 1.

No, C doesn't say this. Where in the C standard does it say that _Bool
can only have two values? I recall that _Bool is an integer type,
maybe even an unsigned integer type, but I seem to recall from
previous trips around this merry-go-round that it can take on
other values, all true.

> The reason that C compilers often look at more than a single bit is that
> most "Boolean" operators return and "int", e.g.

> "The result of the logical negation operator ! is 0 if the value of its
> operand compares unequal to 0, 1 if the value of its operand compares
> equal to 0. The result has type int. The expression !E is equivalent to
> (0==E)." (C99, 6.5.3.3)

> But if the compiler knows that "E" is always either 0 or 1, it can flip a
> single bit. But that's actually the case for C99's Boolean type (6.3.1.2):

> "When any scalar value is converted to _Bool, the result is 0 if the value
> compares equal to 0; otherwise, the result is 1."

But the interesting cases happen when an _Bool value is set without
any conversion taking place, and that is where the internal
representation of _Bool matters.

> I think for conditions, it doesn't matter that much whether one checks
> whether "%register is zero", however, for ".not.logical_var", flipping a
> single bit is advantageous.

>> The C compiler could follow the extended
>> Fortran behavior and still conform to the standard, but this choice
>> is never made, so any Fortran compiler that permits mixing of real
>> and logical expressions must set C_BOOL to -1

> I am lost again. Why should a compiler set C_Bool to -1? It just has to
> comply to C99 by ensuring that only 0 and 1 are passed to the register. Or
> alternatively, the same-vendor C compiler has to handle it in the same
> way. My impression is that this works rather well.

How can you guarantee that the value of a variable of type
LOGICAL(C_BOOL) ever makes it into a register? There are all
sorts of ways it can be set in standard-conforming code, like
with transfer or through a C_PTR that points at a UDT with
the BIND property, or reading from an unformatted read.

> However, it doesn't work well if one mixes compilers of two vendors. If
> you take a compiler which returns -1 for .true. and another one which
> flips the lower bit, then ".not. true()" will be "-2" which might be
> regarded as .true.

> That's actually a real-world problem. But I still maintain that this is
> independent of supporting integers as logical. For instance, both
> compilers do support "logical b; b = 2".

As I said above, it is counterproductive to allow mixing integer and
logical expressions if the result is not to support masking
expressions.

James Van Buskirk

unread,
Sep 1, 2012, 10:48:53 PM9/1/12
to
"Robin Vowels" <robin....@gmail.com> wrote in message
news:1bb34418-4b32-41b2...@v9g2000pbu.googlegroups.com...

On Sep 1, 9:44 am, "James Van Buskirk" <not_va...@comcast.net> wrote:

> > As i have had occasion to point out previously, if the compiler
> > allows free mixing of logical and integer types, then, assuming that
> > 0 is the canonical .FALSE. value and 1 is a .TRUE. value:

> > if x is .TRUE., then 1 .AND. x must be .TRUE. as well, so the
> > low bit of x must be set. Similarly, if x is .FALSE. then
> > 1 .AND. x must be .FALSE., so the low bit of x must be clear.
> > Therefore the value of x depends only on its low bit.

> > Also .NOT. 0 is -1, so the canonical value of .TRUE. must be -1.

> That would depend on the compiler. I tried .not. 0 on one compiler,
> and it gives exactly 1, not -1.

As I pointed out in my reply a couple of minutes ago to Tobias,
that is counterproductive in that it doesn't provide support for
masking expressions in old programs but also doesn't provide the
protection of separate integer and logical types.

> If the compiler of which you speak permits/permitted the intermixing
> of logical and integer variables/values,
> then I would expect it to use 0 for false and 1 for true.

> > Now, this could be consistent with the C _Bool type provided the
> > C compiler considered only the low bit of an _Bool to contribute
> > to its value and set the high bits when creating the true _Bool
> > value. Unfortunately C compilers paradoxically examine all bits
> > of an _Bool when determining whether it is false (all bits zero)
> > or true (anything else). The C compiler could follow the extended
> > Fortran behavior and still conform to the standard, but this choice
> > is never made, so any Fortran compiler that permits mixing of real
> > and logical expressions must set C_BOOL to -1

> And what if it doesn't?

As I said, either the extension is counterproductive or
LOGICAL(C_BOOL) isn't interoperable with _Bool even though the
compiler claims it is.

Terence

unread,
Sep 2, 2012, 5:21:02 AM9/2/12
to
Seems everyone was posting about the use of bitwise operations on integers.
I just reached that itchy point where I have to post. This was 'SO OLD HAT'!

1) First thing I did on loading my now-renowned shiny new 'ancient MS
v3.31' Fortran compiler in 1985, was, (due to just having used the
expensive-to-run two-tape HP1000 mini for the same commercial social survey
work, was to set up a link library with all the missing functions of bitwise
binary logical operations (IAND,IOR,IXOR,ISHR,NBIT, the IEOR alias, and the
unary INOT operator, defined for 16 and 32 bit registers (i.e integers).
Then I could (really 'still can') use the same Fortran functions I was used
to, and the extra link library took care of these non-intrinsic operators.

I should point out that prior to the faster HP mini, I was renting time on a
360/90 in hour lots.
The mini took 20 minutes and most of the later micros did the same jobs in
under two minutes.
The service bureau of course went out of business. This was because the IBM
software actually tested every bit of every row or column in a double
do-loop, when the bitwise tests were at least 256 times faster and occupied
1/16 th of the storage medium and access time to data (that just for 16 bit
work).

2) After doing any programmed bitwise logical operations, (as were refered
to or implied by posters), one shouldn't use a Fortran logical operator to
test the result as a logical variable, but the more general test on an
integer result as IF (iresult.IAND.ival) THEN (action).
This allowed testing for one or any specific results.

My 'other' compiler, the DVF F90/95 does of course have these intrintrics.
It was strange that IBM didn't have them in the for IBM-AT Fortran compilers
earlier that most of its competitors.



Richard Maine

unread,
Sep 2, 2012, 8:52:54 AM9/2/12
to
Terence <tbwr...@bigpond.net.au> wrote:

> 2) After doing any programmed bitwise logical operations, (as were refered
> to or implied by posters), one shouldn't use a Fortran logical operator to
> test the result as a logical variable, but the more general test on an
> integer result as IF (iresult.IAND.ival) THEN (action).

I would be shocked if you had a compiler that actually accepted that
exact syntax and did what you expected. It has 2 problems.

1. The THEN requires the "action" be in a block terminated by ENDIF
instead of being on the same line. Using THEN with an action on the same
line is a bug I've commented about here before. With implicit typing and
blank insignificance, this can result is undetected bugs when the action
is an assignment statement, as it will actually compile without error,
but do the wrong thing.

2. The expression iresult.iand.ival gives an integer result, so your IF
is in the form

IF (<integer-expression>) ...

The form of IF that alows an integer expression there is the arithmetic
IF, which requires 3 statement numbers rather than an action. There have
been compilers that acepted nonstandard variants of IF, so I can't quite
tell whether you are talking about one of those variants or just have
the syntax further confused; I suspect the latter, but am not sure.

Robin Vowels

unread,
Sep 2, 2012, 9:10:24 AM9/2/12
to
On Sep 2, 12:41 pm, "James Van Buskirk" <not_va...@comcast.net> wrote:

> As I said above, if .NOT. 0 is 1,

There is no requirement for .not. 0 to be anything.
.not. 0 is illegal.

In any case, the internal value of any logical variable is
what the implementer of the compiler decides.

> then there is no point in mixed
> logical and integer expressions because they don't provide support
> for old programs that need them for masking expressions.

Any such old programs are non-standard.

No doubt, such an old program can be made to run
by using an appropriate user-written function and/or
some F90 features.

Robin Vowels

unread,
Sep 2, 2012, 9:12:17 AM9/2/12
to
On Sep 2, 7:22 pm, "Terence" <tbwri...@bigpond.net.au> wrote:

> 2) After doing any programmed bitwise logical operations, (as were refered
> to or implied by posters), one shouldn't use a Fortran logical operator to
> test the result as a logical variable, but the more general test on an
> integer result as    IF (iresult.IAND.ival) THEN (action).

Surely, IF (iand(iresult, ival) ) then

Robin Vowels

unread,
Sep 2, 2012, 9:16:18 AM9/2/12
to
On Sep 2, 12:07 pm, "James Van Buskirk" <not_va...@comcast.net> wrote:

> The point was that one starts with a program that requires the
> extension of freely mixing logical and integer expression and from
> that deduces the internal representation of logical variables and
> the properties of the operators under the extension.

What is the point of that?
Any result is implementation dependent, and may not even be
consistent within the one compiler.

Gary Scott

unread,
Sep 2, 2012, 2:08:07 PM9/2/12
to
On 9/2/2012 7:52 AM, Richard Maine wrote:
> Terence <tbwr...@bigpond.net.au> wrote:
>
>> 2) After doing any programmed bitwise logical operations, (as were refered
>> to or implied by posters), one shouldn't use a Fortran logical operator to
>> test the result as a logical variable, but the more general test on an
>> integer result as IF (iresult.IAND.ival) THEN (action).
>
> I would be shocked if you had a compiler that actually accepted that
> exact syntax and did what you expected. It has 2 problems.
>
> 1. The THEN requires the "action" be in a block terminated by ENDIF
> instead of being on the same line. Using THEN with an action on the same
> line is a bug I've commented about here before. With implicit typing and
> blank insignificance, this can result is undetected bugs when the action
> is an assignment statement, as it will actually compile without error,
> but do the wrong thing.
>
> 2. The expression iresult.iand.ival gives an integer result, so your IF
> is in the form
>
> IF (<integer-expression>) ...
>
> The form of IF that alows an integer expression there is the arithmetic
> IF, which requires 3 statement numbers rather than an action. There have
> been compilers that acepted nonstandard variants of IF, so I can't quite
> tell whether you are talking about one of those variants or just have
> the syntax further confused; I suspect the latter, but am not sure.
>
there were compilers that implemented such things as:

ivalue = ivalue .and. 27 .shift. 8 .rotat. 3

and allowed comparisons in if statements to include .shift. and .rotat.
(and others).

Richard Maine

unread,
Sep 2, 2012, 4:10:46 PM9/2/12
to
Gary Scott <garyl...@sbcglobal.net> wrote:

> > 2. The expression iresult.iand.ival gives an integer result, so your IF
> > is in the form
> >
> > IF (<integer-expression>) ...
> >
> > The form of IF that alows an integer expression there is the arithmetic
> > IF, which requires 3 statement numbers rather than an action. There have
> > been compilers that acepted nonstandard variants of IF, so I can't quite
> > tell whether you are talking about one of those variants or just have
> > the syntax further confused; I suspect the latter, but am not sure.
> >
> there were compilers that implemented such things as:
>
> ivalue = ivalue .and. 27 .shift. 8 .rotat. 3
>
> and allowed comparisons in if statements to include .shift. and .rotat.
> (and others).

Yes, I know there are compilers that allow expressions like that. I
wasn't even commenting about the expression at all - just that the
result ivalue there is still an integer instead of a logical. Yes, I
know that there are also compilers that accept nonstandard variants of
the IF statement (that being what I said above), perhaps even that form,
although I'm not familliar with quite that variant. Note that the form
Terence showed did *NOT* involve a comparison. If it has involved a
comparison, then that would give a logical result and I wouldn't have
commented at all about that (though the form he showed still had THEN
used in a way that I have never seen and would not even be valid as an
extension in fixed source form because it would conflict with otherwise
valid, albeit horrible style, code).

James Van Buskirk

unread,
Sep 2, 2012, 4:22:41 PM9/2/12
to
"James Van Buskirk" <not_...@comcast.net> wrote in message
news:k1uf1j$hei$1...@dont-email.me...

> You know, I said this the last time, but my message didn't seem to
> get through. I was going to create an example that demonstrated
> what I am talking about, but it was rather long-winded and the old
> version of ifort I have is too buggy for me to even get started.

Here is an expanded test of ifort's handling of logical values:

C:\gfortran\clf\logtest>type logtest1.f90
program logtest1
implicit none
integer A
logical L

A = 2
L = transfer(A,L)
call sub(L)
end program logtest1

subroutine sub(x)
implicit none
logical x
character c
integer a(1)
character(*), parameter :: strings(2) = ['.TRUE. ','.FALSE.']
integer i
logical b(1,1)
integer m

write(*,'(a,i0)') 'Value by TRANSFER: ', transfer(x,0)
write(c,'(L1)') x
select case(c)
case('T','t')
write(*,'(a)') 'Value by WRITE: .TRUE.'
case('F','f')
write(*,'(a)') 'Value by WRITE: .FALSE.'
case default
write(*,'(a)') 'WRITE test failed'
end select
select case(x)
case(.TRUE.)
write(*,'(a)') 'Value by SELECT CASE: .TRUE.'
case(.FALSE.)
write(*,'(a)') 'Value by SELECT CASE: .FALSE.'
case default
write(*,'(a)') 'SELECT CASE test failed'
end select
if(x) then
write(*,'(a)') 'Value by IF: .TRUE.'
else
write(*,'(a)') 'Value by IF: .FALSE.'
end if
where([x])
a = 1
elsewhere
a = 2
end where
write(*,'(a)') 'Value by WHERE: '//trim(strings(a(1)))
a = 2
forall(i=1:1,x)
a(i) = 1
end forall
write(*,'(a)') 'Value by FORALL: '//trim(strings(a(1)))
if(all([x])) then
write(*,'(a)') 'Value by ALL: .TRUE.'
else
write(*,'(a)') 'Value by ALL: .FALSE.'
end if
if(any([x])) then
write(*,'(a)') 'Value by ANY: .TRUE.'
else
write(*,'(a)') 'Value by ANY: .FALSE.'
end if
if(count([x]) == 1) then
write(*,'(a)') 'Value by COUNT: .TRUE.'
else
write(*,'(a)') 'Value by COUNT: .FALSE.'
end if
if(dot_product([x],[x])) then
write(*,'(a)') 'Value by DOT_PRODUCT: .TRUE.'
else
write(*,'(a)') 'Value by DOT_PRODUCT: .FALSE.'
end if
write(*,'(a)') 'Value by INDEX: '// &
trim(strings(3-index('AA','A',back=x)))
if(logical(x,selected_int_kind(2))) then
write(*,'(a)') 'Value by LOGICAL: .TRUE.'
else
write(*,'(a)') 'Value by LOGICAL: .FALSE.'
end if
b = reshape([x],shape(b))
b = matmul(b,b)
if(b(1,1)) then
write(*,'(a)') 'Value by MATMUL: .TRUE.'
else
write(*,'(a)') 'Value by MATMUL: .FALSE.'
end if
a = maxloc([2,1],mask=[x,.TRUE.])
write(*,'(a)') 'Value by MAXLOC(MASK): '// &
trim(strings(a(1)))
! a = maxloc([1,1],back=x)
! write(*,'(a)') 'Value by MAXLOC(BACK): '// &
! trim(strings(3-a(1)))
m = maxval([2,1],mask=[x,.TRUE.])
write(*,'(a)') 'Value by MAXVAL: '//trim(strings(3-m))
write(*,'(a)') 'VAlue by MERGE: '// &
trim(merge('.TRUE. ','.FALSE.',x))
a = minloc([1,2],mask=[x,.TRUE.])
write(*,'(a)') 'Value by MINLOC(MASK): '// &
trim(strings(a(1)))
! a = minloc([1,1],back=x)
! write(*,'(a)') 'Value by MINLOC(BACK): '// &
! trim(strings(3-a(1)))
m = minval([1,2],mask=[x,.TRUE.])
write(*,'(a)') 'Value by MINVAL: '//trim(strings(m))
a = pack([1],[x],[2])
write(*,'(a)') 'Value by PACK: '//trim(strings(a(1)))
m = product([2],[x])
write(*,'(a)') 'Value by PRODUCT: '//trim(strings(3-m))
write(*,'(a)') 'Value by SCAN: '// &
trim(strings(3-scan('AA','A',back=x)))
m = sum([1],[x])
write(*,'(a)') 'Value by SUM: '//trim(strings(2-m))
a = unpack([1],[x],[2])
write(*,'(a)') 'Value by UNPACK: '// &
trim(strings(a(1)))
write(*,'(a)') 'Value by VERIFY: '// &
trim(strings(3-verify('AA','b',back=x)))
end subroutine sub

C:\gfortran\clf\logtest>ifort /fpscomp:nologicals logtest1.f90
Intel(R) Fortran Compiler for 32-bit applications, Version 9.1 Build
20061103
Z Package ID: W_FC_C_9.1.033
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 8.00.50727.363
Copyright (C) Microsoft Corporation. All rights reserved.

-out:logtest1.exe
-subsystem:console
logtest1.obj

C:\gfortran\clf\logtest>logtest1
Value by TRANSFER: 2
Value by WRITE: .FALSE.
Value by SELECT CASE: .FALSE.
Value by IF: .FALSE.
Value by WHERE: .FALSE.
Value by FORALL: .FALSE.
Value by ALL: .TRUE.
Value by ANY: .TRUE.
Value by COUNT: .FALSE.
Value by DOT_PRODUCT: .TRUE.
Value by INDEX: .TRUE.
Value by LOGICAL: .FALSE.
Value by MATMUL: .TRUE.
Value by MAXLOC(MASK): .FALSE.
Value by MAXVAL: .TRUE.
VAlue by MERGE: .TRUE.
Value by MINLOC(MASK): .FALSE.
Value by MINVAL: .TRUE.
Value by PACK: .FALSE.
Value by PRODUCT: .TRUE.
Value by SCAN: .TRUE.
Value by SUM: .TRUE.
Value by UNPACK: .FALSE.
Value by VERIFY: .TRUE.

So it looks like it works OK for constructs, but randomly
on intrinsics. Can anyone test the above on recent ifort?

Ian Harvey

unread,
Sep 2, 2012, 5:43:17 PM9/2/12
to
The ALL and ANY tests are different with 12.1.5 and /standard-semantics
on IA-32.

Thomas Koenig

unread,
Sep 2, 2012, 6:35:39 PM9/2/12
to
On 2012-09-02, James Van Buskirk <not_...@comcast.net> wrote:

> Here is an expanded test of ifort's handling of logical values:

[...]

If you play around with TRANSFER and mask arguments to intrinsics,
you are going to get some interesting results in gfortran at least.

Inlined versions usually use use the C convention of "nonzero
is true".

Library versions use a convention that only the lowermost byte gets
looked at, so 1 would be .true. and 256 would be .false. This was
done (by myself) to avoid multiplying the number of library routines
by the number of available LOGICAL kinds (four or five, usually).

So, play with TRANSFER to logical values at your own risk. Here be
dragons :-)

James Van Buskirk

unread,
Sep 2, 2012, 8:41:55 PM9/2/12
to
"Thomas Koenig" <tko...@netcologne.de> wrote in message
news:k20mvr$h73$1...@newsreader4.netcologne.de...
You know, before posting I forgot to give my program the
basic test of setting A = 0 or A = -1 (the documented values of
.TRUE. and .FALSE. for ifort with /fpscomp:nologicals) in program
logtest1 to check that the outputs were all .TRUE. in the first
case and .FALSE. in the second. I just tried that test on ifort
and my program passed.

Now, with gfortran setting A = 0 (the documented value of .FALSE.
for gfortran), all outputs are .FALSE., but with A = 1 as gfortran
documents for .TRUE., or for that matter L = .TRUE., I get

C:\gfortran\clf\logtest>logtest1
Value by TRANSFER: 1
Value by WRITE: .TRUE.
Value by SELECT CASE: .TRUE.
Value by IF: .TRUE.
Value by WHERE: .TRUE.
Value by FORALL: .TRUE.
Value by ALL: .TRUE.
Value by ANY: .TRUE.
Value by COUNT: .TRUE.
Value by DOT_PRODUCT: .TRUE.
Value by INDEX: .TRUE.
Value by LOGICAL: .TRUE.
Value by MATMUL: .TRUE.
Value by MAXLOC(MASK): .TRUE.
Value by MAXVAL: .TRUE.
VAlue by MERGE: .TRUE.
Value by MINLOC(MASK): .TRUE.
Value by MINVAL: .TRUE.
Value by PACK: .TRUE.
Value by PRODUCT: .TRUE.
Value by SCAN: .FALSE.
Value by SUM: .TRUE.
Value by UNPACK: .TRUE.
Value by VERIFY: .FALSE.

So a couple of dragons seem to have been provided reciprocally.

James Van Buskirk

unread,
Sep 2, 2012, 8:53:25 PM9/2/12
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1kps57i.14j8re0u0irxwN%nos...@see.signature...

> 2. The expression iresult.iand.ival gives an integer result, so your IF
> is in the form

> IF (<integer-expression>) ...

> The form of IF that alows an integer expression there is the arithmetic
> IF, which requires 3 statement numbers rather than an action. There have
> been compilers that acepted nonstandard variants of IF, so I can't quite
> tell whether you are talking about one of those variants or just have
> the syntax further confused; I suspect the latter, but am not sure.

Interesting analysis, but given that operator(.iand.) is an
extension how do you know the type of its output? In F90+, one
could certainly create such an operator with two INTEGER inputs
and LOGICAL output. But I think it would be much easier to link
an assembly language IAND function with an F77- compiler than
to tell it somehow that it had a new .iand. operator, so I
suspect the exact recollection of the syntax much as you and
Robin do.

Terence

unread,
Sep 3, 2012, 2:20:25 AM9/3/12
to
Oh come ON Richard!
I didn't want to give the exact code for the two forms, trusting to english
meaning and intent.

Of course it's
IF (something) action

or else
IF (something) THEN
someaction
ENDIF

And don't now tell me that '(something)' is a real variable, or that 'or
else' is syntaxically inorrect.




Terence

unread,
Sep 3, 2012, 2:30:34 AM9/3/12
to
Please note I used the word 'FUNCTION' and not 'operator'
The 'intrinsics' I was missing and whose absence replaced with function
calls, and use, and still use, take the form of

iresult-=IAND(integer1,integer2)

And of course for testing 'integer2 is a masking bit pattern in the form of
an integer constant expressed as a hexadecimal contant..
There was no implied use by me of any form of code using a syntax (j .iand.
k).

And I usually side with Robin; he has used Fortran as long as I have and few
can say that.



Richard Maine

unread,
Sep 3, 2012, 3:18:16 AM9/3/12
to
Terence <tbwr...@bigpond.net.au> wrote:

> Please note I used the word 'FUNCTION' and not 'operator'
> The 'intrinsics' I was missing and whose absence replaced with function
> calls, and use, and still use, take the form of
>
> iresult-=IAND(integer1,integer2)
>
> And of course for testing 'integer2 is a masking bit pattern in the form of
> an integer constant expressed as a hexadecimal contant..
> There was no implied use by me of any form of code using a syntax (j .iand.
> k).

You mean other than the following? It is copied directly from your
prior post and is what I was talking about.

>> IF (iresult.IAND.ival) THEN (action)

I suppose that might not count as "implied use" because it seems
explicit instead of implied.

In any case, the result is still an integer, which was the point
actually in question. With the function forms, that is much more certain
that with the operator forms as James noted.

glen herrmannsfeldt

unread,
Sep 4, 2012, 1:29:25 AM9/4/12
to
James Van Buskirk <not_...@comcast.net> wrote:

(snip, someone wrote)
>> But that assumption you can also do in C as you know that _Bool only has
>> two values: 0 and 1.

> No, C doesn't say this. Where in the C standard does it say that _Bool
> can only have two values? I recall that _Bool is an integer type,
> maybe even an unsigned integer type, but I seem to recall from
> previous trips around this merry-go-round that it can take on
> other values, all true.

There is no _Bool in C89. I haven't looked much at C01 or C11,
don't remember which one added _Bool.

The C89 rules apply to int. I presume that the C01 and C11 rules,
applied to int, work the same way, but that wouldn't necessarily
be true for _Bool.

Also, even so, it doesn't seem to me that would affect the Fortran
operators on C interoperability types.

-- glen

glen herrmannsfeldt

unread,
Sep 4, 2012, 1:32:17 AM9/4/12
to
Richard Maine <nos...@see.signature> wrote:

(snip on THEN in logical IF)

> 2. The expression iresult.iand.ival gives an integer result, so your IF
> is in the form

> IF (<integer-expression>) ...

> The form of IF that alows an integer expression there is the arithmetic
> IF, which requires 3 statement numbers rather than an action. There have
> been compilers that acepted nonstandard variants of IF, so I can't quite
> tell whether you are talking about one of those variants or just have
> the syntax further confused; I suspect the latter, but am not sure.

Compilers that allow integers for logical operators tend, though
presumably aren't required, to accept them in logical IF.

The effect is presumably system dependent.

-- glen

Steve Lionel

unread,
Sep 4, 2012, 1:54:15 PM9/4/12
to
On 9/2/2012 8:41 PM, James Van Buskirk wrote:
> You know, before posting I forgot to give my program the
> basic test of setting A = 0 or A = -1 (the documented values of
> .TRUE. and .FALSE. for ifort with /fpscomp:nologicals) in program
> logtest1 to check that the outputs were all .TRUE. in the first
> case and .FALSE. in the second. I just tried that test on ifort
> and my program passed.

Intel Fortran's test for true/false of LOGICALs, as derived from the DEC
compilers, is not interoperable with C's _Bool type. This is why saying
/standard-semantics turns on the /fpscomp:logicals option which does
make it interoperable, and hence LOGICAL(C_BOOL) is properly
interoperable only when /fpscomp:logicals is in effect (explicitly or
implicitly.)

I would discourage anyone writing Fortran code today to mix integer and
logical types, whether or not the compiler you use supports that as an
extension. The language has the tools you need to do bitwise operations
on integers, even if they can look a bit verbose in more complex
expressions.

--
Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/
Intel Software Development Products Support
http://software.intel.com/sites/support/
My Fortran blog
http://www.intel.com/software/drfortran

Refer to http://software.intel.com/en-us/articles/optimization-notice
for more information regarding performance and optimization choices in
Intel software products.

James Van Buskirk

unread,
Sep 4, 2012, 4:28:59 PM9/4/12
to
"Steve Lionel" <steve....@intel.invalid> wrote in message
news:aamti9...@mid.individual.net...

> On 9/2/2012 8:41 PM, James Van Buskirk wrote:

>> You know, before posting I forgot to give my program the
>> basic test of setting A = 0 or A = -1 (the documented values of
>> .TRUE. and .FALSE. for ifort with /fpscomp:nologicals) in program
>> logtest1 to check that the outputs were all .TRUE. in the first
>> case and .FALSE. in the second. I just tried that test on ifort
>> and my program passed.

> Intel Fortran's test for true/false of LOGICALs, as derived from the DEC
> compilers, is not interoperable with C's _Bool type. This is why saying
> /standard-semantics turns on the /fpscomp:logicals option which does make
> it interoperable, and hence LOGICAL(C_BOOL) is properly interoperable only
> when /fpscomp:logicals is in effect (explicitly or implicitly.)

Does current ifort still flunk this test? My understanding is that
C_BOOL = 1 = SELECTED_INT_KIND(2), right? With my ancient version of
ifort, the test is not passed for either /fpscomp:nologicals or
/fpscomp:logicals:

C:\gfortran\clf\logtest>type logtest1b.f90
program logtest1
implicit none
integer(selected_int_kind(2)) A
logical(kind(A)) L

A = 2
L = transfer(A,L)
call sub(L)
end program logtest1

subroutine sub(x)
implicit none
logical(selected_int_kind(2)) x
character c
integer a(1)
character(*), parameter :: strings(2) = ['.TRUE. ','.FALSE.']
integer i
logical b(1,1)
integer m
logical(kind(x)), parameter :: t = .TRUE.

write(*,'(a,i0)') 'Value by TRANSFER: ', transfer(x,int(0,kind(x)))
if(logical(x,selected_int_kind(9))) then
write(*,'(a)') 'Value by LOGICAL: .TRUE.'
else
write(*,'(a)') 'Value by LOGICAL: .FALSE.'
end if
b = reshape([x],shape(b))
b = matmul(b,b)
if(b(1,1)) then
write(*,'(a)') 'Value by MATMUL: .TRUE.'
else
write(*,'(a)') 'Value by MATMUL: .FALSE.'
end if
a = maxloc([2,1],mask=[x,t])
write(*,'(a)') 'Value by MAXLOC(MASK): '// &
trim(strings(a(1)))
! a = maxloc([1,1],back=x)
! write(*,'(a)') 'Value by MAXLOC(BACK): '// &
! trim(strings(3-a(1)))
m = maxval([2,1],mask=[x,t])
write(*,'(a)') 'Value by MAXVAL: '//trim(strings(3-m))
write(*,'(a)') 'VAlue by MERGE: '// &
trim(merge('.TRUE. ','.FALSE.',x))
a = minloc([1,2],mask=[x,t])
write(*,'(a)') 'Value by MINLOC(MASK): '// &
trim(strings(a(1)))
! a = minloc([1,1],back=x)
! write(*,'(a)') 'Value by MINLOC(BACK): '// &
! trim(strings(3-a(1)))
m = minval([1,2],mask=[x,t])
write(*,'(a)') 'Value by MINVAL: '//trim(strings(m))
a = pack([1],[x],[2])
write(*,'(a)') 'Value by PACK: '//trim(strings(a(1)))
m = product([2],[x])
write(*,'(a)') 'Value by PRODUCT: '//trim(strings(3-m))
write(*,'(a)') 'Value by SCAN: '// &
trim(strings(3-scan('AA','A',back=x)))
m = sum([1],[x])
write(*,'(a)') 'Value by SUM: '//trim(strings(2-m))
a = unpack([1],[x],[2])
write(*,'(a)') 'Value by UNPACK: '// &
trim(strings(a(1)))
write(*,'(a)') 'Value by VERIFY: '// &
trim(strings(3-verify('AA','b',back=x)))
end subroutine sub

C:\gfortran\clf\logtest>ifort /fpscomp:nologicals logtest1b.f90
Intel(R) Fortran Compiler for 32-bit applications, Version 9.1 Build
20061103
Z Package ID: W_FC_C_9.1.033
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 8.00.50727.363
Copyright (C) Microsoft Corporation. All rights reserved.

-out:logtest1b.exe
-subsystem:console
logtest1b.obj

C:\gfortran\clf\logtest>logtest1b
Value by TRANSFER: 2
Value by WRITE: .FALSE.
Value by SELECT CASE: .FALSE.
Value by IF: .FALSE.
Value by WHERE: .FALSE.
Value by FORALL: .FALSE.
Value by ALL: .TRUE.
Value by ANY: .TRUE.
Value by COUNT: .FALSE.
Value by DOT_PRODUCT: .TRUE.
Value by INDEX: .TRUE.
Value by LOGICAL: .FALSE.
Value by MATMUL: .TRUE.
Value by MAXLOC(MASK): .FALSE.
Value by MAXVAL: .TRUE.
VAlue by MERGE: .TRUE.
Value by MINLOC(MASK): .FALSE.
Value by MINVAL: .TRUE.
Value by PACK: .FALSE.
Value by PRODUCT: .TRUE.
Value by SCAN: .TRUE.
Value by SUM: .TRUE.
Value by UNPACK: .FALSE.
Value by VERIFY: .TRUE.

C:\gfortran\clf\logtest>ifort /fpscomp:logicals logtest1b.f90
Intel(R) Fortran Compiler for 32-bit applications, Version 9.1 Build
20061103
Z Package ID: W_FC_C_9.1.033
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 8.00.50727.363
Copyright (C) Microsoft Corporation. All rights reserved.

-out:logtest1b.exe
-subsystem:console
logtest1b.obj

C:\gfortran\clf\logtest>logtest1b
Value by TRANSFER: 2
Value by WRITE: .FALSE.
Value by SELECT CASE: .TRUE.
Value by IF: .TRUE.
Value by WHERE: .FALSE.
Value by FORALL: .FALSE.
Value by ALL: .FALSE.
Value by ANY: .FALSE.
Value by COUNT: .FALSE.
Value by DOT_PRODUCT: .FALSE.
Value by INDEX: .TRUE.
Value by LOGICAL: .TRUE.
Value by MATMUL: .FALSE.
Value by MAXLOC(MASK): .FALSE.
Value by MAXVAL: .TRUE.
VAlue by MERGE: .TRUE.
Value by MINLOC(MASK): .FALSE.
Value by MINVAL: .TRUE.
Value by PACK: .FALSE.
Value by PRODUCT: .TRUE.
Value by SCAN: .TRUE.
Value by SUM: .TRUE.
Value by UNPACK: .FALSE.
Value by VERIFY: .TRUE.

So neither state of the switch produces consistent results for the
above standard-conforming code.

> I would discourage anyone writing Fortran code today to mix integer and
> logical types, whether or not the compiler you use supports that as an
> extension. The language has the tools you need to do bitwise operations
> on integers, even if they can look a bit verbose in more complex
> expressions.

For both ifort and gfortran, the support seems to be only partial.
That makes it a dangerous extension to use.

Steve Lionel

unread,
Sep 5, 2012, 11:35:31 AM9/5/12
to
On 9/4/2012 4:28 PM, James Van Buskirk wrote:
> Does current ifort still flunk this test? My understanding is that
> C_BOOL = 1 = SELECTED_INT_KIND(2), right? With my ancient version of
> ifort, the test is not passed for either /fpscomp:nologicals or
> /fpscomp:logicals:

James,

Thanks for this test. Indeed, ifort does not seem to make the right
choice in all these cases. We'll investigate.

James Van Buskirk

unread,
Sep 5, 2012, 11:03:58 PM9/5/12
to
"Steve Lionel" <steve....@intel.invalid> wrote in message
news:aap9q5...@mid.individual.net...

> James,

> Thanks for this test. Indeed, ifort does not seem to make the right
> choice in all these cases. We'll investigate.

You're welcome. Unfortunately, the test was limited to what that
old version of ifort could handle, which meant excluding newer
intrinsics and no initialization expressions. I have written up
a test which is a little more comprehensive:

C:\gfortran\clf\logtest>type exit_test.f90
program exit_test
stop 7
end program exit_test

C:\gfortran\clf\logtest>gfortran exit_test.f90 -oexit_test

C:\gfortran\clf\logtest>type logtest3.f90
!DEC$ IF(.FALSE.)
module ifwin
use ISO_C_BINDING
implicit none
integer, parameter, public :: BOOL = C_INT
public SetEnvironmentVariable
interface
function SetEnvironmentVariable(lpName, lpValue) &
bind(C,name='SetEnvironmentVariableA')
import
implicit none
!gcc$ attributes stdcall :: SetEnvironmentVariable
integer(BOOL) SetEnvironmentVariable
character(kind=C_CHAR) lpName(*)
character(kind=C_CHAR) lpValue(*)
end function SetEnvironmentVariable
end interface
end module ifwin
!DEC$ ENDIF

program logtest3
implicit none
! ********************************************************!
! ******* Everything depends on this parameter ***********!
integer, parameter :: A1 = 2
! ********************************************************!
integer A
logical, parameter :: L1 = transfer(A1,.FALSE.)
logical L
character(*), parameter :: strings(2) = ['.TRUE. ','.FALSE.']
integer, parameter :: I_TRANSFER = transfer(L1,0)
logical, parameter :: L_ALL = all([L1])
logical, parameter :: L_ANY = any([L1])
integer, parameter :: I_COUNT = count([L1])
logical, parameter :: L_DOT_PRODUCT = dot_product([L1],[L1])
! integer, parameter :: I_FINDLOC_MASK(1) = findloc([1,1],1, &
! mask=[L1,.TRUE.])
! integer, parameter :: I_FINDLOC_BACK(1) = findloc([1,1],1, &
! back=x)
integer, parameter :: I_IALL = iall([1],mask=[L1])
integer, parameter :: I_IANY = iany([1],mask=[L1])
integer, parameter :: I_INDEX = index('AA','A',back=L1)
integer, parameter :: I_IPARITY = iparity([1],mask=[L1])
logical(selected_int_kind(2)), parameter :: L_LOGICAL = &
logical(L1,kind(L_LOGICAL))
logical, parameter, dimension(1,1) :: b = &
reshape([L1],shape(b))
logical, parameter :: L_MATMUL(1,1) = matmul(b,b)
! integer, parameter :: I_MAXLOC_MASK(1) = &
! maxloc([2,1],mask=[L1,.TRUE.])
! integer, parameter :: I_MAXLOC_BACK(1) = &
! maxloc([1,1],back=L1)
! integer, parameter :: I_MAXVAL = &
! maxval([2,1],mask=[L1,.TRUE.])
integer, parameter :: I_MERGE = merge(1,2,L1)
! integer, parameter :: I_MINLOC_MASK(1) = &
! minloc([2,1],mask=[L1,.TRUE.])
! integer, parameter :: I_MINLOC_BACK(1) = &
! minloc([1,1],back=L1)
! integer, parameter :: I_MINVAL = &
! minval([2,1],mask=[L1,.TRUE.])
integer, parameter :: I_PACK(1) = pack([1],[L1],[2])
logical, parameter :: L_PARITY = parity([L1])
integer, parameter :: I_PRODUCT = product([2],[L1])
integer, parameter :: I_SCAN = scan('AA','A',back=L1)
integer, parameter :: I_SUM = sum([1],[L1])
integer, parameter :: I_UNPACK(1) = unpack([1],[L1],[2])
integer, parameter :: I_VERIFY = verify('AA','b',back=L1)
logical, parameter :: L_TOTAL = L_ALL .NEQV. L_ANY &
.NEQV. L_DOT_PRODUCT .NEQV. L_LOGICAL .NEQV. &
L_MATMUL(1,1) .NEQV. L_PARITY
integer, parameter :: I_TOTAL = I_COUNT+I_IALL+I_IANY &
+I_INDEX+I_IPARITY+I_PACK(1)+I_PRODUCT+I_SCAN+I_SUM &
! +I_FINDLOC_MASK(1)+I_FINDLOC_BACK(1)+I_MAXLOC_MASK(1) &
! +I_MAXLOC_BACK(1)+I_MAXVAL+I_MINLOC_MASK(1) &
! +I_MINLOC_BACK(1)+I_MINVAL
+I_UNPACK(1)+I_VERIFY
integer, parameter :: I_CHECK = min(I_TOTAL,0)+ &
merge(kind(1.0),kind(1.0d0),L_TOTAL)
real(I_CHECK) x_check

x_check = 1
write(*,'(a)') 'Testing constant expressions'
write(*,'(a,i0)') 'Value by TRANSFER: ', I_TRANSFER
if(L_ALL) then
write(*,'(a)') 'Value by ALL: .TRUE.'
else
write(*,'(a)') 'Value by ALL: .FALSE.'
end if
if(L_ANY) then
write(*,'(a)') 'Value by ANY: .TRUE.'
else
write(*,'(a)') 'Value by ANY: .FALSE.'
end if
if(I_COUNT == 1) then
write(*,'(a)') 'Value by COUNT: .TRUE.'
else
write(*,'(a)') 'Value by COUNT: .FALSE.'
end if
if(L_DOT_PRODUCT) then
write(*,'(a)') 'Value by DOT_PRODUCT: .TRUE.'
else
write(*,'(a)') 'Value by DOT_PRODUCT: .FALSE.'
end if
! write(*,'(a)') 'Value by FINDLOC(MASK): '// &
! trim(strings(I_FINDLOC_MASK(1)))
! write(*,'(a)') 'Value by FINDLOC(BACK): '// &
! trim(strings(3-I_FINDLOC_BACK(1)))
if(I_IALL == 1) then
write(*,'(a)') 'Value by IALL: .TRUE.'
else
write(*,'(a)') 'Value by IALL: .FALSE.'
end if
if(I_IANY == 1) then
write(*,'(a)') 'Value by IANY: .TRUE.'
else
write(*,'(a)') 'Value by IANY: .FALSE.'
end if
write(*,'(a)') 'Value by INDEX: '// &
trim(strings(3-I_INDEX))
if(I_IPARITY == 1) then
write(*,'(a)') 'Value by IPARITY: .TRUE.'
else
write(*,'(a)') 'Value by IPARITY: .FALSE.'
end if
if(L_LOGICAL) then
write(*,'(a)') 'Value by LOGICAL: .TRUE.'
else
write(*,'(a)') 'Value by LOGICAL: .FALSE.'
end if
if(L_MATMUL(1,1)) then
write(*,'(a)') 'Value by MATMUL: .TRUE.'
else
write(*,'(a)') 'Value by MATMUL: .FALSE.'
end if
! write(*,'(a)') 'Value by MAXLOC(MASK): '// &
! trim(strings(I_MAXLOC_MASK(1)))
! write(*,'(a)') 'Value by MAXLOC(BACK): '// &
! trim(strings(3-I_MAXLOC_BACK(1)))
! write(*,'(a)') 'Value by MAXVAL: '//trim(strings(3-I_MAXVAL))
write(*,'(a)') 'Value by MERGE: '//trim(strings(I_MERGE))
! write(*,'(a)') 'Value by MINLOC(MASK): '// &
! trim(strings(I_MINLOC_MASK(1)))
! write(*,'(a)') 'Value by MINLOC(BACK): '// &
! trim(strings(3-I_MINLOC_BACK(1)))
! write(*,'(a)') 'Value by MINVAL: '//trim(strings(3-I_MINVAL))
write(*,'(a)') 'Value by PACK: '//trim(strings(I_PACK(1)))
if(L_PARITY) then
write(*,'(a)') 'Value by PARITY: .TRUE.'
else
write(*,'(a)') 'Value by PARITY: .FALSE.'
end if
write(*,'(a)') 'Value by PRODUCT: '// &
trim(strings(3-I_PRODUCT))
write(*,'(a)') 'Value by SCAN: '// &
trim(strings(3-I_SCAN))
write(*,'(a)') 'Value by SUM: '//trim(strings(2-I_SUM))
write(*,'(a)') 'Value by UNPACK: '// &
trim(strings(I_UNPACK(1)))
write(*,'(a)') 'Value by VERIFY: '// &
trim(strings(3-I_VERIFY))

A = A1
L = transfer(A,L)
call sub(L)
end program logtest3

subroutine sub(x)
use ifwin
implicit none
logical x
character c
integer a(1)
character(*), parameter :: strings(2) = ['.TRUE. ','.FALSE.']
integer i
logical b(1,1)
integer m
integer exitstat
character(7) var
integer(BOOL) res

write(*,'(/a)') 'Testing ordinary expressions'
write(*,'(a,i0)') 'Value by TRANSFER: ', transfer(x,0)
exitstat = 999
call execute_command_line(COMMAND = 'exit_test', &
WAIT = x, EXITSTAT = exitstat)
select case(exitstat)
case(999)
write(*,'(a)') 'Value by EXECUTE_COMMAND_LINE: .FALSE.'
case(7)
write(*,'(a)') 'Value by EXECUTE_COMMAND_LINE: .TRUE.'
case default
write(*,'(a)') 'EXECUTE_COMMAND_LINE test failed'
end select
! a = findloc([1,1],1,mask=[x,.TRUE.])
! write(*,'(a)') 'Value by FINDLOC(MASK): '// &
! trim(strings(a(1)))
! a = findloc([1,1],back=x)
! write(*,'(a)') 'Value by FINDLOC(BACK): '// &
! trim(strings(3-a(1)))
res = SetEnvironmentVariable('PhiX174 '//achar(0), &
'.FALSE.'//achar(0))
res = SetEnvironmentVariable('PhiX174'//achar(0), &
'.TRUE.'//achar(0))
call get_environment_variable('PhiX174 ', &
value=var,status=m,trim_name=x)
if(m == 0) then
write(*,'(a)') 'Value by GET_ENVIRONMENT_'// &
'VARIABLE: '//trim(var)
else
write(*,'(a)') 'GET_ENVIRONMENT_VARIABLE test failed'
end if
if(iall([1],mask=[x]) == 1) then
write(*,'(a)') 'Value by IALL: .TRUE.'
else
write(*,'(a)') 'Value by IALL: .FALSE.'
end if
if(iany([1],mask=[x]) == 1) then
write(*,'(a)') 'Value by IANY: .TRUE.'
else
write(*,'(a)') 'Value by IANY: .FALSE.'
end if
write(*,'(a)') 'Value by INDEX: '// &
trim(strings(3-index('AA','A',back=x)))
if(iparity([1],mask=[x]) == 1) then
write(*,'(a)') 'Value by IPARITY: .TRUE.'
else
write(*,'(a)') 'Value by IPARITY: .FALSE.'
end if
if(logical(x,selected_int_kind(2))) then
write(*,'(a)') 'Value by LOGICAL: .TRUE.'
else
write(*,'(a)') 'Value by LOGICAL: .FALSE.'
end if
b = reshape([x],shape(b))
b = matmul(b,b)
if(b(1,1)) then
write(*,'(a)') 'Value by MATMUL: .TRUE.'
else
write(*,'(a)') 'Value by MATMUL: .FALSE.'
end if
a = maxloc([2,1],mask=[x,.TRUE.])
write(*,'(a)') 'Value by MAXLOC(MASK): '// &
trim(strings(a(1)))
! a = maxloc([1,1],back=x)
! write(*,'(a)') 'Value by MAXLOC(BACK): '// &
! trim(strings(3-a(1)))
m = maxval([2,1],mask=[x,.TRUE.])
write(*,'(a)') 'Value by MAXVAL: '//trim(strings(3-m))
write(*,'(a)') 'Value by MERGE: '// &
trim(merge('.TRUE. ','.FALSE.',x))
a = minloc([1,2],mask=[x,.TRUE.])
write(*,'(a)') 'Value by MINLOC(MASK): '// &
trim(strings(a(1)))
! a = minloc([1,1],back=x)
! write(*,'(a)') 'Value by MINLOC(BACK): '// &
! trim(strings(3-a(1)))
m = minval([1,2],mask=[x,.TRUE.])
write(*,'(a)') 'Value by MINVAL: '//trim(strings(m))
a = pack([1],[x],[2])
write(*,'(a)') 'Value by PACK: '//trim(strings(a(1)))
if(parity([x])) then
write(*,'(a)') 'Value by PARITY: .TRUE.'
else
write(*,'(a)') 'Value by PARITY: .FALSE.'
end if
m = product([2],[x])
write(*,'(a)') 'Value by PRODUCT: '//trim(strings(3-m))
write(*,'(a)') 'Value by SCAN: '// &
trim(strings(3-scan('AA','A',back=x)))
m = sum([1],[x])
write(*,'(a)') 'Value by SUM: '//trim(strings(2-m))
a = unpack([1],[x],[2])
write(*,'(a)') 'Value by UNPACK: '// &
trim(strings(a(1)))
write(*,'(a)') 'Value by VERIFY: '// &
trim(strings(3-verify('AA','b',back=x)))
end subroutine sub

C:\gfortran\clf\logtest>gfortran logtest3.f90 -ologtest3
logtest3.f90:47.15:

reshape([L1],shape(b))
1
Warning: Assigning value other than 0 or 1 to LOGICAL has undefined result
at (1
)
logtest3.f90:28.29:

logical, parameter :: L1 = transfer(A1,.FALSE.)
1
Warning: Assigning value other than 0 or 1 to LOGICAL has undefined result
at (1
)

Now, it's not the purpose of this post to discuss whether or
not gfortran documents the internal representations denied
above, so we change to:

integer, parameter :: A1 = 0

and recompile to get:

C:\gfortran\clf\logtest>gfortran logtest3.f90 -ologtest3

C:\gfortran\clf\logtest>logtest3
Testing constant expressions
Value by TRANSFER: 0
Value by ALL: .FALSE.
Value by ANY: .FALSE.
Value by COUNT: .FALSE.
Value by DOT_PRODUCT: .FALSE.
Value by IALL: .FALSE.
Value by IANY: .FALSE.
Value by INDEX: .FALSE.
Value by IPARITY: .FALSE.
Value by LOGICAL: .FALSE.
Value by MATMUL: .FALSE.
Value by MERGE: .FALSE.
Value by PACK: .FALSE.
Value by PARITY: .FALSE.
Value by PRODUCT: .FALSE.
Value by SCAN: .FALSE.
Value by SUM: .FALSE.
Value by UNPACK: .FALSE.
Value by VERIFY: .FALSE.

Testing ordinary expressions
Value by TRANSFER: 0
Value by WRITE: .FALSE.
Value by SELECT CASE: .FALSE.
Value by IF: .FALSE.
Value by WHERE: .FALSE.
Value by FORALL: .FALSE.
Value by ALL: .FALSE.
Value by ANY: .FALSE.
Value by COUNT: .FALSE.
Value by DOT_PRODUCT: .FALSE.
STOP 7
Value by EXECUTE_COMMAND_LINE: .TRUE.
GET_ENVIRONMENT_VARIABLE test failed
Value by IALL: .FALSE.
Value by IANY: .FALSE.
Value by INDEX: .FALSE.
Value by IPARITY: .FALSE.
Value by LOGICAL: .FALSE.
Value by MATMUL: .FALSE.
Value by MAXLOC(MASK): .FALSE.
Value by MAXVAL: .FALSE.
Value by MERGE: .FALSE.
Value by MINLOC(MASK): .FALSE.
Value by MINVAL: .FALSE.
Value by PACK: .FALSE.
Value by PARITY: .FALSE.
Value by PRODUCT: .FALSE.
Value by SCAN: .FALSE.
Value by SUM: .FALSE.
Value by UNPACK: .FALSE.
Value by VERIFY: .FALSE.

So that's all OK, except gfortran hasn't yet implemented WAIT=.FALSE.
yet for EXECUTE_COMMAND_LINE on Windows and also gfortran seems to
be saving the state of the environmental variables at program start
and not taking into account the dynamic state of the environmental
variables as it changes during program execution.

Then we change to the other value that gfortran approves of:

integer, parameter :: A1 = 1

Recompile and rerun:

C:\gfortran\clf\logtest>gfortran logtest3.f90 -ologtest3

C:\gfortran\clf\logtest>logtest3
Testing constant expressions
Value by TRANSFER: 1
Value by ALL: .TRUE.
Value by ANY: .TRUE.
Value by COUNT: .TRUE.
Value by DOT_PRODUCT: .TRUE.
Value by IALL: .TRUE.
Value by IANY: .TRUE.
Value by INDEX: .TRUE.
Value by IPARITY: .TRUE.
Value by LOGICAL: .TRUE.
Value by MATMUL: .TRUE.
Value by MERGE: .TRUE.
Value by PACK: .TRUE.
Value by PARITY: .TRUE.
Value by PRODUCT: .TRUE.
Value by SCAN: .TRUE.
Value by SUM: .TRUE.
Value by UNPACK: .TRUE.
Value by VERIFY: .TRUE.

Testing ordinary expressions
Value by TRANSFER: 1
Value by WRITE: .TRUE.
Value by SELECT CASE: .TRUE.
Value by IF: .TRUE.
Value by WHERE: .TRUE.
Value by FORALL: .TRUE.
Value by ALL: .TRUE.
Value by ANY: .TRUE.
Value by COUNT: .TRUE.
Value by DOT_PRODUCT: .TRUE.
STOP 7
Value by EXECUTE_COMMAND_LINE: .TRUE.
GET_ENVIRONMENT_VARIABLE test failed
Value by IALL: .TRUE.
Value by IANY: .TRUE.
Value by INDEX: .TRUE.
Value by IPARITY: .TRUE.
Value by LOGICAL: .TRUE.
Value by MATMUL: .TRUE.
Value by MAXLOC(MASK): .TRUE.
Value by MAXVAL: .TRUE.
Value by MERGE: .TRUE.
Value by MINLOC(MASK): .TRUE.
Value by MINVAL: .TRUE.
Value by PACK: .TRUE.
Value by PARITY: .TRUE.
Value by PRODUCT: .TRUE.
Value by SCAN: .FALSE.
Value by SUM: .TRUE.
Value by UNPACK: .TRUE.
Value by VERIFY: .FALSE.

And we can see that gfortran fails for SCAN and VERIFY for ordinary
expressions. The reason for this is that gfortran uses its
constant expression mechanism whenever it can so you have to take
extra precautions (here making the BACK= argument to the intrinsics
a dummy argument in subroutine sub) to discourage gfortran from
doing so, permitting us to test behaviour with ordinary expressions
when gfortran's test suite missed it.

As can be seen from the commented out code, gfortran does not yet
implement the BACK= argument for the MAXLOC and MINLOC intrinsics,
doesn't yet implement MAXLOC, MAXVAL, MINLOC, MINVAL for constant
expressions and doesn't implement FINDLOC at all.

Well, as I like to say, there are some tricky points regarding the
seemingly simple LOGICAL type in Fortran and hopefully my tests
will help persuade the reader that maybe there is some validity to
my assertion.

How much of this can the latest ifort handle, and can it do any of
the commented-out code?

Steve Lionel

unread,
Sep 6, 2012, 11:25:54 AM9/6/12
to
On 9/5/2012 11:03 PM, James Van Buskirk wrote:
> How much of this can the latest ifort handle, and can it do any of
> the commented-out code?

ifort does support the BACK= keyword for intrinsics that have it, but
doesn't yet support the F2008 intrinsics FINDLOC and
EXECUTE_COMMAND_LINE and also doesn't yet support the F2008 relaxed
rules for constant expressions that would allow such things as MATMUL
and DOT_PRODUCT in constant expressions. Therefore, a lot of this
latest results in errors from ifort. When I have the time, I'll try to
reduce this to what ifort can compile and see what it does.

FWIW, you are welcome to download a 30-day free trial of Intel Fortran.
We just released the "2013" series of our developer tools, including
version 13.0 of the compilers.

James Van Buskirk

unread,
Sep 6, 2012, 2:58:52 PM9/6/12
to
"Steve Lionel" <steve....@intel.invalid> wrote in message
news:aartk3...@mid.individual.net...

> On 9/5/2012 11:03 PM, James Van Buskirk wrote:

>> How much of this can the latest ifort handle, and can it do any of
>> the commented-out code?

> ifort does support the BACK= keyword for intrinsics that have it, but
> doesn't yet support the F2008 intrinsics FINDLOC and EXECUTE_COMMAND_LINE
> and also doesn't yet support the F2008 relaxed rules for constant
> expressions that would allow such things as MATMUL and DOT_PRODUCT in
> constant expressions. Therefore, a lot of this latest results in errors
> from ifort. When I have the time, I'll try to reduce this to what ifort
> can compile and see what it does.

I thought that transformational intrinsics in initialization
expressions was f2003. N1601.pdf, section 7.1.7:

"An initialization expression is an expression with limitations
that make it suitable for use as a kind type parameter,
initializer, or named constant. It is an expression in which
each operation is intrinsic, and each primary is

(5) A reference to a transformational standard intrinsic function
other than NULL, where each argument is an initialization
expression"

And that's from 2004.

> FWIW, you are welcome to download a 30-day free trial of Intel Fortran. We
> just released the "2013" series of our developer tools, including version
> 13.0 of the compilers.

I would like to see what it does but am afraid that installing it
might make it more difficult to use the installation of ifort that
I have now when 13.0 expires. Also I would like to do some testing
and send in some bug reports that Intel's support personnel could
handle literally like the Dilbert cartoon where tech support was
bullying Dilbert into closing the ticket so I would have to have
more free time to do anything substantive in just a month.

However, buying ifort this year might be within budget for habits
like computing if I acquire the disposable income.

James Van Buskirk

unread,
Sep 8, 2012, 12:31:47 AM9/8/12
to
"Steve Lionel" <steve....@intel.invalid> wrote in message
news:aartk3...@mid.individual.net...

> User communities for Intel Software Development Products
> http://software.intel.com/en-us/forums/

Oh yeah, this... aren't you risking copyright infringement
proceedings from the new google groups with the usability features
of the new ifort forum? I tried logging on but the helpful forum
software wanted me to change my password and wouldn't let me use
an old password. Some of us consider the password stuff to be
a security risk because it enables whoever owns the website to
capture passwords that we use and attempt to violate our security
on other sites if we use duplicate passwords. If we don't
duplicate passwords then given our passwords on enough sites
someone could attempt to detect patterns in the passwords we
create. If we create random passwords for every site we visit,
then there is no way we could remember them and we have to have
them all written down somewhere easy to find so that any visitor
to our house could easily copy them down, too. Why can't ifort's
users decide what security approach is best for them?

On topic for this subthread, following a link from one of your
recent posts in that forum I encountered:

http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/fortran/win/pdf/Creating_Fortran_Win_Apps.pdf

which has a table of OpenGL type which says that GLboolean
corresponds to LOGICAL and pointers correspond to INTEGER.
Obviously quite out of date in that pointers should correspond
to INTEGER(INT_PTR_KIND()) or INTEGER(C_INTPTR_T) or much
better, TYPE(C_PTR). The GLboolean entry bolters my assertion
that trying to make C boolean data types (C99 _Bool or C++ bool,
or here OpenGL GLboolean) correspond to Fortran LOGICAL data
types is pretty much always a mistake. GLboolean on Windows
seems to equate to unsigned char which probably should
translate to INTEGER(C_INT8_T) in Fortran. At least default
LOGICAL simply has the wrong size to match GLboolean on Windows.

glen herrmannsfeldt

unread,
Sep 8, 2012, 2:38:23 AM9/8/12
to
James Van Buskirk <not_...@comcast.net> wrote:

(snip)
> Oh yeah, this... aren't you risking copyright infringement
> proceedings from the new google groups with the usability features
> of the new ifort forum? I tried logging on but the helpful forum
> software wanted me to change my password and wouldn't let me use
> an old password. Some of us consider the password stuff to be
> a security risk because it enables whoever owns the website to
> capture passwords that we use and attempt to violate our security
> on other sites if we use duplicate passwords.

Hopefully they only store the hashed passwords.

Everyone should only store hashed passwords, but some recent
security breaches show that isn't true.

> If we don't
> duplicate passwords then given our passwords on enough sites
> someone could attempt to detect patterns in the passwords we
> create. If we create random passwords for every site we visit,
> then there is no way we could remember them and we have to have
> them all written down somewhere easy to find so that any visitor
> to our house could easily copy them down, too. Why can't ifort's
> users decide what security approach is best for them?

These I agree with.

-- glen

Thomas Jahns

unread,
Sep 10, 2012, 5:30:51 AM9/10/12
to
On 09/08/2012 06:31 AM, James Van Buskirk wrote:
> Oh yeah, this... aren't you risking copyright infringement
> proceedings from the new google groups with the usability features
> of the new ifort forum? I tried logging on but the helpful forum
> software wanted me to change my password and wouldn't let me use
> an old password. Some of us consider the password stuff to be
> a security risk because it enables whoever owns the website to
> capture passwords that we use and attempt to violate our security
> on other sites if we use duplicate passwords. If we don't
> duplicate passwords then given our passwords on enough sites
> someone could attempt to detect patterns in the passwords we
> create. If we create random passwords for every site we visit,
> then there is no way we could remember them and we have to have
> them all written down somewhere easy to find so that any visitor
> to our house could easily copy them down, too. Why can't ifort's
> users decide what security approach is best for them?

you are aware that software solutions to this problem exist? I know of good
experiences with the old GNOME password manager, Mozilla's internal password
manager, KeePassX and 1Password. But I'm sure other fine solutions exist and if
you want to do it old-school[TM], one can easily imagine keeping passwords in a
PGP/GPG-encrypted file (which can be superficially directly opened in emacs or vim).

Regards, Thomas

Ron Shepard

unread,
Sep 10, 2012, 9:00:52 AM9/10/12
to
In article <k2kc0b$2cjs$1...@gwdu112.gwdg.de>,
This approach would work if you have only one computer and you
always access the web from that device. These days however, people
typically have a phone, an iPad, a laptop, a smart TV, a game
system, and maybe a home and/or an office desktop computer. Some of
these devices might not even have a command line interface. So in
this case, you need the encrypted password file to be accessible
also over the web, and that seems to be much less secure, in
principle, than a local file that cannot be accessed remotely.

$.02 -Ron Shepard

JB

unread,
Sep 10, 2012, 9:28:57 AM9/10/12
to
On 2012-09-08, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
> James Van Buskirk <not_...@comcast.net> wrote:
>
> (snip)
>> Oh yeah, this... aren't you risking copyright infringement
>> proceedings from the new google groups with the usability features
>> of the new ifort forum? I tried logging on but the helpful forum
>> software wanted me to change my password and wouldn't let me use
>> an old password. Some of us consider the password stuff to be
>> a security risk because it enables whoever owns the website to
>> capture passwords that we use and attempt to violate our security
>> on other sites if we use duplicate passwords.
>
> Hopefully they only store the hashed passwords.
>
> Everyone should only store hashed passwords, but some recent
> security breaches show that isn't true.

Storing hashed passwords can, depending on how one does it, be
hopelessly incompetent as e.g. the recent LinkedIN incident showed.

LinkedIN did store hashed passwords, but critically, they didn't use a
unique per-password salt, and they used SHA512 which is relatively
fast to compute. Both critical errors. Had they used salting and one
of PBKDF2/bcrypt/scrypt/sha512crypt instead of plain sha-512 the
attackers would most likely have managed to crack only a very small
fraction of the passwords they now managed to crack.


--
JB

Richard Maine

unread,
Sep 10, 2012, 11:40:43 AM9/10/12
to
Not that I'm a fan of random sites requiring a user-name and password
just to do nonsensitive things. I've declined to use sites instead of
bothering with that. (In fact, I don't use the subject Intel site, but
that's largely because I'm not currently using the Intel compiler,
though I have used versions of it in the past).

But 1Password does address the multi-computer issues you mentioned. I'm
a reasonably satisfied user of it. Syncs between my various machines
(including my newest toy - an iPhone that I finally got once there was
someone with a plan at a monthly price I could stomach). Of course, as
you say, this does add a security risk of its own, but I've been
adquately convinced that their encryption is decent, unlike that of
ransom web sites. No Glen, just having a password stored encrypted is no
guarantee if the site is naive about such things. Real-world
demonstrations exist; lots of them. JB mentioned LinkedIN, but there
have been plenty of others. Things that were considered secure a few
decades ago are laughably easy to crack today. There was a good
ArsTechnical article on it not long ago.

glen herrmannsfeldt

unread,
Sep 10, 2012, 12:14:11 PM9/10/12
to
Richard Maine <nos...@see.signature> wrote:

(snip)
> Not that I'm a fan of random sites requiring a user-name and password
> just to do nonsensitive things. I've declined to use sites instead of
> bothering with that. (In fact, I don't use the subject Intel site, but
> that's largely because I'm not currently using the Intel compiler,
> though I have used versions of it in the past).

I have a password that I only use for non-sensitive sites that
require one anyway.

> But 1Password does address the multi-computer issues you mentioned. I'm
> a reasonably satisfied user of it. Syncs between my various machines
> (including my newest toy - an iPhone that I finally got once there was
> someone with a plan at a monthly price I could stomach). Of course, as
> you say, this does add a security risk of its own, but I've been
> adquately convinced that their encryption is decent, unlike that of
> ransom web sites. No Glen, just having a password stored encrypted
> is no guarantee if the site is naive about such things. Real-world
> demonstrations exist; lots of them. JB mentioned LinkedIN, but there
> have been plenty of others.

I knew about the LinkedIn leak, but none of the details. Especially,
the detail about not using salt. As far as I know, there are still
sites around without any encryption, but that haven't been interesting
enough for anyone to break.

> Things that were considered secure a few
> decades ago are laughably easy to crack today. There was a good
> ArsTechnical article on it not long ago.

The 30 year (about) old unix crypt() at least does use salt.
Not so hard to break, but at least the salt slows one down a
little bit.

-- glen

Steve Lionel

unread,
Sep 10, 2012, 3:21:39 PM9/10/12
to
On 9/10/2012 5:30 AM, Thomas Jahns wrote:
> you are aware that software solutions to this problem exist? I know of good
> experiences with the old GNOME password manager, Mozilla's internal password
> manager, KeePassX and 1Password. But I'm sure other fine solutions exist and if
> you want to do it old-school[TM], one can easily imagine keeping passwords in a
> PGP/GPG-encrypted file (which can be superficially directly opened in emacs or vim).

And I use LastPass for this. As shown in this thread, there are several
good solutions for using a separate, "random" and strong password on
every site.

--
Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/

Steve Lionel

unread,
Sep 10, 2012, 3:22:31 PM9/10/12
to
On 9/8/2012 12:31 AM, James Van Buskirk wrote:
> On topic for this subthread, following a link from one of your
> recent posts in that forum I encountered:
>
> http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/fortran/win/pdf/Creating_Fortran_Win_Apps.pdf
>
> which has a table of OpenGL type which says that GLboolean
> corresponds to LOGICAL and pointers correspond to INTEGER.
> Obviously quite out of date in that pointers should correspond
> to INTEGER(INT_PTR_KIND()) or INTEGER(C_INTPTR_T) or much
> better, TYPE(C_PTR). The GLboolean entry bolters my assertion
> that trying to make C boolean data types (C99 _Bool or C++ bool,
> or here OpenGL GLboolean) correspond to Fortran LOGICAL data
> types is pretty much always a mistake. GLboolean on Windows
> seems to equate to unsigned char which probably should
> translate to INTEGER(C_INT8_T) in Fortran. At least default
> LOGICAL simply has the wrong size to match GLboolean on Windows.

Thanks - I will ask to have this corrected.

--
Steve Lionel
Developer Products Division
Intel Corporation
Merrimack, NH

For email address, replace "invalid" with "com"

User communities for Intel Software Development Products
http://software.intel.com/en-us/forums/

David Thompson

unread,
Oct 11, 2012, 3:02:18 AM10/11/12
to
On Tue, 4 Sep 2012 05:29:25 +0000 (UTC), glen herrmannsfeldt
<g...@ugcs.caltech.edu> wrote:

> James Van Buskirk <not_...@comcast.net> wrote:
>
> (snip, someone wrote)
> >> But that assumption you can also do in C as you know that _Bool only has
> >> two values: 0 and 1.
>
> > No, C doesn't say this. Where in the C standard does it say that _Bool
> > can only have two values? I recall that _Bool is an integer type,
> > maybe even an unsigned integer type, but I seem to recall from
> > previous trips around this merry-go-round that it can take on
> > other values, all true.
>
> There is no _Bool in C89. I haven't looked much at C01 or C11,
> don't remember which one added _Bool.
>
C99.

> The C89 rules apply to int. I presume that the C01 and C11 rules,
> applied to int, work the same way, but that wouldn't necessarily
> be true for _Bool.
>

6.3.1.2: "When any scalar value is converted to _Bool, the result is 0
if the value compares equal
to 0; otherwise, the result is 1."

This is an extension of the int-as-boolean rules in C: if(x) or
while(x) etc is treated as true if x compares unequal to 0, for _Bool
it is materialized as an actual 1 or 0. A _Bool variable, or bitfield,
is required to be able to store 0 or 1, but storing anything else is
not specified, and by the rules of the C standard this leaves it as
undefined behavior if you get some other representation into to the
underlying memory i.e. by union, or memcpy, etc.

0 new messages