author: kx <kx@radix-linux.su> 2024-12-20 16:11:07 +0300
committer: kx <kx@radix-linux.su> 2024-12-20 16:11:07 +0300
commit: 868b2b66b564b5c00e3a74d10be45db7151627ac
parent: cce2ae8d3312493b7653358bb4af201d3271377b
Commit Summary:
Diffstat:
1 file changed, 12871 insertions, 0 deletions
diff --git a/mpu/mpu-real.c b/mpu/mpu-real.c
new file mode 100644
index 0000000..c52a339
--- /dev/null
+++ b/mpu/mpu-real.c
@@ -0,0 +1,15694 @@
+
+/***************************************************************
+ __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.
+ ***************************************************************/