On Sat, Feb 4, 2012 at 11:20 AM, James Courtier-Dutton
<james.dut...@gmail.com> wrote:
> On 4 February 2012 00:06, Vincent Lefevre <vincent+...@vinc17.org> wrote:
>> On 2012-02-03 17:40:05 +0100, Dominique Dhumieres wrote:
>>> While I fail to see how the "correct value" of
>>> cos(4.47460300787e+182)+sin(4.47460300787e+182)
>>> can be defined in the 'double' world, cos^2(x)+sin^2(x)=1 and
>>> sin(2*x)=2*sin(x)*cos(x) seems to be verified (at least for this value)
>>> even if the actual values of sin and cos depends on the optimisation level.
>>
>> Actually this depends on the context. It is even worse: the value
>> of sin(some_value) depends on the context. Consider the following
>> program:
>>
>> #include <stdio.h>
>> #include <math.h>
>>
>> int main (void)
>> {
>>  double x, c, s;
>>  volatile double v;
>>
>>  x = 1.0e22;
>>  s = sin (x);
>>  printf ("sin(%.17g) = %.17g\n", x, s);
>>
>>  v = x;
>>  x = v;
>>  c = cos (x);
>>  s = sin (x);
>>  printf ("sin(%.17g) = %.17g\n", x, s);
>>
>>  return c == 0;
>> }
>>
>> With "gcc -O" on x86_64 with glibc 2.13, one gets:
>>
>> sin(1e+22) = -0.85220084976718879
>> sin(1e+22) = 0.46261304076460175
>>
>> In the program, you can replace 1.0e22 by 4.47460300787e+182 or
>> whatever large constant you want. You'll get the same problem.
>>
>
> Ok, so the value -0.85... seems to be the correct value.
>
> If you convert all the doubles into long doubles.
> You get:
> gcc -O0 -c -o sincos.o sincos.c
> gcc sincos.o -lm
> sinl(10000000000000000000000.00000000000000000) = 0.46261304076460176
> sinl(10000000000000000000000.00000000000000000) = 0.46261304076460176
> gcc sincos.o -lm
> gcc -O2 -c -o sincos.o sincos.c
> sin(10000000000000000000000.00000000000000000) = -0.85220084976718880
> sin(10000000000000000000000.00000000000000000) = 0.46261304076460176
>
> So, I agree with Vincent Lefevre, my earlier statements are wrong.
> There is definitely something going wrong either in gcc or libm.

Note that you are comparing a constant folded sin() result against sincos()
(or sin() and cos()).  Use

#include <stdio.h>
#include <math.h>

int main (void)
{
  double x, c, s;
  volatile double v;

  x = 1.0e22;
  v = x;
  x = v;
  s = sin (x);
  printf ("sin(%.17g) = %.17g\n", x, s);

  v = x;
  x = v;
  c = cos (x);
  s = sin (x);
  printf ("sin(%.17g) = %.17g\n", x, s);

  return c == 0;
}

to compare libm sin against sincos.  Works for me, btw.  Note that I remember
that at some point sincos() was just fsincos even on x86_64 (ugh).

Richard.

Reply via email to