Listing 1 fixed.cpp

/*----------------------------------------------------
        Module: FIXED.CPP
     
      Class: Fixed
      
      Description: A fixed point numerical
      class that performs numerical operations
      in a 15.16 bit signed format, using a signed
      long as native storage.
      
      This format is capable of storing numbers
      in a range of +32,767 to -32,768 in 1/65535ths
      increments (approx. 0.0000153, or about 5
      decimals of accuracy).
      
      Revision History
-----------------------------------------------------
  Date       Name  Comment
-----------------------------------------------------

Feb-16-93    rbf   Added the addProduct function

Nov-24-92    rbf   Initial Creation

---------------------------------------------------*/

#include "FIXED.H"
#include <stdio.h>

/*--------------------------------------------------
   default constructor
---------------------------------------------------*/

Fixed::Fixed()
{
   fixeddata.long_rep = FixedData)0;
}

/*-------------------------------------------------
   default copy constructor
--------------------------------------------------*/

Fixed::Fixed(const Fixed& rhs)
{
   fixeddata.long_rep = rhs.fixeddata.long_rep;
}

/*-------------------------------------------------
   constructor taking a double
--------------------------------------------------*/

Fixed::Fixed(double rhs)
{
   // shift it into the 2nd 16 bits-------+
   //          round it---------+         |
   //  then truncate it --+     |         |
   //                     |     |         |
   fixeddata.long_rep = (long)(0.5 + (rhs * 65536.0));
}

/*-------------------------------------------------
   constructor taking an int
--------------------------------------------------*/

Fixed::Fixed(int rhs)
{
   // shift it into the 2nd 16 bits
   fixeddata.long_rep = (FixedData)rhs << 16;
}

/*-------------------------------------------------
   default assignment
--------------------------------------------------*/

Fixed&   Fixed::operator=(const Fixed& rhs)
{
   fixeddata.long_rep = rhs.fixeddata.long_rep;
   
   return *this;
}

/*-------------------------------------------------
   default destructor
--------------------------------------------------*/

Fixed::~Fixed()
{
   ; // if there were something to destroy,
     // we'd do it here
}

/*-------------------------------------------------
   ostream output
--------------------------------------------------*/

// describe how to output a fixed value

ostream& operator<<( ostream& s, Fixed& rhs )
{
   return ( s <<
      (((double)rhs.fixeddata.long_rep) / 65536.0) );
}

/*-------------------------------------------------
   addition operator
   the order of the addition makes no difference
--------------------------------------------------*/

Fixed operator+(const Fixed& lhs,
     const Fixed& rhs)
{
   Fixed return_val(rhs); // create a return temporary
   
   // add the data parts together
   return_val.fixeddata.long_rep +=
      lhs.fixeddata.long_rep;
   
   return return_val;
}

/*-------------------------------------------------
   subtraction operator
   the order of the subtraction does make a difference
   this function can be considered
   "lhs.operator-( rhs )" for the
   expression lhs-rhs
--------------------------------------------------*/

Fixed operator-(const Fixed& lhs,
     const Fixed& rhs)
{
   Fixed return_val(lhs);// create a return temporary
   
   // do the math, subtracting the
   // left hand side from the right
   return_val.fixeddata.long_rep =
        rhs.fixeddata.long_rep;
   
   return return_val;
}

/*-------------------------------------------------
   multiplication operator
--------------------------------------------------*/

// Force the use of the real assembler
// for 386 instructions
#pragma inline
// quiet the compiler from complaining since
// it can't read ASM code
#pragma argsused

Fixed operator*(const Fixed& lhs, const Fixed& rhs)
{
   Fixed return_val; // create a return temporary
   
   _asm{
   .386C;   /* enable 386 instruction set */
   
   mov   bx,word ptr [bp+10]; /* get rhs's offset */
   mov   eax,dword ptr [bx];  /* move rhs's 32 bits*/
                         /*  into eax */
   mov   bx,word ptr [bp+8];  /* get this offset */
   imul   dword ptr [bx];    /* mul by left hand side */
   
   /* if we overflow a 16 bit rational, */
   /*   we don't check */
   
   mov   word ptr [bp-2],dx;     /* dx = high word of */
                      /*  return_value's pointer */
   
   /* shift the 32 bit fraction */
   /* into a 16 bit (eax->ax) */
   shr   eax,16;
   mov   word ptr [bp-4],ax;    /* low word */
   } /* asm */
   
   return return_val;
}

/*-------------------------------------------------
  division operator
--------------------------------------------------*/

// see comments for multiplication operator
#pragma inline
#pragma argsused

