## c++ - cos bug

- "Steve Hall" <sthall lorrexinc.com> Jun 04 2003
- Heinz Saathoff <hsaat bre.ipnet.de> Jun 05 2003
- "Steve Hall" <sthall lorrexinc.com> Jun 05 2003
- Keith Fuller <Keith_member pathlink.com> Jun 05 2003
- "Steve Hall" <sthall lorrexinc.com> Jun 05 2003
- "Walter" <walter digitalmars.com> Jun 05 2003
- "Steve Hall" <sthall lorrexinc.com> Jun 06 2003
- "Walter" <walter digitalmars.com> Jun 06 2003
- Keith Fuller <Keith_member pathlink.com> Jun 05 2003
- Heinz Saathoff <hsaat bre.ipnet.de> Jun 06 2003
- "Walter" <walter digitalmars.com> Jun 06 2003

The following code return wrong result: #include <math.h> #include <stdio.h> int main() { float vf = 7.7915e19; double vd = 7.7915e19; long double vl = 7.7915e19; printf("cosf(%lg) = %lg\n", vf, cosf(vf)); printf("cos(%lg) = %lg\n", vd, cos(vd)); printf("cosl(%Lg) = %Lg", vl, cosl(vl)); return 0; } The output is: cosf(7.7915e+19) = 7.7915e+19 cos(7.7915e+19) = 7.7915e+19 cosl(7.7915e+19) = 7.7915e+19 The used compiler is Digital Mars Compiler v8.34. Regards, Steve

Jun 04 2003

Steve Hall schrieb...include <math.h> #include <stdio.h> int main() { float vf = 7.7915e19; double vd = 7.7915e19; long double vl = 7.7915e19; printf("cosf(%lg) = %lg\n", vf, cosf(vf)); printf("cos(%lg) = %lg\n", vd, cos(vd)); printf("cosl(%Lg) = %Lg", vl, cosl(vl)); return 0; } The output is: cosf(7.7915e+19) = 7.7915e+19 cos(7.7915e+19) = 7.7915e+19 cosl(7.7915e+19) = 7.7915e+19 The used compiler is Digital Mars Compiler v8.34.

1. Why use such a huge number as argument to cos? 2. My old 486 Processor handbook tells me that the argument range is abs(arg) < 2^63 2^63 = 9.2233e+18 I would assume this is also valid for the pentiom family? So your argument is already out of range for the numeric coprozessor. When the coprocessor exception is ignored (as is with DM) then the argument on FPU stack isn't changed and you get back the argument unmodified. - Heinz

Jun 05 2003

