#define BITSHIFT 5 /* additional bit shift to avoid rounding errors */
/* add: returns z which is the sum of x and y */
void add(float *zp, const float *xp, const float *yp)
{
unsigned long x, sx, ex, fx;
unsigned long y, sy, ey, fy;
unsigned long z, sz, ez, fz;
int d, p;
/* get the bit pattern of each floting-point */
x = *(unsigned long *)xp;
y = *(unsigned long *)yp;
/* sign */
sx = x >> 31;
sy = y >> 31;
/* exponential part */
ex = (x & 0x7fffffffUL) >> 23;
ey = (y & 0x7fffffffUL) >> 23;
/* fractional part */
fx = (x & 0x007fffffUL) | (1UL << 23);
fy = (y & 0x007fffffUL) | (1UL << 23);
/* additional bit shift to avoid rounding errors */
fx <<= BITSHIFT;
fy <<= BITSHIFT;
/* shift the bits of fractional part to conform the exponential part.
This may cause a round error. */
d = ex - ey;
if (d > 0) {
if (d > 24)
fy = 0;
else
fy >>= d;
ez = ex;
} else if (d) { /* d < 0 */
d = -d;
if (d > 24)
fx = 0;
else
fx >>= d;
ez = ey;
} else {
ez = ex;
}
/* convert negative numbers in two-complement number representation */
if (sx)
fx = ~fx + 1;
if (sy)
fy = ~fy + 1;
/* obtain the sum of fx and fy */
fz = fx + fy;
/* zero check */
if (fz) {
/* obtain the sign and convert negative numbers into positive */
sz = fz >> 31;
if (sz)
fz = ~(fz - 1);
/* adjust exponential part so that the 1st 1-bit occurs at 23rd position from the right */
for (d = 31; d >= 0 && ((fz >> d) & 1) == 0; d--)
;
if ((p = d - 23 - BITSHIFT) > 0) {
fz >>= p;
ez += p;
} else if (p) { /* p < 0 */
p = -p;
fz <<= p;
ez -= p;
}
/* take off the additional bit shift and round the last bit */
fz = (fz >> BITSHIFT) + ((fz >> (BITSHIFT-1)) & 1);
/* overflow check */
if (ez >= 0xffUL)
fz = 0UL;
/* build the complete an IEEE 754 single precision value */
z = (sz << 31) | ((ez & 0x000000ffUL) << 23) | (fz & 0x007fffffUL);
} else {
z = 0UL;
}
/* set the value */
*zp = *(float*)&z;
}
最終更新:2008年03月11日 23:27