/***************************************************************
__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 <config.h>
#endif
#include <errno.h> /* errno(3) */
#include <string.h> /* strcpy(3) */
#include <strings.h> /* bzero(3) */
#include <stdlib.h>
#include <libmpu.h>
#include <mpu-context.h>
#include <mpu-emutype.h>
#include <mpu-integer.h>
#include <mpu-real.h>
#include <mpu-floatp.h>
#include <mpu-ioreal.h>
#include <mpu-char.h>
#include <mpu-symbols.h>
#include <mpu-math-errno.h>
#include <mpu-mtherr.h>
#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 <etens/emu00128/ei_mtens_001_emu32lsb.dfn>
#include <etens/emu00128/ei_ptens_001_emu32lsb.dfn>
#else
#include <etens/emu00128/ei_mtens_001_emu32msb.dfn>
#include <etens/emu00128/ei_ptens_001_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 128 */
#if MPU_REAL_IO_LIMIT >= 256
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu00256/ei_mtens_002_emu32lsb.dfn>
#include <etens/emu00256/ei_ptens_002_emu32lsb.dfn>
#else
#include <etens/emu00256/ei_mtens_002_emu32msb.dfn>
#include <etens/emu00256/ei_ptens_002_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 256 */
#if MPU_REAL_IO_LIMIT >= 512
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu00512/ei_mtens_004_emu32lsb.dfn>
#include <etens/emu00512/ei_ptens_004_emu32lsb.dfn>
#else
#include <etens/emu00512/ei_mtens_004_emu32msb.dfn>
#include <etens/emu00512/ei_ptens_004_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 512 */
#if MPU_REAL_IO_LIMIT >= 1024
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu01024/ei_mtens_008_emu32lsb.dfn>
#include <etens/emu01024/ei_ptens_008_emu32lsb.dfn>
#else
#include <etens/emu01024/ei_mtens_008_emu32msb.dfn>
#include <etens/emu01024/ei_ptens_008_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 1024 */
#if MPU_REAL_IO_LIMIT >= 2048
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu02048/ei_mtens_016_emu32lsb.dfn>
#include <etens/emu02048/ei_ptens_016_emu32lsb.dfn>
#else
#include <etens/emu02048/ei_mtens_016_emu32msb.dfn>
#include <etens/emu02048/ei_ptens_016_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 2048 */
#if MPU_REAL_IO_LIMIT >= 4096
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu04096/ei_mtens_032_emu32lsb.dfn>
#include <etens/emu04096/ei_ptens_032_emu32lsb.dfn>
#else
#include <etens/emu04096/ei_mtens_032_emu32msb.dfn>
#include <etens/emu04096/ei_ptens_032_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 4096 */
#if MPU_REAL_IO_LIMIT >= 8192
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu08192/ei_mtens_064_emu32lsb.dfn>
#include <etens/emu08192/ei_ptens_064_emu32lsb.dfn>
#else
#include <etens/emu08192/ei_mtens_064_emu32msb.dfn>
#include <etens/emu08192/ei_ptens_064_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 8192 */
#if MPU_REAL_IO_LIMIT >= 16384
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu16384/ei_mtens_128_emu32lsb.dfn>
#include <etens/emu16384/ei_ptens_128_emu32lsb.dfn>
#else
#include <etens/emu16384/ei_mtens_128_emu32msb.dfn>
#include <etens/emu16384/ei_ptens_128_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 16384 */
#if MPU_REAL_IO_LIMIT >= 32768
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu32768/ei_mtens_256_emu32lsb.dfn>
#include <etens/emu32768/ei_ptens_256_emu32lsb.dfn>
#else
#include <etens/emu32768/ei_mtens_256_emu32msb.dfn>
#include <etens/emu32768/ei_ptens_256_emu32msb.dfn>
#endif
#endif /* MPU_REAL_IO_LIMIT >= 32768 */
#if MPU_REAL_IO_LIMIT >= 65536
#if MPU_WORD_ORDER_BIG_ENDIAN == 0
#include <etens/emu65536/ei_mtens_512_emu32lsb.dfn>
#include <etens/emu65536/ei_ptens_512_emu32lsb.dfn>
#else
#include <etens/emu65536/ei_mtens_512_emu32msb.dfn>
#include <etens/emu65536/ei_ptens_512_emu32msb.dfn>
#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.
***************************************************************/