#define clear_Cx() (I387.swd &= ~0x4500) /* reset C0,C3,C2 */
static void normalize(temp_real * a)
{
int i = a->exponent & 0x7fff;
int sign = a->exponent & 0x8000;
if (!(a->a || a->b)) { /* zero */
a->exponent = 0;
return;
}
/*
Zero 0/1 000...0 0.000...0
Denormalized finite 0/1 000...0 0.XXX...X (X:不全为0)
Normalized finite 0/1 YYY...Y 1.XXX...X (Y:不全为0或1)
Infinite 0/1 111...1 1.000...0
SNaN 0/1 111...1 1.0XX...X (X:不全为0)
QNaN 0/1 111...1 1.1XX...X
Pseudo denormal 0/1 000...0 1.XXX...X
Pseudo normal 0/1 YYY...Y 0.XXX...X (Y:不全为0或1)
Pseudo infinite 0/1 111...1 0.000...0
Pseudo SNaN 0/1 111...1 0.0XX...X (X:不全为0)
Pseudo QNaN 0/1 111...1 0.1XX...X
*/
while (i && a->b >= 0) { /* 它的目的是将bit63规范化为1,
通过自己加自己(即向左移1位)来实现,注意指数部分得对应减1 */
i--;
__asm__("addl %0,%0 ; adcl %1,%1"
:"=r" (a->a),"=r" (a->b)
:"0" (a->a),"1" (a->b));
}
a->exponent = i | sign;
}
void ftst(const temp_real * a) /* 和0.0比较 */
{
temp_real b;
clear_Cx();
b = *a;
normalize(&b);
/*
condition C3 C2 C0
> 0 0 0
< 0 0 1
= 1 0 0
*/
if (b.a || b.b || b.exponent) { /* 其实a.a和a.b都为0时,指数必然为0 */
if (b.exponent < 0)
set_C0(); /* < 0.0 */
} else
set_C3(); /* = 0.0 */
}
void fcom(const temp_real * src1, const temp_real * src2)
{
temp_real a;
a = *src1;
a.exponent ^= 0x8000;
fadd(&a,src2,&a); /* a = src2 - src1 */
ftst(&a); /* a和0比较 */
}
void fucom(const temp_real * src1, const temp_real * src2)
{
fcom(src1,src2);
}
Linux 0.12 OS. math - compare.c
最新推荐文章于 2022-01-01 21:44:10 发布