home *** CD-ROM | disk | FTP | other *** search
- #ifdef __ZTC__
- #include <stream.hpp>
- #endif
- #ifdef __TURBOC__
- #include <iostream.h>
- #endif
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h> // for exit() prototype
-
- /* define only on of these to 1 */
- /* #define BIT32 */
- #define BIT16 1 /* we have a 16-bit compiler */
-
- #ifdef BIT32
- #define INT int
- #else
- #define INT long /* for 16-bit C++ compilers */
- #endif
-
- const unsigned INT QNAN = 0x7FFFFFFF;
- const unsigned INT SNAN = 0x7FC00000;
- const unsigned INT INF = 0x7F800000;
- const unsigned INT ZERO = 0x00000000;
- const unsigned INT DENORM = 0x00000001;
- const unsigned INT NORM = 0x00800000;
-
- //
- // This is a class definition for single precision IEEE-854-Std arithmetic.
- // class real is by no means complete - it is the basic outline for
- // implementing a portable numerics system.
- //
-
- class real {
- private:
- union {
- float f;
- unsigned INT i;
- };
- public:
-
- // constructors
-
- real();
- real(char *);
- real(float f);
- real(double d);
- real(char c);
- real(short s);
- real(INT i);
-
- // No destructors really necessary
-
- // some basic primitives
-
- inline friend int isqnan(real &r);
- inline friend int issnan(real &r);
- inline friend int iszero(real &r);
- inline friend int isinf(real &r);
- inline friend int isdenorm(real &r);
- inline friend int isnorm(real &r);
-
- // overloaded operators
-
- friend real operator+( real &, real & );
- friend real operator-( real &, real & );
- friend real operator*( real &, real & );
- friend real &operator/( real &, real & );
-
- friend int operator==( real &, real & );
- friend int operator!=( real &, real & );
- friend int operator> ( real &, real & );
- friend int operator>=( real &, real & );
- friend int operator<=( real &, real & );
- friend int operator< ( real &, real & );
-
- inline void print(void) { cout << f; }
-
- }; // end of class real
-
- // I/O related overloads
-
- ostream &operator << (ostream &out, real &r) {
- /* r.print(); this was an error in magazine listing */
- if (isqnan(r)) cout << " QNAN ";
- else if (issnan(r)) cout << " SNAN ";
- else if (isinf(r)) cout << " INF ";
- else if (isdenorm(r)) cout << " DENORM ";
- else r.print();
-
- return out;
- }
-
- istream &operator >> (istream &in, real &r) {
-
- return in;
- }
-
- real::real() {} // allow uninitialized variables
-
- real::real(char *str){
- if (strcmp(str,"INF") == 0)
- i = INF;
- else if (strcmp(str,"QNAN") == 0)
- i = QNAN;
- else if (strcmp(str,"SNAN") == 0)
- i = SNAN;
- else if (strcmp(str,"ZERO") == 0)
- i = ZERO;
- else if (strcmp(str,"DENORM") == 0)
- i = DENORM;
- else if (strcmp(str,"NORM") == 0)
- i = NORM;
- else {
- cout << "Unrecognized string format :" << str << ":\n";
- exit(1);
- }
- }
-
- real::real(float fl){ f = fl; }
-
- real::real(double d){ f = float(d); }
-
- real::real(char c){ f = float(c); }
-
- real::real(short s){ f = float(s); }
-
- real::real(INT I){ f = float(I); }
-
- int isqnan( real &r ){
- unsigned INT i = r.i;
- if ((i >= 0x7FC00000) && (i <= 0x7FFFFFFF))
- return 1;
- return 0;
- }
-
- int issnan( real &r ){
- unsigned INT i = r.i;
- if ((i >= 0x7F800001) && (i <= 0x7FBFFFFF))
- return 1;
- return 0;
- }
-
- int iszero( real &r ){
- unsigned INT i = r.i;
- if (i == 0)
- return 1;
- return 0;
- }
-
- int isinf( real &r ){
- unsigned INT i = r.i;
- if (i == 0x7F800000)
- return 1;
- return 0;
- }
-
- int isdenorm( real &r ){
- unsigned INT i = r.i;
- if ((i >= 0x00000001) && (i <= 0x007FFFFF))
- return 1;
- return 0;
- }
-
- int isnorm( real &r ){
- unsigned INT i = r.i;
- if ((i >= 0x00800000) && (i <= 0x7F7FFFFF))
- return 1;
- return 0;
- }
-
- int operator==( real &num, real &dem ){
- // this is a skeleton == operator for reals
- if (isnorm(num) && isnorm(num)) return (num.i == dem.i);
- else if (isqnan(num) && isqnan(dem)) return 1;
- else if (issnan(num) && issnan(dem)) return 1;
- else if (isinf(num) && isinf(dem)) return 1;
- else if (isdenorm(num) && isdenorm(dem)) return 1;
- return 0;
- }
-
- const char DIV_BY_NAN = 0;
- const char DIV_BY_QNAN = 1;
- const char DIV_BY_ZERO = 2;
- const char INVALID_OP = 3;
- const char DIV_BY_INF = 4;
-
- void set_psr(char c){
- // a stub for setting a user controlled processor control word
- }
-
- real result;
-
- real& operator/(real &nom, real &dem) {
- if (isqnan(nom) || isqnan(dem) || issnan(nom) || issnan(dem)){
- set_psr(DIV_BY_NAN);
- result.i = QNAN;
- return result;
- }
- else if (iszero(nom) && iszero(dem)){
- set_psr( DIV_BY_QNAN );
- result.i = QNAN;
- return result;
- }
- else if (iszero(dem)) {
- set_psr( DIV_BY_ZERO );
- result.i = INF;
- return result;
- }
- else if (isinf(nom) && isinf(dem)) {
- set_psr( INVALID_OP );
- result.i = QNAN;
- return result;
- }
- else if (isinf(nom) && isnorm(dem)) {
- set_psr( DIV_BY_INF );
- result.i = INF;
- return result;
- }
- else if ((isnorm(nom) || iszero(nom)) && isinf(dem)) {
- result.i = ZERO;
- return result;
- }
- result.f = float(nom.f) / float(dem.f);
- return result;
- } // end of real::operator/
-
- /*
- ** A very simple program showing real assignments, divide operations,
- ** output routines, and comparisons.
- */
-
- int main(void) {
-
- real r1;
- real r2 = 0.0;
- real r3 = 1.0;
- real rinf = "INF";
- real rqnan = "QNAN";
- real rsnan = "SNAN";
- real rzero = "ZERO";
- real rdenorm = "DENORM";
-
- cout << "r1 = " << r1 << "\n";
- cout << "r2 = " << r2 << "\n";
- cout << "r3 = " << r3 << "\n";
- cout << "rinf = " << rinf << "\n";
- cout << "rqnan = " << rqnan << "\n";
- cout << "rsnan = " << rsnan << "\n";
- cout << "rzero = " << rzero << "\n";
- cout << "rdenorm = " << rdenorm << "\n";
-
- r1 = r3 / r2; // this should generate an INF
- cout << "r1 = INF ?? " << r1 << "\n";
-
- r1 = rqnan / rqnan; // this should generate a QNAN
- cout << "rqnan = QNAN ?? " << rqnan << "\n";
-
- if (r1 == rsnan)
- cout << "WRONG!!! QNAN == SNAN\n";
- else
- cout << "RIGHT!!! QNAN != SNAN\n";
-
- } // end of main
-