Archives
D Programming
D
D.gnu
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
|
c++ - cos bug
↑ ↓ ← → "Steve Hall" <sthall lorrexinc.com> writes:
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
↑ ↓ ← → Heinz Saathoff <hsaat bre.ipnet.de> writes:
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
↑ ↓ ← → "Steve Hall" <sthall lorrexinc.com> writes:
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
↑ ↓ ← → Keith Fuller <Keith_member pathlink.com> writes:
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
↑ ↓ ← → "Steve Hall" <sthall lorrexinc.com> writes:
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
↑ ↓ ← → "Walter" <walter digitalmars.com> writes:
"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.
↑ ↓ ← → "Steve Hall" <sthall lorrexinc.com> writes:
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.
↑ ↓ ← → "Walter" <walter digitalmars.com> writes:
"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.
↑ ↓ ← → Keith Fuller <Keith_member pathlink.com> writes:
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
↑ ↓ ← → Heinz Saathoff <hsaat bre.ipnet.de> writes:
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
↑ ↓ ← → "Walter" <walter digitalmars.com> writes:
"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.
|
|