EMATH.C
资源名称:ertos.rar [点击查看]
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:11k
源码类别:
操作系统开发
开发平台:
DOS
- /*
- * emath.c
- *
- * Copyright (c) 1987, 1999 Erick Engelke
- */
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- /*------------------------------------------------------------------------*/
- #include <emath.h>
- /*------------------------------------------------------------------------*/
- EM EM_INT( EM x )
- {
- int sign = 1;
- if ( x < EM_ZERO ) {
- sign = -1;
- x = -x;
- }
- return( sign * (x & EM_INTEGERS) );
- }
- /*------------------------------------------------------------------------*/
- EM EM_ROUND( EM x )
- {
- x += (x > 0) ? EM_POINT_5 : - EM_POINT_5 ;
- return( x & EM_INTEGERS );
- }
- /*------------------------------------------------------------------------*/
- EM EM_SGN( EM x )
- {
- if ( x < 0 ) return( EM_MINUS_ONE );
- if ( x > 0 ) return( EM_ONE );
- return( EM_ZERO );
- }
- /*------------------------------------------------------------------------*/
- EM EM_ABS( EM x )
- {
- if ( x & EM_SIGN_BIT ) x *= -1 ;
- return( x );
- }
- /*------------------------------------------------------------------------*/
- EM EM_MUL( EM a, EM b )
- {
- EM ah, al, bh, bl, r;
- long sign = 1;
- if ( a < EM_ZERO ) {
- sign = -1;
- a = -a;
- }
- if ( b < EM_ZERO ) {
- sign *= -1;
- b = -b;
- }
- ah = a >> 16;
- al = a & 65535;
- bh = b >> 16;
- bl = b & 65535;
- r = (( ah * bh ) << 17)
- + ( ( ( al * bh ) + ( ah * bl ) ) << 1 )
- + ((( al>>1 ) * (bl>>1)) >> 13 );
- return( r * sign );
- }
- /*------------------------------------------------------------------------*/
- EM EM_DIV( EM num , EM denom )
- {
- int i;
- EM r;
- int sign = 1;
- if ( num < 0 ) {
- num = -num;
- sign = -1;
- }
- if (denom <0) {
- denom = -denom;
- sign *= -1;
- }
- /* prescale to preserve accuracy */
- i = EM_BDIGITS;
- for ( i = EM_BDIGITS ; i ; i-- ) {
- if ( ( num & EM_HIGH_BIT ) == 0 ) num *= 2; /* preserve sign */
- else if ((denom & 1)==0) denom /= 2;
- else break;
- }
- if ( denom == 0 ) return( EM_MAXINT );
- r = num / denom;
- /* finish scaling */
- if ( i > 0 ) r <<= i;
- return( r * sign );
- }
- /*------------------------------------------------------------------------*/
- /* Conversion Routines */
- /*------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------*/
- EM EM_ASSIGN( long numerator, long denominator)
- {
- EM scale = EM_ONE;
- while ( !( scale & 1 ) && !( denominator & 1 )) {
- scale >>= 1;
- denominator >>= 1;
- }
- return( numerator * scale / denominator);
- }
- /*------------------------------------------------------------------------*/
- long emtol( EM em, long divisor )
- {
- long basedivisor = EM_ONE;
- /* try to minimize lost bits */
- while ( ((basedivisor & 1 ) == 0 ) && ((divisor &1 )==0 ) ) {
- basedivisor >>= 1;
- divisor >>= 1;
- }
- return( (em * divisor) / basedivisor );
- }
- /*------------------------------------------------------------------------*/
- EM strtoem( char *s )
- {
- EM x;
- long j,k;
- int i;
- char *p;
- int sign = 1;
- /* skip leading spaces */
- while ( isspace( *s )) s++;
- /* fix sign, and more intermediate spaces */
- if ( *s == '-' ) {
- sign = -1;
- s++;
- while ( isspace( *s )) s++;
- }
- x = 0;
- x = atol( s ) * EM_DENOMINATOR;
- if ( ( p = strchr( s,'.' )) != NULL ) {
- ++p;
- for ( j = 1, i = 0 ; isdigit( p[i] ) ; ++i, j*=10 );
- x += (atol( p ) * EM_DENOMINATOR + (j>>1)) / j;
- }
- if ( sign < 0 ) x = -x;
- return( x );
- }
- /*------------------------------------------------------------------------*/
- char *emtostr( EM x, char *s )
- {
- int sign = ( x < 0 ) ? -1 : 1;
- char *p = s;
- char ch;
- if ( sign == -1 ) {
- *p++ = '-';
- x = -x;
- }
- sprintf( p, "%li.%0*li", x / EM_DENOMINATOR , EM_DEC_DIGITS,
- (( x % EM_DENOMINATOR) * EM_DECIMAL_DENOMINATOR +
- (EM_DECIMAL_DENOMINATOR>>1) )/ EM_DENOMINATOR );
- /* kill trailing zeros */
- p = strrchr( p, 0 );
- while ( --p != s ) {
- ch = *p;
- /* don't need a trailing '.' */
- if ( ch == '.' ) {
- *p = 0;
- break;
- }
- if ( ch == '0' ) *p = 0;
- else break;
- }
- return( s );
- }
- /*------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------*/
- /* Mathematic Routines */
- /*------------------------------------------------------------------------*/
- EM EM_SQR( EM in )
- {
- EM newx, guess;
- long scale;
- int iteration;
- if ( in < EM_ZERO ) return( EM_MAXNEGINT ); /* invalid input */
- /* reduce range */
- for ( scale = 1 ; in > EM_ONE ; scale *= 10 )
- in /= 100;
- /* polynomial guess */
- guess = EM_ADD( EM_ASSIGN( 1154,10000),
- EM_MUL( EM_ASSIGN( 11544,10000), in ));
- /* refine */
- for ( iteration = 5 ; iteration ; --iteration ) {
- guess = EM_MUL( EM_POINT_5, EM_ADD( guess, EM_DIV( in , guess )));
- }
- return( guess * scale );
- }
- /*------------------------------------------------------------------------*/
- EM EM_LOG10( EM in )
- {
- long sign = 1;
- EM scale, x3, x4, y;
- EM s, z, r;
- if ( in <= EM_ZERO ) return( EM_MAXNEGINT ); /* invalid input */
- if ( in < EM_ONE ) {
- sign = -1;
- in = EM_DIV( EM_ONE, in );
- }
- /* scale to useful */
- scale = EM_ZERO;
- while ( in >= EM_ONE ) {
- in /= 10 ;
- scale = EM_ADD( scale, EM_ONE );
- }
- in = EM_MUL( EM_ASSIGN( 31623, 10000 ), in );
- in = EM_DIV( EM_SUB( in, EM_ONE ), EM_ADD( in, EM_ONE ));
- y = EM_MUL( in, in );
- x3 = EM_ADD(
- EM_ASSIGN( 31878, 10000 ),
- EM_MUL( y,
- EM_ADD(
- EM_ASSIGN( -26558,10000),
- EM_MUL( y, EM_ASSIGN(2669, 10000))
- )
- ) );
- x4 = EM_ADD( EM_ASSIGN( 36701, 10000),
- EM_MUL( y,
- EM_ADD( EM_ASSIGN( -42810,10000), y) ));
- y = EM_SUB(
- EM_ADD( scale,
- EM_DIV(
- EM_MUL(in,x3),
- x4)),
- EM_POINT_5) *sign;
- return( y );
- }
- /*------------------------------------------------------------------------*/
- EM EM_POWER10( EM x )
- {
- int inv = 0;
- EM n, y, x3, x4;
- if ( x < EM_ZERO ) {
- inv = 1;
- x = -x;
- }
- n = EM_INT( x );
- x = EM_SUB( EM_SUB( x, n ), EM_POINT_5 );
- y = EM_MUL( x, x );
- x3 = EM_ADD( EM_ASSIGN( 695570,10000),
- EM_MUL( y, EM_ASSIGN( 87518, 10000)));
- x4 = EM_ADD( EM_ASSIGN( 604164, 10000),
- EM_MUL( y,
- EM_ADD( EM_ASSIGN( 342951, 10000), y )));
- // y = 2 * x3 * x / ( x4 - x * x3 );
- y = EM_DIV( 2 * EM_MUL( x3, x ),
- EM_SUB( x4,
- EM_MUL( x, x3 )));
- y = EM_MUL( EM_ASSIGN(31623,10000) ,
- EM_ADD( EM_ONE, y ));
- while ( n > 0 ) {
- y *= 10;
- n = EM_SUB( n, EM_ONE );
- }
- if ( inv ) y = EM_DIV( 1, y );
- return( y );
- }
- /*------------------------------------------------------------------------*/
- EM EM_LN( EM x )
- {
- #define EM_LOG10_E 14231
- return( EM_DIV( EM_LOG10( x ) , EM_LOG10_E ));
- }
- /*------------------------------------------------------------------------*/
- EM EM_EXP( EM x )
- {
- return( EM_POWER10( EM_MUL( x , EM_LOG10_E )));
- }
- /*------------------------------------------------------------------------*/
- EM EM_POWER( EM x, EM y )
- {
- return( EM_POWER10( EM_MUL( y, EM_LOG10( x ))));
- }
- /*------------------------------------------------------------------------*/
- EM EM_COS( EM rad )
- {
- EM y;
- int test;
- int sign = 1;
- if ( rad < 0 )
- rad = -rad;
- /* get into scale */
- rad = EM_SUB( rad,
- EM_MUL( EM_INT( EM_DIV( rad, EM_TWO_PI )),
- EM_TWO_PI ));
- /* stage of rad in range 0..2pi */
- test = emtol( EM_DIV( rad, EM_90_DEG_RAD ), 1 );
- switch (test) {
- case 0 : break;
- case 1 : rad = EM_ABS( EM_SUB( EM_PI, rad )) ; sign = -1 ; break;
- case 2 : rad = EM_ABS( EM_SUB( EM_PI, rad )) ; sign = -1 ; break;
- case 3 : rad = EM_ABS( EM_SUB( rad, EM_TWO_PI)); break;
- }
- rad = EM_MUL( rad, rad );
- y = EM_ADD( EM_ONE,
- EM_MUL( rad,
- EM_ADD( EM_ASSIGN( -5, 10 ),
- EM_MUL( rad,
- EM_ADD( EM_ASSIGN( 417, 10000),
- EM_MUL( rad,
- EM_ASSIGN( -14, 10000)
- )
- )
- )
- )
- )
- );
- return( y * sign );
- }
- /*------------------------------------------------------------------------*/
- EM EM_SIN( EM rad )
- {
- return( EM_COS( rad - EM_PI/2 ));
- }
- /*------------------------------------------------------------------------*/
- EM EM_TAN( EM rad )
- {
- EM x, y;
- x = EM_SIN( rad );
- y = EM_COS( rad );
- return( EM_DIV( x, y ));
- }
- /*------------------------------------------------------------------------*/
- EM EM_ATAN( EM x )
- {
- long sign = 1;
- int flag = 0;
- EM x3, x4, y;
- if ( x < EM_ZERO ) {
- sign = -1;
- x = -x;
- }
- if ( x > EM_ONE ) {
- x = EM_DIV( EM_ONE, x );
- flag = 1;
- }
- y = EM_MUL( x , x );
- x3 = EM_ADD( EM_ASSIGN( 8079, 100 ),
- EM_MUL( y,
- EM_ADD( EM_ASSIGN( 725814, 10000 ),
- EM_MUL( y,
- EM_ASSIGN( 111177, 10000 )))));
- x4 = EM_ADD( EM_ASSIGN( 8079, 100 ),
- EM_MUL( y,
- EM_ADD( EM_ASSIGN( 995113, 10000 ),
- EM_MUL( y,
- EM_ADD( EM_ASSIGN( 281329, 10000),
- y )))));
- y = EM_DIV( EM_MUL( x, x3) , x4 );
- if ( flag )
- y = EM_SUB( EM_ASSIGN(15708,10000), y );
- return( y * sign );
- }
- /*------------------------------------------------------------------------*/
- EM EM_ASIN( EM x )
- {
- EM c;
- c = EM_DIV( x, EM_SQR( EM_SUB( EM_ONE, EM_MUL( x, x ))));
- return( EM_ATAN( c ));
- }
- /*------------------------------------------------------------------------*/
- EM EM_ACOS( EM x )
- {
- EM c;
- c = EM_DIV( EM_SQR( EM_SUB( EM_ONE,
- EM_MUL( x, x ))),
- x );
- return( EM_ATAN( c ));
- }
- /*------------------------------------------------------------------------*/
- EM EM_DEG( EM rad )
- {
- return( EM_MUL( rad , EM_ASSIGN( 572958, 10000 )));
- }
- /*------------------------------------------------------------------------*/
- EM EM_RAD( EM deg )
- {
- return( EM_DIV( deg , EM_ASSIGN( 572958, 10000 )));
- }