Fixed operator/(const Fixed& lhs, const Fixed& rhs)
{

   Fixed temp = 0; // do our math in this temp on stack
   
   _asm{
   .386C;   /* enable 386 instruction set */
   
   mov       eax,dword ptr [bp+8]; /* lhs */
   sub     eax,eax;
   mov     edx,[bp+10]; /* rhs */
   shrd    eax,edx,16;   /* position result */
   sar     edx,16;      /* in EAX */
   idiv    dword ptr [bp+8]; /* lhs */
   shld    edx,eax,16 /* whole part in DX */
             /* fractional already in AX */
   } /* asm */
   
   return Fixed(temp);
}

/*------------------------------------------------
   addProduct member function
-------------------------------------------------*/

// see comments for multiplication operator
#pragma inline
#pragma argsused

void      Fixed::addProduct(const Fixed& rhs1,const
Fixed& rhs2)
{
   _asm{
   .386C;  /*  enable 386 instruction set */
   
   /* word ptr [bp+4] is the address of *this data */
   /* word ptr [bp+6] is the address of rhs1 data */
   /* word ptr [bp+8] is the address of rhs2 data */
   
   mov   si,word ptr [bp+4] ; /* address of *this */
   
   mov   bx,  word ptr [bp+6]; /* get rhs1's offset */
   mov   eax,dword ptr [bx];   /* move rhs1's 32 bits*/
   
   mov   bx,  word ptr [bp+8]; /* get rhs2's offset */
   imul   dword ptr [bx];       /* mul rhs2 by rhs1 */
   
   /* if we overflow (as before) we don't check */
   
   /* shift the 32 bit fraction into a 16 bit (eax->ax) */
   shr   eax,16;
   
   /* dx = high word (fractions) */
   /* ax = low word (whole numbers) */
   add   word ptr [si],ax;
   adc   word ptr [si+2],dx;
   
   } /* asm */
}

/*-------------------------------------------------
   relational operator equal to
--------------------------------------------------*/

int    operator==(const Fixed& lbs,
      const Fixed& rhs)
{
   // compare the long values
   return ( lhs.fixeddata.long_rep ==
      rhs.fixeddata.long_rep );
}

/*------------------------------------------------
   relational operator not equal to
-------------------------------------------------*/

int    operator!=(const Fixed& lhs,
      const Fixed& rhs)
{
   // compare the long values
   return ( lhs.fixeddata.long_rep !=
      rhs.fixeddata.long_rep );
}

/*------------------------------------------------
   relational operator greater than
--------------------------------------------------*/

int    operator>(const Fixed& lhs,
      const Fixed& rhs)
{

   // compare the the long values
   return ( lhs.fixeddata,long_rep >
      rhs.fixeddata.long_rep);
}

/*-------------------------------------------------
   relational operator less than
--------------------------------------------------*/

int    operator<(const Fixed& lhs,
      const Fixed& rhs)
{
   // compare the long values
   return ( lhs.fixeddata. long_rep <
      rhs.fixeddata.long_rep);
}

/*-------------------------------------------------
   relational operator greater than equal to
--------------------------------------------------*/

int    operator>=(const fixed& lhs,
      const Fixed& rhs)
{
   // compare the long values
   return ( lhs.fixeddata, long_rep >=
      rhs.fixeddata.long_rep );
}

/*------------------------------------------------
   relational operator less than equal to
-------------------------------------------------*/

int    operator<=(const Fixed& lhs,
      const Fixed& rhs)
{
   // compare the long values
   return ( lhs.fixeddata.long_rep <=
      rhs.fixeddata.long_rep );
}

/*-------------------------------------------------
   compound assignment addition operator
--------------------------------------------------*/

Fixed& Fixed::operator+=(conts Fixed& rhs)
{
   fixeddata.long_rep += rhs.fixeddata.long_rep;
   return *this;
}

/*-------------------------------------------------
   compound assignment subtraction operator
--------------------------------------------------*/

Fixed& Fixed::operator-=(const Fixed& rhs)
{
   fixeddata.long_rep -= rhs.fixeddata.long_rep;
   
   return *this;
}

/*-------------------------------------------------
   compound assignment multiplication operator
--------------------------------------------------*/

Fixed& Fixed::operator*=(const Fixed& rhs)
{
   *this = *this * rhs;  // wimpy way of doing it.....
   
   return *this;
}

/*-------------------------------------------------
   compound assignment division operator
--------------------------------------------------*/

Fixed& Fixed::operator/=(const Fixed& rhs)
{
   *this = *this / rhs;  // wimpy way of doing it.....
   
   return *this;
}

/*-------------------------------------------------
   Unary plus operator
--------------------------------------------------*/
Fixed Fixed::operator+()
{
   return Fixed(*this);
}

/*-------------------------------------------------
   Unary minus operator
--------------------------------------------------*/
Fixed Fixed::operator-()
{
   Fixed return_val ( *this );
   return_val *= -1;
   return return_val;
}

// End of File