epow.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /* epow.c */
  2. /* power function: z = x**y */
  3. /* by Stephen L. Moshier. */
  4. #include "ehead.h"
  5. #define MAXPOS ((long) (((unsigned long) ~(0L)) >> 1))
  6. #define MAXNEG (-MAXPOS)
  7. /* #define MAXNEG (-MAXPOS - 1L) */
  8. extern int rndprc;
  9. void epowi();
  10. static void epowr();
  11. /* Run-time determination of largest integers */
  12. int powinited = 0;
  13. unsigned short maxposint[NE], maxnegint[NE];
  14. void initpow()
  15. {
  16. long li;
  17. li = MAXPOS;
  18. ltoe( &li, maxposint );
  19. li = MAXNEG;
  20. ltoe( &li, maxnegint );
  21. powinited = 1;
  22. }
  23. void epow( x, y, z )
  24. unsigned short *x, *y, *z;
  25. {
  26. unsigned short w[NE];
  27. int rndsav;
  28. long li;
  29. if( powinited == 0 )
  30. initpow();
  31. /* Check for integer power. */
  32. efloor( y, w );
  33. if( (ecmp(y,w) == 0)
  34. && (ecmp(maxposint,w) >= 0)
  35. && (ecmp(w,maxnegint) >= 0) )
  36. {
  37. eifrac( y, &li, w );
  38. epowi( x, y, z );
  39. return;
  40. }
  41. epowr( x, y, z );
  42. }
  43. /* y is integer valued. */
  44. void epowi( x, y, z )
  45. unsigned short x[], y[], z[];
  46. {
  47. unsigned short w[NE];
  48. long li, lx;
  49. unsigned long lu;
  50. int rndsav;
  51. unsigned short signx;
  52. /* unsigned short signy; */
  53. if( powinited == 0 )
  54. initpow();
  55. rndsav = rndprc;
  56. if( (ecmp(y,maxposint) > 0) || (ecmp(maxnegint,y) > 0) )
  57. {
  58. epowr( x, y, z );
  59. return;
  60. }
  61. eifrac( y, &li, w );
  62. if( li < 0 )
  63. lx = -li;
  64. else
  65. lx = li;
  66. /*
  67. if( (x[NE-1] & (unsigned short )0x7fff) == 0 )
  68. */
  69. if( ecmp( x, ezero) == 0 )
  70. {
  71. if( li == 0 )
  72. {
  73. emov( eone, z );
  74. return;
  75. }
  76. else if( li < 0 )
  77. {
  78. einfin( z );
  79. return;
  80. }
  81. else
  82. {
  83. eclear( z );
  84. return;
  85. }
  86. }
  87. if( li == 0L )
  88. {
  89. emov( eone, z );
  90. return;
  91. }
  92. emov( x, w );
  93. signx = w[NE-1] & (unsigned short )0x8000;
  94. w[NE-1] &= (unsigned short )0x7fff;
  95. /* Overflow detection */
  96. /*
  97. lx = li * (w[NE-1] - 0x3fff);
  98. if( lx > 16385L )
  99. {
  100. einfin( z );
  101. mtherr( "epowi", OVERFLOW );
  102. goto done;
  103. }
  104. if( lx < -16450L )
  105. {
  106. eclear( z );
  107. return;
  108. }
  109. */
  110. rndprc = NBITS;
  111. if( li < 0 )
  112. {
  113. lu = (unsigned int )( -li );
  114. /* signy = 0xffff;*/
  115. ediv( w, eone, w );
  116. }
  117. else
  118. {
  119. lu = (unsigned int )li;
  120. /* signy = 0;*/
  121. }
  122. /* First bit of the power */
  123. if( lu & 1 )
  124. {
  125. emov( w, z );
  126. }
  127. else
  128. {
  129. emov( eone, z );
  130. signx = 0;
  131. }
  132. lu >>= 1;
  133. while( lu != 0L )
  134. {
  135. emul( w, w, w ); /* arg to the 2-to-the-kth power */
  136. if( lu & 1L ) /* if that bit is set, then include in product */
  137. emul( w, z, z );
  138. lu >>= 1;
  139. }
  140. done:
  141. if( signx )
  142. eneg( z ); /* odd power of negative number */
  143. /*
  144. if( signy )
  145. {
  146. if( ecmp( z, ezero ) != 0 )
  147. {
  148. ediv( z, eone, z );
  149. }
  150. else
  151. {
  152. einfin( z );
  153. printf( "epowi OVERFLOW\n" );
  154. }
  155. }
  156. */
  157. rndprc = rndsav;
  158. emul( eone, z, z );
  159. }
  160. /* z = exp( y * log(x) ) */
  161. static void epowr( x, y, z )
  162. unsigned short *x, *y, *z;
  163. {
  164. unsigned short w[NE];
  165. int rndsav;
  166. rndsav = rndprc;
  167. rndprc = NBITS;
  168. elog( x, w );
  169. emul( y, w, w );
  170. eexp( w, z );
  171. rndprc = rndsav;
  172. emul( eone, z, z );
  173. }