Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

220 lines
3.5 KiB

#define IMCW_RC 0x00000003
#define IRC_CHOP 0x00000001
#define IRC_UP 0x00000002
#define IRC_DOWN 0x00000003
#define IRC_NEAR 0x00000000
#define fTrue 1
#define fFalse 0
unsigned int _statfp(void);
unsigned long rgconst[32] = { 0x80000000,
0xc0000000,
0xe0000000,
0xf0000000,
0xf8000000,
0xfc000000,
0xfe000000,
0xff000000,
0xff800000,
0xffc00000,
0xffe00000,
0xfff00000,
0xfff80000,
0xfffc0000,
0xfffe0000,
0xffff0000,
0xffff8000,
0xffffc000,
0xffffe000,
0xfffff000,
0xfffff800,
0xfffffc00,
0xfffffe00,
0xffffff00,
0xffffff80,
0xffffffc0,
0xffffffe0,
0xfffffff0,
0xfffffff8,
0xfffffffc,
0xfffffffe,
0xffffffff,
};
unsigned long rgconst2[32] = { 0x80000000,
0x40000000,
0x20000000,
0x10000000,
0x08000000,
0x04000000,
0x02000000,
0x01000000,
0x00800000,
0x00400000,
0x00200000,
0x00100000,
0x00080000,
0x00040000,
0x00020000,
0x00010000,
0x00008000,
0x00004000,
0x00002000,
0x00001000,
0x00000800,
0x00000400,
0x00000200,
0x00000100,
0x00000080,
0x00000040,
0x00000020,
0x00000010,
0x00000008,
0x00000004,
0x00000002,
0x00000001,
};
double _frnd(double x)
{
union {
unsigned long rg[2];
double db;
} _db;
short sign, exp;
int roundmode;
int fROUNDUP=fFalse;
_db.db = x;
roundmode = _statfp()&IMCW_RC;
sign = (short)((_db.rg[0] & 0x80000000)>>31);
exp = (short)((_db.rg[0] & 0x7ff00000)>>20);
if (sign && roundmode == IRC_DOWN)
{
roundmode = IRC_UP;
}
else if (sign && roundmode == IRC_UP)
{
roundmode = IRC_DOWN;
}
if (exp > 0 && exp < 2047)
{
//normalized
exp = exp -1023;
if (exp < 0)
{
if (roundmode == IRC_UP)
{
return (sign ? -1.0 : 1.0);
}
else if (roundmode == IRC_NEAR)
{
if (exp == -1)
{
return (sign ? -1.0 : 1.0);
}
}
return 0.0;
}
else if (exp >= 52)
{
return x;
}
else
{
if (exp > 20)
{
if (roundmode == IRC_UP)
{
if ((~rgconst[exp-21])&_db.rg[1])
{
fROUNDUP = fTrue;
}
}
else if (roundmode == IRC_NEAR)
{
if (rgconst2[exp-20]&_db.rg[1])
{
fROUNDUP=fTrue;
}
}
_db.rg[1] = rgconst[exp-21]&_db.rg[1];
}
else if (exp == 20)
{
if (roundmode == IRC_UP)
{
if (_db.rg[1])
{
fROUNDUP = fTrue;
}
}
else if (roundmode == IRC_NEAR)
{
if (rgconst2[0]&_db.rg[1])
{
fROUNDUP=fTrue;
}
}
_db.rg[1]=0;
}
else
{
if (roundmode == IRC_UP)
{
if ((~rgconst[exp+11])&_db.rg[0] || _db.rg[1])
{
fROUNDUP = fTrue;
}
}
else if (roundmode == IRC_NEAR)
{
if (rgconst2[exp+12]&_db.rg[0])
{
fROUNDUP=fTrue;
}
}
_db.rg[0]=rgconst[exp+11]&_db.rg[0];
_db.rg[1]=0;
}
if (fROUNDUP)
{
_db.db = _db.db + (sign ? -1.0 : 1.0);
}
return _db.db;
}
}
else if (exp == 0)
{
/* denormalized or zero*/
return x;
}
else if (exp == 2047)
{
/* inf or NaN */
return x;
}
else
{
/* should never get here */
;
}
}