/***************************************************************
__MPU_MATH.C
This file contains source code of functions for
REAL MATH operations.
PART OF : MPU - library .
USAGE : Internal only .
NOTE : NONE .
Copyright (C) 2000 - 2024 by Andrew V.Kosteltsev.
All Rights Reserved.
***************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h> /* errno(3) */
#include <string.h> /* strcpy(3) */
#include <strings.h> /* bzero(3) */
#include <stdlib.h>
#include <libmpu.h>
#include <mpu-context.h>
#include <mpu-emutype.h>
#include <mpu-integer.h>
#include <mpu-real.h>
#include <mpu-floatp.h>
#include <mpu-ioreal.h>
#include <mpu-m-const.h>
#include <mpu-math.h>
#include <mpu-char.h>
#include <mpu-symbols.h>
#include <mpu-math-errno.h>
#include <mpu-mtherr.h>
#include <st-cos.h>
#include <st-sin.h>
#include <st-cosh.h>
#include <st-sinh.h>
#include <st-atan2.h>
#include <st-exp.h>
#include <st-log.h>
#include <st-ln.h>
#include <st-service.h>
#include <st-logtable.h>
static void ei_copysign( EMUSHORT *eiy, EMUSHORT *eix, EMUSHORT *eis, int nb )
/***************************************************************
Description : ei_copysign() Работает с internal
e-type data struct.
Concepts : Copy VALUE from EIX into EIY and
SIGN from EIS into EIY.
NOTE :
Use Global Variable:
Use Functions : internal_np( nb ); | mpu-real.c
ei_copy( eiy, eix, nb ); | mpu-real.c
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE VALUE;
EMUSHORT *eis; - указатель на
internal e-type
data struct.
SOURCE SIGN;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT sign;
int ps = 0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ps = internal_np( nb ) - 1;
#endif
sign = eis[ps];
ei_copy( eiy, eix, nb );
eiy[ps] = sign;
} /* End of ei_copysign() */
static void ei_drem( EMUSHORT *eiy, EMUSHORT *eix, EMUSHORT *eid, int nb )
/***************************************************************
Description : ei_drem() Работает с
internal e-type data struct.
Concepts : Reduce EIX into [-EID/2, EID/2] and
return result in EIY.
NOTE :
Use Global Variable:
Use Functions : internal_np( nb ); | mpu-real.c
_gen_two( eic, nb ); | mpu-real.c
ei_copy( eiy, eix, nb ); | mpu-real.c
ei_remain( r,q,y,x,nb ); | mpu-real.c
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE VALUE;
EMUSHORT *eid; - указатель на
internal e-type
data struct.
SOURCE +
2*DIAPASON;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*b = NULL,
*d = NULL,
*two = NULL;
EMUSHORT sign;
int ps = 0;
int np;
np = internal_np( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ps = np - 1;
#endif
/*** Allocate memory for x, b, d, two . *********************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !b )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
d = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !d )
{
/* fatal error */
/* FREE x *****************/
/* FREE b *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE b *****************/
/* FREE d *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_two( two, nb );
sign = eix[ps];
ei_copy( x, eix, nb );
x[ps] = (EMUSHORT)0; /* ei_abs( x, nb ); */
ei_copy( d, eid, nb );
d[ps] = (EMUSHORT)0; /* ei_abs( d, nb ); */
ei_div( b, d, two, nb );
if( ei_cmp( x, d, nb ) > 0 )
ei_remain( x, (EMUSHORT *)0, x, d, nb );
if( ei_cmp( x, b, nb ) >= 0 )
{
ei_sub( x, x, d, nb );
}
x[ps] ^= sign;
ei_copy( eiy, x, nb ); /* return value */
/* FREE x *****************/
/* FREE b *****************/
/* FREE d *****************/
/* FREE two ***************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_drem() */
#if BITS_PER_EMUSHORT == 16
static EMUSHORT bzmask[] =
{
0xffff,
0xfffe,
0xfffc,
0xfff8,
0xfff0,
0xffe0,
0xffc0,
0xff80,
0xff00,
0xfe00,
0xfc00,
0xf800,
0xf000,
0xe000,
0xc000,
0x8000,
0x0000,
};
#else /* not (BITS_PER_EMUSHORT == 16) */
#if BITS_PER_EMUSHORT == 32
static EMUSHORT bzmask[] =
{
0xffffffff,
0xfffffffe,
0xfffffffc,
0xfffffff8,
0xfffffff0,
0xffffffe0,
0xffffffc0,
0xffffff80,
0xffffff00,
0xfffffe00,
0xfffffc00,
0xfffff800,
0xfffff000,
0xffffe000,
0xffffc000,
0xffff8000,
0xffff0000,
0xfffe0000,
0xfffc0000,
0xfff80000,
0xfff00000,
0xffe00000,
0xffc00000,
0xff800000,
0xff000000,
0xfe000000,
0xfc000000,
0xf8000000,
0xf0000000,
0xe0000000,
0xc0000000,
0x80000000,
0x00000000,
};
#else /* not (BITS_PER_EMUSHORT == 32) */
#if BITS_PER_EMUSHORT == 64
static EMUSHORT bzmask[] =
{
0xffffffffffffffff,
0xfffffffffffffffe,
0xfffffffffffffffc,
0xfffffffffffffff8,
0xfffffffffffffff0,
0xffffffffffffffe0,
0xffffffffffffffc0,
0xffffffffffffff80,
0xffffffffffffff00,
0xfffffffffffffe00,
0xfffffffffffffc00,
0xfffffffffffff800,
0xfffffffffffff000,
0xffffffffffffe000,
0xffffffffffffc000,
0xffffffffffff8000,
0xffffffffffff0000,
0xfffffffffffe0000,
0xfffffffffffc0000,
0xfffffffffff80000,
0xfffffffffff00000,
0xffffffffffe00000,
0xffffffffffc00000,
0xffffffffff800000,
0xffffffffff000000,
0xfffffffffe000000,
0xfffffffffc000000,
0xfffffffff8000000,
0xfffffffff0000000,
0xffffffffe0000000,
0xffffffffc0000000,
0xffffffff80000000,
0xffffffff00000000,
0xfffffffe00000000,
0xfffffffc00000000,
0xfffffff800000000,
0xfffffff000000000,
0xffffffe000000000,
0xffffffc000000000,
0xffffff8000000000,
0xffffff0000000000,
0xfffffe0000000000,
0xfffffc0000000000,
0xfffff80000000000,
0xfffff00000000000,
0xffffe00000000000,
0xffffc00000000000,
0xffff800000000000,
0xffff000000000000,
0xfffe000000000000,
0xfffc000000000000,
0xfff8000000000000,
0xfff0000000000000,
0xffe0000000000000,
0xffc0000000000000,
0xff80000000000000,
0xff00000000000000,
0xfe00000000000000,
0xfc00000000000000,
0xf800000000000000,
0xf000000000000000,
0xe000000000000000,
0xc000000000000000,
0x8000000000000000,
0x0000000000000000,
};
#else /* not (BITS_PER_EMUSHORT == 64) */
#error mpu-math.c: Cannot use that size of EMUSHORT type
#endif /* BITS_PER_EMUSHORT == 64 */
#endif /* BITS_PER_EMUSHORT == 32 */
#endif /* BITS_PER_EMUSHORT == 16 */
void ei_trunc( EMUSHORT *eix, unsigned int bz, int nb )
/***************************************************************
Description : ei_trunc() Работает с
internal e-type data struct.
Concepts : ZERO to BZ last bits of Significand of EIX.
NOTE :
Use Global Variable:
Use Functions : internal_ne( nb ); | mpu-real.c
internal_ns( nb ); | mpu-real.c
ei_issignull( eix, nb ); | mpu-real.c
Parameters : EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE, TARGET;
unsigned int bz; - количество
обнуляемых младших
бит мантиссы в
external e-type
data struct.
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *p;
int ne, ns;
unsigned int k = (unsigned)NSBITS(nb);
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"trunc" );
return;
}
if( bz > k )
{
/* error: Invalid number of TRUNC bits(BZ) */
/* количество обнуляемых бит больше чем количество бит мантиссы */
__real_truncate_error();
return;
}
/* Если на входе знаковый ноль. */
if( ei_issignull( eix, nb ) )
{
return;
}
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &eix[ne+ns+2]; /* lgw */
*p-- = (EMUSHORT)0; /* p -> low part of Significand */
#else
p = &eix[0]; /* lgw */
*p++ = (EMUSHORT)0; /* p -> low part of Significand */
#endif
while( bz >= BITS_PER_EMUSHORT )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*p-- = (EMUSHORT)0;
#else
*p++ = (EMUSHORT)0;
#endif
bz -= BITS_PER_EMUSHORT;
}
/* Clear the remaining bits. */
*p &= bzmask[bz];
} /* End of ei_TRUNC() */
static void __ei_TRUNC( EMUSHORT *eix, int nb )
{
unsigned int z = 0;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
z = 44;
break;
case NBR_256:
z = 95;
break;
case NBR_512:
z = 184;
break;
case NBR_1024:
z = 388;
break;
case NBR_2048:
z = 770;
break;
case NBR_4096:
z = 1585;
break;
case NBR_8192:
z = 3964;
break;
case NBR_16384:
z = 6424;
break;
case NBR_32768:
z = 12842;
break;
case NBR_65536:
z = 15882;
break;
case NBR_131072:
z = 51758;
break;
default:
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"TRUNC" );
break;
} /* End of switch( nb ) */
ei_trunc( eix, z, nb );
} /* End of __ei_TRUNC() */
void ei_sin( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_sin() Работает с
internal e-type data struct.
Concepts : Return in EIY = SIN( EIX ).
NOTE : See: ei_sin__S() & ei_cos__C().
Use Global Variable:
Use Functions : ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *a = NULL,
*c = NULL,
*z = NULL,
*x = NULL,
*half = NULL,
*one = NULL,
*small = NULL;
EMUSHORT *pi, *pi2, *pi_2, *pi_4, *pi3_4;
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"sin" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* SIN(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"sin", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* SIN(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"sin", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* SIN(Infinity) must by NaN */
if( ei_isinfin( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"sin", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL Infinity - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
pi = _get_m_pi_ptr ( nb );
pi2 = _get_m_2pi_ptr ( nb );
pi_2 = _get_m_pi_2_ptr ( nb );
pi_4 = _get_m_pi_4_ptr ( nb );
pi3_4 = _get_m_3pi_4_ptr( nb );
/*** Allocate memory for a, c, z, half, one, small . ******/
a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !a )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
c = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !c )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE half **************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
small = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !small )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_half( half, nb );
_gen_one ( one, nb );
/*********************************************
small: 1.0 + small^2 == 1.0;
big : big = 1/(small^2);
*********************************************/
ei_sqrt( small, _get_epsilon_ptr( nb ), nb );
ei_drem( x, eix, pi2, nb ); /* reduse EIX into [-PI, PI]. */
ei_copysign( a, x, one, nb );
if( ei_cmp( a, pi_4, nb ) >= 0 )
{
if( ei_cmp( a, pi3_4, nb ) >= 0 ) /* ... in [3PI/4, PI]. */
{
ei_sub( a, pi, a, nb );
ei_copysign( x, a, x, nb );
}
else /* ... in [PI/4, 3PI/4]. */
{
/* return: sign(x)*COS(PI/2-|x|).*/
ei_sub( a, pi_2, a, nb );
ei_mul( z, a, a, nb );
ei_cos__C( c, z, nb );
ei_mul( z, z, half, nb );
ei_sub( a, z, c, nb );
ei_sub( a, one, a, nb );
ei_copysign( eiy, a, x, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
}
/* return: SIN(x) */
if( ei_cmp( a, small, nb ) < 0 )
{
ei_copy( eiy, x, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_mul( z, x, x, nb );
ei_sin__S( z, z, nb );
ei_mul( z, z, x, nb );
ei_add( eiy, x, z, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_sin() */
void ei_cos( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_cos() Работает с
internal e-type data struct.
Concepts : Return in EIY = COS( EIX ).
NOTE : See: ei_sin__S() & ei_cos__C().
Use Global Variable:
Use Functions : ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *a = NULL,
*c = NULL,
*z = NULL,
*x = NULL,
*s = NULL,
*half = NULL,
*one = NULL,
*small = NULL;
EMUSHORT *pi, *pi2, *pi_2, *pi_4, *pi3_4;
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"cos" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* COS(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"cos", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* COS(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"cos", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* COS(Infinity) must by NaN */
if( ei_isinfin( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"cos", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL Infinity - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
pi = _get_m_pi_ptr ( nb );
pi2 = _get_m_2pi_ptr ( nb );
pi_2 = _get_m_pi_2_ptr ( nb );
pi_4 = _get_m_pi_4_ptr ( nb );
pi3_4 = _get_m_3pi_4_ptr( nb );
/*** Allocate memory for a, c, z, s, half, one, small . *****/
a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !a )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
c = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !c )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
s = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !s )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE s *****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE half **************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
small = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !small )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_one ( s, nb );
/*********************************************
small: 1.0 + small^2 == 1.0;
big : big = 1/(small^2);
*********************************************/
ei_sqrt( small, _get_epsilon_ptr( nb ), nb );
ei_drem( x, eix, pi2, nb ); /* reduse EIX into [-PI, PI]. */
ei_copysign( a, x, one, nb );
if( ei_cmp( a, pi_4, nb ) >= 0 )
{
if( ei_cmp( a, pi3_4, nb ) >= 0 ) /* ... in [3PI/4, PI]. */
{
ei_sub( a, pi, a, nb );
ei_neg( s, nb );
}
else /* ... in [PI/4, 3PI/4]. */
{
/* return: SIN(PI/2-|x|).*/
ei_sub( a, pi_2, a, nb );
ei_mul( z, a, a, nb );
ei_sin__S( z, z, nb );
ei_mul( z, z, a, nb );
ei_add( eiy, a, z, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
}
/* return: s*COS(a) */
if( ei_cmp( a, small, nb ) < 0 )
{
ei_copy( eiy, s, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_mul( z, a, a, nb );
ei_cos__C( c, z, nb );
ei_mul( z, z, half, nb );
ei_sub( a, z, c, nb );
ei_sub( a, one, a, nb );
ei_copysign( eiy, a, s, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_cos() */
void ei_tan( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_tan() Работает с
internal e-type data struct.
Concepts : Return in EIY = TAN( EIX ).
NOTE : See: ei_sin__S() & ei_cos__C().
Use Global Variable:
Use Functions : ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *a = NULL,
*c = NULL,
*z = NULL,
*ss = NULL,
*cc = NULL,
*x = NULL,
*half = NULL,
*one = NULL,
*small = NULL;
EMUSHORT *pi, *pi_2, *pi_4;
int np;
int k;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"tan" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* TAN(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"tan", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* TAN(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"tan", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* TAN(Infinity) must by NaN */
if( ei_isinfin( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"tan", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL Infinity - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
pi = _get_m_pi_ptr ( nb );
pi_2 = _get_m_pi_2_ptr ( nb );
pi_4 = _get_m_pi_4_ptr ( nb );
/*** Allocate memory for a, c, z, ss, cc, half, one, small. */
a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !a )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
c = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !c )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ss = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ss )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
cc = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !cc )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE ss ****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE ss ****************/
/* FREE cc ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE ss ****************/
/* FREE cc ****************/
/* FREE half **************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
small = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !small )
{
/* fatal error */
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE ss ****************/
/* FREE cc ****************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_half( half, nb );
_gen_one ( one, nb );
/*********************************************
small: 1.0 + small^2 == 1.0;
big : big = 1/(small^2);
*********************************************/
ei_sqrt( small, _get_epsilon_ptr( nb ), nb );
ei_drem( x, eix, pi, nb ); /* reduse EIX into [-PI/2, PI/2]. */
ei_copysign( a, x, one, nb ); /* ... = abs(x) */
if( ei_cmp( a, pi_4, nb ) >= 0 )
{
k = 1;
ei_sub( a, pi_2, a, nb );
ei_copysign( x, a, x, nb );
}
else
{
k = 0;
if( ei_cmp( a, small, nb ) < 0 )
{
ei_copy( eiy, x, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE ss ****************/
/* FREE cc ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
}
ei_mul( z, x, x, nb );
ei_cos__C( cc, z, nb );
ei_sin__S( ss, z, nb );
ei_mul( z, z, half, nb ); /* Next get c = cos(x) accurately */
ei_sub( c, z, cc, nb );
ei_sub( c, one, c, nb );
if( k == 0 )
{
/* a use as temp variable */
/* return x+(x*(z-(cc-ss)))/c; ... sin/cos */
ei_sub( a, cc, ss, nb );
ei_sub( a, z, a, nb );
ei_mul( a, x, a, nb );
ei_div( a, a, c, nb );
ei_add( a, x, a, nb );
ei_copy( eiy, a, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE ss ****************/
/* FREE cc ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* a use as temp variable */
/* return c/(x+x*ss); ... cos/sin */
ei_mul( a, x, ss, nb );
ei_add( a, x, a, nb );
ei_div( a, c, a, nb );
ei_copy( eiy, a, nb );
/* FREE x *****************/
/* FREE a *****************/
/* FREE c *****************/
/* FREE z *****************/
/* FREE ss ****************/
/* FREE cc ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( k == 0 ) */
} /* End of ei_tan() */
void ei_log1p( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_log1p() Работает с
internal e-type data struct.
Concepts : Return in EIY the LOGARITHM of ( 1 + EIX ).
METHOD : 1. Argument Reduction: find k and f such that
1+x = 2^k * (1+f),
whwre sqrt(2)/2 < 1+f < sqrt(2).
2. Let s = f/(2+f); Based on
log(1+f) = log(1+s) - log(1-s) =
= 2*S + (2/3)*S^3 + (2/5)*S^5 + ... = L,
log(1+f) is computed by
log(1+f) = 2*s + s*log__L(s*s),
where
log__L(z) =
= z*(L1 + z*(L2 + z*(L3 + ... )) ... ).
See: ei_log__L() for the values of the
coefficients.
3. Finaly, log(1+x) = k*ln2 + log(1+f).
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: FLOATP.H].
NOTE : 1. В шаге 3 n*ln2 всегда сохраняется в двух
числах n*ln2hi + n*ln2lo, где ln2hi ищется
таким, чтобы последние биты были равны 0.
Это обеспечивает точное представление
произведения n*ln2hi в разрядной сетке
машины. Количество младших обнуляемых
бит можно увидеть в
'./service/emuXXXXX/SxxxCxxX.c'.
2. In step 1, f may not representable.
A correction term c for f is computed.
It follows that the correction term for
f - t (the leading term of log(1+f)
in step 2) is c-c*x. We add this correction
term to n*ln2lo to attenuate the error.
SPECIAL CASES : log1p(x) = -InD с выставлением DOMAIN flag
[если( x < -1 )];
log1p(+NaN) = +NaN с выставлением DOMAIN flag;
log1p(-NaN) = -NaN с выставлением DOMAIN flag;
log1p(-inf) = -InD с выставлением DOMAIN flag;
log1p(-1) = -inf с выставлением DOMAIN flag;
log1p(+inf) = +inf [норма];
log1p(0) = 0 [норма];
Use Global Variable:
Use Functions : ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *z = NULL,
*s = NULL,
*t = NULL,
*c = NULL,
*x = NULL,
*tx = NULL, /* temp */
*tr = NULL, /* temp */
*half = NULL,
*one = NULL,
*negone = NULL,
*two = NULL,
*zero = NULL;
static
EMUSHORT *k = NULL, /* for Exponent */
*tk = NULL; /* temp */
EMUSHORT *ln2hi, *ln2lo, *sqrt2, *small;
int np, ne;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"log1p" );
ei_ind( eiy, nb );
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
ne = internal_ne( nb ) + 1;
/*** Allocate memory for x, zero . **************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE zero **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_zero( zero, nb ); /* Befor test +/-inf */
ei_copy( x, eix, nb );
/***************************
Test for EIX.
***************************/
/* LOG1P(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log1p", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /*Set REAL InD - produsing Domain Flag */
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* LOG1P(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log1p", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL NaN - produsing Domain Flag */
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*
LOG1P(+Infinity) must by Infinity;
LOG1P(-Infinity) must by InD;
*/
if( ei_isinfin( eix, nb ) )
{
if( ei_cmp( eix, zero, nb ) < 0 ) /* ( EIX < 0 ) */
{
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log1p", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL -Infinity - produsing Domain Flag */
}
else
ei_copy( eiy, eix, nb );
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for z, s, t, c, tx, tr . ***************/
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
s = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !s )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
c = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !c )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for half, one, negone, two . ***********/
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
negone = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !negone )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for k, tk . ****************************/
k = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !k )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tk = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !tk )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_one ( negone, nb );
ei_neg ( negone, nb );
_gen_two ( two, nb );
ln2hi = _get_m_ln2hi_ptr( nb ); /* Service Constant */
ln2lo = _get_m_ln2lo_ptr( nb ); /* Service Constant */
sqrt2 = _get_m_sqrt2_ptr( nb ); /* Math Constant */
small = _get_epsilon_ptr( nb ); /* See: FLOATP.H */
if( ei_cmp( x, negone, nb ) > 0 ) /* ( x > -1.0 ) */
{
/********************
Argument reduction
********************/
ei_copysign( tx, x, one, nb );
if( ei_cmp( tx, small, nb ) < 0 ) /* if( x < small ) */
{
ei_copy( eiy, x, nb ); /* return( x ); */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_add( tx, one, x, nb );
ei_logb( k, tx, ne, nb ); /* k=logb(1+x); */
ei_nege( tk, k, ne );
ei_ldexp( z, tk, x, ne, nb ); /* z=ldexp( x,-k); */
ei_ldexp( t, tk, one, ne, nb ); /* t=ldexp(one,-k); */
ei_add( tx, z, t, nb );
if( ei_cmp( tx, sqrt2, nb ) >= 0 ) /* if( z+t >= sqrt2 ) */
{
ei_ince( k, k, ne ); /* k += 1; */
ei_mul( z, z, half, nb ); /* z *= half; */
ei_mul( t, t, half, nb ); /* t *= half; */
}
ei_add( t, t, negone, nb ); /* t += negone; */
ei_add( x, z, t, nb ); /* x = z + t; */
ei_sub( tx, t, x, nb ); /* Correction term for x */
ei_add( c, tx, z, nb ); /* c = (t-x) + z; */
/******************
Compute log(1+x)
******************/
ei_add( tx, two, x, nb );
ei_div( s, x, tx, nb ); /* s = x/(2+x); */
ei_mul( tx, x, x, nb );
ei_mul( t, tx, half, nb ); /* t = x*x*half; */
ei_ltor( tr, k, nb, ne );
ei_mul( tr, tr, ln2lo, nb );
ei_mul( tx, c, x, nb );
ei_sub( tr, tr, tx, nb );
ei_add( c, c, tr, nb ); /* c += (k*ln2lo-c*x); */
ei_mul( tr, s, s, nb );
ei_log__L( tx, tr, nb );
ei_add( tx, t, tx, nb );
ei_mul( tr, s, tx, nb );
ei_add( z, c, tr, nb ); /* z = c+s*(t+log_L(s*s)); */
ei_sub( tx, z, t, nb );
ei_add( x, x, tx, nb ); /* x += (z - t); */
ei_ltor( tr, k, nb, ne );
ei_mul( tr, tr, ln2hi, nb );
ei_add( eiy, tr, x, nb ); /* return( k*ln2hi+x ); */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else /* т.е. ( x <= -1.0 ) */
{
if( ei_cmp( x, negone, nb ) == 0 ) /* ( x == -1.0 ) */
{
/* x == -1, return -Infinity with signal */
/* "argument domain error" */
/* return: -Infinity */
ei_infin( eiy, (unsigned)1, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log1p", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* ( x == -1 ) - produsing Domain Flag */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* x < -1, return -InD with signal */
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log1p", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* ( x < -1 ) - produsing Domain Flag */
/* FREE x *****************/
/* FREE zero **************/
/* FREE z *****************/
/* FREE s *****************/
/* FREE t *****************/
/* FREE c *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( x > -1.0 ) */
} /* End of ei_log1p() */
void ei_log( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_log() Работает с
internal e-type data struct.
Concepts : Return in EIY the LOGARITHM of ( EIX ).
METHOD : * This code was derived, with minor
* modification, from:
* Teter Tang, "Table-Driven Implementation
* of the Logarithm in IEEE Floating-Point
* arithmetic." ACM Trans. Math Software,
* vol 16. no 4, pp 378-400, Dec 1990).
Calculates log(2^m*F*(1+f/F)), |f/j| <= 1/256,
where F = j/128 for j an integer in [0, 128].
log(2^m) = log2_hi*m + log2_tail*m
since m is an integer, the dominant term
is exact. m has at most
nE*HOST_BITS_PER_EMUSHORT digits
(for subnormal numbers), and log2_hi has
nE*HOST_BITS_PER_EMUSHORT + 1
trailing zero bits.
log(F) = logF_hi[j] + logF_lo[j]
is in tabular form in log_table[]
logF_hi[] + 512 is exact.
log(1+f/F) =
2*f/(2*F + f) + 1/12 * (2*f/(2*F + f))**3 + ...
the leading term is calculated to extra
precision in two parts, the larger of which
adds exactly to the dominant m and F terms.
There are two cases:
1. when m, j are non-zero (m | j), use
absolute precision for the leading term.
2. when m = j = 0, |1-x| < 1/256,
and log(x) ~= (x-1).
In this case, use a relative precision
of [after __ei_TRUNC()] bits.
(This is done differently in the original
paper).
Table of log(Fj) = logF_head[j] + logF_tail[j],
for Fj = 1+j/128. Used for generation of
extend precision logarithms.
Values for log(F) were generated using
ei_log1p() function.
EI_LOG__N() : Построение ряда:
=====================================================================
log(1+f/F) = 2*f/(2*F+f) + 1/12 * (2*f/(2*F+f))**3 + ...
q = f/F;
s = q/(2+q) = (f/F)/(2+f/F) = f/(2F+f);
тогда
log(1+f/F) = 2s + (2/3)s^3 + (2/5)s^5 + ... =
/ f \ 2 / f \ ^3 2 / f \ ^5
= 2*| ---- | + ---*| ---- | + ---*| ---- | + ... =
\2F+f/ 3 \2F+f/ 5 \2F+f/
/ f \ 2*2^2 / f \ ^3 2*2^4 / f \ ^5
= 2*| ---- | + -----*| ---- | + -----*| ---- | + ... =
\2F+f/ 3*2^2 \2F+f/ 5*2^4 \2F+f/
/ 2f \ 1 / 2f \ ^3 1 / 2f \ ^5
= | ---- | + -----*| ---- | + -----*| ---- | + ... .
\2F+f/ 3*2^2 \2F+f/ 5*2^4 \2F+f/
1 1
ei_log__N(x) = -----*x^3 + -----*x^5 + ... .
3*2^2 5*2^4
Общая формула получения коэффициентов для APPROX():
k = 1/(s*2^(s-1)), где s = 3, 5, 7, 9, 11, ... .
Интервал для APPROX(): [0.0, 1/256].
=====================================================================
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: FLOATP.H].
NOTE : log2_hi = logF_head[n_log_table];
log2_lo = logF_tail[n_log_table];
Not use the service constants ln2hi, ln2lo.
SPECIAL CASES : log(x) = -InD с выставлением DOMAIN flag
[если( x < 0 )];
log(+NaN) = +NaN с выставлением DOMAIN flag;
log(-NaN) = -NaN с выставлением DOMAIN flag;
log(-inf) = -InD с выставлением DOMAIN flag;
log( 0 ) = -inf с выставлением DOMAIN flag;
log(+inf) = +inf [норма];
log(1) = 0 [норма];
Use Global Variable:
Use Functions : ei_log__N( eiy, eix, nb ); | st-ln.c
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*F = NULL,
*f = NULL,
*g = NULL,
*q = NULL,
*u = NULL,
*u1 = NULL,
*u2 = NULL,
*v = NULL,
*zero = NULL,
*one = NULL,
*half = NULL,
*two = NULL,
*tx = NULL, /* temp */
*tm = NULL, /* temp */
*tr = NULL; /* temp */
EMUSHORT *log2_hi = NULL,
*log2_lo = NULL;
EMUSHORT *m = NULL, /* for Exponent */
*je = NULL,
*min_bin_exp = NULL,
*mt = NULL; /* temp */
EMUSHORT *p, *logF_head, *logF_tail;
__mpu_int32_t j;
int np, ne, i;
int n_log_table;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"log" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
ne = internal_ne( nb ) + 1;
/*** Allocate memory for x, y . *****************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_zero( zero, nb ); /* Befor test +/-inf */
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* LOG(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL InD - produsing Domain Flag */
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* LOG(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL NaN - produsing Domain Flag */
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*
LOG(+Infinity) must by Infinity;
LOG(-Infinity) must by InD;
*/
if( ei_isinfin( eix, nb ) )
{
if( ei_cmp( eix, zero, nb ) < 0 ) /* ( EIX < 0 ) */
{
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL -Infinity - produsing Domain Flag */
}
else
ei_copy( eiy, eix, nb );
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for F, f, g, q, u, u1, u2, v . *********/
F = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !F )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
f = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !f )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
g = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !g )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
q = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !q )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
u = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !u )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
u1 = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !u1 )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
u2 = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !u2 )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
v = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !v )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for one, half, two, tx, tm, tr . *******/
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tm = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tm )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(14*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for log2_hi, log2_lo . *****************/
log2_hi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !log2_hi )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(16*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
log2_lo = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !log2_lo )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
__mpu_sbrk( -(int)(17*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for m, je, min_bin_exp, mt . ***********/
m = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !m )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
je = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !je )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
min_bin_exp = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !min_bin_exp )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
/* FREE je ****************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
mt = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !mt )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
/* FREE je ****************/
/* FREE min_bin_exp *******/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
n_log_table = _get_n_log_table( nb );
logF_head = _get_logF_head_ptr( nb );
logF_tail = _get_logF_tail_ptr( nb );
ei_cpye( min_bin_exp, _get_min_2_exp_ptr( nb ), ne, ne );
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_two ( two, nb );
/* Service Constant: hight entries of log_table[] */
ei_copy( log2_hi, logF_head + np*n_log_table, nb );
ei_copy( log2_lo, logF_tail + np*n_log_table, nb );
/* ei_copy( x, eix, nb ); */
if( ei_cmp( x, zero, nb ) > 0 ) /* ( x > 0.0 ) */
{
/********************
Argument reduction
********************/
ei_logb( m, x, ne, nb ); /* m = logb( x ); */
ei_nege( mt, m, ne );
ei_ldexp( g, mt, x, ne, nb ); /* g = ldexp( x, -m ); */
/* if( m == min_bin_exp ) */
if( ei_cmpe( m, min_bin_exp, ne ) == 0 )
{
ei_logb( je, g, ne, nb ); /* je = logb( g ); */
ei_adde( m, m, je, ne ); /* m += je; */
ei_nege( mt, je, ne );
ei_ldexp( g, mt, g, ne, nb ); /* g = ldexp( g, -je ); */
}
/* begin: ************************
j = n_log_table*(g-1) + .5;
F = (1.0/n_log_table) * j + 1;
f = g - F;
*********************************/
j = (__mpu_int32_t)n_log_table;
ei_ltor( tr, (EMUSHORT *)&j, nb, 1 );
ei_sub( tx, g, one, nb );
ei_mul( tr, tr, tx, nb );
ei_add( tr, tr, half, nb ); /* tr=j; */
ei_ltor( tx, (EMUSHORT *)&j, nb, 1 );
ei_div( tx, one, tx, nb );
/* begin : *********************************
Skip digits after decimal point.
*******************************************/
ei_rtol_frac( (EMUSHORT *)&j, /* j = tr; */
(EMUSHORT *)0, tr, 1, nb );
ei_ltor( tr, (EMUSHORT *)&j, nb, 1 );
/* end : ***********************************
Skip digits after decimal point.
*******************************************/
ei_mul( tx, tx, tr, nb );
ei_add( F, tx, one, nb ); /* F*128 is an integer in [128,512] */
ei_sub( f, g, F, nb );
/* For following Code. */
ei_rtol_frac( je, /* je = tr; */
(EMUSHORT *)0, tr, ne, nb );
/* end: **************************
j = n_log_table*(g-1) + .5;
F = (1.0/n_log_table) * j + 1;
f = g - F;
*********************************/
/**************************************************
Approximate expansion for log( 1+f/F ) ~= u + q.
**************************************************/
ei_mul( tr, two, F, nb );
ei_add( tr, tr, f, nb );
ei_div( g, one, tr, nb ); /* g = 1/(2*F+f); */
ei_mul( u, two, f, nb );
ei_mul( u, u, g, nb ); /* u = 2*f*g; */
ei_mul( v, u, u, nb ); /* v = u*u; */
ei_log__N( tx, v, nb );
ei_mul( q, u, tx, nb ); /* q = u*v*(A1+v*(A2+v*(A3+...))); */
if( ei_cmp0e( m, ne ) || ei_cmp0e( je, ne ) )
{
/* Формирование константы 0x2000.....0001; */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = mt;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXTWO >> 1; /* 0x2000... */
for( i = 0; i < ne - 2; i++ ) *p++ = (EMUSHORT)0;
p--;
*p |= 1;
#else
/* hight part */
p = mt + ne - 1;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXTWO >> 1;
for( i = 0; i < ne - 2; i++ ) *p-- = (EMUSHORT)0;
p++;
*p |= 1;
#endif
ei_ltor( tr, mt, nb, ne );
ei_add( u1, u, tr, nb ); /* u1 = u + 513; */
ei_sub( u1, u1, tr, nb ); /* u1 -= 513; */
}
else
{
ei_copy( u1, u, nb );
__ei_TRUNC( u1, nb );
}
ei_mul( tr, F, u1, nb );
ei_sub( tr, f, tr, nb );
ei_mul( tr, two, tr, nb );
ei_mul( tx, u1, f, nb );
ei_sub( tr, tr, tx, nb );
ei_mul( u2, tr, g, nb ); /* u2 = (2.0*(f - F*u1) - u1*f) * g; */
/******************************************
u1 + u2 = 2f/(2F+f); to extra precision.
******************************************/
/***********************************************************
log(x) = log(2^m*F*(1+f/F)) =
(m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q);
(exact) + (tiny).
***********************************************************/
ei_ltor( tm, m, nb, ne );
ei_mul( tr, tm, log2_hi, nb );
ei_add( tr, tr, logF_head+np*j, nb );
ei_add( u1, u1, tr, nb ); /* u1 += m*logF_head[N] +
logF_head[j]; */
ei_add( tr, u2, logF_tail+np*j, nb );
ei_add( u2, tr, q, nb ); /* u2 = (u2 + logF_tail[j]) + q; */
ei_mul( tr, log2_lo, tm, nb );
ei_add( u2, u2, tr, nb ); /* u2 += logF_tail[N]*m; */
ei_add( eiy, u1, u2, nb ); /* return( u1 + u2 ); */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
/* FREE je ****************/
/* FREE min_bin_exp *******/
/* FREE mt ****************/
__mpu_sbrk( -(int)(4*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else /* т.е. ( x <= 0.0 ) */
{
if( ei_cmp( x, zero, nb ) == 0 ) /* ( x == 0.0 ) */
{
/* x == 0.0, return -Infinity with signal */
/* "argument domain error" */
/* return: -Infinity */
ei_infin( eiy, (unsigned)1, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* ( x == 0 ) - produsing Domain Flag */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
/* FREE je ****************/
/* FREE min_bin_exp *******/
/* FREE mt ****************/
__mpu_sbrk( -(int)(4*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* x < 0.0, return -InD with signal */
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"log", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* ( x < 0 ) - produsing Domain Flag */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
/* FREE je ****************/
/* FREE min_bin_exp *******/
/* FREE mt ****************/
__mpu_sbrk( -(int)(4*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( x > 0.0 ) */
} /* End of ei_log() */
typedef struct Double Double;
struct Double
{
EMUSHORT *a;
EMUSHORT *b;
};
static void __ei_log__D( Double diy, EMUSHORT *eix, int nb )
{
EMUSHORT *x = NULL,
*F = NULL,
*f = NULL,
*g = NULL,
*q = NULL,
*u = NULL,
*u1 = NULL,
*u2 = NULL,
*v = NULL,
*zero = NULL,
*one = NULL,
*half = NULL,
*two = NULL,
*tx = NULL, /* temp */
*tm = NULL, /* temp */
*tr = NULL; /* temp */
EMUSHORT *log2_hi = NULL,
*log2_lo = NULL;
EMUSHORT *m = NULL, /* for Exponent */
*je = NULL,
*min_bin_exp = NULL,
*mt = NULL; /* temp */
EMUSHORT *p, *logF_head, *logF_tail;
__mpu_int32_t j;
int np, ne, i;
int n_log_table;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
ne = internal_ne( nb ) + 1;
/*** Allocate memory for x, y . *****************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for F, f, g, q, u, u1, u2, v . *********/
F = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !F )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
f = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !f )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
g = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !g )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
q = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !q )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
u = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !u )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
u1 = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !u1 )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
u2 = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !u2 )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
v = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !v )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for one, half, two, tx, tm, tr . *******/
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tm = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tm )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(14*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for log2_hi, log2_lo . *****************/
log2_hi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !log2_hi )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(16*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
log2_lo = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !log2_lo )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
__mpu_sbrk( -(int)(17*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for m, je, min_bin_exp, mt . ***********/
m = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !m )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
je = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !je )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
min_bin_exp = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !min_bin_exp )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
/* FREE je ****************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
mt = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !mt )
{
/* fatal error */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
/* FREE je ****************/
/* FREE min_bin_exp *******/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
n_log_table = _get_n_log_table( nb );
logF_head = _get_logF_head_ptr( nb );
logF_tail = _get_logF_tail_ptr( nb );
ei_cpye( min_bin_exp, _get_min_2_exp_ptr( nb ), ne, ne );
_gen_zero( zero, nb );
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_two ( two, nb );
/* Service Constant: hight entries of log_table[] */
ei_copy( log2_hi, logF_head + np*n_log_table, nb );
ei_copy( log2_lo, logF_tail + np*n_log_table, nb );
ei_copy( x, eix, nb );
/********************
Argument reduction
********************/
ei_logb( m, x, ne, nb ); /* m = logb( x ); */
ei_nege( mt, m, ne );
ei_ldexp( g, mt, x, ne, nb ); /* g = ldexp( x, -m ); */
/* if( m == min_bin_exp ) */
if( ei_cmpe( m, min_bin_exp, ne ) == 0 )
{
ei_logb( je, g, ne, nb ); /* je = logb( g ); */
ei_adde( m, m, je, ne ); /* m += je; */
ei_nege( mt, je, ne );
ei_ldexp( g, mt, g, ne, nb ); /* g = ldexp( g, -je ); */
}
/* begin: ************************
j = n_log_table*(g-1) + .5;
F = (1.0/n_log_table) * j + 1;
f = g - F;
*********************************/
j = (__mpu_int32_t)n_log_table;
ei_ltor( tr, (EMUSHORT *)&j, nb, 1 );
ei_sub( tx, g, one, nb );
ei_mul( tr, tr, tx, nb );
ei_add( tr, tr, half, nb ); /* tr=j; */
ei_ltor( tx, (EMUSHORT *)&j, nb, 1 );
ei_div( tx, one, tx, nb );
/* begin : *********************************
Skip digits after decimal point.
*******************************************/
ei_rtol_frac( (EMUSHORT *)&j, /* j = tr; */
(EMUSHORT *)0, tr, 1, nb );
ei_ltor( tr, (EMUSHORT *)&j, nb, 1 );
/* end : ***********************************
Skip digits after decimal point.
*******************************************/
ei_mul( tx, tx, tr, nb );
ei_add( F, tx, one, nb ); /* F*128 is an integer in [128,512] */
ei_sub( f, g, F, nb );
/* For following Code. */
ei_rtol_frac( je, /* je = tr; */
(EMUSHORT *)0, tr, ne, nb );
/* end: **************************
j = n_log_table*(g-1) + .5;
F = (1.0/n_log_table) * j + 1;
f = g - F;
*********************************/
/**************************************************
Approximate expansion for log( 1+f/F ) ~= u + q.
**************************************************/
ei_mul( tr, two, F, nb );
ei_add( tr, tr, f, nb );
ei_div( g, one, tr, nb ); /* g = 1/(2*F+f); */
ei_mul( u, two, f, nb );
ei_mul( u, u, g, nb ); /* u = 2*f*g; */
ei_mul( v, u, u, nb ); /* v = u*u; */
ei_log__N( tx, v, nb );
ei_mul( q, u, tx, nb ); /* q = u*v*(A1+v*(A2+v*(A3+...))); */
if( ei_cmp0e( m, ne ) || ei_cmp0e( je, ne ) )
{
/* Формирование константы 0x2000.....0001; */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = mt;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXTWO >> 1; /* 0x2000... */
for( i = 0; i < ne - 2; i++ ) *p++ = (EMUSHORT)0;
p--;
*p |= 1;
#else
/* hight part */
p = mt + ne - 1;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXTWO >> 1;
for( i = 0; i < ne - 2; i++ ) *p-- = (EMUSHORT)0;
p++;
*p |= 1;
#endif
ei_ltor( tr, mt, nb, ne );
ei_add( u1, u, tr, nb ); /* u1 = u + 513; */
ei_sub( u1, u1, tr, nb ); /* u1 -= 513; */
}
else
{
ei_copy( u1, u, nb );
__ei_TRUNC( u1, nb );
}
ei_mul( tr, F, u1, nb );
ei_sub( tr, f, tr, nb );
ei_mul( tr, two, tr, nb );
ei_mul( tx, u1, f, nb );
ei_sub( tr, tr, tx, nb );
ei_mul( u2, tr, g, nb ); /* u2 = (2.0*(f - F*u1) - u1*f) * g; */
/******************************************
u1 + u2 = 2f/(2F+f); to extra precision.
******************************************/
/***********************************************************
log(x) = log(2^m*F*(1+f/F)) =
(m*log2_hi+logF_head[j]+u1) + (m*log2_lo+logF_tail[j]+q);
(exact) + (tiny).
***********************************************************/
ei_ltor( tm, m, nb, ne );
ei_mul( tr, tm, log2_hi, nb );
ei_add( tr, tr, logF_head+np*j, nb );
ei_add( u1, u1, tr, nb ); /* u1 += m*logF_head[N] +
logF_head[j]; */
ei_add( tr, u2, logF_tail+np*j, nb );
ei_add( u2, tr, q, nb ); /* u2 = (u2 + logF_tail[j]) + q; */
ei_mul( tr, log2_lo, tm, nb );
ei_add( u2, u2, tr, nb ); /* u2 += logF_tail[N]*m; */
/* Only difference is here */
ei_add( diy.a, u1, u2, nb ); /* diy.a = u1 + u2; */
__ei_TRUNC( diy.a, nb );
ei_sub( tr, u1, diy.a, nb );
ei_add( diy.b, tr, u2, nb ); /* diy.b = (u1 - diy.a) + u2; */
/* FREE x *****************/
/* FREE zero **************/
/* FREE F *****************/
/* FREE f *****************/
/* FREE g *****************/
/* FREE q *****************/
/* FREE u *****************/
/* FREE u1 ****************/
/* FREE u2 ****************/
/* FREE v *****************/
/* FREE one ***************/
/* FREE half **************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tr ****************/
/* FREE log2_hi ***********/
/* FREE log2_lo ***********/
__mpu_sbrk( -(int)(18*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE m *****************/
/* FREE je ****************/
/* FREE min_bin_exp *******/
/* FREE mt ****************/
__mpu_sbrk( -(int)(4*ne*SIZE_OF_EMUSHORT) );
/**************************/
return; /* return( diy ); */
} /* End of __ei_log__D() */
void ei_log10( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
log10( e ) = 1/ln( 10. );
Переход от натурального логарифма к десятичному:
log10( N ) = log10( e )*ln( N ).
***************************************************************/
/*******************************
mtherr("ei_log10"); ПОТОМ !!!
*******************************/
{
EMUSHORT *m_1_ln10;
m_1_ln10 = _get_m_1_ln10_ptr( nb );
ei_log( eiy, eix, nb );
ei_mul( eiy, eiy, m_1_ln10, nb );
}
void ei_log2( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Переход от натурального логарифма к логарифму по основанию 2:
log2( N ) = log2( e )*ln( N ).
***************************************************************/
/******************************
mtherr("ei_log2"); ПОТОМ !!!
******************************/
{
EMUSHORT *m_1_ln2;
m_1_ln2 = _get_m_1_ln2_ptr( nb );
ei_log( eiy, eix, nb );
ei_mul( eiy, eiy, m_1_ln2, nb );
}
static void __ei_exp__E( EMUSHORT *eiy, EMUSHORT *eix, EMUSHORT *eic, int nb )
/***************************************************************
Description : __ei_exp__E() Работает с
internal e-type data struct.
Concepts : ASSUMPTION: EIC << EIX SO THAT
__ei_TRUNC( EIX+EIC) = EIX.
(EIC is the correction term for EIX)
ei_exp__E(x,c) RETURNS in EIY:
/ exp(x+c)-1-x ,
| EPS < |x| < .3465736...
ei_exp__E(x,c) = |
\ 0, |x| < EPS;
where the constant .3465736... = ln(2)/2.
METHOD : 1. Rational approximation. Let r=x+c.
Based on
2 * sinh(r/2)
exp(r) - 1 = -----------------------,
cosh(r/2) - sinh(r/2)
__ei_exp__E(r) is computed using
x*x (x/2)*W-(Q-(2*P+x*P))
--- + (c + x*[----------------------- + c ])
2 1 - W
where P := p1*x^2 + p2*x^4 + ...,
Q := q1*x^2 + q2*x^4 + ...,
W := x/2-(Q-x*P),
See the listing below for the values
of p1,p2,q1,q2,q3. The polynomials
P and Q may be regarded as the
approximations to ei_sinh__S() and
ei_cosh__C() :
sinh(r/2) = r/2 + r * P,
cosh(r/2) = 1 + Q.)
EI_SINH__S() : Построение ряда:
==============================================================
Известно, что
sinh(x) = x + (1/3!)*x^3 + (1/5!)*x^5 + ... .
Мы имеем следующий способ
sinh(r/2) = r/2 + r*P;
и
sinh(r/2) = r/2 + (1/3!)*(r/2)^3 + (1/5!)*(r/2)^5 + ... .
следовательно
P = (1/3!)*(r^2/2^3) + (1/5!)*(r^4/2^5) + ... =
1 1 1
= ------*r^2 + ------*r^4 + ------*r^6 + ... .
2^3*3! 2^5*5! 2^7*7!
z = r*r; P = p1*z + p2*z^2 + p3*z^3 + ... .
Вот все, что нужно для APPROX(), чтобы получить p1, p2, p3, ...
на интервале [0, ln(2)/2] по флгоритму Ремеза.
==============================================================
EI_COSH__C() : Построение ряда:
==============================================================
Известно, что
cosh(x) = 1 + (1/2!)*x^2 + (1/4!)*x^4 + ... .
Мы имеем следующий способ
cosh(r/2) = 1 + Q;
и
cosh(r/2) = 1 + (1/2!)*(r/2)^2 + (1/4!)*(r/2)^4 + ... .
следовательно
1 1 1
Q = ------*r^2 + ------*r^4 + ------*r^6 + ... .
2^2*2! 2^4*4! 2^6*6!
z = r*r; Q = p1*z + p2*z^2 + p3*z^3 + ... .
Вот все, что нужно для APPROX(), чтобы получить q1, q2, q3, ...
на интервале [0, ln(2)/2] по флгоритму Ремеза.
==============================================================
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: FLOATP.H].
NOTE : The coefficient hS's & hC's
[ in __ei_sinh__S(), __ei_cosh__C()]
are obtained by a special Remez algorithm.
==========================================
В INTERNET я нашел следующие алгоритмы:
409 cacm 355 356 14 5 May 1971 e2 A60
------------------------------------------
H. Schmitt;
Discrete {Chebychev} Curve Fit
approximation;Chebyshev approximation;
Chebyshev curve fitting;
+Chebyshev polynomial;
curve approximation;curve fitting;
exchange algorithm;
+polynomial approximation;Remez algorithm;
501 toms 95 97 2 1 March 1976 e2 F K2
---------------------------------------------
J. C. Simpson;
{FORTRAN} Translation of Algorithm 409
Discrete {Chebyshev} Curve Fit
approximation;polynomial approximation;
exchange algorithm;
+Chebyshev approximation;
polynomial approximation;
R,toms,95,4,1,March,1978,F. Futrell;
последний из которых я перевел на "С", затем
на язык операций повышенной разрядности.
==========================================
Use Global Variable:
Use Functions : ei_sinh__S( eiy, eix, nb ); | st-sinh.c
ei_cosh__C( eiy, eix, nb ); | st-cosh.c
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
EMUSHORT *eic; - указатель на
internal e-type
data struct.
(EIC is the
correction term
for EIX)
SOURCE & TARGET;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *z = NULL,
*c = NULL,
*p = NULL,
*q = NULL,
*xp = NULL,
*xh = NULL,
*w = NULL,
*x = NULL,
*tx = NULL, /* temp */
*tr = NULL, /* temp */
*half = NULL,
*one = NULL,
*zero = NULL;
EMUSHORT *small;
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for z, c, p, q, xp, xh, w, x, tx, tr . */
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
return;
}
c = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !c )
{
/* fatal error */
/* FREE z *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
p = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
q = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !q )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
xp = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !xp )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
xh = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !xh )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
w = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !w )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
/* FREE w *****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
/* FREE w *****************/
/* FREE x *****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
/* FREE w *****************/
/* FREE x *****************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for half, one, zero . ******************/
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
/* FREE w *****************/
/* FREE x *****************/
/* FREE tx ****************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
/* FREE w *****************/
/* FREE x *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
/* FREE w *****************/
/* FREE x *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_zero( zero, nb );
_gen_half( half, nb );
_gen_one ( one, nb );
small = _get_epsilon_ptr( nb ); /* See: FLOATP.H */
ei_copy( x, eix, nb );
ei_copy( c, eic, nb );
ei_copysign( tx, x, one, nb );
if( ei_cmp( tx, small, nb ) > 0 ) /* if( x > small ) */
{
ei_mul( z, x, x, nb );
ei_sinh__S( p, z, nb );
ei_cosh__C( q, z, nb );
ei_mul( xp, x, p, nb ); /* xp = x*p; */
ei_mul( xh, x, half, nb ); /* xh = x*half; */
ei_sub( tx, q, xp, nb );
ei_sub( w, xh, tx, nb ); /* w = xh-(q-xp); */
ei_add( p, p, p, nb ); /* p = p + p; */
ei_add( tx, p, xp, nb );
ei_sub( tx, q, tx, nb );
ei_mul( tr, xh, w, nb );
ei_sub( tx, tr, tx, nb );
ei_sub( tr, one, w, nb );
ei_div( tx, tx, tr, nb );
ei_add( tx, tx, c, nb );
ei_mul( tx, x, tx, nb );
ei_add( c, c, tx, nb ); /* c+=x*[(xh*w-(q-(p+xp)))/(one-w)+c]; */
ei_mul( tr, z, half, nb );
ei_add( tr, tr, c, nb ); /* return( z*half+c ); */
ei_copy( eiy, tr, nb );
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
/* FREE w *****************/
/* FREE x *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE zero **************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else /* т.е. ( |x| < small ) */
{
if( ei_cmp( x, zero, nb ) != 0 )
{
/* raise the inexact flag */
}
/* return( copysign(zero,x) ); */
ei_copysign( eiy, zero, x, nb );
/* FREE z *****************/
/* FREE c *****************/
/* FREE p *****************/
/* FREE q *****************/
/* FREE xp ****************/
/* FREE xh ****************/
/* FREE w *****************/
/* FREE x *****************/
/* FREE tx ****************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE zero **************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End of __ei_exp__E() */
void ei_expm1( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_expm1() Работает с
internal e-type data struct.
Concepts : EI_EXPM1(EIX) RETURN in EIY
THE EXPONENTIAL OF EIX MINUS ONE.
METHOD :
1. Argument Reduction: given the input EIX,
find r and integer k such that
EIX = k*ln2 + r, |r| <= 0.5*ln2 .
r will be represented as r = z+c for better
accuracy.
2. Compute EI_EXPM1(r) = exp(r)-1 by
EI_EXPM1(r=z+c) := z + __ei_exp__E(z,c)
3. EI_EXPM1(x) = 2^k*(EI_EXPM1(r) + 1-2^-k).
Remarks:
1. When k=1 and z < -0.25, we use the
following formula for better accuracy:
EI_EXPM1(x) = 2*((z+0.5)+__ei_exp__E(z,c)).
2. To avoid rounding error in 1-2^-k where
k is large, we use
EI_EXPM1(x) =
= 2^k*{[z+(__ei_exp__E(z,c)-2^-k )] + 1}
when k > NSBITS(nb).
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: mpu-float.h].
SPECIAL CASES : expm1(+NaN) = +NaN с выставлением DOMAIN flag;
expm1(-NaN) = -NaN с выставлением DOMAIN flag;
expm1(-inf) = -1 [норма];
expm1(+inf) = +inf [норма];
expm1(0) = 0 [норма];
Use Global Variable:
Use Functions : __ei_exp__E( eiy, eix, nb ); | this file
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*z = NULL,
*hi = NULL,
*lo = NULL,
*c = NULL,
*zero = NULL,
*half = NULL,
*one = NULL,
*negone = NULL,
*quart = NULL,
*tx = NULL, /* temp */
*tm = NULL, /* temp */
*tk = NULL; /* temp */
EMUSHORT *k = NULL, /* for Exponent */
*mk = NULL,
*prec1 = NULL,
*prec2 = NULL,
*kone = NULL; /* temp 1 */
EMUSHORT *ln2hi, *ln2lo, *invln2, *lnhuge, *lntiny;
EMUSHORT prec;
int np, ne, i;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"expm1" );
/* ei_ind( eiy, nb ); *//* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* EXPM1(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"expm1", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EXPM1(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"expm1", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ne = internal_ne( nb ) + 1;
/*** Allocate memory for z, hi, lo, c . *******************/
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
hi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !hi )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
lo = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !lo )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
c = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !c )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for zero, half, one, negone, quart . ***/
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
negone = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !negone )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
quart = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !quart )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for tx, tm, tk . ***********************/
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tm = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tm )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tk = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tk )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for k, mk, prec1, prec2, kone . ********/
k = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !k )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
mk = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !mk )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
prec1 = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !prec1 )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE mk ****************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
prec2 = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !prec2 )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE mk ****************/
/* FREE prec1 *************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
kone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !kone )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE prec2 *************/
__mpu_sbrk( -(int)(4*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* _gen( kone = 1 ); */
for( i = 0; i < ne; i++ ) kone[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
kone[ne-1] = (EMUSHORT)1;
#else
kone[0] = (EMUSHORT)1;
#endif
prec = NSBITS(nb);
ei_cpye_unpack( prec1, (EMUSHORT *)&prec, ne, 1 );
ei_shln( prec2, prec1, ne, ne );
ln2hi = _get_m_ln2hi_ptr( nb ); /* Service Constant */
ln2lo = _get_m_ln2lo_ptr( nb ); /* Service Constant */
lnhuge = _get_m_ln_huge_ptr( nb ); /* Service Constant */
lntiny = _get_m_ln_tiny_ptr( nb ); /* Service Constant */
invln2 = _get_m_1_ln2_ptr( nb ); /* Math Constant */
_gen_zero( zero, nb );
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_one ( negone, nb ); /* Befor test +/-inf */
ei_neg ( negone, nb );
_gen_two ( quart, nb );
ei_div( quart, half, quart, nb );
ei_neg ( quart, nb ); /* quart = -0.25; */
/* ei_copy( x, eix, nb ); */
if( ei_cmp( x, lnhuge, nb ) <= 0 )
{
if( ei_cmp( x, lntiny, nb ) >= 0 )
{
/********************
Argument reduction
********************/
ei_copysign( tm, half, x, nb );
ei_mul( tx, invln2, x, nb );
ei_add( tx, tx, tm, nb );
/* begin : *********************************
k = _REALtoINT(x/ln(2)).
*******************************************/
ei_rtol_frac( k, /* k = tx; */
(EMUSHORT *)0,
tx, ne, nb ); /* k = _RtoINT(x/ln2); */
ei_ltor( tk, k, nb, ne ); /* tk = k; */
/* end : ***********************************
k = _REALtoINT(x/ln(2)).
*******************************************/
ei_mul( tx, tk, ln2hi, nb );
ei_sub( hi, x, tx, nb ); /* hi = x-k*ln2hi; */
ei_mul( lo, tk, ln2lo, nb );
ei_sub( z, hi, lo, nb ); /* z = hi-(lo=k*ln2lo); */
ei_sub( tm, hi, z, nb );
ei_sub( c, tm, lo, nb ); /* c = (hi-z)-lo; */
if( ei_cmp0e( k, ne ) == 0 ) /* if( k == 0 ) */
{
__ei_exp__E( tx, z, c, nb );
ei_add( eiy, z, tx, nb ); /* return(z+__ei_exp__E(z,c)); */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE prec2 *************/
/* FREE kone **************/
__mpu_sbrk( -(int)(5*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( k == 0 ) */
if( ei_cmpe( k, kone, ne ) == 0 ) /* if( k == 1 ) */
{
if( ei_cmp( z, quart, nb ) < 0 ) /* if( z < -0.25 ) */
{
ei_add( x, z, half, nb ); /* x = z+half; */
__ei_exp__E( tx, z, c, nb );
ei_add( x, x, tx, nb ); /* x += __ei_exp__E(z,c); */
ei_add( eiy, x, x, nb ); /* return( x + x ); */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE prec2 *************/
/* FREE kone **************/
__mpu_sbrk( -(int)(5*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
__ei_exp__E( tx, z, c, nb );
ei_add( z, z, tx, nb ); /* z += __ei_exp__E(z,c); */
ei_add( x, half, z, nb ); /* x = half+z; */
ei_add( eiy, x, x, nb ); /* return( x + x ); */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE prec2 *************/
/* FREE kone **************/
__mpu_sbrk( -(int)(5*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( k == 1 ) */
else
{
ei_nege( mk, k, ne ); /* mk = -k; */
if( ei_cmpe( k, prec1, ne ) <= 0 ) /* if( k <= prec1 ) */
{
ei_ldexp( tx, mk, one, ne, nb );
ei_sub( x, one, tx, nb ); /* x = one-ldexp(one,-k); */
__ei_exp__E( tx, z, c, nb );
ei_add( z, z, tx, nb ); /* z += __ei_exp__E(z,c); */
}
else if( ei_cmpe( k, prec2, ne ) < 0 ) /* if( k < prec2 ) */
{
/* x = __ei_exp__E(z,c)-ldexp(one,-k); */
__ei_exp__E( tx, z, c, nb );
ei_ldexp( tm, mk, one, ne, nb );
ei_sub( x, tx, tm, nb );
ei_add( x, x, z, nb ); /* x += z; */
ei_copy( z, one, nb ); /* z = one; */
}
else
{
__ei_exp__E( tx, z, c, nb );
ei_add( x, tx, z, nb ); /* x = __ei_exp__E(z,c)+z; */
ei_copy( z, one, nb ); /* z = one; */
}
ei_add( tx, x, z, nb );
ei_ldexp( eiy, k, tx, ne, nb );
/* return( ldexp(x+z,k) ); */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE prec2 *************/
/* FREE kone **************/
__mpu_sbrk( -(int)(5*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( x >= lntiny ) */
else
{
/* ( x <= lntiny ) */
/****************************************
EXPM1(-Infinity) must by -1.0 [exact];
****************************************/
if( !ei_isinfin( eix, nb ) )
{
/* raise the inexact flag */
/* -big# - rounded to -1.0 (inexact) */
/* return: -1.0 ( after if(){} body ) */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_copy( eiy, negone, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, /* Non change */
(__mpu_char8_t *)"expm1", __INEXACT__,
eiy, x, (EMUSHORT *)0, nb );
__STINX; /* -big# - produsing Inexact Flag */
}
ei_copy( eiy, negone, nb );
} /* End of ( x <= lntiny ) */
} /* End if( x <= lnhuge ) */
else
{
/* ( x >= lnhuge ) */
/****************************************
EXPM1(+Infinity) must by +Inf [exact];
****************************************/
if( !ei_isinfin( eix, nb ) )
{
/* raise the inexact flag */
/* +big# - overflow to +Inf */
/* return: +Infinity ( after if(){} body ) */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_infin( eiy, (unsigned)0, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную __error_no
следующим образом.
__error_no = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, /* Non change */
(__mpu_char8_t *)"expm1", __INEXACT__,
eiy, x, (EMUSHORT *)0, nb );
__STINX; /* +big# - produsing Inexact Flag */
}
ei_infin( eiy, (unsigned)0, nb );
} /* End of ( x >= lnhuge ) */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE quart *************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE prec2 *************/
/* FREE kone **************/
__mpu_sbrk( -(int)(5*ne*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_expm1() */
void ei_exp( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_exp() Работает с
internal e-type data struct.
Concepts : EI_EXP(EIX) RETURN in EIY
THE EXPONENTIAL OF EIX.
METHOD :
1. Argument Reduction: given the input EIX,
find r and integer k such that
EIX = k*ln2 + r, |r| <= 0.5*ln2 .
r will be represented as r = z+c for better
accuracy.
2. Compute EXP(r) by
EXP(r) = 1 + r + r*R1/(2-R1),
where
R1 = x - x^2*(p1+x^2*(p2+x^2*( ... ))).
3. EI_EXP(x) = 2^k * EXP(r).
EI_EXP__E() : Построение ряда:
==============================================================
Известно, что
exp(x) = 1 + x + (1/2!)*x^2 + (1/3!)*x^3 + ... .
Мы имеем:
exp(x) = 1 + x + x*R1/(2-R1);
следовательно
x*R1/(2-R1) = (1/2!)*x^2 + (1/3!)*x^3 + ... = E.
тогда
(2-R1)/x*R1 = 1/E,
2/(x*R1) - 1/x = 1/E
далее
2/(x*R1) = (x+E)/(E*x),
(x*R1)/2 = (E*x)/(x+E),
R1 = (2*E*x)/(x*(x+E)).
Это значит, что
(2/2!)*x^3 + (2/3!)*x^4 + (2/4!)*x^5 + ...
R1 = --------------------------------------------------.
x^2 + (1/2!)*x^3 + (1/3!)*x^4 + (1/4!)*x^5 + ...
Разделив полином числителя на полином знаменателя можно
получить формулы вычисления коэффициентов p1, p2, p3, ...
полинома
R1 = p1*z + p2*z^2 + p3*z^3 + ... ,
где z = x*x.
Вот все, что нужно для APPROX(), чтобы получить p1, p2, p3, ...
на интервале [0, ln(2)/2] по флгоритму Ремеза.
==============================================================
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: FLOATP.H].
SPECIAL CASES : exp(+NaN) = +NaN с выставлением DOMAIN flag;
exp(-NaN) = -NaN с выставлением DOMAIN flag;
exp(-inf) = 0 [норма];
exp(+inf) = +inf [норма];
exp(0) = 1 [норма];
Use Global Variable:
Use Functions : ei_exp__E( eiy, eix, nb ); | st-exp.c
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*z = NULL,
*hi = NULL,
*lo = NULL,
*c = NULL,
*zero = NULL,
*half = NULL,
*one = NULL,
*two = NULL,
*tx = NULL, /* temp */
*tm = NULL, /* temp */
*tk = NULL; /* temp */
EMUSHORT *k = NULL; /* for Exponent */
EMUSHORT *ln2hi, *ln2lo, *invln2, *lnhuge, *lntiny;
int np, ne;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"exp" );
/* ei_ind( eiy, nb ); *//* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* EXP(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"exp", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EXP(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"exp", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ne = internal_ne( nb ) + 1;
/*** Allocate memory for z, hi, lo, c . *******************/
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
hi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !hi )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
lo = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !lo )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
c = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !c )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for zero, half, one, two . *************/
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for tx, tm, tk . ***********************/
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tm = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tm )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tk = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tk )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for k . ********************************/
k = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !k )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ln2hi = _get_m_ln2hi_ptr( nb ); /* Service Constant */
ln2lo = _get_m_ln2lo_ptr( nb ); /* Service Constant */
lnhuge = _get_m_ln_huge_ptr( nb ); /* Service Constant */
lntiny = _get_m_ln_tiny_ptr( nb ); /* Service Constant */
invln2 = _get_m_1_ln2_ptr( nb ); /* Math Constant */
_gen_zero( zero, nb ); /* Befor test +/-inf */
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_two ( two, nb );
/* ei_copy( x, eix, nb ); */
if( ei_cmp( x, lnhuge, nb ) <= 0 )
{
if( ei_cmp( x, lntiny, nb ) >= 0 )
{
/*************************************
Argument reduction: x --> x - k*ln2
*************************************/
ei_copysign( tm, half, x, nb );
ei_mul( tx, invln2, x, nb );
ei_add( tx, tx, tm, nb );
/* begin : *********************************
k = _REALtoINT(x/ln(2)).
*******************************************/
ei_rtol_frac( k, /* k = tx; */
(EMUSHORT *)0,
tx, ne, nb ); /* k = _RtoINT(x/ln2); */
ei_ltor( tk, k, nb, ne ); /* tk = k; */
/* end : ***********************************
k = _REALtoINT(x/ln(2)).
*******************************************/
/*****************************************************
Express x-k*ln2 as hi-lo and let x = hi-lo rounded.
*****************************************************/
ei_mul( tx, tk, ln2hi, nb );
ei_sub( hi, x, tx, nb ); /* hi = x-k*ln2hi; */
ei_mul( lo, tk, ln2lo, nb );
ei_sub( x, hi, lo, nb ); /* x = hi-(lo=k*ln2lo); */
/********************************
return( 2^k*[1+x+x*c/(2+c)] );
********************************/
ei_mul( z, x, x, nb );
ei_exp__E( tx, z, nb );
ei_sub( c, x, tx, nb ); /* c = x - ei_exp__E(z); */
ei_mul( tx, x, c, nb );
ei_sub( tm, two, c, nb );
ei_div( tx, tx, tm, nb );
ei_sub( tx, lo, tx, nb );
ei_sub( tx, hi, tx, nb );
ei_add( tx, one, tx, nb );
/* return( ldexp(1.0+(hi-(lo-(x*c)/(2.0-c))), k) ); */
ei_ldexp( eiy, k, tx, ne, nb );
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( x >= lntiny ) */
else
{
/* ( x <= lntiny ) */
/****************************************
EXP(-Infinity) must by 0.0 [exact];
****************************************/
if( !ei_isinfin( eix, nb ) )
{
/* raise the inexact flag */
/* -big# - underflows to ZERO */
/* return: 0.0 ( after if(){} body ) */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_copy( eiy, zero, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, /* Non change */
(__mpu_char8_t *)"exp", __INEXACT__,
eiy, x, (EMUSHORT *)0, nb );
__STINX; /* -big# - produsing Inexact Flag */
}
ei_copy( eiy, zero, nb );
} /* End of ( x <= lntiny ) */
} /* End if( x <= lnhuge ) */
else
{
/* ( x >= lnhuge ) */
/****************************************
EXP(+Infinity) must by +Inf [exact];
****************************************/
if( !ei_isinfin( eix, nb ) )
{
/* raise the inexact flag */
/* +big# - overflows to +Inf */
/* return: +Infinity ( after if(){} body ) */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_infin( eiy, (unsigned)0, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, /* Non change */
(__mpu_char8_t *)"exp", __INEXACT__,
eiy, x, (EMUSHORT *)0, nb );
__STINX; /* +big# - produsing Inexact Flag */
}
ei_infin( eiy, (unsigned)0, nb );
} /* End of ( x >= lnhuge ) */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_exp() */
static void __ei_exp__D( EMUSHORT *eiy, EMUSHORT *eix, EMUSHORT *eic, int nb )
/***************************************************************
Return:
EXP( r=x+c ) for |c| < |x|
with no overlap (без перекрытия).
***************************************************************/
{
EMUSHORT *x = NULL,
*z = NULL,
*hi = NULL,
*lo = NULL,
*c = NULL,
*zero = NULL,
*half = NULL,
*one = NULL,
*two = NULL,
*tx = NULL, /* temp */
*tm = NULL, /* temp */
*tk = NULL; /* temp */
EMUSHORT *k = NULL; /* for Exponent */
EMUSHORT *ln2hi, *ln2lo, *invln2, *lnhuge, *lntiny;
int np, ne;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
/* ei_ind( eiy, nb ); *//* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* EXP__D(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"__ei_exp__D", __DOMAIN__,
eiy, x, eic, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EXP__D(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"__ei_exp__D", __DOMAIN__,
eiy, x, eic, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ne = internal_ne( nb ) + 1;
/*** Allocate memory for z, hi, lo, c . *******************/
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
hi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !hi )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
lo = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !lo )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
c = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !c )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for zero, half, one, two . *************/
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for tx, tm, tk . ***********************/
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tm = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tm )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tk = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tk )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for k . ********************************/
k = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !k )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ln2hi = _get_m_ln2hi_ptr( nb ); /* Service Constant */
ln2lo = _get_m_ln2lo_ptr( nb ); /* Service Constant */
lnhuge = _get_m_ln_huge_ptr( nb ); /* Service Constant */
lntiny = _get_m_ln_tiny_ptr( nb ); /* Service Constant */
invln2 = _get_m_1_ln2_ptr( nb ); /* Math Constant */
_gen_zero( zero, nb ); /* Befor test +/-inf */
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_two ( two, nb );
/* ei_copy( x, eix, nb ); */
ei_copy( c, eic, nb );
if( ei_cmp( x, lnhuge, nb ) <= 0 )
{
if( ei_cmp( x, lntiny, nb ) >= 0 )
{
/*************************************
Argument reduction: x --> x - k*ln2
*************************************/
ei_copysign( tm, half, x, nb );
ei_mul( tx, invln2, x, nb );
ei_add( tx, tx, tm, nb );
/* begin : *********************************
k = _REALtoINT(x/ln(2)).
*******************************************/
ei_rtol_frac( k, /* k = tx; */
(EMUSHORT *)0,
tx, ne, nb ); /* k = _RtoINT(x/ln2); */
ei_ltor( tk, k, nb, ne ); /* tk = k; */
/* end : ***********************************
k = _REALtoINT(x/ln(2)).
*******************************************/
/*********************************************************
Express (x+c)-k*ln2 as hi-lo and let x = hi-lo rounded.
*********************************************************/
ei_mul( tx, tk, ln2hi, nb );
ei_sub( hi, x, tx, nb ); /* hi = x-k*ln2hi; */
ei_mul( lo, tk, ln2lo, nb );
ei_sub( lo, lo, c, nb );
ei_sub( x, hi, lo, nb ); /* x = hi-(lo=k*ln2lo-c); */
/********************************
return( 2^k*[1+x+x*c/(2+c)] );
********************************/
ei_mul( z, x, x, nb );
ei_exp__E( tx, z, nb );
ei_sub( c, x, tx, nb ); /* c = x - ei_exp__E(z); */
ei_mul( tx, x, c, nb );
ei_sub( tm, two, c, nb );
ei_div( c, tx, tm, nb ); /* c = (x*c)/(2.0-c); */
ei_sub( tx, lo, c, nb );
ei_sub( tx, hi, tx, nb );
ei_add( tx, one, tx, nb );
/* return( ldexp(1.0 + (hi - (lo - c)), k) ); */
ei_ldexp( eiy, k, tx, ne, nb );
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( x >= lntiny ) */
else
{
/* ( x <= lntiny ) */
/****************************************
EXP__D(-Infinity) must by 0.0 [exact];
****************************************/
if( !ei_isinfin( eix, nb ) )
{
/* raise the inexact flag */
/* -big# - underflows to ZERO */
/* return: 0.0 ( after if(){} body ) */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_copy( eiy, zero, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, /* Non change */
(__mpu_char8_t *)"__ei_exp__D", __INEXACT__,
eiy, x, eic, nb );
__STINX; /* -big# - produsing Inexact Flag */
}
ei_copy( eiy, zero, nb );
} /* End of ( x <= lntiny ) */
} /* End if( x <= lnhuge ) */
else
{
/* ( x >= lnhuge ) */
/****************************************
EXP__D(+Infinity) must by +Inf [exact];
****************************************/
if( !ei_isinfin( eix, nb ) )
{
/* raise the inexact flag */
/* +big# - overflows to +Inf */
/* return: +Infinity ( after if(){} body ) */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_infin( eiy, (unsigned)0, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, /* Non change */
(__mpu_char8_t *)"__ei_exp__D", __INEXACT__,
eiy, x, eic, nb );
__STINX; /* +big# - produsing Inexact Flag */
}
ei_infin( eiy, (unsigned)0, nb );
} /* End of ( x >= lnhuge ) */
/* FREE x *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE c *****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE tm ****************/
/* FREE tk ****************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of __ei_exp__D() */
void ei_atan2( EMUSHORT *eic, EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_atan2() Работает с
internal e-type data struct.
Concepts : ATAN2( EIY,EIX ) RETURN ARG( EIX+iEIY).
METHOD :
1. Reduce y to positive
by atan2(y,x)=-atan2(-y,x).
2. Reduce x to positive by
(if x and y are unexceptional):
ARG(x+iy) = arctan(y/x) ... if x>0,
ARG(x+iy) = pi-arctan[y/(-x)] ... if x<0,
3. According to the integer k=4t+0.25
truncated, t=y/x, the argument
is further reduced to one of the following
intervals and the arctangent of y/x
is evaluated by the corresponding formula:
[0,7/16] atan(y/x) = t - t^3*(a1+t^2*(a2+...(a10+t^2*a11)...)
[7/16,11/16] atan(y/x) = atan(1/2) + atan( (y-x/2)/(x+y/2) )
[11/16,19/16] atan(y/x) = atan( 1 ) + atan( (y-x)/(x+y) )
[19/16,39/16] atan(y/x) = atan(3/2) + atan( (y-1.5x)/(x+1.5y) )
[39/16,INF] atan(y/x) = atan(INF) + atan( -x/y )
EI_ATAN2__A() : Построение ряда:
==============================================================
Известно, что
atan(x) = x - (1/3)*x^3 + (1/5)*x^5 - (1/7)*x^7 + ... .
Мы имеем следующий способ
atan(t) = t - t*(z*a1+z^2*a2+z^3*a3...) = t - t*A,
где
z = t*t.
Следовательно
a1 = +1/3; a2 = -1/5; a3 = +1/7; a4 = -1/9; ... .
Вот все, что нужно для APPROX(), чтобы получить a1, a2, a3, ...
на интервале [-7/16, +7/16] по флгоритму Ремеза.
==============================================================
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: FLOATP.H].
Atan2(y,x) returns (PI/pi) * the exact ARG(x+iy)
nearly rounded, where pi is rounded value
of exact PI.
NOTE : The coefficient A's
[ in ei_atan2__A()]
are obtained by a special Remez algorithm.
==========================================
В INTERNET я нашел следующие алгоритмы:
409 cacm 355 356 14 5 May 1971 e2 A60
------------------------------------------
H. Schmitt;
Discrete {Chebychev} Curve Fit
approximation;Chebyshev approximation;
Chebyshev curve fitting;
+Chebyshev polynomial;
curve approximation;curve fitting;
exchange algorithm;
+polynomial approximation;Remez algorithm;
501 toms 95 97 2 1 March 1976 e2 F K2
---------------------------------------------
J. C. Simpson;
{FORTRAN} Translation of Algorithm 409
Discrete {Chebyshev} Curve Fit
approximation;polynomial approximation;
exchange algorithm;
+Chebyshev approximation;
polynomial approximation;
R,toms,95,4,1,March,1978,F. Futrell;
последний из которых я перевел на "С", затем
на язык операций повышенной разрядности.
==========================================
SPECIAL CASES :
Notations:
atan2(y,x) == ARG (x+iy) == ARG(x,y).
ARG( NAN, (anything) ) is NaN;
ARG( (anything), NaN ) is NaN;
ARG(+(anything but NaN), +-0) is +-0 ;
ARG(-(anything but NaN), +-0) is +-PI;
ARG( 0, +-(anything but 0 and NaN) ) is +-PI/2;
ARG(+INF,+-(anything but INF and NaN) ) is +-0 ;
ARG(-INF,+-(anything but INF and NaN) ) is +-PI;
ARG(+INF,+-INF ) is +- PI/4;
ARG(-INF,+-INF ) is +-3PI/4;
ARG(
(anything but,0,NaN,and INF),+-INF
) is +-PI/2;
Use Global Variable:
Use Functions : ei_atan2__A( eiy, eix, nb ); | st-atan2.c
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eiy; - указатель на
internal e-type
data struct.
SOURCE;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*y = NULL,
*z = NULL,
*hi = NULL,
*lo = NULL,
*t = NULL,
*signy = NULL,
*signx = NULL,
*zero = NULL,
*one = NULL,
*two = NULL,
*small = NULL,
*big = NULL,
*tx = NULL, /* temp */
*ty = NULL; /* temp */
EMUSHORT *k = NULL, /* for Exponent */
*m = NULL, /* for Exponent */
*kt = NULL,
*mk = NULL,
*prec1 = NULL,
*mprec2 = NULL;
EMUSHORT *pi, *pi_2, *pi_4, *pi3_4;
EMUSHORT *athfhi, *athflo, *at1fhi, *at1flo;
EMUSHORT *c39_16, *c1_16;
EMUSHORT prec, j;
int np, ne;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"atan2" );
/* ei_ind( eiy, nb ); *//* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x, y . *****************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
y = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !y )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( y, eiy, nb ); /* temp for _mtherr() */
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX, EIY.
***************************/
/*
if x or y is InD ATAN2(x,y) must by InD.
******************************************/
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eic, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"atan2", __DOMAIN__,
eic, y, x, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
/* FREE y *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_isind( eiy, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eic, eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"atan2", __DOMAIN__,
eic, y, x, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
/* FREE y *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*
if x or y is NaN ATAN2(x,y) must by NaN.
******************************************/
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eic, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"atan2", __DOMAIN__,
eic, y, x, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
/* FREE y *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_isnans( eiy, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eic, eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"atan2", __DOMAIN__,
eic, y, x, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
/* FREE y *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ne = internal_ne( nb ) + 1;
/*** Allocate memory for z, hi, lo, t, signy, signx . *******/
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
hi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !hi )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
lo = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !lo )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
signy = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !signy )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
signx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !signx )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for zero, one, two, small, big . *******/
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
small = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !small )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
big = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !big )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
__mpu_sbrk( -(int)(12*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for tx, ty . ***************************/
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
__mpu_sbrk( -(int)(13*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ty = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ty )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(14*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for k, m, kt, mk, prec1, mprec2 . ******/
k = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !k )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
m = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !m )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
kt = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !kt )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
mk = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !mk )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
prec1 = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !prec1 )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
__mpu_sbrk( -(int)(4*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
mprec2 = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !mprec2 )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
/* FREE prec1 *************/
__mpu_sbrk( -(int)(5*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_zero( zero, nb );
_gen_one ( one, nb );
_gen_two ( two, nb );
/*********************************************
small: 1.0 + small^2 == 1.0;
big : big = 1/(small^2);
*********************************************/
ei_sqrt( small, _get_epsilon_ptr( nb ), nb );
ei_div( big, one, _get_epsilon_ptr( nb ), nb );
pi = _get_m_pi_ptr ( nb );
pi_2 = _get_m_pi_2_ptr ( nb );
pi_4 = _get_m_pi_4_ptr ( nb );
pi3_4 = _get_m_3pi_4_ptr( nb );
/* Service Constants */
athfhi = _get_m_athfhi_ptr( nb );
athflo = _get_m_athflo_ptr( nb );
at1fhi = _get_m_at1fhi_ptr( nb );
at1flo = _get_m_at1flo_ptr( nb );
c39_16 = _get_m_39_16_ptr ( nb );
c1_16 = _get_m_1_16_ptr ( nb );
/* ei_copy( y, eiy, nb ); */
/* ei_copy( x, eix, nb ); */
/************************************
Copy down the sign of EIY and EIX.
************************************/
ei_copysign( signy, one, y, nb );
ei_copysign( signx, one, x, nb );
/**************************
If x is 1.0, goto begin.
**************************/
if( ei_cmp( x, one, nb ) == 0 )
{
ei_copysign( y, y, one, nb );
ei_copy( t, y, nb );
if( !ei_isinfin( t, nb ) ) goto begin;
}
/*************
If y is 0.0
*************/
if( ei_cmp( y, zero, nb ) == 0 )
{
if( ei_cmp( signx, one, nb ) == 0 )
ei_copy( eic, y, nb );
else
ei_copysign( eic, pi, signy, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE mprec2 ************/
__mpu_sbrk( -(int)(6*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*************
If x is 0.0
*************/
if( ei_cmp( x, zero, nb ) == 0 )
{
ei_copysign( eic, pi_2, signy, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE mprec2 ************/
__mpu_sbrk( -(int)(6*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/********************
When x is Infinity
********************/
if( ei_isinfin( x, nb ) )
{
if( ei_isinfin( y, nb ) )
{
if( ei_cmp( signx, one, nb ) == 0 )
ei_copysign( eic, pi_4, signy, nb );
else
ei_copysign( eic, pi3_4, signy, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE mprec2 ************/
__mpu_sbrk( -(int)(6*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
if( ei_cmp( signx, one, nb ) == 0 )
ei_copysign( eic, zero, signy, nb );
else
ei_copysign( eic, pi, signy, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE mprec2 ************/
__mpu_sbrk( -(int)(6*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( x == Infinity ) */
/********************
When y is Infinity
********************/
if( ei_isinfin( y, nb ) )
{
ei_copysign( eic, pi_2, signy, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE mprec2 ************/
__mpu_sbrk( -(int)(6*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( y == Infinity ) */
/*************
Compute y/x
*************/
/* prec1 = NSBITS(nb); mprec2 = -(3/2)*NSBITS(nb); */
prec = NSBITS(nb);
ei_cpye_unpack( prec1, (EMUSHORT *)&prec, ne, 1 );
prec /= 2;
ei_cpye_unpack( mprec2, (EMUSHORT *)&prec, ne, 1 );
ei_adde( mprec2, mprec2, prec1, ne );
ei_nege( mprec2, mprec2, ne );
ei_copysign( y, y, one, nb );
ei_copysign( x, x, one, nb );
ei_logb( k, y, ne, nb ); /* k = logb( y ); */
ei_logb( kt, x, ne, nb ); /* kt = logb( x ); */
ei_sube( m, k, kt, ne ); /* m = (k=logb(y)) - logb(x); */
ei_nege( mk, k, ne ); /* mk = -k; */
if( ei_cmpe( m, prec1, ne ) > 0 )
{
ei_add( t, big, big, nb ); /* t = big+big; */
}
else if( ei_cmpe( m, mprec2, ne ) < 0 )
{
ei_div( t, y, x, nb ); /* t = y/x; */
}
else
{
ei_div( t, y, x, nb ); /* t = y/x; */
ei_ldexp( y, mk, y, ne, nb ); /* y = ldexp( y, -k ); */
ei_ldexp( x, mk, x, ne, nb ); /* x = ldexp( x, -k ); */
}
/*************************************************************
BEGIN ARGUMENT REDUCTION:
*************************************************************/
begin:
if( ei_cmp( t, c39_16, nb ) < 0 ) /* if( t < 39/16 ) */
{
/* truncate 4(t+1/16) to integer for branching */
ei_add( tx, t, c1_16, nb );
ei_mul( tx, tx, two, nb );
ei_mul( tx, tx, two, nb );
ei_rtol_frac( (EMUSHORT *)&j, /* j = 4*(t+0.0625); */
(EMUSHORT *)0, tx, 1, nb );
switch( j )
{
/* t is in [0, 7/16] */
case 0:
case 1:
if( ei_cmp( t, small, nb ) < 0 )
{
if( ei_cmp( signx, zero, nb ) > 0 )
{
ei_copysign( eic, t, signy, nb );
}
else
{
ei_sub( t, pi, t, nb );
ei_copysign( eic, t, signy, nb );
}
/* raise the inexact flag */
/* big+small */
ei_copy( y, eiy, nb ); /* for &eiy == &eic */
ei_copy( x, eix, nb ); /* for &eix == &eic */
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* Non change */
(__mpu_char8_t *)"atan2", __INEXACT__,
eic, y, x, nb );
__STINX; /* produsing Inexact Flag */
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE mprec2 ************/
__mpu_sbrk( -(int)(6*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_copy( hi, zero, nb );
ei_copy( lo, zero, nb );
break;
/* t is in [7/16, 11/16] */
case 2:
ei_copy( hi, athfhi, nb );
ei_copy( lo, athflo, nb );
ei_add( z, x, x, nb ); /* z = x+x; */
ei_add( ty, y, y, nb );
ei_sub( ty, ty, x, nb );
ei_add( tx, z, y, nb );
ei_div( t, ty, tx, nb ); /* t = ((y+y)-x)/(z+y); */
break;
/* t is in [11/16, 19/16] */
case 3:
case 4:
ei_copy( hi, pi_4, nb );
ei_copy( lo, zero, nb );
ei_sub( ty, y, x, nb );
ei_add( tx, x, y, nb );
ei_div( t, ty, tx, nb ); /* t = (y-x)/(x+y); */
break;
/* t is in [19/16, 39/16] */
default:
ei_copy( hi, at1fhi, nb );
ei_copy( lo, at1flo, nb );
ei_sub( z, y, x, nb ); /* z = y-x; */
ei_add( ty, y, y, nb );
ei_add( y, ty, y, nb ); /* y = y+y+y; */
ei_add( t, x, x, nb ); /* t = x+x; */
ei_add( ty, z, z, nb );
ei_sub( ty, ty, x, nb );
ei_add( tx, t, y, nb );
ei_div( t, ty, tx, nb ); /* t = ((z+z)-x)/(t+y); */
break;
} /* End of switch( j ) */
} /* End if( t < 39/16 ) */
else
{
ei_copy( hi, pi_2, nb );
ei_copy( lo, zero, nb );
/* t is in [39/16, big] */
if( ei_cmp( t, big, nb ) <= 0 )
{
ei_copy( tx, x, nb );
ei_neg( tx, nb );
ei_div( t, tx, y, nb ); /* t = -x/y; */
}
/* t is in [big, Infinity] */
else
{
/* raise the inexact flag */
/* big+small */
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* Non change */
(__mpu_char8_t *)"atan2", __INEXACT__,
(EMUSHORT *)0, eiy, eix, nb );
__STINX; /* produsing Inexact Flag */
ei_copy( t, zero, nb );
}
}
/*************************************************************
:END OF ARGUMENT REDUCTION.
*************************************************************/
/*************************************************************
COMPUTE ATAN(t) FOR t in [-7/16, 7/16].
*************************************************************/
ei_mul( z, t, t, nb );
ei_atan2__A( tx, z, nb );
ei_mul( z, t, tx, nb );
ei_sub( z, lo, z, nb );
ei_add( z, z, t, nb );
ei_add( z, z, hi, nb );
if( ei_cmp( signx, zero, nb ) > 0 )
{
ei_copysign( eic, z, signy, nb );
}
else
{
ei_sub( z, pi, z, nb );
ei_copysign( eic, z, signy, nb );
}
/* FREE x *****************/
/* FREE y *****************/
/* FREE z *****************/
/* FREE hi ****************/
/* FREE lo ****************/
/* FREE t *****************/
/* FREE signy *************/
/* FREE signx *************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE two ***************/
/* FREE small *************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(15*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE k *****************/
/* FREE m *****************/
/* FREE kt ****************/
/* FREE mk ****************/
/* FREE prec1 *************/
/* FREE mprec2 ************/
__mpu_sbrk( -(int)(6*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End of ei_atan2() */
void ei_atan( EMUSHORT *eiy, EMUSHORT *eix, int nb )
{
EMUSHORT *one = NULL;
int np;
np = internal_np( nb );
/*** Allocate memory for one . ******************************/
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
return;
}
/************************************************************/
_gen_one( one, nb );
ei_atan2( eiy, eix, one, nb );
/* FREE one ***************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_atan() */
void ei_sinh( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_sinh() Работает с
internal e-type data struct.
Concepts : SINH(EIX) RETURN THE HYPERBOLIC SINE OF EIX.
METHOD :
1. Reduce x to non-negative by
sinh(-x) = - sinh(x).
2.
expm1(x) + expm1(x)/(expm1(x)+1)
0 <= x <= lnovfl: sinh(x) = --------------------------------;
2
lnovfl <=x<= lnovfl+ln2: sinh(x) = expm1(x)/2 (avoid overflow);
lnovfl+ln2 < x < INF: overflow to INF;
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: FLOATP.H].
NOTE :
SPECIAL CASES : sinh(-InD) = -InD с выставлением DOMAIN flag;
sinh(+NaN) = +NaN с выставлением DOMAIN flag;
sinh(-NaN) = -NaN с выставлением DOMAIN flag;
sinh(-inf) = -Inf [норма];
sinh(+inf) = +inf [норма];
sinh(+big#)= +Inf с выставлением OVERFLOW flag;
sinh(-big#)= -Inf с выставлением OVERFLOW flag;
sinh(0) = 0 [норма];
Use Global Variable:
Use Functions : ei_expm1( eiy, eix, nb ); | this file
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*t = NULL,
*sign = NULL,
*ln2p = NULL,
*one = NULL,
*half = NULL,
*tr = NULL; /* temp */
EMUSHORT *max = NULL; /* for MAX_BIN_Exponent */
EMUSHORT *ln2, *lnovfl;
int np, ne;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"sinh" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* SINH(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"sinh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* SINH(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"sinh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*
SINH(+Infinity) must by +Infinity;
SINH(-Infinity) must by -Infinity;
*/
if( ei_isinfin( eix, nb ) )
{
/* Normal Exit */
ei_copy( eiy, eix, nb );
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ne = internal_ne( nb ) + 1;
/*** Allocate memory for t, sign, ln2p, one, half, tr . *****/
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
sign = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !sign )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ln2p = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ln2p )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE ln2p **************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE ln2p **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE ln2p **************/
/* FREE one ***************/
/* FREE half **************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for max . ******************************/
max = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !max )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE ln2p **************/
/* FREE one ***************/
/* FREE half **************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ln2 = _get_m_ln2_ptr( nb );
ei_cpye( max, _get_max_2_exp_ptr( nb ), ne, ne );
_gen_half( half, nb );
_gen_one ( one, nb );
/* Service Constant: */
lnovfl = _get_m_ln_huge_ptr( nb );
ei_add( ln2p, lnovfl, ln2, nb );
/* ei_copy( x, eix, nb ); */
ei_copysign( sign, one, x, nb );
ei_copysign( x, x, one, nb );
if( ei_cmp( x, lnovfl, nb ) < 0 )
{
ei_expm1( t, x, nb );
/* return( copysign((t+t/(one+t))*half, sign) ); */
ei_add( tr, one, t, nb );
ei_div( tr, t, tr, nb );
ei_add( tr, t, tr, nb );
ei_mul( tr, tr, half, nb );
ei_copysign( eiy, tr, sign, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE ln2p **************/
/* FREE one ***************/
/* FREE half **************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE max ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
if( ei_cmp( x, ln2p, nb ) <= 0 ) /* if( x <= lnovfl+ln2 ) */
{
/*
Substract x by ln(2^(max+1)) and return 2^max*exp(x)
to avoid unnecessary overflow.
******************************************************/
ei_sub( tr, x, lnovfl, nb );
ei_expm1( tr, tr, nb );
ei_add( tr, one, tr, nb );
ei_ldexp( tr, max, tr, ne, nb );
ei_copysign( eiy, tr, sign, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE ln2p **************/
/* FREE one ***************/
/* FREE half **************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE max ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* SINH(+-big#) overflow to +-Infinity */
/* return: +-Infinity */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_expm1( tr, x, nb );
ei_mul( eiy, tr, sign, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную __error_no
следующим образом.
__error_no = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"sinh", __OVERFLOW__,
eiy, x, (EMUSHORT *)0, nb );
__STOVF; /* +-big# - produsing Overflow Flag */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE ln2p **************/
/* FREE one ***************/
/* FREE half **************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE max ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if/else( x <= lnovfl+ln2 ) */
} /* Enf if/else( x < lnovfl ) */
} /* End of ei_sinh() */
void ei_cosh( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_cosh() Работает с
internal e-type data struct.
Concepts : COSH(EIX) RETURN THE HYPERBOLIC COSINE OF EIX.
METHOD :
1. Replace x by |x|.
2.
0 <= x <= ln2/2 :
[ exp(x) - 1 ]^2
cosh(x) = 1 + -------------------;
2*exp(x)
ln2/2 <= x <= thovfl :
exp(x) + 1/exp(x)
cosh(x) = -------------------;
2
thovfl <= x <= lnovfl: cosh(x) = exp(x)/2;
lnovfl<=x<=lnovfl+ln2: cosh(x) = exp(x)/2
(avoid overflow);
ln2+lnovfl < x < INF : overflow to INF;
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: mpu-floatp.h].
NOTE : thovfl = log1p(2.0/EPSILON-2.0) / 2.0;
[small == EPSILON].
SPECIAL CASES : cosh(-InD) = -InD с выставлением DOMAIN flag;
cosh(+NaN) = +NaN с выставлением DOMAIN flag;
cosh(-NaN) = -NaN с выставлением DOMAIN flag;
cosh(-inf) = +Inf [норма];
cosh(+inf) = +Inf [норма];
cosh(+big#)= +Inf с выставлением OVERFLOW flag;
cosh(-big#)= +Inf с выставлением OVERFLOW flag;
cosh(0) = 1.0 [норма];
Use Global Variable:
Use Functions : ei_exp( eiy, eix, nb ); | this file
__ei_exp__E( eiy, eix, eic, nb ); | this file
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*t = NULL,
*ln2p = NULL,
*ln2_2 = NULL,
*zero = NULL,
*half = NULL,
*one = NULL,
*two = NULL,
*tr = NULL; /* temp */
EMUSHORT *max = NULL; /* for MAX_BIN_Exponent */
EMUSHORT *ln2, *lnovfl, *thovfl, *small;
int np, ne;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"cosh" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* COSH(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"cosh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* COSH(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"cosh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*
COSH(+Infinity) must by +Infinity;
COSH(-Infinity) must by -Infinity;
*/
if( ei_isinfin( eix, nb ) )
{
/* Normal Exit */
ei_copy( eiy, eix, nb );
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ne = internal_ne( nb ) + 1;
/*** Allocate memory for t, ln2p, ln2_2, tr . ***************/
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ln2p = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ln2p )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ln2_2 = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ln2_2 )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for zero, half, one, two . *************/
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
/* FREE half **************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for max . ******************************/
max = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !max )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ln2 = _get_m_ln2_ptr( nb );
small = _get_epsilon_ptr( nb );
ei_cpye( max, _get_max_2_exp_ptr( nb ), ne, ne );
_gen_zero( zero, nb );
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_two ( two, nb );
/* Service Constant: */
lnovfl = _get_m_ln_huge_ptr( nb );
thovfl = _get_m_thovfl_ptr( nb );
ei_add( ln2p, lnovfl, ln2, nb );
ei_div( ln2_2, ln2, two, nb );
ei_copysign( x, x, one, nb );
if( ei_cmp( x, thovfl, nb ) <= 0 )
{
if( ei_cmp( x, ln2_2, nb ) < 0 )
{
if( ei_cmp( x, small, nb ) < 0 )
{
ei_add( eiy, one, x, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE max ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
__ei_exp__E( tr, x, zero, nb );
ei_add( t, x, tr, nb ); /* t = x+__ei_exp__E(x,0.0); */
ei_add( x, t, t, nb ); /* x = t+t; */
ei_add( tr, two, x, nb );
ei_div( tr, t, tr, nb );
ei_mul( tr, t, tr, nb );
ei_add( eiy, one, tr, nb ); /* return(one+t*t/(2.0+x)); */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE max ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
}
else
{
/*******************************
for x lies in [ln2/2, thovfl]
*******************************/
ei_exp( t, x, nb );
/* return( (t+one/t)*half ); */
ei_div( tr, one, t, nb );
ei_add( tr, t, tr, nb );
ei_mul( eiy, tr, half, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE max ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( x <= thovfl ) */
/* if( lnovfl <= x && x <= lnovfl+ln2 ) */
if( (ei_cmp( lnovfl, x, nb ) <= 0) &&
(ei_cmp( x, ln2p, nb ) <= 0) )
{
/*
Substract x by ln(2^(max+1)) and return 2^max*exp(x)
to avoid unnecessary overflow.
******************************************************/
ei_sub( tr, x, lnovfl, nb );
ei_exp( tr, tr, nb );
ei_ldexp( eiy, max, tr, ne, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE max ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
ei_copy( t, eix, nb ); /* for &eiy == &eix */
ei_exp( tr, x, nb );
/* new version: */ ei_mul( eiy, tr, half, nb );
if( ei_cmp( x, ln2p, nb ) > 0 )
{
/* for large (x != +-Infinity), cosh(x) = exp(x)/2; */
/* COSH(+-big#) overflow to +-Infinity */
/* return: +-Infinity ( after if(){} body ) */
/* previus version: ei_mul( eiy, tr, half, nb );
for _mtherr() */
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, /* previus version: No change */
(__mpu_char8_t *)"cosh", __OVERFLOW__,
eiy, t, (EMUSHORT *)0, nb );
__STOVF; /* +-big# - produsing Overflow Flag */
}
/* previus version: ei_mul( eiy, tr, half, nb ); */
/* FREE x *****************/
/* FREE t *****************/
/* FREE ln2p **************/
/* FREE ln2_2 *************/
/* FREE tr ****************/
/* FREE zero **************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE max ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if/else( lnovfl <= x && x <= lnovfl+ln2 ) */
} /* End of ei_cosh() */
void ei_tanh( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_tanh() Работает с
internal e-type data struct.
Concepts : TANH(EIX) RETURN THE HYPERBOLIC TANGENT OF EIX.
METHOD :
1. Reduce x to non-negative by
tanh(-x) = -tanh(x).
2.
0<x<=small : tanh(x) = x; [inexact];
-expm1(-2x)
small<x<=1 : tanh(x) = ----------------;
expm1(-2x) + 2
2
1<=x<=thovfl : tanh(x) = 1 - ---------------;
expm1(2x) + 2
thovfl<x<=INF: tanh(x) = 1.; [inexact];
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: FLOATP.H].
NOTE : thovfl = log1p(2.0/EPSILON-2.0) / 2.0;
[1+small^2 == 1].
SPECIAL CASES : tanh(-InD) = -InD с выставлением DOMAIN flag;
tanh(+NaN) = +NaN с выставлением DOMAIN flag;
tanh(-NaN) = -NaN с выставлением DOMAIN flag;
tanh(+inf) = +1.0 [норма];
tanh(-inf) = -1.0 [норма];
tanh(+big#)= +1.0 с выставлением INEXACT flag;
tanh(-big#)= -1.0 с выставлением INEXACT flag;
tanh(0) = 0.0 [норма];
Use Global Variable:
Use Functions : ei_exp( eiy, eix, nb ); | this file
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*t = NULL,
*sign = NULL,
*small = NULL,
*half = NULL,
*one = NULL,
*two = NULL,
*tr = NULL; /* temp */
EMUSHORT *thovfl;
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"tanh" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* TANH(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"tanh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* TANH(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"tanh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for t, sign, small, tr . ***************/
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
sign = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !sign )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
small = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !small )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for half, one, two . *******************/
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
/* FREE tr ****************/
/* FREE half **************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_sqrt( small, _get_epsilon_ptr( nb ), nb );
_gen_half( half, nb );
_gen_one ( one, nb );
_gen_two ( two, nb );
/* Service Constant: */
thovfl = _get_m_thovfl_ptr( nb );
ei_copysign( sign, one, x, nb );
ei_copysign( x, x, one, nb );
/*
TANH(+Infinity) must by +1.0;
TANH(-Infinity) must by -1.0;
*/
if( ei_isinfin( eix, nb ) )
{
/* Normal Exit */
ei_copy( eiy, sign, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_cmp( x, thovfl, nb ) < 0 )
{
if( ei_cmp( x, one, nb ) > 0 )
{
/* return( copysign( one-two/(expm1(x+x)+two), sign ) ); */
ei_add( tr, x, x, nb );
ei_expm1( tr, tr, nb );
ei_add( tr, tr, two, nb );
ei_div( tr, two, tr, nb );
ei_sub( tr, one, tr, nb );
ei_copysign( eiy, tr, sign, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
if( ei_cmp( x, small, nb ) > 0 )
{
/* t = -expm1(-(x+x)); */
ei_add( tr, x, x, nb );
ei_neg( tr, nb );
ei_expm1( tr, tr, nb );
ei_neg( tr, nb );
ei_copy( t, tr, nb );
/* return( copysign( t/(two-t), sign ) ); */
ei_sub( tr, two, t, nb );
ei_div( tr, t, tr, nb );
ei_copysign( eiy, tr, sign, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
ei_copy( t, eix, nb ); /* for &eiy == &eix */
/* raise the inexact flag for non-zero x*/
/* return: +-x */
ei_copysign( eiy, x, sign, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* Non change */
(__mpu_char8_t *)"tanh", __INEXACT__,
eiy, t, (EMUSHORT *)0, nb );
__STINX; /* produsing Inexact Flag */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if/else( x > small ) */
} /* End if/else( x > one ) */
}
else
{
ei_copy( t, eix, nb ); /* for &eiy == &eix */
/* TANH(+-big#) round to +-1.0 */
/* raise the inexact flag */
/* return: +-1.0 */
ei_copy( eiy, sign, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* Non change */
(__mpu_char8_t *)"tanh", __INEXACT__,
eiy, t, (EMUSHORT *)0, nb );
__STINX; /* produsing Inexact Flag */
/* FREE x *****************/
/* FREE t *****************/
/* FREE sign **************/
/* FREE small *************/
/* FREE tr ****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE two ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* Enf if/else( x < thovfl ) */
} /* End of ei_tanh() */
void ei_asinh( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_asinh() Работает с
internal e-type data struct.
Concepts : ASINH(X) RETURN
THE INVERSE HYPERBOLIC SINE OF EIX.
METHOD : Based on
asinh(x) = sign(x)*log[ |x|+sqrt(x*x+1) ]
we have
asinh(x) = x if(1+x*x=1),
= sign(x)*(log1p(x)+ln2)
if(sqrt(1+x*x)=x), else
= sign(x)*
log1p(|x|+
|x|/
(1/|x|+sqrt(1+(1/|x|)^2)) ).
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: mpu-floatp.h].
NOTE :
SPECIAL CASES : asinh(-InD) = -InD с выставлением DOMAIN flag;
asinh(+NaN) = +NaN с выставлением DOMAIN flag;
asinh(-NaN) = -NaN с выставлением DOMAIN flag;
Use Global Variable:
Use Functions : ei_log1p( eiy, eix, nb ); | this file
ei_sqrt( eiy, eix, nb ); | mpu-real.c
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*t = NULL,
*s = NULL,
*small = NULL,
*big = NULL,
*one = NULL,
*ten = NULL,
*tr = NULL; /* temp */
EMUSHORT *ln2hi, *ln2lo;
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"asinh" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* ASINH(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"asinh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* ASINH(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"asinh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for t, s, small, big, one, ten, tr . ***/
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
s = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !s )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
small = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !small )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
big = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !big )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE small *************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE small *************/
/* FREE big ***************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ten = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ten )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE small *************/
/* FREE big ***************/
/* FREE one ***************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE small *************/
/* FREE big ***************/
/* FREE one ***************/
/* FREE ten ***************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_one ( one, nb );
_gen_ten ( ten, nb );
/*********************************************
small: 1.0 + small^2 == 1.0;
big : big = 1/(small^2); & (big+1) == big;
*********************************************/
ei_sqrt( small, _get_epsilon_ptr( nb ), nb );
ei_div( big, one, _get_epsilon_ptr( nb ), nb );
ei_mul( big, big, ten, nb );
/* Service Constant: */
ln2hi = _get_m_ln2hi_ptr( nb );
ln2lo = _get_m_ln2lo_ptr( nb );
ei_copysign( t, x, one, nb );
if( ei_cmp( t, small, nb ) > 0 )
{
if( ei_cmp( t, big, nb ) < 0 )
{
ei_div( s, one, t, nb ); /* s = one/t; */
/* return( copysign( log1p( t+t/(s+sqrt(one+s*s)) ), x ) ); */
ei_mul( tr, s, s, nb );
ei_add( tr, one, tr, nb );
ei_sqrt( tr, tr, nb );
ei_add( tr, s, tr, nb );
ei_div( tr, t, tr, nb );
ei_add( tr, t, tr, nb );
ei_log1p( tr, tr, nb );
ei_copysign( eiy, tr, x, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE small *************/
/* FREE big ***************/
/* FREE one ***************/
/* FREE ten ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* ( |x| > big ) */
ei_log1p( tr, t, nb );
ei_add( s, tr, ln2lo, nb ); /* s = log1p(t)+ln2lo; */
ei_add( tr, s, ln2hi, nb );
/* return( copysign(s+ln2hi,x) ); */
ei_copysign( eiy, tr, x, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE small *************/
/* FREE big ***************/
/* FREE one ***************/
/* FREE ten ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
}
else
{
/* ( |x| < small ) */
ei_copy( eiy, x, nb ); /* return( x ); */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE small *************/
/* FREE big ***************/
/* FREE one ***************/
/* FREE ten ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End of ei_asinh() */
void ei_acosh( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_acosh() Работает с
internal e-type data struct.
Concepts : ASINH(X) RETURN
THE INVERSE HYPERBOLIC COSINE OF EIX.
METHOD : Based on
acosh(x) = log[ x + sqrt(x*x-1) ]
we have
acosh(x) = log1p(x)+ln2 if(x>big), else
= log1p(
sqrt(x-1) *
( sqrt(x-1) + sqrt(x+1) )
).
These formulae avoid the over/underflow
complication.
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: mpu-floatp.h].
NOTE :
SPECIAL CASES : acosh(-InD) = -InD с выставлением DOMAIN flag;
acosh(+NaN) = +NaN с выставлением DOMAIN flag;
acosh(-NaN) = -NaN с выставлением DOMAIN flag;
acosh( x<1 ) = -Ind с выставлением DOMAIN flag;
Use Global Variable:
Use Functions : ei_log1p( eiy, eix, nb ); | this file
ei_sqrt( eiy, eix, nb ); | mpu-real.c
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*t = NULL,
*big = NULL,
*one = NULL,
*ten = NULL,
*tr = NULL; /* temp */
EMUSHORT *ln2hi, *ln2lo;
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"acosh" );
/* ei_ind( eiy, nb ); *//* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* ACOSH(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"acosh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* ACOSH(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"acosh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for t, big, one, ten, tr . *************/
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
big = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !big )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE big ***************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ten = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ten )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE big ***************/
/* FREE one ***************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE big ***************/
/* FREE one ***************/
/* FREE ten ***************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_one ( one, nb );
/* ACOSH( x < 1 ) must by InD */
if( ei_cmp( eix, one, nb ) < 0 )
{
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"acosh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* (x < 1) - produsing Domain Flag */
/* FREE x *****************/
/* FREE t *****************/
/* FREE big ***************/
/* FREE one ***************/
/* FREE ten ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
_gen_ten ( ten, nb );
/*********************************************
big : big = 1/(small^2); & (big+1) == big;
*********************************************/
ei_div( big, one, _get_epsilon_ptr( nb ), nb );
ei_mul( big, big, ten, nb );
/* Service Constant: */
ln2hi = _get_m_ln2hi_ptr( nb );
ln2lo = _get_m_ln2lo_ptr( nb );
/* ei_copy( x, eix, nb ); */
if( ei_cmp( x, big, nb ) > 0 )
{
/* return( log1p(x) + ln(2) ) if x is large. */
ei_log1p( t, x, nb );
ei_add( t, t, ln2lo, nb ); /* t = log1p(x)+ln2lo; */
ei_add( eiy, t, ln2hi, nb ); /* return( t+ln2hi ); */
/* FREE x *****************/
/* FREE t *****************/
/* FREE big ***************/
/* FREE one ***************/
/* FREE ten ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_sub( tr, x, one, nb );
ei_sqrt( t, tr, nb ); /* t = sqrt(x-1.0); */
ei_add( tr, x, one, nb );
ei_sqrt( tr, tr, nb );
ei_add( tr, t, tr, nb );
ei_mul( tr, t, tr, nb );
ei_log1p( eiy, tr, nb ); /* return( log1p( t*(t+sqrt(x+1.0)) ) ); */
/* FREE x *****************/
/* FREE t *****************/
/* FREE big ***************/
/* FREE one ***************/
/* FREE ten ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End of ei_acosh() */
void ei_atanh( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_atanh() Работает с
internal e-type data struct.
Concepts : ATANH(X) RETURN
THE INVERSE HYPERBOLIC TANGENT OF EIX.
METHOD : Return
1 2x x
atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------);
2 1 - x 1 - x
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: mpu-floatp.h].
NOTE : Для r в интервале [0, thovfl], проделаем
следующее:
t = tanh ( r );
t = atanh( t ).
При этом для r в интервале [1.0, thovfl]
с увеличением r растет и величина разности
(t-r) чего в принципе не должно быть.
СЛЕДОВАТЕЛЬНО ПОКА МЫ МОЖЕМ РЕКОМЕНДОВАТЬ
проводить такие опыты лишь на промежутке
[-1, 1].
SPECIAL CASES : atanh(-InD) = -InD с выставлением DOMAIN flag;
atanh(+NaN) = +NaN с выставлением DOMAIN flag;
atanh(-NaN) = -NaN с выставлением DOMAIN flag;
atanh(|x|>1) = -Ind с выставлением DOMAIN flag;
atanh( +-1 ) = +-Inf с выставлением
OVERFLOW flag;
Use Global Variable:
Use Functions : ei_log1p( eiy, eix, nb ); | this file
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*z = NULL,
*half = NULL,
*one = NULL,
*tr = NULL; /* temp */
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"atanh" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* ATANH(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"atanh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* ATANH(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"atanh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for z, half, one, tr . *****************/
z = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !z )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE half **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE z *****************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_half( half, nb );
_gen_one ( one, nb );
/* ei_copy( x, eix, nb ); */
ei_copysign( z, half, x, nb );
ei_copysign( x, x, one, nb );
/* ATANH( |x| > 1 ) must by InD */
if( ei_cmp( x, one, nb ) > 0 )
{
/* "argument domain error" */
/* return: InD */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"atanh", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* (x > 1) - produsing Domain Flag */
/* FREE x *****************/
/* FREE z *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* ATANH( |x| == 1 ) must by sign(x)*Infinity */
if( ei_cmp( x, one, nb ) == 0 )
{
/* ATANH(|x| == 1) overflow to +-Infinity */
/* "overflow range error" */
/* return: sign(x)*Infinity */
ei_copy( x, eix, nb ); /* for &eiy == &eix */
ei_infin( tr, (unsigned)0, nb );
ei_copysign( eiy, tr, z, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"atanh", __OVERFLOW__,
eiy, x, (EMUSHORT *)0, nb );
__STOVF; /* (|x| == 1) - produsing Overflow Flag */
/* FREE x *****************/
/* FREE z *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_sub( tr, one, x, nb );
ei_div( x, x, tr, nb ); /* x = x/(1.0-x); */
ei_add( tr, x, x, nb );
ei_log1p( tr, tr, nb );
ei_mul( eiy, z, tr, nb ); /* return( z*log1p(x+x) ); */
/* FREE x *****************/
/* FREE z *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End of ei_atanh() */
void ei_asin( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_asin() Работает с
internal e-type data struct.
Concepts : ASIN(X) RETURN THE INVERSE SINE OF EIX.
METHOD : Return
asin(x) = atan2(x,sqrt(1-x*x));
for better accuracy, 1-x*x is computed
as follows
if( x < 0.5) 1-x*x;
if( x >= 0.5) 2*(1-|x|)-(1-|x|)*(1-|x|).
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: mpu-floatp.h].
NOTE :
SPECIAL CASES : asin(-InD) = -InD с выставлением DOMAIN flag;
asin(+NaN) = +NaN с выставлением DOMAIN flag;
asin(-NaN) = -NaN с выставлением DOMAIN flag;
asin(|x|>1) = -Ind с выставлением DOMAIN flag;
Use Global Variable:
Use Functions : ei_atan2( eiy, eix, nb ); | this file
ei_sqrt( eiy, eix, nb ); | mpu-real.c
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*t = NULL,
*s = NULL,
*half = NULL,
*one = NULL,
*tr = NULL; /* temp */
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"asin" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* ASIN(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"asin", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* ASIN(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"asin", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for t, s, half, one, tr . **************/
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
s = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !s )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE half **************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE half **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_half( half, nb );
_gen_one ( one, nb );
ei_copysign( s, x, one, nb );
/* ATANH( |x| > 1 ) must by InD */
if( ei_cmp( s, one, nb ) > 0 )
{
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"asin", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* (x > 1) - produsing Domain Flag */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_cmp( s, half, nb ) <= 0 )
{
/* return( atan2( x, sqrt( one - x*x ) ) ); */
ei_mul( tr, x, x, nb );
ei_sub( tr, one, tr, nb );
ei_sqrt( tr, tr, nb );
ei_atan2( eiy, x, tr, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
ei_sub( t, one, s, nb ); /* t = one - s; */
ei_add( s, t, t, nb ); /* s = t + t; */
/* return( atan2( x, sqrt( s - t*t ) ) ); */
ei_mul( tr, t, t, nb );
ei_sub( tr, s, tr, nb );
ei_sqrt( tr, tr, nb );
ei_atan2( eiy, x, tr, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE half **************/
/* FREE one ***************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End of ei_asin() */
void ei_acos( EMUSHORT *eiy, EMUSHORT *eix, int nb )
/***************************************************************
Description : ei_acos() Работает с
internal e-type data struct.
Concepts : ACOS(X) RETURN THE INVERSE COSINE OF EIX.
METHOD : Return
________
/ 1 - x
acos(x) = 2*atan2( / --------, 1 ).
\/ 1 + x
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: mpu-floatp.h].
NOTE :
SPECIAL CASES : acos(-InD) = -InD с выставлением DOMAIN flag;
acos(+NaN) = +NaN с выставлением DOMAIN flag;
acos(-NaN) = -NaN с выставлением DOMAIN flag;
acos(|x|>1) = -Ind с выставлением DOMAIN flag;
Use Global Variable:
Use Functions : ei_atan2( eiy, eix, nb ); | this file
ei_sqrt( eiy, eix, nb ); | mpu-real.c
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eiy; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*t = NULL,
*s = NULL,
*zero = NULL,
*one = NULL,
*negone = NULL,
*tx = NULL, /* temp */
*tr = NULL; /* temp */
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"acos" );
/* ei_ind( eiy, nb ); */ /* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x . ********************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( x, eix, nb ); /* temp for _mtherr() */
/***************************
Test for EIX.
***************************/
/* ACOS(InD) must by InD */
if( ei_isind( eix, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"acos", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* ACOS(NaN) must by NaN */
if( ei_isnans( eix, nb ) )
{
/* "argument domain error" */
/* return: NaN */
ei_copy( eiy, eix, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"acos", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* NaN - produsing Domain Flag */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for t, s, zero, one, negone, tx, tr . **/
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
s = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !s )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
negone = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !negone )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE zero **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tr = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tr )
{
/* fatal error */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_zero( zero, nb );
_gen_one ( one, nb );
_gen_one ( negone, nb );
ei_neg ( negone, nb );
ei_copysign( s, x, one, nb );
/* ATANH( |x| > 1 ) must by InD */
if( ei_cmp( s, one, nb ) > 0 )
{
/* "argument domain error" */
/* return: InD */
ei_ind( eiy, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eiy, (__mpu_char8_t *)"acos", __DOMAIN__,
eiy, x, (EMUSHORT *)0, nb );
__STDOM; /* (x > 1) - produsing Domain Flag */
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE tx ****************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_cmp( x, negone, nb ) != 0 )
{
/* t = atan2( sqrt( (one-x)/(one+x) ), one ); */
ei_sub( tx, one, x, nb );
ei_add( tr, one, x, nb );
ei_div( tx, tx, tr, nb );
ei_sqrt( tx, tx, nb );
ei_atan2( t, tx, one, nb );
}
else
{
ei_atan2( t, one, zero, nb ); /* t = PI/2; */
}
ei_add( eiy, t, t, nb );
/* FREE x *****************/
/* FREE t *****************/
/* FREE s *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE tx ****************/
/* FREE tr ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End of ei_acos() */
static void __ei_pow__P( EMUSHORT *eic, EMUSHORT *eix, EMUSHORT *eiy, int nb )
{
EMUSHORT *s_a = NULL,
*s_b = NULL,
*t_a = NULL,
*t_b = NULL;
Double s, t;
EMUSHORT *x = NULL,
*y = NULL,
*zero = NULL,
*one = NULL,
*big = NULL,
*tx = NULL, /* temp */
*ty = NULL; /* temp */
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
/* ei_ind( eic, nb ); *//* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for s_a, s_b, t_a, t_b . ***************/
s_a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !s_a )
{
/* fatal error */
return;
}
s_b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !s_b )
{
/* fatal error */
/* FREE s_a ***************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
t_a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t_a )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
t_b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t_b )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for x, y, zero, one, big, tx, ty . *****/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
y = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !y )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
big = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !big )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ty = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ty )
{
/* fatal error */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(10*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
s.a = s_a;
s.b = s_b;
t.a = t_a;
t.b = t_b;
_gen_zero( zero, nb );
_gen_one ( one, nb );
/*********************************************
big : big = 1/(small^2);
*********************************************/
ei_div( big, one, _get_epsilon_ptr( nb ), nb );
ei_copy( x, eix, nb );
ei_copy( y, eiy, nb );
if( ei_cmp( x, zero, nb ) == 0 )
{
if( ei_cmp( y, zero, nb ) > 0 )
{
/* #(12) */
ei_copy( eic, zero, nb ); /* Not set the FLAGS */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* (14) DIV_BY_ZERO */
/* "function singularity" */
/* return: +Infinity */
ei_infin( eic, (unsigned)0, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"pow", __SING__,
eic, x, y, nb );
__STSNG; /* +0^(-(y!=0,NaN)) - produsing Sing Flag */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( x == zero ) */
if( ei_cmp( x, one, nb ) == 0 )
{
ei_copy( eic, one, nb );
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_isinfin( x, nb ) )
{
if( ei_cmp( y, zero, nb ) < 0 )
{
/* #(18) */
ei_copy( eic, zero, nb ); /* Not set the FLAGS */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* #(17) */
/* "overflow range error" */
/* "Result too large" */
/* return: +Infinity */
ei_infin( eic, (unsigned)0, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"pow", __OVERFLOW__,
eic, x, y, nb );
__STOVF; /* produsing Overflow Flag */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( x == Infinity ) */
if( ei_cmp( y, big, nb ) >= 0 )
{
if( ei_cmp( x, one, nb ) < 0 )
{
/* "underflow range error" */
/* return: ZERO */
ei_copy( eic, zero, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"pow", __UNDERFLOW__,
eic, x, y, nb );
__STUDF; /* produsing Underflow Flag */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* "overflow range error" */
/* "Result too large" */
/* return: +Infinity */
ei_infin( eic, (unsigned)0, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"pow", __OVERFLOW__,
eic, x, y, nb );
__STOVF; /* produsing Overflow Flag */
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( y >= big ) */
/*********************************************************
Return exp( y*log( x ) ), using simulated extended
precision for the log() and the multiply.
*********************************************************/
__ei_log__D( s, x, nb ); /* s = log__D( x ); */
ei_copy( t.a, y, nb ); /* t.a = y; */
__ei_TRUNC( t.a, nb ); /* _TRUNC( t.a ); */
ei_sub( t.b, y, t.a, nb ); /* t.b = y - t.a; */
ei_mul( ty, s.b, y, nb );
ei_mul( tx, t.b, s.a, nb );
ei_add( t.b, ty, tx, nb ); /* t.b = s.b*y + t.b*s.a; */
ei_mul( t.a, t.a, s.a, nb ); /* t.a *= s.a; */
ei_add( s.a, t.a, t.b, nb ); /* s.a = t.a + t.b; */
ei_sub( tx, t.a, s.a, nb );
ei_add( s.b, tx, t.b, nb ); /* s.b = (t.a - s.a) + t.b; */
/********* return( __ei_exp__D( s.a, s.b ) ); **********/
__ei_exp__D( eic, s.a, s.b, nb );
/* FREE s_a ***************/
/* FREE s_b ***************/
/* FREE t_a ***************/
/* FREE t_b ***************/
/* FREE x *****************/
/* FREE y *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE big ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(11*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End of __ei_pow__P() */
void ei_pow( EMUSHORT *eic, EMUSHORT *eix, EMUSHORT *eiy, int nb )
/***************************************************************
Description : ei_pow() Работает с
internal e-type data struct.
Concepts : EI_POW( EIC, EIX, EIY) RETURN EIC = EIX^EIY.
METHOD : 1. Compute and return log(x) in three pieces:
log(x) = n*ln2 + hi + lo,
where n is an integer.
2. Perform y*log(x) by simulating
muti-precision arithmetic and return
the answer in three pieces:
y*log(x) = m*ln2 + hi + lo,
where m is an integer.
3. Return
x^y = exp(y*log(x)) = 2^m*(exp(hi+lo)).
ACCURACY : In the absence of rounding error,
the appriximation has absolute error
less than EPSILON [see: mpu-floatp.h].
NOTE :
SPECIAL CASES :
====================================================================
| |
X | Y | RESULT
| |
====================|====================|==========================
#( 1)
(anything) ^ 0 = 1 ;
(anything) ^ 1 = itself;
(anything) ^ NaN = NaN;
--------------------|--------------------|--------------------------
#( 4)
NaN ^ (anything
except 0) = NaN;
--------------------|--------------------|--------------------------
#( 5)
+(anything > 1) ^ +INF = +INF;
-(anything > 1) ^ +INF = NaN;
+-(anything > 1) ^ -INF = +0;
+-(anything < 1) ^ +INF = +0;
+(anything < 1) ^ -INF = +INF;
-(anything < 1) ^ -INF = NaN;
+-1 ^ +-INF = -InD and signal DOMAIN;
--------------------|--------------------|--------------------------
#(12)
+0 ^ +(anything
except 0, NaN) = +0;
--------------------|--------------------|--------------------------
#(13)
-0 ^ +(anything
except 0, NaN,
odd integer) = +0;
--------------------|--------------------|--------------------------
#(14)
+0 ^ -(anything
except 0, NaN) = +INF
and signal DIV-BY-ZERO;
--------------------|--------------------|--------------------------
#(15)
-0 ^ -(anything
except 0, NaN,
odd integer) = +INF with signal;
--------------------|--------------------|--------------------------
#(16)
-0 ^ (odd integer) = -( +0^(odd integer) );
--------------------|--------------------|--------------------------
#(17)
+INF ^ +(anything
except 0, NaN) = +INF;
--------------------|--------------------|--------------------------
#(18)
+INF ^ -(anything
except 0, NaN) = +0;
--------------------|--------------------|--------------------------
#(19)
-INF ^ (odd integer) = -( +INF^(odd integer) );
-INF ^ (even integer) = ( +INF^(even integer) );
--------------------|--------------------|--------------------------
#(21)
-INF ^ -(anything
except NaN,
integer) = NaN with signal;
--------------------|--------------------|--------------------------
#(22)
-(x=anything) ^ (k=integer) = (-1)^k * (x^k);
-(anything except 0) ^ (non-integer) = NaN with signal;
====================================================================
Use Global Variable:
Use Functions : ei_drem( eiy, eix, eid, nb ); | this file
__ei_pow__P( eic, eix, eiy, nb ); | this file
ei_copy( eiy, eix, nb ); | mpu-real.c
.
.
.
Parameters : EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eix; - указатель на
internal e-type
data struct.
SOURCE;
EMUSHORT *eiy; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *x = NULL,
*y = NULL,
*t = NULL,
*zero = NULL,
*one = NULL,
*negone = NULL,
*two = NULL,
*tx = NULL, /* temp */
*ty = NULL; /* temp */
int np;
if( nb < NBR_32 || nb > MPU_MATH_FN_LIMIT )
{
/* error: Invalid size of operand(s) */
__real_invalid_size( (__mpu_char8_t *)"pow" );
/* ei_ind( eic, nb ); *//* Invalid NB */
return;
}
/*******************************
Hight Precision for r32, r64.
*******************************/
if( nb < NBR_128 ) nb = NBR_128;
np = internal_np( nb );
/*** Allocate memory for x, y . *****************************/
x = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !x )
{
/* fatal error */
return;
}
y = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !y )
{
/* fatal error */
/* FREE x *****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( x, eix, nb );
ei_copy( y, eiy, nb );
if( ei_isind( eix, nb ) || ei_isind( eiy, nb ) )
{
/* "argument domain error" */
/* return: InD */
ei_ind( eic, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"pow", __DOMAIN__,
eic, x, y, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
/* FREE y *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for t, zero, one, negone, two . ********/
t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !t )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
negone = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !negone )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
two = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !two )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for tx, ty . ***************************/
tx = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tx )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ty = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ty )
{
/* fatal error */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
__mpu_sbrk( -(int)(8*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_zero( zero, nb );
_gen_one ( one, nb );
_gen_two ( two, nb );
_gen_one ( negone, nb );
ei_neg ( negone, nb );
if( ei_cmp( y, zero, nb ) == 0 )
{
/* #( 1) */
ei_copy( eic, one, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else if( (ei_cmp( y, one, nb ) == 0) || ei_isnans( x, nb ) )
{
/* #( 2) || #( 4) */
ei_copy( eic, x, nb ); /* Not set the FLAGS */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else if( ei_isnans( y, nb ) )
{
/* #( 3) */
ei_copy( eic, y, nb ); /* Not set the FLAGS */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else if( ei_isinfin( eiy, nb ) )
{
ei_copy( t, x, nb );
if( ei_cmp( t, one, nb ) == 0 )
{
/* #(11) */
/* +-1^+-Inf = InD; */
/* "argument domain error" */
/* return: InD */
ei_ind( eic, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"pow", __DOMAIN__,
eic, x, y, nb );
__STDOM; /* InD - produsing Domain Flag */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else if( ei_cmp( t, one, nb ) > 0 )
{
if( ei_cmp( y, zero, nb ) < 0 )
{
/* #( 7) */
ei_copy( eic, zero, nb ); /* Not set the FLAGS */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else if( ei_cmp( x, zero, nb ) < 0 )
{
/* #( 6) */
/* raise inexact flag */
ei_nanmax( eic, (unsigned)0, nb ); /* Not set the FLAGS */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else /* ( x >= zero ) */
{
/* #( 5) */
ei_copy( eic, y, nb ); /* Not set the FLAGS */
/* NOTE: y == +Infinity */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( |x| > one ) */
else /* ( |x| < one ) */
{
if( ei_cmp( y, zero, nb ) > 0 )
{
/* #( 8) */
ei_copy( eic, zero, nb ); /* Not set the FLAGS */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else if( ei_cmp( x, zero, nb ) < 0 )
{
/* #(10) */
/* raise inexact flag */
ei_nanmax( eic, (unsigned)0, nb ); /* Not set the FLAGS */
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, /* for No change set (EMUSHORT *)0 */
(__mpu_char8_t *)"pow", __INEXACT__,
eic, x, y, nb );
__STINX; /* produsing Inexact Flag */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else /* ( x >= zero ) */
{
/* #( 9) */
ei_copy( eic, y, nb ); /* Not set the FLAGS */
/* NOTE: y == +Infinity */
ei_neg( eic, nb ); /* return( -y ); */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End ( |x| < one ) */
} /* End if( eiy == +-Infinity ) */
else /* ( eiy != +-Infinity ) */
{
if( ei_cmp( y, two, nb ) == 0 )
{
ei_mul( eic, x, x, nb ); /* return( x*x ); */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else if( ei_cmp( y, negone, nb ) == 0 )
{
ei_div( eic, one, x, nb ); /* return( 1.0/x ); */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( y == -1.0 ) */
else /* ( y != -1.0 ) */
{
ei_copysign( tx, one, x, nb );
if( ei_cmp( tx, one, nb ) == 0 )
{
/* x > 0, my be x == +0 */
__ei_pow__P( eic, x, y, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( x >= +0 ) */
else /* ( x < +0 ) */
{
ei_drem( t, y, two, nb );
if( ei_cmp( t, zero, nb ) == 0 )
{
/* y - четное целое (y is an even integer) */
ei_neg( x, nb );
__ei_pow__P( eic, x, y, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( y == even integer ) */
else /* ( y != even integer ) */
{
ei_copysign( ty, t, one, nb );
if( ei_cmp( ty, one, nb ) == 0 )
{
/* y - нечетное целое (y is an odd integer) */
ei_neg( x, nb );
__ei_pow__P( eic, x, y, nb );
ei_neg( eic, nb );
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( y == odd integer ) */
else /* ( y != odd integer ) */
{
/* y is not an integer */
if( ei_cmp( x, zero, nb ) == 0 )
{
/* x is -0.
NOTE: for ei_cmp() -0.0 equals +0.0.
***************************************/
if( ei_cmp( y, zero, nb ) > 0 )
{
/* #(13) */
ei_neg( x, nb );
/* return +0 */
ei_copy( eic, x, nb ); /* return( -x ); */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
else
{
/* #(15) */
///////////////////////////////////////
//|unix|//ei_neg( x, nb ); //
//|unix|///* return( 1/(-x) ); */ //
//|unix|//ei_div( eic, one, x, nb ); //
///////////////////////////////////////
/* "function singularity" */
/* -0^(-(y!=0,NaN,odd_int)) */
/* return: +Infinity */
ei_infin( eic, (unsigned)0, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"pow", __SING__,
eic, x, y, nb );
__STSNG; /* produsing Sing Flag */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
} /* End if( x == -0 ) */
else /* ( x != -0 ) */
{
/* #(23) */
/* "argument domain error" */
/* return: InD */
ei_ind( eic, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
_math_error(). Кроме основных действий она
выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"pow", __DOMAIN__,
eic, x, y, nb );
__STDOM; /* produsing Domain Flag */
/* FREE x *****************/
/* FREE y *****************/
/* FREE t *****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE negone ************/
/* FREE two ***************/
/* FREE tx ****************/
/* FREE ty ****************/
__mpu_sbrk( -(int)(9*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End ( x != -0 ) */
} /* End ( y != odd integer ) */
} /* End ( y != even integer ) */
} /* End ( x < +0 ) */
} /* End ( y != -1.0 ) */
} /* End ( eiy != +-Infinity ) */
} /* End of ei_pow() */
/***************************************************************
Hide internal symbols:
***************************************************************/
__mpu_hidden_decl(ei_trunc);
__mpu_hidden_decl(ei_sin);
__mpu_hidden_decl(ei_cos);
__mpu_hidden_decl(ei_tan);
__mpu_hidden_decl(ei_log1p);
__mpu_hidden_decl(ei_log);
__mpu_hidden_decl(ei_log10);
__mpu_hidden_decl(ei_log2);
__mpu_hidden_decl(ei_expm1);
__mpu_hidden_decl(ei_exp);
__mpu_hidden_decl(ei_atan2);
__mpu_hidden_decl(ei_atan);
__mpu_hidden_decl(ei_sinh);
__mpu_hidden_decl(ei_cosh);
__mpu_hidden_decl(ei_tanh);
__mpu_hidden_decl(ei_asinh);
__mpu_hidden_decl(ei_acosh);
__mpu_hidden_decl(ei_atanh);
__mpu_hidden_decl(ei_asin);
__mpu_hidden_decl(ei_acos);
__mpu_hidden_decl(ei_pow);
/*
End of hide internal symbols.
***************************************************************/