- Community Home
- >
- Servers and Operating Systems
- >
- Operating Systems
- >
- Operating System - OpenVMS
- >
- 104.0 > 100000001: C 6.5 bug?
Categories
Company
Local Language
Forums
Discussions
Forums
- Data Protection and Retention
- Entry Storage Systems
- Legacy
- Midrange and Enterprise Storage
- Storage Networking
- HPE Nimble Storage
Discussions
Discussions
Discussions
Forums
Forums
Discussions
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
- BladeSystem Infrastructure and Application Solutions
- Appliance Servers
- Alpha Servers
- BackOffice Products
- Internet Products
- HPE 9000 and HPE e3000 Servers
- Networking
- Netservers
- Secure OS Software for Linux
- Server Management (Insight Manager 7)
- Windows Server 2003
- Operating System - Tru64 Unix
- ProLiant Deployment and Provisioning
- Linux-Based Community / Regional
- Microsoft System Center Integration
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Discussion Boards
Community
Resources
Forums
Blogs
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-09-2003 04:01 PM
тАО11-09-2003 04:01 PM
$ cc/version
Compaq C V6.5-001 on OpenVMS Alpha V7.3-1
Consider the following test program:
$ type relcomp.c
#include
#define BIGNUM 100000001
int
main() {
float x = 104.0;
( x <= BIGNUM ?
printf("%f <= %d\n", x, BIGNUM)
: printf("%f NOT <= %d !!!\n", x, BIGNUM) );
}
Most compile options cause this program to yield the expected result, namely that 104.0 is less than a 9-digit integer. However, with /FLOAT=IEEE/IEEE=DENORM_RESULTS, the opposite happens:
$ cc/float=ieee/ieee=denorm relcomp
$ link relcomp
$ run relcomp
104.000000 NOT <= 100000001 !!!
If I understand the C standard on how this should work, the first thing that should happen in the comparison "104.0 <= 100000001" is that 100000001 should be converted to a double. That's because all operands of the relational operators (when they are not pointers) must be of real type, and the real type required to hold 100000001 is a double. Then the single precision value 104.0 should also be converted to a double since when comparing two types in the same type domain (in this case two real types), everything should be converted to the type with the greater range. At last the comparison should take place between two doubles.
Something about /IEEE=DENORM seems to throw a wrench in the procedure I've described above. I'd suspect 100000001 is being converted to a single precision real that of course can't hold the value and denormalization suppresses any exceptions while picking a number that can be represented as a single, a number that apparently turns out to be less than 104. That's just a hunch and I've spared myself generating a machine listing to see what actually happens since Alpha assembler and I are not well acquainted with each other.
So, is this a compiler bug, or is there some rationale for what happens?
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-09-2003 06:48 PM
тАО11-09-2003 06:48 PM
Re: 104.0 > 100000001: C 6.5 bug?
#define BIGNUM 100000001 int
I altered the program a bit (for what I can tell functional the same)
#include
#define BIGNUM 100000001
int
main() {
float x = 104.0;
float y = BIGNUM * 1.0 ; <------ ADDED
( x <= y ? <------ modified
printf("%f <= %d\n", x, BIGNUM)
: printf("%f NOT <= %d !!!\n", x, BIGNUM) );
}
and then the output IS correct:
BPS2004A> run t
104.000000 <= 100000001
BPS2004A>
I don't know C that well, I would say: compiler bug.
OpenVMS Developer & System Manager
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-09-2003 08:09 PM
тАО11-09-2003 08:09 PM
Re: 104.0 > 100000001: C 6.5 bug?
this is weird or a bug of optimizer; if you use standard form
if ( x <= BIGNUM)
printf("%f <= %d\n", x, BIGNUM);
else
printf("%f NOT <= %d !!!\n", x, BIGNUM;
program fails however?
Also it's better write
#define 100000001.0
so you avoid some cast conversion and try using CC/NOOPT.
I complied your example but my old CC (V5) works fine and I can't help you.
Bye
Antoniov
P.S.
Because using CC V5 your program works, I think it's a bug of V6.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-09-2003 09:45 PM
тАО11-09-2003 09:45 PM
Re: 104.0 > 100000001: C 6.5 bug?
OpenVMS Developer & System Manager
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-09-2003 10:08 PM
тАО11-09-2003 10:08 PM
Re: 104.0 > 100000001: C 6.5 bug?
#include
#define BIGNUM 100000001
int
main() {
float x = 104.0;
( x <= BIGNUM ?
printf("%f <= %d\n", x, BIGNUM)
: printf("%f NOT <= %d !!!\n", x, BIGNUM) );
float y = BIGNUM * 1.0 ;
( x <= y ? printf("%f <= %d\n", x, BIGNUM) : printf("%f NOT <= %d !!!\n", x, BIGNUM) );
if ( x <= BIGNUM)
printf("%f <= %d\n", x, BIGNUM);
else
printf("%f NOT <= %d !!!\n", x, BIGNUM);
}
compiled /FLOAT=IEEE/IEEE=DENORM_RESULTS, output is:
104.000000 NOT <= 100000001 !!!
104.000000 <= 100000001
104.000000 NOT <= 100000001 !!!
same with /NOOPT.
Adding ".0" to BIGNUM as Antonio suggest gives compliation warnings %CC-W-OUTFLOATINT (obviously) on th eprintf for output, but results are musch more in line with expectations:
104.000000 <= 67108864
104.000000 <= 67108864
104.000000 <= 67108864
Ok, the output IS wrong but it seems the IF statement is Ok.
It _could_ be a compiler bug, but, on the other hand, you _ought_ to know that you're comparing float to int in this example. So it could be a deliberate choice, since the last changed example yields the correct result of the IF statement.
OpenVMS Developer & System Manager
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-10-2003 12:05 AM
тАО11-10-2003 12:05 AM
Re: 104.0 > 100000001: C 6.5 bug?
I can't suggest no more, because my old version of cc works fine (in this case)!!
It's a bug compiler, this is sure.
Craig,
until there is a new patch, I think you could make as Willen suggested or you have to compile without /IEE=DENORM.
Also, send notice to HP.
Bye
Antoniov
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-10-2003 05:54 AM
тАО11-10-2003 05:54 AM
Re: 104.0 > 100000001: C 6.5 bug?
Thanks for the replies. There are certainly several ways one can force 100000001 to be a double, either at compile time or run time. The rules as I read them, though, seem to indicate the conversion should happen without any special tricks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-10-2003 03:50 PM
тАО11-10-2003 03:50 PM
Re: 104.0 > 100000001: C 6.5 bug?
As you're almost certainly aware, floating point arithmetic can do some very odd things. Even more so when you start playing at the fringes of the IEEE features, like denorms, NaNs and infinities.
According to the listing, your BIGNUM value is being interpreted as 0.175x10**-37
00BEBC20 0044 .LONG X^BEBC20 ; .S_FLOATING 0.1751623E-37
42D00000 0048 .LONG X^42D00000 ; .S_FLOATING 104.0000
Although I haven't worked out why, I wouldn't be too surprised to find there is a valid "language lawyer" reason, buried in an obscure paragraph of some IEEE standards document.
Do you really need /IEEE=DENORM? What do you think it's buying you?
Best practice in ANY language is to express ALL data type conversions, no matter how trivial, explicitly and unambiguously. Take care to make sure you KNOW the data type of any object and be aware of it's limitations and ideosyncrasies. For example, in most cases a test for exact equality of floating point values will be incorrect!
The vast majority of cases I see can be explained by misunderstanding the rules of the language. People are often horrified to see the complex chain of type conversions that an apparently innocuous little statement can generate. (though C is nowhere near as bad as, say, Basic in this area).
Although I'm leaning toward "bug" for this program, I'm not completely convinced. I'll run your program past the compiler engineers to see what they think.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-11-2003 01:14 AM
тАО11-11-2003 01:14 AM
Re: 104.0 > 100000001: C 6.5 bug?
Thanks for your comments and for running this by the C folks. I think what you've posted confirms that it generates a denorm when it can't store 100000001 in a single precision float. That certainly follows the rules for denorms. So I guess this is really a question of whether the rules for comparisons using relational operators trump the rules for generating denorms in this case.
The program I posted is a greatly reduced example of a problem I encountered in porting some open source code that needs to convert various types to integer types. It needs to check whether the source of the conversion is within a range that can be represented by the target and return an error if not. It needs to do so portably, so trapping exceptions is really out of the question. So there are a bunch of macros like so, where "x" may be a real or integer of varying sizes:
#define REAL_RANGE_INT(x) ( INT_MIN <= (x) && (x) <= INT_MAX )
This works ok except when denorms are enabled, and I've enabled those because there are some places in the code that want to break the rules without generating exceptions (i.e., underflow, overflow, and such). I can work a bit harder to see if I can get away without denorms, but it's possible I can't, in which case I'll probably have to complicate the range checking logic.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
тАО11-11-2003 01:29 AM
тАО11-11-2003 01:29 AM
Re: 104.0 > 100000001: C 6.5 bug?
I my memory doesn't swindle my mind (!?) in IEEE standard NaN is applicable only to double not to single precision (but I not sure). So your code may work using double
#include
#define BIGNUM 100000001
int
main() {
double x = 104.0;
( x <= BIGNUM ?
printf("%f <= %d\n", x, BIGNUM)
: printf("%f NOT <= %d !!!\n", x, BIGNUM) );
}
I can't try because V5 works fine; try installa old version of cc.
Bye
Antoniov