Very difficult floating point question

F

Flash Gordon

bartc said:
Of course just for extra safety the programmers have absolutely no idea
of the word sizes, byte-orientation, alignment rules or typical memory
sizes of the processors inside the missile.

Most of the time you don't need to know that stuff, and I *have* done C
development in the defense industry. Not on missile launching systems,
but...
(Programming 'blind' like is considered good practice in this group.)

No, what is considered good practice is programming so that those things
don't matter *except* when you have specific *need* to know them. Or
more generally, so that you are not dependent on the specifics of your
implementation except where you need to be.

Oh, and I have debugged software on hardware with drastically different
characteristics to the target hardware. Specifically 8 bit bytes where
the target had 16 bit bytes and I don't (and didn't even then) know what
other differences. All I replaced was the actual routines which
interfaced to the HW, which was a minuscule amount of the code (two
small functions, one of which needed to be written in assembler for
speed on the target HW).
 
N

Nick Keighley

but irrelevant to C programmers as C is bit-endian blind. How can you
find out which way the bits are ordered? Does the question even make
sense?

If char is 8-bit then a 32-bit quantity only has 4! ways of being
arranged.

Most of the time you don't need to know that stuff, and I *have* done C
development in the defense industry. Not on missile launching systems,
but...

[semi-embedded in my case] quite right. You define the interface
between the processors in terms of streams of bytes (or octets if you
want to sound good). The two ends *really* don't need to know about
each other. I've worked on a system where the "controller" changed
endianess half way through. The impact on the "controlled" system?
None. I'm pretty sure the controller *didn't* know the endianess, word-
size or alignment rules of the controlled system (I'd have been
worried if *had* they cared).

Take a look at ASN.1 or RPC.

No, what is considered good practice is programming so that those things
don't matter *except* when you have specific *need* to know them. Or
more generally, so that you are not dependent on the specifics of your
implementation except where you need to be.

Oh, and I have debugged software on hardware with drastically different
characteristics to the target hardware. Specifically 8 bit bytes where
the target had 16 bit bytes and I don't (and didn't even then) know what
other differences. All I replaced was the actual routines which
interfaced to the HW, which was a minuscule amount of the code (two
small functions, one of which needed to be written in assembler for
speed on the target HW).

desk-top people, what can you do with 'em...
 
T

TonyMc

Flash Gordon said:
Most of the time you don't need to know that stuff, and I *have* done
C development in the defense industry. Not on missile launching
systems, but...

That's a relief because the head of the missile launching systems was Dr
Hans Zarkov.

Tony
 
E

Eric Sosman

Nick said:
but irrelevant to C programmers as C is bit-endian blind. How can you
find out which way the bits are ordered? Does the question even make
sense?

In one sense you can't. I've made the point before by
positing a computer built from four-state components each
storing one "quit" that encodes two bits: It makes no sense
to ask about the order of the two bits encoded in a single
quit.

But in another sense you *can* find an order by looking
at the int as an array of unsigned char, and inspecting the
values in those chars. It is conceivable (although highly
unlikely) that you might find

int c[0] c[1] c[2] c[4]
1 1 0 0 0
2 0 1 0 0
4 0 0 1 0
8 0 0 0 1
16 2 0 0 0
...

That is, there are 32! one-to-one mappings of the value bits
of the int to the value bits of the four bytes.
If char is 8-bit then a 32-bit quantity only has 4! ways of being
arranged.

Ah, but that assumes a sane machine designer! The Standard
does not require sanity (sometimes it engenders the opposite). ;-)
 
N

Nick Keighley

I was thinking along these lines

int x = 0;

x |= 1; /* set the least significant bit */

how can this *not* set the bottom most bit? If I overlay the int with
an array of unsiged char (union, pointer or memcpy) then the mapping
of int octets to unsigned char is at the whim of the implementor. But
he doesn't hae the same degree of freedom at the bit level. A
particular bit in the int can only be in one of 4 possible places in
the byte array.

So I think I'm missing your point.

     In one sense you can't.  I've made the point before by
positing a computer built from four-state components each
storing one "quit" that encodes two bits: It makes no sense
to ask about the order of the two bits encoded in a single
quit.

could you implement an ISO compliant C compiler on such a machine?
Well yes but I think you'd have to hide the quits. That x|= 1 would
still have to work even if the C compiler was run on a machine made of
knotted string.
     But in another sense you *can* find an order by looking
