mirror of https://github.com/lianthony/NT4.0
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.
341 lines
10 KiB
341 lines
10 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: efloat.hxx *
|
|
* *
|
|
* Contains internal floating point objects and methods. *
|
|
* *
|
|
* Created: 12-Nov-1990 16:45:01 *
|
|
* Author: Wendy Wu [wendywu] *
|
|
* *
|
|
* Copyright (c) 1990 Microsoft Corporation *
|
|
\**************************************************************************/
|
|
|
|
#define BOOL_TRUNCATE 0
|
|
#define BOOL_ROUND 1
|
|
|
|
class EFLOAT;
|
|
|
|
extern "C" {
|
|
|
|
BOOL eftol_c(EFLOAT *, PLONG, LONG);
|
|
BOOL eftofx_c(EFLOAT *, PFIX);
|
|
LONG eftof_c(EFLOAT *);
|
|
VOID ltoef_c(LONG, EFLOAT *);
|
|
VOID fxtoef_c(FIX, EFLOAT *);
|
|
VOID ftoef_c(FLOAT, EFLOAT *);
|
|
|
|
// New style floating point support routines. The first pointer specifies
|
|
// where to put the return value. The first pointer is the return value.
|
|
|
|
EFLOAT *addff3_c(EFLOAT *,EFLOAT *,EFLOAT *);
|
|
EFLOAT *subff3_c(EFLOAT *,EFLOAT *,EFLOAT *);
|
|
EFLOAT *mulff3_c(EFLOAT *,const EFLOAT *,const EFLOAT *);
|
|
EFLOAT *divff3_c(EFLOAT *,EFLOAT *,EFLOAT *);
|
|
EFLOAT *sqrtf2_c(const EFLOAT *,const EFLOAT *);
|
|
EFLOAT *fraction_c(EFLOAT *,EFLOAT *);
|
|
|
|
};
|
|
|
|
class POINTFL;
|
|
|
|
/*********************************Class************************************\
|
|
* class EFLOAT *
|
|
* *
|
|
* Energized floating point object. *
|
|
* *
|
|
* The floating point object defined below has 32 bits of signed mantissa *
|
|
* and 16 bits of signed exponent. The decimal point is before the MSB *
|
|
* of mantissa. The value of a number is determined by the following *
|
|
* equation: *
|
|
* value = 0.mantissa * 2^exponent *
|
|
* *
|
|
* Zero has only one unique representation with mantissa and exponent both *
|
|
* zero. *
|
|
* *
|
|
* History: *
|
|
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
|
|
* Wrote it. *
|
|
\**************************************************************************/
|
|
|
|
class EFLOAT
|
|
{
|
|
public: // has to be public in order for
|
|
EFLOAT_S i; // MAKEEFLOAT to do initializations
|
|
|
|
public:
|
|
|
|
EFLOAT_S Base() {return(i);}
|
|
|
|
// Operator+= -- Add two EFLOAT numbers together. Caller is responsible for
|
|
// overflow checking.
|
|
|
|
VOID operator+=(EFLOAT& ef) {addff3_c(this,this,&ef);}
|
|
|
|
// Operator-= -- Substract an EFLOAT number from another. Caller is
|
|
// responsible for overflow checkings.
|
|
|
|
VOID operator-=(EFLOAT& ef) {subff3_c(this,this,&ef);}
|
|
|
|
// Operator*= -- Multiply two EFLOAT numbers together. Caller is responsible for
|
|
// overflow checkings.
|
|
|
|
VOID operator*=(EFLOAT& ef) {mulff3_c(this,this,&ef);}
|
|
|
|
// vTimes16 -- Multiply an EFLOAT number by 16.
|
|
|
|
VOID vTimes16() { if (i.lMant != 0) i.lExp += 4; }
|
|
|
|
// Operator/ -- Divide an EFLOAT number by another. Caller is responsible for
|
|
// overflow checkings.
|
|
|
|
VOID operator/=(EFLOAT& ef) {divff3_c(this,this,&ef);}
|
|
|
|
// vDivBy16 -- Divide an EFLOAT number by 16.
|
|
|
|
VOID vDivBy16() { if (i.lMant != 0) i.lExp -= 4; }
|
|
|
|
// vNegate - Negate an EFLOAT number.
|
|
|
|
VOID vNegate()
|
|
{
|
|
if (i.lMant != 0x80000000)
|
|
i.lMant = -i.lMant;
|
|
else
|
|
{
|
|
i.lMant = 0x40000000;
|
|
i.lExp += 1;
|
|
}
|
|
}
|
|
|
|
// operator> -- Signed compare two numbers. See if an EFLOAT number is
|
|
// greater than a given number.
|
|
|
|
// Is there a better way to do this???
|
|
|
|
BOOL operator>(EFLOAT& ef)
|
|
{
|
|
LONG lsignSrc = ef.i.lMant >> 31, lsignDest = i.lMant >> 31;
|
|
BOOL bReturn = FALSE;
|
|
|
|
if (lsignSrc < lsignDest) // src is negative, dest is positive
|
|
bReturn = TRUE;
|
|
else if (lsignSrc > lsignDest) // src is positive, dest is negative
|
|
;
|
|
else if (i.lExp == ef.i.lExp) // same sign, same exp, comp mantissa
|
|
bReturn = i.lMant > ef.i.lMant;
|
|
else if (lsignSrc == 0) // both src and dest are positive
|
|
{
|
|
if (((i.lExp > ef.i.lExp) && (i.lMant != 0)) || ef.i.lMant == 0)
|
|
bReturn = TRUE;
|
|
}
|
|
else // both negative
|
|
{
|
|
if (i.lExp < ef.i.lExp) // zero won't reach here
|
|
bReturn = TRUE;
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
// operator<=,>,>=,== -- Compare two EFLOAT numbers.
|
|
|
|
BOOL operator<=(EFLOAT& ef) { return(!((*this) > ef)); }
|
|
BOOL operator<(EFLOAT& ef) { return(ef > (*this)); }
|
|
BOOL operator>=(EFLOAT& ef) { return(ef <= (*this)); }
|
|
BOOL operator==(EFLOAT& ef)
|
|
{
|
|
return((i.lMant == ef.i.lMant) && (i.lExp == ef.i.lExp));
|
|
}
|
|
|
|
// Operator= -- Assign a value to an EFLOAT number.
|
|
|
|
VOID operator=(LONG l) {ltoef_c(l,this);}
|
|
VOID operator=(FLOAT f) {ftoef_c(f,this);}
|
|
|
|
// vFxToEf -- Convert a FIX number to an EFLOAT number.
|
|
// This could have been another operator=(FIX fx). However, since
|
|
// FIX is defined as LONG. The compiler doesn't accept the second
|
|
// definition.
|
|
|
|
VOID vFxToEf(FIX fx) {fxtoef_c(fx,this);}
|
|
|
|
// bEfToL -- Convert an EFLOAT number to a LONG integer. Fractions of 0.5 or
|
|
// greater are rounded up.
|
|
|
|
BOOL bEfToL(LONG &l) { return(eftol_c(this, &l, BOOL_ROUND)); }
|
|
|
|
// bEfToLTruncate -- Convert an EFLOAT number to a LONG integer. The fractions
|
|
// are truncated.
|
|
|
|
BOOL bEfToLTruncate(LONG &l){ return(eftol_c(this, &l, BOOL_TRUNCATE)); }
|
|
|
|
// lEfToF -- Convert an EFLOAT number to an IEEE FLOAT number. The return
|
|
// value is placed in eax. We want to treat it as a LONG to
|
|
// avoid any fstp later.
|
|
|
|
LONG lEfToF() { return(eftof_c(this)); }
|
|
|
|
VOID vEfToF(FLOAT &e) { LONG l = eftof_c(this); e = *((PFLOAT) (&l)); }
|
|
|
|
// bEfToFx -- Convert an EFLOAT number to a FIX number.
|
|
|
|
BOOL bEfToFx(FIX &fx) { return(eftofx_c(this, &fx)); }
|
|
|
|
// bIsZero -- See if an EFLOAT number is zero.
|
|
|
|
BOOL bIsZero() { return((i.lMant == 0) && (i.lExp == 0)); }
|
|
|
|
// bIs16 -- Quick way to check the value of an EFLOAT number.
|
|
|
|
BOOL bIs16() { return((i.lMant == 0x040000000) && (i.lExp == 6)); }
|
|
BOOL bIsNeg16() { return((i.lMant == 0x0c0000000) && (i.lExp == 6)); }
|
|
BOOL bIs1() { return((i.lMant == 0x040000000) && (i.lExp == 2)); }
|
|
BOOL bIsNeg1() { return((i.lMant == 0x0c0000000) && (i.lExp == 2)); }
|
|
BOOL bIs1Over16() { return((i.lMant == 0x040000000) && (i.lExp == -2)); }
|
|
BOOL bIsNeg1Over16() { return((i.lMant == 0x0c0000000) && (i.lExp == -2)); }
|
|
|
|
// vDivBy2 -- Divide an EFLOAT number by 2.
|
|
|
|
VOID vDivBy2() { i.lExp -= 1; }
|
|
|
|
VOID vMultByPowerOf2(INT ii) { i.lExp += (LONG) ii; }
|
|
|
|
// vSetToZero -- Set the value of an EFLOAT number to zero.
|
|
|
|
VOID vSetToZero() { i.lMant = 0; i.lExp = 0; }
|
|
|
|
// vSetToOne -- Set the value of an EFLOAT number to one.
|
|
|
|
VOID vSetToOne() {i.lMant=0x040000000; i.lExp=2;}
|
|
|
|
// bIsNegative -- See if an EFLOAT number is negative.
|
|
|
|
BOOL bIsNegative() { return(i.lMant < 0); }
|
|
|
|
// signum -- Return a LONG representing the sign of the number.
|
|
|
|
LONG lSignum() {return((i.lMant > 0) - (i.lMant < 0));}
|
|
|
|
// vAbs -- Compute the absolute value.
|
|
|
|
VOID vAbs() { if (bIsNegative()) vNegate(); }
|
|
|
|
// vFraction -- Get the fraction part of an EFLOAT number. The result is
|
|
// stored in the passed in parameter.
|
|
//!!! This looks backwards. [chuckwh]
|
|
|
|
VOID vFraction(EFLOAT& ef) {fraction_c(&ef,this);}
|
|
|
|
// bExpInRange -- See if the exponent of an EFLOAT number is within the
|
|
// given range.
|
|
|
|
BOOL bExpLessThan(LONG max)
|
|
{
|
|
return(i.lExp <=max);
|
|
}
|
|
|
|
// vSqrt -- Takes the square root.
|
|
|
|
VOID vSqrt() {sqrtf2_c(this,this);}
|
|
|
|
// New style math routines.
|
|
//
|
|
// Usage example: EFLOAT z,t; z.eqAdd(x,t.eqSqrt(y));
|
|
// This would be the same as: EFLOAT z,t; z = x + (t = sqrt(y));
|
|
//
|
|
// I.e. you can build complex expressions, but you must declare your own
|
|
// temporaries.
|
|
|
|
EFLOAT& eqSqrt(const EFLOAT& ef)
|
|
{
|
|
return(*sqrtf2_c(this,&ef));
|
|
}
|
|
|
|
EFLOAT& eqAdd(EFLOAT& efA,EFLOAT& efB)
|
|
{
|
|
return(*addff3_c(this,&efA,&efB));
|
|
}
|
|
|
|
EFLOAT& eqSub(EFLOAT& efA,EFLOAT& efB)
|
|
{
|
|
return(*subff3_c(this,&efA,&efB));
|
|
}
|
|
|
|
EFLOAT& eqMul(const EFLOAT& efA,const EFLOAT& efB)
|
|
{
|
|
return(*mulff3_c(this,&efA,&efB));
|
|
}
|
|
|
|
EFLOAT& eqDiv(EFLOAT& efA,EFLOAT& efB)
|
|
{
|
|
return(*divff3_c(this,&efA,&efB));
|
|
}
|
|
|
|
EFLOAT& eqFraction(EFLOAT& ef)
|
|
{
|
|
return(*fraction_c(this,&ef));
|
|
}
|
|
|
|
EFLOAT& eqAbs(EFLOAT& ef)
|
|
{
|
|
i.lExp = ef.i.lExp;
|
|
i.lMant = ef.i.lMant;
|
|
if (i.lMant < 0)
|
|
{
|
|
if (i.lMant != 0x80000000)
|
|
{
|
|
i.lMant = -i.lMant;
|
|
}
|
|
else
|
|
{
|
|
i.lMant = 0x40000000;
|
|
i.lExp++;
|
|
}
|
|
}
|
|
return(*this);
|
|
}
|
|
|
|
// eqDot -- Dot product of two vectors.
|
|
|
|
EFLOAT eqDot(const POINTFL&,const POINTFL&);
|
|
|
|
// eqCross -- Cross product of two vectors. (A scaler in 2 dimensions.)
|
|
|
|
EFLOAT eqCross(const POINTFL&,const POINTFL&);
|
|
|
|
// eqLength -- Length of a vector.
|
|
|
|
EFLOAT eqLength(const POINTFL&);
|
|
};
|
|
|
|
class EFLOATEXT: public EFLOAT {
|
|
public:
|
|
EFLOATEXT() {}
|
|
EFLOATEXT(LONG l) {ltoef_c(l,this);}
|
|
EFLOATEXT(FLOAT e) {ftoef_c(e,this);}
|
|
|
|
VOID operator=(const EFLOAT& ef) {*(EFLOAT*) this = ef;}
|
|
VOID operator=(LONG l) {*(EFLOAT*) this = l;}
|
|
|
|
VOID operator*=(LONG l)
|
|
{
|
|
EFLOATEXT efT(l);
|
|
mulff3_c(this,this,&efT);
|
|
}
|
|
|
|
VOID operator*=(EFLOAT& ef)
|
|
{
|
|
*(EFLOAT*)this *= ef;
|
|
}
|
|
|
|
VOID operator/=(EFLOAT& ef)
|
|
{
|
|
*(EFLOAT*)this /= ef;
|
|
}
|
|
|
|
VOID operator/=(LONG l)
|
|
{
|
|
EFLOATEXT efT(l);
|
|
divff3_c(this,this,&efT);
|
|
}
|
|
};
|
|
|
|
extern "C" LONG lCvt(EFLOAT ef,LONG ll);
|