[comp.os.msdos.programmer] Microsoft C actually does something better!

toma@sail.LABS.TEK.COM (Tom Almy) (02/05/91)

Microsoft C has been bad-mouthed here by myself and others over the years,
but this past weekend I discovered at least one place where it beats the
major competition -- the math library. Two cases:

Case 1: { double x=1e200; printf("%g",x*x); }
(With some compilers, the 80x87 has to have the overflow trap masked off).

Microsoft C (V6.00A): prints +inf	(correct!)
Microway NDP C-386 (V1.4e): prints -*inf** (wrong sign!?!)
Metaware High C DOS 386 (V1.62): prints infinity (correct!)
Turbo C (C++ V1.0): hangs, requiring "three fingered salute".
Zortech C (V2.18): prints 1.797693e+308

Case 2: { double x=1e50; x = sin(x); printf("%g", x);}
( matherr() function defined where available )

Microsoft: sine function causes error "Total loss of significance" (correct!)
Microway: crashes, producing register dump, executing sine function.
Metaware: with inline 80387 code, 1e50; with fp library, NaN (ok.)
Turbo C: sine function causes error "Domain" (wrong error)
Zortech C: prints garbage answer.

A test of some other language compilers produced dismal results as well.
Only Microsoft C worked.

Tom Almy
toma@sail.labs.tek.com 
Standard Disclaimers Apply

-- 
Tom Almy
toma@sail.labs.tek.com <<< Note new address
Standard Disclaimers Apply

dmurdoch@watstat.waterloo.edu (Duncan Murdoch) (02/05/91)

In article <8904@sail.LABS.TEK.COM> toma@sail.LABS.TEK.COM (Tom Almy) writes:
>Microsoft C has been bad-mouthed here by myself and others over the years,
>but this past weekend I discovered at least one place where it beats the
>major competition -- the math library. Two cases:
>
>Case 1: { double x=1e200; printf("%g",x*x); }
>(With some compilers, the 80x87 has to have the overflow trap masked off).

I tried your tests in Turbo Pascal 6.0, and was pleasantly surprised at the
results.  (TP 6.0 has some real problems with esoteric floating point code.)
>
>Microsoft C (V6.00A): prints +inf	(correct!)

MSC may be correct for C, but TP prints 1.00000000E+0400, which is even more
correct.  (This is because TP promotes expressions to the 10 byte extended 
type.)  When I forced the result to go into a double, I got an overflow 
error; when I masked those, I got INF.
>
>Case 2: { double x=1e50; x = sin(x); printf("%g", x);}
>( matherr() function defined where available )
>
>Microsoft: sine function causes error "Total loss of significance" (correct!)

TP just gives an invalid operation error, or a NAN when masked.

>A test of some other language compilers produced dismal results as well.
>Only Microsoft C worked.

And TP!

Duncan Murdoch
dmurdoch@watstat.waterloo.edu

kdq@demott.com (Kevin D. Quitt) (02/06/91)

In article <1991Feb5.020455.26710@maytag.waterloo.edu> dmurdoch@watstat.waterloo.edu (Duncan Murdoch) writes:
>In article <8904@sail.LABS.TEK.COM> toma@sail.LABS.TEK.COM (Tom Almy) writes:
>>Microsoft C has been bad-mouthed here by myself and others over the years,
>>but this past weekend I discovered at least one place where it beats the
>>major competition -- the math library. Two cases:
>>
>>Case 1: { double x=1e200; printf("%g",x*x); }
>>(With some compilers, the 80x87 has to have the overflow trap masked off).
>
>I tried your tests in Turbo Pascal 6.0, and was pleasantly surprised at the
>results.  (TP 6.0 has some real problems with esoteric floating point code.)
>>
>>Microsoft C (V6.00A): prints +inf	(correct!)
>
>MSC may be correct for C, but TP prints 1.00000000E+0400, which is even more
>correct.  (This is because TP promotes expressions to the 10 byte extended 
>type.)  When I forced the result to go into a double, I got an overflow 
>error; when I masked those, I got INF.

    It's more correct mathematically, but not according to the C language
spec.  There *are* (non-standard) ways in MSC to use the 10-byte reals.
-- 
 _
Kevin D. Quitt         demott!kdq   kdq@demott.com
DeMott Electronics Co. 14707 Keswick St.   Van Nuys, CA 91405-1266
VOICE (818) 988-4975   FAX (818) 997-1190  MODEM (818) 997-4496 PEP last

6600m00n@ucsbuxa.ucsb.edu (Steelworker) (02/06/91)

In article <8904@sail.LABS.TEK.COM> toma@sail.LABS.TEK.COM (Tom Almy) writes:

>Microsoft C has been bad-mouthed here by myself and others over the years,
>but this past weekend I discovered at least one place where it beats the
>major competition -- the math library. Two cases:

>Case 1: { double x=1e200; printf("%g",x*x); }
>(With some compilers, the 80x87 has to have the overflow trap masked off).

First problem-  the printf should read 
printf("%lg",x*x);
         ^
I have made this error enough times to preach about this one!

Try your test's again with this and post the results.

Robert Blair
6600m00n@ucsbuxa.ucsb.edu

dmurdoch@watstat.waterloo.edu (Duncan Murdoch) (02/06/91)

In article <1991Feb5.184015.9539@demott.com> kdq@demott.com (Kevin D. Quitt) writes:
>>
>>MSC may be correct for C, but TP prints 1.00000000E+0400, which is even more
>>correct.  (This is because TP promotes expressions to the 10 byte extended 
>>type.)  When I forced the result to go into a double, I got an overflow 
>>error; when I masked those, I got INF.
>
>    It's more correct mathematically, but not according to the C language
>spec.  There *are* (non-standard) ways in MSC to use the 10-byte reals.

