windows-nt/Source/XPSP1/NT/base/crts/fpw32/conv/mantold.c

183 lines
4.1 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/***
*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;
}