home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
progjour
/
1991
/
03
/
except.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-17
|
6KB
|
265 lines
#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