Esempio n. 1
0
/** Multiply two single-precision floats.
 *
 * @param a First input operand.
 * @param b Second input operand.
 *
 * @return Result of multiplication.
 *
 */
float32 mul_float32(float32 a, float32 b)
{
	float32 result;
	uint64_t frac1, frac2;
	int32_t exp;
	
	result.parts.sign = a.parts.sign ^ b.parts.sign;
	
	if (is_float32_nan(a) || is_float32_nan(b)) {
		/* TODO: fix SigNaNs */
		if (is_float32_signan(a)) {
			result.parts.fraction = a.parts.fraction;
			result.parts.exp = a.parts.exp;
			return result;
		}
		if (is_float32_signan(b)) { /* TODO: fix SigNaN */
			result.parts.fraction = b.parts.fraction;
			result.parts.exp = b.parts.exp;
			return result;
		}
		/* set NaN as result */
		result.bin = FLOAT32_NAN;
		return result;
	}
	
	if (is_float32_infinity(a)) {
		if (is_float32_zero(b)) {
			/* FIXME: zero * infinity */
			result.bin = FLOAT32_NAN;
			return result;
		}
		result.parts.fraction = a.parts.fraction;
		result.parts.exp = a.parts.exp;
		return result;
	}
	
	if (is_float32_infinity(b)) {
		if (is_float32_zero(a)) {
			/* FIXME: zero * infinity */
			result.bin = FLOAT32_NAN;
			return result;
		}
		result.parts.fraction = b.parts.fraction;
		result.parts.exp = b.parts.exp;
		return result;
	}
	
	/* exp is signed so we can easy detect underflow */
	exp = a.parts.exp + b.parts.exp;
	exp -= FLOAT32_BIAS;
	
	if (exp >= FLOAT32_MAX_EXPONENT) {
		/* FIXME: overflow */
		/* set infinity as result */
		result.bin = FLOAT32_INF;
		result.parts.sign = a.parts.sign ^ b.parts.sign;
		return result;
	}
	
	if (exp < 0) { 
		/* FIXME: underflow */
		/* return signed zero */
		result.parts.fraction = 0x0;
		result.parts.exp = 0x0;
		return result;
	}
	
	frac1 = a.parts.fraction;
	if (a.parts.exp > 0) {
		frac1 |= FLOAT32_HIDDEN_BIT_MASK;
	} else {
		++exp;
	}
	
	frac2 = b.parts.fraction;
	
	if (b.parts.exp > 0) {
		frac2 |= FLOAT32_HIDDEN_BIT_MASK;
	} else {
		++exp;
	}
	
	frac1 <<= 1; /* one bit space for rounding */
	
	frac1 = frac1 * frac2;
	
	/* round and return */
	while ((exp < FLOAT32_MAX_EXPONENT) &&
	    (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 2)))) {
		/* 23 bits of fraction + one more for hidden bit (all shifted 1 bit left) */
		++exp;
		frac1 >>= 1;
	}
	
	/* rounding */
	/* ++frac1; FIXME: not works - without it is ok */
	frac1 >>= 1; /* shift off rounding space */
	
	if ((exp < FLOAT32_MAX_EXPONENT) &&
	    (frac1 >= (1 << (FLOAT32_FRACTION_SIZE + 1)))) {
		++exp;
		frac1 >>= 1;
	}
Esempio n. 2
0
/** Add two single-precision floats with the same sign.
 *
 * @param a First input operand.
 * @param b Second input operand.
 * @return Result of addition.
 */
