/*************************************************************** __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 #endif #include /* errno(3) */ #include /* strcpy(3) */ #include /* bzero(3) */ #include #include #include #include #include #include #include #include #include #include #include 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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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 #else #include #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' 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' 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. ***************************************************************/