// class fp
#ifndef FP_H
#define FP_H
#include <iosfwd>
#include <limits>
#include <string>
class fp
{ // naive floating point implementation
public:
fp();
explicit fp(const char *);
explicit fp(double);
fp& operator += (const fp&);
fp& operator -= (const fp&);
fp& operator *= (const fp&);
fp& operator /= (const fp&);
friend fp operator - (const fp&);
friend bool operator == (const fp&, const fp&);
friend bool operator != (const fp&, const fp&);
friend bool operator < (const fp&, const fp&);
friend bool operator <= (const fp&, const fp&);
friend bool operator > (const fp&, const fp&);
friend bool operator >= (const fp&, const fp&);
static const fp zero;
static const fp one;
static const fp two;
friend std::string to_string(const fp&);
friend std::ostream& operator << (std::ostream&, const fp&);
enum round_mode
{
rm_nearest,
rm_down,
rm_up,
rm_zero
};
static void set_round(round_mode m) {rm = m;}
static round_mode get_round() {return rm;}
enum fp_exception
{
div_by_zero = 0x01,
exp_underflow = 0x02,
exp_overflow = 0x04,
inexact = 0x08,
invalid = 0x10
};
typedef fp (*exc_hnd)(fp_exception, fp);
static void set_flag(fp_exception);
static bool get_flag(fp_exception);
static void clear_flags();
static void set_flags(int);
static int get_flags();
static exc_hnd set_handler(fp_exception, exc_hnd);
static exc_hnd get_handler(fp_exception);
private:
fp(int e, int f, bool neg);
bool eq(const fp&) const;
bool lt(const fp&) const;
fp& add(const fp&, const fp&);
fp& normalize(int, long);
bool round(long&);
void convert(double);
long lf() const;
enum fpx
{ dbz, exu, exo, ine, inv, EXC_COUNT };
static fp exception(fpx, fp);
bool is_neg;
unsigned char exp;
int frac;
static round_mode rm;
static exc_hnd exc_hndlrs[EXC_COUNT];
static const exc_hnd def_hndlrs[EXC_COUNT];
static unsigned char exc_flg;
static const fp pinf;
static const fp ninf;
static const fp qnan;
static const fp snan;
static const fp pmax;
static const fp nmax;
static const fp nzero;
static fp ex_dbz(fp_exception, fp);
static fp ex_exu(fp_exception, fp);
static fp ex_exo(fp_exception, fp);
static fp ex_ine(fp_exception, fp);
static fp ex_inv(fp_exception, fp);
friend fp def_dbz(fp_exception, fp);
friend fp def_exu(fp_exception, fp);
friend fp def_exo(fp_exception, fp);
friend fp def_ine(fp_exception, fp);
friend fp def_inv(fp_exception, fp);
};
fp operator + (const fp&, const fp&);
fp operator - (const fp&, const fp&);
fp operator * (const fp&, const fp&);
fp operator / (const fp&, const fp&);
inline bool operator == (const fp& f1, const fp& f2)
{ // return f1 equal to f2
return f1.eq(f2);
}
inline bool operator != (const fp& f1, const fp& f2)
{ // return f1 not equal to f2
return !f1.eq(f2);
}
inline bool operator < (const fp& f1, const fp& f2)
{ // return f1 less than f2
return f1.lt(f2);
}
inline bool operator <= (const fp& f1, const fp& f2)
{ // return f1 less than or equal to f2
return !f2.lt(f1);
}
inline bool operator > (const fp& f1, const fp& f2)
{ // return f1 greater than f2
return f2.lt(f1);
}
inline bool operator >= (const fp& f1, const fp& f2)
{ // return f1 greater than or equal to f2
return !f1.lt(f2);
}
#endif /* FP_H */