/*************************************************************** __MPU_IOREAL.C This file contains source code of functions for REAL input/output 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 #include #define NTEN_128 28 #define NTEN_256 28 #define NTEN_512 60 #define NTEN_1024 60 #define NTEN_2048 124 #define NTEN_4096 124 #define NTEN_8192 252 #define NTEN_16384 252 #define NTEN_32768 508 #define NTEN_65536 508 #define NTEN_131072 1020 static int _get_nten( int nb ) { int rc = 0; if( nb < NBR_32 || nb > MPU_REAL_IO_LIMIT ) { /* error: Invalid size of operand(s) */ __real_error_no = __R_ESIZE__; __STIND; /* Set REAL ind-produsing operation Flag */ return( rc ); } switch( nb ) { case NBR_32 : case NBR_64 : case NBR_128 : rc = NTEN_128; break; case NBR_256 : rc = NTEN_256; break; case NBR_512 : rc = NTEN_512; break; case NBR_1024 : rc = NTEN_1024; break; case NBR_2048 : rc = NTEN_2048; break; case NBR_4096 : rc = NTEN_4096; break; case NBR_8192 : rc = NTEN_8192; break; case NBR_16384: rc = NTEN_16384; break; case NBR_32768: rc = NTEN_32768; break; case NBR_65536: rc = NTEN_65536; 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 _get_nten() */ /*************************************************************** Кодировка имен файлов: Трехзначное десятичное число, представляющее количество 128-и битных слов, из которых состоят вещественные числа размещенные в массивах: размер чисел в битах кодировка -------------------- --------- 128 001 256 002 512 004 1024 008 2048 016 4096 032 8192 064 16384 128 32768 256 65536 512 (это предел); ПРИМЕРЫ: ------- ei_mtens_001_emu32lsb.dfn - 128-бит, ei_mtens_512_emu32lsb.dfn - 65536-бит. ***************************************************************/ #if MPU_REAL_IO_LIMIT >= 128 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 128 */ #if MPU_REAL_IO_LIMIT >= 256 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 256 */ #if MPU_REAL_IO_LIMIT >= 512 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 512 */ #if MPU_REAL_IO_LIMIT >= 1024 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 1024 */ #if MPU_REAL_IO_LIMIT >= 2048 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 2048 */ #if MPU_REAL_IO_LIMIT >= 4096 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 4096 */ #if MPU_REAL_IO_LIMIT >= 8192 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 8192 */ #if MPU_REAL_IO_LIMIT >= 16384 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 16384 */ #if MPU_REAL_IO_LIMIT >= 32768 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 32768 */ #if MPU_REAL_IO_LIMIT >= 65536 #if MPU_WORD_ORDER_BIG_ENDIAN == 0 #include #include #else #include #include #endif #endif /* MPU_REAL_IO_LIMIT >= 65536 */ static EMUSHORT *_get_tens_ptr( int nb ) { EMUSHORT *rc = (EMUSHORT *)NULL; if( nb < NBR_32 || nb > MPU_REAL_IO_LIMIT ) { /* error: Invalid size of operand(s) */ __real_error_no = __R_ESIZE__; __STIND; /* Set REAL ind-produsing operation Flag */ return( rc ); } switch( nb ) { #if MPU_REAL_IO_LIMIT >= 128 case NBR_32 : case NBR_64 : case NBR_128 : rc = (EMUSHORT *)&_ei_tens_128_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 128 */ #if MPU_REAL_IO_LIMIT >= 256 case NBR_256 : rc = (EMUSHORT *)&_ei_tens_256_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 256 */ #if MPU_REAL_IO_LIMIT >= 512 case NBR_512 : rc = (EMUSHORT *)&_ei_tens_512_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 512 */ #if MPU_REAL_IO_LIMIT >= 1024 case NBR_1024 : rc = (EMUSHORT *)&_ei_tens_1024_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 1024 */ #if MPU_REAL_IO_LIMIT >= 2048 case NBR_2048 : rc = (EMUSHORT *)&_ei_tens_2048_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 2048 */ #if MPU_REAL_IO_LIMIT >= 4096 case NBR_4096 : rc = (EMUSHORT *)&_ei_tens_4096_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 4096 */ #if MPU_REAL_IO_LIMIT >= 8192 case NBR_8192 : rc = (EMUSHORT *)&_ei_tens_8192_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 8192 */ #if MPU_REAL_IO_LIMIT >= 16384 case NBR_16384: rc = (EMUSHORT *)&_ei_tens_16384_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 16384 */ #if MPU_REAL_IO_LIMIT >= 32768 case NBR_32768: rc = (EMUSHORT *)&_ei_tens_32768_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 32768 */ #if MPU_REAL_IO_LIMIT >= 65536 case NBR_65536: rc = (EMUSHORT *)&_ei_tens_65536_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 65536 */ 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 _get_tens_ptr() */ static EMUSHORT *_get_mtens_ptr( int nb ) { EMUSHORT *rc = (EMUSHORT *)NULL; if( nb < NBR_32 || nb > MPU_REAL_IO_LIMIT ) { /* error: Invalid size of operand(s) */ __real_error_no = __R_ESIZE__; __STIND; /* Set REAL ind-produsing operation Flag */ return( rc ); } switch( nb ) { #if MPU_REAL_IO_LIMIT >= 128 case NBR_32 : case NBR_64 : case NBR_128 : rc = (EMUSHORT *)&_ei_mtens_128_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 128 */ #if MPU_REAL_IO_LIMIT >= 256 case NBR_256 : rc = (EMUSHORT *)&_ei_mtens_256_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 256 */ #if MPU_REAL_IO_LIMIT >= 512 case NBR_512 : rc = (EMUSHORT *)&_ei_mtens_512_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 512 */ #if MPU_REAL_IO_LIMIT >= 1024 case NBR_1024 : rc = (EMUSHORT *)&_ei_mtens_1024_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 1024 */ #if MPU_REAL_IO_LIMIT >= 2048 case NBR_2048 : rc = (EMUSHORT *)&_ei_mtens_2048_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 2048 */ #if MPU_REAL_IO_LIMIT >= 4096 case NBR_4096 : rc = (EMUSHORT *)&_ei_mtens_4096_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 4096 */ #if MPU_REAL_IO_LIMIT >= 8192 case NBR_8192 : rc = (EMUSHORT *)&_ei_mtens_8192_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 8192 */ #if MPU_REAL_IO_LIMIT >= 16384 case NBR_16384: rc = (EMUSHORT *)&_ei_mtens_16384_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 16384 */ #if MPU_REAL_IO_LIMIT >= 32768 case NBR_32768: rc = (EMUSHORT *)&_ei_mtens_32768_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 32768 */ #if MPU_REAL_IO_LIMIT >= 65536 case NBR_65536: rc = (EMUSHORT *)&_ei_mtens_65536_[0][0]; break; #endif /* MPU_REAL_IO_LIMIT >= 65536 */ 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 _get_mtens_ptr() */ /*************************************************************** SEE: __MPU_FLOATP.H for definitions REAL_xxxxxx__MAX_STRING ***************************************************************/ #define MAX_STRING_SIZE(n) REAL_##n##_MAX_STRING #if MPU_REAL_IO_LIMIT == 32 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(32) #else #if MPU_REAL_IO_LIMIT == 64 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(64) #else #if MPU_REAL_IO_LIMIT == 128 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(128) #else #if MPU_REAL_IO_LIMIT == 256 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(256) #else #if MPU_REAL_IO_LIMIT == 512 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(512) #else #if MPU_REAL_IO_LIMIT == 1024 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(1024) #else #if MPU_REAL_IO_LIMIT == 2048 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(2048) #else #if MPU_REAL_IO_LIMIT == 4096 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(4096) #else #if MPU_REAL_IO_LIMIT == 8192 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(8192) #else #if MPU_REAL_IO_LIMIT == 16384 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(16384) #else #if MPU_REAL_IO_LIMIT == 32768 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(32768) #else #if MPU_REAL_IO_LIMIT == 65536 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(65536) #else #if MPU_REAL_IO_LIMIT == 131072 #define REAL_MAX_STRING_SIZE MAX_STRING_SIZE(131072) #else #error mpu-ioreal.c: Failed value of MPU_REAL_IO_LIMIT (use: 32,64, ..., 131072) #endif /* MPU_REAL_IO_LIMIT == 131072 */ #endif /* MPU_REAL_IO_LIMIT == 65536 */ #endif /* MPU_REAL_IO_LIMIT == 32768 */ #endif /* MPU_REAL_IO_LIMIT == 16384 */ #endif /* MPU_REAL_IO_LIMIT == 8192 */ #endif /* MPU_REAL_IO_LIMIT == 4096 */ #endif /* MPU_REAL_IO_LIMIT == 2048 */ #endif /* MPU_REAL_IO_LIMIT == 1024 */ #endif /* MPU_REAL_IO_LIMIT == 512 */ #endif /* MPU_REAL_IO_LIMIT == 256 */ #endif /* MPU_REAL_IO_LIMIT == 128 */ #endif /* MPU_REAL_IO_LIMIT == 64 */ #endif /* MPU_REAL_IO_LIMIT == 32 */ void ei_real_to_ascii( __mpu_char8_t *string, EMUSHORT *ei, int ndigs, int exp_delim, int exp_digs, int gen_plus, int nb ) /*************************************************************** Description : ei_real_to_ascii() Работает с internal e-type data struct. Concepts : Convert internal e-type EI to ASCII STRING with NDIGS digits after the decimal point. EXP_DELIM is char to delimited Exponent in the output STRING, for example, 1.j+27. Use Global Variable: Use Functions : iitoa_np(); | mpu-integer.c internal_np( nb ); | mpu-real.c internal_ne( nb ); | mpu-real.c internal_ns( nb ); | mpu-real.c Parameters : __mpu_char8_t *string; - output string; EMUSHORT *ei; - указатель на internal e-type data struct; int ndigs; - количество цифр после десятичной точки; int exp_delim; - символ отделяющий ЭКСРОНЕНТУ; int exp_digs; - количество цифр экспоненты; NOTE ==================================== В том случае, когда( exp_digs > 0 ) { Если реальное количество цифр меньше exp_digs, то экспонента будет дополнена старшими незначащими нулями. Если реальное количество цифр больше exp_digs, то экспонента изменена не будет. } ========================================= int gen_plus; - принудительная генерация знака плюс перед положтельным числом; NOTE ==================================== В случае, когда( gen_plus != 0 ) { При переводе положительного числа в строку происходит принудительная запись знака плюс перед числом в строке. } иначе { Положительное число печатается как обычно (т.е. без знака). } ========================================= int nb; - количество бит в external e-type data struct. Return : [void] ***************************************************************/ { EMUSHORT *n = NULL, *m = NULL, *expon = NULL, *exone = NULL, *inc = NULL, *equot = NULL, *tmp = NULL, *ten = NULL, *y = NULL, *t = NULL, *u = NULL, *w = NULL; EMUSHORT *p, *r; EMUSHORT sign; __mpu_int32_t j, digit; int rndsave, n_ten; int jc, k; __mpu_char8_t *s, *ss, *t_string = NULL; int np, ne, ns, i, ln, n_dec; errno = 0; if( nb < NBR_32 || nb > MPU_REAL_IO_LIMIT ) { /* error: Invalid size of operand(s) */ __real_error_no = __R_ESIZE__; __STIND; /* Set REAL ind-produsing operation Flag */ return; } t_string = (__mpu_char8_t *)malloc(REAL_MAX_STRING_SIZE+1); if( !t_string ) { /* fatal error */ return; } rndsave = rndprc; ss = string; s = t_string; *ss = '\0'; ln = _get_max_string( nb ); for( i = 0; i < ln; i++ ) s[i] = '\0'; /* or bzero( s, ln ); */ np = internal_np( nb ); ne = internal_ne( nb ); ns = internal_ns( nb ); /*** Allocate memory for n, m, expon, exone, inc . **********/ n = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !n ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ return; } m = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !m ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ __mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return; } expon = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !expon ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ __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 t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ __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 t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ __mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return; } /************************************************************/ /*** Allocate memory for equot, tmp, ten, y, t, u, w . ******/ equot = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !equot ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return; } tmp = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !tmp ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE equot *************/ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) ); /**************************/ return; } ten = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !ten ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE equot *************/ /* FREE tmp ***************/ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) ); /**************************/ return; } y = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !y ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE equot *************/ /* FREE tmp ***************/ /* FREE ten ***************/ __mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) ); /**************************/ return; } t = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !t ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE equot *************/ /* FREE tmp ***************/ /* FREE ten ***************/ /* FREE y *****************/ __mpu_sbrk( -(int)(4*np*SIZE_OF_EMUSHORT) ); /**************************/ return; } u = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !u ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE equot *************/ /* FREE tmp ***************/ /* FREE ten ***************/ /* FREE y *****************/ /* FREE t *****************/ __mpu_sbrk( -(int)(5*np*SIZE_OF_EMUSHORT) ); /**************************/ return; } w = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !w ) { /* fatal error */ /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE equot *************/ /* FREE tmp ***************/ /* FREE ten ***************/ /* FREE y *****************/ /* FREE t *****************/ /* FREE u *****************/ __mpu_sbrk( -(int)(6*np*SIZE_OF_EMUSHORT) ); /**************************/ return; } /************************************************************/ n_dec = _get_ndec( nb ); n_ten = _get_nten( nb ); if( nb > NBR_64 ) n_dec -= 1; /* Необходимо для правильного округления мантиссы */ if( ei_isind( ei, nb ) ) { strncpy( t_string, " -ind", 6 ); /* " -1.#IND00"; */ if( exp_delim == 'r' || exp_delim == 'R' ) { strcat( t_string, "_r" ); } else if( exp_delim == 'j' || exp_delim == 'J' ) { strcat( t_string, "_j" ); } goto bxit; } if( ei_isnans( ei, nb ) ) { if( ei_isneg( ei, nb ) ) strncpy( t_string, " -", 3 ); else if( gen_plus ) strncpy( t_string, " +", 3 ); else strncpy( t_string, " ", 2 ); /* + */ strcat( t_string, "NaN" ); /* "1.#QNAN0"; */ if( exp_delim == 'r' || exp_delim == 'R' ) { strcat( t_string, "_r" ); } else if( exp_delim == 'j' || exp_delim == 'J' ) { strcat( t_string, "_j" ); } goto bxit; } rndprc = (int)NSBITS(nb); /* Set to full precision */ ei_copy( y, ei, nb ); /* Save Sign */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 if( y[0] ) #else if( y[ns + ne + 2] ) #endif { sign = MASK_ALL_BITS; #if MPU_WORD_ORDER_BIG_ENDIAN == 1 y[0] = (EMUSHORT)0; /* Clear sign */ #else y[ns + ne + 2] = (EMUSHORT)0; /* Clear sign */ #endif } else { sign = (EMUSHORT)0; } /* expon = 0 */ for( i = 0; i < ne+1; i++ ) expon[i] = (EMUSHORT)0; /* ten = 1.0E1 */ _gen_ten( ten, nb ); /* t = 1.0E0 */ _gen_one( t, nb ); /* Gen 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 /************************** Test for zero Exponent **************************/ /* Copy Exponents */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_unpack( inc, &y[1], ne+1, ne ); #else ei_cpye_unpack( inc, &y[ns+2], ne+1, ne ); #endif if( ei_cmp0e( inc, ne+1 ) == 0 ) /* Exponent == 0 */ { #if MPU_WORD_ORDER_BIG_ENDIAN == 1 for( i = ne+2; i < np-1; i++ ) #else for( i = 1; i < ns+1; i++ ) #endif { if( y[i] != (EMUSHORT)0 ) goto tnzero; /* Denormalized number */ } goto isone; /* Valid all zeros */ } /* End if( Exponent == 0 ) */ tnzero: /********************* Test for infinity *********************/ if( ei_isinfin( y, nb ) ) { if( sign ) strncpy( t_string, " -inf", 6 ); /* " -1.#INF00"; */ else if( gen_plus ) strncpy( t_string, " +inf", 6 ); /* " +1.#INF00"; */ else strncpy( t_string, " inf", 5 ); /* " 1.#INF00"; */ if( exp_delim == 'r' || exp_delim == 'R' ) { strcat( t_string, "_r" ); } else if( exp_delim == 'j' || exp_delim == 'J' ) { strcat( t_string, "_j" ); } goto bxit; } /* End of Infin */ /********************************************************** Test for Exponent nonzero but Significand denormalized. This is an ERROR condition. **********************************************************/ if( (ei_cmp0e( inc, ne+1 ) != 0) && #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ((y[ne+2] & MASK_SIGN) == 0) ) #else ((y[ns] & MASK_SIGN) == 0) ) #endif { /* "domain error" */ errno = __mpu_math_errnotab[__DOMAIN__]; __STDOM; /* Set REAL Domain Flag */ strncpy( t_string, "NaN", 4 ); /* "1.#QNAN0"; */ if( exp_delim == 'r' || exp_delim == 'R' ) { strcat( t_string, "_r" ); } else if( exp_delim == 'j' || exp_delim == 'J' ) { strcat( t_string, "_j" ); } goto bxit; } /****************** Compare to 1.0 ******************/ jc = ei_cmp( t, y, nb ); if( jc == 0 ) goto isone; if( jc == -2 ) { /* abort() */ strncpy( string, " -ind", 6 ); /* " -1.#IND00"; */ if( exp_delim == 'r' || exp_delim == 'R' ) { strcat( t_string, "_r" ); } else if( exp_delim == 'j' || exp_delim == 'J' ) { strcat( t_string, "_j" ); } /* abort() */ } if( jc < 0 ) /* Number is greater than 1 (y > 1.0) */ { ei_copy( u, y, nb ); /* u[Exponent] = EXONE + NSBITS - 1 */ j = (EMUSHORT)NSBITS(nb); j -= 1; ei_cvte_unpack( inc, (EMUSHORT *)&j, ne+1, 1 ); ei_adde( inc, exone, inc, ne+1 ); /* Copy Exponents */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_pack( &u[1], inc, ne, ne+1 ); #else ei_cpye_pack( &u[ns+2], inc, ne, ne+1 ); #endif p = _get_tens_ptr( nb ); /* if( BITS_PER_EMUSHORT == 16 ) { *p = 10**16; } */ /* if( BITS_PER_EMUSHORT == 32 ) { *p = 10**32; } */ /* if( BITS_PER_EMUSHORT == 64 ) { *p = 10**64; } */ p += np*(n_ten-POW2); /* -POW2 see: mpu-emutype.h */ j = BITS_PER_EMUSHORT; ei_cvte_unpack( m, (EMUSHORT *)&j, ne+1, 1 ); /* m = BITS_PER_EMUSHORT; */ do { ei_div( t, u, p, nb ); ei_floor( w, t, nb ); #if MPU_WORD_ORDER_BIG_ENDIAN == 1 for( i = ne+2; i < np-1; i++ ) #else for( i = 1; i < ns+1; i++ ) #endif { if( t[i] != w[i] ) goto noint; } ei_copy( u, t, nb ); ei_adde( expon, expon, m, ne+1 ); noint: p += np; ei_shrn( m, m, (unsigned)1, ne+1 ); /* m >>= 1 */ } while( ei_cmp0e( m, ne+1 ) != 0 ); /* Rescale from integer Significand */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_unpack( m, &y[1], ne+1, ne ); #else ei_cpye_unpack( m, &y[ns+2], ne+1, ne ); #endif #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_unpack( n, &u[1], ne+1, ne ); #else ei_cpye_unpack( n, &u[ns+2], ne+1, ne ); #endif /* inc еще равно EXONE + NSBITS - 1 */ ei_sube( m, m, inc, ne+1 ); ei_adde( n, n, m, ne+1 ); #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_pack( &u[1], n, ne, ne+1 ); #else ei_cpye_pack( &u[ns+2], n, ne, ne+1 ); #endif /* т.е. u[exp] += y[exp] -(unsigned)(EXONE + NBITS - 1) */ ei_copy( y, u, nb ); /* Find power of 10 */ /* t = 1.0E0 */ _gen_one( t, nb ); /* m = MAXP */ for( i = 0; i < ne+1; i++ ) m[i] = (EMUSHORT)0; #if MPU_WORD_ORDER_BIG_ENDIAN == 1 m[1] = HIGHT_EXMAX_P; #else m[ne-1] = HIGHT_EXMAX_P; #endif p = _get_tens_ptr( nb ); /* An unordered compare result shouldn't happen here */ while( ei_cmp( ten, u, nb ) <= 0 ) { if( ei_cmp( p, u, nb ) <= 0 ) { ei_div( u, u, p, nb ); ei_mul( t, t, p, nb ); ei_adde( expon, expon, m, ne+1 ); } /* End if( p <= u ) */ ei_shrn( m, m, (unsigned)1, ne+1 ); /* m >>= 1 */ if( ei_cmp0e( m, ne+1 ) == 0 ) break; p += np; } /* End of while( ten <= u ) */ } else /* Number is less than 1 (y < 1.0) */ { /* tmp = 1.0E0 */ _gen_one( tmp, nb ); /* Pad Significand with trailing decimal zeros */ /* Test for zero Exponent */ /* Copy Exponents */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_unpack( inc, &y[1], ne+1, ne ); #else ei_cpye_unpack( inc, &y[ns+2], ne+1, ne ); #endif if( ei_cmp0e( inc, ne+1 ) == 0 ) /* Exponent == 0 */ { #if MPU_WORD_ORDER_BIG_ENDIAN == 1 while( (y[ne+2] & MASK_SIGN) == 0 ) #else while( (y[ns] & MASK_SIGN) == 0 ) #endif { ei_mul( y, y, ten, nb ); ei_dece( expon, expon, ne+1 ); /* expon -= 1; */ } } else /* Exponent != 0 */ { ei_copy( w, y, nb ); for( i = 0; i < n_dec + 1; i++ ) { #if MPU_WORD_ORDER_BIG_ENDIAN == 1 if( (w[ne+ns+2] & 0x7) != 0 ) /* lgw */ #else if( (w[0] & 0x7) != 0 ) /* lgw */ #endif break; /* multiply by 10 */ ei_copyzlgw( u, w, nb ); ei_shdown( u, (unsigned)2, nb ); ei_addm( u, w, u, nb ); j = 3; /* Exponent += 3 */ ei_cvte_unpack( inc, (EMUSHORT *)&j, ne, 1 ); #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_adde( &u[1], &u[1], inc, ne ); #else ei_adde( &u[ns+2], &u[ns+2], inc, ne ); #endif #if MPU_WORD_ORDER_BIG_ENDIAN == 1 while( u[ne+1] != (EMUSHORT)0 ) /* hgw != 0 */ #else while( u[ns+1] != (EMUSHORT)0 ) /* hgw != 0 */ #endif { ei_shdown( u, (unsigned)1, nb ); /* Exponent += 1 */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_ince( &u[1], &u[1], ne ); #else ei_ince( &u[ns+2], &u[ns+2], ne ); #endif } #if MPU_WORD_ORDER_BIG_ENDIAN == 1 if( u[ne+ns+2] != (EMUSHORT)0 ) /* lgw != 0 */ #else if( u[0] != (EMUSHORT)0 ) /* lgw != 0 */ #endif break; #if MPU_WORD_ORDER_BIG_ENDIAN == 1 if( ei_cmpe( &tmp[1], &u[1], ne ) <= 0 ) #else if( ei_cmpe( &tmp[ns+2], &u[ns+2], ne ) <= 0 ) #endif break; ei_copyzlgw( w, u, nb ); ei_dece( expon, expon, ne+1 ); /* expon -= 1; */ } /* End for( i < n_dec ) */ ei_copy( y, w, nb ); } /* Enf if( y[Exponent] == 0 ) */ /* m = - MAXP */ for( i = 0; i < ne+1; i++ ) m[i] = (EMUSHORT)0; #if MPU_WORD_ORDER_BIG_ENDIAN == 1 m[1] = HIGHT_EXMAX_P; #else m[ne-1] = HIGHT_EXMAX_P; #endif p = _get_mtens_ptr( nb ); r = _get_tens_ptr( nb ); ei_copy( w, y, nb ); ei_copy( t, tmp, nb ); /* t = 1.0 */ while( ei_cmp( tmp, w, nb ) > 0 ) { if( ei_cmp( p, w, nb ) >= 0 ) { ei_mul( w, w, r, nb ); ei_mul( t, t, r, nb ); ei_sube( expon, expon, m, ne+1 ); /* expon -= m; */ } ei_shrn( m, m, (unsigned)1, ne+1 ); /* m /= 2; */ if( ei_cmp0e( m, ne+1 ) == 0 ) break; p += np; r += np; } ei_div( t, tmp, t, nb ); /* t = 1.0 / t; */ } isone: /* Find the first (leading) digit */ ei_copy( w, t, nb ); ei_copyzlgw( t, w, nb ); ei_copy( w, y, nb ); ei_copyzlgw( y, w, nb ); ei_remain( y, equot, y, t, nb ); #if MPU_WORD_ORDER_BIG_ENDIAN == 1 digit = equot[ne+ns+2]; /* lgw */ #else digit = equot[0]; /* lgw */ #endif /* tmp = 0E0 */ _gen_zero( tmp, nb ); while( (digit == 0) && (ei_cmp( y, tmp, nb ) != 0) ) { ei_shup( y, (unsigned)1, nb ); ei_copyzlgw( u, y, nb ); ei_shup( u, (unsigned)2, nb ); ei_addm( y, y, u, nb ); ei_remain( y, equot, y, t, nb ); #if MPU_WORD_ORDER_BIG_ENDIAN == 1 digit = equot[ne+ns+2]; /* lgw */ #else digit = equot[0]; /* lgw */ #endif ei_dece( expon, expon, ne+1 ); /* expon -= 1; */ } s = t_string; if( sign ) *s++ = '-'; else if( gen_plus ) *s++ = '+'; else *s++ = ' '; /* Examine number of digits requested by caller */ if( ndigs < 0 ) ndigs = 0; if( ndigs > n_dec ) ndigs = (int)n_dec; if( digit == 10 ) { *s++ = '1'; *s++ = '.'; if( ndigs > 0 ) { *s++ = '0'; ndigs -= 1; } ei_ince( expon, expon, ne+1 ); /* expon += 1; */ } else { *s++ = (__mpu_char8_t)digit + '0'; *s++ = '.'; } /* Generate digits after the decimal point */ for( k = 0; k <= ndigs; k++ ) { ei_shup( y, (unsigned)1, nb ); ei_copyzlgw( u, y, nb ); ei_shup( u, (unsigned)2, nb ); ei_addm( y, u, y, nb ); ei_remain( y, equot, y, t, nb ); #if MPU_WORD_ORDER_BIG_ENDIAN == 1 *s++ = (__mpu_char8_t)equot[ne+ns+2] + '0'; /* lgw */ #else *s++ = (__mpu_char8_t)equot[0] + '0'; /* lgw */ #endif } #if MPU_WORD_ORDER_BIG_ENDIAN == 1 digit = equot[ne+ns+2]; /* lgw */ #else digit = equot[0]; /* lgw */ #endif --s; ss = s; /* Round off the ASCII string */ if( digit > 4 ) { /* Test for critical rounding case in ASCII output */ if( digit == 5 ) { ei_copy( t, y, nb ); if( ei_cmp( t, tmp, nb ) != 0 ) goto roun; /* round to nearest */ if( (*(s - 1) & 1) == 0 ) goto doexp; /* round to even */ } /* End if( digit == 5 ) */ /* Round up and propagate carry-outs */ roun: --s; k = *s & 0x7f; /* Carry out to most significant digit? */ if( k == '.' ) { --s; k = *s; k += 1; *s = (__mpu_char8_t)k; /* Most significant digit carries to 10? */ if( k > '9' ) { ei_ince( expon, expon, ne+1 ); /* expon += 1; */ *s = '1'; } goto doexp; } /* Round up and carry out from less significant digits */ k += 1; *s = (__mpu_char8_t)k; if( k > '9' ) { *s = '0'; goto roun; } } /* Enf if( digit > 4 ) */ doexp: { __mpu_char8_t sexp[512]; __mpu_char8_t sexd[4]; /* Не изменяет флаги: CF, AF, PF, ZF, SF, OF, RF. */ iitoa_np( sexp, expon, 10, /* radix */ 0, /* upper flag */ ne+1 ); if( exp_digs > 0 ) { /************************************************* Если это необходимо, недостающие цифры Exponent будут поставлены как старшие незначащие нули. *************************************************/ __mpu_char8_t stmp[512], *ptr; int i, len; ptr = sexp; if( *ptr == '-' ) ptr++; /* skip sign */ len = strlen( ptr ); if( len < exp_digs ) { strcpy( stmp, ptr ); len = exp_digs - len; for( i = 0; i < len; i++ ) *ptr++ = '0'; *ptr = '\0'; strcat( sexp, stmp ); } /* End if( len < exp_digs ) */ } /* End if( exp_digs > 0 ) */ if( ei_cmp0e( expon, ne+1 ) >= 0 ) { /* Don't use sprintf() */ sexd[0] = (__mpu_char8_t)exp_delim; sexd[1] = '+'; sexd[2] = '\0'; } else { /* Don't use sprintf() */ sexd[0] = (__mpu_char8_t)exp_delim; sexd[1] = '\0'; } strcpy( ss, sexd ); /* exp_delim */ strcat( ss, sexp ); } bxit: rndprc = rndsave; /* Copy out the working string */ s = string; ss = t_string; while( *ss == ' ' ) ++ss; /* Strip possible leading space */ while( (*s++ = *ss++) != '\0' ) ; /* FREE t_string **********/ free( t_string ); /**************************/ /* FREE n *****************/ /* FREE m *****************/ /* FREE expon *************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE equot *************/ /* FREE tmp ***************/ /* FREE ten ***************/ /* FREE y *****************/ /* FREE t *****************/ /* FREE u *****************/ /* FREE w *****************/ __mpu_sbrk( -(int)(7*np*SIZE_OF_EMUSHORT) ); /**************************/ } /* End of ei_real_to_ascii() */ int ei_ascii_to_real( EMUSHORT *ei, __mpu_char8_t *ss, int nb ) /*************************************************************** Description : ei_ascii_to_real() Работает с internal e-type data struct. Concepts : Convert ASCII string SS to internal e-type EI. Return Code: -1 (ASCII_TO_REAL_ERROR) - read error; 0 (LONGHAND_REAL_NUMBER) - прочитано простое число (типа 1e1); 1 (REAL_PART_OF_COMPLEX) - прочитана вещественная часть комплексного числа (типа 1r1); 2 (IMAGINARY_OF_COMPLEX) - прочитана мнимая часть комплексного числа (типа 1j1); NOTE: ==== Количество цифр, после десятичной точки, не должно превышать величины REAL_nnnn_MDEC_DIG + 1 (см.: mpu-floatp.h). Use Global Variable: Use Functions : internal_np( nb ); | mpu-real.c internal_ne( nb ); | mpu-real.c internal_ns( nb ); | mpu-real.c Parameters : EMUSHORT *ei; - указатель на internal e-type data struct; __mpu_char8_t *ss; - input string; int nb; - количество бит в external e-type data struct. Return : int rc; - Return Code. if( exp_delim == ('e' || 'E') ) rc = 0; if( exp_delim == ('r' || 'R') ) rc = 1; if( exp_delim == ('j' || 'J') ) rc = 2; error: rc = -1; ***************************************************************/ { EMUSHORT *nexp = NULL, *lexp = NULL, *dexp = NULL, *exp = NULL, *exone = NULL, *inc = NULL, *yy = NULL, *xt = NULL, *tt = NULL; EMUSHORT nsign, *p, *min_dexp, *max_dexp; __mpu_int32_t j, jc; int k, trail, c, rndsave, n_ten; int esign, decflag, signflag, prec, lost; __mpu_char8_t *s, *sp, *lstr = NULL; int rc = ASCII_TO_REAL_ERROR, type_r = LONGHAND_REAL_NUMBER; int np, ne, ns, i; errno = 0; if( nb < NBR_32 || nb > MPU_REAL_IO_LIMIT ) { /* error: Invalid size of operand(s) */ __real_error_no = __R_ESIZE__; __STIND; /* Set REAL ind-produsing operation Flag */ return( rc ); } /* Copy the input string */ lstr = (__mpu_char8_t *)malloc( strlen( ss ) + 1 ); if( !lstr ) { /* fatal error */ return( rc ); } s = ss; while( *s == ' ' ) ++s; /* Skip leading spaces */ sp = lstr; while( (*sp++ = *s++) != '\0' ) ; s = lstr; np = internal_np( nb ); ne = internal_ne( nb ); ns = internal_ns( nb ); /*** Allocate memory for nexp, lexp, dexp, exp, exone, inc . ***********************/ nexp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !nexp ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ return( rc ); } lexp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !lexp ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ __mpu_sbrk( -(int)((ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return( rc ); } dexp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !dexp ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ /* FREE lexp **************/ __mpu_sbrk( -(int)(2*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return( rc ); } exp = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !exp ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ /* FREE lexp **************/ /* FREE dexp **************/ __mpu_sbrk( -(int)(3*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return( rc ); } exone = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !exone ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ /* FREE lexp **************/ /* FREE dexp **************/ /* FREE exp ***************/ __mpu_sbrk( -(int)(4*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return( rc ); } inc = (EMUSHORT *)__mpu_sbrk( (int)((ne+1)*SIZE_OF_EMUSHORT) ); if( !inc ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ /* FREE lexp **************/ /* FREE dexp **************/ /* FREE exp ***************/ /* FREE exone *************/ __mpu_sbrk( -(int)(5*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return( rc ); } /************************************************************/ /*** Allocate memory for yy, xt, tt . ***********************/ yy = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !yy ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ /* FREE lexp **************/ /* FREE dexp **************/ /* FREE exp ***************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(6*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ return( rc ); } xt = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !xt ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ /* FREE lexp **************/ /* FREE dexp **************/ /* FREE exp ***************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(6*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE yy ****************/ __mpu_sbrk( -(int)(np*SIZE_OF_EMUSHORT) ); /**************************/ return( rc ); } tt = (EMUSHORT *)__mpu_sbrk( (int)(np*SIZE_OF_EMUSHORT) ); if( !tt ) { /* fatal error */ /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ /* FREE lexp **************/ /* FREE dexp **************/ /* FREE exp ***************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(6*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE yy ****************/ /* FREE xt ****************/ __mpu_sbrk( -(int)(2*np*SIZE_OF_EMUSHORT) ); /**************************/ return( rc ); } /************************************************************/ /* Gen 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 rndsave = rndprc; if( nb == NBR_32 ) rndprc = 24; else if( nb == NBR_64 ) rndprc = 53; else rndprc = (int)NSBITS( nb ); lost = 0; nsign = (EMUSHORT)0; decflag = 0; signflag = 0; prec = 0; for( i = 0; i < ne+1; i++ ) nexp[i] = (EMUSHORT)0; for( i = 0; i < ne+1; i++ ) exp[i] = (EMUSHORT)0; ei_cleaz( yy, nb ); trail = 0; nextcom: k = *s - '0'; if( (k >= 0) && (k <= 9) ) { /* Ignore leading zeros */ if( (prec == 0) && (decflag == 0) && (k == 0) ) goto donchar; /* Identify and strip trailing zeros after the decimal point */ if( (trail == 0) && (decflag != 0) ) { sp = s; while( (*sp >= '0') && (*sp <= '9') ) ++sp; /* check for syntax error */ c = *sp & 0x7f; /* Only ASCII code */ if( (c != 'e') && (c != 'E') && (c != 'r') && (c != 'R') && (c != 'j') && (c != 'J') && (c != '\n') && (c != '\r') && (c != '\t') && (c != '\v') && (c != '\0') && (c != ' ') && (c != ',') ) goto errors; --sp; while( *sp == '0' ) *sp-- = 'z'; trail = 1; if( *s == 'z' ) goto donchar; } /* End if( trail == 0) && (decflag != 0) ) */ /************************************************************** Продолжая пока не будет что-то записано в hgw, мы гарантируем, что биты округления после нормализации будут выше lgw. **************************************************************/ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 if( yy[ne+1] == (EMUSHORT)0 ) /* hgw == 0 */ #else if( yy[ns+1] == (EMUSHORT)0 ) /* hgw == 0 */ #endif { /* Count digits after decimal point */ if( decflag ) ei_ince( nexp, nexp, ne+1 ); /* Multiply current number to 10 */ ei_shup( yy, (unsigned)1, nb ); ei_copyzlgw( xt, yy, nb ); ei_shup( xt, (unsigned)2, nb ); ei_addm( yy, xt, yy, nb ); ei_cleaz( xt, nb ); #if MPU_WORD_ORDER_BIG_ENDIAN == 1 xt[ne+ns+1] = (EMUSHORT)k; /* low part of Significand */ #else xt[1] = (EMUSHORT)k; /* low part of Significand */ #endif ei_addm( yy, xt, yy, nb ); } else /* ( hgw != 0 ) */ { /* Marc any lost non-zero digit */ lost |= k; /* Count lost digits before the decimal point */ if( decflag == 0 ) ei_dece( nexp, nexp, nb ); } /* End if( hgw == 0 ) */ prec += 1; goto donchar; } /* End if( (k >= 0) && (k <= 9) ) */ switch( *s ) { case 'z': break; case 'e': case 'E': goto exponent; case 'r': case 'R': type_r = REAL_PART_OF_COMPLEX; goto exponent; case 'j': case 'J': type_r = IMAGINARY_OF_COMPLEX; goto exponent; case '.': /* decimal point */ if( decflag ) goto errors; ++decflag; break; case '-': nsign = MASK_ALL_BITS; if( signflag ) goto errors; /* Здесь можно пропустить пробелы между знаком и числом: */ while( s[1] == ' ' || s[1] == '\n' || s[1] == '\r' || s[1] == '\t' || s[1] == '\v' ) ++s; ++signflag; break; case '+': if( signflag ) goto errors; /* Здесь можно пропустить пробелы между знаком и числом: */ while( s[1] == ' ' || s[1] == '\n' || s[1] == '\r' || s[1] == '\t' || s[1] == '\v' ) ++s; ++signflag; break; case ',': case ' ': case '\0': case '\n': case '\r': case '\t': case '\v': goto daldone; case 'i': case 'I': /* ind ****************************************/ if( (s[1] == 'n' || s[1] == 'N') && (s[2] == 'd' || s[2] == 'D') ) { if( s[3] == '_' ) { switch( s[4] ) { case 'r': case 'R': type_r = REAL_PART_OF_COMPLEX; break; case 'j': case 'J': type_r = IMAGINARY_OF_COMPLEX; break; case 'e': case 'E': type_r = LONGHAND_REAL_NUMBER; break; default: break; } } /* ind */ ei_ind( yy, nb ); rndprc = rndsave; goto ind_exit; } /* inf ****************************************/ else if( (s[1] == 'n' || s[1] == 'N') && (s[2] == 'f' || s[2] == 'F') ) { if( s[3] == '_' ) { switch( s[4] ) { case 'r': case 'R': type_r = REAL_PART_OF_COMPLEX; break; case 'j': case 'J': type_r = IMAGINARY_OF_COMPLEX; break; case 'e': case 'E': type_r = LONGHAND_REAL_NUMBER; break; default: break; } } /* inf */ goto infinite; } else /**********************************************/ goto errors; case 'n': case 'N': /* NaN ****************************************/ if( (s[1] == 'a' || s[1] == 'A') && (s[2] == 'n' || s[2] == 'N') ) { if( s[3] == '_' ) { switch( s[4] ) { case 'r': case 'R': type_r = REAL_PART_OF_COMPLEX; break; case 'j': case 'J': type_r = IMAGINARY_OF_COMPLEX; break; case 'e': case 'E': type_r = LONGHAND_REAL_NUMBER; break; default: break; } } /* nan */ ei_nan( yy, (unsigned)nsign, nb ); rndprc = rndsave; goto ind_exit; } else /**********************************************/ goto errors; default: errors: type_r = ASCII_TO_REAL_ERROR; ei_nan( yy, (unsigned)0, nb ); goto aexit; } /* End of switch( *s ) */ donchar: ++s; goto nextcom; /************************* Exponent interpretation *************************/ exponent: max_dexp = _get_maxdecexp_ptr( nb ); /* size ne+1 always */ min_dexp = _get_mindecexp_ptr( nb ); /* size ne+1 always */ ei_cpye_unpack( dexp, min_dexp, ne+1, ne+1 ); ei_nege( dexp, dexp, ne+1 ); /* dexp == -(MINDECEXP) */ esign = 1; ++s; /* Check for + or - */ if( *s == '-' ) { esign = -1; ++s; } if( *s == '+' ) ++s; while( (*s >= '0') && (*s <= '9') ) { /* exp *= 10; */ ei_shln( exp, exp, (unsigned)1, ne+1 ); ei_shln( inc, exp, (unsigned)2, ne+1 ); ei_adde( exp, inc, exp, ne+1 ); /* exp += *s++ - '0'; */ j = *s++ - '0'; ei_cvte_unpack( inc, (EMUSHORT *)&j, ne+1, 1 ); ei_adde( exp, exp, inc, ne+1 ); if( ei_cmpe( exp, dexp, ne+1 ) > 0 ) /* exp > -(MINDECEXP) */ { if( esign < 0 ) goto zero; else goto infinite; } } /* End of while( is_digit(*s) ) */ if( esign < 0 ) ei_nege( exp, exp, ne+1 ); /* exp = -exp */ if( ei_cmpe( exp, max_dexp, ne+1 ) > 0 ) /* exp > (MAXDECEXP) */ { infinite: ei_infin( yy, (unsigned)nsign, nb ); /* Infinity */ goto aexit; } if( ei_cmpe( exp, min_dexp, ne+1 ) < 0 ) /* exp < (MINDECEXP) */ { zero: ei_signull( yy, (unsigned)nsign, nb ); /* signed NULL */ goto aexit; } daldone: ei_sube( nexp, exp, nexp, ne+1 ); /* Pad trailing zeros to minimize power of 10, per IEEE spec. */ while( (ei_cmp0e( nexp, ne+1 ) > 0) && #if MPU_WORD_ORDER_BIG_ENDIAN == 1 (yy[ne+1] == (EMUSHORT)0) ) /* hgw == 0 */ #else (yy[ns+1] == (EMUSHORT)0) ) /* hgw == 0 */ #endif { ei_copyzlgw( xt, yy, nb ); ei_shup( xt, (unsigned)2, nb ); ei_addm( xt, yy, xt, nb ); ei_shup( xt, (unsigned)1, nb ); #if MPU_WORD_ORDER_BIG_ENDIAN == 1 if( xt[ne+1] != (EMUSHORT)0 ) break; /* hgw != 0 */ #else if( xt[ns+1] != (EMUSHORT)0 ) break; /* hgw != 0 */ #endif ei_dece( nexp, nexp, ne+1 ); /* nexp -= 1; */ ei_copyzlgw( yy, xt, nb ); } /* End of while( (nexp > 0) && (hgw == 0) ) */ if( (jc = ei_normalize( yy, nb )) > (__mpu_int32_t)NSBITS(nb) ) { ei_cleaz( yy, nb ); type_r = rc; /* количество цифр после точки превышает размер мантиссы */ goto aexit; } /* lexp = (EXONE - 1 + NSBITS(nb)) - jc */ ei_dece( lexp, exone, ne+1 ); j = NSBITS( nb ); ei_cvte_unpack( inc, (EMUSHORT *)&j, ne+1, 1 ); ei_cvte_unpack( dexp, (EMUSHORT *)&jc, ne+1, 1 ); ei_adde( lexp, lexp, inc, ne+1 ); ei_sube( lexp, lexp, dexp, ne+1 ); /* Здесь главное, чтобы параметр int rcontrol не был равен 0, для того чтобы функция ei_mdenorm() использовала, ранее установленное значение RNDPRC */ ei_mdenorm( yy, lost, 0, lexp, NSBITS_DEFAULT, nb ); /****************************************** Convert GO ON ******************************************/ /* dexp = MAXP */ for( i = 0; i < ne+1; i++ ) dexp[i] = (EMUSHORT)0; #if MPU_WORD_ORDER_BIG_ENDIAN == 1 dexp[1] = HIGHT_EXMAX_P; #else dexp[ne-1] = HIGHT_EXMAX_P; #endif n_ten = _get_nten( nb ); p = _get_tens_ptr( nb ); /* *p = 10**MAXP */ /* Copy Exponents */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_unpack( lexp, &yy[1], ne+1, ne ); #else ei_cpye_unpack( lexp, &yy[ns+2], ne+1, ne ); #endif if( ei_cmp0e( nexp, ne+1 ) == 0 ) /* nexp == 0 */ { j = 0; goto expdone; } /* End if( nexp == 0 ) */ esign = 1; if( ei_cmp0e( nexp, ne+1 ) < 0 ) /* nexp < 0 */ { ei_nege( nexp, nexp, ne+1 ); esign = -1; if( ei_cmpe( nexp, dexp, ne+1 ) > 0 ) /* nexp > MAXP */ { /* Punt. Can't handle this without 2 divides */ ei_copy( tt, p, nb ); /* Copy Exponents */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_unpack( inc, &tt[1], ne+1, ne ); #else ei_cpye_unpack( inc, &tt[ns+2], ne+1, ne ); #endif ei_sube( lexp, lexp, inc, ne+1 ); j = ei_divm( yy, yy, tt, nb ); ei_adde( lexp, lexp, exone, ne+1 ); ei_sube( nexp, nexp, dexp, ne+1 ); } } /* End if( nexp < 0 ) */ p = _get_tens_ptr( nb ); p += np*n_ten; /* xt = 1.0E0 */ _gen_one( xt, nb ); for( i = 0; i < ne+1; i++ ) exp[i] = (EMUSHORT)0; #if MPU_WORD_ORDER_BIG_ENDIAN == 1 exp[ne] = (EMUSHORT)1; /* exp = 1 */ #else exp[0] = (EMUSHORT)1; /* exp = 1 */ #endif do { ei_ande( inc, exp, nexp, ne+1 ); if( ei_cmp0e( inc, ne+1 ) ) /* if( exp & nexp ) */ ei_mul( xt, xt, p, nb ); p -= np; ei_adde( exp, exp, exp, ne+1 ); } while( ei_cmpe( exp, dexp, ne+1 ) <= 0 ); /* exp <= MAXP */ ei_copy( tt, xt, nb ); /* Copy Exponent of TT */ #if MPU_WORD_ORDER_BIG_ENDIAN == 1 ei_cpye_unpack( inc, &tt[1], ne+1, ne ); #else ei_cpye_unpack( inc, &tt[ns+2], ne+1, ne ); #endif if( esign < 0 ) { ei_sube( lexp, lexp, inc, ne+1 ); j = ei_divm( yy, yy, tt, nb ); ei_adde( lexp, lexp, exone, ne+1 ); } else { ei_adde( lexp, lexp, inc, ne+1 ); j = ei_mulm( yy, yy, tt, nb ); ei_sube( lexp, lexp, exone, ne+1 ); ei_ince( lexp, lexp, ne+1 ); /* lexp -= EXONE -1; */ } expdone: /* Здесь главное, чтобы параметр int rcontrol не был равен 0, для того чтобы функция ei_mdenorm() использовала, ранее установленное значение RNDPRC */ ei_mdenorm( yy, (int)j, 0, lexp, NSBITS_DEFAULT, nb ); aexit: rndprc = rndsave; #if MPU_WORD_ORDER_BIG_ENDIAN == 1 yy[0] = nsign; /* copy Sign */ #else yy[ne+ns+2] = nsign; /* copy Sign */ #endif ind_exit: ei_copy( ei, yy, nb ); /* FREE lstr **************/ free( lstr ); /**************************/ /* FREE nexp **************/ /* FREE lexp **************/ /* FREE dexp **************/ /* FREE exp ***************/ /* FREE exone *************/ /* FREE inc ***************/ __mpu_sbrk( -(int)(6*(ne+1)*SIZE_OF_EMUSHORT) ); /**************************/ /* FREE yy ****************/ /* FREE xt ****************/ /* FREE tt ****************/ __mpu_sbrk( -(int)(3*np*SIZE_OF_EMUSHORT) ); /**************************/ rc = type_r; return( rc ); } /* End of ei_ascii_to_real() */ /*************************************************************** Hide internal symbols: ***************************************************************/ __mpu_hidden_decl(ei_real_to_ascii); __mpu_hidden_decl(ei_ascii_to_real); /* End of hide internal symbols. ***************************************************************/