home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource3 / 188_01 / trans.doc < prev    next >
Encoding:
Text File  |  1987-10-01  |  14.1 KB  |  275 lines

  1. .mt 0
  2. .mb 11
  3. .po 13
  4. /*
  5. HEADER:        ;
  6. TITLE:        C elementary transcendentals;
  7. VERSION:    1.0;
  8.  
  9. DESCRIPTION:       Source    code    for   all   standard    C                            
  10.  
  11.                transcendentals
  12.  
  13.         Employs  ldexp()  and  frexp()  functions;  if                
  14.  
  15.                suitable  versions  of these are  not  provided                
  16.  
  17.                by  a given compiler,  the versions provided in                
  18.  
  19.                source  code  will require  adaptation  to  the                
  20.  
  21.                double float formats of the compiler.
  22.  
  23. KEYWORDS:    Transcendentals, library;
  24. SYSTEM:        CP/M-80, V3.1;
  25. FILENAME:    TRANS.C;
  26. WARNINGS:      frexp()   and  ldexp()  are   implementation                
  27.  
  28.                dependent.   The  compiler  employed  does  not 
  29.  
  30.                support    minus   (-)   unary   operators   in                
  31.  
  32.                initializer  lists,  which are required by  the                
  33.  
  34.                code.
  35. AUTHORS:    Tim Prince;
  36. COMPILERS:    MIX C, v2.0.1;
  37. */
  38.               Transcendental Function Algorithms
  39.  
  40.      All  programming languages which are descended from  FOR-
  41.  
  42. TRAN  or  Algol include pre-defined transcendental  functions.     
  43.  
  44. Standard  textbooks on programming assume that the usual  math 
  45.  
  46. functions  are already available and not worth the  paper  re-
  47.  
  48. quired  to describe how they might be coded.   This is  unfor-
  49.  
  50. tunate,  as few computer systems provide reliable transcenden-
  51.  
  52. tals,  and  a basic understanding of their contents is helpful 
  53.  
  54. in their use.
  55.  
  56.      The  following  examples use polynomial  representations, 
  57.  
  58. because  they lead to compact code and give  average  accuracy 
  59.  
  60. within one bit of the best available.  Faster algorithms exist 
  61.  
  62. but require more code or data storage,  if written in the same 
  63.  
  64. language.   Commercial  versions of the functions are  usually 
  65.  
  66. written  in  assembler,  but the ideas are best  expressed  in 
  67.  
  68. higher  level languages.   Obscure tricks which  an  anonymous 
  69.  
  70. coder thought would improve speed are useless when the program 
  71.  
  72. fails  and the source code is not available.   These functions 
  73.  
  74. have been tested in nearly the same form on several  computers 
  75.  
  76. in both FORTRAN and C.
  77.  
  78.      The  author's hope is that these examples may set a mini-
  79.  
  80. mum standard for accuracy and speed of C library  transcenden-
  81.  
  82. tals.   Failing  this,  the  individual user should  have  the 
  83.  
  84. opportunity  to check whether any deficiencies of his code may 
  85.  
  86. be due to the library provided with the C compiler.  C's  soon 
  87.  
  88. to  be standardized support of bit fields and low level opera-
  89.  
  90. tions on doubles helps in the expression of these  algorithms.  
  91.  
  92. Since  C,  even in the future ANSI standard,  will not support 
  93.  
  94. pure single precision on computers which were not designed for 
  95.  
  96. mixed precision arithmetic, and the standard library functions 
  97.  
  98. are double, we show only the double precision, with the under-
  99.  
  100. standing that changes in the polynomials would adapt to  other 
  101.  
  102. precisions.   The file TRANSLIB.FOR shows FORTRAN versions  in 
  103.  
  104. single precision, which should serve as a demonstration of the 
  105.  
  106. changes required to vary precision and language.
  107.  
  108.      The  polynomial  coefficients were determined by  running 
  109.  
  110. one  of  Steve Ruzinsky's programs (1).   In  each  case,  the 
  111.  
  112. polynomial  is derived by truncating a standard Taylor  series 
  113.  
  114. or  rational  polynomial representation of  the  function  and 
  115.  
  116. using Steve's program to obtain more accuracy with fewer terms 
  117.  
  118. in the required range.   In some cases, 25 digit arithmetic is 
  119.  
  120. required  to fit a polynomial accurate to at least 16  digits.  
  121.  
  122. Tables of coefficients have been generated for polynomials  of 
  123.  
  124. any accuracy required up to 20 or more significant digits.
  125.  
  126.      Trigonometric  functions can be calculated with  adequate 
  127.  
  128. efficiency  using portable code,  even in archaic dialects  of 
  129.  
  130. FORTRAN,  Pascal,  and C.   When using polynomials, it appears 
  131.  
  132. best  to use the sin() function as the basic series and calcu-
  133.  
  134. late the others from it.   A polynomial for tan() requires  as 
  135.  
  136. many terms as sin() and cos() together.  Since cos() and tan() 
  137.  
  138. may be calculated from sin(),  only one shorter table of coef-
  139.  
  140. ficients  is  needed.   In effect,  tan() is calculated  by  a 
  141.  
  142. rational polynomial approximation.   Expressing these trigono-
  143.  
  144. metric relationships by #define teaches the preprocessor alge-
  145.  
  146. bra  which  an  optimizing compiler could  use  to  advantage.  
  147.  
  148. Check  that your compiler does not execute functions  multiple 
  149.  
  150. times  as a result of macro expansion.   Tan() could be calcu-
  151.  
  152. lated much faster with a big table as is built in to the 8087, 
  153.  
  154. but  most programs we have seen spend more time on  sin()  and 
  155.  
  156. cos().
  157.  
  158.      The  first  step in calculating sin() is  to  reduce  the 
  159.  
  160. range to |x| < pi/2 by subtracting the nearest multiple of pi.  
  161.  
  162. The  ODD() function shown assumes that (int) will extract  the 
  163.  
  164. low  order  bits  in case the argument  exceeds  maxint.   The 
  165.  
  166. multiplication  and subtraction should be done in long  double 
  167.  
  168. if it is available, but in any case the range reduction should 
  169.  
  170. not reduce accuracy when the original argument was already  in 
  171.  
  172. the  desired  range.   The  method most often used  saves  one 
  173.  
  174. divide (which may be changed to a multiply), at the cost of an 
  175.  
  176. unnecessary  roundoff.   Worse,  the result may  underflow  to 
  177.  
  178. zero.   Underflows  in the code shown occur only where a  zero 
  179.  
  180. does not affect the result.  With the precautions taken, extra 
  181.  
  182. precision   is  not  needed  anywhere  other  than  the  range 
  183.  
  184. reduction.
  185.  
  186.      Most  computer  systems include a  polynomial  evaluation 
  187.  
  188. function,  sometimes in microcode.  To save space we prefer to 
  189.  
  190. use such a function even though it may be slower than  writing 
  191.  
  192. out  the  polynomial in Horner form.   Such functions  operate 
  193.  
  194. like poly() shown here,  but (presumably) faster.   This modu-
  195.  
  196. larity  permits  special  hardware features to  be  used  more 
  197.  
  198. effectively,  although the time required to call another func-
  199.  
  200. tion may be excessive.  Loop unrolling (shown here) or odd and 
  201.  
  202. even  summing (see exp2()) are often  effective.   The  series 
  203.  
  204. used  for elementary functions have terms increasing in magni-
  205.  
  206. tude fast enough so that there is no need for extra  precision 
  207.  
  208. intermediate computation.
  209.  
  210.      The  arctan function uses several substitutions to reduce 
  211.  
  212. to a range of 0 < x < 1.   Although the Taylor series does not 
  213.  
  214. converge over this range,  the minimax polynomial does, but so 
  215.  
  216. many terms are needed that one further step of range reduction 
  217.  
  218. is preferred.   Code length may be traded for speed by using a 
  219.  
  220. table of tangents with a shorter series.   A rational  polyno-
  221.  
  222. mial(3)  is used by many run-time libraries,  at some cost  of 
  223.  
  224. accuracy.   A  series with one less term would still give over 
  225.  
  226. 15  digits  accuracy,  which is the maximum possible  on  some 
  227.  
  228. systems.
  229.  
  230.      Although  log base 2 is not usually included in the  list 
  231.  
  232. of  library functions,  it is almost always used as the  basic 
  233.  
  234. logarithm  for binary floating point,  because it is the  most 
  235.  
  236. efficient  base for exponentiation with a float  power.   Many 
  237.  
  238. implementations fail to obtain the logarithm of numbers  close 
  239.  
  240. to 1.   The following routine is the most widely tested of the 
  241.  
  242. examples  given here,  and has been found accurate on all  ma-
  243.  
  244. chines which subtract 1 accurately (some don't!).   In theory, 
  245.  
  246. precision  is  lost when the exponent is added in at the  end, 
  247.  
  248. but  this  is not serious in the most common cases of  numbers 
  249.  
  250. near 1.  Making the function long double would correct this.
  251.  
  252.      Log2  can  be written in portable code  if  the  standard 
  253.  
  254. functions  frexp() and ldexp() for extracting and changing the 
  255.  
  256. exponent field of a floating point number are  available.   On 
  257.  
  258. many  systems,  adequate speed will not be obtained unless the 
  259.  
  260. code  is  supplied in line.   This should  be  possible  using 
  261.  
  262. unions of structures,  but direct use of any applicable float-
  263.  
  264. ing point hardware instructions is preferable.   The algorithm 
  265.  
  266. requires separate calculation of the log of a number near 1 by 
  267.  
  268. a  series,  which is added to the scale (nearest integer power 
  269.  
  270. of 2) of the argument.
  271.  
  272.      Using  bit  fields  of structures as  an  alternative  to 
  273.  
  274. frexp() and ldexp() can be tricky,  but will allow a short int 
  275.  
  276. comparison to be substituted for the float comparison. The DEC 
  277.  
  278. system  is unusual in that floating point numbers  are  stored 
  279.  
  280. with  byte pairs reversed while integers are stored with  full 
  281.  
  282. reverse byte order.   This may not ruin the bit field code, if 
  283.  
  284. no  field crosses a 16-bit boundary.   The C function  frexp() 
  285.  
  286. conflicts  with  the  suggested IEEE standard  which  gives  a 
  287.  
  288. result just greater than 1 rather than just less than 1.
  289.  
  290.      A  common error in commercial implementations of log() is 
  291.  
  292. to bypass the conversion of a comparison into an increment  of 
  293.  
  294. the  scale  by subtracting and adding sqrt(.5) instead  of  1.  
  295.  
  296. This  has  never been seen to work well,  as sqrt(.5)  is  not 
  297.  
  298. represented exactly, and all significance of an argument which 
  299.  
  300. is  near  1  may be lost.   It isn't even as fast  unless  the 
  301.  
  302. machine  is one which is better suited to  extended  precision 
  303.  
  304. floating  point  than integer and logical  operations.   Since 
  305.  
  306. most systems have immediate constant representations of 1. and 
  307.  
  308. 2., the difference in code length is small.
  309.  
  310.      In  a  full IEEE standard(3)  system,  log()  would  need 
  311.  
  312. special  code to take care of log(0) and infinities and assure 
  313.  
  314. that accuracy is not lost on subnormals.   The code shown will 
  315.  
  316. give  a system-dependent result for log(0) which is such  that 
  317.  
  318. exp(log(0)) still returns 0.
  319.  
  320.      The  exponential  is the most difficult of  the  standard 
  321.  
  322. functions to calculate with full accuracy.   It could be writ-
  323.  
  324. ten  in  portable  code if there were a way to  ascertain  the 
  325.  
  326. exponent range at compile time;  IEEE P754 dictates a slightly 
  327.  
  328. different  range from older systems and requires special  case 
  329.  
  330. handling of out of range arguments.   If ldexp() takes care of 
  331.  
  332. over- and underflow, these checks may be omitted.  Many varia-
  333.  
  334. tions may be found,  but they have in common a range reduction 
  335.  
  336. based on splitting the argument into an integer and a fractio-
  337.  
  338. nal part, raising 2 to the power of each part, and (in effect) 
  339.  
  340. multiplying to get the result.
  341.  
  342.      Unlike the other functions,  which have no even terms  in 
  343.  
  344. their Taylor series,  exponentiation has a symmetry which  can 
  345.  
  346. be  exploited  only in a rational approximation.   Since  
  347. 2^(-x)=1/2^x,  the rational polynomial takes the form 
  348. P(x)/P(-x),  where the numerator and denominator are identical 
  349.  
  350. except for the sign of the odd power terms.   Only half of the 
  351.  
  352. terms  need to be evaluated.
  353.  
  354.      The  coefficients may be calculated by pencil  and  paper 
  355.  
  356. algebra,  converting  a continued fraction(4) into a  rational 
  357.  
  358. approximation(5).  Since the equations for the coefficients to 
  359.  
  360. fit the approximation to a set of points take the same form as 
  361.  
  362. for  a simple polynomial,  the minimax fitting program may  be 
  363.  
  364. used to reduce the number of terms required.  The precision of 
  365.  
  366. the  final result cannot be as great as the precision  of  the 
  367.  
  368. numerator  and denominator polynomials,  since changes of  the 
  369.  
  370. last  bit  in  numerator and denominator change  the  quotient 
  371.  
  372. irregularly but by an average of two bits.   Use of tables  to 
  373.  
  374. reduce  the  number  of  terms required would  speed  up  this 
  375.  
  376. function.
  377.  
  378.      Sinh()  should  have its own polynomial for |x|  <  1  to 
  379.  
  380. maintain accuracy and save the time which would be required to 
  381.  
  382. calculate  even power terms in exp().   Tanh() should  include 
  383.  
  384. code  to  give +-1 directly as a result for  large  arguments.  
  385.  
  386. The  solution  using a special exp-1 function is workable  but 
  387.  
  388. slower  and incompatible with the rational  approximation  for 
  389.  
  390. exp().
  391.  
  392.  
  393. .cp 5
  394.      Sqrt()  is  best coded as an arithmetic operation on  the 
  395.  
  396. same level as divide,  so that it can execute faster than  and 
  397.  
  398. as accurately as divide.   Many systems fail to do this and so 
  399.  
  400. a typical procedure is shown.  A minimax polynomial is used to 
  401.  
  402. get  an  approximation accurate to 2 or 3 digits,  and  Newton 
  403.  
  404. iterations  are performed until maximum accuracy  is  reached.  
  405.  
  406. It is faster to perform the maximum number of iterations which 
  407.  
  408. may  be  required rather than to go until the  last  iteration 
  409.  
  410. makes no significant change.  If the arithmetic operations are 
  411.  
  412. properly  rounded,  the result will be within one bit of  full 
  413.  
  414. machine accuracy.
  415.  
  416.      The  code required to implement the algorithms appears to 
  417.  
  418. be  consistent  with published standards for the  C  language.  
  419.  
  420. Some compiler designers consider that the Reference  Manual(6) 
  421.  
  422. definition  is satisfied by accepting but ignoring minus signs 
  423.  
  424. in  initializers.   The code was tested by patching  the  con-
  425.  
  426. stants  in  the  compiler output code.   This problem  may  be 
  427.  
  428. circumvented by expanding the polynomials in line,  which is a 
  429.  
  430. favorable  trade of length for speed on some  machines.   This 
  431.  
  432. sort  of  problem  does not occur even in  TRANS   DOCee!Xt code.
  433.  
  434.      Tests show that FORTRAN and C versions of these functions 
  435.  
  436. may  be improved in speed or code length by assembler  coding.  
  437.  
  438. Except possibly for exp(),  the accuracy of these functions is 
  439.  
  440. as  good  as the best and frequently better  than  the  store-
  441.  
  442. bought  versions.   
  443. .pa
  444.  
  445. References
  446.  
  447. 1.Ruzinsky,  Steven  A.   "A Simple Minimax  Algorithm,"  Dr. 
  448.  
  449. Dobb's Journal #93 pp. 84-91, July 1984
  450.  
  451. 2.Moshier,  Stephen L.   "Computer Approximations,"  Byte pp. 
  452.  
  453. 161-178, Apr. 1986
  454.  
  455. 3.Cody,  W.  J., Karpinski, R."A Proposed Radix- and 
  456.  
  457. Word-length-independent  Standard for Floating-point  Arithme-
  458.  
  459. tic," IEEE Micro pp. 86-100, August 1984
  460.  
  461. 4.Abramowitz,  M.,  Stegun,  I.   "Handbook  of  Mathematical 
  462.  
  463. Functions," Dover 1968
  464.  
  465. 5.Press,  W.H. et al.  "Numerical Recipes," Cambridge Univer-
  466.  
  467. sity Press 1986
  468.  
  469. 6.Ritchie, Dennis M.  "The C Programming Language - Reference 
  470.  
  471. Manual,"  in UNIX Programmer's Manual,  v.2, Holt Rinehart amd 
  472.  
  473. Winston, 1983
  474.