float32 add_float32(float32 a, float32 b)
{
	int expdiff;
	uint32_t exp1, exp2, frac1, frac2;
	
	expdiff = a.parts.exp - b.parts.exp;
	if (expdiff < 0) {
		if (is_float32_nan(b)) {
			/* TODO: fix SigNaN */
			if (is_float32_signan(b)) {
			}

			return b;
		}
		
		if (b.parts.exp == FLOAT32_MAX_EXPONENT) { 
			return b;
		}
		
		frac1 = b.parts.fraction;
		exp1 = b.parts.exp;
		frac2 = a.parts.fraction;
		exp2 = a.parts.exp;
		expdiff *= -1;
	} else {
		if ((is_float32_nan(a)) || (is_float32_nan(b))) {
			/* TODO: fix SigNaN */
			if (is_float32_signan(a) || is_float32_signan(b)) {
			}
			return (is_float32_nan(a) ? a : b);
		}
		
		if (a.parts.exp == FLOAT32_MAX_EXPONENT) { 
			return a;
		}
		
		frac1 = a.parts.fraction;
		exp1 = a.parts.exp;
		frac2 = b.parts.fraction;
		exp2 = b.parts.exp;
	}
	
	if (exp1 == 0) {
		/* both are denormalized */
		frac1 += frac2;
		if (frac1 & FLOAT32_HIDDEN_BIT_MASK ) {
			/* result is not denormalized */
			a.parts.exp = 1;
		}
		a.parts.fraction = frac1;
		return a;
	}
	
	frac1 |= FLOAT32_HIDDEN_BIT_MASK; /* add hidden bit */

	if (exp2 == 0) {
		/* second operand is denormalized */
		--expdiff;
	} else {
		/* add hidden bit to second operand */
		frac2 |= FLOAT32_HIDDEN_BIT_MASK; 
	}
	
	/* create some space for rounding */
	frac1 <<= 6;
	frac2 <<= 6;
	
	if (expdiff < (FLOAT32_FRACTION_SIZE + 2) ) {
		frac2 >>= expdiff;
		frac1 += frac2;
	} else {
Esempio n. 3
0
/** Divide two single-precision floats.
 *
 * @param a Nominator.
 * @param b Denominator.
 *
 * @return Result of division.
 *
 */
float32 div_float32(float32 a, float32 b)
{
	float32 result;
	int32_t aexp, bexp, cexp;
	uint64_t afrac, bfrac, cfrac;
	
	result.parts.sign = a.parts.sign ^ b.parts.sign;
	
	if (is_float32_nan(a)) {
		if (is_float32_signan(a)) {
			// FIXME: SigNaN
		}
		/* NaN */
		return a;
	}
	
	if (is_float32_nan(b)) {
		if (is_float32_signan(b)) {
			// FIXME: SigNaN
		}
		/* NaN */
		return b;
	}
	
	if (is_float32_infinity(a)) {
		if (is_float32_infinity(b)) {
			/*FIXME: inf / inf */
			result.bin = FLOAT32_NAN;
			return result;
		}
		/* inf / num */
		result.parts.exp = a.parts.exp;
		result.parts.fraction = a.parts.fraction;
		return result;
	}
	
	if (is_float32_infinity(b)) {
		if (is_float32_zero(a)) {
			/* FIXME 0 / inf */
			result.parts.exp = 0;
			result.parts.fraction = 0;
			return result;
		}
		/* FIXME: num / inf*/
		result.parts.exp = 0;
		result.parts.fraction = 0;
		return result;
	}
	
	if (is_float32_zero(b)) {
		if (is_float32_zero(a)) {
			/*FIXME: 0 / 0*/
			result.bin = FLOAT32_NAN;
			return result;
		}
		/* FIXME: division by zero */
		result.parts.exp = 0;
		result.parts.fraction = 0;
		return result;
	}
	
	afrac = a.parts.fraction;
	aexp = a.parts.exp;
	bfrac = b.parts.fraction;
	bexp = b.parts.exp;
	
	/* denormalized numbers */
	if (aexp == 0) {
		if (afrac == 0) {
			result.parts.exp = 0;
			result.parts.fraction = 0;
			return result;
		}
		
		/* normalize it*/
		afrac <<= 1;
		/* afrac is nonzero => it must stop */
		while (!(afrac & FLOAT32_HIDDEN_BIT_MASK)) {
			afrac <<= 1;
			aexp--;
		}
	}
	
	if (bexp == 0) {
		bfrac <<= 1;
		/* bfrac is nonzero => it must stop */
		while (!(bfrac & FLOAT32_HIDDEN_BIT_MASK)) {
			bfrac <<= 1;
			bexp--;
		}
	}
	
	afrac = (afrac | FLOAT32_HIDDEN_BIT_MASK) << (32 - FLOAT32_FRACTION_SIZE - 1);
	bfrac = (bfrac | FLOAT32_HIDDEN_BIT_MASK) << (32 - FLOAT32_FRACTION_SIZE);
	
	if (bfrac <= (afrac << 1)) {
		afrac >>= 1;
		aexp++;
	}