183 lines
4.1 KiB
C
183 lines
4.1 KiB
C
/***
|
|
*mantold.c - conversion of a decimal mantissa to _LDBL12
|
|
*
|
|
* Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* Conversion of a decimal mantissa into _LDBL12 format (i.e. long
|
|
* double with two additional bytes of significand)
|
|
*
|
|
*Revision History:
|
|
* 7-17-91 GDP Initial version (ported from assembly)
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <cv.h>
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
*int _CALLTYPE5 __addl(u_long x, u_long y, u_long *sum) - u_long addition
|
|
*
|
|
*Purpose: add two u_long numbers and return carry
|
|
*
|
|
*Entry: u_long x, u_long y : the numbers to be added
|
|
* u_long *sum : where to store the result
|
|
*
|
|
*Exit: *sum receives the value of x+y
|
|
* the value of the carry is returned
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
int _CALLTYPE5 __addl(u_long x, u_long y, u_long *sum)
|
|
{
|
|
u_long r;
|
|
int carry=0;
|
|
r = x+y;
|
|
if (r < x || r < y)
|
|
carry++;
|
|
*sum = r;
|
|
return carry;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
*void _CALLTYPE5 __add_12(_LDBL12 *x, _LDBL12 *y) - _LDBL12 addition
|
|
*
|
|
*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
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
void _CALLTYPE5 __add_12(_LDBL12 *x, _LDBL12 *y)
|
|
{
|
|
int c0,c1,c2;
|
|
c0 = __addl(*UL_LO_12(x),*UL_LO_12(y),UL_LO_12(x));
|
|
if (c0) {
|
|
c1 = __addl(*UL_MED_12(x),(u_long)1,UL_MED_12(x));
|
|
if (c1) {
|
|
(*UL_HI_12(x))++;
|
|
}
|
|
}
|
|
c2 = __addl(*UL_MED_12(x),*UL_MED_12(y),UL_MED_12(x));
|
|
if (c2) {
|
|
(*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));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
*void _CALLTYPE5 __shl_12(_LDBL12 *x) - _LDBL12 shift left
|
|
*void _CALLTYPE5 __shr_12(_LDBL12 *x) - _LDBL12 shift right
|
|
*
|
|
*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)
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
void _CALLTYPE5 __shl_12(_LDBL12 *p)
|
|
{
|
|
u_long c0,c1;
|
|
|
|
c0 = *UL_LO_12(p) & MSB_ULONG ? 1: 0;
|
|
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;
|
|
}
|
|
|
|
void _CALLTYPE5 __shr_12(_LDBL12 *p)
|
|
{
|
|
u_long c2,c1;
|
|
c2 = *UL_HI_12(p) & 0x1 ? MSB_ULONG: 0;
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
*void _CALLTYPE5 __mtold12(char *manptr,unsigned manlen,_LDBL12 *ld12) -
|
|
* convert a mantissa into a _LDBL12
|
|
*
|
|
*Purpose: convert a mantissa into a _LDBL12. The mantissa is
|
|
* in the form of an array of manlen BCD digits and is
|
|
* considered to be an integer.
|
|
*
|
|
*Entry: manptr: the array containing the packed BCD digits of the mantissa
|
|
* manlen: the size of the array
|
|
* ld12: a pointer to the long double where the result will be stored
|
|
*
|
|
*Exit:
|
|
* ld12 gets the result of the conversion
|
|
*
|
|
*Exceptions:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
void _CALLTYPE5 __mtold12(char *manptr,
|
|
unsigned manlen,
|
|
_LDBL12 *ld12)
|
|
{
|
|
_LDBL12 tmp;
|
|
u_short expn = LD_BIASM1+80;
|
|
|
|
*UL_LO_12(ld12) = 0;
|
|
*UL_MED_12(ld12) = 0;
|
|
*UL_HI_12(ld12) = 0;
|
|
for (;manlen>0;manlen--,manptr++){
|
|
tmp = *ld12;
|
|
__shl_12(ld12);
|
|
__shl_12(ld12);
|
|
__add_12(ld12,&tmp);
|
|
__shl_12(ld12); /* multiply by 10 */
|
|
*UL_LO_12(&tmp) = (u_long)*manptr;
|
|
*UL_MED_12(&tmp) = 0;
|
|
*UL_HI_12(&tmp) = 0;
|
|
__add_12(ld12,&tmp);
|
|
}
|
|
|
|
/* normalize mantissa -- first shift word by word */
|
|
while (*UL_HI_12(ld12) == 0) {
|
|
*UL_HI_12(ld12) = *UL_MED_12(ld12) >> 16;
|
|
*UL_MED_12(ld12) = *UL_MED_12(ld12) << 16 | *UL_LO_12(ld12) >> 16;
|
|
(*UL_LO_12(ld12)) <<= 16;
|
|
expn -= 16;
|
|
}
|
|
while ((*UL_HI_12(ld12) & 0x8000) == 0) {
|
|
__shl_12(ld12);
|
|
expn--;
|
|
}
|
|
*U_EXP_12(ld12) = expn;
|
|
}
|