1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
#ifndef __fixed_point_header_h__
#define __fixed_point_header_h__
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/operators.hpp>
#include <boost/concept_check.hpp>
#include <limits>
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#define __FP_DEFINED_USE_MATH_DEFINES__
#endif
namespace fp {
// FP The fixed point(base) type, should be an integer type
// I Integer part bit count
// F fractional part bit count
template<typename FP, unsigned char I, unsigned char F = std::numeric_limits<FP>::digits - I>
// boost/operators implements a few operators directly, others are //implemented automatically by the ordered_field_operators and shiftable templates.
class fixed_point: boost::ordered_field_operators<fp::fixed_point<FP, I, F> >
{
BOOST_CONCEPT_ASSERT((boost::Integer<FP>)); //assures that only integer types can be used as the fixed point type.
BOOST_STATIC_ASSERT(I + F == std::numeric_limits<FP>::digits); // The number of bits of the base type must satisfy the following formula:(B)=S+I+F
//As the fixed_point class needs 2 to the power of P in several parts for //floating point conversions, template recursion using template metaprogramming //is used to calculate 2 to the power of F at compile time itself.
template<int P,typename T = void>
struct power2
{
static const long long value = 2 * power2<P-1,T>::value;
};
template <typename P>
struct power2<0, P>
{
static const long long value = 1;
};
/// Initializing constructor.
//! This constructor takes a value of type FP and initializes the //internal representation of fixed_point<FP, I, F> with it.
fixed_point(FP value,bool): fixed_(value){ } // initializer list
public:
typedef FP base_type; /// fixed point base type of this fixed_point cass.
static const unsigned char integer_bit_count = I; /// integer part bit count.
static const unsigned char fractional_bit_count = F; /// fractional part bit count.
fixed_point(){ } /// Default constructor.
//Conversion by constructors.
//Integer to Fixed point
//This constructor takes an integer value of type T and converts it to the //fixed_point<B, I, F> type.
template<typename T> fixed_point(T value) : fixed_((FP)value << F)
{
BOOST_CONCEPT_ASSERT((boost::Integer<T>));
}
//floating point to fixed point
fixed_point(float value) :fixed_((FP)(value * power2<F>::value))
{ }
fixed_point(double value) : fixed_((FP)(value * power2<F>::value))
{ }
fixed_point(long double value) : fixed_((FP)(value * power2<F>::value))
{ }
/// Copy constructor,explicit definition
fixed_point(
/// The right hand side.
fixed_point<FP, I, F> const& rhs)
: fixed_(rhs.fixed_)
{ }
// copy-and-swap idiom.
/// Copy assignment operator.
fp::fixed_point<FP, I, F> & operator =(fp::fixed_point<FP, I, F> const& rhs)
{
fp::fixed_point<FP, I, F> temp(rhs);
swap(temp); //swapping the copied(old) data the new data.
return *this; //return by reference
}
/// Exchanges the elements of two fixed_point objects.
void swap(
/// The right hand side.
fp::fixed_point<FP, I, F> & rhs)
{
std::swap(fixed_, rhs.fixed_);
}
//Less than operator.
//The boost::ordered_field_operators class automatically implements
//operator >, operator >=, and operator <= in terms of operator <
//return true if less than, false otherwise.
bool operator <(
/// Right hand side.
fp::fixed_point<FP, I, F> const& rhs) const
{
return
fixed_ < rhs.fixed_; //return by value
}
bool operator ==(
/// Right hand side.
fp::fixed_point<FP, I, F> const& rhs) const
{
return
fixed_ == rhs.fixed_; //return by value
}
/// Negation operator.
bool operator !() const
{
return fixed_ == 0;
}
/// Unary minus operator.
//!
//! For signed fixed-point types you can apply the unary minus operator to
//! get the additive inverse.
fp::fixed_point<FP, I, F> operator -() const
{
fp::fixed_point<FP, I, F> result;
result.fixed_ = -fixed_;
return result; // return The negative value.
}
/// Addition.
fp::fixed_point<FP, I, F> & operator +=(fp::fixed_point<FP, I, F> const& summation)
{
fixed_ += summation.fixed_;
return *this; //! /return A reference to this object.
}
/// Subtraction.
fp::fixed_point<FP, I, F> & operator -=(fp::fixed_point<FP, I, F> const& subtraction)
{
fixed_ -= subtraction.fixed_;
return *this; // return A reference to this object.
}
/// Multiplication.
fp::fixed_point<FP, I, F> & operator *=(
/// Factor for mutliplication.
fp::fixed_point<FP, I, F> const& factor)
{
fixed_ = (fixed_) * factor.fixed_ >> F; // shifting right
return *this; //return A reference to this object.
}
/// Division.
fp::fixed_point<FP, I, F> & operator /=(
/// Divisor for division.
fp::fixed_point<FP, I, F> const& divisor)
{
fixed_ = (fixed_) << F / divisor.fixed_; // shifting left
return *this; //return A reference to this object.
}
/// fixed to a float.
operator const float()
{
return (float)fixed_ / power2<F>::value;
}
/// fixed to a double.
operator const double()
{
return (double)fixed_ / power2<F>::value;
}
/// fixed to a long double.
operator const long double()
{
return (long double)fixed_ / power2<F>::value;
}
private:
/// The value in fixed point format.
FP fixed_;
};
} // namespace fmpl
#ifdef __FPML_DEFINED_USE_MATH_DEFINES__
#undef _USE_MATH_DEFINES
#undef __FPML_DEFINED_USE_MATH_DEFINES__
#endif
#endif // __fixed_point_h__
|