//////////////////////////////////////////////////////////////////////////////// // // 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 * 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.