EMATH.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:11k
源码类别:

操作系统开发

开发平台:

DOS

  1. /*
  2.  * emath.c
  3.  *
  4.  * Copyright (c) 1987, 1999 Erick Engelke
  5.  */
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <ctype.h>
  10. /*------------------------------------------------------------------------*/
  11. #include <emath.h>
  12. /*------------------------------------------------------------------------*/
  13. EM EM_INT( EM x )
  14. {
  15.     int sign = 1;
  16.     if ( x < EM_ZERO ) {
  17.         sign = -1;
  18.         x = -x;
  19.     }
  20.     return( sign * (x & EM_INTEGERS) );
  21. }
  22. /*------------------------------------------------------------------------*/
  23. EM EM_ROUND( EM x )
  24. {
  25.     x += (x > 0) ? EM_POINT_5 : - EM_POINT_5 ;
  26.     return( x & EM_INTEGERS );
  27. }
  28. /*------------------------------------------------------------------------*/
  29. EM EM_SGN( EM x )
  30. {
  31.     if ( x < 0 ) return( EM_MINUS_ONE );
  32.     if ( x > 0 ) return( EM_ONE );
  33.     return( EM_ZERO );
  34. }
  35. /*------------------------------------------------------------------------*/
  36. EM EM_ABS( EM x )
  37. {
  38.     if ( x & EM_SIGN_BIT ) x *= -1 ;
  39.     return( x );
  40. }
  41. /*------------------------------------------------------------------------*/
  42. EM EM_MUL( EM a, EM b )
  43. {
  44.     EM ah, al, bh, bl, r;
  45.     long sign = 1;
  46.     if ( a < EM_ZERO ) {
  47.         sign = -1;
  48.         a = -a;
  49.     }
  50.     if ( b < EM_ZERO ) {
  51.         sign *= -1;
  52.         b = -b;
  53.     }
  54.     ah = a >> 16;
  55.     al = a & 65535;
  56.     bh = b >> 16;
  57.     bl = b & 65535;
  58.     r = (( ah * bh )  << 17)
  59.         + (  (  ( al * bh ) + (  ah * bl ) ) << 1 )
  60.       + ((( al>>1 ) * (bl>>1)) >> 13 );
  61.     return( r * sign );
  62. }
  63. /*------------------------------------------------------------------------*/
  64. EM EM_DIV( EM num , EM denom )
  65. {
  66.     int i;
  67.     EM r;
  68.     int sign = 1;
  69.     if ( num < 0 ) {
  70.         num = -num;
  71.         sign = -1;
  72.     }
  73.     if (denom <0) {
  74.         denom = -denom;
  75.         sign *= -1;
  76.     }
  77.     /* prescale to preserve accuracy */
  78.     i = EM_BDIGITS;
  79.     for ( i = EM_BDIGITS ; i ; i-- ) {
  80.         if ( ( num & EM_HIGH_BIT ) == 0 ) num *= 2; /* preserve sign */
  81.         else if ((denom & 1)==0) denom /= 2;
  82.         else break;
  83.     }
  84.     if ( denom == 0 ) return( EM_MAXINT );
  85.     r = num / denom;
  86.     /* finish scaling */
  87.     if ( i > 0 ) r <<= i;
  88.     return( r * sign );
  89. }
  90. /*------------------------------------------------------------------------*/
  91. /* Conversion Routines                                                    */
  92. /*------------------------------------------------------------------------*/
  93. /*------------------------------------------------------------------------*/
  94. EM EM_ASSIGN( long numerator, long denominator)
  95. {
  96.     EM scale = EM_ONE;
  97.     while ( !( scale & 1 ) && !( denominator &  1 )) {
  98.         scale >>= 1;
  99.         denominator >>= 1;
  100.     }
  101.     return( numerator * scale / denominator);
  102. }
  103. /*------------------------------------------------------------------------*/
  104. long emtol( EM em, long divisor )
  105. {
  106.     long basedivisor = EM_ONE;
  107.     /* try to minimize lost bits */
  108.     while ( ((basedivisor & 1 ) == 0 ) && ((divisor &1 )==0 ) ) {
  109.         basedivisor >>= 1;
  110.         divisor >>= 1;
  111.     }
  112.     return( (em * divisor) / basedivisor );
  113. }
  114. /*------------------------------------------------------------------------*/
  115. EM strtoem( char *s )
  116. {
  117.     EM x;
  118.     long j,k;
  119.     int i;
  120.     char *p;
  121.     int sign = 1;
  122.     /* skip leading spaces */
  123.     while ( isspace( *s )) s++;
  124.     /* fix sign, and more intermediate spaces */
  125.     if ( *s == '-' ) {
  126.         sign = -1;
  127.         s++;
  128.         while ( isspace( *s )) s++;
  129.     }
  130.     x = 0;
  131.     x = atol( s ) * EM_DENOMINATOR;
  132.     if ( ( p = strchr( s,'.' )) != NULL ) {
  133.         ++p;
  134.         for ( j = 1, i = 0 ; isdigit( p[i] ) ; ++i, j*=10 );
  135.         x += (atol( p ) * EM_DENOMINATOR + (j>>1)) / j;
  136.     }
  137.     if ( sign < 0 ) x = -x;
  138.     return( x );
  139. }
  140. /*------------------------------------------------------------------------*/
  141. char *emtostr( EM x, char *s )
  142. {
  143.     int sign = ( x < 0 ) ? -1 : 1;
  144.     char *p = s;
  145.     char ch;
  146.     if ( sign == -1  ) {
  147.         *p++ = '-';
  148.         x = -x;
  149.     }
  150.     sprintf( p, "%li.%0*li", x / EM_DENOMINATOR , EM_DEC_DIGITS,
  151.         (( x % EM_DENOMINATOR) * EM_DECIMAL_DENOMINATOR +
  152.             (EM_DECIMAL_DENOMINATOR>>1) )/ EM_DENOMINATOR );
  153.     /* kill trailing zeros */
  154.     p = strrchr( p, 0 );
  155.     while ( --p != s ) {
  156.         ch = *p;
  157.         /* don't need a trailing '.' */
  158.         if ( ch == '.' ) {
  159.             *p = 0;
  160.             break;
  161.         }
  162.         if ( ch == '0' ) *p = 0;
  163.         else break;
  164.     }
  165.     return( s );
  166. }
  167. /*------------------------------------------------------------------------*/
  168. /*------------------------------------------------------------------------*/
  169. /* Mathematic Routines                                                    */
  170. /*------------------------------------------------------------------------*/
  171. EM EM_SQR( EM in )
  172. {
  173.     EM newx, guess;
  174.     long scale;
  175.     int iteration;
  176.     if ( in <  EM_ZERO ) return( EM_MAXNEGINT );    /* invalid input */
  177.     /* reduce range */
  178.     for ( scale = 1 ; in > EM_ONE ; scale *= 10 )
  179.         in /= 100;
  180.     /* polynomial guess */
  181.     guess = EM_ADD( EM_ASSIGN(  1154,10000),
  182.             EM_MUL( EM_ASSIGN( 11544,10000), in ));
  183.     /* refine */
  184.     for ( iteration = 5 ; iteration ; --iteration ) {
  185.         guess = EM_MUL( EM_POINT_5, EM_ADD(  guess, EM_DIV( in , guess )));
  186.     }
  187.     return( guess * scale );
  188. }
  189. /*------------------------------------------------------------------------*/
  190. EM EM_LOG10( EM in )
  191. {
  192.     long sign = 1;
  193.     EM scale, x3, x4, y;
  194.     EM s, z, r;
  195.     if ( in <= EM_ZERO ) return( EM_MAXNEGINT );    /* invalid input */
  196.     if ( in < EM_ONE ) {
  197.         sign = -1;
  198.         in = EM_DIV( EM_ONE, in );
  199.     }
  200.     /* scale to useful */
  201.     scale = EM_ZERO;
  202.     while ( in >= EM_ONE ) {
  203.         in /= 10 ;
  204.         scale = EM_ADD( scale, EM_ONE );
  205.     }
  206.     in = EM_MUL( EM_ASSIGN( 31623, 10000 ), in );
  207.     in = EM_DIV( EM_SUB( in, EM_ONE ), EM_ADD( in, EM_ONE ));
  208.     y = EM_MUL( in, in );
  209.     x3 = EM_ADD(
  210.             EM_ASSIGN( 31878, 10000 ),
  211.             EM_MUL( y,
  212.                     EM_ADD(
  213.                         EM_ASSIGN( -26558,10000),
  214.                         EM_MUL( y, EM_ASSIGN(2669, 10000))
  215.                     )
  216.                  ) );
  217.     x4 = EM_ADD( EM_ASSIGN( 36701, 10000),
  218.                  EM_MUL( y,
  219.                     EM_ADD( EM_ASSIGN( -42810,10000), y) ));
  220.     y = EM_SUB(
  221.             EM_ADD( scale,
  222.                     EM_DIV(
  223.                         EM_MUL(in,x3),
  224.                         x4)),
  225.             EM_POINT_5) *sign;
  226.     return( y );
  227. }
  228. /*------------------------------------------------------------------------*/
  229. EM EM_POWER10( EM x )
  230. {
  231.     int inv = 0;
  232.     EM n, y, x3, x4;
  233.     if ( x < EM_ZERO ) {
  234.         inv = 1;
  235.         x = -x;
  236.     }
  237.     n = EM_INT( x );
  238.     x = EM_SUB( EM_SUB( x, n ), EM_POINT_5 );
  239.     y = EM_MUL( x, x );
  240.     x3 = EM_ADD( EM_ASSIGN( 695570,10000),
  241.                  EM_MUL( y, EM_ASSIGN( 87518, 10000)));
  242.     x4 = EM_ADD( EM_ASSIGN( 604164, 10000),
  243.                  EM_MUL( y,
  244.                     EM_ADD( EM_ASSIGN( 342951, 10000), y )));
  245. //    y = 2 * x3 * x  / ( x4 - x * x3 );
  246.     y = EM_DIV( 2 * EM_MUL( x3, x ),
  247.                 EM_SUB( x4,
  248.                         EM_MUL( x, x3 )));
  249.     y = EM_MUL( EM_ASSIGN(31623,10000) ,
  250.                 EM_ADD( EM_ONE, y ));
  251.     while ( n > 0 ) {
  252.         y *= 10;
  253.         n = EM_SUB( n, EM_ONE );
  254.     }
  255.     if ( inv ) y = EM_DIV( 1, y );
  256.     return( y );
  257. }
  258. /*------------------------------------------------------------------------*/
  259. EM EM_LN( EM x )
  260. {
  261. #define EM_LOG10_E 14231
  262.     return( EM_DIV( EM_LOG10( x ) , EM_LOG10_E ));
  263. }
  264. /*------------------------------------------------------------------------*/
  265. EM EM_EXP( EM x )
  266. {
  267.     return( EM_POWER10( EM_MUL( x , EM_LOG10_E )));
  268. }
  269. /*------------------------------------------------------------------------*/
  270. EM EM_POWER( EM x, EM y )
  271. {
  272.     return( EM_POWER10( EM_MUL( y, EM_LOG10( x ))));
  273. }
  274. /*------------------------------------------------------------------------*/
  275. EM EM_COS( EM rad )
  276. {
  277.     EM y;
  278.     int test;
  279.     int sign = 1;
  280.     if ( rad < 0 )
  281.         rad = -rad;
  282.     /* get into scale */
  283.     rad = EM_SUB( rad,
  284.                   EM_MUL( EM_INT( EM_DIV( rad, EM_TWO_PI )),
  285.                           EM_TWO_PI ));
  286.     /* stage of rad in range 0..2pi */
  287.     test = emtol( EM_DIV( rad, EM_90_DEG_RAD ), 1 );
  288.     switch (test) {
  289.         case 0 : break;
  290.         case 1 : rad = EM_ABS( EM_SUB( EM_PI, rad )) ; sign = -1 ; break;
  291.         case 2 : rad = EM_ABS( EM_SUB( EM_PI, rad )) ; sign = -1 ; break;
  292.         case 3 : rad = EM_ABS( EM_SUB( rad, EM_TWO_PI)); break;
  293.     }
  294.     rad = EM_MUL( rad, rad );
  295.     y = EM_ADD( EM_ONE,
  296.                 EM_MUL( rad,
  297.                         EM_ADD( EM_ASSIGN( -5, 10 ),
  298.                                 EM_MUL( rad,
  299.                                         EM_ADD( EM_ASSIGN( 417, 10000),
  300.                                                 EM_MUL( rad,
  301.                                                         EM_ASSIGN( -14, 10000)
  302.                                                        )
  303.                                         )
  304.                                  )
  305.                          )
  306.                  )
  307.                 );
  308.     return( y * sign );
  309. }
  310. /*------------------------------------------------------------------------*/
  311. EM EM_SIN( EM rad )
  312. {
  313.     return( EM_COS( rad - EM_PI/2 ));
  314. }
  315. /*------------------------------------------------------------------------*/
  316. EM EM_TAN( EM rad )
  317. {
  318.     EM x, y;
  319.     x = EM_SIN( rad );
  320.     y = EM_COS( rad );
  321.     return( EM_DIV( x, y ));
  322. }
  323. /*------------------------------------------------------------------------*/
  324. EM EM_ATAN( EM x )
  325. {
  326.     long sign = 1;
  327.     int flag = 0;
  328.     EM x3, x4, y;
  329.     if ( x < EM_ZERO ) {
  330.         sign = -1;
  331.         x = -x;
  332.     }
  333.     if ( x > EM_ONE ) {
  334.         x = EM_DIV( EM_ONE, x );
  335.         flag = 1;
  336.     }
  337.     y = EM_MUL( x , x );
  338.     x3 = EM_ADD( EM_ASSIGN( 8079, 100 ),
  339.                  EM_MUL( y,
  340.                          EM_ADD( EM_ASSIGN( 725814, 10000 ),
  341.                                  EM_MUL( y,
  342.                                          EM_ASSIGN( 111177, 10000 )))));
  343.     x4 = EM_ADD( EM_ASSIGN( 8079, 100 ),
  344.                  EM_MUL( y,
  345.                          EM_ADD( EM_ASSIGN( 995113, 10000 ),
  346.                                  EM_MUL( y,
  347.                                          EM_ADD( EM_ASSIGN( 281329, 10000),
  348.                                                  y )))));
  349.     y = EM_DIV( EM_MUL( x, x3) , x4 );
  350.     if ( flag )
  351.         y = EM_SUB( EM_ASSIGN(15708,10000), y );
  352.     return( y * sign );
  353. }
  354. /*------------------------------------------------------------------------*/
  355. EM EM_ASIN( EM x )
  356. {
  357.     EM c;
  358.     c = EM_DIV( x, EM_SQR( EM_SUB( EM_ONE, EM_MUL( x, x ))));
  359.     return( EM_ATAN( c ));
  360. }
  361. /*------------------------------------------------------------------------*/
  362. EM EM_ACOS( EM x )
  363. {
  364.     EM c;
  365.     c = EM_DIV( EM_SQR( EM_SUB( EM_ONE,
  366.                                 EM_MUL( x, x ))),
  367.                 x );
  368.     return( EM_ATAN( c ));
  369. }
  370. /*------------------------------------------------------------------------*/
  371. EM EM_DEG( EM rad )
  372. {
  373.     return( EM_MUL( rad , EM_ASSIGN( 572958, 10000 )));
  374. }
  375. /*------------------------------------------------------------------------*/
  376. EM EM_RAD( EM deg )
  377. {
  378.     return( EM_DIV( deg , EM_ASSIGN( 572958, 10000 )));
  379. }
  380.