home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
p
/
ptv3n5.zip
/
FPNUM.H
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-20
|
7KB
|
160 lines
/*==================================================================
fpnum.h -- Fixed point math class header [Listing #1]
by Robert N. Goldrich
Tested with Borland, Microsoft, Zortech, and TopSpeed C++
==================================================================*/
#include <iostream.h> // for stream operators
/*------------------------------------------------------------------
fpnum class
------------------------------------------------------------------*/
#define sizeof_long 4 // sizeof not allowed in preprocessor
#define sizeof_int 2 // .. so have to do this manually
#define FP_FRCBITS 16 // number of fraction bits
#define FP_TOTBITS ( sizeof_long *8 ) // bits in a 'long'
#if( (FP_FRCBITS >= FP_TOTBITS-1) || (FP_FRCBITS < sizeof_int*8) )
#error (fpnum.h) Too many or too few decimal bits in fpnum.
#endif
#define FP_ONE ( 1L << FP_FRCBITS )
#define FP_HALF ( FP_ONE >> 1 )
#define FP_MIN ( 1L << ( FP_TOTBITS-1 ) ) // 8000 0000
#define FP_MAX ( ~FP_MIN ) // 7fff ffff
#define FP_ALLBITS ( ~0L ) // ffff ffff
#define FP_MAXDECPL ( ((FP_TOTBITS-1)*301) / 1000 - 1 )
// 301 = log(2) the maximum # of decimal places shown on output
class fpnum {
long xx ;
fpnum( long a ) { xx = a ; } ;
/*--
A *private* constructor which just stuffs a long value into xx.
Dangerous if public and not needed publicly because generally,
a long is too large to store in a fpnum. Use poke() instead.
--*/
public:
//--constructors
fpnum() { xx = 0 ; } ;
fpnum( int a ) { xx = (long)a << FP_FRCBITS ; } ;
fpnum( int a, int b ) { *this = fpnum(a) / fpnum(b) ; } ;
fpnum( char *str ) { *this = atofp( str ) ; } ;
//--simple assignment method
// The following assignment operator is generated automatically for
// every class. It can, however be overridden.
// fpnum& operator=( const fpnum& a ) { xx = a.xx; return *this;} ;
//--binary operators: fpnum (operator) fpnum
friend fpnum operator+( const fpnum& a, const fpnum& b ) {
return fpnum( a.xx + b.xx ) ; } ;
friend fpnum operator-( const fpnum& a, const fpnum& b ) {
return fpnum( a.xx - b.xx ) ; } ;
friend fpnum operator*( const fpnum& a, const fpnum& b ) ;
friend fpnum operator/( const fpnum& a, const fpnum& b ) ;
friend fpnum operator%( const fpnum& a, const fpnum& b ) {
return fpnum( a.xx % b.xx ) ; } ;
//--binary operators: fpnum * int
/*---
The following two methods are included to enhance performance,
and are really not needed from a language point of view.
Multiplication of fpnums with integers could be handled without
them as follows:
1. the int will be promoted to a fpnum via the constructor
conversion
2. the fpnum * fpnum function will be called
These operators perform the same function much more efficiently.
---*/
friend fpnum operator*( const fpnum& a, int b ) {
return fpnum( a.xx * b ) ; } ;
friend fpnum operator*( int a, const fpnum& b ) {
return fpnum( b.xx * a ) ; } ;
//--assignment operators
fpnum& operator+=( const fpnum& a ) {
xx += a.xx ; return *this ; } ;
fpnum& operator-=( const fpnum& a ) {
xx -= a.xx ; return *this ; } ;
fpnum& operator*=( const fpnum& a ) {
*this = *this * a ; return *this ; } ;
fpnum& operator/=( const fpnum& a ) {
*this = *this / a ; return *this ; } ;
fpnum& operator%=( const fpnum& a ) {
*this = *this % a ; return *this ; } ;
//--increment/decrement operators
// pre- operators return reference to self after incrementing
fpnum& operator++() { xx += FP_ONE; return *this; } ;
fpnum& operator--() { xx -= FP_ONE; return *this; } ;
// post- operators return value of original fpnum
fpnum operator++( int ) {
long yy = xx ; xx += FP_ONE ; return fpnum( yy ) ; } ;
fpnum operator--( int ) {
long yy = xx ; xx -= FP_ONE ; return fpnum( yy ) ; } ;
//--unary operators
// Zortech doesn't like the unary + operator for some reason
fpnum operator+() const { return *this ; } ;
fpnum operator-() const { return fpnum( -xx ) ; }
//--type conversion methods
friend int round_to_int( const fpnum& a ) ;
friend int trunc_to_int( const fpnum& a ) ;
//--logical operators
friend int operator<( const fpnum& a, const fpnum& b ) {
return ( a.xx < b.xx ) ; } ;
friend int operator<=( const fpnum& a, const fpnum& b ) {
return ( a.xx <= b.xx ) ; } ;
friend int operator==( const fpnum& a, const fpnum& b ) {
return ( a.xx == b.xx ) ; } ;
friend int operator>=( const fpnum& a, const fpnum& b ) {
return ( a.xx >= b.xx ) ; } ;
friend int operator>( const fpnum& a, const fpnum& b ) {
return ( a.xx > b.xx ) ; } ;
friend int operator!=( const fpnum& a, const fpnum& b ) {
return ( a.xx != b.xx ) ; } ;
//--trig functions
friend fpnum fp_sin( int angle ) ;
friend fpnum fp_cos( int angle ) { return fp_sin( 90+angle ); };
friend fpnum fp_tan( int angle ) ;
//--conversions between fpnums and strings / stream operators
friend fpnum atofp( char *str ) ;
friend char *fptoa( const fpnum& n, char *str ) ;
friend ostream& operator<<( ostream& o, const fpnum& n ) ;
friend istream& operator>>( istream& i, const fpnum& n ) ;
//--odds and ends
fpnum& poke( long a ) { xx = a ; return *this ; } ;
long peek() const { return xx ; } ;
fpnum& inc_by( long a ) { // might want this in a pinch
xx += a ; return *this ; } ;
fpnum& change_sign() { // much more efficient than fp= -fp
xx = -xx ; return *this ; } ;
friend fpnum fpabs( fpnum a ) {
return fpnum( (a.xx < 0 ? -a.xx : a.xx ) ) ; } ;
friend int signof( fpnum a ) {
return a.xx < 0 ? -1 : 1 ; } ;
//--fpnum constants
#if 0
// Borland, Zortech, and TopSpeed do not allow these constants to be
// initialized with the private constructor, though they should.
static const fpnum fp_max, // maximum fpnum
fp_min, // minimum fpnum
fp_res ; // fpnum resolution
#endif
} ;