Heinz, thank you for your reply. dmc v3.34 is a C99 conformed compiler with IEC 60559 support according to macros __STDC_VERSION__(199901) and __STDC_IEC_559__. Types float and double are respectively single and double precision types from IEC 60559(Binary floating-point arithmetic for microprocessor systems, second edition). The floating-point standard is independent of the hardware. According to C99 the maximum representable number for type float is FLT_MAX = 3.40282347E+38, for type double is DBL_MAX = 1.7976931348623157E+308. Type double is subset of type long double, which is compiler dependent(for dmc v3.34 long double contain 80 bits). The same code compiled with gcc v3.2.3 (mingw special 20030504-1) return reasonable results for functions cos and cosf(the recent version of MinGW gcc doesn't support properly displaying of long double type thru printf function). The software that I develop depend on precision C99 floating-point arithmetic. Regards, Steve "Heinz Saathoff" <hsaat bre.ipnet.de> wrote in message news:MPG.194952a884bb81f79896bc news.digitalmars.com...Steve Hall schrieb...include <math.h> #include <stdio.h> int main() { float vf = 7.7915e19; double vd = 7.7915e19; long double vl = 7.7915e19; printf("cosf(%lg) = %lg\n", vf, cosf(vf)); printf("cos(%lg) = %lg\n", vd, cos(vd)); printf("cosl(%Lg) = %Lg", vl, cosl(vl)); return 0; } The output is: cosf(7.7915e+19) = 7.7915e+19 cos(7.7915e+19) = 7.7915e+19 cosl(7.7915e+19) = 7.7915e+19 The used compiler is Digital Mars Compiler v8.34.

1. Why use such a huge number as argument to cos? 2. My old 486 Processor handbook tells me that the argument range is abs(arg) < 2^63 2^63 = 9.2233e+18 I would assume this is also valid for the pentiom family? So your argument is already out of range for the numeric coprozessor. When the coprocessor exception is ignored (as is with DM) then the argument on FPU stack isn't changed and you get back the argument unmodified. - Heinz

Jun 05 2003

In article <bbnl8t$2g9$1 digitaldaemon.com>, Steve Hall says...The same code compiled with gcc v3.2.3 (mingw special 20030504-1) return reasonable results for functions cos and cosf(the recent version of MinGW gcc doesn't support properly displaying of long double type thru printf function).

gcc may return a "reasonable"-looking result for cos and cosf, but that result is totally meaningless. The FPU is rejecting your calculation for good reason. If you start with, float vf = 7.7915e19; and subtract a multiple of 2*pi (=m) such that 0 <= vf - (m*2*pi) < 2*pi, all you are really left with is just random rounding error garbage. If you try to calculate (vf) - (vf - 1); do you really get 1? Maybe with 80 bits of precision; otherwise I don't think so.The software that I develop depend on precision C99 floating-point arithmetic.

If you really need to know the cosine of such a large number, I would suggest you use an arbitrary precision math package. Or else consider writing your own cos function that just returns zero if the argument is too large. But I don't know if it is good to slow down everyone else just for people with weird requirements performing meaningless cosine calculations.Regards, Steve

Keith Fuller keithfx h.tmail.com

Jun 05 2003

But I don't know if it is good to slow down everyone else just for people

Thanks for your answer. You are right that cos of big values return "just random rounding error garbage". Any value between [-1; 1] is acceptable for cos function with such argument. But value outside of this region is mathematicaly unacceptable.If you really need to know the cosine of such a large number, I would

writing your own cos function that just returns zero if the argument is too large. In fact the compiler is mathematical based language translator. It must mathematical accurately to translate every piece of the code in precise machine readable form. If it fail, the compiled code will produce "just random rounding error garbage". What you think Walter about this (thanks for the correction of powl bug)? Do you accept to close your eyes in front of outstanding mathematical inaccuracy of your compiler? Do you accept to sell mathematical inaccurate compiler and prefer everyone of your clients to know that you haven't interest to correct such a poblems? Can I develop mathematical/logicaly stable software if the used compiler contain mathematical bugs? From your point of view all you need to do is just to ignore this post, because I'm the only one who want mathematical stable compiler. Thank you for your patience Walter, Steve Hall

Jun 05 2003

"Steve Hall" <sthall lorrexinc.com> wrote in message news:bboebu$ptk$1 digitaldaemon.com...What you think Walter about this (thanks for the correction of powl bug)? Do you accept to close your eyes in front of outstanding mathematical inaccuracy of your compiler? Do you accept to sell mathematical inaccurate compiler and prefer everyone of your clients to know that you haven't interest to correct such a poblems? Can I develop mathematical/logicaly stable software if the used compiler contain mathematical bugs? From your point of view all you need to do is just to ignore this post, because I'm the only one who want mathematical stable compiler. Thank you for your patience Walter, Steve Hall

The fundamental problem is DMC++ gets killed in benchmark comparisons unless cos() is recognized by the compiler and replaced with the single FCOS instruction. So, it is depending on the FPU to get it right. The FPU sets C2 if it is out of range, which you can test with the JP instruction. Alternatively, you can: #include <math.h> #undef cos which will disable the insertion of the fcos instruction, and will instead call the library cos() function. The library routine will test C2 and attempt argument reduction. It'll be significantly slower, though. To sum up, accurate and fast floating point are often at odds with each other.

Jun 05 2003

Thank you Walter. Would you tell me how I can use cosl and sinl library functions? Do you intend to implement tgmath.h or do you have plans to finish C99 support for the math functions? Steve "Walter" <walter digitalmars.com> wrote in message news:bbohg1$sh1$1 digitaldaemon.com..."Steve Hall" <sthall lorrexinc.com> wrote in message news:bboebu$ptk$1 digitaldaemon.com...What you think Walter about this (thanks for the correction of powl

Do you accept to close your eyes in front of outstanding mathematical inaccuracy of your compiler? Do you accept to sell mathematical

compiler and prefer everyone of your clients to know that you haven't interest to correct such a poblems? Can I develop mathematical/logicaly stable software if the used compiler contain mathematical bugs? From your point of view all you need to do is just to ignore this post, because I'm the only one who want mathematical stable compiler. Thank you for your patience Walter, Steve Hall

The fundamental problem is DMC++ gets killed in benchmark comparisons

cos() is recognized by the compiler and replaced with the single FCOS instruction. So, it is depending on the FPU to get it right. The FPU sets

if it is out of range, which you can test with the JP instruction. Alternatively, you can: #include <math.h> #undef cos which will disable the insertion of the fcos instruction, and will instead call the library cos() function. The library routine will test C2 and attempt argument reduction. It'll be significantly slower, though. To sum up, accurate and fast floating point are often at odds with each other.

Jun 06 2003

"Steve Hall" <sthall lorrexinc.com> wrote in message news:bbpms5$1uae$1 digitaldaemon.com...Would you tell me how I can use cosl and sinl library functions?

At the moment, you can just use the inline FCOS and FSIN versions.Do you intend to implement tgmath.h

That turns out to be a **** to implement.or do you have plans to finish C99 support for the math functions?

Yes.

Jun 06 2003

Can I develop mathematical/logicaly stable software if the used compiler contain mathematical bugs?

If this were a meaningful calculation, I would agree with you. If this were another programming language, I would probably agree with you. But this is C. There is no lower-level language available. People using C would rather have the maximum performance and smallest code instead of catering to goofy calculations.Thank you for your patience Walter, Steve Hall

Keith Fuller keithfx.h tmail.com

Jun 05 2003

Steve Hall schrieb...dmc v3.34 is a C99 conformed compiler with IEC 60559 support according to macros __STDC_VERSION__(199901) and __STDC_IEC_559__. Types float and double are respectively single and double precision types from IEC 60559(Binary floating-point arithmetic for microprocessor systems, second edition). The floating-point standard is independent of the hardware.

I don't have the C99 Standard here but would assume that the floating point specs rely on the IEEE spec, and that is the basic for FPU implementations.According to C99 the maximum representable number for type float is FLT_MAX = 3.40282347E+38, for type double is DBL_MAX = 1.7976931348623157E+308. Type double is subset of type long double, which is compiler dependent(for dmc v3.34 long double contain 80 bits).

So far DMC doesn't have a problem. It would be interesting to see what the C99 standard tells about argument ranges. Is it required for sin/cos to provide a reasonable (not correct, only range [-1,1]) result for all float/double arguments? What about tan, when the huge argument reduces to PI/2?The same code compiled with gcc v3.2.3 (mingw special 20030504-1) return reasonable results for functions cos and cosf(the recent version of MinGW gcc doesn't support properly displaying of long double type thru printf function).

I don't have access to mingw. Maybe the compiler evaluates the FPU flags to detect the fault and corrects ist? To Walter: is this where the difference between -f and -ff is? As I understand the -ff (fast floating point) option doesn't check for special cases (nan, overflows). - Heinz

Jun 06 2003

"Heinz Saathoff" <hsaat bre.ipnet.de> wrote in message news:MPG.194a68fa681300f79896be news.digitalmars.com...To Walter: is this where the difference between -f and -ff is? As I understand the -ff (fast floating point) option doesn't check for special cases (nan, overflows).

Right. It was put in there for benchmarking floating point against compilers which do not handle nans.

Jun 06 2003