819 lines
33 KiB
C++
819 lines
33 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: Number.cpp
|
|
//
|
|
// Note:
|
|
//
|
|
|
|
#include "hal.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
#define LITTLE_ENDIAN
|
|
|
|
#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC) || defined(_M_IA64)
|
|
#define REQUIRES_UNALIGNED_FLAG
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
static const int32 SCALE_NAN = (int32)0x80000000;
|
|
static const int32 SCALE_INF = 0x7FFFFFFF;
|
|
|
|
// Currently our string conversion routines do not conform to the special
|
|
// requirements of the IEEE standard for floating point conversions.
|
|
// We do this to avoid IEEE exceptions.
|
|
|
|
#pragma pack(4)
|
|
typedef struct {
|
|
uint8 ld12[12];
|
|
} _LDBL12;
|
|
#pragma pack()
|
|
|
|
#define PTR_12(x) ((uint8 *)(&(x)->ld12))
|
|
|
|
#define MAX_USHORT ((uint16)0xffff)
|
|
#define MSB_USHORT ((uint16)0x8000)
|
|
#define MAX_ULONG ((uint32)0xffffffff)
|
|
#define MSB_ULONG ((uint32)0x80000000)
|
|
|
|
#define LD_BIAS 0x3fff // exponent bias for long double
|
|
#define LD_BIASM1 0x3ffe // LD_BIAS - 1
|
|
#define LD_MAXEXP 0x7fff // maximum biased exponent
|
|
|
|
#define D_BIAS 0x3ff // exponent bias for double
|
|
#define D_BIASM1 0x3fe // D_BIAS - 1
|
|
#define D_MAXEXP 0x7ff // maximum biased exponent
|
|
|
|
#define _IS_MAN_INF(signbit, manhi, manlo) ((manhi)==MSB_ULONG && (manlo)==0x0 )
|
|
|
|
#if defined (LITTLE_ENDIAN)
|
|
|
|
// Manipulation of a 12-byte long double number (an ordinary
|
|
// 10-byte long double plus two extra bytes of mantissa).
|
|
//
|
|
// byte layout:
|
|
//
|
|
// +--+--+--+--+--+--+--+--+--+--+--+--+
|
|
// |XT:2 | MANLO:4 | MANHI:4 |EXP:2|
|
|
// +--+--+--+--+--+--+--+--+--+--+--+--+
|
|
// | UL_LO:4 | UL_MED:4 | UL_HI:4 |
|
|
// +--+--+--+--+--+--+--+--+--+--+--+--+
|
|
//
|
|
#define U_EXP_12(p) ((uint16 *)(PTR_12(p)+10)) // exponent/sign
|
|
#if !defined(REQUIRES_UNALIGNED_FLAG)
|
|
#define UL_MANHI_12(p) ((uint32 *)(PTR_12(p)+6)) // 4 hi-order bytes of ord mantissa
|
|
#define UL_MANLO_12(p) ((uint32 *)(PTR_12(p)+2)) // 4 lo-order bytes of ord mantissa
|
|
#else
|
|
#define UL_MANHI_12(p) ((uint32 __unaligned *) (PTR_12(p)+6) )
|
|
#define UL_MANLO_12(p) ((uint32 __unaligned *) (PTR_12(p)+2) )
|
|
#endif // defined(REQUIRES_UNALIGNED_FLAG)
|
|
#define U_XT_12(p) ((uint16 *)PTR_12(p)) // 2 extra-lo bytes of mantissa
|
|
|
|
#define UL_LO_12(p) ((uint32 *)PTR_12(p)) // 4 lo-order bytes of 12-byte value
|
|
#define UL_MED_12(p) ((uint32 *)(PTR_12(p)+4)) // 4 mid-order bytes of 12-byte value
|
|
#define UL_HI_12(p) ((uint32 *)(PTR_12(p)+8)) // 4 hi-order bytes of 12-byte value
|
|
|
|
#define UCHAR_12(p,i) ((uint8 *)PTR_12(p)+(i)) // byte of order i (LSB=0)
|
|
#define USHORT_12(p,i) ((uint16 *)((uint8 *)PTR_12(p)+(i))) // uint16 at byte of order i
|
|
#define ULONG_12(p,i) ((uint32 *)((uint8 *)PTR_12(p)+(i))) // uint32 at byte of order i
|
|
|
|
// Manipulation of a 64bit IEEE double
|
|
#define UINT164_D(p) ((uint16 *)(p) + 3)
|
|
#define UL_HI_D(p) ((uint32 *)(p) + 1)
|
|
#define UL_LO_D(p) ((uint32 *)(p))
|
|
|
|
#endif // defined(LITTLE_ENDIAN)
|
|
|
|
#if defined (BIG_ENDIAN)
|
|
|
|
#define U_EXP_12(p) ((uint16 *)PTR_12(p))
|
|
#define UL_MANHI_12(p) ((uint32 *)(PTR_12(p)+2))
|
|
#define UL_MANLO_12(p) ((uint32 *)(PTR_12(p)+6))
|
|
#define U_XT_12(p) ((uint16 *)(PTR_12(p)+10))
|
|
|
|
#define UL_LO_12(p) ((uint32 *)(PTR_12(p)+8))
|
|
#define UL_MED_12(p) ((uint32 *)(PTR_12(p)+4))
|
|
#define UL_HI_12(p) ((uint32 *)PTR_12(p))
|
|
|
|
#define UCHAR_12(p,i) ((uint8 *)PTR_12(p)+(11-(i)))
|
|
#define USHORT_12(p,i) ((uint16 *)((uint8 *)PTR_12(p)+10-(i)))
|
|
#define ULONG_12(p,i) ((uint32 *)((uint8 *)PTR_12(p)+8-(i)))
|
|
|
|
// Manipulation of a 64bit IEEE double
|
|
#define UINT164_D(p) ((uint16 *)(p))
|
|
#define UL_HI_D(p) ((uint32 *)(p))
|
|
#define UL_LO_D(p) ((uint32 *)(p) + 1)
|
|
|
|
#endif // defined(BIG_ENDIAN)
|
|
|
|
#define PUT_INF_12(p,sign) \
|
|
*UL_HI_12(p) = (sign)?0xffff8000:0x7fff8000; \
|
|
*UL_MED_12(p) = 0; \
|
|
*UL_LO_12(p) = 0;
|
|
|
|
#define PUT_ZERO_12(p) *UL_HI_12(p) = 0; \
|
|
*UL_MED_12(p) = 0; \
|
|
*UL_LO_12(p) = 0;
|
|
|
|
#define ISZERO_12(p) ((*UL_HI_12(p)&0x7fffffff) == 0 && \
|
|
*UL_MED_12(p) == 0 && \
|
|
*UL_LO_12(p) == 0 )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Purpose: Convert a double into a _LDBL12
|
|
//
|
|
// Entry: double *px
|
|
//
|
|
// Exit: the corresponding _LDBL12 value is returned in *pld
|
|
//
|
|
static void dtold12(_LDBL12 *pld, const double *px)
|
|
{
|
|
uint32 msb = MSB_ULONG;
|
|
uint16 ldexp = 0;
|
|
uint16 exp = (*UINT164_D(px) & (uint16)0x7ff0) >> 4;
|
|
uint16 sign = *UINT164_D(px) & (uint16)0x8000;
|
|
uint32 manhi = *UL_HI_D(px) & 0xfffff;
|
|
uint32 manlo = *UL_LO_D(px);
|
|
|
|
switch (exp) {
|
|
case D_MAXEXP:
|
|
ldexp = LD_MAXEXP;
|
|
break;
|
|
case 0:
|
|
// check for zero
|
|
if (manhi == 0 && manlo == 0) {
|
|
*UL_MANHI_12(pld) = 0;
|
|
*UL_MANLO_12(pld) = 0;
|
|
*U_XT_12(pld) = 0;
|
|
*U_EXP_12(pld) = 0;
|
|
return;
|
|
}
|
|
// we have a denormal -- we'll normalize later
|
|
ldexp = (uint16) ((int16)exp - D_BIAS + LD_BIAS + 1);
|
|
msb = 0;
|
|
break;
|
|
default:
|
|
exp -= D_BIAS;
|
|
ldexp = (uint16) ((int16)exp + LD_BIAS);
|
|
break;
|
|
}
|
|
|
|
*UL_MANHI_12(pld) = msb | (manhi << 11) | (manlo >> 21);
|
|
*UL_MANLO_12(pld) = manlo << 11;
|
|
|
|
// normalize if necessary
|
|
while ((*UL_MANHI_12(pld) & MSB_ULONG) == 0) {
|
|
// shift left
|
|
*UL_MANHI_12(pld) = (*UL_MANHI_12(pld) << 1) |
|
|
(MSB_ULONG & *UL_MANLO_12(pld) ? 1: 0);
|
|
(*UL_MANLO_12(pld)) <<= 1;
|
|
ldexp --;
|
|
}
|
|
*U_EXP_12(pld) = sign | ldexp;
|
|
*U_XT_12(pld) = 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Purpose: add two uint32 numbers and return carry
|
|
//
|
|
// Entry: uint32 x, uint32 y : the numbers to be added
|
|
// uint32 *sum : where to store the result
|
|
//
|
|
// Exit: *sum receives the value of x+y
|
|
// the value of the carry is returned
|
|
//
|
|
static int addl(uint32 x, uint32 y, uint32 *sum)
|
|
{
|
|
uint32 r = x + y;
|
|
*sum = r;
|
|
return (r < x || r < y);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Purpose: add two _LDBL12 numbers. The numbers are added
|
|
// as 12-byte integers. Overflow is ignored.
|
|
//
|
|
// Entry: x,y: pointers to the operands
|
|
//
|
|
// Exit: *x receives the sum
|
|
//
|
|
static void add_12(_LDBL12 *x, _LDBL12 *y)
|
|
{
|
|
if (addl(*UL_LO_12(x),*UL_LO_12(y),UL_LO_12(x))) {
|
|
if (addl(*UL_MED_12(x),(uint32)1,UL_MED_12(x))) {
|
|
(*UL_HI_12(x))++;
|
|
}
|
|
}
|
|
if (addl(*UL_MED_12(x),*UL_MED_12(y),UL_MED_12(x))) {
|
|
(*UL_HI_12(x))++;
|
|
}
|
|
// ignore next carry -- assume no overflow will occur
|
|
(void)addl(*UL_HI_12(x),*UL_HI_12(y),UL_HI_12(x));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Purpose: Shift a _LDBL12 number one bit to the left (right). The number
|
|
// is shifted as a 12-byte integer. The MSB is lost.
|
|
//
|
|
// Entry: x: a pointer to the operand
|
|
//
|
|
// Exit: *x is shifted one bit to the left (or right)
|
|
//
|
|
static void shl_12(_LDBL12 *p)
|
|
{
|
|
uint32 c0 = (*UL_LO_12(p) & MSB_ULONG) ? 1: 0;
|
|
uint32 c1 = (*UL_MED_12(p) & MSB_ULONG) ? 1: 0;
|
|
*UL_LO_12(p) <<= 1;
|
|
*UL_MED_12(p) = (*UL_MED_12(p) << 1) | c0;
|
|
*UL_HI_12(p) = (*UL_HI_12(p) << 1) | c1;
|
|
}
|
|
|
|
static void shr_12(_LDBL12 *p)
|
|
{
|
|
uint32 c2 = (*UL_HI_12(p) & 0x1) ? MSB_ULONG: 0;
|
|
uint32 c1 = (*UL_MED_12(p) & 0x1) ? MSB_ULONG: 0;
|
|
*UL_HI_12(p) >>= 1;
|
|
*UL_MED_12(p) = (*UL_MED_12(p) >> 1) | c2;
|
|
*UL_LO_12(p) = (*UL_LO_12(p) >> 1) | c1;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Purpose: multiply two _LDBL12 numbers
|
|
//
|
|
// Entry: px,py: pointers to the _LDBL12 operands
|
|
//
|
|
// Exit: *px contains the product
|
|
//
|
|
static void ld12mul(_LDBL12 *px, _LDBL12 *py)
|
|
{
|
|
_LDBL12 tempman; // this is actually a 12-byte mantissa, not a 12-byte long double
|
|
|
|
*UL_LO_12(&tempman) = 0;
|
|
*UL_MED_12(&tempman) = 0;
|
|
*UL_HI_12(&tempman) = 0;
|
|
|
|
uint16 expx = *U_EXP_12(px);
|
|
uint16 expy = *U_EXP_12(py);
|
|
uint16 sign = (expx ^ expy) & (uint16)0x8000;
|
|
expx &= 0x7fff;
|
|
expy &= 0x7fff;
|
|
uint16 expsum = expx + expy;
|
|
if (expx >= LD_MAXEXP
|
|
|| expy >= LD_MAXEXP
|
|
|| expsum > LD_MAXEXP + LD_BIASM1) {
|
|
// overflow to infinity
|
|
PUT_INF_12(px,sign);
|
|
return;
|
|
}
|
|
if (expsum <= LD_BIASM1 - 63) {
|
|
// underflow to zero
|
|
PUT_ZERO_12(px);
|
|
return;
|
|
}
|
|
if (expx == 0) {
|
|
// If this is a denormal temp real then the mantissa
|
|
// was shifted right once to set bit 63 to zero.
|
|
expsum++; // Correct for this
|
|
if (ISZERO_12(px)) {
|
|
// put positive sign
|
|
*U_EXP_12(px) = 0;
|
|
return;
|
|
}
|
|
}
|
|
if (expy == 0) {
|
|
expsum++; // because arg2 is denormal
|
|
if (ISZERO_12(py)) {
|
|
PUT_ZERO_12(px);
|
|
return;
|
|
}
|
|
}
|
|
|
|
int roffs = 0;
|
|
for (int i = 0; i < 5; i++) {
|
|
int poffs = i << 1;
|
|
int qoffs = 8;
|
|
for (int j = 5 - i; j > 0; j--) {
|
|
uint32 prod;
|
|
int carry;
|
|
uint16 *p, *q;
|
|
uint32 *r;
|
|
p = USHORT_12(px,poffs);
|
|
q = USHORT_12(py,qoffs);
|
|
r = ULONG_12(&tempman,roffs);
|
|
prod = (uint32)*p * (uint32)*q;
|
|
carry = addl(*r,prod,r);
|
|
if (carry) {
|
|
// roffs should be less than 8 in this case
|
|
(*USHORT_12(&tempman,roffs+4))++;
|
|
}
|
|
poffs += 2;
|
|
qoffs -= 2;
|
|
}
|
|
roffs += 2;
|
|
}
|
|
|
|
expsum -= LD_BIASM1;
|
|
|
|
// normalize
|
|
while ((int16)expsum > 0 &&
|
|
((*UL_HI_12(&tempman) & MSB_ULONG) == 0)) {
|
|
shl_12(&tempman);
|
|
expsum--;
|
|
}
|
|
|
|
if ((int16)expsum <= 0) {
|
|
bool sticky = false;
|
|
expsum--;
|
|
while ((int16)expsum < 0) {
|
|
if (*U_XT_12(&tempman) & 0x1) {
|
|
sticky = true;
|
|
}
|
|
shr_12(&tempman);
|
|
expsum++;
|
|
}
|
|
if (sticky) {
|
|
*U_XT_12(&tempman) |= 0x1;
|
|
}
|
|
}
|
|
|
|
if (*U_XT_12(&tempman) > 0x8000 ||
|
|
((*UL_LO_12(&tempman) & 0x1ffff) == 0x18000)) {
|
|
// round up
|
|
if (*UL_MANLO_12(&tempman) == MAX_ULONG) {
|
|
*UL_MANLO_12(&tempman) = 0;
|
|
if (*UL_MANHI_12(&tempman) == MAX_ULONG) {
|
|
*UL_MANHI_12(&tempman) = 0;
|
|
if (*U_EXP_12(&tempman) == MAX_USHORT) {
|
|
// 12-byte mantissa overflow
|
|
*U_EXP_12(&tempman) = MSB_USHORT;
|
|
expsum++;
|
|
}
|
|
else {
|
|
(*U_EXP_12(&tempman))++;
|
|
}
|
|
}
|
|
else {
|
|
(*UL_MANHI_12(&tempman))++;
|
|
}
|
|
}
|
|
else {
|
|
(*UL_MANLO_12(&tempman))++;
|
|
}
|
|
}
|
|
|
|
// check for exponent overflow
|
|
if (expsum >= 0x7fff) {
|
|
PUT_INF_12(px, sign);
|
|
return;
|
|
}
|
|
|
|
// put result in px
|
|
*U_XT_12(px) = *USHORT_12(&tempman,2);
|
|
*UL_MANLO_12(px) = *UL_MED_12(&tempman);
|
|
*UL_MANHI_12(px) = *UL_HI_12(&tempman);
|
|
*U_EXP_12(px) = expsum | sign;
|
|
}
|
|
|
|
static void multtenpow12(_LDBL12 *pld12, int pow)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Format: A 10 byte long double + 2 bytes of extra precision
|
|
// If the extra precision is desired, the 10-byte long double
|
|
// should be "unrounded" first.
|
|
//
|
|
static _LDBL12 _pow10pos[] = {
|
|
#if defined(LITTLE_ENDIAN)
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0x02,0x40}}, // P0001
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC8,0x05,0x40}}, // P0002
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFA,0x08,0x40}}, // P0003
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9C,0x0C,0x40}}, // P0004
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xC3,0x0F,0x40}}, // P0005
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x24,0xF4,0x12,0x40}}, // P0006
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x80,0x96,0x98,0x16,0x40}}, // P0007
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x20,0xBC,0xBE,0x19,0x40}}, // P0008
|
|
{{0x00,0x00, 0x00,0x00,0x00,0x04,0xBF,0xC9,0x1B,0x8E,0x34,0x40}}, // P0016
|
|
{{0x00,0x00, 0x00,0xA1,0xED,0xCC,0xCE,0x1B,0xC2,0xD3,0x4E,0x40}}, // P0024
|
|
{{0x20,0xF0, 0x9E,0xB5,0x70,0x2B,0xA8,0xAD,0xC5,0x9D,0x69,0x40}}, // P0032
|
|
{{0xD0,0x5D, 0xFD,0x25,0xE5,0x1A,0x8E,0x4F,0x19,0xEB,0x83,0x40}}, // P0040
|
|
{{0x71,0x96, 0xD7,0x95,0x43,0x0E,0x05,0x8D,0x29,0xAF,0x9E,0x40}}, // P0048
|
|
{{0xF9,0xBF, 0xA0,0x44,0xED,0x81,0x12,0x8F,0x81,0x82,0xB9,0x40}}, // P0056
|
|
{{0xBF,0x3C, 0xD5,0xA6,0xCF,0xFF,0x49,0x1F,0x78,0xC2,0xD3,0x40}}, // P0064
|
|
{{0x6F,0xC6, 0xE0,0x8C,0xE9,0x80,0xC9,0x47,0xBA,0x93,0xA8,0x41}}, // P0128
|
|
{{0xBC,0x85, 0x6B,0x55,0x27,0x39,0x8D,0xF7,0x70,0xE0,0x7C,0x42}}, // P0192
|
|
{{0xBC,0xDD, 0x8E,0xDE,0xF9,0x9D,0xFB,0xEB,0x7E,0xAA,0x51,0x43}}, // P0256
|
|
{{0xA1,0xE6, 0x76,0xE3,0xCC,0xF2,0x29,0x2F,0x84,0x81,0x26,0x44}}, // P0320
|
|
{{0x28,0x10, 0x17,0xAA,0xF8,0xAE,0x10,0xE3,0xC5,0xC4,0xFA,0x44}}, // P0384
|
|
{{0xEB,0xA7, 0xD4,0xF3,0xF7,0xEB,0xE1,0x4A,0x7A,0x95,0xCF,0x45}}, // P0448
|
|
{{0x65,0xCC, 0xC7,0x91,0x0E,0xA6,0xAE,0xA0,0x19,0xE3,0xA3,0x46}}, // P0512
|
|
{{0x0D,0x65, 0x17,0x0C,0x75,0x81,0x86,0x75,0x76,0xC9,0x48,0x4D}}, // P1024
|
|
{{0x58,0x42, 0xE4,0xA7,0x93,0x39,0x3B,0x35,0xB8,0xB2,0xED,0x53}}, // P1536
|
|
{{0x4D,0xA7, 0xE5,0x5D,0x3D,0xC5,0x5D,0x3B,0x8B,0x9E,0x92,0x5A}}, // P2048
|
|
{{0xFF,0x5D, 0xA6,0xF0,0xA1,0x20,0xC0,0x54,0xA5,0x8C,0x37,0x61}}, // P2560
|
|
{{0xD1,0xFD, 0x8B,0x5A,0x8B,0xD8,0x25,0x5D,0x89,0xF9,0xDB,0x67}}, // P3072
|
|
{{0xAA,0x95, 0xF8,0xF3,0x27,0xBF,0xA2,0xC8,0x5D,0xDD,0x80,0x6E}}, // P3584
|
|
{{0x4C,0xC9, 0x9B,0x97,0x20,0x8A,0x02,0x52,0x60,0xC4,0x25,0x75}} // P4096
|
|
#endif
|
|
#if defined(BIG_ENDIAN)
|
|
{{0x40,0x02,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, // P0001
|
|
{{0x40,0x05,0xC8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, // P0002
|
|
{{0x40,0x08,0xFA,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, // P0003
|
|
{{0x40,0x0C,0x9C,0x40,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, // P0004
|
|
{{0x40,0x0F,0xC3,0x50,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, // P0005
|
|
{{0x40,0x12,0xF4,0x24,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, // P0006
|
|
{{0x40,0x16,0x98,0x96,0x80,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, // P0007
|
|
{{0x40,0x19,0xBE,0xBC,0x20,0x00,0x00,0x00,0x00,0x00, 0x00,0x00}}, // P0008
|
|
{{0x40,0x34,0x8E,0x1B,0xC9,0xBF,0x04,0x00,0x00,0x00, 0x00,0x00}}, // P0016
|
|
{{0x40,0x4E,0xD3,0xC2,0x1B,0xCE,0xCC,0xED,0xA1,0x00, 0x00,0x00}}, // P0024
|
|
{{0x40,0x69,0x9D,0xC5,0xAD,0xA8,0x2B,0x70,0xB5,0x9E, 0xF0,0x20}}, // P0032
|
|
{{0x40,0x83,0xEB,0x19,0x4F,0x8E,0x1A,0xE5,0x25,0xFD, 0x5D,0xD0}}, // P0040
|
|
{{0x40,0x9E,0xAF,0x29,0x8D,0x05,0x0E,0x43,0x95,0xD7, 0x96,0x71}}, // P0048
|
|
{{0x40,0xB9,0x82,0x81,0x8F,0x12,0x81,0xED,0x44,0xA0, 0xBF,0xF9}}, // P0056
|
|
{{0x40,0xD3,0xC2,0x78,0x1F,0x49,0xFF,0xCF,0xA6,0xD5, 0x3C,0xBF}}, // P0064
|
|
{{0x41,0xA8,0x93,0xBA,0x47,0xC9,0x80,0xE9,0x8C,0xE0, 0xC6,0x6F}}, // P0128
|
|
{{0x42,0x7C,0xE0,0x70,0xF7,0x8D,0x39,0x27,0x55,0x6B, 0x85,0xBC}}, // P0192
|
|
{{0x43,0x51,0xAA,0x7E,0xEB,0xFB,0x9D,0xF9,0xDE,0x8E, 0xDD,0xBC}}, // P0256
|
|
{{0x44,0x26,0x81,0x84,0x2F,0x29,0xF2,0xCC,0xE3,0x76, 0xE6,0xA1}}, // P0320
|
|
{{0x44,0xFA,0xC4,0xC5,0xE3,0x10,0xAE,0xF8,0xAA,0x17, 0x10,0x28}}, // P0384
|
|
{{0x45,0xCF,0x95,0x7A,0x4A,0xE1,0xEB,0xF7,0xF3,0xD4, 0xA7,0xEB}}, // P0448
|
|
{{0x46,0xA3,0xE3,0x19,0xA0,0xAE,0xA6,0x0E,0x91,0xC7, 0xCC,0x65}}, // P0512
|
|
{{0x4D,0x48,0xC9,0x76,0x75,0x86,0x81,0x75,0x0C,0x17, 0x65,0x0D}}, // P1024
|
|
{{0x53,0xED,0xB2,0xB8,0x35,0x3B,0x39,0x93,0xA7,0xE4, 0x42,0x58}}, // P1536
|
|
{{0x5A,0x92,0x9E,0x8B,0x3B,0x5D,0xC5,0x3D,0x5D,0xE5, 0xA7,0x4D}}, // P2048
|
|
{{0x61,0x37,0x8C,0xA5,0x54,0xC0,0x20,0xA1,0xF0,0xA6, 0x5D,0xFF}}, // P2560
|
|
{{0x67,0xDB,0xF9,0x89,0x5D,0x25,0xD8,0x8B,0x5A,0x8B, 0xFD,0xD1}}, // P3072
|
|
{{0x6E,0x80,0xDD,0x5D,0xC8,0xA2,0xBF,0x27,0xF3,0xF8, 0x95,0xAA}}, // P3584
|
|
{{0x75,0x25,0xC4,0x60,0x52,0x02,0x8A,0x20,0x97,0x9B, 0xC9,0x4C}} // P4096
|
|
#endif
|
|
};
|
|
|
|
static _LDBL12 _pow10neg[] = {
|
|
#if defined(LITTLE_ENDIAN)
|
|
{{0xCD,0xCC, 0xCD,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFB,0x3F}}, // N0001
|
|
{{0x71,0x3D, 0x0A,0xD7,0xA3,0x70,0x3D,0x0A,0xD7,0xA3,0xF8,0x3F}}, // N0002
|
|
{{0x5A,0x64, 0x3B,0xDF,0x4F,0x8D,0x97,0x6E,0x12,0x83,0xF5,0x3F}}, // N0003
|
|
{{0xC3,0xD3, 0x2C,0x65,0x19,0xE2,0x58,0x17,0xB7,0xD1,0xF1,0x3F}}, // N0004
|
|
{{0xD0,0x0F, 0x23,0x84,0x47,0x1B,0x47,0xAC,0xC5,0xA7,0xEE,0x3F}}, // N0005
|
|
{{0x40,0xA6, 0xB6,0x69,0x6C,0xAF,0x05,0xBD,0x37,0x86,0xEB,0x3F}}, // N0006
|
|
{{0x33,0x3D, 0xBC,0x42,0x7A,0xE5,0xD5,0x94,0xBF,0xD6,0xE7,0x3F}}, // N0007
|
|
{{0xC2,0xFD, 0xFD,0xCE,0x61,0x84,0x11,0x77,0xCC,0xAB,0xE4,0x3F}}, // N0008
|
|
{{0x2F,0x4C, 0x5B,0xE1,0x4D,0xC4,0xBE,0x94,0x95,0xE6,0xC9,0x3F}}, // N0016
|
|
{{0x92,0xC4, 0x53,0x3B,0x75,0x44,0xCD,0x14,0xBE,0x9A,0xAF,0x3F}}, // N0024
|
|
{{0xDE,0x67, 0xBA,0x94,0x39,0x45,0xAD,0x1E,0xB1,0xCF,0x94,0x3F}}, // N0032
|
|
{{0x24,0x23, 0xC6,0xE2,0xBC,0xBA,0x3B,0x31,0x61,0x8B,0x7A,0x3F}}, // N0040
|
|
{{0x61,0x55, 0x59,0xC1,0x7E,0xB1,0x53,0x7C,0x12,0xBB,0x5F,0x3F}}, // N0048
|
|
{{0xD7,0xEE, 0x2F,0x8D,0x06,0xBE,0x92,0x85,0x15,0xFB,0x44,0x3F}}, // N0056
|
|
{{0x24,0x3F, 0xA5,0xE9,0x39,0xA5,0x27,0xEA,0x7F,0xA8,0x2A,0x3F}}, // N0064
|
|
{{0x7D,0xAC, 0xA1,0xE4,0xBC,0x64,0x7C,0x46,0xD0,0xDD,0x55,0x3E}}, // N0128
|
|
{{0x63,0x7B, 0x06,0xCC,0x23,0x54,0x77,0x83,0xFF,0x91,0x81,0x3D}}, // N0192
|
|
{{0x91,0xFA, 0x3A,0x19,0x7A,0x63,0x25,0x43,0x31,0xC0,0xAC,0x3C}}, // N0256
|
|
{{0x21,0x89, 0xD1,0x38,0x82,0x47,0x97,0xB8,0x00,0xFD,0xD7,0x3B}}, // N0320
|
|
{{0xDC,0x88, 0x58,0x08,0x1B,0xB1,0xE8,0xE3,0x86,0xA6,0x03,0x3B}}, // N0384
|
|
{{0xC6,0x84, 0x45,0x42,0x07,0xB6,0x99,0x75,0x37,0xDB,0x2E,0x3A}}, // N0448
|
|
{{0x33,0x71, 0x1C,0xD2,0x23,0xDB,0x32,0xEE,0x49,0x90,0x5A,0x39}}, // N0512
|
|
{{0xA6,0x87, 0xBE,0xC0,0x57,0xDA,0xA5,0x82,0xA6,0xA2,0xB5,0x32}}, // N1024
|
|
{{0xE2,0x68, 0xB2,0x11,0xA7,0x52,0x9F,0x44,0x59,0xB7,0x10,0x2C}}, // N1536
|
|
{{0x25,0x49, 0xE4,0x2D,0x36,0x34,0x4F,0x53,0xAE,0xCE,0x6B,0x25}}, // N2048
|
|
{{0x8F,0x59, 0x04,0xA4,0xC0,0xDE,0xC2,0x7D,0xFB,0xE8,0xC6,0x1E}}, // N2560
|
|
{{0x9E,0xE7, 0x88,0x5A,0x57,0x91,0x3C,0xBF,0x50,0x83,0x22,0x18}}, // N3072
|
|
{{0x4E,0x4B, 0x65,0x62,0xFD,0x83,0x8F,0xAF,0x06,0x94,0x7D,0x11}}, // N3584
|
|
{{0xE4,0x2D, 0xDE,0x9F,0xCE,0xD2,0xC8,0x04,0xDD,0xA6,0xD8,0x0A}} // N4096
|
|
#endif
|
|
#if defined(BIG_ENDIAN)
|
|
{{0x3F,0xFB,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCD, 0xCC,0xCD}}, // N0001
|
|
{{0x3F,0xF8,0xA3,0xD7,0x0A,0x3D,0x70,0xA3,0xD7,0x0A, 0x3D,0x71}}, // N0002
|
|
{{0x3F,0xF5,0x83,0x12,0x6E,0x97,0x8D,0x4F,0xDF,0x3B, 0x64,0x5A}}, // N0003
|
|
{{0x3F,0xF1,0xD1,0xB7,0x17,0x58,0xE2,0x19,0x65,0x2C, 0xD3,0xC3}}, // N0004
|
|
{{0x3F,0xEE,0xA7,0xC5,0xAC,0x47,0x1B,0x47,0x84,0x23, 0x0F,0xD0}}, // N0005
|
|
{{0x3F,0xEB,0x86,0x37,0xBD,0x05,0xAF,0x6C,0x69,0xB6, 0xA6,0x40}}, // N0006
|
|
{{0x3F,0xE7,0xD6,0xBF,0x94,0xD5,0xE5,0x7A,0x42,0xBC, 0x3D,0x33}}, // N0007
|
|
{{0x3F,0xE4,0xAB,0xCC,0x77,0x11,0x84,0x61,0xCE,0xFD, 0xFD,0xC2}}, // N0008
|
|
{{0x3F,0xC9,0xE6,0x95,0x94,0xBE,0xC4,0x4D,0xE1,0x5B, 0x4C,0x2F}}, // N0016
|
|
{{0x3F,0xAF,0x9A,0xBE,0x14,0xCD,0x44,0x75,0x3B,0x53, 0xC4,0x92}}, // N0024
|
|
{{0x3F,0x94,0xCF,0xB1,0x1E,0xAD,0x45,0x39,0x94,0xBA, 0x67,0xDE}}, // N0032
|
|
{{0x3F,0x7A,0x8B,0x61,0x31,0x3B,0xBA,0xBC,0xE2,0xC6, 0x23,0x24}}, // N0040
|
|
{{0x3F,0x5F,0xBB,0x12,0x7C,0x53,0xB1,0x7E,0xC1,0x59, 0x55,0x61}}, // N0048
|
|
{{0x3F,0x44,0xFB,0x15,0x85,0x92,0xBE,0x06,0x8D,0x2F, 0xEE,0xD7}}, // N0056
|
|
{{0x3F,0x2A,0xA8,0x7F,0xEA,0x27,0xA5,0x39,0xE9,0xA5, 0x3F,0x24}}, // N0064
|
|
{{0x3E,0x55,0xDD,0xD0,0x46,0x7C,0x64,0xBC,0xE4,0xA1, 0xAC,0x7D}}, // N0128
|
|
{{0x3D,0x81,0x91,0xFF,0x83,0x77,0x54,0x23,0xCC,0x06, 0x7B,0x63}}, // N0192
|
|
{{0x3C,0xAC,0xC0,0x31,0x43,0x25,0x63,0x7A,0x19,0x3A, 0xFA,0x91}}, // N0256
|
|
{{0x3B,0xD7,0xFD,0x00,0xB8,0x97,0x47,0x82,0x38,0xD1, 0x89,0x21}}, // N0320
|
|
{{0x3B,0x03,0xA6,0x86,0xE3,0xE8,0xB1,0x1B,0x08,0x58, 0x88,0xDC}}, // N0384
|
|
{{0x3A,0x2E,0xDB,0x37,0x75,0x99,0xB6,0x07,0x42,0x45, 0x84,0xC6}}, // N0448
|
|
{{0x39,0x5A,0x90,0x49,0xEE,0x32,0xDB,0x23,0xD2,0x1C, 0x71,0x33}}, // N0512
|
|
{{0x32,0xB5,0xA2,0xA6,0x82,0xA5,0xDA,0x57,0xC0,0xBE, 0x87,0xA6}}, // N1024
|
|
{{0x2C,0x10,0xB7,0x59,0x44,0x9F,0x52,0xA7,0x11,0xB2, 0x68,0xE2}}, // N1536
|
|
{{0x25,0x6B,0xCE,0xAE,0x53,0x4F,0x34,0x36,0x2D,0xE4, 0x49,0x25}}, // N2048
|
|
{{0x1E,0xC6,0xE8,0xFB,0x7D,0xC2,0xDE,0xC0,0xA4,0x04, 0x59,0x8F}}, // N2560
|
|
{{0x18,0x22,0x83,0x50,0xBF,0x3C,0x91,0x57,0x5A,0x88, 0xE7,0x9E}}, // N3072
|
|
{{0x11,0x7D,0x94,0x06,0xAF,0x8F,0x83,0xFD,0x62,0x65, 0x4B,0x4E}}, // N3584
|
|
{{0x0A,0xD8,0xA6,0xDD,0x04,0xC8,0xD2,0xCE,0x9F,0xDE, 0x2D,0xE4}} // N4096
|
|
#endif
|
|
};
|
|
|
|
_LDBL12 *pow_10p = _pow10pos - 8;
|
|
if (pow == 0) {
|
|
return;
|
|
}
|
|
if (pow < 0) {
|
|
pow = -pow;
|
|
pow_10p = _pow10neg - 8;
|
|
}
|
|
|
|
while (pow) {
|
|
pow_10p += 7;
|
|
int last3 = pow & 0x7; // the 3 LSBits of pow
|
|
pow >>= 3;
|
|
if (last3 == 0) {
|
|
continue;
|
|
}
|
|
_LDBL12 *py = pow_10p + last3;
|
|
|
|
// do an exact 12 byte multiplication
|
|
if (*U_XT_12(py) >= 0x8000) {
|
|
|
|
_LDBL12 unround = *py; // copy number
|
|
(*UL_MANLO_12(&unround))--; // unround adjacent byte
|
|
py = &unround; // point to new operand
|
|
}
|
|
ld12mul(pld12, py);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Purpose:
|
|
// _ecvt converts value to a null terminated string of
|
|
// UNICODE digits, and returns a pointer to the result.
|
|
// The position of the decimal point relative to the
|
|
// beginning of the string is stored indirectly through
|
|
// decpt, where negative means to the left of the returned
|
|
// digits. If the sign of the result is negative, the
|
|
// bool pointed to by negative is set to true, otherwise it is
|
|
// false. The low order digit is rounded.
|
|
//
|
|
// Entry:
|
|
// double value - number to be converted
|
|
// int digits - number of digits after decimal point
|
|
//
|
|
// Exit:
|
|
// returns pointer to the character representation of value.
|
|
// int *decpt - pointer to int with position of decimal point
|
|
// bool *negative - pointer to bool for if value < 0.
|
|
//
|
|
bool Class_System_Number::g_ecvt(double value,
|
|
int digits,
|
|
ClassVector_bartok_char * buf,
|
|
int *decpt,
|
|
bool *negative)
|
|
{
|
|
if ((uint32)digits > buf->length - 1) {
|
|
digits = buf->length - 1;
|
|
}
|
|
bartok_char *man = buf->values;
|
|
|
|
// useful constants (see algorithm explanation below)
|
|
const uint16 log2hi = 0x4d10;
|
|
const uint16 log2lo = 0x4d;
|
|
const uint16 log4hi = 0x9a;
|
|
const uint32 c = 0x134312f4;
|
|
#if defined(LITTLE_ENDIAN)
|
|
_LDBL12 ld12_one_tenth = {
|
|
{0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xfb,0x3f}
|
|
};
|
|
#endif
|
|
#if defined(BIG_ENDIAN)
|
|
_LDBL12 ld12_one_tenth = {
|
|
{0x3f,0xfb,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc}
|
|
};
|
|
#endif
|
|
|
|
// convert the double into a 12-byte long double.
|
|
_LDBL12 ld12;
|
|
dtold12(&ld12, &value);
|
|
|
|
uint16 expn = *U_EXP_12(&ld12);
|
|
uint32 manhi = *UL_MANHI_12(&ld12);
|
|
uint32 manlo = *UL_MANLO_12(&ld12);
|
|
uint16 sign = expn & MSB_USHORT;
|
|
expn &= 0x7fff;
|
|
*U_EXP_12(&ld12) = expn;
|
|
|
|
*negative = (sign != 0);
|
|
|
|
if (expn == 0 && manhi == 0 && manlo == 0) {
|
|
zero_fos:
|
|
*decpt = 0;
|
|
*negative = false;
|
|
man[0] = '0';
|
|
man[1] = '\0';
|
|
return true;
|
|
}
|
|
|
|
if (expn == 0x7fff) {
|
|
man[0] = '\0';
|
|
*decpt = SCALE_NAN;
|
|
if (_IS_MAN_INF(sign, manhi, manlo)) {
|
|
*decpt = SCALE_INF; // infinity
|
|
}
|
|
return false;
|
|
}
|
|
else {
|
|
// * Algorithm for the decoding of a valid real number x *
|
|
//
|
|
// In the following INT(r) is the largest integer less than or
|
|
// equal to r (i.e. r rounded toward -infinity). We want a result
|
|
// r equal to 1 + log(x), because then x = mantissa
|
|
// * 10^(INT(r)) so that .1 <= mantissa < 1. Unfortunately,
|
|
// we cannot compute s exactly so we must alter the procedure
|
|
// slightly. We will instead compute an estimate r of 1 +
|
|
// log(x) which is always low. This will either result
|
|
// in the correctly normalized number on the top of the stack
|
|
// or perhaps a number which is a factor of 10 too large. We
|
|
// will then check to see that if x is larger than one
|
|
// and if so multiply x by 1/10.
|
|
//
|
|
// We will use a low precision (fixed point 24 bit) estimate
|
|
// of of 1 + log base 10 of x. We have approximately .mm
|
|
// * 2^hhll on the top of the stack where m, h, and l represent
|
|
// hex digits, mm represents the high 2 hex digits of the
|
|
// mantissa, hh represents the high 2 hex digits of the exponent,
|
|
// and ll represents the low 2 hex digits of the exponent. Since
|
|
// .mm is a truncated representation of the mantissa, using it
|
|
// in this monotonically increasing polynomial approximation
|
|
// of the logarithm will naturally give a low result. Let's
|
|
// derive a formula for a lower bound r on 1 + log(x):
|
|
//
|
|
// .4D104D42H < log(2)=.30102999...(base 10) < .4D104D43H
|
|
// .9A20H < log(4)=.60205999...(base 10) < .9A21H
|
|
//
|
|
// 1/2 <= .mm < 1
|
|
// ==> log(.mm) >= .mm * log(4) - log(4)
|
|
//
|
|
// Substituting in truncated hex constants in the formula above
|
|
// gives r = 1 + .4D104DH * hhll. + .9AH * .mm - .9A21H. Now
|
|
// multiplication of hex digits 5 and 6 of log(2) by ll has an
|
|
// insignificant effect on the first 24 bits of the result so
|
|
// it will not be calculated. This gives the expression r =
|
|
// 1 + .4D10H * hhll. + .4DH * .hh + .9A * .mm - .9A21H.
|
|
// Finally we must add terms to our formula to subtract out the
|
|
// effect of the exponent bias. We obtain the following formula:
|
|
//
|
|
// (implied decimal point)
|
|
// < >.< >
|
|
// |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|0|0|0|0|0|0|0|0|0|0|
|
|
// |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|
|
|
// + < 1 >
|
|
// + < .4D10H * hhll. >
|
|
// + < .00004DH * hh00. >
|
|
// + < .9AH * .mm >
|
|
// - < .9A21H >
|
|
// - < .4D10H * 3FFEH >
|
|
// - < .00004DH * 3F00H >
|
|
//
|
|
// ==> r = .4D10H * hhll. + .4DH * .hh + .9AH * .mm - 1343.12F4H
|
|
//
|
|
// The difference between the lower bound r and the upper bound
|
|
// s is calculated as follows:
|
|
//
|
|
// .937EH < 1/ln(10)-log(1/ln(4))=.57614993...(base 10) < .937FH
|
|
//
|
|
// 1/2 <= .mm < 1
|
|
// ==> log(.mm) <= .mm * log(4) - [1/ln(10) - log(1/ln(4))]
|
|
//
|
|
// so tentatively s = r + log(4) - [1/ln(10) - log(1/ln(4))],
|
|
// but we must also add in terms to ensure we will have an upper
|
|
// bound even after the truncation of various values. Because
|
|
// log(2) * hh00. is truncated to .4D104DH * hh00. we must
|
|
// add .0043H, because log(2) * ll. is truncated to .4D10H *
|
|
// ll. we must add .0005H, because <mantissa> * log(4) is
|
|
// truncated to .mm * .9AH we must add .009AH and .0021H.
|
|
//
|
|
// Thus s = r - .937EH + .9A21H + .0043H + .0005H + .009AH + .0021H
|
|
// = r + .07A6H
|
|
// ==> s = .4D10H * hhll. + .4DH * .hh + .9AH * .mm - 1343.0B4EH
|
|
//
|
|
// r is equal to 1 + log(x) more than (10000H - 7A6H) /
|
|
// 10000H = 97% of the time.
|
|
//
|
|
// In the above formula, a uint32 is use to accommodate r, and
|
|
// there is an implied decimal point in the middle.
|
|
|
|
uint16 hh = expn >> 8;
|
|
uint16 ll = expn & (uint16)0xff;
|
|
uint16 mm = (uint16) (manhi >> 24); // the two most significant bytes of the mantissa.
|
|
int32 r = (int32)log2hi*(int32)expn + log2lo*hh + log4hi*mm - c;
|
|
// the corresponding power of 10
|
|
int32 ir = (int16)(r >> 16); // ir = floor(r)
|
|
|
|
// We stated that we wanted to normalize x so that
|
|
//
|
|
// .1 <= x < 1
|
|
//
|
|
// This was a slight oversimplification. Actually we want a
|
|
// number which when rounded to 16 significant digits is in the
|
|
// desired range. To do this we must normalize x so that
|
|
//
|
|
// .1 - 5*10^(-18) <= x < 1 - 5*10^(-17)
|
|
//
|
|
// and then round.
|
|
//
|
|
// If we had f = INT(1+log(x)) we could multiply by 10^(-f)
|
|
// to get x into the desired range. We do not quite have
|
|
// f but we do have INT(r) from the last step which is equal
|
|
// to f 97% of the time and 1 less than f the rest of the time.
|
|
// We can multiply by 10^-[INT(r)] and if the result is greater
|
|
// than 1 - 5*10^(-17) we can then multiply by 1/10. This final
|
|
// result will lie in the proper range.
|
|
|
|
// multiply by 10^(-ir)
|
|
multtenpow12(&ld12,-ir);
|
|
|
|
// if ld12 >= 1.0 then divide by 10.0
|
|
if (*U_EXP_12(&ld12) >= 0x3fff) {
|
|
ir++;
|
|
ld12mul(&ld12,&ld12_one_tenth);
|
|
}
|
|
|
|
*decpt = ir;
|
|
|
|
int ub_exp = *U_EXP_12(&ld12) - 0x3ffe; // unbias exponent
|
|
*U_EXP_12(&ld12) = 0;
|
|
|
|
// Now the mantissa has to be converted to fixed point.
|
|
// Then we will use the MSB of ld12 for generating
|
|
// the decimal digits. The next 11 bytes will hold
|
|
// the mantissa (after it has been converted to
|
|
// fixed point).
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
shl_12(&ld12);
|
|
// make space for an extra byte, in case we shift right later.
|
|
}
|
|
if (ub_exp < 0) {
|
|
int shift_count = (-ub_exp) & 0xff;
|
|
for (; shift_count > 0; shift_count--) {
|
|
shr_12(&ld12);
|
|
}
|
|
}
|
|
|
|
bartok_char *p = man;
|
|
for (int digcount = digits + 1; digcount > 0; digcount--) {
|
|
_LDBL12 tmp12 = ld12;
|
|
shl_12(&ld12);
|
|
shl_12(&ld12);
|
|
add_12(&ld12,&tmp12);
|
|
shl_12(&ld12); // ld12 *= 10
|
|
|
|
// Now we have the first decimal digit in the most significant byte of exponent
|
|
*p++ = (char) (*UCHAR_12(&ld12,11) + '0');
|
|
*UCHAR_12(&ld12,11) = 0;
|
|
}
|
|
|
|
bartok_char round = *(--p);
|
|
p--;
|
|
// p points now to the last character of the string excluding the rounding digit.
|
|
if (round >= '5') {
|
|
// look for a non-9 digit starting from the end of string
|
|
for (; p >= man && *p == '9'; p--) {
|
|
*p = '0';
|
|
}
|
|
if (p < man) {
|
|
p++;
|
|
(*decpt)++;
|
|
}
|
|
(*p)++;
|
|
}
|
|
else {
|
|
// we probably don't want to truncate all of the zeros!
|
|
for (; p >= man && *p == '0'; p--) {
|
|
// remove extra zeros;
|
|
}
|
|
if (p < man) {
|
|
goto zero_fos;
|
|
}
|
|
}
|
|
man[(p - man + 1)] = '\0';
|
|
return true;
|
|
}
|
|
}
|
|
|
|
double Class_System_Number::g_atof(struct ClassVector_uint8 *a)
|
|
{
|
|
Assert(!"atof");
|
|
return 0;
|
|
}
|
|
//
|
|
///////////////////////////////////////////////////////////////// End of File.
|