home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / lang / c / 13206 < prev    next >
Encoding:
Text File  |  1992-09-03  |  3.8 KB  |  117 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!elroy.jpl.nasa.gov!nntp-server.caltech.edu!news
  3. From: mcs@goblin.caltech.edu (Martin Shepherd)
  4. Subject: Re: C vs. FORTRAN
  5. Message-ID: <1992Sep4.005337.24425@cco.caltech.edu>
  6. Sender: news@cco.caltech.edu
  7. Nntp-Posting-Host: goblin.caltech.edu
  8. Organization: California Institute of Technology
  9. References: <DWISEMAN.92Sep3164036@spsd630a.erim.org>
  10. Date: Fri, 4 Sep 1992 00:53:37 GMT
  11. Lines: 104
  12.  
  13. ----
  14. In article 57339 of comp.lang.c, dwiseman@erim.org writes:
  15. > I have a (two) simple programs, one in fortran, and one in C. I have compiled
  16. > them both optimized, and timed the results.  The fortran version takes .1 s
  17. > to run, and the C version takes 12.5s to run.  I know (hope) that there is a
  18. > simple remedy for this.  The project that I am working on has to do many 
  19. > sines and cosines, and I'd prefer to keep the entire program in C, and not
  20. > mix the languages.  What can I do to improve the speed of the C version?
  21. >----------------------------------------------------------------------------
  22. >#include <stdio.h>
  23. >#include <math.h>
  24. >
  25. >main (argc,argv)
  26. >     int argc;
  27. >     char **argv;
  28. >{
  29. >  double angle,delta,the_sin,the_cos;
  30. >  int i;
  31. >  
  32. >  angle = 0.0;
  33. >  delta = 0.01;
  34. >  
  35. >  for (i=0; i<1000000; i++)
  36. >  {
  37. >    the_sin = sin(angle);
  38. >    the_cos = cos(angle);
  39. >    angle += delta; 
  40. >  }
  41.  
  42. [Fortran example deleted]
  43.  
  44. In the particular program cited, you can speed up the code considerably
  45. by using trigonometric recurrence to remove the sin() and cos() function
  46. calls from inside the loop.
  47.  
  48. Using the trig identities:
  49.  
  50.  cos(a+b) = cos(a)*cos(b) - sin(a)*sin(b)
  51.  sin(a+b) = sin(a)*cos(b) + cos(a)*sin(a)
  52.  
  53. you can increment sin(angle) to sin(angle+delta) and cos(angle) to
  54. cos(angle+delta) just by knowing the sin()'s and cos()'s of 'angle' and
  55. 'delta'. Thus you only have to call the trig functions four times,
  56. just before the loop starts. I have coded this below.
  57.  
  58. ---cut here-------------------------------------------------------------
  59. #include <math.h>
  60. #include <stdio.h>
  61.  
  62. #define START 0.0   /* The start 'angle' */
  63. #define DELTA 0.01  /* The increment in 'angle' per iteration */
  64.  
  65. main (argc,argv)
  66.      int argc;
  67.      char **argv;
  68. {
  69.   double the_sin; /* The sin() of the last value of 'angle' */
  70.   double the_cos; /* The cos() of the last value of 'angle' */
  71.   double sin_inc; /* sin(delta) used to increment sin() and cos() */
  72.   double cos_inc; /* cos(delta) used to increment sin() and cos() */
  73.   double las_sin; /* Temporary intermediary in recurrence calculations */
  74.   int i;
  75. /*
  76.  * Determine cos() and sin() of the start angle.
  77.  */
  78.   the_sin = sin(START);
  79.   the_cos = cos(START);
  80. /*
  81.  * Precompute the sin() and cos() of the angle increment.
  82.  */
  83.   sin_inc = sin(DELTA);
  84.   cos_inc = cos(DELTA);
  85.  
  86.   for (i=0; i<1000000; i++)
  87.   {
  88. /*
  89.  * Use the current value of the_sin and the_cos here.
  90.  */
  91.  
  92. /* Then compute the incremented sin() and cos() values here using
  93.  * recurrence relations.
  94.  */
  95.     las_sin = the_sin;
  96.     the_sin = the_sin*cos_inc + the_cos*sin_inc;
  97.     the_cos = the_cos*cos_inc - las_sin*sin_inc;
  98.   };
  99.   return 0;
  100. }
  101.  
  102. ---cut here----------------------------------------------------------------
  103.  
  104. Given the number of times your loop repeats, precision errors will start to
  105. creep in. If your loop really needs to have the above repeat
  106. count and the precision errors prove to be a problem then you could always
  107. add an outer loop to reinitialise the_sin and the_cos, using the library
  108. sin() and cos() functions, every given number of iterations.
  109. However you probably won't need to do this - I just inserted an printf()
  110. in the program to check the value of 'the_sin' against the machine's
  111. sin() function. After 10000 iterations the two values were still identical
  112. within the 6 decimal places that printf() produced. The program as written
  113. above takes 1 second of cpu time on a SUN IPX (using cc -O ).
  114.  
  115. mcs@phobos.caltech.edu  (Martin Shepherd)
  116.  
  117.