Sure, I understand that.  Just curious though:  does the C standard address
the problem of what to do when an expression overflows?  That seems like such
a machine dependent thing that I'd think it would be left up to the 
implementation, but you never know.

Duncan Murdoch
dmurdoch@watstat.waterloo.edu

kooijman@duteca (Richard Kooijman) (02/07/91)

6600m00n@ucsbuxa.ucsb.edu (Steelworker) writes:

>In article <8904@sail.LABS.TEK.COM> toma@sail.LABS.TEK.COM (Tom Almy) writes:


>>Case 1: { double x=1e200; printf("%g",x*x); }
>>(With some compilers, the 80x87 has to have the overflow trap masked off).

>First problem-  the printf should read 
>printf("%lg",x*x);
>         ^
>I have made this error enough times to preach about this one!

WRONG, the l modifier only applies to long int's and not floating point
numbers.

Richard.

ath@linkoping.telesoft.se (Anders Thulin) (02/07/91)

In article <8904@sail.LABS.TEK.COM> toma@sail.LABS.TEK.COM (Tom Almy) writes:

>Case 1: { double x=1e200; printf("%g",x*x); }
>(With some compilers, the 80x87 has to have the overflow trap masked off).
>
>Microsoft C (V6.00A): prints +inf	(correct!)
>Microway NDP C-386 (V1.4e): prints -*inf** (wrong sign!?!)
>Metaware High C DOS 386 (V1.62): prints infinity (correct!)
>Turbo C (C++ V1.0): hangs, requiring "three fingered salute".
>Zortech C (V2.18): prints 1.797693e+308

Why is 'infinity' the correct answer? I don't think ANSI C says
anything about that, so the Zortech answer may be 'as correct' as the
Microsoft or Metware.

>Case 2: { double x=1e50; x = sin(x); printf("%g", x);}
>( matherr() function defined where available )
>
>Microsoft: sine function causes error "Total loss of significance" (correct!)
>Microway: crashes, producing register dump, executing sine function.
>Metaware: with inline 80387 code, 1e50; with fp library, NaN (ok.)
>Turbo C: sine function causes error "Domain" (wrong error)
>Zortech C: prints garbage answer.

A suggestion:

In an ANSI C environment, you must clear errno before the invocation
of sin, and test it afterwards to detect any errors. As I don't see
it in your code, I suspect you didn't use it.

Naturally, 'correctness' must be relative some standard. I assume ANSI C,
but you may have chosen something different.




-- 
Anders Thulin       ath@linkoping.telesoft.se 
Telesoft Europe AB, Teknikringen 2B, S-583 30 Linkoping, Sweden

toma@sail.LABS.TEK.COM (Tom Almy) (02/11/91)

In article <730@castor.linkoping.telesoft.se> ath@linkoping.telesoft.se (Anders Thulin) writes:
>In article <8904@sail.LABS.TEK.COM> toma@sail.LABS.TEK.COM (Tom Almy) writes:
>
>>Case 1: { double x=1e200; printf("%g",x*x); }
>>(With some compilers, the 80x87 has to have the overflow trap masked off).
>>Microsoft C (V6.00A): prints +inf	(correct!)
>>Microway NDP C-386 (V1.4e): prints -*inf** (wrong sign!?!)
>>Metaware High C DOS 386 (V1.62): prints infinity (correct!)
>>Turbo C (C++ V1.0): hangs, requiring "three fingered salute".
>>Zortech C (V2.18): prints 1.797693e+308

>Why is 'infinity' the correct answer? I don't think ANSI C says
>anything about that, so the Zortech answer may be 'as correct' as the
>Microsoft or Metware.

In every case IEEE floating point is used. The floating point co-processor
generates the result "+inf". The Zortech runtime doesn't recognize the
special value, but instead prints the largest float. "+inf" is more correct
because that is the internally represented value, and is also indicative
that overflow has occured. It is interesting to note that only the ZOrtech
compiler does not mask overflow by default -- with the other compilers
(which print "inf") you have to mask overflow to get the infinity result
since they would otherwise abort with a fp overflow trap.

>>Case 2: { double x=1e50; x = sin(x); printf("%g", x);}
>>( matherr() function defined where available )
>>Microsoft: sine function causes error "Total loss of significance" (correct!)
>>Microway: crashes, producing register dump, executing sine function.
>>Metaware: with inline 80387 code, 1e50; with fp library, NaN (ok.)
>>Turbo C: sine function causes error "Domain" (wrong error)
>>Zortech C: prints garbage answer.

>A suggestion:

>In an ANSI C environment, you must clear errno before the invocation
>of sin, and test it afterwards to detect any errors. As I don't see
>it in your code, I suspect you didn't use it.

Microsoft, Turbo, and Zortech provide matherr() functions which are supposed
to trap the errors (in fact all but Zortech did). Neither Metaware nor
Zortech set errno. I was able to get Zortech to indicate an error by
telling the run time that no floating point was available -- it gives the
error when the emulator is used! But that doesn't help performance.

An investigation of this problem showed that the library implementers
did not RTFM! The sine function (and some others) leave the argument 
untouched when out of range, but set a flag indicating failed reduction.
These compilers just fail to check the flag.

>Naturally, 'correctness' must be relative some standard. I assume ANSI C,
>but you may have chosen something different.

IMHO C is not my language of choice for numeric programs because it is
so slopily defined (although I must admit ANSI C is improving). Expecting
floating point errors to be handled might be asking too much, but as I
said "Microsoft C actually does something better."

Tom Almy
toma@sail.labs.tek.com
Standard Disclaimers Apply


-- 
Tom Almy
toma@sail.labs.tek.com
Standard Disclaimers Apply