wendyt@isieng.UUCP (Wendy Thrash) (01/21/86)
Followup-To: About two weeks ago I posted my large double to unsigned conversion test program. This program was motivated by my own attempts to do something reasonable with a 68020/68881 compiler. The 68881 is a lovely chip in some ways. It makes float/double->int conversions very easy. Unfortunately, it has no concept of unsigned (or if it does, I've been too stupid to find it.) I was trying to decide how much care it was reasonable to take, wondered what other compiler writers had done. Many thanks to those who sent replies or posted followups. My choice for the gold medal is gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>), who posted a followup, run with SVR2 on an unspecified VAX: Values 1 2147483647 2147483648 2147483649 4294967295 Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Turn into 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Negated, into 0xffffffff 0x80000001 0x80000000 0x7fffffff 0x00000001 Incremented, 0x80000001 0xffffffff 0x00000000 0x00000001 0x7fffffff Inc. & neg., 0x7fffffff 0x00000001 0x00000000 0xffffffff 0x80000001 Doug suggests that this seems correct "according to the language rules," and I agree. Actually, K&R state that "The result is undefined if the value will not fit in the space provided." It may be undefined to the user, but compiler writers have to set it to SOMETHING. To me (and, apparently, to DG) it makes some sense to have double->unsigned conversions wrap around in the same way as int->char and the like. Although things are a bit fuzzy, the first three lines seem like the kind of thing a compiler ought to be able to do as a minimum: take an unsigned, convert it into a double, get the correct (positive) numerical value, convert that back into unsigned, and get what you started with. The fourth line should also easy, as should the first two columns of the last two lines. I received results from eight other systems. NONE matched the results above, and they seldom matched each other. (I suppose the program should have done some fflush(stdout) calls for the sake of the 3B-20s. Mea culpa.) Results can be found at the end of this article. I also received mail from Philip Kos (osiris!phil) and Tracey Baker (gatech!vax135!tab), but the bodies of their messages were somehow stripped, so I have no idea what they sent. Again, thanks to all. Ken Turkowski ( {amd,decwrl,hplabs,seismo,spar}!turtlevax!ken ) is the only one who responded to my question about really large values. His followup suggests arithmetic exceptions and 0xffffffff when things get out of hand. Sounds good, but I still like wraparound as long as there is any precision left. Conclusion: Don't assume that your compiler does what you would expect. As the guy used to say on Hill Street Blues, "Let's be careful out there." -------------------------- results follow ---------------------------- Tony Hansen (ihnp4!pegasus!hansen) sent mail with the following results from an AT&T 3B-20 running System V release 2: Values 1 2147483647 2147483648 2147483649 4294967295 Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Floating exception - core dumped Robert Skinner sent the following: VAX 11/750 with S/W NON-IEEE floating point: Values 1 2147483647 -2147483648 -2147483647 -1 Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Turn into 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Negated, into 0xffffffff 0x80000001 0x80000000 0x7fffffff 0x00000001 Incremented, 0x80000001 0xffffffff 0x00000000 0x00000001 0x7fffffff Inc. & neg., 0x7fffffff 0x00000001 0x00000000 0xffffffff 0x80000001 National Semi 32032 with H/W IEEE floating point: Values 1.0000000000 2147483647 -2147483648 -2147483647 -1.0000000000 Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Turn into 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Negated, into 0xffffffff 0x80000001 ********** 0x7fffffff 0x00000001 Incremented, ********** ********** 0x00000000 0x00000001 0x7fffffff Inc. & neg., ********** ********** 0x00000000 0xffffffff 0x80000001 ***** = Floating Point Exception in truncation to integer. Roger Hayes <pyramid!Shasta!rogerh%arizona.csnet@CSNET-RELAY.ARPA> sent the following: Vax/8600 running a beta 4.3: (crt0.c 5.1 (Berkeley) 5/30/85, cc.c 4.13 9/18/85) Values 1 2147483647 -2147483648 -2147483647 -1 Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Turn into 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Negated, into 0xffffffff 0x80000001 0x80000000 0x7fffffff 0x00000001 Incremented, 0x80000001 0xffffffff 0x00000000 0x00000001 0x7fffffff Inc. & neg., 0x7fffffff 0x00000001 0x00000000 0xffffffff 0x80000001 Sun-120, running Sun 4.2 version 2.0: (crt0.s 1.1 84/12/20 Copyr 1983 Sun Micro ... cc.c 1.1 84/12/20 SMI ... ecvt.c 1.1 84/12/20 Copyr 1984 Sun Micro ... isinf.c 1.1 84/12/20 SMI ...) Values 1 2147483647 -2147483648 -2147483647 -1 Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Turn into 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Negated, into 0xffffffff 0x80000001 0x80000000 0x7fffffff 0x00000001 Incremented, 0x80000000 0x80000000 0x00000000 0x00000001 0x7fffffff Inc. & neg., 0x80000000 0x80000000 0x00000000 0xffffffff 0x80000001 "a HP 9040 (?) system we have lying around:" (/bin/cc: 26.1) Values 1 2147483647 -2147483648 -2147483647 -1 Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Turn into 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Negated, into 0xffffffff 0x80000001 0x7fffffff 0x7fffffff 0x00000001 Incremented, 0x7fffffff 0x7fffffff 0x00000000 0x00000001 0x7fffffff Inc. & neg., 0x80000000 0x80000000 0x00000000 0xffffffff 0x80000001 "a Ridge-32 running some version of ROS:" (cc.v 1.36 6/7/85) Values 1 2147483647 -2147483648 -2147483647 -1 Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Turn into 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff Negated, into 0xffffffff 0x80000001 0x7fffffff 0x7fffffff 0x00000001 Incremented, 0x7fffffff 0x7fffffff 0x00000000 0x00000001 0x7fffffff Inc. & neg., 0x80000000 0x80000000 0x00000000 0xffffffff 0x80000001 3B5 running Sys V rel 2.0 version 2: Illegal instruction - core dumped
gwyn@brl-tgr.UUCP (01/22/86)
> Values 1 2147483647 2147483648 2147483649 4294967295 > Came from 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff > Turn into 0x00000001 0x7fffffff 0x80000000 0x80000001 0xffffffff > Negated, into 0xffffffff 0x80000001 0x80000000 0x7fffffff 0x00000001 > Incremented, 0x80000001 0xffffffff 0x00000000 0x00000001 0x7fffffff > Inc. & neg., 0x7fffffff 0x00000001 0x00000000 0xffffffff 0x80000001 > > Doug suggests that this seems correct "according to the language rules," > and I agree. Actually, K&R state that "The result is undefined if the > value will not fit in the space provided." It may be undefined to the > user, but compiler writers have to set it to SOMETHING. To me (and, > apparently, to DG) it makes some sense to have double->unsigned conversions > wrap around in the same way as int->char and the like. X3J11 has been a bit more thorough in specifying arithmetic conversions, and my belief is that the above results agree with what they propose. > Conclusion: Don't assume that your compiler does what you would expect. > As the guy used to say on Hill Street Blues, "Let's be careful out there." Especially beware of Berkeley-based systems, which often use C compilers derived from a PCC of approximately USG 3.0 vintage. That compiler did not properly propagate types through expressions. (The same is true of older Ritchie PDP-11 C compilers.) Except for the ICON problem reported some time ago, I have not experienced any unpleasant surprises due to the SVR2 VAX PCC's interpretation of the C language rules. One would hope that PCC2 (which I do not have access to) is as reliable, but after your posting of the results, this is less certain. (Surely at least one of those 3Bs must have used PCC2?)