Listing 1: Class definition for floating-point class fp

//    fp.h
//    class fp

#ifndef FP_H
#define FP_H

#include <iosfwd>
#include <limits>
#include <string>

class fp;
template <> class std::numeric_limits<fp>;

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;}

private:
    friend class std::numeric_limits<fp>;
    fp(int e, int f);

    bool eq(const fp&) const;
    bool lt(const fp&) const;
    
    fp& add(const fp&, const fp&);
    fp& normalize(int, long);
    void round(long&);
    void convert(double);
    long lf() const;
    
    enum fp_exception
        {
        div_by_zero,
        exp_underflow,
        exp_overflow
        };

    void exception(fp_exception);

    bool is_neg;
    unsigned char exp;
    int frac;
    static round_mode rm;

};

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);
    }

template <> class std::numeric_limits<fp>
{    // specialization of std::numeric_limits for class fp
public:
    static const bool is_specialized = true;
    static fp min()
        {    // return minimum normalized value
        return fp(min_exponent,0x4000);
        }
    static fp max()
        {    // return maximum finite value
        return fp(max_exponent, 0x7fff);
        }
    static const int digits = 15;
    static const int digits10 = 4;
    static const bool is_signed = true;
    static const bool is_integer = false;
    static const bool is_exact = false;
    static const int radix = 2;
    static fp epsilon()
        {    // return f - 1.0, where f is smallest value
            // greater than 1.0 that can be represented
        return fp(-13, 0x4000);
        }
    static fp round_error()
        {    // return estimate of the maximum rounding error
        return fp(0.5);
        }

    static const int min_exponent = -128;
    static const int min_exponent10 = -38;
    static const int max_exponent = 127;
    static const int max_exponent10 = 38;

    static const bool has_infinity = false;
    static const bool has_quiet_NaN = false;
    static const bool has_signaling_NaN = false;
    static const std::float_denorm_style has_denorm = 
        std::denorm_absent;
    static const bool has_denorm_loss = false;
    static fp infinity() throw();
    static fp quiet_NaN() throw();
    static fp signaling_NaN() throw();
    static fp denorm_min()
        {    // return minimum denormalized value 
             // (denormals not supported)
        return min();
        }

    static const bool is_iec559 = false;
    static const bool is_bounded = true;
    static const bool is_modulo = false;

    static const bool traps = false;
    static const bool tinyness_before = false;
    static const std::float_round_style round_style = 
       std::round_to_nearest;
};

#endif    /* FP_H */