pow.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:9k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* pow.c - math routines */
  2. /* Copyright 1992-1993 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01e,05feb93,jdi  doc changes based on kdl review.
  7. 01d,02dec92,jdi  doc tweaks.
  8. 01c,28oct92,jdi  documentation cleanup.
  9. 01b,20sep92,smb  documentation additions
  10. 01a,08jul92,smb  documentation.
  11. */
  12. /*
  13. DESCRIPTION
  14. * Copyright (c) 1985 Regents of the University of California.
  15. * All rights reserved.
  16. *
  17. * Redistribution and use in source and binary forms are permitted
  18. * provided that the above copyright notice and this paragraph are
  19. * duplicated in all such forms and that any documentation,
  20. * advertising materials, and other materials related to such
  21. * distribution and use acknowledge that the software was developed
  22. * by the University of California, Berkeley.  The name of the
  23. * University may not be used to endorse or promote products derived
  24. * from this software without specific prior written permission.
  25. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  26. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  27. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  28. *
  29. * All recipients should regard themselves as participants in an ongoing
  30. * research project and hence should feel obligated to report their
  31. * experiences (good or bad) with these elementary function codes, using
  32. * the sendbug(8) program, to the authors.
  33. *
  34. SEE ALSO: American National Standard X3.159-1989
  35. NOMANUAL
  36. */
  37. #include "vxWorks.h"
  38. #include "math.h"
  39. #include "private/mathP.h"
  40. #if defined(vax)||defined(tahoe) /* VAX D format */
  41. #include <errno.h>
  42. extern double infnan();
  43. #ifdef vax
  44. #define _0x(A,B) 0x/**/A/**/B
  45. #else /* vax */
  46. #define _0x(A,B) 0x/**/B/**/A
  47. #endif /* vax */
  48. /* static double */
  49. /* ln2hi  =  6.9314718055829871446E-1    , Hex  2^  0   *  .B17217F7D00000 */
  50. /* ln2lo  =  1.6465949582897081279E-12   , Hex  2^-39   *  .E7BCD5E4F1D9CC */
  51. /* invln2 =  1.4426950408889634148E0     , Hex  2^  1   *  .B8AA3B295C17F1 */
  52. /* sqrt2  =  1.4142135623730950622E0     ; Hex  2^  1   *  .B504F333F9DE65 */
  53. static long     ln2hix[] = { _0x(7217,4031), _0x(0000,f7d0)};
  54. static long     ln2lox[] = { _0x(bcd5,2ce7), _0x(d9cc,e4f1)};
  55. static long    invln2x[] = { _0x(aa3b,40b8), _0x(17f1,295c)};
  56. static long     sqrt2x[] = { _0x(04f3,40b5), _0x(de65,33f9)};
  57. #define    ln2hi    (*(double*)ln2hix)
  58. #define    ln2lo    (*(double*)ln2lox)
  59. #define   invln2    (*(double*)invln2x)
  60. #define    sqrt2    (*(double*)sqrt2x)
  61. #else /* defined(vax)||defined(tahoe) */
  62. static double
  63. ln2hi  =  6.9314718036912381649E-1    , /*Hex  2^ -1   *  1.62E42FEE00000 */
  64. ln2lo  =  1.9082149292705877000E-10   , /*Hex  2^-33   *  1.A39EF35793C76 */
  65. invln2 =  1.4426950408889633870E0     , /*Hex  2^  0   *  1.71547652B82FE */
  66. sqrt2  =  1.4142135623730951455E0     ; /*Hex  2^  0   *  1.6A09E667F3BCD */
  67. #endif /* defined(vax)||defined(tahoe) */
  68. static double zero=0.0, half=1.0/2.0, one=1.0, two=2.0, negone= -1.0;
  69. /*******************************************************************************
  70. *
  71. * pow - compute the value of a number raised to a specified power (ANSI)
  72. *
  73. * This routine returns <x> to the power of <y> in
  74. * double precision (IEEE double, 53 bits).
  75. *
  76. * A domain error occurs if <x> is negative and <y> is not an integral value.
  77. * A domain error occurs if the result cannot be represented when <x> is zero
  78. * and <y> is less than or equal to zero.  A range error may occur.
  79. *
  80. * INTERNAL:
  81. * Method:
  82. * (1) Compute and return log(x) in three pieces:
  83. *
  84. *         log(x) = n*ln2 + hi + lo
  85. *
  86. *     where <n> is an integer.
  87. *
  88. * (2) Perform y*log(x) by simulating multi-precision arithmetic and
  89. *     return the answer in three pieces:
  90. *
  91. *         y*log(x) = m*ln2 + hi + lo
  92. *
  93. *     where <m> is an integer.
  94. *
  95. * (3) Return:
  96. *
  97. *         x**y = exp(y*log(x)) = 2^m * ( exp(hi+lo) )
  98. *
  99. * INCLUDE FILES: math.h
  100. *
  101. * RETURNS: The double-precision value of <x> to the power of <y>.
  102. *
  103. * Special cases:
  104. * .TS
  105. * tab(|);
  106. * l0 c0 l.
  107. *     (anything) ** 0                       | is | 1
  108. *     (anything) ** 1                       | is | itself
  109. *     (anything) ** NaN                     | is | NaN
  110. *     NaN ** (anything except 0)            | is | NaN
  111. *     +-(anything > 1) ** +INF              | is | +INF
  112. *     +-(anything > 1) ** -INF              | is | +0
  113. *     +-(anything < 1) ** +INF              | is | +0
  114. *     +-(anything < 1) ** -INF              | is | +INF
  115. *     +-1 ** +-INF                          | is | NaN, signal INVALID
  116. *     +0 ** +(anything non-0, NaN)          | is | +0
  117. *     -0 ** +(anything non-0, NaN, odd int) | is | +0
  118. *     +0 ** -(anything non-0, NaN)          | is | +INF, signal DIV-BY-ZERO
  119. *     -0 ** -(anything non-0, NaN, odd int) | is | +INF with signal
  120. *     -0 ** (odd integer)                   | =  | -(+0 ** (odd integer))
  121. *     +INF ** +(anything except 0, NaN)     | is | +INF
  122. *     +INF ** -(anything except 0, NaN)     | is | +0
  123. *     -INF ** (odd integer)                 | =  | -(+INF ** (odd integer))
  124. *     -INF ** (even integer)                | =  | (+INF ** (even integer))
  125. *     -INF ** -(any non-integer, NaN)       | is | NaN with signal
  126. *     -(x=anything) ** (k=integer)          | is | (-1)**k * (x ** k)
  127. *     -(anything except 0) ** (non-integer) | is | NaN with signal
  128. * .TE
  129. *
  130. * SEE ALSO: mathALib
  131. *
  132. * INTERNAL:
  133. * Coded in C by K.C. Ng, 1/8/85;
  134. * Revised by K.C. Ng on 7/10/85.
  135. */
  136. double pow
  137.     (
  138.     double x, /* operand  */
  139.     double y /* exponent */
  140.     )
  141.     {
  142. double drem(),pow_p(),copysign(),t;
  143. int finite();
  144. if     (y==zero)      return(one);
  145. else if(y==one
  146. #if !defined(vax)&&!defined(tahoe)
  147. ||x!=x
  148. #endif /* !defined(vax)&&!defined(tahoe) */
  149. ) return( x );      /* if x is NaN or y=1 */
  150. #if !defined(vax)&&!defined(tahoe)
  151. else if(y!=y)         return( y );      /* if y is NaN */
  152. #endif /* !defined(vax)&&!defined(tahoe) */
  153. else if(!finite(y))                     /* if y is INF */
  154.      if((t=copysign(x,one))==one) return(zero/zero);
  155.      else if(t>one) return((y>zero)?y:zero);
  156.      else return((y<zero)?-y:zero);
  157. else if(y==two)       return(x*x);
  158. else if(y==negone)    return(one/x);
  159.     /* sign(x) = 1 */
  160. else if(copysign(one,x)==one) return(pow_p(x,y));
  161.     /* sign(x)= -1 */
  162. /* if y is an even integer */
  163. else if ( (t=drem(y,two)) == zero) return( pow_p(-x,y) );
  164. /* if y is an odd integer */
  165. else if (copysign(t,one) == one) return( -pow_p(-x,y) );
  166. /* Henceforth y is not an integer */
  167. else if(x==zero) /* x is -0 */
  168.     return((y>zero)?-x:one/(-x));
  169. else { /* return NaN */
  170. #if defined(vax)||defined(tahoe)
  171.     return (infnan(EDOM)); /* NaN */
  172. #else /* defined(vax)||defined(tahoe) */
  173.     return(zero/zero);
  174. #endif /* defined(vax)||defined(tahoe) */
  175. }
  176.     }
  177. /****************************************************************************
  178. *
  179. * pow_p -
  180. *
  181. * pow_p(x,y) return x**y for x with sign=1 and finite y *
  182. *
  183. * RETURN:
  184. * NOMANUAL
  185. */
  186. double pow_p(x,y)
  187. double x,y;
  188. {
  189.         double logb(),scalb(),copysign(),log__L(),exp__E();
  190.         double c,s,t,z,tx,ty;
  191. #ifdef tahoe
  192. double tahoe_tmp;
  193. #endif /* tahoe */
  194.         float sx,sy;
  195. long k=0;
  196.         int n,m;
  197. if(x==zero||!finite(x)) {           /* if x is +INF or +0 */
  198. #if defined(vax)||defined(tahoe)
  199.      return((y>zero)?x:infnan(ERANGE)); /* if y<zero, return +INF */
  200. #else /* defined(vax)||defined(tahoe) */
  201.      return((y>zero)?x:one/x);
  202. #endif /* defined(vax)||defined(tahoe) */
  203. }
  204. if(x==1.0) return(x); /* if x=1.0, return 1 since y is finite */
  205.     /* reduce x to z in [sqrt(1/2)-1, sqrt(2)-1] */
  206.         z=scalb(x,-(n=logb(x)));
  207. #if !defined(vax)&&!defined(tahoe) /* IEEE double; subnormal number */
  208.         if(n <= -1022) {n += (m=logb(z)); z=scalb(z,-m);}
  209. #endif /* !defined(vax)&&!defined(tahoe) */
  210.         if(z >= sqrt2 ) {n += 1; z *= half;}  z -= one ;
  211.     /* log(x) = nlog2+log(1+z) ~ nlog2 + t + tx */
  212. s=z/(two+z); c=z*z*half; tx=s*(c+log__L(s*s));
  213. t= z-(c-tx); tx += (z-t)-c;
  214.    /* if y*log(x) is neither too big nor too small */
  215. if((s=logb(y)+logb(n+t)) < 12.0)
  216.     if(s>-60.0) {
  217. /* compute y*log(x) ~ mlog2 + t + c */
  218.          s=y*(n+invln2*t);
  219.                 m=s+copysign(half,s);   /* m := nint(y*log(x)) */
  220. k=y;
  221. if((double)k==y) { /* if y is an integer */
  222.     k = m-k*n;
  223.     sx=t; tx+=(t-sx); }
  224. else { /* if y is not an integer */
  225.     k =m;
  226.       tx+=n*ln2lo;
  227.     sx=(c=n*ln2hi)+t; tx+=(c-sx)+t; }
  228.    /* end of checking whether k==y */
  229.                 sy=y; ty=y-sy;          /* y ~ sy + ty */
  230. #ifdef tahoe
  231. s = (tahoe_tmp = sx)*sy-k*ln2hi;
  232. #else /* tahoe */
  233. s=(double)sx*sy-k*ln2hi;        /* (sy+ty)*(sx+tx)-kln2 */
  234. #endif /* tahoe */
  235. z=(tx*ty-k*ln2lo);
  236. tx=tx*sy; ty=sx*ty;
  237. t=ty+z; t+=tx; t+=s;
  238. c= -((((t-s)-tx)-ty)-z);
  239.     /* return exp(y*log(x)) */
  240. t += exp__E(t,c); return(scalb(one+t,m));
  241.      }
  242. /* end of if log(y*log(x)) > -60.0 */
  243.     else
  244. /* exp(+- tiny) = 1 with inexact flag */
  245. {ln2hi+ln2lo; return(one);}
  246.     else if(copysign(one,y)*(n+invln2*t) <zero)
  247. /* exp(-(big#)) underflows to zero */
  248.          return(scalb(one,-5000));
  249.     else
  250.         /* exp(+(big#)) overflows to INF */
  251.      return(scalb(one, 5000));
  252. }