Listing 1: The new version of the header fp.h

// 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 */