/***************************************************************
__MPU_REAL.C
This file contains source code of functions for
REAL arithmetic 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-char.h>
#include <mpu-symbols.h>
#include <mpu-math-errno.h>
#include <mpu-strerror.h>
#include <mpu-mtherr.h>
int internal_np( int nb )
/***************************************************************
Description : internal_np() возвращает количество слов
размера EMUSHORT в internal
e-type data struct.
Concepts :
Use Global Variable:
Use Functions :
Parameters : int nb; - количество бит в
external e-type data
struct.
Return : int rc; - количество слов.
[rc = 0] - error.
***************************************************************/
{
int rc = 0;
switch( nb )
{
case NBR_32:
rc = NPIR_32;
break;
case NBR_64:
rc = NPIR_64;
break;
case NBR_128:
rc = NPIR_128;
break;
case NBR_256:
rc = NPIR_256;
break;
case NBR_512:
rc = NPIR_512;
break;
case NBR_1024:
rc = NPIR_1024;
break;
case NBR_2048:
rc = NPIR_2048;
break;
case NBR_4096:
rc = NPIR_4096;
break;
case NBR_8192:
rc = NPIR_8192;
break;
case NBR_16384:
rc = NPIR_16384;
break;
case NBR_32768:
rc = NPIR_32768;
break;
case NBR_65536:
rc = NPIR_65536;
break;
case NBR_131072:
rc = NPIR_131072;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of internal_np() */
int internal_ne( int nb )
/***************************************************************
Description : internal_ne() возвращает количество слов
размера EMUSHORT в Exponent
(internal e-type data
struct).
Concepts :
Use Global Variable:
Use Functions :
Parameters : int nb; - количество бит в
external e-type data
struct.
Return : int rc; - количество слов
Exponent.
[rc = 0] - error.
***************************************************************/
{
int rc = 0;
switch( nb )
{
case NBR_32:
rc = NPIE_32;
break;
case NBR_64:
rc = NPIE_64;
break;
case NBR_128:
rc = NPIE_128;
break;
case NBR_256:
rc = NPIE_256;
break;
case NBR_512:
rc = NPIE_512;
break;
case NBR_1024:
rc = NPIE_1024;
break;
case NBR_2048:
rc = NPIE_2048;
break;
case NBR_4096:
rc = NPIE_4096;
break;
case NBR_8192:
rc = NPIE_8192;
break;
case NBR_16384:
rc = NPIE_16384;
break;
case NBR_32768:
rc = NPIE_32768;
break;
case NBR_65536:
rc = NPIE_65536;
break;
case NBR_131072:
rc = NPIE_131072;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of internal_ne() */
int internal_ns( int nb )
/***************************************************************
Description : internal_ns() возвращает количество слов
размера EMUSHORT в
Significand (internal e-type
data struct).
Concepts :
Use Global Variable:
Use Functions :
Parameters : int nb; - количество бит в
external e-type data
struct.
Return : int rc; - количество слов
Significand.
[rc = 0] - error.
***************************************************************/
{
int rc = 0;
switch( nb )
{
case NBR_32:
rc = NPIR_32 - 3 - NPIE_32;
break;
case NBR_64:
rc = NPIR_64 - 3 - NPIE_64;
break;
case NBR_128:
rc = NPIR_128 - 3 - NPIE_128;
break;
case NBR_256:
rc = NPIR_256 - 3 - NPIE_256;
break;
case NBR_512:
rc = NPIR_512 - 3 - NPIE_512;
break;
case NBR_1024:
rc = NPIR_1024 - 3 - NPIE_1024;
break;
case NBR_2048:
rc = NPIR_2048 - 3 - NPIE_2048;
break;
case NBR_4096:
rc = NPIR_4096 - 3 - NPIE_4096;
break;
case NBR_8192:
rc = NPIR_8192 - 3 - NPIE_8192;
break;
case NBR_16384:
rc = NPIR_16384 - 3 - NPIE_16384;
break;
case NBR_32768:
rc = NPIR_32768 - 3 - NPIE_32768;
break;
case NBR_65536:
rc = NPIR_65536 - 3 - NPIE_65536;
break;
case NBR_131072:
rc = NPIR_131072 - 3 - NPIE_131072;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of internal_ns() */
void ei_cleaz( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_cleaz() Работает с
internal e-type data struct.
Concepts : clear out exploded internal e-type real
number.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int np;
np = internal_np( nb );
(void)memset( (void *)ei, 0, np * SIZE_OF_EMUSHORT );
} /* End of ei_cleaz() */
void ei_cleazs( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_cleazs() Работает с
internal e-type data struct.
Concepts : clear out exploded internal e-type real
number, but don't touch the sign.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int np;
np = internal_np( nb ) - 1;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++ei;
#endif
(void)memset( (void *)ei, 0, np * SIZE_OF_EMUSHORT );
} /* End of ei_cleazs() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/ei_ind_emu32lsb.dfn>
#else
#include <r_const/ei_ind_emu32msb.dfn>
#endif
void ei_ind( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_ind() Работает с
internal e-type data struct.
Concepts : формирует `неопределенность' (- 1.IND)
Sign Exp 1. Significand
==== ===== == ===========
1 1...1 1 10.......00,
которое не равно nan_max, nan_min и nan.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
size_t nbytes = internal_np( nb ) * SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
(void)memcpy( (void *)ei, (void *)&_ei_ind_128_[0], nbytes );
break;
case NBR_256:
(void)memcpy( (void *)ei, (void *)&_ei_ind_256_[0], nbytes );
break;
case NBR_512:
(void)memcpy( (void *)ei, (void *)&_ei_ind_512_[0], nbytes );
break;
case NBR_1024:
(void)memcpy( (void *)ei, (void *)&_ei_ind_1024_[0], nbytes );
break;
case NBR_2048:
(void)memcpy( (void *)ei, (void *)&_ei_ind_2048_[0], nbytes );
break;
case NBR_4096:
(void)memcpy( (void *)ei, (void *)&_ei_ind_4096_[0], nbytes );
break;
case NBR_8192:
(void)memcpy( (void *)ei, (void *)&_ei_ind_8192_[0], nbytes );
break;
case NBR_16384:
(void)memcpy( (void *)ei, (void *)&_ei_ind_16384_[0], nbytes );
break;
case NBR_32768:
(void)memcpy( (void *)ei, (void *)&_ei_ind_32768_[0], nbytes );
break;
case NBR_65536:
(void)memcpy( (void *)ei, (void *)&_ei_ind_65536_[0], nbytes );
break;
case NBR_131072:
(void)memcpy( (void *)ei, (void *)&_ei_ind_131072_[0], nbytes );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of ei_ind() */
int ei_isind( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_isind() Работает с
internal e-type data struct.
Concepts : проверка на `неопределенность' (- 1.IND)
Sign Exp 1. Significand
==== ===== == ===========
1 1...1 1 10.......00,
которая не равна nan_max, nan_min и nan.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `неопределенность' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, ne, is, ns;
int rc = 0; /* Return Code */
ne = internal_ne( nb );
ns = internal_ns( nb );
/*************************************************************
NOTE:
====
Compare 'Sign...Exp' and 'Significand'; skip lgw and hgw.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 0; is = ne + 2;
#else
ie = ns + 2; is = 1;
#endif
++ne;
ne *= SIZE_OF_EMUSHORT;
ns *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_128_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_128_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_256:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_256_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_256_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_512:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_512_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_512_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_1024:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_1024_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_1024_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_2048:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_2048_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_2048_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_4096:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_4096_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_4096_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_8192:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_8192_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_8192_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_16384:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_16384_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_16384_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_32768:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_32768_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_32768_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_65536:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_65536_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_65536_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_131072:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_ind_131072_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_ind_131072_[0][is], (size_t)ns )
) rc = 1;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of ei_isind() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/e_ind_emu32lsb.dfn>
#else
#include <r_const/e_ind_emu32msb.dfn>
#endif
void e_ind( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_ind() Работает с
external e-type data struct.
Concepts : формирует `неопределенность' (- 1.IND)
Sign Exp Significand
==== ===== ===========
1 1...1 10.......00,
которое не равно nan_max, nan_min и nan.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
/*************************************************************
NOTE:
====
Здесь работа идет словами EMUSHORT (согласно
определениям из файлов e_ind_emu32*sb.dfn) и,
следовательно, на данный момент подразумевается,
что размер EMUSHORT равен 4 байта (32 bits).
Если BITS_PER_EMUSHORT > 32, то надо использовать
прямое присваивание значений, например:
__mpu_uint32_t *e = (__mpu_uint32_t *)ee;
*e = 0xffc00000;
не забывая об очередности LITTLE/BIG endian.
*************************************************************/
switch( nb )
{
case NBR_32:
(void)memcpy( (void *)ee, (void *)&_e_ind_32_[0], np );
break;
case NBR_64:
(void)memcpy( (void *)ee, (void *)&_e_ind_64_[0], np );
break;
case NBR_128:
(void)memcpy( (void *)ee, (void *)&_e_ind_128_[0], np );
break;
case NBR_256:
(void)memcpy( (void *)ee, (void *)&_e_ind_256_[0], np );
break;
case NBR_512:
(void)memcpy( (void *)ee, (void *)&_e_ind_512_[0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ee, (void *)&_e_ind_1024_[0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ee, (void *)&_e_ind_2048_[0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ee, (void *)&_e_ind_4096_[0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ee, (void *)&_e_ind_8192_[0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ee, (void *)&_e_ind_16384_[0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ee, (void *)&_e_ind_32768_[0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ee, (void *)&_e_ind_65536_[0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ee, (void *)&_e_ind_131072_[0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of e_ind() */
int e_isind( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isind() Работает с
external e-type data struct.
Concepts : проверка на `неопределенность' (- 1.IND)
Sign Exp Significand
==== ===== ===========
1 1...1 10.......00,
которое не равно nan_max, nan_min и nan.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `неопределенность' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int rc = 0; /* Return Code */
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
switch( nb )
{
case NBR_32:
if( !memcmp( (void *)ee, (void *)&_e_ind_32_[0], np ) ) rc = 1;
break;
case NBR_64:
if( !memcmp( (void *)ee, (void *)&_e_ind_64_[0], np ) ) rc = 1;
break;
case NBR_128:
if( !memcmp( (void *)ee, (void *)&_e_ind_128_[0], np ) ) rc = 1;
break;
case NBR_256:
if( !memcmp( (void *)ee, (void *)&_e_ind_256_[0], np ) ) rc = 1;
break;
case NBR_512:
if( !memcmp( (void *)ee, (void *)&_e_ind_512_[0], np ) ) rc = 1;
break;
case NBR_1024:
if( !memcmp( (void *)ee, (void *)&_e_ind_1024_[0], np ) ) rc = 1;
break;
case NBR_2048:
if( !memcmp( (void *)ee, (void *)&_e_ind_2048_[0], np ) ) rc = 1;
break;
case NBR_4096:
if( !memcmp( (void *)ee, (void *)&_e_ind_4096_[0], np ) ) rc = 1;
break;
case NBR_8192:
if( !memcmp( (void *)ee, (void *)&_e_ind_8192_[0], np ) ) rc = 1;
break;
case NBR_16384:
if( !memcmp( (void *)ee, (void *)&_e_ind_16384_[0], np ) ) rc = 1;
break;
case NBR_32768:
if( !memcmp( (void *)ee, (void *)&_e_ind_32768_[0], np ) ) rc = 1;
break;
case NBR_65536:
if( !memcmp( (void *)ee, (void *)&_e_ind_65536_[0], np ) ) rc = 1;
break;
case NBR_131072:
if( !memcmp( (void *)ee, (void *)&_e_ind_131072_[0], np ) ) rc = 1;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of e_isind() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/ei_nan_emu32lsb.dfn>
#else
#include <r_const/ei_nan_emu32msb.dfn>
#endif
void ei_nan( EMUSHORT *ei, unsigned sign, int nb )
/***************************************************************
Description : ei_nan() Работает с
internal e-type data struct.
Concepts : формирует `не число' (+/- 1.NAN)
Sign Exp 1. Significand
==== ===== == ===========
S 1...1 1 10.......01,
которое не равно nan_max, nan_min и ind.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int sn = 0;
size_t np = internal_np( nb ) * SIZE_OF_EMUSHORT;
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
(void)memcpy( (void *)ei, (void *)&_ei_nan_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ei, (void *)&_ei_nan_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ei, (void *)&_ei_nan_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ei, (void *)&_ei_nan_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ei, (void *)&_ei_nan_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ei, (void *)&_ei_nan_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ei, (void *)&_ei_nan_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ei, (void *)&_ei_nan_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ei, (void *)&_ei_nan_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ei, (void *)&_ei_nan_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ei, (void *)&_ei_nan_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of ei_nan() */
int ei_isnans( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_isnans() Работает с
internal e-type data struct.
Concepts : проверка на `не число' (+/- 1.NAN)
Sign Exp 1. Significand
==== ===== == ===========
S 1...1 1 00.......01, min
+ 1...1 1 10.......00, (-ind)
S 1...1 1 10.......01,
S 1...1 1 11.......11, max
которое не равно ind.
Use Global Variable:
Use Functions :
ei_isind( ei, nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( любое `не число' кроме `ind') [rc = 1];
else [rc = 0];
***************************************************************/
{
int i, ne, ns;
if( ei_isind( ei, nb ) ) return( 0 );
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + ne + ns + 1; /* skip Sign */
#else
ei++;
#endif
/* test ALL NaNs */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part of Exponent */
if( (*ei++ & HIGHT_EXP) != HIGHT_EXP ) return( 0 );
/* low parts of Exponent (if is present) */
for( i = 1; i < ne; i++ )
{
if( *ei++ != MASK_ALL_BITS ) return( 0 );
}
ei++; /* skip the hgw */
/* hight part of Significand (без неявной 1.0) */
if( *ei++ & HIGHT_EXP ) return( 1 );
/* low parts of Significand (if is present) */
for( i = 1; i < ns; i++ ) if( *ei++ ) return( 1 );
#else
/* hight part of Exponent */
if( (*ei-- & HIGHT_EXP) != HIGHT_EXP ) return( 0 );
/* low parts of Exponent (if is present) */
for( i = 1; i < ne; i++ )
{
if( *ei-- != MASK_ALL_BITS ) return( 0 );
}
ei--; /* skip the hgw */
/* hight part of Significand (без неявной 1.0) */
if( *ei-- & HIGHT_EXP ) return( 1 );
/* low parts of Significand (if is present) */
for( i = 1; i < ns; i++ ) if( *ei-- ) return( 1 );
#endif
/* ei -> lgw */
return( 0 );
} /* End of ei_isnans() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/e_nan_emu32lsb.dfn>
#else
#include <r_const/e_nan_emu32msb.dfn>
#endif
void e_nan( EMUSHORT *ee, unsigned sign, int nb )
/***************************************************************
Description : e_ind() Работает с
external e-type data struct.
Concepts : формирует `не число' (+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 10.......01,
которое не равно nan_max, nan_min и ind.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
int sn = 0;
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
(void)memcpy( (void *)ee, (void *)&_e_nan_32_[sn][0], np );
break;
case NBR_64:
(void)memcpy( (void *)ee, (void *)&_e_nan_64_[sn][0], np );
break;
case NBR_128:
(void)memcpy( (void *)ee, (void *)&_e_nan_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ee, (void *)&_e_nan_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ee, (void *)&_e_nan_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ee, (void *)&_e_nan_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ee, (void *)&_e_nan_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ee, (void *)&_e_nan_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ee, (void *)&_e_nan_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ee, (void *)&_e_nan_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ee, (void *)&_e_nan_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ee, (void *)&_e_nan_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ee, (void *)&_e_nan_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of e_nan() */
static int e_isnans_32( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnans_32() Работает с
external e-type data struct.
Concepts : проверка на `не число' (+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01, min
+ 1...1 10.......00, (-ind)
S 1...1 10.......01,
S 1...1 11.......11, max
которое не равно ind.
Use Global Variable:
Use Functions :
e_isind( ee, nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( любое `не число' кроме `ind') [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint16_t *e;
int rc = 1, rc1 = 0; /* Return Code */
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc1 );
}
if( e_isind( ee, nb ) ) return( rc1 );
e = (__mpu_uint16_t *)ee;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
if( (*e & 0x7f80) == 0x7f80 ) rc &= 1;
else rc &= 0;
if( rc )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( ((*e & 0x7f) != 0) || (*(e + 1) != 0) )
#else
if( ((*e & 0x7f) != 0) || (*(e - 1) != 0) )
#endif
rc1 |= 1;
return( rc1 );
}
else
{
return( rc1 );
}
} /* End of e_isnans_32() */
static int e_isnans_64( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnans_64() Работает с
external e-type data struct.
Concepts : проверка на `не число' (+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01, min
+ 1...1 10.......00, (-ind)
S 1...1 10.......01,
S 1...1 11.......11, max
которое не равно ind.
Use Global Variable:
Use Functions :
e_isind( ee, nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( любое `не число' кроме `ind') [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 1, rc1 = 0; /* Return Code */
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc1 );
}
if( e_isind( ee, nb ) ) return( rc1 );
e = (__mpu_uint32_t *)ee;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
if( (*e & 0x7ff00000) == 0x7ff00000 ) rc &= 1;
else rc &= 0;
if( rc )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( ((*e & 0xfffff) != 0) || (*(e + 1) != 0) )
#else
if( ((*e & 0xfffff) != 0) || (*(e - 1) != 0) )
#endif
rc1 |= 1;
return( rc1 );
}
else
{
return( rc1 );
}
} /* End of e_isnans_64() */
static int e_isnans_np( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnans_np() Работает с
external e-type data struct.
Concepts : проверка на `не число' (+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01, min
+ 1...1 10.......00, (-ind)
S 1...1 10.......01,
S 1...1 11.......11, max
которое не равно ind.
Use Global Variable:
Use Functions :
e_isind( ee, nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( любое `не число' кроме `ind' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int i, ne, ns;
if( e_isind( ee, nb ) ) return( 0 );
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ee = ee + ne + ns - 1; /* Sign */
#endif
/* test ALL NaNs */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part of Exponent (skip Sign) */
if( (*ee++ & HIGHT_EXP) != HIGHT_EXP ) return( 0 );
/* low parts of Exponent (if is present) */
for( i = 1; i < ne; i++ )
{
if( *ee++ != MASK_ALL_BITS ) return( 0 );
}
/* all parts of Significand (if is present) */
for( i = 0; i < ns; i++ ) if( *ee++ ) return( 1 );
#else
/* hight part of Exponent (skip Sign) */
if( (*ee-- & HIGHT_EXP) != HIGHT_EXP ) return( 0 );
/* low parts of Exponent (if is present) */
for( i = 1; i < ne; i++ )
{
if( *ee-- != MASK_ALL_BITS ) return( 0 );
}
/* all parts of Significand (if is present) */
for( i = 0; i < ns; i++ ) if( *ee-- ) return( 1 );
#endif
return( 0 );
} /* End of e_isnans_np() */
int e_isnans( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnans() Работает с
external e-type data struct.
Concepts : проверка на `не число' (+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01, min
+ 1...1 10.......00, (-ind)
S 1...1 10.......01,
S 1...1 11.......11, max
которое не равно ind.
Use Global Variable:
Use Functions :
e_isnans_32(); | this file
e_isnans_64(); | this file
e_isnans_np(); | this file
Parameters : unsigned EMUSHORT *ee; - указатель на
external e-type
data struct;
unsigned int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( любое `не число' кроме `ind' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int rc = 0; /* Return Code */
switch( nb )
{
case NBR_32 :
rc = e_isnans_32( ee, nb );
break;
case NBR_64 :
rc = e_isnans_64( ee, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
rc = e_isnans_np( ee, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of e_isnans() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/ei_nanmax_emu32lsb.dfn>
#else
#include <r_const/ei_nanmax_emu32msb.dfn>
#endif
void ei_nanmax( EMUSHORT *ei, unsigned sign, int nb )
/***************************************************************
Description : ei_nanmax() Работает с
internal e-type data struct.
Concepts : формирует максимальное `не число'
(+/- 1.NAN)
Sign Exp 1. Significand
==== ===== == ===========
S 1...1 1 11.......11,
которое не равно nan_min и ind.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int sn = 0;
size_t np = internal_np( nb ) * SIZE_OF_EMUSHORT;
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ei, (void *)&_ei_nanmax_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of ei_nanmax() */
int ei_isnanmax( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_isnanmax() Работает с
internal e-type data struct.
Concepts : проверка на максимальное `не число'
(+/- 1.NAN)
Sign Exp 1. Significand
==== ===== == ===========
S 1...1 1 11.......11,
которое не равно nan_min и ind.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( max `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, ne, is, ns;
int rc = 0; /* Return Code */
ne = internal_ne( nb );
ns = internal_ns( nb );
/*************************************************************
NOTE:
====
Compare 'Exp' and 'Significand'; skip Sign, lgw and hgw.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 1; is = ne + 2;
#else
ie = ns + 2; is = 1;
#endif
ne *= SIZE_OF_EMUSHORT;
ns *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_128_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_128_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_256:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_256_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_256_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_512:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_512_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_512_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_1024:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_1024_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_1024_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_2048:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_2048_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_2048_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_4096:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_4096_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_4096_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_8192:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_8192_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_8192_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_16384:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_16384_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_16384_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_32768:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_32768_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_32768_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_65536:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_65536_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_65536_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_131072:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmax_131072_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmax_131072_[0][is], (size_t)ns )
) rc = 1;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of ei_isnanmax() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/e_nanmax_emu32lsb.dfn>
#else
#include <r_const/e_nanmax_emu32msb.dfn>
#endif
void e_nanmax( EMUSHORT *ee, unsigned sign, int nb )
/***************************************************************
Description : e_nanmax() Работает с
external e-type data struct.
Concepts : формирует максимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 11.......11,
которое не равно nan_min и ind.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
int sn = 0;
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_32_[sn][0], np );
break;
case NBR_64:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_64_[sn][0], np );
break;
case NBR_128:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ee, (void *)&_e_nanmax_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of e_nanmax() */
static int e_isnanmax_32( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnanmax_32() Работает с
external e-type data
struct.
Concepts : проверка на максимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 11.......11,
которое не равно nan_min и ind.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( max `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 0; /* Return Code */
e = (__mpu_uint32_t *)ee;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
}
/* skip Sign */
if( (*e & 0x7fffffff) == 0x7fffffff )
rc = 1;
return( rc );
} /* End of e_isnanmax_32() */
static int e_isnanmax_64( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnanmax_64() Работает с
external e-type data
struct.
Concepts : проверка на максимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 11.......11,
которое не равно nan_min и ind.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( max `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 1; /* Return Code */
e = (__mpu_uint32_t *)ee;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
/* skip Sign */
if( (*e & 0x7fffffff) == 0x7fffffff ) rc &= 1;
else rc &= 0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
e++; /* low part of real32 data struct */
#else
e--;
#endif
if( *e == 0xffffffff ) rc &= 1;
else rc &= 0;
return( rc );
} /* End of e_isnanmax_64() */
static int e_isnanmax_np( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnanmax_np() Работает с
external e-type data
struct.
Concepts : проверка на максимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 11.......11,
которое не равно nan_min и ind.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( max `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, is, np;
int rc = 1; /* Return Code */
np = internal_np( nb ) - 3; /* Sign, hgw, lgw */
/*************************************************************
NOTE:
====
Compare 'Exp' and 'Significand'; skip Sign.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 1; is = 0;
#else
ie = 0; is = np - 1;
#endif
--np;
/* skip Sign */
if( (ee[is] & HIGHT_EXP) == HIGHT_EXP ) rc &= 1;
else rc &= 0;
np *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_128:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_128_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_256:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_256_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_512:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_512_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_1024:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_1024_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_2048:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_2048_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_4096:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_4096_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_8192:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_8192_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_16384:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_16384_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_32768:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_32768_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_65536:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_65536_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_131072:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmax_131072_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of e_isnanmax_np() */
int e_isnanmax( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnanmax() Работает с
external e-type data struct.
Concepts : проверка на максимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 11.......11,
которое не равно nan_min и ind.
Use Global Variable:
Use Functions :
e_isnanmax_32(); | this file
e_isnanmax_64(); | this file
e_isnanmax_np(); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( max `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int rc = 0; /* Return Code */
switch( nb )
{
case NBR_32 :
rc = e_isnanmax_32( ee, nb );
break;
case NBR_64 :
rc = e_isnanmax_64( ee, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
rc = e_isnanmax_np( ee, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of e_isnanmax() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/ei_nanmin_emu32lsb.dfn>
#else
#include <r_const/ei_nanmin_emu32msb.dfn>
#endif
void ei_nanmin( EMUSHORT *ei, unsigned sign, int nb )
/***************************************************************
Description : ei_nanmin() Работает с
internal e-type data struct.
Concepts : формирует минимальное `не число'
(+/- 1.NAN)
Sign Exp 1. Significand
==== ===== == ===========
S 1...1 1 00.......01,
которое не равно nan_max и ind.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int sn = 0;
size_t np = internal_np( nb ) * SIZE_OF_EMUSHORT;
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ei, (void *)&_ei_nanmin_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of ei_nanmin() */
int ei_isnanmin( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_isnanmin() Работает с
internal e-type data
struct.
Concepts : проверка на минимальное `не число'
(+/- 1.NAN)
Sign Exp 1. Significand
==== ===== == ===========
S 1...1 1 00.......01,
которое не равно nan_max, и ind.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( min `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, ne, is, ns;
int rc = 0; /* Return Code */
ne = internal_ne( nb );
ns = internal_ns( nb );
/*************************************************************
NOTE:
====
Compare 'Exp' and 'Significand'; skip Sign, lgw and hgw.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 1; is = ne + 2;
#else
ie = ns + 2; is = 1;
#endif
ne *= SIZE_OF_EMUSHORT;
ns *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_128_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_128_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_256:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_256_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_256_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_512:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_512_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_512_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_1024:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_1024_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_1024_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_2048:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_2048_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_2048_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_4096:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_4096_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_4096_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_8192:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_8192_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_8192_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_16384:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_16384_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_16384_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_32768:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_32768_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_32768_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_65536:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_65536_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_65536_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_131072:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_nanmin_131072_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_nanmin_131072_[0][is], (size_t)ns )
) rc = 1;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of ei_isnanmin() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/e_nanmin_emu32lsb.dfn>
#else
#include <r_const/e_nanmin_emu32msb.dfn>
#endif
void e_nanmin( EMUSHORT *ee, unsigned sign, int nb )
/***************************************************************
Description : e_nanmin() Работает с
external e-type data struct.
Concepts : формирует минимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01,
которое не равно nan_max и ind.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
int sn = 0;
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_32_[sn][0], np );
break;
case NBR_64:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_64_[sn][0], np );
break;
case NBR_128:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ee, (void *)&_e_nanmin_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of e_nanmin() */
static int e_isnanmin_32( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnanmin_32() Работает с
external e-type data
struct.
Concepts : проверка на минимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01,
которое не равно nan_max и ind.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( min `не число') [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 0; /* Return Code */
e = (__mpu_uint32_t *)ee;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
}
/* skip Sign */
if( (*e & 0x7fffffff) == 0x7f800001 )
rc = 1;
return( rc );
} /* End of e_isnanmin_32() */
static int e_isnanmin_64( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnanmin_64() Работает с
external e-type data
struct.
Concepts : проверка на минимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01,
которое не равно nan_max и ind.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( min `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 1; /* Return Code */
e = (__mpu_uint32_t *)ee;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
/* skip Sign */
if( (*e & 0x7fffffff) == 0x7ff00000 ) rc &= 1;
else rc &= 0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
e++; /* low part of real32 data struct */
#else
e--;
#endif
if( *e == 0x00000001 ) rc &= 1;
else rc &= 0;
return( rc );
} /* End of e_isnanmin_64() */
static int e_isnanmin_np( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnanmin_np() Работает с
external e-type data
struct.
Concepts : проверка на минимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01,
которое не равно nan_max и ind.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( min `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, is, np;
int rc = 1; /* Return Code */
np = internal_np( nb ) - 3; /* Sign, hgw, lgw */
/*************************************************************
NOTE:
====
Compare 'Exp' and 'Significand'; skip Sign.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 1; is = 0;
#else
ie = 0; is = np - 1;
#endif
--np;
/* skip Sign */
if( (ee[is] & HIGHT_EXP) == HIGHT_EXP ) rc &= 1;
else rc &= 0;
np *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_128:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_128_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_256:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_256_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_512:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_512_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_1024:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_1024_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_2048:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_2048_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_4096:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_4096_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_8192:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_8192_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_16384:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_16384_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_32768:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_32768_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_65536:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_65536_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_131072:
if( !memcmp( (void *)&ee[ie], (void *)&_e_nanmin_131072_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of e_isnanmin_np() */
int e_isnanmin( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isnanmin() Работает с
external e-type data struct.
Concepts : проверка на минимальное `не число'
(+/- 1.NAN)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......01,
которое не равно nan_max и ind.
Use Global Variable:
Use Functions :
e_isnanmin_32(); | this file
e_isnanmin_64(); | this file
e_isnanmin_np(); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( min `не число' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int rc = 0; /* Return Code */
switch( nb )
{
case NBR_32 :
rc = e_isnanmin_32( ee, nb );
break;
case NBR_64 :
rc = e_isnanmin_64( ee, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
rc = e_isnanmin_np( ee, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of e_isnanmin() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/ei_inf_emu32lsb.dfn>
#else
#include <r_const/ei_inf_emu32msb.dfn>
#endif
void ei_infin( EMUSHORT *ei, unsigned sign, int nb )
/***************************************************************
Description : ei_infin() Работает с
internal e-type data struct.
Concepts : формирует `бесконечность' (+/- 1.INF)
Sign Exp 1. Significand
==== ===== == ===========
S 1...1 1 00.......00,
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int sn = 0;
size_t np = internal_np( nb ) * SIZE_OF_EMUSHORT;
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
(void)memcpy( (void *)ei, (void *)&_ei_inf_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ei, (void *)&_ei_inf_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ei, (void *)&_ei_inf_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ei, (void *)&_ei_inf_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ei, (void *)&_ei_inf_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ei, (void *)&_ei_inf_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ei, (void *)&_ei_inf_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ei, (void *)&_ei_inf_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ei, (void *)&_ei_inf_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ei, (void *)&_ei_inf_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ei, (void *)&_ei_inf_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of ei_infin() */
int ei_isinfin( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_ininfin() Работает с
internal e-type data struct.
Concepts : проверка на `бесконечность' (+/- 1.INF)
Sign Exp 1. Significand
==== ===== == ===========
S 1...1 1 00.......00,
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `бесконечность' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, ne, is, ns;
int rc = 0; /* Return Code */
ne = internal_ne( nb );
ns = internal_ns( nb );
/*************************************************************
NOTE:
====
Compare 'Exp' and 'Significand'; skip Sign, lgw and hgw.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 1; is = ne + 2;
#else
ie = ns + 2; is = 1;
#endif
ne *= SIZE_OF_EMUSHORT;
ns *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_128_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_128_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_256:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_256_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_256_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_512:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_512_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_512_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_1024:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_1024_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_1024_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_2048:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_2048_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_2048_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_4096:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_4096_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_4096_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_8192:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_8192_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_8192_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_16384:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_16384_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_16384_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_32768:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_32768_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_32768_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_65536:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_65536_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_65536_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_131072:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_inf_131072_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_inf_131072_[0][is], (size_t)ns )
) rc = 1;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of ei_isinfin() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/e_inf_emu32lsb.dfn>
#else
#include <r_const/e_inf_emu32msb.dfn>
#endif
void e_infin( EMUSHORT *ee, unsigned sign, int nb )
/***************************************************************
Description : e_infin() Работает с
external e-type data struct.
Concepts : формирует `бесконечность' (+/- 1.INF)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......00,
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
int sn = 0;
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
(void)memcpy( (void *)ee, (void *)&_e_inf_32_[sn][0], np );
break;
case NBR_64:
(void)memcpy( (void *)ee, (void *)&_e_inf_64_[sn][0], np );
break;
case NBR_128:
(void)memcpy( (void *)ee, (void *)&_e_inf_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ee, (void *)&_e_inf_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ee, (void *)&_e_inf_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ee, (void *)&_e_inf_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ee, (void *)&_e_inf_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ee, (void *)&_e_inf_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ee, (void *)&_e_inf_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ee, (void *)&_e_inf_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ee, (void *)&_e_inf_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ee, (void *)&_e_inf_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ee, (void *)&_e_inf_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of e_infin() */
static int e_isinfin_32( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isinfin_32() Работает с
external e-type data
struct.
Concepts : проверка на `бесконечность' (+/- 1.INF)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......00,
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `бесконечность' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 0; /* Return Code */
e = (__mpu_uint32_t *)ee;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
}
/* skip Sign */
if( (*e & 0x7fffffff) == 0x7f800000 )
rc = 1;
return( rc );
} /* End of e_isinfin_32() */
static int e_isinfin_64( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isinfin_64() Работает с
external e-type data
struct.
Concepts : проверка на `бесконечность' (+/- 1.INF)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......0,
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `бесконечность' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 1; /* Return Code */
e = (__mpu_uint32_t *)ee;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
/* skip Sign */
if( (*e & 0x7fffffff) == 0x7ff00000 ) rc &= 1;
else rc &= 0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
e++; /* low part of real32 data struct */
#else
e--;
#endif
if( *e == 0x00000000 ) rc &= 1;
else rc &= 0;
return( rc );
} /* End of e_isinfin_64() */
static int e_isinfin_np( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_ininfin_np() Работает с
external e-type data
struct.
Concepts : проверка на `бесконечность' (+/- 1.INF)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......00,
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `бесконечность' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, is, np;
int rc = 1; /* Return Code */
np = internal_np( nb ) - 3; /* Sign, hgw, lgw */
/*************************************************************
NOTE:
====
Compare 'Exp' and 'Significand'; skip Sign.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 1; is = 0;
#else
ie = 0; is = np - 1;
#endif
--np;
/* skip Sign */
if( (ee[is] & HIGHT_EXP) == HIGHT_EXP ) rc &= 1;
else rc &= 0;
np *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_128:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_128_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_256:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_256_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_512:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_512_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_1024:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_1024_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_2048:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_2048_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_4096:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_4096_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_8192:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_8192_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_16384:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_16384_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_32768:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_32768_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_65536:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_65536_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_131072:
if( !memcmp( (void *)&ee[ie], (void *)&_e_inf_131072_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of e_isinfin_np() */
int e_isinfin( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isinfin() Работает с
external e-type data struct.
Concepts : проверка на `бесконечность' (+/- 1.INF)
Sign Exp Significand
==== ===== ===========
S 1...1 00.......00,
Use Global Variable:
Use Functions :
e_isinfin_32(); | this file
e_isinfin_64(); | this file
e_isinfin_np(); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `бесконечность' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int rc = 0; /* Return Code */
switch( nb )
{
case NBR_32 :
rc = e_isinfin_32( ee, nb );
break;
case NBR_64 :
rc = e_isinfin_64( ee, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
rc = e_isinfin_np( ee, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of e_isinfin() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/e_realmin_emu32lsb.dfn>
#else
#include <r_const/e_realmin_emu32msb.dfn>
#endif
void e_realmin( EMUSHORT *ee, unsigned sign, int nb )
/***************************************************************
Description : e_realmin() Работает с
external e-type data struct.
Concepts : формирует `минимальное число'
Sign Exp Significand
==== ===== ===========
S 0..01 00.......00,
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
int sn = 0;
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
(void)memcpy( (void *)ee, (void *)&_e_realmin_32_[sn][0], np );
break;
case NBR_64:
(void)memcpy( (void *)ee, (void *)&_e_realmin_64_[sn][0], np );
break;
case NBR_128:
(void)memcpy( (void *)ee, (void *)&_e_realmin_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ee, (void *)&_e_realmin_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ee, (void *)&_e_realmin_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ee, (void *)&_e_realmin_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ee, (void *)&_e_realmin_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ee, (void *)&_e_realmin_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ee, (void *)&_e_realmin_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ee, (void *)&_e_realmin_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ee, (void *)&_e_realmin_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ee, (void *)&_e_realmin_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ee, (void *)&_e_realmin_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of e_realmin() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/e_realmax_emu32lsb.dfn>
#else
#include <r_const/e_realmax_emu32msb.dfn>
#endif
void e_realmax( EMUSHORT *ee, unsigned sign, int nb )
/***************************************************************
Description : e_realmax() Работает с
external e-type data struct.
Concepts : формирует `максимальное число' (+/- 0.0)
Sign Exp Significand
==== ===== ===========
S 1..10 11.......11,
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
int sn = 0;
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
(void)memcpy( (void *)ee, (void *)&_e_realmax_32_[sn][0], np );
break;
case NBR_64:
(void)memcpy( (void *)ee, (void *)&_e_realmax_64_[sn][0], np );
break;
case NBR_128:
(void)memcpy( (void *)ee, (void *)&_e_realmax_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ee, (void *)&_e_realmax_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ee, (void *)&_e_realmax_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ee, (void *)&_e_realmax_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ee, (void *)&_e_realmax_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ee, (void *)&_e_realmax_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ee, (void *)&_e_realmax_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ee, (void *)&_e_realmax_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ee, (void *)&_e_realmax_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ee, (void *)&_e_realmax_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ee, (void *)&_e_realmax_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of e_realmax() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/ei_null_emu32lsb.dfn>
#else
#include <r_const/ei_null_emu32msb.dfn>
#endif
void ei_signull( EMUSHORT *ei, unsigned sign, int nb )
/***************************************************************
Description : ei_signull() Работает с
internal e-type data struct.
Concepts : формирует `знаковый ноль' (+/- 0.0)
Sign Exp 1. Significand
==== ===== == ===========
S 0..00 0 00.......00,
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int sn = 0;
int np = internal_np( nb );
(void)memset( (void *)ei, 0, np * SIZE_OF_EMUSHORT );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
sn = np - 1;
#endif
if( sign )
ei[sn] = MASK_ALL_BITS;
} /* End of ei_signull() */
int ei_issignull( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_issignull() Работает с
internal e-type data struct.
Concepts : проверка на `знаковый ноль' (+/- 0.0)
Sign Exp 1. Significand
==== ===== == ===========
S 0..00 0 00.......00,
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `знаковый ноль' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, ne, is, ns;
int rc = 0; /* Return Code */
ne = internal_ne( nb );
ns = internal_ns( nb );
/*************************************************************
NOTE:
====
Compare 'Exp' and 'Significand'; skip Sign, lgw and hgw.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 1; is = ne + 2;
#else
ie = ns + 2; is = 1;
#endif
ne *= SIZE_OF_EMUSHORT;
ns *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_32:
case NBR_64:
case NBR_128:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_128_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_128_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_256:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_256_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_256_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_512:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_512_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_512_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_1024:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_1024_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_1024_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_2048:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_2048_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_2048_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_4096:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_4096_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_4096_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_8192:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_8192_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_8192_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_16384:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_16384_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_16384_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_32768:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_32768_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_32768_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_65536:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_65536_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_65536_[0][is], (size_t)ns )
) rc = 1;
break;
case NBR_131072:
if( !memcmp( (void *)&ei[ie], (void *)&_ei_null_131072_[0][ie], (size_t)ne ) &&
!memcmp( (void *)&ei[is], (void *)&_ei_null_131072_[0][is], (size_t)ns )
) rc = 1;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of ei_issignull() */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <r_const/e_null_emu32lsb.dfn>
#else
#include <r_const/e_null_emu32msb.dfn>
#endif
void e_signull( EMUSHORT *ee, unsigned sign, int nb )
/***************************************************************
Description : e_signull() Работает с
external e-type data
struct.
Concepts : формирует `знаковый ноль' (+/- 0.0)
Sign Exp Significand
==== ===== ===========
S 0..00 00.......00,
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
unsigned int sign; - знак формируемого
числа;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int sn = 0;
size_t np = nb / BITS_PER_BYTE_T; /* in Bytes */
if( sign ) sn = 1;
switch( nb )
{
case NBR_32:
(void)memcpy( (void *)ee, (void *)&_e_null_32_[sn][0], np );
break;
case NBR_64:
(void)memcpy( (void *)ee, (void *)&_e_null_64_[sn][0], np );
break;
case NBR_128:
(void)memcpy( (void *)ee, (void *)&_e_null_128_[sn][0], np );
break;
case NBR_256:
(void)memcpy( (void *)ee, (void *)&_e_null_256_[sn][0], np );
break;
case NBR_512:
(void)memcpy( (void *)ee, (void *)&_e_null_512_[sn][0], np );
break;
case NBR_1024:
(void)memcpy( (void *)ee, (void *)&_e_null_1024_[sn][0], np );
break;
case NBR_2048:
(void)memcpy( (void *)ee, (void *)&_e_null_2048_[sn][0], np );
break;
case NBR_4096:
(void)memcpy( (void *)ee, (void *)&_e_null_4096_[sn][0], np );
break;
case NBR_8192:
(void)memcpy( (void *)ee, (void *)&_e_null_8192_[sn][0], np );
break;
case NBR_16384:
(void)memcpy( (void *)ee, (void *)&_e_null_16384_[sn][0], np );
break;
case NBR_32768:
(void)memcpy( (void *)ee, (void *)&_e_null_32768_[sn][0], np );
break;
case NBR_65536:
(void)memcpy( (void *)ee, (void *)&_e_null_65536_[sn][0], np );
break;
case NBR_131072:
(void)memcpy( (void *)ee, (void *)&_e_null_131072_[sn][0], np );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
} /* End of e_signull() */
static int e_issignull_32( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_issignull_32() Работает с
external e-type data
struct.
Concepts : проверка на `знаковый ноль' (+/- 0.0)
Sign Exp Significand
==== ===== ===========
S 0..00 00.......00,
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `знаковый ноль' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 0; /* Return Code */
e = (__mpu_uint32_t *)ee;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
}
/* skip Sign */
if( (*e & 0x7fffffff) == (__mpu_uint32_t)0 )
rc = 1;
return( rc );
} /* End of e_issignull_32() */
static int e_issignull_64( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_issignull_64() Работает с
external e-type data
struct.
Concepts : проверка на `знаковый ноль' (+/- 0.0)
Sign Exp Significand
==== ===== ===========
S 0..00 00.......00,
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `знаковый ноль' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
int rc = 1; /* Return Code */
e = (__mpu_uint32_t *)ee;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
/* skip Sign */
if( (*e & 0x7fffffff) == (__mpu_uint32_t)0 ) rc &= 1;
else rc &= 0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
e++; /* low part of real32 data struct */
#else
e--;
#endif
if( *e == (__mpu_uint32_t)0 ) rc &= 1;
else rc &= 0;
return( rc );
} /* End of e_issignull_64() */
static int e_issignull_np( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_issignull_np() Работает с
external e-type data
struct.
Concepts : проверка на `знаковый ноль' (+/- 0.0)
Sign Exp Significand
==== ===== ===========
S 0..00 00.......00,
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `знаковый ноль' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int ie, is, np;
int rc = 1; /* Return Code */
np = internal_np( nb ) - 3; /* Sign, hgw, lgw */
/*************************************************************
NOTE:
====
Compare 'Exp' and 'Significand'; skip Sign.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ie = 1; is = 0;
#else
ie = 0; is = np - 1;
#endif
--np;
/* skip Sign */
if( (ee[is] & HIGHT_EXP) == (EMUSHORT)0 ) rc &= 1;
else rc &= 0;
np *= SIZE_OF_EMUSHORT;
switch( nb )
{
case NBR_128:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_128_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_256:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_256_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_512:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_512_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_1024:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_1024_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_2048:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_2048_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_4096:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_4096_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_8192:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_8192_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_16384:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_16384_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_32768:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_32768_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_65536:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_65536_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
case NBR_131072:
if( !memcmp( (void *)&ee[ie], (void *)&_e_null_131072_[0][ie], (size_t)np ) ) rc &= 1;
else rc &= 0;
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
break;
}
} /* End of switch( nb ) */
return rc;
} /* End of e_issignull_np() */
int e_issignull( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_issignull() Работает с
external e-type data struct.
Concepts : проверка на `знаковый ноль' (+/- 0.0)
Sign Exp Significand
==== ===== ===========
S 0..00 00.......00,
Use Global Variable:
Use Functions :
e_issignull_32(); | this file
e_issignull_64(); | this file
e_issignull_np(); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( `знаковый ноль' ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int rc = 0; /* Return Code */
switch( nb )
{
case NBR_32 :
rc = e_issignull_32( ee, nb );
break;
case NBR_64 :
rc = e_issignull_64( ee, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
rc = e_issignull_np( ee, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( rc );
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of e_issignull() */
void ei_neg( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_neg() Работает с
internal e-type data struct.
Concepts : Negate the e-type real number.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int np;
np = internal_np( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + np - 1; /* go to Sign */
#endif
*ei ^= MASK_ALL_BITS;
} /* End of ei_neg() */
int ei_isneg( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_isneg() Работает с
internal e-type data struct.
Concepts : Return 1 if Sign e-type real number is
nonzero, else return zero.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
***************************************************************/
{
int np;
np = internal_np( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + np - 1; /* go to Sign */
#endif
if( *ei & MASK_ALL_BITS ) return( 1 );
else return( 0 );
} /* End of ei_isneg() */
static void e_neg_32( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_neg_32() Работает с
external e-type data struct.
Concepts : Negate the e-type real number.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
__mpu_uint16_t *e;
e = (__mpu_uint16_t *)ee;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
*e ^= 0x8000;
} /* End of e_neg_32() */
static void e_neg_64( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_neg_64() Работает с
external e-type data struct.
Concepts : Negate the e-type real number.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
__mpu_uint32_t *e;
e = (__mpu_uint32_t *)ee;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
*e ^= 0x80000000;
} /* End of e_neg_64() */
static void e_neg_np( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_neg_np() Работает с
external e-type data struct.
Concepts : Negate the e-type real number.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int np;
np = internal_np( nb ) - 3; /* Sign, hgw, lgw */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ee = ee + np - 1; /* go to Sign */
#endif
*ee ^= MASK_SIGN;
} /* End of e_neg_np() */
void e_neg( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_neg() Работает с
external e-type data struct.
Concepts : Negate the e-type real number.
Use Global Variable:
Use Functions :
e_neg_32(); | this file
e_neg_64(); | this file
e_neg_np(); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
switch( nb )
{
case NBR_32 :
e_neg_32( ee, nb );
break;
case NBR_64 :
e_neg_64( ee, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
e_neg_np( ee, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return;
} /* End of e_neg() */
static int e_isneg_32( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isneg_32() Работает с
external e-type data struct.
Concepts : Return 1 if Sign e-type real number is
nonzero, else return zero.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( Sign == 1 ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint16_t *e;
e = (__mpu_uint16_t *)ee;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
if( *e & 0x8000 ) return( 1 );
else return( 0 );
} /* End of e_isneg_32() */
static int e_isneg_64( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isneg_64() Работает с
external e-type data struct.
Concepts : Return 1 if Sign e-type real number is
nonzero, else return zero.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( Sign == 1 ) [rc = 1];
else [rc = 0];
***************************************************************/
{
__mpu_uint32_t *e;
e = (__mpu_uint32_t *)ee;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real64 data struct */
#endif
if( *e & 0x80000000 ) return( 1 );
else return( 0 );
} /* End of e_isneg_64() */
static int e_isneg_np( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isneg_np() Работает с
external e-type data struct.
Concepts : Return 1 if Sign e-type real number is
nonzero, else return zero.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
***************************************************************/
{
int np;
np = internal_np( nb ) - 3; /* Sign, hgw, lgw */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ee = ee + np - 1; /* go to Sign */
#endif
if( *ee & MASK_SIGN ) return( 1 );
else return( 0 );
} /* End of e_isneg_np() */
int e_isneg( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_isneg() Работает с
external e-type data struct.
Concepts : Return 1 if Sign e-type real number is
nonzero, else return zero.
Use Global Variable:
Use Functions :
e_isneg_32(); | this file
e_isneg_64(); | this file
e_isneg_np(); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc;
if( Sign == 1 ) [rc = 1];
else [rc = 0];
***************************************************************/
{
int rc = 0; /* Return Code */
switch( nb )
{
case NBR_32 :
rc = e_isneg_32( ee, nb );
break;
case NBR_64 :
rc = e_isneg_64( ee, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
rc = e_isneg_np( ee, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return( rc );
} /* End of e_isneg() */
void ei_abs( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_abs() Работает с
internal e-type data struct.
Concepts : сбрасывает знак числа.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int np;
np = internal_np( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + np - 1; /* go to Sign */
#endif
*ei &= (EMUSHORT)0;
} /* End of ei_abs() */
static void e_abs_32( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_abs_32() Работает с
external e-type data struct.
Concepts : сбрасывает знак числа.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
__mpu_uint16_t *e;
e = (__mpu_uint16_t *)ee;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real32 data struct */
#endif
*e &= 0x7fff;
} /* End of e_abs_32() */
static void e_abs_64( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_abs_64() Работает с
external e-type data struct.
Concepts : сбрасывает знак числа.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
__mpu_uint32_t *e;
e = (__mpu_uint32_t *)ee;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
e++; /* high part of real64 data struct */
#endif
*e &= 0x7fffffff;
} /* End of e_abs_64() */
static void e_abs_np( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_abs_np() Работает с
external e-type data struct.
Concepts : сбрасывает знак числа.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int np;
np = internal_np( nb ) - 3; /* Sign, hgw, lgw */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ee = ee + np - 1; /* go to Sign */
#endif
*ee &= HIGHT_EXP;
} /* End of e_abs_np() */
void e_abs( EMUSHORT *ee, int nb )
/***************************************************************
Description : e_abs() Работает с
external e-type data struct.
Concepts : сбрасывает знак числа.
Use Global Variable:
Use Functions :
e_abs_32(); | this file
e_abs_64(); | this file
e_abs_np(); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
switch( nb )
{
case NBR_32 :
e_abs_32( ee, nb );
break;
case NBR_64 :
e_abs_64( ee, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
e_abs_np( ee, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
return;
} /* End of e_abs() */
/***************************************************************
Functions for LONG INTEGER NUMBERS.
(for Exponent in Internal e-type data struct.)
***************************************************************/
int ei_cmpe( EMUSHORT *a, EMUSHORT *b, int np )
/******************************************
SIGNED COMPARE TWO SIGNED INTEGER NUMBER
if( a > b ) return( 1);
if( a == b ) return( 0);
if( a < b ) return( -1);
******************************************/
{
EMUSHORT p, q;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
a += np - 1;
b += np - 1;
#endif
p = *a & MASK_SIGN;
q = *b & MASK_SIGN;
/* the signs are different */
if( p != q )
{
if( p == (EMUSHORT)0 ) return( 1 );
else return( -1 );
}
/* both are the same sign */
for( i = 0; i < np; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *a++ != *b++ )
#else
if( *a-- != *b-- )
#endif
{
/* different */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *(--a) > *(--b) )
#else
if( *(++a) > *(++b) )
#endif
return( 1 );
else
return( -1 );
} /* End if( != ) */
} /* End for( i = 0; i < np; i++ ) */
return( 0 );
} /* End of ei_cmpe() */
int ei_cmp0e( EMUSHORT *a, int np )
/******************************************
SIGNED COMPARE A with ZERO
if( a > 0 ) return( 1);
if( a == 0 ) return( 0);
if( a < 0 ) return( -1);
******************************************/
{
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
a += np - 1;
#endif
/* the sign are negative */
if( *a & MASK_SIGN ) return( -1 );
else
{
/* the sign are positive */
for( i = 0; i < np; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *a++ != (EMUSHORT)0 )
#else
if( *a-- != (EMUSHORT)0 )
#endif
return( 1 );
} /* End for( i = 0; i < np; i++ ) */
} /* End if( sign ) */
return( 0 );
} /* End of ei_cmp0e() */
void ei_cpye_pack( EMUSHORT *a, EMUSHORT *b, int npa, int npb )
/*************************************************
КОПИРОВАНИЕ БОЛЬШЕГО В МЕНЬШЕЕ (npa < npb)
*************************************************/
{
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
a += npa - 1; /* low part */
b += npb - 1;
#endif
for( i = 0; i < npa; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*a-- = *b--;
#else
*a++ = *b++;
#endif
} /* End for( i = 0; i < npa; i++ ) */
} /* End of ei_cpye_pack() */
void ei_cpye_unpack( EMUSHORT *a, EMUSHORT *b, int npa, int npb )
/*************************************************
КОПИРОВАНИЕ МЕНЬШЕГО В БОЛЬШЕЕ (npa >= npb)
*************************************************/
{
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
a += npa - 1; /* low part */
b += npb - 1;
#endif
for( i = 0; i < npb; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*a-- = *b--;
#else
*a++ = *b++;
#endif
} /* End for( i = 0; i < npb; i++ ) */
while( i < npa )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*a-- = (EMUSHORT)0;
#else
*a++ = (EMUSHORT)0;
#endif
i++;
}
} /* End of ei_cpye_unpack() */
void ei_cpye( EMUSHORT *a, EMUSHORT *b, int npa, int npb )
/*************************************************
COPY UNSIGNED INTEGER NUMBER
*************************************************/
{
if( npa >= npb ) ei_cpye_unpack( a, b, npa, npb );
else ei_cpye_pack ( a, b, npa, npb );
}
void ei_cvte_unpack( EMUSHORT *a, EMUSHORT *b, int npa, int npb )
/*************************************************
КОНВЕРТИРОВАНИЕ МЕНЬШЕГО В БОЛЬШЕЕ (npa >= npb)
*************************************************/
{
EMUSHORT save_sign = (EMUSHORT)0;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
a += npa - 1; /* low part */
b += npb - 1;
#endif
for( i = 0; i < npb; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*a-- = *b--;
#else
*a++ = *b++;
#endif
} /* End for( i = 0; i < npb; i++ ) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
b++;
#else
b--;
#endif
if( *b & MASK_SIGN ) save_sign = MASK_ALL_BITS;
while( i < npa )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*a-- = save_sign;
#else
*a++ = save_sign;
#endif
i++;
}
} /* End of ei_cvte_unpack() */
void ei_cvte_pack( EMUSHORT *a, EMUSHORT *b, int npa, int npb )
/*************************************************
КОНВЕРТИРОВАНИЕ БОЛЬШЕГО В МЕНЬШЕЕ (npa < npb)
*************************************************/
{
EMUSHORT save_sign = (EMUSHORT)0;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *b & MASK_SIGN ) save_sign = MASK_SIGN;
#else
if( *(b + npb - 1) & MASK_SIGN ) save_sign = MASK_SIGN;
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
a += npa - 1; /* low part */
b += npb - 1;
#endif
for( i = 0; i < npa; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*a-- = *b--;
#else
*a++ = *b++;
#endif
} /* End for( i = 0; i < npa; i++ ) */
if( save_sign )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(++a) |= save_sign;
#else
*(--a) |= save_sign;
#endif
}
else
{
/* ПРИНУДИТЕЛЬНЫЙ POSITIVE */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(++a) &= HIGHT_EXP;
#else
*(--a) &= HIGHT_EXP;
#endif
}
} /* End of ei_cvte_pack() */
void ei_cvte( EMUSHORT *a, EMUSHORT *b, int npa, int npb )
/*************************************************
CONVERT SIGNED INTEGER NUMBER
*************************************************/
{
if( npa >= npb ) ei_cvte_unpack( a, b, npa, npb );
else ei_cvte_pack ( a, b, npa, npb );
}
void ei_adde( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
/******************************************
ADD INTEGER NUMBER
******************************************/
{
EMULONG rc, carry = 0;
EMUSHORT *z, *x, *y;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* point to low part */
x = a + np - 1;
y = b + np - 1;
z = c + np - 1;
#else
/* point to low part */
x = a;
y = b;
z = c;
#endif
for( i = 0; i < np; i++ )
{
rc = (EMULONG)(*x) + (EMULONG)(*y) + carry;
if( rc & MASK_CARRY ) carry = 1;
else carry = 0;
*z = (EMUSHORT)rc;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--x;
--y;
--z;
#else
++x;
++y;
++z;
#endif
} /* End for( i = 0; i < np; i++ ) */
} /* End of ei_adde() */
void ei_ince( EMUSHORT *c, EMUSHORT *a, int np )
/******************************************
INCrement INTEGER NUMBER
******************************************/
{
EMULONG rc, carry = 1;
EMUSHORT *z, *x;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* point to low part */
x = a + np - 1;
z = c + np - 1;
#else
/* point to low part */
x = a;
z = c;
#endif
for( i = 0; i < np; i++ )
{
rc = (EMULONG)(*x) + carry;
if( rc & MASK_CARRY ) carry = 1;
else carry = 0;
*z = (EMUSHORT)rc;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--x;
--z;
#else
++x;
++z;
#endif
} /* End for( i = 0; i < np; i++ ) */
} /* End of ei_ince() */
void ei_sube( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
/******************************************
SUB INTEGER NUMBER
******************************************/
{
EMULONG rc, carry = 0;
EMUSHORT *z, *x, *y;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* point to low part */
x = a + np - 1;
y = b + np - 1;
z = c + np - 1;
#else
/* point to low part */
x = a;
y = b;
z = c;
#endif
for( i = 0; i < np; i++ )
{
rc = (EMULONG)(*x) - (EMULONG)(*y) - carry;
if( rc & MASK_CARRY ) carry = 1;
else carry = 0;
*z = (EMUSHORT)rc;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--x;
--y;
--z;
#else
++x;
++y;
++z;
#endif
} /* End for( i = 0; i < np; i++ ) */
} /* End of ei_sube() */
void ei_dece( EMUSHORT *c, EMUSHORT *a, int np )
/******************************************
DECrement INTEGER NUMBER
******************************************/
{
EMULONG rc, carry = 1;
EMUSHORT *z, *x;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* point to low part */
x = a + np - 1;
z = c + np - 1;
#else
/* point to low part */
x = a;
z = c;
#endif
for( i = 0; i < np; i++ )
{
rc = (EMULONG)(*x) - carry;
if( rc & MASK_CARRY ) carry = 1;
else carry = 0;
*z = (EMUSHORT)rc;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--x;
--z;
#else
++x;
++z;
#endif
} /* End for( i = 0; i < np; i++ ) */
} /* End of ei_dece() */
void ei_nege( EMUSHORT *c, EMUSHORT *a, int np )
/******************************************
NEGATE Signed INTEGER NUMBER
******************************************/
{
EMULONG rc, carry = 1;
EMUSHORT *z, *x;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* point to low part */
x = a + np - 1;
z = c + np - 1;
#else
/* point to low part */
x = a;
z = c;
#endif
for( i = 0; i < np; i++ )
{
rc = (EMULONG)(~(*x)) + carry;
if( rc & MASK_CARRY ) carry = 1;
else carry = 0;
*z = (EMUSHORT)rc;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--x;
--z;
#else
++x;
++z;
#endif
} /* End for( i = 0; i < np; i++ ) */
} /* End of ei_nege() */
void ei_ande( EMUSHORT *c, EMUSHORT *a, EMUSHORT *b, int np )
/******************************************
AND INTEGER NUMBER
******************************************/
{
EMUSHORT *z, *x, *y;
int i;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* point to low part */
x = a + np - 1;
y = b + np - 1;
z = c + np - 1;
#else
/* point to low part */
x = a;
y = b;
z = c;
#endif
for( i = 0; i < np; i++ )
{
*z = (*x) & (*y);
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--x;
--y;
--z;
#else
++x;
++y;
++z;
#endif
} /* End for( i = 0; i < np; i++ ) */
} /* End of ei_ande() */
/***************************************************************
СДВИГИ
***************************************************************/
#define N_SC_PARTS(b) ((b)>>POW2)
#define N_SC_BITS(b) ((b)&(BITS_PER_EMUSHORT-1))
void ei_shrn( EMUSHORT *c, EMUSHORT *a, unsigned b, int np )
/******************************************
SHIFT RIGHT
******************************************/
{
EMUSHORT *x, *y, tmp;
int i, n_parts = 0, n_bits = 0;
if( np == 0 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
if( b > BITS_PER_EMUSHORT*np )
{
for( i = 0; i < np; i++ ) c[i] = (EMUSHORT)0;
return;
}
n_parts = N_SC_PARTS(b);
n_bits = N_SC_BITS(b);
if( b == 0 )
{
for( i = 0; i < np; i++ ) c[i] = a[i];
return;
}
if( n_parts == np )
{
for( i = 0; i < np; i++ ) c[i] = (EMUSHORT)0;
return;
}
if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
{
x = a;
y = c;
i = np;
while( i ) { *y = *x; x++; y++; i--; }
}
if( n_parts )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
x = a + np - 1 - n_parts;
y = c + np - 1 - n_parts;
#else
x = a + n_parts;
y = c + n_parts;
#endif
i = np - n_parts;
while( i )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(y + n_parts) = *x;
#else
*(y - n_parts) = *x;
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
x--;
y--;
#else
x++;
y++;
#endif
i--;
}
i = n_parts;
while( i )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
y++;
#else
y--;
#endif
*y = 0;
i--;
}
} /* End if( n_parts ) */
if( n_bits )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
y = c + np - 1;
#else
y = c;
#endif
*y = *y >> n_bits;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
y--;
#else
y++;
#endif
i = np - 1;
while( i )
{
tmp = *y;
*y = *y >> n_bits;
tmp = tmp << (BITS_PER_EMUSHORT-n_bits);
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(y + 1) |= tmp;
#else
*(y - 1) |= tmp;
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
y--;
#else
y++;
#endif
i--;
}
} /* End if( n_bits ) */
} /* End of ei_shrn() */
void ei_shln( EMUSHORT *c, EMUSHORT *a, unsigned b, int np )
/******************************************
SHIFT LEFT
******************************************/
{
EMUSHORT *x, *y, tmp;
int i, n_parts = 0, n_bits = 0;
if( np == 0 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
if( b > BITS_PER_EMUSHORT*np )
{
for( i = 0; i < np; i++ ) c[i] = (EMUSHORT)0;
return;
}
n_parts = N_SC_PARTS(b);
n_bits = N_SC_BITS(b);
if( b == 0 )
{
for( i = 0; i < np; i++ ) c[i] = a[i];
return;
}
if( n_parts == np )
{
for( i = 0; i < np; i++ ) c[i] = (EMUSHORT)0;
return;
}
if( n_parts == 0 ) /* переписываем c <= a, т.к. n_bits уже != 0 */
{
x = a;
y = c;
i = np;
while( i ) { *y = *x; x++; y++; i--; }
}
if( n_parts )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
x = a + n_parts;
y = c + n_parts;
#else
x = a + np - 1 - n_parts;
y = c + np - 1 - n_parts;
#endif
i = np - n_parts;
while( i )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(y - n_parts) = *x;
#else
*(y + n_parts) = *x;
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
x++;
y++;
#else
x--;
y--;
#endif
i--;
}
i = n_parts;
while( i )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
y--;
#else
y++;
#endif
*y = 0;
i--;
}
} /* End if( n_parts ) */
if( n_bits )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
y = c;
#else
y = c + np - 1;
#endif
*y = *y << n_bits;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
y++;
#else
y--;
#endif
i = np - 1;
while( i )
{
tmp = *y;
*y = *y << n_bits;
tmp = tmp >> (BITS_PER_EMUSHORT-n_bits);
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(y - 1) |= tmp;
#else
*(y + 1) |= tmp;
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
y++;
#else
y--;
#endif
i--;
}
} /* End if( n_bits ) */
} /* End of ei_shln() */
/***************************************************************
End of Functions for LONG INTEGER NUMBERS.
***************************************************************/
void ei_shdown( EMUSHORT *ei, unsigned sc, int nb )
/***************************************************************
Description : ei_shdown() Работает с
internal e-type data struct.
Concepts : shift right Significand of exploded
internal e-type data struct.
Guard words are included in the shift.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int sc; - количество
сдвигаемых бит.
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int ns;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
int ne;
ne = internal_ne( nb );
ei = ei + ne + 1; /* point to hgw */
#endif /* else point to lgw */
ns = internal_ns( nb );
ei_shrn( ei, ei, sc, ns + 2 );
} /* End of ei_shdown() */
void ei_shup( EMUSHORT *ei, unsigned sc, int nb )
/***************************************************************
Description : ei_shup() Работает с
internal e-type data struct.
Concepts : shift left Significand of exploded
internal e-type data struct.
Guard words are included in the shift.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int sc; - количество
сдвигаемых бит.
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int ns;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
int ne;
ne = internal_ne( nb );
ei = ei + ne + 1; /* point to hgw */
#endif /* else point to lgw */
ns = internal_ns( nb );
ei_shln( ei, ei, sc, ns + 2 );
} /* End of ei_shup() */
int ei_shift( EMUSHORT *ei, int sc, int nb )
/***************************************************************
Description : ei_shift() Работает с
internal e-type data struct.
Concepts : shift the Significand of exploded
internal e-type data struct.
Guard words are included in the shift.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
ei_shup( *ei, sc, nb ); | this file
ei_shdown( *ei, sc, nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int sc; - количество
сдвигаемых бит
(positive = up).
int nb; - количество бит в
external e-type
data struct.
Return : int lost;
if( sc < 0 &&
`выдвинут хотябы один единичный бит' )
[lost = 1];
else [lost = 0];
***************************************************************/
{
EMUSHORT lost = (EMUSHORT)0;
EMUSHORT *p;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
int ne;
#endif
int ns;
if( sc == 0 ) return( (int)lost );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ne = internal_ne( nb );
p = ei + ne + 1; /* point to hgw */
#else
p = ei; /* point to lgw */
#endif
ns = internal_ns( nb );
if( sc < 0 )
{
int i, k, ks;
sc = -sc;
/********************************************
remember lost bits
********************************************/
k = EMUSHORTSIZE(sc) - 1;
for( i = 0; i < k; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lost |= p[ns + 1 - i];
#else
lost |= p[i];
#endif
}
ks = sc - k*BITS_PER_EMUSHORT;
for( i = 0; i < ks; i++ )
{
lost |= ORDER_BIT( p, i + k*BITS_PER_EMUSHORT, ns+2 );
}
/******* end of remember lost bits **********/
ei_shdown( ei, (unsigned)sc, nb );
}
else
{
ei_shup( ei, (unsigned)sc, nb );
}
if( lost ) lost = (EMUSHORT)1;
return( (int)lost );
} /* End of ei_shift() */
/***************************************************************
NOTE:
Количество бит мантиссы вещественного числа во внутреннем
формате не должно превышать максимального положительного
signed EMUSHORT, которому соответствует тип __mpu_int32_t.
***************************************************************/
/* количество бит в Significand in Internal e-type data struct */
#define EINSBITS(nb) ((__mpu_int32_t)(internal_ns(nb)*BITS_PER_EMUSHORT))
__mpu_int32_t ei_normalize( EMUSHORT *ei, int nb )
/***************************************************************
Description : ei_normalize() Работает с
internal e-type data
struct.
Concepts : left-justify the Significand of exploded
internal e-type data struct.
Guard words are included in the shift.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
ei_shup( *ei, sc, nb ); | this file
ei_shdown( *ei, sc, nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : __mpu_int32_t sc; - shift counter.
if( sc < 0 ) => был сдвиг вверх;
else if( sc == 0 ) => сдвигов не было;
else => был сдвиг вниз;
***************************************************************/
{
__mpu_int32_t sc = 0; /* Ret. Code (shift counter) */
EMUSHORT *p;
int ns;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
int ne;
ne = internal_ne( nb );
p = ei + ne + 1; /* point to hgw */
#endif
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
p = ei + ns + 1; /* point to hgw */
#endif
if( *p == 0 ) /* normalize up (left) */
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p++;
#else
p--;
#endif
if( *p & MASK_SIGN )
return( sc ); /* already normalized (sc = 0) */
/*******************************************
Left-justify the Significand.
*******************************************/
while( *p == (EMUSHORT)0 )
{
ei_shup( ei, (unsigned)BITS_PER_EMUSHORT, nb );
sc += BITS_PER_EMUSHORT;
if( sc > EINSBITS(nb) )
{
/*
With guard word, there are
EINSBITS(nb)+BITS_PER_EMUSHORT
bits available.
Return true if all are zero
(SIGNED NULL or ei_cleazs(), for example).
*/
return( sc );
}
}
/* see if high byte is zero */
while( (*p & HIGHT_BYTE) == (EMUSHORT)0 )
{
ei_shup( ei, (unsigned)8, nb );
sc += 8;
}
/* now shift 1 bit at a time */
while( (*p & MASK_SIGN) == (EMUSHORT)0 )
{
ei_shup( ei, (unsigned)1, nb );
sc += 1;
if( sc > EINSBITS(nb) )
{
/* ONLY: выставить ошибку и вернуть SC */
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* Not change */
(__mpu_char8_t *)"ei_normalize", __UNDERFLOW__,
(EMUSHORT *)0,
(EMUSHORT *)0, (EMUSHORT *)0, nb );
__STUDF; /* Set REAL Underflow Flag */
return( sc );
}
}
} /* End of normalize up (left) */
else /* normalize down (right) */
{
/*******************************************
Normalize by shifting down (right) out of
the high guard word of the Significand.
*******************************************/
while( *p != (EMUSHORT)0 )
{
ei_shdown( ei, (unsigned)1, nb );
sc -= 1;
if( sc < - EINSBITS(nb) )
{
/* ONLY: выставить ошибку и вернуть SC */
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* Not change */
(__mpu_char8_t *)"ei_normalize", __OVERFLOW__,
(EMUSHORT *)0,
(EMUSHORT *)0, (EMUSHORT *)0, nb );
__STOVF; /* Set REAL Overflow Flag */
return( sc );
}
}
} /* End of normalize down (right) */
__CLOVF; /* Clear REAL Overflow Flag */
__CLUDF; /* Clear REAL Underflow Flag */
return( sc );
} /* End of ei_normalize() */
static void unpack_32( EMUSHORT *ei, EMUSHORT *ee, int nb )
/***************************************************************
Description : unpack_32() Распаковывает real32 data
struct в internal e-type data
struct.
Concepts :
NOTE : Функция работает правильно только для
размеров EMUSHORT кратных 16 бит
(16,32,48,64,80,96,...).
SEE operator:
pe += (BITS_PER_EMUSHORT - 16) / 16
in LITTLE_ENDIAN case.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
память под нее
выделяется до
применения
unpack_32() и
ее размер на
совести
программиста;
EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *exone = NULL,
*inc = NULL,
*r = NULL;
EMUSHORT *p;
__mpu_uint16_t *he, *pe;
int denorm = 0;
__mpu_int32_t k;
int np, ne, ns, i;
errno = 0;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, inc, r . ********************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
r = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !r )
{
/* fatal error */
/* FREE exone *************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
he = (__mpu_uint16_t *)ee;
ei_cleaz( ei, nb ); /* clear out exploded internal
e-type real number. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
++he; /* point to high __mpu_uint16_t */
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = inc;
for( i = 0; i < ne - 1; i++ ) *p++ = (EMUSHORT)0;
*p = (EMUSHORT)0x7f;
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
p = r;
for( i = 0; i < ne - 1; i++ ) *p++ = (EMUSHORT)0;
*p = (EMUSHORT)(*he);
#else
/* hight part */
p = inc + ne - 1;
for( i = 0; i < ne - 1; i++ ) *p-- = (EMUSHORT)0;
*p = (EMUSHORT)0x7f;
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
p = r + ne - 1;
for( i = 0; i < ne - 1; i++ ) *p-- = (EMUSHORT)0;
*p = (EMUSHORT)(*he);
#endif
/* Sign */
if( *he & 0x8000 )
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*ei = MASK_ALL_BITS;
#else
*(ei + np - 1) = MASK_ALL_BITS;
#endif
/* hgw */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei[ne + 1] = (EMUSHORT)((*he & 0x7f) | 0x80);
#else
ei[ns + 1] = (EMUSHORT)((*he & 0x7f) | 0x80);
#endif
/* Skip Sign and 7 significand bits */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(r + ne - 1) &= (EMUSHORT)0x7f80; /* т.е. (~0x807f) */
#else
*r &= (EMUSHORT)0x7f80; /* т.е. (~0x807f) */
#endif
/****************
INFINITY
****************/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *(r + ne - 1) == 0x7f80 )
#else
if( *r == 0x7f80 )
#endif
{
/********
NANS
********/
/* indeterminacy */
if( e_isind( ee, nb ) )
{
ei_ind( ei, nb );
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nanmin */
if( e_isnanmin( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nanmin( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nanmin( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nanmax */
if( e_isnanmax( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nanmax( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nanmax( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nans */
if( e_isnans( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nan( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nan( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/**********
END NANS
**********/
ei_cleazs( ei, nb ); /* не трогать знак */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_infin( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_infin( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/**************
END INFINITY
**************/
ei_shrn( r, r, 7, ne );
/* If zero Exponent, then the Significand is denormalized.
So take back the understood high Significand bit. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *(r + ne - 1) == 0 )
#else
if( *r == 0 )
#endif
{
denorm = 1;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei[ne + 1] &= ~((EMUSHORT)0x80);
#else
ei[ns + 1] &= ~((EMUSHORT)0x80);
#endif
}
ei_sube( exone, exone, inc, ne );
ei_adde( r, r, exone, ne );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( &ei[1], r, ne, ne );
#else
ei_cpye_unpack( &ei[ns+2], r, ne, ne );
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
pe = (__mpu_uint16_t *)&ei[ne + 2];
/* NOTE: I not TEST !!! */
*pe = *(he + 1);
/* продолжение для e53
*(++pe) = *(he + 2);
*(++pe) = *(he + 3);
*/
#else
pe = (__mpu_uint16_t *)&ei[ns];
/* следующий оператор требуется только здесь */
pe += (BITS_PER_EMUSHORT - 16) / 16;
*pe = *(he - 1);
/* продолжение для e53
*(--pe) = *(he - 2);
*(--pe) = *(he - 3);
*/
#endif
ei_shift( ei, -8, nb ); /* `-' - down(right) */
if( denorm )
{
/* if zero Exponent, then normalize the Significand */
if( (k = ei_normalize(ei, nb)) > (__mpu_int32_t)EINSBITS(nb) )
ei_cleazs( ei, nb );
else
{
/* Exponent -= (k - 1); */
k -= 1;
ei_cvte_unpack( inc, (EMUSHORT *)&k, ne, 1 );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &ei[1];
#else
p = &ei[ns+2];
#endif
ei_sube( p, p, inc, ne );
}
} /* End if( denorm ) */
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of unpack_32() */
static void unpack_64( EMUSHORT *ei, EMUSHORT *ee, int nb )
/***************************************************************
Description : unpack_64() Распаковывает real64 data
struct в internal e-type data
struct.
Concepts :
NOTE : Функция работает правильно только для
размеров EMUSHORT кратных 16 бит
(16,32,48,64,80,96,...).
SEE operator:
pe += (BITS_PER_EMUSHORT - 16) / 16
in LITTLE_ENDIAN case.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
память под нее
выделяется до
применения
unpack_32() и
ее размер на
совести
программиста;
EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *exone = NULL,
*inc = NULL,
*r = NULL;
EMUSHORT *p;
__mpu_uint16_t *he, *pe;
int denorm = 0;
__mpu_int32_t k;
int np, ne, ns, i;
errno = 0;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, inc, r . ********************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
r = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !r )
{
/* fatal error */
/* FREE exone *************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
he = (__mpu_uint16_t *)ee;
ei_cleaz( ei, nb ); /* clear out exploded internal
e-type real number. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
he += 3; /* point to high word16bits */
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = inc;
for( i = 0; i < ne - 1; i++ ) *p++ = (EMUSHORT)0;
*p = (EMUSHORT)0x3ff;
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
p = r;
for( i = 0; i < ne - 1; i++ ) *p++ = (EMUSHORT)0;
*p = (EMUSHORT)(*he);
#else
/* hight part */
p = inc + ne - 1;
for( i = 0; i < ne - 1; i++ ) *p-- = (EMUSHORT)0;
*p = (EMUSHORT)0x3ff;
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
p = r + ne - 1;
for( i = 0; i < ne - 1; i++ ) *p-- = (EMUSHORT)0;
*p = (EMUSHORT)(*he);
#endif
/* Sign */
if( *he & 0x8000 )
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*ei = MASK_ALL_BITS;
#else
*(ei + np - 1) = MASK_ALL_BITS;
#endif
/* hgw */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei[ne + 1] = (EMUSHORT)((*he & 0x0f) | 0x10);
#else
ei[ns + 1] = (EMUSHORT)((*he & 0x0f) | 0x10);
#endif
/* Skip Sign and 7 significand bits */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(r + ne - 1) &= (EMUSHORT)0x7ff0; /* т.е. (~0x800f) */
#else
*r &= (EMUSHORT)0x7ff0; /* т.е. (~0x800f) */
#endif
/****************
INFINITY
****************/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *(r + ne - 1) == 0x7ff0 )
#else
if( *r == 0x7ff0 )
#endif
{
/********
NANS
********/
/* indeterminacy */
if( e_isind( ee, nb ) )
{
ei_ind( ei, nb );
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nanmin */
if( e_isnanmin( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nanmin( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nanmin( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nanmax */
if( e_isnanmax( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nanmax( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nanmax( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nans */
if( e_isnans( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nan( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nan( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/**********
END NANS
**********/
ei_cleazs( ei, nb ); /* не трогать знак */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_infin( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_infin( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/**************
END INFINITY
**************/
ei_shrn( r, r, 4, ne );
/* If zero Exponent, then the Significand is denormalized.
So take back the understood high Significand bit. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *(r + ne - 1) == 0 )
#else
if( *r == 0 )
#endif
{
denorm = 1;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei[ne + 1] &= ~((EMUSHORT)0x10);
#else
ei[ns + 1] &= ~((EMUSHORT)0x10);
#endif
}
ei_sube( exone, exone, inc, ne );
ei_adde( r, r, exone, ne );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( &ei[1], r, ne, ne );
#else
ei_cpye_unpack( &ei[ns+2], r, ne, ne );
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
pe = (__mpu_uint16_t *)&ei[ne + 2];
/* NOTE: I not TEST !!! */
*pe = *(he + 1);
*(++pe) = *(he + 2);
*(++pe) = *(he + 3);
#else
pe = (__mpu_uint16_t *)&ei[ns];
/* следующий оператор требуется только здесь */
pe += (BITS_PER_EMUSHORT - 16) / 16;
*pe = *(he - 1);
*(--pe) = *(he - 2);
*(--pe) = *(he - 3);
#endif
ei_shift( ei, -5, nb ); /* `-' - down(right) */
if( denorm )
{
/* if zero Exponent, then normalize the Significand */
if( (k = ei_normalize(ei, nb)) > (__mpu_int32_t)EINSBITS(nb) )
ei_cleazs( ei, nb );
else
{
/* Exponent -= (k - 1); */
k -= 1;
ei_cvte_unpack( inc, (EMUSHORT *)&k, ne, 1 );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &ei[1];
#else
p = &ei[ns+2];
#endif
ei_sube( p, p, inc, ne );
}
} /* End if( denorm ) */
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of unpack_64() */
/***************************************************************
NOTE:
EMUPART <= EMUSHORT всегда.
На данный момент мы используем размер в 32 бита как для
EMUSHORT, так и для EMUPART по тому, что работаем с
моделями ILP32, LP64 для машин с разрядностью до 64 бит.
В случаее 128-разрядных машин, следует сохранить размер
EMUPART в 32 бита, а размер EMUSHORT может быть 64 бита.
***************************************************************/
static void unpack_np( EMUSHORT *ei, EMUSHORT *ee, int nb )
/***************************************************************
Description : unpack_np() Распаковывает все начиная с
real128 (real128,...) data
struct в internal e-type
data struct.
Concepts :
NOTE :
Функция работает правильно только для
размеров EMUSHORT кратных
BITS_PER_EMUPART(16|32) бит.
SEE:
(BITS_PER_EMUSHORT - BITS_PER_EMUPART)
p += ----------------------------------------;
BITS_PER_EMUPART;
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
память под нее
выделяется до
применения
unpack_128() и
ее размер на
совести
программиста;
EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *exone = NULL,
*inc = NULL,
*r = NULL;
EMUSHORT *p;
EMUPART *he, *pe;
int denorm = 0;
__mpu_int32_t k;
int np, ne, ns, nex, nsx, i;
if( nb < NBR_128 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, inc, r . ********************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
r = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !r )
{
/* fatal error */
/* FREE exone *************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
nex = EMUPARTSIZE(NEBITS(nb));
nsx = EMUPARTSIZE(NSBITS(nb));
he = (EMUPART *)ee;
ei_cleaz( ei, nb ); /* clear out exploded internal
e-type real number. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
he += nex - 1; /* point to low EMUPART of Exponent */
#else
he += nsx; /* point to low EMUPART of Exponent */
#endif
/* inc используется для хранения EXONE исходного формата */
/*
но до ее основного применения она используется для:
1) проверки всех бит исходной экспоненты на 1;
2) проверки всех бит исходной экспоненты на 0;
*/
for( i = 0; i < ne; i++ ) inc[i] = (EMUSHORT)0;
for( i = 0; i < ne; i++ ) r[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* исходный формат EXONE */
/* low part */
pe = (EMUPART *)(inc + ne - 1);
pe += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* -------------------------------------- */
BITS_PER_EMUPART;
for( i = 0; i < nex - 1; i++ ) *pe-- = PART_MASK_ALL_BITS;
*pe = PART_HIGHT_EXP;
/* целевой формат EXONE */
/* hight part */
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
/* Copy Exponent */
/* low part */
pe = (EMUPART *)(r + ne - 1);
pe += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* -------------------------------------- */
BITS_PER_EMUPART;
for( i = 0; i < nex - 1; i++ ) *pe-- = *he--;
*pe = *he;
#else
/* исходный формат EXONE */
/* low part */
pe = (EMUPART *)inc;
for( i = 0; i < nex - 1; i++ ) *pe++ = PART_MASK_ALL_BITS;
*pe = PART_HIGHT_EXP;
/* целевой формат EXONE */
/* hight part */
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
/* Copy Exponent */
/* low part */
pe = (EMUPART *)r;
for( i = 0; i < nex - 1; i++ ) *pe++ = *he++;
*pe = *he;
#endif
/* NOW *he point to hight EMUPART of Exponent in the source format */
/* NOW *pe point to hight EMUPART of Exponent in the target (r) */
/* Sign */
if( *he & PART_MASK_SIGN )
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*ei = MASK_ALL_BITS;
#else
*(ei + np - 1) = MASK_ALL_BITS;
#endif
/* hgw */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei[ne + 1] = (EMUSHORT)1;
#else
ei[ns + 1] = (EMUSHORT)1;
#endif
/* Skip Sign */
*pe &= PART_HIGHT_EXP;
/****************
INFINITY
****************/
if( ei_cmpe( r, inc, ne ) == 0 ) /* r == inc */
{
/********
NANS
********/
/* indeterminacy */
if( e_isind( ee, nb ) )
{
ei_ind( ei, nb );
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nanmin */
if( e_isnanmin( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nanmin( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nanmin( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nanmax */
if( e_isnanmax( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nanmax( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nanmax( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nans */
if( e_isnans( ee, nb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nan( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_nan( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/**********
END NANS
**********/
ei_cleazs( ei, nb ); /* не трогать знак */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_infin( ei, ei[0] != (EMUSHORT)0, nb );
#else
ei_infin( ei, ei[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/**************
END INFINITY
**************/
/* If zero Exponent, then the Significand is denormalized.
So take back the understood high Significand bit. */
for( i = 0; i < ne; i++ ) inc[i] = (EMUSHORT)0;
if( ei_cmpe( r, inc, ne ) == 0 ) /* r == inc (inc = 0) */
{
denorm = 1;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei[ne + 1] = (EMUSHORT)0;
#else
ei[ns + 1] = (EMUSHORT)0;
#endif
}
/* Create EXONE of source format */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* исходный формат EXONE */
/* low part */
pe = (EMUPART *)(inc + ne - 1);
pe += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* -------------------------------------- */
BITS_PER_EMUPART;
for( i = 0; i < nex - 1; i++ ) *pe-- = PART_MASK_ALL_BITS;
*pe = PART_HIGHT_EXONE;
#else
/* исходный формат EXONE */
/* low part */
pe = (EMUPART *)inc;
for( i = 0; i < nex - 1; i++ ) *pe++ = PART_MASK_ALL_BITS;
*pe = PART_HIGHT_EXONE;
#endif
/* r += EXONEtarget - EXONEsource */
ei_sube( exone, exone, inc, ne );
ei_adde( r, r, exone, ne );
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( &ei[1], r, ne, ne );
#else
ei_cpye_unpack( &ei[ns+2], r, ne, ne );
#endif
/* Copy Significand */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
pe = (EMUPART *)&ei[ne + 2];
he = (EMUPART *)&ee[nex];
/* NOTE: I not TEST !!! */
for( i = 0; i < nsx; i++ ) *pe++ = *he++;
#else
pe = (EMUPART *)&ei[ns];
he = (EMUPART *)&ee[ns-1];
/* следующий оператор требуется только здесь */
pe += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* -------------------------------------- */
BITS_PER_EMUPART;
he += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* -------------------------------------- */
BITS_PER_EMUPART;
for( i = 0; i < nsx; i++ ) *pe-- = *he--;
#endif
ei_shift( ei, -1, nb ); /* `-' - down(right) */
if( denorm )
{
/* if zero Exponent, then normalize the Significand */
if( (k = ei_normalize(ei, nb)) > (__mpu_int32_t)EINSBITS(nb) )
ei_cleazs( ei, nb );
else
{
/* Exponent -= (k - 1); */
k -= 1;
ei_cvte_unpack( inc, (EMUSHORT *)&k, ne, 1 );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &ei[1];
#else
p = &ei[ns+2];
#endif
ei_sube( p, p, inc, ne );
}
} /* End if( denorm ) */
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of unpack_np() */
void unpack( EMUSHORT *ei, EMUSHORT *ee, int nb )
/***************************************************************
Description : unpack() Распаковывает `real<all>' data
struct в internal e-type data
struct.
Concepts :
Use Global Variable:
Use Functions :
unpack_32 ( *ei, *ee, nb ); | this file
unpack_64 ( *ei, *ee, nb ); | this file
unpack_np ( *ei, *ee, nb ); | this file
Parameters : EMUSHORT *ei; - указатель на
internal e-type
data struct;
память под нее
выделяется до
применения
unpack() и
ее размер на
совести
программиста;
EMUSHORT *ee; - указатель на
external e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *ex = NULL; /* External format */
int np;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
/*
NP in EMUPARTs.
BITS_PER_EMUPART == only(16 || 32).
*/
np = nb/(BITS_PER_EMUPART);
/*** Allocate memory for ex . *******************************/
ex = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUPART) );
if( !ex )
{
/* fatal error */
return;
}
/************************************************************/
/* copy EE to EX (External format) */
(void)memcpy( (void *)ex, (void *)ee, (size_t)(np*SIZE_OF_EMUPART) );
switch( nb )
{
case NBR_32 :
unpack_32( ei, ex, nb );
break;
case NBR_64 :
unpack_64( ei, ex, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
unpack_np( ei, ex, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
/* FREE ex ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUPART) );
/**************************/
return;
} /* End of unpack() */
int ei_cmpm( EMUSHORT *ai, EMUSHORT *bi, int nb )
/***************************************************************
Description : ei_cmpm() Compare Significands of numbers
in internal e-type data struct.
Concepts : Guard words are included in the
comparison.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ai; - указатель на
internal e-type
data struct;
EMUSHORT *bi; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc; - Result of Comparison.
if( ai > bi ) rc = +1;
if( ai == bi ) rc = 0;
if( ai < bi ) rc = -1;
***************************************************************/
{
EMUSHORT *x, *y;
int ne, ns, hgw, i;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( 0 );
}
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
hgw = ne + 1;
#else
hgw = ns + 1;
#endif
x = &ai[hgw];
y = &bi[hgw];
for( i = 0; i < ns + 2; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *x++ != *y++ )
#else
if( *x-- != *y-- )
#endif
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *(--x) > *(--y) )
#else
if( *(++x) > *(++y) )
#endif
return( 1 );
else
return( -1 );
} /* End if( != ) */
} /* End for( i = 0; i < ns+2; i++ ) */
return( 0 );
} /* End of ei_cmpm() */
void ei_addm( EMUSHORT *ci, EMUSHORT *ai, EMUSHORT *bi, int nb )
/***************************************************************
Description : ei_addm() Add Significands of e-type AI
and BI. AI + BI replaces CI.
Concepts : Guard words are included in the Add.
CI может указывать на любое число,
даже на AI или BI.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ci; - Result;
EMUSHORT *ai; - указатель на
internal e-type
data struct;
EMUSHORT *bi; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void].
***************************************************************/
{
EMULONG rc, carry = 0;
EMUSHORT *z, *x, *y;
int np, ns, i;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* point to lgw */
x = ai + np - 1;
y = bi + np - 1;
z = ci + np - 1;
#else
/* point to lgw */
x = ai;
y = bi;
z = ci;
#endif
for( i = 0; i < ns + 2; i++ )
{
rc = (EMULONG)(*x) + (EMULONG)(*y) + carry;
if( rc & MASK_CARRY ) carry = 1;
else carry = 0;
*z = (EMUSHORT)rc;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--x;
--y;
--z;
#else
++x;
++y;
++z;
#endif
} /* End for( i = 0; i < ns + 2; i++ ) */
} /* End of ei_addm() */
void ei_subm( EMUSHORT *ci, EMUSHORT *ai, EMUSHORT *bi, int nb )
/***************************************************************
Description : ei_subm() Subtract Significands of e-type
AI and BI. AI - BI replaces CI.
Concepts : Guard words are included in the
Subtraction. CI может указывать на любое
число, даже на AI или BI.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *ci; - Result;
EMUSHORT *ai; - указатель на
internal e-type
data struct;
EMUSHORT *bi; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void].
***************************************************************/
{
EMULONG rc, carry = 0;
EMUSHORT *z, *x, *y;
int np, ns, i;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* point to lgw */
x = ai + np - 1;
y = bi + np - 1;
z = ci + np - 1;
#else
/* point to lgw */
x = ai;
y = bi;
z = ci;
#endif
for( i = 0; i < ns + 2; i++ )
{
rc = (EMULONG)(*x) - (EMULONG)(*y) - carry;
if( rc & MASK_CARRY ) carry = 1;
else carry = 0;
*z = (EMUSHORT)rc;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--x;
--y;
--z;
#else
++x;
++y;
++z;
#endif
} /* End for( i = 0; i < ns + 2; i++ ) */
} /* End of ei_subm() */
/***************************************************************
Radix MAX[unsigned EMUSHORT] versions of multiply and divide.
if HOST_BITS_PER_EMUSHORT == 16(от 0 до 65 535),
then Radix = 65 536;
if HOST_BITS_PER_EMUSHORT == 32(от 0 до 4 294 967 295),
then Radix = 4 294 967 296;
if HOST_BITS_PER_EMUSHORT == 64(от 0 до 18 446 744 073 709 551 616),
then Radix = 18 446 744 073 709 551 616;
etc.
***************************************************************/
static void mEMUSHORTm( EMUSHORT *prodi, EMUSHORT *numi, EMUSHORT mul, int nb )
/************************************************
Multiply significand of e-type number NUMI
by BITS_PER_EMUSHORT-bit quantity MUL,
return e-type result to PRODI.
ВОЗМОЖНО ИСПОЛЬЗОВАНИЕ mEMUSHORTm(X,X,a,nb):
т.е. результат можно поместить на место
операнда NUMI.
************************************************/
{
EMUSHORT *pp;
EMULONG carry;
EMUSHORT *prod = NULL;
EMUSHORT *ps;
EMULONG a, m;
int i, np, ne, ns;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for prod . *****************************/
prod = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !prod )
{
/* fatal error */
return;
}
/************************************************************/
a = mul;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* low part of Significand */
pp = &prod[np - 2];
*pp++ = (EMUSHORT)0;
/* lgw */
ps = &numi[np - 1];
#else
/* low part of Significand */
pp = &prod[1];
*pp-- = (EMUSHORT)0;
/* lgw */
ps = &numi[0];
#endif
*pp = (EMUSHORT)0;
for( i = 0; i < ns + 1; i++ )
{
if( *ps == (EMUSHORT)0 )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--ps;
--pp;
*(pp-1) = (EMUSHORT)0;
#else
++ps;
++pp;
*(pp+1) = (EMUSHORT)0;
#endif
}
else
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
m = (EMULONG) a * *ps--;
#else
m = (EMULONG) a * *ps++;
#endif
carry = (m & MASK_ALL_BITS) + *pp;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*pp-- = (EMUSHORT)carry;
#else
*pp++ = (EMUSHORT)carry;
#endif
carry = (carry >> BITS_PER_EMUSHORT) + (m >> BITS_PER_EMUSHORT) + *pp;
*pp = (EMUSHORT)carry;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*(pp-1) = (EMUSHORT)(carry >> BITS_PER_EMUSHORT);
#else
*(pp+1) = (EMUSHORT)(carry >> BITS_PER_EMUSHORT);
#endif
}
} /* End for( i = 0; i < ns + 1; i++ ) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
for( i = ne + 1; i < np; i++ )
#else
for( i = 0; i < ns + 2; i++ )
#endif
prodi[i] = prod[i];
/* FREE prod **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of mEMUSHORTm() */
int ei_divm( EMUSHORT *quoti, EMUSHORT *numi, EMUSHORT *deni, int nb )
/***************************************************************
Description : ei_divm() Divide Significands of e-type
NUMI and DENI. NUMI / DENI
replaces QUOTI.
Concepts : Sign and Exponent of NUMI replaces Sign
and Exponent of QUOTI(NUMI[Sign,Exp] ->
QUOTI[Sign,Exp]).
QUOTI может указывать на любое число,
даже на NUMI или DENI.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *quoti; - Result;
EMUSHORT *numi; - указатель на
internal e-type
data struct -
ДЕЛИМОЕ;
EMUSHORT *deni; - указатель на
internal e-type
data struct -
ДЕЛИТЕЛЬ;
int nb; - количество бит в
external e-type
data struct.
Return : int j; - признак наличия
остатка от
деления;
if( remainder != 0 ) j = 1;
if( remainder == 0 ) j = 0;
if( error ) j = -1;
***************************************************************/
{
EMUSHORT *pcpy_num = NULL,
*pcpy_den = NULL,
*tprod = NULL;
EMUSHORT *p, *q;
EMULONG tnum;
EMUSHORT j, tdenm, tquot;
int i, np, ne, ns;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( -1 );
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for pcpy_num, pcpy_den, tprod . ********/
pcpy_num = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !pcpy_num )
{
/* fatal error */
return( -1 );
}
pcpy_den = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !pcpy_den )
{
/* fatal error */
/* FREE pcpy_num **********/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return( -1 );
}
tprod = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tprod )
{
/* fatal error */
/* FREE pcpy_num **********/
/* FREE pcpy_den **********/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return( -1 );
}
/************************************************************/
/* Copy NUM */
p = numi;
q = pcpy_num;
for( i = 0; i < np; i++ ) *q++ = *p++;
/* Copy DEN */
p = deni;
q = pcpy_den;
for( i = 0; i < np; i++ ) *q++ = *p++;
ei_cleaz( quoti, nb ); /* clear out exploded internal
e-type real number. */
/* Copy Sign & Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = pcpy_num;
q = quoti;
for( i = 0; i < ne + 1; i++ ) *q++ = *p++;
#else
/* hight part */
p = pcpy_num + np - 1;
q = quoti + np - 1;
for( i = 0; i < ne + 1; i++ ) *q-- = *p--;
#endif
ei_shdown( pcpy_num, (unsigned)1, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
tdenm = pcpy_den[ne + 2];
q = "i[nE + 1]; /* hgw */
#else
tdenm = pcpy_den[ns];
q = "i[ns + 1]; /* hgw */
#endif
for( i = 0; i < ns + 2; i++ )
{
/* Find trial quotient digit (the radix ...). */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
tnum = (((EMULONG)pcpy_num[ne + 1]) << BITS_PER_EMUSHORT) + pcpy_num[ne + 2];
#else
tnum = (((EMULONG)pcpy_num[ns + 1]) << BITS_PER_EMUSHORT) + pcpy_num[ns];
#endif
/* Do not execute the divide instruction if it will overflow. */
if( ((EMULONG)tdenm * MASK_ALL_BITS) < tnum )
tquot = MASK_ALL_BITS;
else
tquot = (EMUSHORT)(tnum / tdenm);
/* Multiply denominator by trial quotient digit. */
mEMUSHORTm( tprod, pcpy_den, tquot, nb );
/* The quotient digit may have been over estimated. */
if( ei_cmpm( tprod, pcpy_num, nb ) > 0 )
{
tquot -= 1;
ei_subm( tprod, tprod, pcpy_den, nb );
if( ei_cmpm( tprod, pcpy_num, nb ) > 0 )
{
tquot -= 1;
ei_subm( tprod, tprod, pcpy_den, nb );
}
}
ei_subm( pcpy_num, pcpy_num, tprod, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*q++ = tquot;
#else
*q-- = tquot;
#endif
ei_shup( pcpy_num, (unsigned)BITS_PER_EMUSHORT, nb );
}
/* test for nonzero remainder after roundoff bit */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* Set pointer to hgw */
p = &pcpy_num[ne + 1];
#else
/* Set pointer to hgw */
p = &pcpy_num[ns + 1];
#endif
j = (EMUSHORT)0;
for( i = 0; i < ns + 2; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
j |= *p++;
#else
j |= *p--;
#endif
}
if( j ) j = (EMUSHORT)1;
/* FREE pcpy_num **********/
/* FREE pcpy_den **********/
/* FREE tprod *************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return( (int)j );
} /* End of ei_divm() */
int ei_mulm( EMUSHORT *prodi, EMUSHORT *numi, EMUSHORT *muli, int nb )
/***************************************************************
Description : ei_mulm() Multiply Significands of e-type
NUMI and MULI. NUMI * MULI
replaces PRODI.
Concepts : Sign and Exponent of NUMI replaces Sign
and Exponent of PRODI(NUMI[Sign,Exp] ->
PRODI[Sign,Exp]).
PRODI может указывать на любое число,
даже на NUMI или MULI.
МАНТИССА МНОЖИТЕЛЯ НЕ МОЖЕТ БЫТЬ РАВНА
НУЛЮ.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *prodi; - Result;
EMUSHORT *numi; - указатель на
internal e-type
data struct -
МНОЖИМОЕ;
EMUSHORT *muli; - указатель на
internal e-type
data struct -
МНОЖИТЕЛЬ;
int nb; - количество бит в
external e-type
data struct.
Return : int j; - флаг потерянных
ненулевых бит;
if( lost nonzero bits != 0 ) j = 1;
if( lost nonzero bits == 0 ) j = 0;
if( error ) j = -1;
***************************************************************/
{
EMUSHORT *pcpy_num = NULL,
*pcpy_mul = NULL,
*tprod = NULL;
EMUSHORT *p, *q;
EMUSHORT j;
int i, np, ne, ns;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( -1 );
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for pcpy_num, pcpy_mul, tprod . ********/
pcpy_num = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !pcpy_num )
{
/* fatal error */
return( -1 );
}
pcpy_mul = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !pcpy_mul )
{
/* fatal error */
/* FREE pcpy_num **********/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return( -1 );
}
tprod = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !tprod )
{
/* fatal error */
/* FREE pcpy_num **********/
/* FREE pcpy_mul **********/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return( -1 );
}
/************************************************************/
/* Copy NUM */
p = numi;
q = pcpy_num;
for( i = 0; i < np; i++ ) *q++ = *p++;
/* Copy MUL */
p = muli;
q = pcpy_mul;
for( i = 0; i < np; i++ ) *q++ = *p++;
ei_cleaz( prodi, nb ); /* clear out exploded internal
e-type real number. */
/* Copy Sign & Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = pcpy_num;
q = prodi;
for( i = 0; i < ne + 1; i++ ) *q++ = *p++;
#else
/* hight part */
p = pcpy_num + np - 1;
q = prodi + np - 1;
for( i = 0; i < ne + 1; i++ ) *q-- = *p--;
#endif
j = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* lgw */
p = &pcpy_mul[np - 1];
q = &prodi[np - 1];
#else
/* lgw */
p = &pcpy_mul[0];
q = &prodi[0];
#endif
for( i = 0; i < ns + 1; i++ )
{
if( *p == (EMUSHORT)0 )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
--p;
#else
++p;
#endif
}
else
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
mEMUSHORTm( tprod, pcpy_num, *p--, nb );
#else
mEMUSHORTm( tprod, pcpy_num, *p++, nb );
#endif
ei_addm( prodi, prodi, tprod, nb );
}
j |= *q;
ei_shdown( prodi, (unsigned)BITS_PER_EMUSHORT, nb );
} /* End for( i = 0; i < ns + 1; i++ ) */
if( j ) j = (EMUSHORT)1;
/* FREE pcpy_num **********/
/* FREE pcpy_mul **********/
/* FREE tprod *************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return( (int)j );
} /* End of ei_mulm() */
/***************************************************************
ROUNDOFF parameter register control.
= == = = =
регистр управления параметрами ОКРУГЛЕНИЯ.
***************************************************************/
int rndprc = NSBITS_DEFAULT;
static int nsbits = NSBITS_DEFAULT; /* текущее NSBITS(nb) */
static int nslast = -1; /* предыдущее NSBITS(nb) */
static int rlast = -1;
static int rw = 0; /* rounding word */
static EMUSHORT rm_mask = 0;
static EMUSHORT rm_bit = 0;
static EMUSHORT re_bit = 0;
static int re = 0;
void ei_mdenorm( EMUSHORT *si, int lost, int subflag, EMUSHORT *exp, int rcontrol, int nb )
/***************************************************************
Description : ei_mdenorm() .
Concepts : .
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *si; - указатель на
internal e-type
data struct -
число, подлежащее
округлению;
int lost; - флаг бита,
потерянного
предыдущей
операцией;
int subflag; - указывает на то,
SI получено в
результате
операции
вычитания. В том
случае, когда
LOST != 0, SI
на самом деле
немного меньше,
чем дано;
EMUSHORT *exp; - смещенный порядок,
который может быть
отрицательным.
Поле Exponent
параметра SI
игнорируется, и
замещается EXP,
откорректированным
в процессе
нормализации и
округления;
ВНИМАНИЕ: функция ei_mdenorm() СЧИТАЕТ, ЧТО
РАЗМЕР EXP РАВЕН
internal_ne( nb ) + 1,
=====================
А ЗАТЕМ ПОРТИТ СОДЕРЖИМОЕ EXP.
==============================
int rcontrol; - поле управления
округлением. Если
RCONTROL != 0, то
SI будет округлено
к RNDPRC битам;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *rbit = NULL,
*inc = NULL,
*hexp = NULL; /* or 0 */
EMUSHORT *p;
EMUSHORT r;
__mpu_int32_t j;
int k;
int np, ne, ns, i;
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for rbit, inc, hexp . ******************/
rbit = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !rbit )
{
/* fatal error */
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE rbit **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
hexp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !hexp )
{
/* fatal error */
/* FREE rbit **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
if( nb < NBR_128 ) nb = NBR_128; /* т.к. NSBITS(32) = 16,
NSBITS(64) = 48,
остальные работают верно. */
nsbits = NSBITS(nb); /* Actual number of bits in the Significand */
for( i = 0; i < np; i++ ) rbit[i] = (EMUSHORT)0;
for( i = 0; i < ne+1; i++ ) hexp[i] = (EMUSHORT)0;
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* low part */
/* исходный формат HIGHT_EXP */
p = hexp + ne;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
*p = HIGHT_EXP;
#else
/* low part */
/* исходный формат HIGHT_EXP */
p = hexp;
for( i = 0; i < ne - 1; i++ ) *p++ = PART_MASK_ALL_BITS;
*p = HIGHT_EXP;
#endif
/* NORMALIZE */
j = ei_normalize( si, nb );
/* exp -= j */
ei_cvte_unpack( inc, (EMUSHORT *)&j, ne+1, 1 );
ei_sube( exp, exp, inc, ne+1 );
/* exp < hexp */
if( (j > (__mpu_int32_t)nsbits) &&
( ei_cmpe( exp, hexp, ne+1 ) < 0 ) ) /* exp < hexp */
{
/* FREE rbit **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
/* FREE hexp **************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
ei_cleazs( si, nb );
return;
}
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
if( ei_cmpe( exp, inc, ne+1 ) < 0 ) /* exp < 0L */
{
j = -((__mpu_int32_t)nsbits)-1;
ei_cvte_unpack( inc, (EMUSHORT *)&j, ne+1, 1 );
if( ei_cmpe( exp, inc, ne+1 ) > 0 ) /* exp > (-NSBITS-1) */
{
ei_cvte_pack( (EMUSHORT *)&j, exp, 1, ne+1 );
k = ei_shift( si, (int)j, nb );
if( k ) lost = 1;
}
else
{
/* FREE rbit **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
/* FREE hexp **************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
ei_cleazs( si, nb );
return;
} /* End if( exp > (-NSBITS-1) ) */
} /* End if( exp < 0L ) */
/* Round off, unless told not to by rcontrol */
if( rcontrol == 0 ) goto md_final;
/* Установить параметры если управляющий регистр изменен ||
идет обработка другого типа вещественного числа */
if( (rndprc != rlast) || (nsbits != nslast) )
{
switch( rndprc )
{
/*
NOTE:
HOST_BITS_PER_EMUSHORT == 16, 32, 64, 128,..., etc.
ONLY.
*/
default:
case NSBITS_DEFAULT:
/* Sign + Significand = NSBITS(nb)+1 */
#if HOST_BITS_PER_EMUSHORT > 32
k = ns*BITS_PER_EMUSHORT - rndprc;
if( (k > BITS_PER_EMUSHORT) || (k < 0) )
{
/* FREE rbit **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
/* FREE hexp **************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
ei_cleazs( si, nb );
return;
}
if( k )
{
int n;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
re = rw = ne + ns + 1;
#else
re = rw = 1;
#endif
rm_mask = 0xffff;
rm_bit = 0x8000;
re_bit = (EMUSHORT)1;
n = k - 16;
while( n > 0 )
{
rm_mask <<= 16;
rm_mask |= 0xffff;
n -= 16;
} /* End of while( n ) */
rm_bit <<= k - 16;
re_bit <<= k;
}
else
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
rw = ne + ns + 2; /* lgw */
re = rw - 1;
#else
rw = 0; /* lgw */
re = 1;
#endif
rm_mask = MASK_ALL_BITS;
rm_bit = MASK_SIGN;
re_bit = (EMUSHORT)1;
} /* End if( k ) */
#else /* HOST_BITS_PER_EMUSHORT <= 32 */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
rw = ne + ns + 2; /* lgw */
re = rw - 1;
#else
rw = 0; /* lgw */
re = 1;
#endif
rm_mask = MASK_ALL_BITS;
rm_bit = MASK_SIGN;
re_bit = (EMUSHORT)1;
#endif /* HOST_BITS_PER_EMUSHORT > 32 */
break;
case 53:
/* NBR_64: Sign + Significand = 53 bits */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( BITS_PER_EMUSHORT == 16 ) rw = ne + 5;
else if( BITS_PER_EMUSHORT == 32 ) rw = ne + 3;
else /* >= 64 */ rw = ne + 2;
#else
if( BITS_PER_EMUSHORT == 16 ) rw = ns - 3;
else if( BITS_PER_EMUSHORT == 32 ) rw = ns - 1;
else /* >= 64 */ rw = ns;
#endif
rm_mask = 0x07ff;
rm_bit = 0x0400;
re_bit = 0x0800;
#if HOST_BITS_PER_EMUSHORT > 64
/* if( HOST_BITS_PER_EMUSHORT > 64 ) */
{ /* case HOST_BITS_PER_EMUSHORT == 128, 256,..., etc. */
int n;
n = (BITS_PER_EMUSHORT - 64);
while( n > 0 )
{
rm_mask <<= 16;
rm_mask |= 0xffff;
n -= 16;
} /* End of while( n ) */
rm_bit <<= (BITS_PER_EMUSHORT - 64);
re_bit <<= (BITS_PER_EMUSHORT - 64);
}
#endif /* HOST_BITS_PER_EMUSHORT > 64 */
re = rw;
break;
case 24:
/* NBR_32: Sign + Significand = 24 bits */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( BITS_PER_EMUSHORT == 16 ) rw = ne + 3;
else /* >= 32 */ rw = ne + 2;
#else
if( BITS_PER_EMUSHORT == 16 ) rw = ns - 1;
else /* >= 32 */ rw = ns;
#endif
rm_mask = 0x00ff;
rm_bit = 0x0080;
re_bit = 0x0100;
if( BITS_PER_EMUSHORT > 32 )
{ /* case HOST_BITS_PER_EMUSHORT == 64, 128,..., etc. */
int n;
n = (BITS_PER_EMUSHORT - 32);
while( n > 0 )
{
rm_mask <<= 16;
rm_mask |= 0xffff;
n -= 16;
} /* End of while( n ) */
rm_bit <<= (BITS_PER_EMUSHORT - 32);
re_bit <<= (BITS_PER_EMUSHORT - 32);
}
re = rw;
break;
} /* End of switch( rndprc ) */
/* rbit[re] = re_bit; */
rlast = rndprc;
nslast = nsbits;
} /* End if( rndprc != rlast ) */
/*
Убрав следующий оператор из предыдущего блока
мы обеспечили Static хранение массива rbit[]
(наряду с rw, re, rm_mask, rm_bit, re_bit),
содержащего 1 прибавляемый к мантиссе бит.
SEE the following: ei_addm( si, si, rbit, nb );
*/
rbit[re] = re_bit;
/* Временный сдвиг вправо */
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
if( ( ei_cmpe( exp, inc, ne+1 ) <= 0 ) && /* exp <= 0L */
( rndprc != (int)nsbits/*NSBITS(nb)*/ ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lost |= si[ne+ns+2] & (EMUSHORT)1; /* lgw */
#else
lost |= si[0] & (EMUSHORT)1; /* lgw */
#endif
ei_shdown( si, (unsigned)1, nb );
}
/* Очистить все биты ниже бита округления,
запомнить в r, если какой-нибудь из них != 0 */
r = si[rw] & rm_mask;
if( rndprc < (int)nsbits )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
k = rw + 1;
while( k < (int)np )
{
if( si[k] ) r |= (EMUSHORT)1;
si[k] = (EMUSHORT)0;
++k;
}
#else
k = rw - 1;
while( k >= 0 )
{
if( si[k] ) r |= (EMUSHORT)1;
si[k] = (EMUSHORT)0;
--k;
}
#endif
} /* End if( rndprc < NSBITS(nb) ) */
si[rw] &= ~rm_mask;
if( (r & rm_bit) != 0 ) /* Старший из отрезанных */
{
if( r == rm_bit ) /* Все отрезанные (кроме старшего) == 0 */
{
if( lost == 0 ) /* Потерянных ранее нет */
{
if( (si[re] & re_bit) == 0 ) /* Округление к четному */
goto md_done;
}
else
{
if( subflag != 0 ) goto md_done;
}
} /* End if( r == rm_bit ) */
ei_addm( si, si, rbit, nb );
} /* End if( (r & rm_bit) != 0 ) */
md_done:
/* UNDO: Временный сдвиг вправо */
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
if( ( ei_cmpe( exp, inc, ne+1 ) <= 0 ) && /* exp <= 0L */
( rndprc != (int)nsbits/*NSBITS(nb)*/ ) )
{
ei_shup( si, (unsigned)1, nb );
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( si[ne+1] != (EMUSHORT)0 ) /* hgw */
#else
if( si[ns+1] != (EMUSHORT)0 ) /* hgw */
#endif
{
/* overflow on roundoff */
ei_shdown( si, (unsigned)1, nb );
j = (__mpu_int32_t)1;
/* exp += 1 */
ei_cvte_unpack( inc, (EMUSHORT *)&j, ne+1, 1 );
ei_adde( exp, exp, inc, ne+1 );
}
md_final:
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
si[ne+ns+2] = (EMUSHORT)0; /* lgw */
#else
si[0] = (EMUSHORT)0; /* lgw */
#endif
if( ei_cmpe( exp, hexp, ne+1 ) >= 0 ) /* exp >= hexp */
{
/* Формирование +/- 1.#INF */
ei_cleazs( si, nb ); /* не трогать знак */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_infin( si, si[0] != (EMUSHORT)0, nb );
#else
ei_infin( si, si[ns + ne + 2] != (EMUSHORT)0, nb );
#endif
/*
MY ADD:
"ovrflow range error"
***********************/
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* Not change */
(__mpu_char8_t *)"ei_mdenorm", __OVERFLOW__,
(EMUSHORT *)0,
(EMUSHORT *)0, (EMUSHORT *)0, nb );
__STOVF; /* Set REAL Overflow Flag */
/* FREE rbit **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
/* FREE hexp **************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( exp >= HIGHT_EXP ) */
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
if( ei_cmpe( exp, inc, ne+1 ) < 0 ) /* exp < 0L */
{
/* si[exp] = 0 */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = inc + 1;
ei_cpye_unpack( &si[1], p, ne, ne );
#else
p = inc;
ei_cpye_unpack( &si[ns+2], p, ne, ne );
#endif
}
else /* exp >= 0L */
{
/* si[exp] = exp */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = exp + 1;
ei_cpye_unpack( &si[1], p, ne, ne );
#else
p = exp;
ei_cpye_unpack( &si[ns+2], p, ne, ne );
#endif
} /* End if( exp < 0L ) */
/* FREE rbit **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
/* FREE hexp **************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_mdenorm() */
static void pack_32( EMUSHORT *ee, EMUSHORT *ei, int nb )
/***************************************************************
Description : pack_32() Пакует internal e-type data
struct в real32 data struct.
Concepts :
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *exone = NULL,
*exp = NULL,
*inc = NULL;
EMUSHORT *p;
__mpu_uint16_t *he, *pe;
int rndsave;
EMUSHORT k;
int np, ne, ns, i;
if( nb != NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
errno = 0;
e_signull( ee, (unsigned)0, nb ); /* clear out exploded external
real number. */
if( ei_isind( ei, nb ) )
{
e_ind( ee, nb );
return;
}
if( ei_isnanmin( ei, nb ) )
{
e_nanmin( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
if( ei_isnanmax( ei, nb ) )
{
e_nanmax( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
if( ei_isnans( ei, nb ) )
{
e_nan( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, exp, inc . ******************/
exone = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
exp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
for( i = 0; i < ne+1; i++ ) exp[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* low part */
p = inc + ne;
*p = (EMUSHORT)0x7f;
/* hight part */
p = exone;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* low part */
p = inc;
*p = (EMUSHORT)0x7f;
/* hight part */
p = exone + ne;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &ei[1], ne+1, ne );
#else
ei_cpye_unpack( exp, &ei[ns+2], ne+1, ne );
#endif
/* exp = exp - (EXONEsource - EXONEtarget) */
ei_sube( exone, exone, inc, ne+1 );
ei_sube( exp, exp, exone, ne+1 );
if( !ei_isinfin( ei, nb ) )
{
rndsave = rndprc;
rndprc = 24;
ei_mdenorm( ei, 0, 0, exp, NSBITS_DEFAULT, nb );
rndprc = rndsave;
}
he = (__mpu_uint16_t *)ee;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
++he; /* point to high word16bits */
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = ei; /* point to Sign */
#else
p = ei + np - 1; /* point to Sign */
#endif
if( *p )
{
*he = 0x8000; /* output Sign bit */
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p += ne; /* point to low part of Exponent */
k = *p++; /* NOW: p point to hgw */
#else
p -= ne; /* point to low part of Exponent */
k = *p--; /* NOW: p point to hgw */
#endif
/* Handle overflow cases. */
if( k >= (EMUSHORT)255 ) /* hex: 0x00ff */
{
e_infin( ee, (unsigned)ei_isneg( ei, nb ), nb );
errno = ERANGE; /* USER's Variable */
__STOVF; /* Set REAL Overflow Flag */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( k >= 255 ) */
if( k == (EMUSHORT)0 )
{
ei_shift( ei, 7, nb );
}
else
{
k <<= 7;
ei_shift( ei, 8, nb );
}
/* Убрать бывшую явной 1.0 */
k |= *p & (EMUSHORT)0x7f;
/* NOW: p point to hight part of Significand */
/* High order output already has sign bit set */
*he |= (__mpu_uint16_t)k;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++p;
/* point to hight part of Exponent */
pe = (__mpu_uint16_t *)p;
++he;
#else
--p;
/* point to hight part of Exponent */
pe = (__mpu_uint16_t *)p;
pe += (BITS_PER_EMUSHORT - 16) / 16;
--he;
#endif
*he = *pe;
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of pack_32() */
static void pack_64( EMUSHORT *ee, EMUSHORT *ei, int nb )
/***************************************************************
Description : pack_64() Пакует internal e-type data
struct в real64 data struct.
Concepts :
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *exone = NULL,
*exp = NULL,
*inc = NULL;
EMUSHORT *p;
__mpu_uint16_t *he, *pe;
int rndsave;
EMUSHORT k;
int np, ne, ns, i;
if( nb != NBR_64 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
errno = 0;
e_signull( ee, (unsigned)0, nb ); /* clear out exploded external
real number. */
if( ei_isind( ei, nb ) )
{
e_ind( ee, nb );
return;
}
if( ei_isnanmin( ei, nb ) )
{
e_nanmin( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
if( ei_isnanmax( ei, nb ) )
{
e_nanmax( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
if( ei_isnans( ei, nb ) )
{
e_nan( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, exp, inc . ******************/
exone = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
exp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
for( i = 0; i < ne+1; i++ ) exp[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* low part */
p = inc + ne;
*p = (EMUSHORT)0x3ff;
/* hight part */
p = exone;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* low part */
p = inc;
*p = (EMUSHORT)0x3ff;
/* hight part */
p = exone + ne;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &ei[1], ne+1, ne );
#else
ei_cpye_unpack( exp, &ei[ns+2], ne+1, ne );
#endif
/* exp = exp - (EXONEsource - EXONEtarget) */
ei_sube( exone, exone, inc, ne+1 );
ei_sube( exp, exp, exone, ne+1 );
if( !ei_isinfin( ei, nb ) )
{
rndsave = rndprc;
rndprc = 53;
ei_mdenorm( ei, 0, 0, exp, NSBITS_DEFAULT, nb );
rndprc = rndsave;
}
he = (__mpu_uint16_t *)ee;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
he += 3; /* point to high word16bits */
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = ei; /* point to Sign */
#else
p = ei + np - 1; /* point to Sign */
#endif
if( *p )
{
*he = 0x8000; /* output Sign bit */
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p += ne; /* point to low part of Exponent */
k = *p++; /* NOW: p point to hgw */
#else
p -= ne; /* point to low part of Exponent */
k = *p--; /* NOW: p point to hgw */
#endif
/* Handle overflow cases. */
if( k >= (EMUSHORT)2047 ) /* hex: 0x07ff */
{
e_infin( ee, (unsigned)ei_isneg( ei, nb ), nb );
errno = ERANGE; /* USER's Variable */
__STOVF; /* Set REAL Overflow Flag */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( k >= 2047 ) */
if( k == (EMUSHORT)0 )
{
ei_shift( ei, 4, nb );
}
else
{
k <<= 4;
ei_shift( ei, 5, nb );
}
/* Убрать бывшую явной 1.0 */
k |= *p & (EMUSHORT)0x0f;
/* NOW: p point to hight part of Significand */
/* High order output already has sign bit set */
*he |= (__mpu_uint16_t)k;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++p;
/* point to hight part of Exponent */
pe = (__mpu_uint16_t *)p;
++he;
*he = *pe;
*(he + 1) = *(++pe);
*(he + 2) = *(++pe);
#else
--p;
/* point to hight part of Exponent */
pe = (__mpu_uint16_t *)p;
pe += (BITS_PER_EMUSHORT - 16) / 16;
--he;
*he = *pe;
*(he - 1) = *(--pe);
*(he - 2) = *(--pe);
#endif
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of pack_64() */
static void pack_np( EMUSHORT *ee, EMUSHORT *ei, int nb )
/***************************************************************
Description : pack_np() Пакует internal e-type data
struct в real128, real256,
..., etc. data struct.
Concepts :
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *exone = NULL,
*exp = NULL,
*inc = NULL;
EMUSHORT *p;
EMUPART *he, *pe;
int rndsave;
int np, ne, ns, nex, nsx, i;
if( nb < NBR_128 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
errno = 0;
e_signull( ee, (unsigned)0, nb ); /* clear out exploded external
real number. */
if( ei_isind( ei, nb ) )
{
e_ind( ee, nb );
return;
}
if( ei_isnanmin( ei, nb ) )
{
e_nanmin( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
if( ei_isnanmax( ei, nb ) )
{
e_nanmax( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
if( ei_isnans( ei, nb ) )
{
e_nan( ee, (unsigned)ei_isneg( ei, nb ), nb );
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, exp, inc . ******************/
exone = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
exp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
nex = EMUPARTSIZE(NEBITS(nb));
nsx = EMUPARTSIZE(NSBITS(nb));
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
for( i = 0; i < ne+1; i++ ) exp[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* целевой формат EXONE */
/* low part */
pe = (EMUPART *)(inc + ne);
pe += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* ------------------------------------- */
BITS_PER_EMUPART;
for( i = 0; i < nex - 1; i++ ) *pe-- = PART_MASK_ALL_BITS;
*pe = PART_HIGHT_EXONE;
/* исходный формат EXONE */
/* hight part */
p = exone;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* целевой формат EXONE */
/* low part */
pe = (EMUPART *)inc;
for( i = 0; i < nex - 1; i++ ) *pe++ = PART_MASK_ALL_BITS;
*pe = PART_HIGHT_EXONE;
/* исходный формат EXONE */
/* hight part */
p = exone + ne;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &ei[1], ne+1, ne );
#else
ei_cpye_unpack( exp, &ei[ns+2], ne+1, ne );
#endif
/* exp = exp - (EXONEsource - EXONEtarget) */
ei_sube( exone, exone, inc, ne+1 );
ei_sube( exp, exp, exone, ne+1 );
if( !ei_isinfin( ei, nb ) )
{
rndsave = rndprc;
rndprc = (int)NSBITS(nb);
ei_mdenorm( ei, 0, 0, exp, (int)NSBITS(nb), nb );
rndprc = rndsave;
}
he = (EMUPART *)ee;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
he += nex + nsx - 1; /* point to high EMUPART */
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = ei; /* point to Sign */
#else
p = ei + np - 1; /* point to Sign */
#endif
if( *p )
{
*he = PART_MASK_SIGN; /* output Sign bit */
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p += ne; /* NOW: p point to low part of Exponent */
#else
p -= ne; /* NOW: p point to low part of Exponent */
#endif
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &ei[1], ne+1, ne );
#else
ei_cpye_unpack( exp, &ei[ns+2], ne+1, ne );
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* целевой формат HIGHT_EXP */
/* low part */
pe = (EMUPART *)(inc + ne);
pe += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* ------------------------------------- */
BITS_PER_EMUPART;
for( i = 0; i < nex - 1; i++ ) *pe-- = PART_MASK_ALL_BITS;
*pe = PART_HIGHT_EXP;
#else
/* целевой формат HIGHT_EXP */
/* low part */
pe = (EMUPART *)inc;
for( i = 0; i < nex - 1; i++ ) *pe++ = PART_MASK_ALL_BITS;
*pe = PART_HIGHT_EXP;
#endif
/* Handle overflow cases. */
if( ei_cmpe( exp, inc, ne+1 ) >= 0 ) /* exp >= HIGHT_EXP */
{
e_infin( ee, (unsigned)ei_isneg( ei, nb ), nb );
errno = ERANGE; /* USER's Variable */
__STOVF; /* Set REAL Overflow Flag */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( exp >= HIGHT_EXP ) */
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
if( ei_cmpe( exp, inc, ne+1 ) != 0 ) /* exp != NULL */
{
/* Убрать бывшую явной 1.0 */
ei_shift( ei, 1, nb );
}
/* Copy Exponent */
/* High order output already has sign bit set, and
p point to low part of Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* low part */
he = (EMUPART *)&ee[nex - 1];
pe = (EMUPART *)p;
pe += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* -------------------------------------- */
BITS_PER_EMUPART;
for( i = 0; i < nex - 1; i++ ) *he-- = *pe--;
*he |= *pe;
#else
/* low part */
he = (EMUPART *)&ee[ns];
pe = (EMUPART *)p;
for( i = 0; i < nex - 1; i++ ) *he++ = *pe++;
*he |= *pe;
#endif
/* Copy Significand */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
pe = (EMUPART *)&ei[ne + 2];
he = (EMUPART *)&ee[nex];
for( i = 0; i < nsx; i++ ) *he++ = *pe++;
#else
pe = (EMUPART *)&ei[ns];
he = (EMUPART *)&ee[ns-1];
pe += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* ------------------------------------- */
BITS_PER_EMUPART;
he += (BITS_PER_EMUSHORT - BITS_PER_EMUPART) /
/* ------------------------------------- */
BITS_PER_EMUPART;
for( i = 0; i < nsx; i++ ) *he-- = *pe--;
#endif
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of pack_np() */
void pack( EMUSHORT *ee, EMUSHORT *ei, int nb )
/***************************************************************
Description : pack() Пакует all e-type data struct
в `real<all>' data struct
Concepts :
Use Global Variable:
Use Functions :
pack_32( *ee, *ei, nb ); | this file
pack_64( *ee, *ei, nb ); | this file
pack_np( *ee, *ei, nb ); | this file
Parameters : EMUSHORT *ee; - указатель на
external e-type
data struct;
EMUSHORT *ei; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : [void];
***************************************************************/
{
EMUSHORT *eix = NULL; /* Internal format */
int np;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
/*** Allocate memory for eix . ******************************/
eix = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !eix )
{
/* fatal error */
return;
}
/************************************************************/
/* copy EI to EIX (Internal format) */
(void)memcpy( (void *)eix, (void *)ei, (size_t)(np*SIZE_OF_EMUSHORT) );
switch( nb )
{
case NBR_32 :
pack_32( ee, eix, nb );
break;
case NBR_64 :
pack_64( ee, eix, nb );
break;
case NBR_128 :
case NBR_256 :
case NBR_512 :
case NBR_1024 :
case NBR_2048 :
case NBR_4096 :
case NBR_8192 :
case NBR_16384 :
case NBR_32768 :
case NBR_65536 :
case NBR_131072:
pack_np( ee, eix, nb );
break;
default:
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
break;
}
} /* End of switch( nb ) */
/* FREE eix ***************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End of pack() */
void ei_copy( EMUSHORT *eia, EMUSHORT *eib, int nb )
/***************************************************************
Description : ei_copy() Работает с
internal e-type data struct.
Concepts : copy (EIB to EIA) exploded
internal e-type real number.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *eia; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int np;
np = internal_np( nb );
(void)memcpy( (void *)eia, (void *)eib, np * SIZE_OF_EMUSHORT );
} /* End of ei_copy() */
void ei_copyzlgw( EMUSHORT *eia, EMUSHORT *eib, int nb )
/***************************************************************
Description : ei_copyzlgw() Работает с
internal e-type data
struct.
Concepts : copy (EIB to EIA) exploded
internal e-type real number.
And clear low guard word.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *eia; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
int np;
np = internal_np( nb );
(void)memcpy( (void *)eia, (void *)eib, np * SIZE_OF_EMUSHORT );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
eia[np-1] = (EMUSHORT)0;
#else
eia[0] = (EMUSHORT)0;
#endif
} /* End of ei_copyzlgw() */
int ei_cmp( EMUSHORT *ai, EMUSHORT *bi, int nb )
/***************************************************************
Description : ei_cmp() Compare two numbers
in internal e-type data struct.
Concepts : Guard words are included in the
comparison.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters : EMUSHORT *ai; - указатель на
internal e-type
data struct;
EMUSHORT *bi; - указатель на
internal e-type
data struct;
int nb; - количество бит в
external e-type
data struct.
Return : int rc; - Result of Comparison.
if( ai > bi ) rc = +1;
if( ai == bi ) rc = 0;
if( ai < bi ) rc = -1;
if((ai || bi) is NaN) rc = -2;
***************************************************************/
{
EMUSHORT *x, *y;
EMUSHORT *p, *q;
int msign;
int np, i;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return( -3 );
}
if( ei_isnanmin( ai, nb ) || ei_isnanmin( bi, nb ) ) return( -2 );
if( ei_isnanmax( ai, nb ) || ei_isnanmax( bi, nb ) ) return( -2 );
if( ei_isnans ( ai, nb ) || ei_isnans ( bi, nb ) ) return( -2 );
if( ei_isind ( ai, nb ) || ei_isind ( bi, nb ) ) return( -2 );
np = internal_np( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
x = ai; /* Point to Sign */
y = bi;
p = ai + 1; /* Point to hight part of Exponent */
q = bi + 1;
#else
x = ai + np - 1; /* Point to Sign */
y = bi + np - 1;
p = ai + np - 2; /* Point to hight part of Exponent */
q = bi + np - 2;
#endif
/* the Sign are different */
if( *x != *y )
{
/* -0.0 equals +0.0 */
for( i = 1; i < np; i++ ) /* lgw are included */
{
if( *p != (EMUSHORT)0 )
{
/* No Zero */
if( *x == (EMUSHORT)0 ) return( 1 );
else return( -1 );
}
if( *q != (EMUSHORT)0 )
{
/* No Zero */
if( *x == (EMUSHORT)0 ) return( 1 );
else return( -1 );
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++p; ++q;
#else
--p; --q;
#endif
} /* End for( i = 1; i < np - 1; i++ ) */
return( 0 );
} /* End if( *x != *y ) */
/* both are the same sign */
if( *x == (EMUSHORT)0 ) msign = 1;
else msign = -1;
for( i = 0; i < np; i++ ) /* lgw are included */
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *x++ != *y++ )
#else
if( *x-- != *y-- )
#endif
{
/* different */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *(--x) > *(--y) )
#else
if( *(++x) > *(++y) )
#endif
return( msign );
else
return( -msign );
} /* End if( *x++/-- != *y++/-- ) */
} /* End for( i = 0; i < np; i++ ) */
return( 0 ); /* equality */
} /* End of ei_cmp() */
static void ei_cvt_unpack( EMUSHORT *eia, EMUSHORT *eib, int nba, int nbb )
/***************************************************************
Description : ei_cvt_unpack() Работает с
internal e-type data
struct.
Concepts : convert (EIB to EIA) exploded
internal e-type real number.
NOTE : NBA > NBB.
Для real32, real64, and real128 EIA & EIB
могут указывать на одну и туже
internal e-type data struct, т.к.
внутренний формат этих чисел одинаков и
ei_cvt_unpack() работает с копией
EIB (p_b).
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *eia; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
SOURCE;
int nba; - количество бит в
external e-type
data struct.
int nbb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *exone = NULL,
*inc = NULL,
*r = NULL;
EMUSHORT *p;
EMUSHORT *he, *pe;
EMUSHORT *p_b = NULL; /* ptr to copy of EIB */
int denorm = 0;
__mpu_int32_t k;
int npa, nea, nsa, npb, neb, nsb, i;
if( (nba < NBR_32) || (nbb < NBR_32) )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
npb = internal_np( nbb );
neb = internal_ne( nbb );
nsb = internal_ns( nbb );
/*** Allocate memory for p_b . ******************************/
p_b = (EMUSHORT *)__mpu_sbrk( (int)(npb*SIZE_OF_EMUSHORT) );
if( !p_b )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( p_b, eib, nbb );
he = p_b;
ei_cleaz( eia, nba ); /* clear out exploded internal
e-type real number. (TARGET) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
he += neb; /* point to low part of Exponent */
#else
he += nsb + 2; /* point to low part of Exponent */
#endif
npa = internal_np( nba );
nea = internal_ne( nba );
nsa = internal_ns( nba );
/*** Allocate memory for exone, inc, r . ********************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(nea*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(nea*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
__mpu_sbrk( -(int)(nea*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
r = (EMUSHORT *)__mpu_sbrk( (int)(nea*SIZE_OF_EMUSHORT) );
if( !r )
{
/* fatal error */
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*nea*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* inc используется для хранения EXONE исходного формата */
/*
но до ее основного применения она используется для:
1) проверки всех бит исходной экспоненты на 1;
2) проверки всех бит исходной экспоненты на 0;
*/
for( i = 0; i < nea; i++ ) inc[i] = (EMUSHORT)0;
for( i = 0; i < nea; i++ ) r[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* исходный формат EXP */
/* low part */
pe = inc + nea - 1;
for( i = 0; i < neb - 1; i++ ) *pe-- = MASK_ALL_BITS;
*pe = HIGHT_EXP;
/* целевой формат EXONE */
/* hight part */
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < nea - 1; i++ ) *p++ = MASK_ALL_BITS;
/* Copy Exponent */
/* low part */
pe = r + nea - 1;
for( i = 0; i < neb; i++ ) *pe-- = *he--;
#else
/* исходный формат EXP */
/* low part */
pe = inc;
for( i = 0; i < neb - 1; i++ ) *pe++ = MASK_ALL_BITS;
*pe = HIGHT_EXP;
/* целевой формат EXONE */
/* hight part */
p = exone + nea - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < nea - 1; i++ ) *p-- = MASK_ALL_BITS;
/* Copy Exponent */
/* low part */
pe = r;
for( i = 0; i < neb; i++ ) *pe++ = *he++;
#endif
/* NOW *he point to Sign in the source format */
/* Sign */
if( *he )
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*eia = MASK_ALL_BITS;
#else
*(eia + npa - 1) = MASK_ALL_BITS;
#endif
/****************
INFINITY
****************/
if( ei_cmpe( r, inc, nea ) == 0 ) /* r == inc */
{
/********
NANS
********/
/* indeterminacy */
if( ei_isind( p_b, nbb ) )
{
ei_ind( eia, nba );
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*nea*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nanmin */
if( ei_isnanmin( p_b, nbb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nanmin( eia, eia[0] != (EMUSHORT)0, nba );
#else
ei_nanmin( eia, eia[nsa + nea + 2] != (EMUSHORT)0, nba );
#endif
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*nea*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nanmax */
if( ei_isnanmax( p_b, nbb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nanmax( eia, eia[0] != (EMUSHORT)0, nba );
#else
ei_nanmax( eia, eia[nsa + nea + 2] != (EMUSHORT)0, nba );
#endif
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*nea*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* nans */
if( ei_isnans( p_b, nbb ) )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_nan( eia, eia[0] != (EMUSHORT)0, nba );
#else
ei_nan( eia, eia[nsa + nea + 2] != (EMUSHORT)0, nba );
#endif
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*nea*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/**********
END NANS
**********/
ei_cleazs( eia, nba ); /* не трогать знак */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_infin( eia, eia[0] != (EMUSHORT)0, nba );
#else
ei_infin( eia, eia[nsa + nea + 2] != (EMUSHORT)0, nba );
#endif
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*nea*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/**************
END INFINITY
**************/
/* If zero Exponent, then the Significand is denormalized.
So take back the understood high Significand bit. */
for( i = 0; i < nea; i++ ) inc[i] = (EMUSHORT)0;
if( ei_cmpe( r, inc, nea ) == 0 ) /* r == inc (inc = 0) */
{
denorm = 1;
}
/* Create EXONE of source format */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* исходный формат EXONE */
/* low part */
pe = inc + neb - 1;
for( i = 0; i < neb - 1; i++ ) *pe-- = MASK_ALL_BITS;
*pe = HIGHT_EXONE;
#else
/* исходный формат EXONE */
/* low part */
pe = inc;
for( i = 0; i < neb - 1; i++ ) *pe++ = MASK_ALL_BITS;
*pe = HIGHT_EXONE;
#endif
/* r += EXONEtarget - EXONEsource */
ei_sube( exone, exone, inc, nea );
ei_adde( r, r, exone, nea );
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( &eia[1], r, nea, nea );
#else
ei_cpye_unpack( &eia[nsa+2], r, nea, nea );
#endif
/* Copy Significand */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
pe = &eia[nea + 2];
he = &p_b[neb + 2];
for( i = 0; i < nsb; i++ ) *pe++ = *he++;
#else
pe = &eia[nsa];
he = &p_b[nsb];
for( i = 0; i < nsb; i++ ) *pe-- = *he--;
#endif
if( denorm )
{
/* if zero Exponent, then normalize the Significand */
if( (k = ei_normalize(eia, nba)) > (__mpu_int32_t)EINSBITS(nba) )
ei_cleazs( eia, nba );
else
{
/* Exponent -= (k - 1); */
k -= 1;
ei_cvte_unpack( inc, (EMUSHORT *)&k, nea, 1 );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &eia[1];
#else
p = &eia[nsa+2];
#endif
ei_sube( p, p, inc, nea );
}
} /* End if( denorm ) */
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
/* FREE r *****************/
__mpu_sbrk( -(int)(3*nea*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_cvt_unpack() */
static void ei_cvt_pack( EMUSHORT *eia, EMUSHORT *eib, int nba, int nbb )
/***************************************************************
Description : ei_cvt_pack() Работает с
internal e-type data
struct.
Concepts : convert (EIB to EIA) exploded
internal e-type real number.
NOTE : NBA < NBB.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters : EMUSHORT *eia; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
SOURCE;
int nba; - количество бит в
external e-type
data struct.
int nbb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *exone = NULL,
*exp = NULL,
*inc = NULL;
EMUSHORT *p;
EMUSHORT *he, *pe;
EMUSHORT *p_b = NULL; /* ptr to copy EIB */
int rndsave;
int npb, neb, nsb, nea, nsa, i;
errno = 0;
if( (nba < NBR_32) || (nbb < NBR_32) )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
npb = internal_np( nbb );
neb = internal_ne( nbb );
nsb = internal_ns( nbb );
nea = internal_ne( nba );
nsa = internal_ns( nba );
/*** Allocate memory for p_b . ******************************/
p_b = (EMUSHORT *)__mpu_sbrk( (int)(npb*SIZE_OF_EMUSHORT) );
if( !p_b )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( p_b, eib, nbb );
ei_signull( eia, (unsigned)0, nba ); /* clear out exploded internal
e-type real number. */
if( ei_isind( p_b, nbb ) )
{
ei_ind( eia, nba );
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_isnanmin( p_b, nbb ) )
{
ei_nanmin( eia, (unsigned)ei_isneg( p_b, nbb ), nba );
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_isnanmax( p_b, nbb ) )
{
ei_nanmax( eia, (unsigned)ei_isneg( p_b, nbb ), nba );
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
if( ei_isnans( p_b, nbb ) )
{
ei_nan( eia, (unsigned)ei_isneg( p_b, nbb ), nba );
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for exone, exp, inc . ******************/
exone = (EMUSHORT *)__mpu_sbrk( (int)((neb+1)*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
exp = (EMUSHORT *)__mpu_sbrk( (int)((neb+1)*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
__mpu_sbrk( -(int)((neb+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((neb+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE exp ***************/
__mpu_sbrk( -(int)(2*(neb+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
for( i = 0; i < neb+1; i++ ) inc[i] = (EMUSHORT)0;
for( i = 0; i < neb+1; i++ ) exp[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* целевой формат EXONE */
/* low part */
pe = inc + neb;
for( i = 0; i < nea - 1; i++ ) *pe-- = MASK_ALL_BITS;
*pe = HIGHT_EXONE;
/* исходный формат EXONE */
/* hight part */
p = exone;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < neb - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* целевой формат EXONE */
/* low part */
pe = inc;
for( i = 0; i < nea - 1; i++ ) *pe++ = MASK_ALL_BITS;
*pe = HIGHT_EXONE;
/* исходный формат EXONE */
/* hight part */
p = exone + neb;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXONE;
for( i = 0; i < neb - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &p_b[1], neb+1, neb );
#else
ei_cpye_unpack( exp, &p_b[nsb+2], neb+1, neb );
#endif
/* exp = exp - (EXONEsource - EXONEtarget) */
ei_sube( exone, exone, inc, neb+1 );
ei_sube( exp, exp, exone, neb+1 );
if( !ei_isinfin( p_b, nbb ) )
{
rndsave = rndprc;
rndprc = (int)EINSBITS(nbb);
/*****************************************************************
Здесь все равно какое значение RNDPRC, т.к. если оно не равно
(24 или 53), то ei_mdenorm() округляет путем отбрасывания lgw
данного ей числа в internal формате. Ловить здесь 24 или 53
нет смысла (т.к. это будет сделано во время неминуемой
последующей упаковки в external формат), а вот далее при
копировании мантиссы можно заполнить lgw целевого формата
для более точного округления при последующей упаковке.
Мы использовали rndprc = (int)EINSBITS(nb); для того, чтобы
избежать ошибок при больших размерах EMUSHORT.
******************************************************************/
ei_mdenorm( p_b, 0, 0, exp, (int)EINSBITS(nbb), nbb );
rndprc = rndsave;
}
he = eia;
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
he += nea + nsa + 2; /* point to Sign of TARGET */
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = p_b; /* point to Sign of SOURCE */
#else
p = p_b + npb - 1; /* point to Sign of SOURCE */
#endif
if( *p )
{
*he = MASK_ALL_BITS; /* output Sign bit */
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p += neb; /* NOW: p point to low part of Exponent */
#else
p -= neb; /* NOW: p point to low part of Exponent */
#endif
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &p_b[1], neb+1, neb );
#else
ei_cpye_unpack( exp, &p_b[nsb+2], neb+1, neb );
#endif
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* целевой формат HIGHT_EXP */
/* low part */
pe = inc + neb;
for( i = 0; i < nea - 1; i++ ) *pe-- = MASK_ALL_BITS;
*pe = HIGHT_EXP;
#else
/* целевой формат HIGHT_EXP */
/* low part */
pe = inc;
for( i = 0; i < nea - 1; i++ ) *pe++ = MASK_ALL_BITS;
*pe = HIGHT_EXP;
#endif
/* Handle overflow cases. */
if( ei_cmpe( exp, inc, neb+1 ) >= 0 ) /* exp >= HIGHT_EXP */
{
ei_infin( eia, (unsigned)ei_isneg( p_b, nbb ), nba );
errno = ERANGE; /* USER's Variable */
__STOVF; /* Set REAL Overflow Flag */
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*(neb+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( exp >= HIGHT_EXP ) */
/* Copy Exponent */
/* High order output already has sign bit set, and
p point to low part of Exponent of SOURCE */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* low part */
he = &eia[nea];
pe = p;
for( i = 0; i < nea - 1; i++ ) *he-- = *pe--;
*he = *pe;
#else
/* low part */
he = &eia[nsa + 2];
pe = p;
for( i = 0; i < nea - 1; i++ ) *he++ = *pe++;
*he = *pe;
#endif
/* Copy Significand */
/***********************************************************
Я ВКЛЮЧИЛ lgw ДЛЯ БОЛЕЕ ТОЧНОГО ОКРУГЛЕНИЯ ПРИ
ПОСЛЕДУЮЩИХ ОПЕРАЦИЯХ С ПОЛУЧЕННЫМ ЧИСЛОМ.
SEE:
for( i = 0; i < nSa + 1; i++ ) *he++/-- = *pe++/--;
=======
***********************************************************/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
pe = &p_b[neb + 2];
he = &eia[nea + 2];
for( i = 0; i < nsa/* + 1*/; i++ ) *he++ = *pe++;
#else
pe = &p_b[nsb];
he = &eia[nsa];
for( i = 0; i < nsa/* + 1*/; i++ ) *he-- = *pe--;
#endif
/* FREE p_b ***************/
__mpu_sbrk( -(int)(npb*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*(neb+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_cvt_pack() */
void ei_convert( EMUSHORT *eia, EMUSHORT *eib, int nba, int nbb )
/***************************************************************
Description : ei_convert() Работает с
internal e-type data struct.
Concepts : convert (EIB to EIA) exploded
internal e-type real number.
Use Global Variable:
Use Functions :
Parameters : EMUSHORT *eia; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
SOURCE;
int nba; - количество бит в
external e-type
data struct.
int nbb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
if( nba == nbb )
{
ei_copy( eia, eib, nba );
return;
}
if( nba > nbb )
{
ei_cvt_unpack( eia, eib, nba, nbb );
return;
}
if( nba < nbb )
{
ei_cvt_pack( eia, eib, nba, nbb );
return;
}
} /* End of ei_convert() */
static int subflag = 0;
static void ei_add1( EMUSHORT *eic, EMUSHORT *eia, EMUSHORT *eib, int nb )
/***************************************************************
Description : ei_add1() Работает с
internal e-type data struct.
Concepts : Arithmetic common to both addition and
substraction.
EIC = EIA + EIB or
EIC = EIA - EIB.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *lt = NULL,
*lta = NULL,
*ltb = NULL,
*inc = NULL;
EMUSHORT *p;
__mpu_int32_t j;
int rndsave;
int lost, k;
int np, ne, ns, i;
if( ei_isinfin( eib, nb ) )
{
ei_copy( eic, eib, nb );
if( subflag )
{
ei_neg( eic, nb );
}
return;
}
if( ei_isinfin( eia, nb ) )
{
ei_copy( eic, eia, nb );
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for lt, lta, ltb, inc . ****************/
lt = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !lt )
{
/* fatal error */
return;
}
lta = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !lta )
{
/* fatal error */
/* FREE lt ****************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ltb = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !ltb )
{
/* fatal error */
/* FREE lt ****************/
/* FREE lta ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
if( nb < NBR_128 ) nb = NBR_128; /* т.к. NSBITS(32) = 16,
NSBITS(64) = 48,
остальные работают верно. */
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
for( i = 0; i < ne+1; i++ ) lt [i] = (EMUSHORT)0;
for( i = 0; i < ne+1; i++ ) lta[i] = (EMUSHORT)0;
for( i = 0; i < ne+1; i++ ) ltb[i] = (EMUSHORT)0;
if( subflag )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
eib[0] = ~eib[0];
#else
eib[ne+ns+2] = ~eib[ne+ns+2];
#endif
}
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( lta, &eia[1], ne+1, ne );
ei_cpye_unpack( ltb, &eib[1], ne+1, ne );
#else
ei_cpye_unpack( lta, &eia[ns+2], ne+1, ne );
ei_cpye_unpack( ltb, &eib[ns+2], ne+1, ne );
#endif
/* Compate Exponents */
ei_sube( lt, ltb, lta, ne+1 );
if( ei_cmpe( lt, inc, ne+1 ) > 0 ) /* lt > 0L */
{
/* put the larger number in EIA */
ei_copyzlgw( eic, eia, nb ); /* EIC <- EIA */
ei_copyzlgw( eia, eib, nb ); /* EIA <- EIB */
ei_copyzlgw( eib, eic, nb ); /* EIB <- EIC */
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( lta, &eia[1], ne+1, ne );
#else
ei_cpye_unpack( lta, &eia[ns+2], ne+1, ne );
#endif
ei_nege( lt, lt, ne+1 ); /* lt = -lt; */
}
lost = 0;
if( ei_cmpe( lt, inc, ne+1 ) != 0 ) /* lt != 0L */
{
j = -((__mpu_int32_t)NSBITS(nb))-1;
ei_cvte_unpack( inc, (EMUSHORT *)&j, ne+1, 1 );
if( ei_cmpe( lt, inc, ne+1 ) < 0 ) /* lt < (-NSBITS-1) */
{
/* answer same as larger addend */
ei_copy( eic, eia, nb );
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_cvte_pack( (EMUSHORT *)&j, lt, 1, ne+1 );
/* shift the smaller number down */
lost = ei_shift( eib, (int)j, nb );
}
else /* т.е. lt == 0L */
{
/* Exponents were the same, so must compare Significands */
k = ei_cmpm( eib, eia, nb );
if( k == 0 )
{
/* the numbers are identical in magnitude */
/* if different signs, result is zero */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( eia[0] != eib[0] )
#else
if( eia[np-1] != eib[np-1] )
#endif
{
ei_signull( eic, (unsigned)0, nb );
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* if same sign, result is double */
/* double denormalized tiny number */
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &eia[ne+2];
if( (ei_cmpe( &eia[1], inc, ne ) == 0) &&
((*p & MASK_SIGN) == (EMUSHORT)0) )
#else
p = &eia[ns];
if( (ei_cmpe( &eia[ns+2], inc, ne ) == 0) &&
((*p & MASK_SIGN) == (EMUSHORT)0) )
#endif
{
ei_shup( eia, (unsigned)1, nb );
ei_copy( eic, eia, nb );
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* add 1 to Exponent unless both are zero! */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &eia[1];
#else
p = &eia[ne+ns+1];
#endif
for( i = 1; i < np - 1; i++ )
{
if( *p != (EMUSHORT)0 )
{
/* This could overflow,
but let ei_copy() take care of that. */
ei_ince( lta, lta, ne+1 ); /* lta += 1; */
break;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++p;
#else
--p;
#endif
} /* End for( i = 1; i < np - 1; i++ ) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_pack( &eia[1], lta, ne, ne+1 );
#else
ei_cpye_pack( &eia[ns+2], lta, ne, ne+1 );
#endif
ei_copy( eic, eia, nb );
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( k == 0 ) */
if( k > 0 )
{
/* put the larger number in EIA */
ei_copyzlgw( eic, eia, nb ); /* EIC <- EIA */
ei_copyzlgw( eia, eib, nb ); /* EIA <- EIB */
ei_copyzlgw( eib, eic, nb ); /* EIB <- EIC */
} /* End if( k > 0 ) */
} /* End if( lt != 0L ) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( eia[0] == eib[0] )
#else
if( eia[np-1] == eib[np-1] )
#endif
{
ei_addm( eia, eia, eib, nb );
subflag = 0;
}
else
{
ei_subm( eia, eia, eib, nb );
subflag = 1;
}
rndsave = rndprc;
rndprc = (int)EINSBITS(nb);
/*****************************************************************
Здесь все равно какое значение RNDPRC, т.к. если оно не равно
(24 или 53), то ei_mdenorm() округляет путем отбрасывания lgw
данного ей числа в internal формате.
Мы использовали rndprc = (int)EINSBITS(nb); для того, чтобы
избежать ошибок при больших размерах EMUSHORT.
******************************************************************/
ei_mdenorm( eia, lost, subflag, lta, (int)EINSBITS(nb), nb );
rndprc = rndsave;
ei_copy( eic, eia, nb );
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_add1() */
void ei_add( EMUSHORT *eic, EMUSHORT *eia, EMUSHORT *eib, int nb )
/***************************************************************
Description : ei_add() Работает с
internal e-type data struct.
Concepts : EIC = EIA + EIB.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *p_a = NULL, *p_b = NULL;
int np;
np = internal_np( nb );
/*** Allocate memory for p_a, p_b . *************************/
p_a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p_a )
{
/* fatal error */
return;
}
p_b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p_b )
{
/* fatal error */
/* FREE p_a ***************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( p_a, eia, nb );
ei_copy( p_b, eib, nb );
/* EIA */
/* InD plus anything is a InD */
if( ei_isind( eia, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eia, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"add", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eia, nb ) )
{
ei_copy( eic, eia, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EIB */
/* InD plus anything is a InD */
if( ei_isind( eib, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eib, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"add", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eib, nb ) )
{
ei_copy( eic, eib, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* Infinity minus infinity is a InD.
Test for adding infinities of opposite signs. */
if( ei_isinfin( eia, nb ) && ei_isinfin( eib, nb ) &&
(ei_isneg( eia, nb ) ^ ei_isneg( eib, nb )) != 0 )
{
/* "invalid operation" */
ei_ind( eic, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"sub", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
subflag = 0;
ei_add1( eic, p_a, p_b, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_add() */
void ei_sub( EMUSHORT *eic, EMUSHORT *eia, EMUSHORT *eib, int nb )
/***************************************************************
Description : ei_sub() Работает с
internal e-type data struct.
Concepts : EIC = EIA - EIB.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *p_a = NULL, *p_b = NULL;
int np;
np = internal_np( nb );
/*** Allocate memory for p_a, p_b . *************************/
p_a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p_a )
{
/* fatal error */
return;
}
p_b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p_b )
{
/* fatal error */
/* FREE p_a ***************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( p_a, eia, nb );
ei_copy( p_b, eib, nb );
/* EIA */
/* InD plus anything is a InD */
if( ei_isind( eia, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eia, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"sub", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eia, nb ) )
{
ei_copy( eic, eia, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EIB */
/* InD plus anything is a InD */
if( ei_isind( eib, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eib, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"sub", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eib, nb ) )
{
ei_copy( eic, eib, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* Infinity minus infinity is a InD.
Test for adding infinities of opposite signs. */
if( ei_isinfin( eia, nb ) && ei_isinfin( eib, nb ) &&
(ei_isneg( eia, nb ) ^ ei_isneg( eib, nb )) == 0 )
{
/* "invalid operation" */
ei_ind( eic, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"sub", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
subflag = 1;
ei_add1( eic, p_a, p_b, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_sub() */
void ei_div( EMUSHORT *eic, EMUSHORT *eia, EMUSHORT *eib, int nb )
/***************************************************************
Description : ei_div() Работает с
internal e-type data struct.
Concepts : EIC = EIA / EIB.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *p_a = NULL,
*p_b = NULL;
EMUSHORT *exone = NULL,
*lt = NULL,
*lta = NULL,
*ltb = NULL;
EMUSHORT *p;
__mpu_int32_t j;
int k, rndsave;
int np, ne, ns, i;
np = internal_np( nb );
/*** Allocate memory for p_a, p_b . *************************/
p_a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p_a )
{
/* fatal error */
return;
}
p_b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p_b )
{
/* fatal error */
/* FREE p_a ***************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( p_a, eia, nb );
ei_copy( p_b, eib, nb );
/* EIA */
/* InD plus anything is a InD */
if( ei_isind( eia, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eia, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"div", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eia, nb ) )
{
ei_copy( eic, eia, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EIB */
/* InD plus anything is a InD */
if( ei_isind( eib, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eib, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"div", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eib, nb ) )
{
ei_copy( eic, eib, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* Zero over zero, or infinity over infinity, is a InD. */
if( ( ei_isinfin( eia, nb ) && ei_isinfin( eib, nb ) ) ||
( ei_issignull( eia, nb ) && ei_issignull( eib, nb ) ) )
{
/* "invalid operation" */
ei_ind( eic, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"div", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* Infinity over anything else is infinity. */
if( ei_isinfin( eia, nb ) )
{
ei_infin( eic,
(unsigned)(ei_isneg( eia, nb ) ^ ei_isneg( eib, nb )),
nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* Anything else over infinity is zero */
if( ei_isinfin( eib, nb ) )
{
ei_signull( eic,
(unsigned)(ei_isneg( eia, nb ) ^ ei_isneg( eib, nb )),
nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for lt, lta, ltb, exone . **************/
lt = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !lt )
{
/* fatal error */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
lta = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !lta )
{
/* fatal error */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ltb = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !ltb )
{
/* fatal error */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
exone = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( lta, &p_a[1], ne+1, ne );
ei_cpye_unpack( ltb, &p_b[1], ne+1, ne );
#else
ei_cpye_unpack( lta, &p_a[ns+2], ne+1, ne );
ei_cpye_unpack( ltb, &p_b[ns+2], ne+1, ne );
#endif
for( i = 0; i < ne+1; i++ ) exone[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( ei_cmpe( &p_a[1], exone, ne ) == 0 ) /* exp( a ) == 0 */
#else
if( ei_cmpe( &p_a[ns+2], exone, ne ) == 0 ) /* exp( a ) == 0 */
#endif
{
/* See if numerator is zero. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &p_a[ne + 1]; /* hgw */
#else
p = &p_a[ns + 1]; /* hgw */
#endif
for( i = 0; i < ns+2; i++ )
{
if( *p != (EMUSHORT)0 )
{
/* lta -= ei_normalize( p_a, nb ); */
j = ei_normalize( p_a, nb );
ei_cvte_unpack( exone, (EMUSHORT *)&j, ne+1, 1 );
ei_sube( lta, lta, exone, ne+1 );
goto dnzro1;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p++; /* to lgw */
#else
p--; /* to lgw */
#endif
} /* End for( i = 0; i < ns+2; i++ ) */
ei_signull( eic,
(unsigned)(ei_isneg( p_a, nb ) ^ ei_isneg( p_b, nb )),
nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE exone *************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( exp( a ) == 0 ) */
dnzro1:
for( i = 0; i < ne+1; i++ ) exone[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( ei_cmpe( &p_b[1], exone, ne ) == 0 ) /* exp( b ) == 0 */
#else
if( ei_cmpe( &p_b[ns+2], exone, ne ) == 0 ) /* exp( b ) == 0 */
#endif
{
/* possible divide by zero. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &p_b[ne + 1]; /* hgw */
#else
p = &p_b[ns + 1]; /* hgw */
#endif
for( i = 0; i < ns+2; i++ )
{
if( *p != (EMUSHORT)0 )
{
/* ltb -= ei_normalize( p_b, nb ); */
j = ei_normalize( p_b, nb );
ei_cvte_unpack( exone, (EMUSHORT *)&j, ne+1, 1 );
ei_sube( ltb, ltb, exone, ne+1 );
goto dnzro2;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p++; /* to lgw */
#else
p--; /* to lgw */
#endif
} /* End for( i = 0; i < ns+2; i++ ) */
/* Divide by zero is not an invalid operation.
It is a divide-by-zero operation! */
ei_infin( eic,
(unsigned)(ei_isneg( p_a, nb ) ^ ei_isneg( p_b, nb )),
nb );
/* Set SING for divide-by-zero operation! */
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"div", __SING__, eic, p_a, p_b, nb );
__STSNG; /* Set REAL Singularity Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE exone *************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( exp( b ) == 0 ) */
dnzro2:
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* формирование EXONE */
/* hight part */
p = exone;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* формирование EXONE */
/* hight part */
p = exone + ne;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
k = ei_divm( p_a, p_a, p_b, nb );
/* Calculate Exponent */
/* lt = lta - ltb + EXONE; */
ei_sube( lt, lta, ltb, ne+1 );
ei_adde( lt, lt, exone, ne+1 );
rndsave = rndprc;
rndprc = (int)EINSBITS(nb);
/*****************************************************************
Здесь все равно какое значение RNDPRC, т.к. если оно не равно
(24 или 53), то ei_mdenorm() округляет путем отбрасывания lgw
данного ей числа в internal формате.
Мы использовали rndprc = (int)EINSBITS(nb); для того, чтобы
избежать ошибок при больших размерах EMUSHORT.
******************************************************************/
ei_mdenorm( p_a, k, 0, lt, (int)EINSBITS(nb), nb );
rndprc = rndsave;
ei_copy( eic, p_a, nb );
/* Set the Sign */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = eic;
#else
p = eic + np - 1;
#endif
if( ei_isneg( p_a, nb ) ^
ei_isneg( p_b, nb ) ) *p = MASK_ALL_BITS;
else *p = (EMUSHORT)0;
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE exone *************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_div() */
void ei_mul( EMUSHORT *eic, EMUSHORT *eia, EMUSHORT *eib, int nb )
/***************************************************************
Description : ei_mul() Работает с
internal e-type data struct.
Concepts : EIC = EIA * EIB.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
;
EMUSHORT *eib; - указатель на
internal e-type
data struct.
;
int nb; - количество бит в
external e-type
data struct.
Return : [void]
***************************************************************/
{
EMUSHORT *p_a = NULL,
*p_b = NULL;
EMUSHORT *exone = NULL,
*lt = NULL,
*lta = NULL,
*ltb = NULL;
EMUSHORT *p;
__mpu_int32_t j;
int k, rndsave;
int np, ne, ns, i;
np = internal_np( nb );
/*** Allocate memory for p_a, p_b . *************************/
p_a = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p_a )
{
/* fatal error */
return;
}
p_b = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !p_b )
{
/* fatal error */
/* FREE p_a ***************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( p_a, eia, nb );
ei_copy( p_b, eib, nb );
/* EIA */
/* InD plus anything is a InD */
if( ei_isind( eia, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eia, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"mul", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eia, nb ) )
{
ei_copy( eic, eia, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EIB */
/* InD plus anything is a InD */
if( ei_isind( eib, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eib, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"mul", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eib, nb ) )
{
ei_copy( eic, eib, nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* Zero over zero, or infinity over infinity, is a InD. */
if( ( ei_isinfin( eia, nb ) && ei_issignull( eib, nb ) ) ||
( ei_isinfin( eib, nb ) && ei_issignull( eia, nb ) ) )
{
/* "invalid operation" */
ei_ind( eic, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"mul", __INVALID__, eic, p_a, p_b, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* Infinity over anything else is infinity. */
if( ei_isinfin( eia, nb ) || ei_isinfin( eib, nb ) )
{
ei_infin( eic,
(unsigned)(ei_isneg( eia, nb ) ^ ei_isneg( eib, nb )),
nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for lt, lta, ltb, exone . **************/
lt = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !lt )
{
/* fatal error */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
lta = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !lta )
{
/* fatal error */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ltb = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !ltb )
{
/* fatal error */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
exone = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( lta, &p_a[1], ne+1, ne );
ei_cpye_unpack( ltb, &p_b[1], ne+1, ne );
#else
ei_cpye_unpack( lta, &p_a[ns+2], ne+1, ne );
ei_cpye_unpack( ltb, &p_b[ns+2], ne+1, ne );
#endif
for( i = 0; i < ne+1; i++ ) exone[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( ei_cmpe( &p_a[1], exone, ne ) == 0 ) /* exp( a ) == 0 */
#else
if( ei_cmpe( &p_a[ns+2], exone, ne ) == 0 ) /* exp( a ) == 0 */
#endif
{
/* See if EIA is zero. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &p_a[ne + 1]; /* hgw */
#else
p = &p_a[ns + 1]; /* hgw */
#endif
for( i = 0; i < ns+2; i++ )
{
if( *p != (EMUSHORT)0 )
{
/* lta -= ei_normalize( p_a, nb ); */
j = ei_normalize( p_a, nb );
ei_cvte_unpack( exone, (EMUSHORT *)&j, ne+1, 1 );
ei_sube( lta, lta, exone, ne+1 );
goto mnzro1;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p++; /* to lgw */
#else
p--; /* to lgw */
#endif
} /* End for( i = 0; i < ns+2; i++ ) */
ei_signull( eic,
(unsigned)(ei_isneg( p_a, nb ) ^ ei_isneg( p_b, nb )),
nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE exone *************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( exp( a ) == 0 ) */
mnzro1:
for( i = 0; i < ne+1; i++ ) exone[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( ei_cmpe( &p_b[1], exone, ne ) == 0 ) /* exp( b ) == 0 */
#else
if( ei_cmpe( &p_b[ns+2], exone, ne ) == 0 ) /* exp( b ) == 0 */
#endif
{
/* possible divide by zero. */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &p_b[ne + 1]; /* hgw */
#else
p = &p_b[ns + 1]; /* hgw */
#endif
for( i = 0; i < ns+2; i++ )
{
if( *p != (EMUSHORT)0 )
{
/* ltb -= ei_normalize( eib, nb ); */
j = ei_normalize( p_b, nb );
ei_cvte_unpack( exone, (EMUSHORT *)&j, ne+1, 1 );
ei_sube( ltb, ltb, exone, ne+1 );
goto mnzro2;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p++; /* to lgw */
#else
p--; /* to lgw */
#endif
} /* End for( i = 0; i < ns+2; i++ ) */
ei_signull( eic,
(unsigned)(ei_isneg( p_a, nb ) ^ ei_isneg( p_b, nb )),
nb );
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE exone *************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( exp( b ) == 0 ) */
mnzro2:
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* формирование EXONE */
/* hight part */
p = exone;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* формирование EXONE */
/* hight part */
p = exone + ne;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* Multiply significands */
k = ei_mulm( p_a, p_a, p_b, nb );
/* Calculate Exponent */
/* lt = lta + ltb - (EXONE - 1); */
ei_adde( lt, lta, ltb, ne+1 );
ei_dece( exone, exone, ne+1 );
ei_sube( lt, lt, exone, ne+1 );
rndsave = rndprc;
rndprc = (int)EINSBITS(nb);
/*****************************************************************
Здесь все равно какое значение RNDPRC, т.к. если оно не равно
(24 или 53), то ei_mdenorm() округляет путем отбрасывания lgw
данного ей числа в internal формате.
Мы использовали rndprc = (int)EINSBITS(nb); для того, чтобы
избежать ошибок при больших размерах EMUSHORT.
******************************************************************/
ei_mdenorm( p_a, k, 0, lt, (int)EINSBITS(nb), nb );
rndprc = rndsave;
ei_copy( eic, p_a, nb );
/* Set the Sign of product */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = eic;
#else
p = eic + np - 1;
#endif
if( ei_isneg( p_a, nb ) ^
ei_isneg( p_b, nb ) ) *p = MASK_ALL_BITS;
else *p = (EMUSHORT)0;
/* FREE p_a ***************/
/* FREE p_b ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE lt ****************/
/* FREE lta ***************/
/* FREE ltb ***************/
/* FREE exone *************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_mul() */
void ei_ltor( EMUSHORT *ei, EMUSHORT *lp, int nb, int nlp )
/***************************************************************
Description : ei_ltor() Работает с
internal e-type data struct.
Concepts : Convert Signed integer *LP to internal
e-type data struct *EI.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *ei; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *lp; - указатель на
знаковое целое
число.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
int nlp; - количество слов
типа EMUSHORT в
целом числе по
указателю *lp.
Return : [void]
***************************************************************/
{
EMUSHORT *exone = NULL,
*inc = NULL,
*p_l = NULL; /* save *lp */
EMUSHORT *e, *p;
__mpu_int32_t k;
int np, ne, ns, i, n;
if( nb < NBR_32 || nlp == 0 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for p_l . ******************************/
p_l = (EMUSHORT *)__mpu_sbrk( (int)(nlp*SIZE_OF_EMUSHORT) );
if( !p_l )
{
/* fatal error */
return;
}
/************************************************************/
/*** Allocate memory for exone, inc . ***********************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
/* FREE p_l ***************/
__mpu_sbrk( -(int)(nlp*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE p_l ***************/
__mpu_sbrk( -(int)(nlp*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_cleaz( ei, nb );
if( ei_cmp0e( lp, nlp ) < 0 ) /* *LP < 0 */
{
/* Negate *LP */
ei_nege( p_l, lp, nlp );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* put correct Sign in the Internal e-type number */
ei[0] = MASK_ALL_BITS;
#else
/* put correct Sign in the Internal e-type number */
ei[np-1] = MASK_ALL_BITS;
#endif
}
else
{
/* Copy *LP */
for( i = 0; i < nlp; i++ ) p_l[i] = lp[i];
} /* End if( *LP < 0 ) */
/* Copy the LONG INTEGER to EI Significand area */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = p_l; /* hight part */
e = &ei[ne+1]; /* hgw */
#else
p = p_l + nlp - 1; /* hight part */
e = &ei[ns+1]; /* hgw */
#endif
/* if( nlp > ns ) low part of *LP my be LOST; */
if( nlp >= ns ) n = ns;
else n = nlp;
/* Copy the LONG INTEGER to EI Significand area */
for( i = 0; i < n; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*e++ = *p++;
#else
*e-- = *p--;
#endif
} /* End for( copy ) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* формирование EXONE */
/* hight part */
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* формирование EXONE */
/* hight part */
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* Clear inc */
for( i = 0; i < ne; i++ ) inc[i] = (EMUSHORT)0;
/* Количество бит целого также (как и Significand) ограничено
знаковым числом, которое укладывается в тип signed EMUSHORT.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne-1] = (nlp-1)*BITS_PER_EMUSHORT - 1; /* low part */
#else
inc[0] = (nlp-1)*BITS_PER_EMUSHORT - 1;
#endif
/*********************************
For Correct SIGNED result!!!
*********************************/
ei_cvte_unpack( inc, inc, ne, 1 );
/* put correct Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_adde( &ei[1], exone, inc, ne );
#else
ei_adde( &ei[ns+2], exone, inc, ne );
#endif
/* normalize the Significand */
if( (k = ei_normalize( ei, nb )) > (__mpu_int32_t)EINSBITS(nb) )
{
/* it was zero : это был нуль */
ei_cleaz( ei, nb );
}
else
{
ei_cvte_unpack( inc, (EMUSHORT *)&k, ne, 1 );
/* Exponent -= k; */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_sube( &ei[1], &ei[1], inc, ne );
#else
ei_sube( &ei[ns+2], &ei[ns+2], inc, ne );
#endif
}
/* FREE p_l ***************/
__mpu_sbrk( -(int)(nlp*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_ltor() */
void ei_ultor( EMUSHORT *ei, EMUSHORT *lp, int nb, int nlp )
/***************************************************************
Description : ei_ultor() Работает с
internal e-type data struct.
Concepts : Convert UNsigned integer *LP to internal
e-type data struct *EI.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *ei; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *lp; - указатель на
беззнаковое целое
число.
SOURCE;
int nb; - количество бит в
external e-type
data struct.
int nlp; - количество слов
типа EMUSHORT в
целом числе по
указателю *lp.
Return : [void]
***************************************************************/
{
EMUSHORT *exone = NULL,
*inc = NULL,
*p_l = NULL; /* save *lp */
EMUSHORT *e, *p;
__mpu_int32_t k;
int ne, ns, i, n;
if( nb < NBR_32 || nlp == 0 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for p_l . ******************************/
p_l = (EMUSHORT *)__mpu_sbrk( (int)(nlp*SIZE_OF_EMUSHORT) );
if( !p_l )
{
/* fatal error */
return;
}
/************************************************************/
/*** Allocate memory for exone, inc . ***********************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
/* FREE p_l ***************/
__mpu_sbrk( -(int)(nlp*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE p_l ***************/
__mpu_sbrk( -(int)(nlp*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* Copy *lp */
for( i = 0; i < nlp; i++ ) p_l[i] = lp[i];
ei_cleaz( ei, nb );
/* Copy the LONG INTEGER to EI Significand area */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = p_l; /* hight part */
e = &ei[ne+1]; /* hgw */
#else
p = p_l + nlp - 1; /* hight part */
e = &ei[ns+1]; /* hgw */
#endif
/* if( nlp > ns ) low part of *LP my be LOST; */
if( nlp >= ns ) n = ns;
else n = nlp;
/* Copy the LONG INTEGER to EI Significand area */
for( i = 0; i < n; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*e++ = *p++;
#else
*e-- = *p--;
#endif
} /* End for( copy ) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* формирование EXONE */
/* hight part */
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* формирование EXONE */
/* hight part */
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* Clear inc */
for( i = 0; i < ne; i++ ) inc[i] = (EMUSHORT)0;
/* Количество бит целого также (как и Significand) ограничено
знаковым числом, которое укладывается в тип signed EMUSHORT.
*/
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne-1] = (nlp-1)*BITS_PER_EMUSHORT - 1; /* low part */
#else
inc[0] = (nlp-1)*BITS_PER_EMUSHORT - 1;
#endif
/*********************************
For Correct SIGNED result!!!
*********************************/
ei_cvte_unpack( inc, inc, ne, 1 );
/* put correct Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_adde( &ei[1], exone, inc, ne );
#else
ei_adde( &ei[ns+2], exone, inc, ne );
#endif
/* normalize the Significand */
if( (k = ei_normalize( ei, nb )) > (__mpu_int32_t)EINSBITS(nb) )
{
/* it was zero : это был нуль */
ei_cleaz( ei, nb );
}
else
{
ei_cvte_unpack( inc, (EMUSHORT *)&k, ne, 1 );
/* Exponent -= k; */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_sube( &ei[1], &ei[1], inc, ne );
#else
ei_sube( &ei[ns+2], &ei[ns+2], inc, ne );
#endif
} /* End of normalize the Significand */
/* FREE p_l ***************/
__mpu_sbrk( -(int)(nlp*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exone *************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_ultor() */
void ei_rtoul_frac( EMUSHORT *lp, EMUSHORT *frac, EMUSHORT *ei, int nlp, int nb )
/***************************************************************
Description : ei_rtoul_frac() Работает с
internal e-type data
struct.
Concepts : Find Unsigned long INTEGER *LP and
floating point fractional part *FRAC of
Internal e-type floating point input *EI.
A negative input yields INTEGER output=0
but correct fraction.
The output Internal e-type fraction
*FRAC is the positive fractional part of
abs(*EI).
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *lp; - указатель на
беззнаковое целое
число.
TARGET;
EMUSHORT *frac; - указатель на
internal e-type
data struct.
TARGET FRAC;
NOTE:
if( FRAC == 0 ) ei_rtoul_frac() просто
не пытается вывести
полученную дробную часть.
EMUSHORT *ei; - указатель на
internal e-type
data struct.
SOURCE;
int nlp; - количество слов
типа EMUSHORT в
целом числе по
указателю *lp.
int nb; - количество бит в
internal e-type
data struct;
SOURCE & *FRAC.
Return : [void]
***************************************************************/
{
EMUSHORT *exone = NULL,
*inc = NULL,
*k = NULL,
*fi = NULL; /* tmp for FRAC */
EMUSHORT *p;
__mpu_int32_t j;
int np, ne, ns, i;
if( nb < NBR_32 || nlp == 0 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, inc, k, fi . ****************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
k = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !k )
{
/* fatal error */
/* FREE exone *************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
fi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !fi )
{
/* fatal error */
/* FREE exone *************/
/* FREE inc ***************/
/* FREE k *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
for( i = 0; i < nlp; i++ ) lp[i] = (EMUSHORT)0;
ei_copy( fi, ei, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* формирование EXONE */
/* hight part */
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* формирование EXONE */
/* hight part */
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* k = Exponent( fi ) - (EXONE - 1); */
ei_dece( exone, exone, ne ); /* save (EXONE - 1) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_sube( k, &fi[1], exone, ne );
#else
ei_sube( k, &fi[ns+2], exone, ne );
#endif
if( ei_cmp0e( k, ne ) <= 0 )
{
/* if( Exponent <= 0 ), integer = 0 and
real output is fraction */
for( i = 0; i < nlp; i++ ) lp[i] = (EMUSHORT)0;
if( frac ) ei_copy( frac, fi, nb );
/* FREE exone *************/
/* FREE inc ***************/
/* FREE k *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
for( i = 0; i < ne; i++ ) inc[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne-1] = (EMUSHORT)(BITS_PER_EMUSHORT*nlp);
#else
inc[0] = (EMUSHORT)(BITS_PER_EMUSHORT*nlp);
#endif
if( ei_cmpe( k, inc, ne ) > 0 ) /* k > inc */
{
/* long INTEGER overflow: output large integer and
correct fraction */
/* In this case, return the largest unsigned INTEGER */
for( i = 0; i < nlp; i++ ) lp[i] = MASK_ALL_BITS;
/* Страховка на случай если
k > max positive Signed EMUSHORT */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne-1] = HIGHT_EXP;
#else
inc[0] = HIGHT_EXP;
#endif
if( ei_cmpe( k, inc, ne ) > 0 )
{
ei_shift( fi, (ns+1)*BITS_PER_EMUSHORT, nb );
}
else
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
j = k[ne-1];
#else
j = k[0];
#endif
ei_shift( fi, j, nb );
}
if( __extra_warnings )
{
struct __exception e;
__real_error_no = __R_ETRUNC__;
e.who = _REAL_;
e.type = __real_error_no;
e.name = (__mpu_char8_t *)"ei_rtoul_frac";
e.msg = __mpu_utf8mpu_error( _REAL_, __real_error_no );
e.msg_type = _WARNING_MSG_;
e.nb_a1 = 0;
e.nb_a2 = 0;
e.nb_rv = 0;
e.arg_1 = (unsigned char *)0;
e.arg_2 = (unsigned char *)0;
e.return_value = (unsigned char *)0;
__mpu_warning( &e );
if( e.msg ) free( e.msg );
} /* End if( __extra_warnings ) */
}
else /* т.е. k <= (BITS_PER_EMUSHORT*nlp); */
{
/* NOTE: Здесь k > 0 */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
j = k[ne-1];
#else
j = k[0];
#endif
if( j > BITS_PER_EMUSHORT )
{
int n;
n = j % BITS_PER_EMUSHORT;
ei_shift( fi, n, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lp[nlp-1] = fi[ne+1]; /* hgw to low part */
#else
lp[0] = fi[ns+1];
#endif
j -= n;
do
{
ei_shup( fi, BITS_PER_EMUSHORT, nb );
ei_shln( lp, lp, BITS_PER_EMUSHORT, nlp );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lp[nlp-1] = fi[ne+1]; /* hgw to low part */
#else
lp[0] = fi[ns+1];
#endif
} while( (j -= BITS_PER_EMUSHORT) > 0 );
}
else
{
ei_shift( fi, j, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lp[nlp-1] = fi[ne+1]; /* hgw to low part */
#else
lp[0] = fi[ns+1];
#endif
}
} /* End if( k > BITS_PER_EMUSHORT*nlp ) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( fi[0] ) /* if( Sign ) *LP = NULL; */
#else
if( fi[np-1] ) /* if( Sign ) *LP = NULL; */
#endif
for( i = 0; i < nlp; i++ ) lp[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
fi[0] = (EMUSHORT)0; /* Sign */
ei_cpye( &fi[1], exone, ne, ne );
fi[ne+1] = (EMUSHORT)0; /* hgw */
#else
fi[np-1] = (EMUSHORT)0; /* Sign */
ei_cpye( &fi[ns+2], exone, ne, ne );
fi[ns+1] = (EMUSHORT)0; /* hgw */
#endif
/* normalize the Significand */
if( (j = ei_normalize( fi, nb )) > (__mpu_int32_t)EINSBITS(nb) )
{
/* it was zero : это был нуль */
ei_cleaz( fi, nb );
}
else
{
ei_cvte_unpack( inc, (EMUSHORT *)&j, ne, 1 );
/* Exponent -= k; */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_sube( &fi[1], &fi[1], inc, ne );
#else
ei_sube( &fi[ns+2], &fi[ns+2], inc, ne );
#endif
} /* End of normalize the Significand */
if( frac ) ei_copy( frac, fi, nb );
/* FREE exone *************/
/* FREE inc ***************/
/* FREE k *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_rtoul_frac() */
void ei_rtol_frac( EMUSHORT *lp, EMUSHORT *frac, EMUSHORT *ei, int nlp, int nb )
/***************************************************************
Description : ei_rtol_frac() Работает с
internal e-type data
struct.
Concepts : Find Signed long INTEGER *LP and floating
point fractional part *FRAC of Internal
e-type floating point input *EI.
The INTEGER output *LP has the sign of
the input *EI, except that positive
overflov is permitted
if FIXUNS_TRUNC_LIKE_FIX_TRUNC.
The output Internal e-type fraction
*FRAC is the positive fractional part of
abs(*EI).
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *lp; - указатель на
знаковое целое
число.
TARGET;
EMUSHORT *frac; - указатель на
internal e-type
data struct.
TARGET FRAC;
NOTE:
if( FRAC == 0 ) ei_rtol_frac() просто
не пытается вывести
полученную дробную
часть.
EMUSHORT *ei; - указатель на
internal e-type
data struct.
SOURCE;
int nlp; - количество слов
типа EMUSHORT в
целом числе по
указателю *lp.
int nb; - количество бит в
internal e-type
data struct;
SOURCE & *FRAC.
Return : [void]
***************************************************************/
{
EMUSHORT *exone = NULL,
*inc = NULL,
*k = NULL,
*fi = NULL; /* tmp for FRAC */
EMUSHORT *p;
__mpu_int32_t j;
int np, ne, ns, i;
if( nb < NBR_32 || nlp == 0 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, inc, k, fi . ****************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
k = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !k )
{
/* fatal error */
/* FREE exone *************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
fi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !fi )
{
/* fatal error */
/* FREE exone *************/
/* FREE inc ***************/
/* FREE k *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
for( i = 0; i < nlp; i++ ) lp[i] = (EMUSHORT)0;
ei_copy( fi, ei, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* формирование EXONE */
/* hight part */
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* формирование EXONE */
/* hight part */
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* k = Exponent( fi ) - (EXONE - 1); */
ei_dece( exone, exone, ne ); /* save (EXONE - 1) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_sube( k, &fi[1], exone, ne );
#else
ei_sube( k, &fi[ns+2], exone, ne );
#endif
if( ei_cmp0e( k, ne ) <= 0 )
{
/* if( Exponent <= 0 ), integer = 0 and
real output is fraction */
for( i = 0; i < nlp; i++ ) lp[i] = (EMUSHORT)0;
if( frac ) ei_copy( frac, fi, nb );
/* FREE exone *************/
/* FREE inc ***************/
/* FREE k *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
for( i = 0; i < ne; i++ ) inc[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne-1] = (EMUSHORT)(BITS_PER_EMUSHORT*nlp - 1);
#else
inc[0] = (EMUSHORT)(BITS_PER_EMUSHORT*nlp - 1);
#endif
if( ei_cmpe( k, inc, ne ) > 0 ) /* k > inc */
{
/* long INTEGER overflow: output large integer and
correct fraction */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( fi[0] )
#else
if( fi[np-1] )
#endif
{
/* In this case, return the largest negative INTEGER */
for( i = 0; i < nlp; i++ ) lp[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lp[0] = MASK_SIGN;
#else
lp[nlp-1] = MASK_SIGN;
#endif
}
else
{
#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
/* In this case, let it overflow and convert as if unsigned */
ei_rtoul_frac( lp, frac, ei, nlp, nb );
/* FREE exone *************/
/* FREE inc ***************/
/* FREE k *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
#else /* Not FIXUNS_TRUNC_LIKE_FIX_TRUNC */
/* In other cases, return the largest positive INTEGER */
for( i = 0; i < nlp; i++ ) lp[i] = MASK_ALL_BITS;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lp[0] ^= MASK_SIGN;
#else
lp[nlp-1] ^= MASK_SIGN;
#endif
#endif /* FIXUNS_TRUNC_LIKE_FIX_TRUNC */
} /* End if( Sign ) */
/* Страховка на случай если
k > max positive Signed EMUSHORT */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne-1] = HIGHT_EXP;
#else
inc[0] = HIGHT_EXP;
#endif
if( ei_cmpe( k, inc, ne ) > 0 )
{
ei_shift( fi, (ns+1)*BITS_PER_EMUSHORT, nb );
}
else
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
j = k[ne-1];
#else
j = k[0];
#endif
ei_shift( fi, j, nb );
}
if( __extra_warnings )
{
struct __exception e;
__real_error_no = __R_ETRUNC__;
e.who = _REAL_;
e.type = __real_error_no;
e.name = (__mpu_char8_t *)"ei_rtol_frac";
e.msg = __mpu_utf8mpu_error( _REAL_, __real_error_no );
e.msg_type = _WARNING_MSG_;
e.nb_a1 = 0;
e.nb_a2 = 0;
e.nb_rv = 0;
e.arg_1 = (unsigned char *)0;
e.arg_2 = (unsigned char *)0;
e.return_value = (unsigned char *)0;
__mpu_warning( &e );
if( e.msg ) free( e.msg );
} /* End if( __extra_warnings ) */
}
else /* т.е. k <= (BITS_PER_EMUSHORT*nlp - 1); */
{
/* NOTE: Здесь k > 0 */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
j = k[ne-1];
#else
j = k[0];
#endif
if( j > BITS_PER_EMUSHORT )
{
int n;
n = j % BITS_PER_EMUSHORT;
ei_shift( fi, n, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lp[nlp-1] = fi[ne+1]; /* hgw to low part */
#else
lp[0] = fi[ns+1];
#endif
j -= n;
do
{
ei_shup( fi, BITS_PER_EMUSHORT, nb );
ei_shln( lp, lp, BITS_PER_EMUSHORT, nlp );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lp[nlp-1] = fi[ne+1]; /* hgw to low part */
#else
lp[0] = fi[ns+1];
#endif
} while( (j -= BITS_PER_EMUSHORT) > 0 );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( fi[0] )
#else
if( fi[np-1] )
#endif
ei_nege( lp, lp, nlp );
}
else
{
ei_shift( fi, j, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
lp[nlp-1] = fi[ne+1]; /* hgw to low part */
if( fi[0] )
#else
lp[0] = fi[ns+1];
if( fi[np-1] )
#endif
ei_nege( lp, lp, nlp );
}
} /* End if( k > BITS_PER_EMUSHORT*nlp - 1 ) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
fi[0] = (EMUSHORT)0; /* Sign */
ei_cpye( &fi[1], exone, ne, ne );
fi[ne+1] = (EMUSHORT)0; /* hgw */
#else
fi[np-1] = (EMUSHORT)0; /* Sign */
ei_cpye( &fi[ns+2], exone, ne, ne );
fi[ns+1] = (EMUSHORT)0; /* hgw */
#endif
/* normalize the Significand */
if( (j = ei_normalize( fi, nb )) > (__mpu_int32_t)EINSBITS(nb) )
{
/* it was zero : это был нуль */
ei_cleaz( fi, nb );
}
else
{
ei_cvte_unpack( inc, (EMUSHORT *)&j, ne, 1 );
/* Exponent -= k; */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_sube( &fi[1], &fi[1], inc, ne );
#else
ei_sube( &fi[ns+2], &fi[ns+2], inc, ne );
#endif
} /* End of normalize the Significand */
if( frac ) ei_copy( frac, fi, nb );
/* FREE exone *************/
/* FREE inc ***************/
/* FREE k *****************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_rtol_frac() */
/***************************************************************
GENERATORS OF CONSTANT:
***************************************************************/
/***************************************************************
Память адресуемая *EIA должна быть достаточна для размещения
производимых констант. Чтобы избежать ошибок можно
воспользоваться макро NPIR_MAX, например:
unsigned EMUSHORT half[NPIR_MAX];
_gen_half( half, NBR_256 );
***************************************************************/
void _gen_zero( EMUSHORT *eia, int nb )
/****************************************
0.0;
zero: Sign 0x0000 hgw 0x0000 ... lgw
****************************************/
{
EMUSHORT *ei = eia; /* = _ei_zero_; */
ei_signull( ei, (unsigned)0, nb );
} /* End of _gen_zero() */
void _gen_half( EMUSHORT *eia, int nb )
/****************************************
5.0E-1;
half: Sign 0x3ffe hgw 0x8000 ... lgw
****************************************/
{
EMUSHORT *ei = eia; /* = _ei_half_; */
int i, ne, ns;
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + ne + ns + 2; /* начинаем с Sign */
#endif
*ei = (EMUSHORT)0; /* Sign */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++ei;
*ei++ = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *ei++ = MASK_ALL_BITS;
--ei;
*ei ^= 1; /* Low part of Exponent */
++ei;
*ei++ = (EMUSHORT)0; /* hgw */
*ei++ = MASK_SIGN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei++ = (EMUSHORT)0;
#else
--ei;
*ei-- = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *ei-- = MASK_ALL_BITS;
++ei;
*ei ^= 1; /* Low part of Exponent */
--ei;
*ei-- = (EMUSHORT)0; /* hgw */
*ei-- = MASK_SIGN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei-- = (EMUSHORT)0;
#endif
*ei = (EMUSHORT)0; /* lgw */
} /* End of _gen_half() */
void _gen_one( EMUSHORT *eia, int nb )
/****************************************
1.0E0;
one: Sign 0x3fff hgw 0x8000 ... lgw
****************************************/
{
EMUSHORT *ei = eia; /* = _ei_one_; */
int i, ne, ns;
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + ne + ns + 2; /* начинаем с Sign */
#endif
*ei = (EMUSHORT)0; /* Sign */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++ei;
*ei++ = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *ei++ = MASK_ALL_BITS;
*ei++ = (EMUSHORT)0; /* hgw */
*ei++ = MASK_SIGN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei++ = (EMUSHORT)0;
#else
--ei;
*ei-- = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *ei-- = MASK_ALL_BITS;
*ei-- = (EMUSHORT)0; /* hgw */
*ei-- = MASK_SIGN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei-- = (EMUSHORT)0;
#endif
*ei = (EMUSHORT)0; /* lgw */
} /* End of _gen_one() */
void _gen_two( EMUSHORT *eia, int nb )
/****************************************
2.0E0;
two: Sign 0x4000 hgw 0x8000 ... lgw
****************************************/
{
EMUSHORT *ei = eia; /* = _ei_two_; */
int i, ne, ns;
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + ne + ns + 2; /* начинаем с Sign */
#endif
*ei = (EMUSHORT)0; /* Sign */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++ei;
*ei++ = HIGHT_EXTWO;
for( i = 1; i < ne; i++ ) *ei++ = (EMUSHORT)0;
*ei++ = (EMUSHORT)0; /* hgw */
*ei++ = MASK_SIGN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei++ = (EMUSHORT)0;
#else
--ei;
*ei-- = HIGHT_EXTWO;
for( i = 1; i < ne; i++ ) *ei-- = (EMUSHORT)0;
*ei-- = (EMUSHORT)0; /* hgw */
*ei-- = MASK_SIGN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei-- = (EMUSHORT)0;
#endif
*ei = (EMUSHORT)0; /* lgw */
} /* End of _gen_two() */
void _gen_ten( EMUSHORT *eia, int nb )
/****************************************
1.0E1;
10: Sign 0x4002 hgw 0xa000 ... lgw
****************************************/
{
EMUSHORT *ei = eia; /* = _ei_ten_; */
int i, ne, ns;
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + ne + ns + 2; /* начинаем с Sign */
#endif
*ei = (EMUSHORT)0; /* Sign */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++ei;
*ei++ = HIGHT_EXTWO;
for( i = 1; i < ne; i++ ) *ei++ = (EMUSHORT)0;
--ei;
*ei |= 2; /* Low part of Exponent */
++ei;
*ei++ = (EMUSHORT)0; /* hgw */
*ei++ = HIGHT_M_TEN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei++ = (EMUSHORT)0;
#else
--ei;
*ei-- = HIGHT_EXTWO;
for( i = 1; i < ne; i++ ) *ei-- = (EMUSHORT)0;
++ei;
*ei |= 2; /* Low part of Exponent */
--ei;
*ei-- = (EMUSHORT)0; /* hgw */
*ei-- = HIGHT_M_TEN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei-- = (EMUSHORT)0;
#endif
*ei = (EMUSHORT)0; /* lgw */
} /* End of _gen_ten() */
void _gen_mten( EMUSHORT *eia, int nb )
/*********************************************
1.0E-1;
0.1: Sign 0x3ffb hgw 0xcccc ... cccd lgw
*********************************************/
{
EMUSHORT *ei = eia; /* = _ei_mten_; */
int i, ne, ns;
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + ne + ns + 2; /* начинаем с Sign */
#endif
*ei = (EMUSHORT)0; /* Sign */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++ei;
*ei++ = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *ei++ = MASK_ALL_BITS;
--ei;
*ei ^= 4; /* Low part of Exponent */
++ei;
*ei++ = (EMUSHORT)0; /* hgw */
*ei++ = HIGHT_M_MTEN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei++ = HIGHT_M_MTEN;
--ei;
*ei |= 1; /* Low part of Significand */
++ei;
#else
--ei;
*ei-- = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *ei-- = MASK_ALL_BITS;
++ei;
*ei ^= 4; /* Low part of Exponent */
--ei;
*ei-- = (EMUSHORT)0; /* hgw */
*ei-- = HIGHT_M_MTEN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei-- = HIGHT_M_MTEN;
++ei;
*ei |= 1; /* Low part of Significand */
--ei;
#endif
*ei = (EMUSHORT)0; /* lgw */
} /* End of _gen_mten() */
void _gen_32( EMUSHORT *eia, int nb )
/****************************************
3.2E1;
32: Sign 0x4004 hgw 0x8000 ... lgw
****************************************/
{
EMUSHORT *ei = eia; /* = _ei_32_; */
int i, ne, ns;
ne = internal_ne( nb );
ns = internal_ns( nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
ei = ei + ne + ns + 2; /* начинаем с Sign */
#endif
*ei = (EMUSHORT)0; /* Sign */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++ei;
*ei++ = HIGHT_EXTWO;
for( i = 1; i < ne; i++ ) *ei++ = (EMUSHORT)0;
--ei;
*ei |= 4; /* Low part of Exponent */
++ei;
*ei++ = (EMUSHORT)0; /* hgw */
*ei++ = MASK_SIGN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei++ = (EMUSHORT)0;
#else
--ei;
*ei-- = HIGHT_EXTWO;
for( i = 1; i < ne; i++ ) *ei-- = (EMUSHORT)0;
++ei;
*ei |= 4; /* Low part of Exponent */
--ei;
*ei-- = (EMUSHORT)0; /* hgw */
*ei-- = MASK_SIGN; /* с неявной 1.0 */
for( i = 1; i < ns; i++ ) *ei-- = (EMUSHORT)0;
#endif
*ei = (EMUSHORT)0; /* lgw */
} /* End of _gen_32() */
/***************************************************************
END GENERATORS OF CONSTANT.
***************************************************************/
void ei_remain( EMUSHORT *eic, EMUSHORT *eiquot, EMUSHORT *eia, EMUSHORT *eib, int nb )
/***************************************************************
Description : ei_remain() Работает с
internal e-type data struct.
Concepts : EIC = remainder after dividing EIA by EIB.
Sign of remainder == Sign of quotient.
If( EIQUOT != (EMUSHORT *)0 )
{
RETURN quotient of exploded
e-types EIA / EIB as unsigned
integer number in EIQUOT.
}
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET REMAINDER;
EMUSHORT *eiquot; - указатель на
internal e-type
data struct.
TARGET QUOTIENT;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
EMUSHORT *eib; - указатель на
internal e-type
data struct.
int nb; - количество бит в
external e-type
data struct;
EIA, EIB, EIC &
EIQUOT.
Return : [void]
***************************************************************/
{
EMUSHORT *ld = NULL,
*ln = NULL,
*inc = NULL,
*den = NULL,
*num = NULL,
*equot = NULL,
*zero = NULL;
EMUSHORT *p;
EMUSHORT j;
__mpu_int32_t k;
int np, ne, ns;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
if( ei_isinfin( eia, nb ) )
{
ei_nan( eic, 0, nb );
return;
}
/*** Allocate memory for den, num . *************************/
den = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !den )
{
/* fatal error */
return;
}
num = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !num )
{
/* fatal error */
/* FREE den ***************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( num, eia, nb );
ei_copy( den, eib, nb );
/* EIA */
/* InD plus anything is a InD */
if( ei_isind( eia, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eia, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"remain", __INVALID__, eic, num, den, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE den ***************/
/* FREE num ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eia, nb ) )
{
ei_copy( eic, eia, nb );
/* FREE den ***************/
/* FREE num ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EIB */
/* InD plus anything is a InD */
if( ei_isind( eib, nb ) )
{
/* "invalid operation" */
ei_copy( eic, eib, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"remain", __INVALID__, eic, num, den, nb );
__STIND; /* Set REAL ind-produsing operation Flag */
/* FREE den ***************/
/* FREE num ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* NaN plus anything is a NaN */
if( ei_isnans( eib, nb ) )
{
ei_copy( eic, eib, nb );
/* FREE den ***************/
/* FREE num ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for zero . *****************************/
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE den ***************/
/* FREE num ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_zero( zero, nb ); /* for zero[NPIR_MAX] */
if( ei_cmp( eib, zero, nb ) == 0 )
{
ei_cleaz( eic, nb );
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"remain", __SING__, eic, num, den, nb );
__STSNG; /* Set REAL Singularity Flag */
/* FREE den ***************/
/* FREE num ***************/
/* FREE zero **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for equot, inc, ln, ld . ***************/
equot = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !equot )
{
/* fatal error */
/* FREE den ***************/
/* FREE num ***************/
/* FREE zero **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE den ***************/
/* FREE num ***************/
/* FREE zero **************/
/* FREE equot *************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ln = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !ln )
{
/* fatal error */
/* FREE den ***************/
/* FREE num ***************/
/* FREE zero **************/
/* FREE equot *************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ld = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !ld )
{
/* fatal error */
/* FREE den ***************/
/* FREE num ***************/
/* FREE zero **************/
/* FREE equot *************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
/* FREE ln ****************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( ln, &num[1], ne+1, ne );
ei_cpye_unpack( ld, &den[1], ne+1, ne );
#else
ei_cpye_unpack( ln, &num[ns+2], ne+1, ne );
ei_cpye_unpack( ld, &den[ns+2], ne+1, ne );
#endif
k = ei_normalize( num, nb );
ei_cvte_unpack( inc, (EMUSHORT *)&k, ne+1, 1 );
ei_sube( ln, ln, inc, ne+1 );
k = ei_normalize( den, nb );
ei_cvte_unpack( inc, (EMUSHORT *)&k, ne+1, 1 );
ei_sube( ld, ld, inc, ne+1 );
ei_cleaz( equot, nb );
/* Set *p to low part of Significand */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &equot[np - 1];
#else
p = &equot[0];
#endif
while( ei_cmpe( ln, ld, ne+1 ) >= 0 ) /* ( ln >= ld ) */
{
if( ei_cmpm( den, num, nb ) <= 0 )
{
ei_subm( num, num, den, nb );
j = (EMUSHORT)1;
}
else
j = (EMUSHORT)0;
ei_shup( equot, (unsigned)1, nb );
*p |= j;
ei_shup( num, (unsigned)1, nb );
ei_dece( ln, ln, ne+1 );
} /* End while( ln >= ld ) */
ei_mdenorm( num, 0, 0, ln, 0, nb );
/* Sign of remainder == Sign of quotient */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( eia[0] == eib[0] ) num[0] = (EMUSHORT)0;
else num[0] = MASK_ALL_BITS;
#else
if( eia[np-1] == eib[np-1] ) num[np-1] = (EMUSHORT)0;
else num[np-1] = MASK_ALL_BITS;
#endif
if( eiquot ) ei_copy( eiquot, equot, nb );
ei_copy( eic, num, nb );
/* FREE den ***************/
/* FREE num ***************/
/* FREE zero **************/
/* FREE equot *************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE inc ***************/
/* FREE ln ****************/
/* FREE ld ****************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_remain() */
#if BITS_PER_EMUSHORT == 16
static EMUSHORT bitmask[] =
{
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 bitmask[] =
{
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 bitmask[] =
{
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-real.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_floor( EMUSHORT *eic, EMUSHORT *eia, int nb )
/***************************************************************
Description : ei_floor() Работает с
internal e-type data struct.
Concepts : Return EIC = largest integer not greater
than EIA (truncated toward minus
infinity).
Возвращает EIC = наиболшее (ближайшее)
целое не большее чем EIA (срезает в
сторону минус бесконечности).
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET FLOOR;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct;
EIA, & EIC.
Return : [void]
***************************************************************/
{
EMUSHORT *exone = NULL,
*exp = NULL,
*inc = NULL,
*fi = NULL,
*num = NULL,
*equot = NULL,
*one = NULL;
EMUSHORT *p, *q;
EMUSHORT j;
__mpu_int32_t e;
int np, ne, ns, i;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
/* Если на входе знаковый ноль. */
if( ei_issignull( eia, nb ) )
{
ei_copy( eic, eia, nb );
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, exp, inc . ******************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
exp = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for fi, num, equot,one . ***************/
fi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !fi )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
num = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !num )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
equot = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !equot )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
/* FREE num ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
/* FREE num ***************/
/* FREE equot *************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( fi, eia, nb );
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye( exp, &fi[1], ne, ne );
#else
ei_cpye( exp, &fi[ns+2], ne, ne );
#endif
/* Create EXONE */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* hight part */
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
ei_dece( exone, exone, ne );
ei_sube( exp, exp, exone, ne );
if( ei_cmp0e( exp, nb ) <= 0 ) /* ( exp <= 0 ) */
{
ei_cleaz( eic, nb );
goto isitminus;
}
/* Формируем INC как количество бит мантиссы. */
for( i = 0; i < ne; i++ ) inc[i] = (EMUSHORT)0;
j = EINSBITS(nb);
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne-1] = j;
#else
inc[0] = j;
#endif
ei_sube( exp, inc, exp, ne );
ei_copy( eic, fi, nb );
if( ei_cmp0e( exp, ne ) <= 0 ) /* ( exp <= 0 ) */
{
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
/* FREE num ***************/
/* FREE equot *************/
/* FREE one ***************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &eic[ne+ns+2]; /* lgw */
*p-- = (EMUSHORT)0; /* p -> low part of Significand */
#else
p = &eic[0]; /* lgw */
*p++ = (EMUSHORT)0; /* p -> low part of Significand */
#endif
/* Следующее действие правомерно, т.к. количество бит мантиссы
укладывается в число типа signed EMUSHORT. */
ei_cpye_pack( (EMUSHORT *)(&e), exp, 1, ne );
while( e >= BITS_PER_EMUSHORT )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*p-- = (EMUSHORT)0;
#else
*p++ = (EMUSHORT)0;
#endif
e -= BITS_PER_EMUSHORT;
}
/* Clear the remaining bits. */
*p &= bitmask[e];
/* Truncate negatives toward minus infinity. */
isitminus:
if( ei_isneg( fi, nb ) )
{
_gen_one( one, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
q = &eic[ne+ns+1]; /* low part of Signoficand */
p = &fi[ne+ns+1];
#else
q = &eic[1]; /* low part of Signoficand */
p = &fi[1];
#endif
for( i = 0; i < ns; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *p-- != *q-- )
#else
if( *p++ != *q++ )
#endif
{
ei_sub( eic, eic, one, nb );
break;
}
} /* End for( all parts of Significand ) */
} /* End if( isneg(fi) ) */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
/* FREE num ***************/
/* FREE equot *************/
/* FREE one ***************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_floor() */
void ei_ceil( EMUSHORT *eic, EMUSHORT *eia, int nb )
/***************************************************************
Description : ei_ceil() Работает с
internal e-type data struct.
Concepts : Return EIC = neargest integer not smaller
than EIA (truncated toward plus infinity).
Возвращает EIC = наименьшее (ближайшее)
целое не меньшее чем EIA (срезает в
сторону плюс бесконечности).
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET CEIL;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct;
EIA, & EIC.
Return : [void]
***************************************************************/
{
EMUSHORT *exone = NULL,
*exp = NULL,
*inc = NULL,
*fi = NULL,
*num = NULL,
*equot = NULL,
*one = NULL;
EMUSHORT *p, *q;
EMUSHORT j;
__mpu_int32_t e;
int np, ne, ns, i;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
/* Если на входе знаковый ноль. */
if( ei_issignull( eia, nb ) )
{
ei_copy( eic, eia, nb );
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for exone, exp, inc . ******************/
exone = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
return;
}
exp = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
/* FREE exone *************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for fi, num, equot,one . ***************/
fi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !fi )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
num = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !num )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
equot = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !equot )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
/* FREE num ***************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
/* FREE num ***************/
/* FREE equot *************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( fi, eia, nb );
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye( exp, &fi[1], ne, ne );
#else
ei_cpye( exp, &fi[ns+2], ne, ne );
#endif
/* Create EXONE */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = exone;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* hight part */
p = exone + ne - 1;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
ei_dece( exone, exone, ne );
ei_sube( exp, exp, exone, ne );
if( ei_cmp0e( exp, nb ) <= 0 ) /* ( exp <= 0 ) */
{
ei_cleaz( eic, nb );
goto isitplus;
}
/* Формируем INC как количество бит мантиссы. */
for( i = 0; i < ne; i++ ) inc[i] = (EMUSHORT)0;
j = EINSBITS(nb);
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne-1] = j;
#else
inc[0] = j;
#endif
ei_sube( exp, inc, exp, ne );
ei_copy( eic, fi, nb );
if( ei_cmp0e( exp, ne ) <= 0 ) /* ( exp <= 0 ) */
{
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
/* FREE num ***************/
/* FREE equot *************/
/* FREE one ***************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &eic[ne+ns+2]; /* lgw */
*p-- = (EMUSHORT)0; /* p -> low part of Significand */
#else
p = &eic[0]; /* lgw */
*p++ = (EMUSHORT)0; /* p -> low part of Significand */
#endif
/* Следующее действие правомерно, т.к. количество бит мантиссы
укладывается в число типа signed EMUSHORT. */
ei_cpye_pack( (EMUSHORT *)(&e), exp, 1, ne );
while( e >= BITS_PER_EMUSHORT )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
*p-- = (EMUSHORT)0;
#else
*p++ = (EMUSHORT)0;
#endif
e -= BITS_PER_EMUSHORT;
}
/* Clear the remaining bits. */
*p &= bitmask[e];
/* Truncate positives toward plus infinity. */
isitplus:
if( !ei_isneg( fi, nb ) )
{
_gen_one( one, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
q = &eic[ne+ns+1]; /* low part of Signoficand */
p = &fi[ne+ns+1];
#else
q = &eic[1]; /* low part of Signoficand */
p = &fi[1];
#endif
for( i = 0; i < ns; i++ )
{
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
if( *p-- != *q-- )
#else
if( *p++ != *q++ )
#endif
{
ei_add( eic, eic, one, nb );
break;
}
} /* End for( all parts of Significand ) */
} /* End if( !isneg(fi) ) */
/* FREE exone *************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(3*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE fi ****************/
/* FREE num ***************/
/* FREE equot *************/
/* FREE one ***************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_ceil() */
void ei_round( EMUSHORT *eic, EMUSHORT *eia, int nb )
/***************************************************************
Description : ei_round() Работает с
internal e-type data struct.
Concepts : Return EIC = nearest integer to EIA,
as FLOOR( EIA + 0.5 ).
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET CEIL;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct;
EIA, & EIC.
Return : [void]
***************************************************************/
{
EMUSHORT *half = NULL;
int np;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
/*** Allocate memory for half . *****************************/
half = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !half )
{
/* fatal error */
return;
}
/************************************************************/
_gen_half( half, nb );
ei_add( eic, eia, half, nb );
ei_floor( eic, eic, nb );
/* FREE half **************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_round() */
void ei_frexp( EMUSHORT *eis, EMUSHORT *lpexp, EMUSHORT *eia, int nlp, int nb )
/***************************************************************
Description : ei_frexp() Работает с
internal e-type data struct.
Concepts : Return EIS and LPEXP such that
EIS * 2^LPEXP = EIA and 0.5 <= EIS < 1.0.
For example, 1.1 = 0.55 * 2^1.
=========================================
Функция разбивает число EIA на мантиссу
EIS и экспоненту LPEXP таким образом,
что абсолютное значение EIS больше или
равно 0.5 и меньше 1.0 и
EIA == EIS * 2^LPEXP.
Например, 1.1 = 0.55 * 2^1.
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *eis; - указатель на
internal e-type
data struct.
TARGET Significand;
EMUSHORT *lpexp; - указатель на
external long
INTEGER number.
TARGET EXP;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
SOURCE;
int nlp; - количество порций
размера EMUSHORT в
external long
INTEGER number;
LPEXP.
NOTE:
=========================================
NLP должно быть не меньше количества
порций размера EMUSHORT в
Exponent( EIA ), т.е.
nlp >= internal_ne(nb);
ВНИМАНИЕ:
При использовании данной функции
программист обязан самостоятельно
отслеживать размер памяти,
выделяемой под LPEXP.
=========================================
int nb; - количество бит в
external e-type
data struct;
EIA, & EIS.
Return : [void]
***************************************************************/
{
EMUSHORT *exp = NULL,
*inc = NULL,
*xi = NULL;
EMUSHORT *p;
__mpu_int32_t j;
int np, ne, ns, i;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
if( nlp < ne )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
/*** Allocate memory for exp, inc, xi . *********************/
exp = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)(ne*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exp ***************/
__mpu_sbrk( -(int)(ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
xi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !xi )
{
/* fatal error */
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( xi, eia, nb );
/*
Handle denormalized numbers properly using long integer exponent.
*/
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &xi[1], ne, ne );
#else
ei_cpye_unpack( exp, &xi[ns+2], ne, ne );
#endif
if( ei_cmp0e( exp, ne ) == 0 ) /* ( exp == 0 ) */
{
/* exp -= ei_normalize( xi ); */
j = ei_normalize( xi, nb );
ei_cpye_unpack( inc, (EMUSHORT *)&j, ne, 1 );
ei_sube( exp, exp, inc, ne );
}
/* Формирование HALF (экспоненты 0.5) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &inc[0]; /* hight part of Exponent */
*p++ = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *p++ = MASK_ALL_BITS;
--p;
*p ^= 1; /* Low part of Exponent */
#else
p = &inc[ne-1]; /* hight part of Exponent */
*p-- = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *p-- = MASK_ALL_BITS;
++p;
*p ^= 1; /* Low part of Exponent */
#endif
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( &xi[1], inc, ne, ne );
#else
ei_cpye_unpack( &xi[ns+2], inc, ne, ne );
#endif
ei_copy( eis, xi, nb );
ei_sube( exp, exp, inc, ne );
ei_cpye_unpack( lpexp, exp, nlp, ne );
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*ne*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE xi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_frexp() */
void ei_ldexp( EMUSHORT *eic, EMUSHORT *lppwr2, EMUSHORT *eia, int nlp, int nb )
/***************************************************************
Description : ei_ldexp() Работает с
internal e-type data struct.
Concepts : Return EIC = EIA * 2^PWR2.
=========================================
Функция вычисляет значение EIC как
EIA умноженное на 2 в степени LPPWR2.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *lppwr2; - указатель на
external long
INTEGER number.
SOURCE PWR2;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
SOURCE;
int nlp; - количество порций
размера EMUSHORT в
external long
INTEGER number;
LPPWR2.
NOTE:
=========================================
NLP должно быть не больше количества
порций размера EMUSHORT в
Exponent( EIA )+1, т.е.
nlp <= internal_ne(nb)+1;
ВНИМАНИЕ:
При использовании данной функции
программист обязан самостоятельно
отслеживать размер памяти,
выделяемой под LPPWR2.
=========================================
int nb; - количество бит в
external e-type
data struct;
EIA, & EIC.
Return : [void]
***************************************************************/
{
EMUSHORT *exp = NULL,
*inc = NULL,
*xi = NULL;
int np, ne, ns;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
if( nlp > ne+1 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
/*** Allocate memory for exp, inc, xi . *********************/
exp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE exp ***************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
xi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !xi )
{
/* fatal error */
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( xi, eia, nb );
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &xi[1], ne+1, ne );
#else
ei_cpye_unpack( exp, &xi[ns+2], ne+1, ne );
#endif
/* Copy PWR2 */
ei_cpye_unpack( inc, lppwr2, ne+1, nlp );
/* exp += pwr2 */
ei_adde( exp, exp, inc, ne+1 );
ei_mdenorm( xi, 0, 0, exp, 0, nb ); /* rcntrl = 0 (просто обнуляем lgw) */
ei_copy( eic, xi, nb );
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE xi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_ldexp() */
void ei_logb( EMUSHORT *lpbase2, EMUSHORT *eia, int nlp, int nb )
/***************************************************************
Description : ei_logb() Работает с
internal e-type data struct.
Concepts : Return LPbase2 = the base 2 signed
integral Exponent of
EIA.
=========================================
Функция вычисляет значение LPbase2 как
знаковую интегральную экспоненту по
основанию 2 вещественного числа EIA.
Use Global Variable:
Use Functions :
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *lpbase2; - указатель на
external long
INTEGER number.
TARGET;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
SOURCE;
int nlp; - количество порций
размера EMUSHORT в
external long
INTEGER number;
LPBASE2.
NOTE:
=========================================
NLP должно быть БОЛЬШЕ или равно
количеству порций размера EMUSHORT в
Exponent( EIA )+1, т.е.
nlp >= internal_ne(nb)+1;
ВНИМАНИЕ:
При использовании данной функции
программист обязан самостоятельно
отслеживать размер памяти,
выделяемой под LPBASE2.
=========================================
int nb; - количество бит в
external e-type
data struct;
EIA.
Return : [void]
***************************************************************/
{
EMUSHORT *exp = NULL,
*base2 = NULL,
*exone = NULL,
*pwr2 = NULL,
*inc = NULL,
*xi = NULL,
*zero = NULL,
*one = NULL,
*ti = NULL;
EMUSHORT *p;
EMUSHORT n_mant_bits = EINSBITS(nb);
int np, ne, ns, i;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
if( nlp < ne+1 )
{
/* fatal error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
/*** Allocate memory for xi . *******************************/
xi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !xi )
{
/* fatal error */
return;
}
/************************************************************/
ei_copy( xi, eia, nb );
/***************************
Test for EIA.
***************************/
/* EI_LOGB(InD) produsing Domain Flag */
if( ei_isind( eia, nb ) )
{
/* "argument domain error" */
/* return: ZERO */
for( i = 0; i < nlp; i++ ) lpbase2[i] = (EMUSHORT)0;
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* not change */
(__mpu_char8_t *)"logb", __DOMAIN__, (EMUSHORT *)0,
xi, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL InD - produsing Domain Flag */
/* FREE xi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EI_LOGB(NaN) produsing Domain Flag */
if( ei_isnans( eia, nb ) )
{
/* "argument domain error" */
/* return: ZERO */
for( i = 0; i < nlp; i++ ) lpbase2[i] = (EMUSHORT)0;
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* not change */
(__mpu_char8_t *)"logb", __DOMAIN__, (EMUSHORT *)0,
xi, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL NaN - produsing Domain Flag */
/* FREE xi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/* EI_LOGB(Infinity) produsing Domain Flag */
if( ei_isinfin( eia, nb ) )
{
/* "argument domain error" */
/* return: ZERO */
for( i = 0; i < nlp; i++ ) lpbase2[i] = (EMUSHORT)0;
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* not change */
(__mpu_char8_t *)"logb", __DOMAIN__, (EMUSHORT *)0,
xi, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL Infinity - produsing Domain Flag */
/* FREE xi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for zero . *****************************/
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE xi ****************/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_zero( zero, nb );
/* EI_LOGB(0.0) produsing Domain Flag */
if( ei_cmp( zero, eia, nb ) == 0 )
{
/* "argument domain error" */
/* return: ZERO */
for( i = 0; i < nlp; i++ ) lpbase2[i] = (EMUSHORT)0;
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( (EMUSHORT *)0, /* not change */
(__mpu_char8_t *)"logb", __DOMAIN__, (EMUSHORT *)0,
xi, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL (EIA == 0.0) - produsing Domain Flag */
/* FREE xi ****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for one . ******************************/
one = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !one )
{
/* fatal error */
/* FREE xi ****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
_gen_one( one, nb );
/*** Allocate memory for ti, exp, base2, exone, pwr2, inc . */
ti = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !ti )
{
/* fatal error */
/* FREE xi ****************/
/* FREE zero **************/
/* FREE one ***************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
exp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
/* FREE xi ****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE ti ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
base2 = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !base2 )
{
/* fatal error */
/* FREE xi ****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE ti ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
exone = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exone )
{
/* fatal error */
/* FREE xi ****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE ti ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
/* FREE base2 *************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
pwr2 = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !pwr2 )
{
/* fatal error */
/* FREE xi ****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE ti ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
/* FREE base2 *************/
/* FREE exone *************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE xi ****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE ti ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
/* FREE base2 *************/
/* FREE exone *************/
/* FREE pwr2 **************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* Generate the EXONE */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
/* hight part */
p = exone;
*p++ = (EMUSHORT)0;
*p++ = HIGHT_EXONE; /* 0x3fff... */
for( i = 0; i < ne - 1; i++ ) *p++ = MASK_ALL_BITS;
#else
/* hight part */
p = exone + ne;
*p-- = (EMUSHORT)0;
*p-- = HIGHT_EXONE;
for( i = 0; i < ne - 1; i++ ) *p-- = MASK_ALL_BITS;
#endif
/* Copy Exponent */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( exp, &xi[1], ne+1, ne );
#else
ei_cpye_unpack( exp, &xi[ns+2], ne+1, ne );
#endif
if( ei_cmp0e( exp, ne+1 ) == 0 )
{
/**********************************************
A denormalized number.
----------------------
Multiplyng by 2^N_MANT_BITS normalizes it;
we then subtract the N_MANT_BITS we added
to the Exponent.
**********************************************/
ei_cpye_unpack( pwr2, &n_mant_bits, ne+1, 1 );
ei_ldexp( ti, pwr2, one, ne+1, nb );
ei_mul( ti, xi, ti, nb );
ei_logb( pwr2, ti, ne+1, nb ); /* Recursion */
ei_cpye_unpack( inc, &n_mant_bits, ne+1, 1 );
ei_sube( base2, pwr2, inc, ne+1 );
ei_cvte_unpack( lpbase2, base2, nlp, ne+1 ); /* nlp >= ne+1 */
/* FREE xi ****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE ti ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
/* FREE base2 *************/
/* FREE exone *************/
/* FREE pwr2 **************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_sube( base2, exp, exone, ne+1 );
ei_cvte_unpack( lpbase2, base2, nlp, ne+1 ); /* nlp >= ne+1 */
/* FREE xi ****************/
/* FREE zero **************/
/* FREE one ***************/
/* FREE ti ****************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
/* FREE base2 *************/
/* FREE exone *************/
/* FREE pwr2 **************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_logb() */
void ei_sqrt( EMUSHORT *eic, EMUSHORT *eia, int nb )
/***************************************************************
Description : ei_sqrt() Работает с
internal e-type data struct.
Concepts : Longhand SQUARE ROOT routine.
=========================================
Вычисление обыкновенного КВАДРАТНОГО
КОРНЯ. (Если аргумент отрицательный,
то результат равен нулю).
Use Global Variable:
Use Functions :
internal_np( nb ); | this file
internal_ne( nb ); | this file
internal_ns( nb ); | this file
Parameters :
EMUSHORT *eic; - указатель на
internal e-type
data struct.
TARGET;
EMUSHORT *eia; - указатель на
internal e-type
data struct.
SOURCE;
int nb; - количество бит в
external e-type
data struct;
EIA, & EIC.
Return : [void]
***************************************************************/
{
EMUSHORT *exp = NULL,
*inc = NULL,
*mt = NULL,
*m = NULL,
*sqrndbit = NULL,
*temp = NULL,
*num = NULL,
*sq = NULL,
*xi = NULL,
*xa = NULL, /* temp EIA for _mtherr() */
*zero = NULL;
EMUSHORT *p;
__mpu_int32_t j;
int np, ne, ns, i, w;
int k, l, n, nlups;
if( nb < NBR_32 )
{
/* error: Invalid size of operand(s) */
__real_error_no = __R_ESIZE__;
__STIND; /* Set REAL ind-produsing operation Flag */
return;
}
np = internal_np( nb );
ne = internal_ne( nb );
ns = internal_ns( nb );
/*** Allocate memory for sqrndbit . *************************/
sqrndbit = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !sqrndbit )
{
/* fatal error */
return;
}
/************************************************************/
ei_cleaz( sqrndbit, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
sqrndbit[ne+ns+1] = (EMUSHORT)1; /* low part of Significand */
#else
sqrndbit[1] = (EMUSHORT)1; /* low part of Significand */
#endif
/*** Allocate memory for xa . *******************************/
xa = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !xa )
{
/* fatal error */
/* FREE sqrndbit **********/
__mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
ei_copy( xa, eia, nb );
/*** Allocate memory for zero . *****************************/
zero = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !zero )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
__mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* Check for EIA <= 0 */
_gen_zero( zero, nb );
l = ei_cmp( eia, zero, nb );
if( l <= 0 )
{
if( l == -2 )
{
ei_nan( eic, ei_isneg( eia, nb ), nb );
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
ei_cleaz( eic, nb );
if( l < 0 )
{
/* "argument domain error" */
/***************************************************
NOTE:
Функция _mtherr() является переходником между
внутренним форматом и внешней,
переопределяемой пользователем, функцией
__mpu_math_error(). Кроме основных действий
она выставляет системную переменную errno
следующим образом.
errno = __mpu_math_errnotab[type];
***************************************************/
_mtherr( eic, (__mpu_char8_t *)"sqrt", __DOMAIN__,
eic, xa, (EMUSHORT *)0, nb );
__STDOM; /* Set REAL Domain Flag */
}
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
} /* End if( l <= 0 ) */
/* Check Infinity */
if( ei_isinfin( eia, nb ) )
{
ei_infin( eic, ei_isneg( eia, nb ), nb );
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/*** Allocate memory for temp, num, sq, xi . ****************/
temp = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !temp )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
__mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
num = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !num )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
/* FREE temp **************/
__mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
sq = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !sq )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
/* FREE temp **************/
/* FREE num ***************/
__mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
xi = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) );
if( !xi )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
/* FREE temp **************/
/* FREE num ***************/
/* FREE sq ****************/
__mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/*** Allocate memory for exp . ******************************/
exp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !exp )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
/* FREE temp **************/
/* FREE num ***************/
/* FREE sq ****************/
/* FREE xi ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !inc )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
/* FREE temp **************/
/* FREE num ***************/
/* FREE sq ****************/
/* FREE xi ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
__mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
mt = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !mt )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
/* FREE temp **************/
/* FREE num ***************/
/* FREE sq ****************/
/* FREE xi ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
/* FREE inc ***************/
__mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
m = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) );
if( !m )
{
/* fatal error */
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
/* FREE temp **************/
/* FREE num ***************/
/* FREE sq ****************/
/* FREE xi ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
/* FREE inc ***************/
/* FREE mt ****************/
__mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
return;
}
/************************************************************/
/* Bring in the arg and renormalize if it is denormal. */
ei_copy( xi, eia, nb );
/* Copy Exponents */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
ei_cpye_unpack( m, &xi[1], ne+1, ne );
#else
ei_cpye_unpack( m, &xi[ns+2], ne+1, ne );
#endif
if( ei_cmp0e( m, ne+1 ) == 0 )
{
/* m -= ei_normalize( xi ) */
j = ei_normalize( xi, nb );
ei_cvte_unpack( inc, (EMUSHORT *)&j, ne+1, 1 );
ei_sube( m, m, inc, ne+1 );
}
/* bzero inc !!! */
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
/**************************************
Divide Exponent by 2.
**************************************/
/* Формирование HALF (экспоненты 0.5) */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &inc[0]; /* hight part of Exponent */
*p++ = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *p++ = MASK_ALL_BITS;
--p;
*p ^= 1; /* Low part of Exponent */
#else
p = &inc[ne-1]; /* hight part of Exponent */
*p-- = HIGHT_EXONE;
for( i = 1; i < ne; i++ ) *p-- = MASK_ALL_BITS;
++p;
*p ^= 1; /* Low part of Exponent */
#endif
/* m -= 0x3f...fe; */
ei_sube( m, m, inc, ne+1 );
/* exp = (m / 2) + 0x3f...fe; */
if( ei_cmp0e( m, ne+1 ) < 0 )
{
/* НЕЛЬЗЯ ПРОСТО СДВИНУТЬ ОТРИЦАТЕЛЬНОЕ ЧИСЛО. */
ei_nege( mt, m, ne+1 );
ei_shrn( mt, mt, (unsigned)1, ne+1 );
ei_nege( exp, mt, ne+1 );
}
else
ei_shrn( exp, m, (unsigned)1, ne+1 );
ei_adde( exp, exp, inc, ne+1 );
/*** End Divide Exponent by 2 *********/
/* Adjust if Exponent odd. */
for( i = 0; i < ne+1; i++ ) inc[i] = (EMUSHORT)0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
inc[ne] = (EMUSHORT)1; /* low part of Exponent */
#else
inc[0] = (EMUSHORT)1; /* low part of Exponent */
#endif
/* mt = m & 1 */
for( i = 0; i < ne+1; i++ ) mt[i] = m[i] & inc[i];
if( ei_cmp0e( mt, ne+1 ) != 0 )
{
if( ei_cmp0e( m, ne+1 ) > 0 )
ei_adde( exp, exp, inc, ne+1 ); /* exp += 1 */
ei_shdown( xi, (unsigned)1, nb );
}
ei_cleaz( sq, nb );
ei_cleaz( num, nb );
n = ((BITS_PER_EMUSHORT)/2);
nlups = EINSBITS(nb); /* Количество бит мантиссы. */
w = 0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &xi[ne+2]; /* hight part of Significand */
#else
p = &xi[ns]; /* hight part of Significand */
#endif
while( nlups > 0 )
{
/* Bring in next word of arg. */
if( w < ns+1 ) /* Significand + lgw */
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
num[ne+ns+2] = /* lgw */
#else
num[0] = /* lgw */
#endif
*p;
/* Do additional bit on last outer loop, for roundoff. */
if( nlups <= ((BITS_PER_EMUSHORT)/2) ) n = nlups + 1;
for( k = 0; k < n; k++ )
{
/* Next 2 bits of arg */
ei_shup( num, (unsigned)2, nb );
/* Shift up answer */
ei_shup( sq, (unsigned)1, nb );
/* Make trial divisor */
for( i = 0; i < np; i++ ) temp[i] = sq[i];
ei_shup( temp, (unsigned)1, nb );
ei_addm( temp, temp, sqrndbit, nb );
/* Substract and insert answer bit if it goes in */
if( ei_cmpm( temp, num, nb ) <= 0 )
{
ei_subm( num, num, temp, nb );
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
sq[ne+ns+1] |= 1; /* low part of Significand */
#else
sq[1] |= 1; /* low part of Significand */
#endif
} /* End if( ei_cmpm( temp, num ) <= 0 ) */
} /* End for( k = 0; i < n; k++ ) */
nlups -= n;
w += 1;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
++p; /* toward lgw */
#else
--p; /* toward lgw */
#endif
} /* End while( nlups > 0 ) */
/* Adjust for extra, roundoff loop done. */
/* exp += (EINSBITS(nb) - 1) - rndprc; */
/* т.к. в нашем случае (EINSBITS(nb) == rndprc)
делаем exp += -1; т.е. округляем до количества
бит в мантиссе во внутреннем формате. */
ei_dece( exp, exp, ne+1 );
/* Sticky bit = 1 if the remainder is nonzero. */
k = 0;
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p = &num[ne+2]; /* hight part of Significand */
#else
p = &num[ns]; /* hight part of Significand */
#endif
for( i = 0; i < ns+1; i++ ) /* Significand + lgw */
{
/* NOTE: x86_64: sizeof( long ) == 8!
*/
k |= (int)(__mpu_uint64_t)
#if MPU_WORD_ORDER_BIG_ENDIAN == 1
p++; /* toward lgw */
#else
p--; /* toward lgw */
#endif
}
/* Renormalize and round off. */
ei_mdenorm( sq, k, 0, exp, 0, nb );
ei_copy( eic, sq, nb );
/* FREE sqrndbit **********/
/* FREE xa ****************/
/* FREE zero **************/
/* FREE temp **************/
/* FREE num ***************/
/* FREE sq ****************/
/* FREE xi ****************/
__mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) );
/**************************/
/* FREE exp ***************/
/* FREE inc ***************/
/* FREE mt ****************/
/* FREE m *****************/
__mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) );
/**************************/
} /* End of ei_sqrt() */
/***************************************************************
Hide internal symbols:
***************************************************************/
__mpu_hidden_decl(internal_ne);
__mpu_hidden_decl(internal_ns);
__mpu_hidden_decl(internal_np);
__mpu_hidden_decl(ei_cleaz);
__mpu_hidden_decl(ei_cleazs);
__mpu_hidden_decl(ei_ind);
__mpu_hidden_decl(ei_isind);
__mpu_hidden_decl(e_ind);
__mpu_hidden_decl(e_isind);
__mpu_hidden_decl(ei_nan);
__mpu_hidden_decl(ei_isnans);
__mpu_hidden_decl(e_nan);
__mpu_hidden_decl(e_isnans);
__mpu_hidden_decl(ei_nanmax);
__mpu_hidden_decl(ei_isnanmax);
__mpu_hidden_decl(e_nanmax);
__mpu_hidden_decl(e_isnanmax);
__mpu_hidden_decl(ei_nanmin);
__mpu_hidden_decl(ei_isnanmin);
__mpu_hidden_decl(e_nanmin);
__mpu_hidden_decl(e_isnanmin);
__mpu_hidden_decl(ei_infin);
__mpu_hidden_decl(ei_isinfin);
__mpu_hidden_decl(e_infin);
__mpu_hidden_decl(e_isinfin);
__mpu_hidden_decl(e_realmin);
__mpu_hidden_decl(e_realmax);
__mpu_hidden_decl(ei_signull);
__mpu_hidden_decl(ei_issignull);
__mpu_hidden_decl(e_signull);
__mpu_hidden_decl(e_issignull);
__mpu_hidden_decl(ei_neg);
__mpu_hidden_decl(ei_isneg);
__mpu_hidden_decl(e_neg);
__mpu_hidden_decl(e_isneg);
__mpu_hidden_decl(ei_abs);
__mpu_hidden_decl(e_abs);
/********************************************
Functions for LONG INTEGER NUMBERS:
*/
__mpu_hidden_decl(ei_cmpe);
__mpu_hidden_decl(ei_cmp0e);
__mpu_hidden_decl(ei_cpye_pack);
__mpu_hidden_decl(ei_cpye_unpack);
__mpu_hidden_decl(ei_cpye);
__mpu_hidden_decl(ei_cvte_unpack);
__mpu_hidden_decl(ei_cvte_pack);
__mpu_hidden_decl(ei_cvte);
__mpu_hidden_decl(ei_adde);
__mpu_hidden_decl(ei_ince);
__mpu_hidden_decl(ei_sube);
__mpu_hidden_decl(ei_dece);
__mpu_hidden_decl(ei_nege);
__mpu_hidden_decl(ei_ande);
__mpu_hidden_decl(ei_shrn);
__mpu_hidden_decl(ei_shln);
/*
End of Functions for LONG INTEGER NUMBERS.
********************************************/
__mpu_hidden_decl(ei_shdown);
__mpu_hidden_decl(ei_shup);
__mpu_hidden_decl(ei_shift);
__mpu_hidden_decl(ei_normalize);
__mpu_hidden_decl(unpack);
__mpu_hidden_decl(ei_cmpm);
__mpu_hidden_decl(ei_addm);
__mpu_hidden_decl(ei_subm);
__mpu_hidden_decl(ei_divm);
__mpu_hidden_decl(ei_mulm);
__mpu_hidden_decl(ei_mdenorm);
__mpu_hidden_decl(pack);
__mpu_hidden_decl(ei_copy);
__mpu_hidden_decl(ei_copyzlgw);
__mpu_hidden_decl(ei_cmp);
__mpu_hidden_decl(ei_convert);
__mpu_hidden_decl(ei_add);
__mpu_hidden_decl(ei_sub);
__mpu_hidden_decl(ei_div);
__mpu_hidden_decl(ei_mul);
__mpu_hidden_decl(ei_ltor);
__mpu_hidden_decl(ei_ultor);
__mpu_hidden_decl(ei_rtoul_frac);
__mpu_hidden_decl(ei_rtol_frac);
/***************************************************************
GENERATORS OF CONSTANT:
*/
__mpu_hidden_decl(_gen_zero);
__mpu_hidden_decl(_gen_half);
__mpu_hidden_decl(_gen_one);
__mpu_hidden_decl(_gen_two);
__mpu_hidden_decl(_gen_ten);
__mpu_hidden_decl(_gen_mten);
__mpu_hidden_decl(_gen_32);
/*
END GENERATORS OF CONSTANT.
***************************************************************/
__mpu_hidden_decl(ei_remain);
__mpu_hidden_decl(ei_floor);
__mpu_hidden_decl(ei_ceil);
__mpu_hidden_decl(ei_round);
__mpu_hidden_decl(ei_frexp);
__mpu_hidden_decl(ei_ldexp);
__mpu_hidden_decl(ei_logb);
__mpu_hidden_decl(ei_sqrt);
/*
End of hide internal symbols.
***************************************************************/