at the int as an array of unsigned char, and inspecting the
values in those chars.  It is conceivable (although highly
unlikely) that you might find

        int    c[0]  c[1]  c[2]  c[4]
         1       1     0     0     0
         2       0     1     0     0
         4       0     0     1     0
         8       0     0     0     1
        16       2     0     0     0
        ...

That is, there are 32! one-to-one mappings of the value bits
of the int to the value bits of the four bytes.

now here I got lost... Are we still discussing quits?

     Ah, but that assumes a sane machine designer!  The Standard
does not require sanity (sometimes it engenders the opposite).  ;-)

I think it forces some degree of sanity on the implementor
 
E

Eric Sosman

Nick said:
I was thinking along these lines

int x = 0;

x |= 1; /* set the least significant bit */

how can this *not* set the bottom most bit? If I overlay the int with
an array of unsiged char (union, pointer or memcpy) then the mapping
of int octets to unsigned char is at the whim of the implementor. But
he doesn't hae the same degree of freedom at the bit level. A
particular bit in the int can only be in one of 4 possible places in
the byte array.

So I think I'm missing your point.

Your claim, then, is that if we look at the bytes of `x'
we will find one byte with the value 1 and the others with
the value 0 (assuming no padding bits). Can you find language
in the Standard to support this claim? I can't, but I may
have overlooked something.

My belief (still assuming no padding bits) is that one
of the bytes must be equal to a power of two and the others
must be zero. But I think that both the identity of the non-
zero byte and the particular power of two are implementation-
defined (or maybe even unspecified).
 
R

Richard Tobin

but irrelevant to C programmers as C is bit-endian blind. How can you
find out which way the bits are ordered? Does the question even make
sense?
[...]

But in another sense you *can* find an order by looking
at the int as an array of unsigned char, and inspecting the
values in those chars. It is conceivable (although highly
unlikely) that you might find

int c[0] c[1] c[2] c[4]
1 1 0 0 0
2 0 1 0 0
4 0 0 1 0
8 0 0 0 1
16 2 0 0 0
...[/QUOTE]

To determine a "bit endianness" you need to have a way of addressing
bits. That's what endianness is: at which end (or more generally
position) of the large unit at a given address do you find the small
unit at that address.

Eric's example doesn't tell us the bit endianness; it just shows
something about how the endianness for bytes and ints is related. And
in this case there would be no such thing a byte endianness for ints,
since the byte doesn't appear at a position within the int.

One situation where bit endianness is exposed is old monochrome
bit-mapped displays: you can see whether the low order bit of a byte
is the left or the right pixel.

-- Richard
 
E

Edward A. Falk

Flash Gordon had the best answer, and I have almost nothing to add.

My $.02:

You (or more precisely, your instructor) are making completely unsupported
assumptions about the underlying hardware. The question is unanswerable
as stated.

I *think* that if you assume 4-byte ints and floats, and that the ints
are stored in 2's-complement form, and the floats are stored in standard
IEEE format, then the problem is answerable. Learn what the IEEE format
is, learn the range that drand48() can return, try writing down on paper
what a few floating-point values might look like in binary, and you will
find your answer.

(I'm going to assume you know what 2's-complement form is, but then I
may be making my own unsupported assumption.)
 
L

lawrence.jones

Rich Webb said:
To carry this forward a bit, the specific Thou Shalt Not sentence is in
informative appx J.1, Unspecified Behavior: "The value of a union member
other than the last one stored into (6.2.6.1)."

But if we go back to 6.2.6.1, the discussion on unions states: "When a
value is stored in an object of structure or union type, including in a
member object, the bytes of the object representation that correspond to
any padding bytes take unspecified values."

The relevant part of 6.2.6.1 is actually the following paragraph:

7 When a value is stored in a member of an object of union type,
the bytes of the object representation that do not correspond to
that member but do correspond to other members take unspecified
values.
Given this statement, if the objects used in the type punning are the
same size and thus no padding bytes are involved, does that imply that
the unspecified behavior is not invoked?

Not necessarily, you still have to worry about potential trap
representations, padding bits, and the unspecified nature of most
representations. In particular, if you store an int value and read it
back as a float, even if ints and floats are the same size, the actual
float value you get is unspecified and may be a trap representation.
 
E

Edward A. Falk

I am wondering if you could tell me about a platform in which the following
would compile, but fail at the assertion:

A PDP-11, perhaps. Depends on what size the compiler uses for int
and whether or not chars are unsigned. If chars are signed and
ints are 16 bits, then static_assert would pass but assert() would
fail.

PDP-11 stores its bytes little-endian but its halfwords big-endian.

Of course, we're now way off the rails as far as C standards
are concerned.
#include <assert.h>


typedef char static_assert
[
sizeof(unsigned int) == sizeof(unsigned long int) ? 1 : -1
];


union foo
{
unsigned int a;
unsigned long int b;
};


int main(void)
{
union foo f = { 0 };

++f.a;

assert(f.b == 1);

return 0;
}
 
E

Edward A. Falk

I don't think you need be worried about this.
The highly secure U.S. missile launching systems
run Microsoft Vista on Intel boxes.

Haven't you been reading the news? It's all PS3s now.
 
R

Richard Bos

Eric Sosman said:
Rich said:
[... "type-punning with unions needn't work" ...]
But there are at least two possible objections to my gloomy
assessment: First, unions are so commonly used for type-punning
that an implementor might well "make it work" even if the code
is (technically) wrong. Second, I may have misunderstood the
matter; sometimes the language of the Standard requires study
of an intensity exceeding my ability.

To carry this forward a bit, the specific Thou Shalt Not sentence is in
informative appx J.1, Unspecified Behavior: "The value of a union member
other than the last one stored into (6.2.6.1)."

But if we go back to 6.2.6.1, the discussion on unions states: "When a
value is stored in an object of structure or union type, including in a
member object, the bytes of the object representation that correspond to
any padding bytes take unspecified values."

Given this statement, if the objects used in the type punning are the
same size and thus no padding bytes are involved, does that imply that
the unspecified behavior is not invoked?

That's the source of my doubt: I'm not 100% sure the
normative text makes the punning undefined in the "perfect
overlap" case. The appendix says so, but it's non-normative.
And, as you point out, it seems to overstate the normative
text's case a little bit.

Even with perfect overlap, of course, there's still the
possibility that storing one member could produce something
that would be a trap representation when viewed via a different
member. The O.P.'s code stored a float and than manipulated
its representation as an int; integers usually don't have trap
representations but the result when viewed as a float might be
a signalling NaN for all anyone knows to the contrary.

I think that your last paragraph is sufficient reason for concluding
that union-punning is indeed officially undefined behaviour in the
general case (even though it does work in the more usual cases).

Richard
 
K

Kaz Kylheku

Eric Sosman said:
Rich said:
"type-punning with unions needn't work" ...]
But there are at least two possible objections to my gloomy
assessment: First, unions are so commonly used for type-punning
that an implementor might well "make it work" even if the code
is (technically) wrong. Second, I may have misunderstood the
matter; sometimes the language of the Standard requires study
of an intensity exceeding my ability.

To carry this forward a bit, the specific Thou Shalt Not sentence is in
informative appx J.1, Unspecified Behavior: "The value of a union member
other than the last one stored into (6.2.6.1)."

But if we go back to 6.2.6.1, the discussion on unions states: "When a
value is stored in an object of structure or union type, including in a
member object, the bytes of the object representation that correspond to
any padding bytes take unspecified values."

Given this statement, if the objects used in the type punning are the
same size and thus no padding bytes are involved, does that imply that
the unspecified behavior is not invoked?

That's the source of my doubt: I'm not 100% sure the
normative text makes the punning undefined in the "perfect
overlap" case. The appendix says so, but it's non-normative.
And, as you point out, it seems to overstate the normative
text's case a little bit.

Even with perfect overlap, of course, there's still the
possibility that storing one member could produce something
that would be a trap representation when viewed via a different
member. The O.P.'s code stored a float and than manipulated
its representation as an int; integers usually don't have trap
representations but the result when viewed as a float might be
a signalling NaN for all anyone knows to the contrary.

I think that your last paragraph is sufficient reason for concluding
that union-punning is indeed officially undefined behaviour in the
general case (even though it does work in the more usual cases).

I believe that union punning requires implementations only to defeat
their caching optimizations which depend on strict aliasing assumptions.

That is to say, access to a union using a member which was not used for
the most recent store should not fetch stale data.

Whereas straight type punning with pointers is susceptible to this stale
cache problem, in addition to all of the potential representational
issues.

The behavior of union access can be inferred for a given implementation,
if you know the details of the representation of types on a given
implementation. If, according to the representations, the bits all make
sense, then it has to work.
 
D

David Thompson

A PDP-11, perhaps. Depends on what size the compiler uses for int
and whether or not chars are unsigned. If chars are signed and
ints are 16 bits, then static_assert would pass but assert() would
fail.
Signedness of char doesn't matter; his dummy array was never accessed.
For I16 (the traditional and IMO best choice for -11) the static
assert will fail; for I32L32 it will compile and run okay, since there
is only one reasonable (hardware-supported) 32-bit integer.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top