home *** CD-ROM | disk | FTP | other *** search
- // This may look like C code, but it is really -*- C++ -*-
- /*
- Copyright (C) 1988 Free Software Foundation
- written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu)
- adapted for libg++ by Doug Lea (dl@rocky.oswego.edu)
-
- This file is part of the GNU C++ Library. This library is free
- software; you can redistribute it and/or modify it under the terms of
- the GNU Library General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your
- option) any later version. This library is distributed in the hope
- that it will be useful, but WITHOUT ANY WARRANTY; without even the
- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the GNU Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #ifndef _Fix24_h
- #ifdef __GNUG__
- #pragma once
- #pragma interface
- #endif
- #define _Fix24_h 1
-
- #include <stream.h>
- #include <std.h>
-
- // extra type definitions
-
- typedef struct {
- long u;
- unsigned long l;
- } twolongs;
-
- // constant definitions
-
- static const int
- Fix24_shift = 31;
-
- static const double
- Fix24_fs = 2147483648., // 2^Fix24_shift
- Fix24_mult = Fix24_fs,
- Fix24_div = 1./Fix24_fs,
- Fix24_max = 1. - .5/Fix24_fs,
- Fix24_min = -1.;
-
- static const unsigned long
- Fix24_msb = 0x80000000L,
- Fix24_lsb = 0x00000100L,
- Fix24_m_max = 0x7fffff00L,
- Fix24_m_min = 0x80000000L;
-
- static const double
- Fix48_fs = 36028797018963968., // 2^(24+Fix24_shift)
- Fix48_max = 1. - .5/Fix48_fs,
- Fix48_min = -1.,
- Fix48_div_u = 1./Fix24_fs,
- Fix48_div_l = 1./Fix48_fs;
-
- static const twolongs
- Fix48_msb = { 0x80000000L, 0L },
- Fix48_lsb = { 0L, 0x00000100L },
- Fix48_m_max = { 0x7fffff00L, 0xffffff00L },
- Fix48_m_min = { 0x80000000L, 0L };
-
- //
- // Fix24 class: 24-bit Fixed point data type
- //
- // consists of a 24-bit mantissa (sign bit & 23 data bits).
- //
-
- class Fix24
- {
- friend class Fix48;
-
- long m;
-
- long assign(double d);
- operator double();
- Fix24(long i);
- Fix24(int i);
-
-
- public:
- Fix24();
- Fix24(Fix24& f);
- Fix24(double d);
- Fix24(Fix48& f);
-
- ~Fix24();
-
- Fix24& operator=(Fix24& f);
- Fix24& operator=(double d);
- Fix24& operator=(Fix48& f);
-
- friend long& mantissa(Fix24& f);
- friend double value(Fix24& f);
-
- Fix24 operator + ();
- Fix24 operator - ();
-
- friend Fix24 operator + (Fix24& f, Fix24& g);
- friend Fix24 operator - (Fix24& f, Fix24& g);
- friend Fix48 operator * (Fix24& f, Fix24& g);
- friend Fix24 operator * (Fix24& f, long g);
- friend Fix24 operator * (long g, Fix24& f);
- friend Fix24 operator / (Fix24& f, Fix24& g);
- friend Fix24 operator << (Fix24& f, int b);
- friend Fix24 operator >> (Fix24& f, int b);
-
- Fix24& operator += (Fix24& f);
- Fix24& operator -= (Fix24& f);
- Fix24& operator *= (Fix24& f);
- Fix24& operator *= (long b);
- Fix24& operator /= (Fix24& f);
-
- Fix24& operator <<=(int b);
- Fix24& operator >>=(int b);
-
- friend int operator == (Fix24& f, Fix24& g);
- friend int operator != (Fix24& f, Fix24& g);
- friend int operator >= (Fix24& f, Fix24& g);
- friend int operator <= (Fix24& f, Fix24& g);
- friend int operator > (Fix24& f, Fix24& g);
- friend int operator < (Fix24& f, Fix24& g);
-
- friend istream& operator >> (istream& s, Fix24& f);
- friend ostream& operator << (ostream& s, Fix24& f);
-
- void overflow(long&);
- void range_error(long&);
- };
-
-
- //
- // Fix48 class: 48-bit Fixed point data type
- //
- // consists of a 48-bit mantissa (sign bit & 47 data bits).
- //
-
- class Fix48
- {
- friend class Fix24;
-
- twolongs m;
-
- twolongs assign(double d);
- operator double();
- Fix48(twolongs i);
-
- public:
- Fix48();
- Fix48(Fix48& f);
- Fix48(Fix24& f);
- Fix48(double d);
- ~Fix48();
-
- Fix48& operator = (Fix48& f);
- Fix48& operator = (Fix24& f);
- Fix48& operator = (double d);
-
- friend twolongs& mantissa(Fix48& f);
- friend double value(Fix48& f);
-
- Fix48 operator + ();
- Fix48 operator - ();
-
- friend Fix48 operator + (Fix48& f, Fix48& g);
- friend Fix48 operator - (Fix48& f, Fix48& g);
- friend Fix48 operator * (Fix48& f, long g);
- friend Fix48 operator * (long g, Fix48& f);
- friend Fix48 operator << (Fix48& f, int b);
- friend Fix48 operator >> (Fix48& f, int b);
-
- friend Fix48 operator * (Fix24& f, Fix24& g);
-
- Fix48& operator += (Fix48& f);
- Fix48& operator -= (Fix48& f);
- Fix48& operator *= (long b);
- Fix48& operator <<=(int b);
- Fix48& operator >>=(int b);
-
- friend int operator == (Fix48& f, Fix48& g);
- friend int operator != (Fix48& f, Fix48& g);
- friend int operator >= (Fix48& f, Fix48& g);
- friend int operator <= (Fix48& f, Fix48& g);
- friend int operator > (Fix48& f, Fix48& g);
- friend int operator < (Fix48& f, Fix48& g);
-
- friend istream& operator >> (istream& s, Fix48& f);
- friend ostream& operator << (ostream& s, Fix48& f);
-
- void overflow(twolongs& i);
- void range_error(twolongs& i);
- };
-
-
- // active error handler declarations
-
- typedef void (*Fix24_peh)(long&);
- typedef void (*Fix48_peh)(twolongs&);
-
- extern Fix24_peh Fix24_overflow_handler;
- extern Fix48_peh Fix48_overflow_handler;
-
- extern Fix24_peh Fix24_range_error_handler;
- extern Fix48_peh Fix48_range_error_handler;
-
-
- // error handler declarations
-
- #if defined(SHORT_NAMES) || defined(VMS)
- #define set_overflow_handler sohndl
- #define set_range_error_handler srnghdl
- #endif
-
- extern Fix24_peh set_Fix24_overflow_handler(Fix24_peh);
- extern Fix48_peh set_Fix48_overflow_handler(Fix48_peh);
- extern void set_overflow_handler(Fix24_peh, Fix48_peh);
-
- extern Fix24_peh set_Fix24_range_error_handler(Fix24_peh);
- extern Fix48_peh set_Fix48_range_error_handler(Fix48_peh);
- extern void set_range_error_handler(Fix24_peh, Fix48_peh);
-
- extern void
- Fix24_ignore(long&),
- Fix24_overflow_saturate(long&),
- Fix24_overflow_warning_saturate(long&),
- Fix24_warning(long&),
- Fix24_abort(long&);
-
- extern void
- Fix48_ignore(twolongs&),
- Fix48_overflow_saturate(twolongs&),
- Fix48_overflow_warning_saturate(twolongs&),
- Fix48_warning(twolongs&),
- Fix48_abort(twolongs&);
-
- #if defined(__OPTIMIZE__) || defined(USE_LIBGXX_INLINES)
-
- inline Fix24::~Fix24() {}
-
- inline Fix24::Fix24(long i)
- {
- m = i;
- }
-
- inline Fix24::Fix24(int i)
- {
- m = i;
- }
-
- inline Fix24::operator double()
- {
- return Fix24_div * m;
- }
-
- inline Fix24::Fix24()
- {
- m = 0;
- }
-
- inline Fix24::Fix24(Fix24& f)
- {
- m = f.m;
- }
-
- inline Fix24::Fix24(double d)
- {
- m = assign(d);
- }
-
- inline Fix24::Fix24(Fix48& f)
- {
- m = f.m.u;
- }
-
- inline Fix24& Fix24::operator=(Fix24& f)
- {
- m = f.m;
- return *this;
- }
-
- inline Fix24& Fix24::operator=(double d)
- {
- m = assign(d);
- return *this;
- }
-
- inline Fix24& Fix24::operator=(Fix48& f)
- {
- m = f.m.u;
- return *this;
- }
-
- inline long& mantissa(Fix24& f)
- {
- return f.m;
- }
-
- inline double value(Fix24& f)
- {
- return double(f);
- }
-
- inline Fix24 Fix24::operator+()
- {
- return m;
- }
-
- inline Fix24 Fix24::operator-()
- {
- return -m;
- }
-
- inline Fix24 operator+(Fix24& f, Fix24& g)
- {
- long sum = f.m + g.m;
- if ( (f.m ^ sum) & (g.m ^ sum) & Fix24_msb )
- f.overflow(sum);
- return sum;
- }
-
- inline Fix24 operator-(Fix24& f, Fix24& g)
- {
- long sum = f.m - g.m;
- if ( (f.m ^ sum) & (-g.m ^ sum) & Fix24_msb )
- f.overflow(sum);
- return sum;
- }
-
- inline Fix24 operator*(Fix24& a, long b)
- {
- return a.m * b;
- }
-
- inline Fix24 operator*(long b, Fix24& a)
- {
- return a * b;
- }
-
- inline Fix24 operator<<(Fix24& a, int b)
- {
- return a.m << b;
- }
-
- inline Fix24 operator>>(Fix24& a, int b)
- {
- return (a.m >> b) & 0xffffff00L;
- }
-
- inline Fix24& Fix24:: operator+=(Fix24& f)
- {
- return *this = *this + f;
- }
-
- inline Fix24& Fix24:: operator-=(Fix24& f)
- {
- return *this = *this - f;
- }
-
- inline Fix24& Fix24::operator*=(Fix24& f)
- {
- return *this = *this * f;
- }
-
- inline Fix24& Fix24:: operator/=(Fix24& f)
- {
- return *this = *this / f;
- }
-
- inline Fix24& Fix24:: operator<<=(int b)
- {
- return *this = *this << b;
- }
-
- inline Fix24& Fix24:: operator>>=(int b)
- {
- return *this = *this >> b;
- }
-
- inline Fix24& Fix24::operator*=(long b)
- {
- return *this = *this * b;
- }
-
- inline int operator==(Fix24& f, Fix24& g)
- {
- return f.m == g.m;
- }
-
- inline int operator!=(Fix24& f, Fix24& g)
- {
- return f.m != g.m;
- }
-
- inline int operator>=(Fix24& f, Fix24& g)
- {
- return f.m >= g.m;
- }
-
- inline int operator<=(Fix24& f, Fix24& g)
- {
- return f.m <= g.m;
- }
-
- inline int operator>(Fix24& f, Fix24& g)
- {
- return f.m > g.m;
- }
-
- inline int operator<(Fix24& f, Fix24& g)
- {
- return f.m < g.m;
- }
-
- inline istream& operator>>(istream& s, Fix24& f)
- {
- double d;
- s >> d;
- f = d;
- return s;
- }
-
- inline ostream& operator<<(ostream& s, Fix24& f)
- {
- return s << double(f);
- }
-
- inline Fix48::~Fix48() {}
-
- inline Fix48::Fix48(twolongs i)
- {
- m = i;
- }
-
- inline Fix48:: operator double()
- {
- /*
- * Note: can't simply do Fix48_div_u * m.u + Fix48_div_l * m.l, because
- * m.u is signed and m.l is unsigned.
- */
- return (m.u >= 0)? Fix48_div_u * m.u + Fix48_div_l * m.l :
- (Fix48_div_u * ((unsigned long)(m.u & 0xffffff00))
- + Fix48_div_l * m.l) - 2;
- }
-
- inline Fix48::Fix48()
- {
- m.u = 0;
- m.l = 0;
- }
-
- inline Fix48::Fix48(Fix48& f)
- {
- m = f.m;
- }
-
- inline Fix48::Fix48(Fix24& f)
- {
- m.u = f.m;
- m.l = 0;
- }
-
- inline Fix48::Fix48(double d)
- {
- m = assign(d);
- }
-
- inline Fix48& Fix48::operator=(Fix48& f)
- {
- m = f.m;
- return *this;
- }
-
- inline Fix48& Fix48::operator=(Fix24& f)
- {
- m.u = f.m;
- m.l = 0;
- return *this;
- }
-
- inline Fix48& Fix48::operator=(double d)
- {
- m = assign(d);
- return *this;
- }
-
- inline twolongs& mantissa(Fix48& f)
- {
- return f.m;
- }
-
- inline double value(Fix48& f)
- {
- return double(f);
- }
-
- inline Fix48 Fix48::operator+()
- {
- return m;
- }
-
- inline Fix48 Fix48::operator-()
- {
- twolongs n;
- n.l = -m.l;
- n.u = ~m.u + ((n.l ^ m.l) & Fix24_msb ? 0 : Fix24_lsb);
- return Fix48(n);
- }
-
- inline Fix48 operator*(long b, Fix48& a)
- {
- return a * b;
- }
-
- inline Fix48& Fix48::operator+=(Fix48& f)
- {
- return *this = *this + f;
- }
-
- inline Fix48& Fix48::operator-=(Fix48& f)
- {
- return *this = *this - f;
- }
-
- inline Fix48& Fix48::operator*=(long b)
- {
- return *this = *this * b;
- }
-
- inline Fix48& Fix48::operator<<=(int b)
- {
- return *this = *this << b;
- }
-
- inline Fix48& Fix48::operator>>=(int b)
- {
- return *this = *this >> b;
- }
-
- inline int operator==(Fix48& f, Fix48& g)
- {
- return f.m.u == g.m.u && f.m.l == g.m.l;
- }
-
- inline int operator!=(Fix48& f, Fix48& g)
- {
- return f.m.u != g.m.u || f.m.l != g.m.l;
- }
-
- inline int operator>=(Fix48& f, Fix48& g)
- {
- return f.m.u >= g.m.u || (f.m.u == g.m.u && f.m.l >= g.m.l);
- }
-
- inline int operator<=(Fix48& f, Fix48& g)
- {
- return f.m.u <= g.m.u || (f.m.u == g.m.u && f.m.l <= g.m.l);
- }
-
- inline int operator>(Fix48& f, Fix48& g)
- {
- return f.m.u > g.m.u || (f.m.u == g.m.u && f.m.l > g.m.l);
- }
-
- inline int operator<(Fix48& f, Fix48& g)
- {
- return f.m.u < g.m.u || (f.m.u == g.m.u && f.m.l < g.m.l);
- }
-
- inline istream& operator>>(istream& s, Fix48& f)
- {
- double d;
- s >> d;
- f = d;
- return s;
- }
-
- inline ostream& operator<<(ostream& s, Fix48& f)
- {
- return s << double(f);
- }
-
-
- #endif
- #endif
-
-