|
|
/***
*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; }
|