| 1 |
//====================================================================== |
| 2 |
//----------------------------------------------------------------------- |
| 3 |
/** |
| 4 |
* @file FndIEEE.h |
| 5 |
* @brief IEEE754 ƒtƒ@ƒCƒ‹ |
| 6 |
* |
| 7 |
* @author t.sirayanagi |
| 8 |
* @version 1.0 |
| 9 |
* |
| 10 |
* @par copyright |
| 11 |
* Copyright (C) 2011-2012 Takazumi Shirayanagi\n |
| 12 |
* The new BSD License is applied to this software. |
| 13 |
* see iris_LICENSE.txt |
| 14 |
*/ |
| 15 |
//----------------------------------------------------------------------- |
| 16 |
//====================================================================== |
| 17 |
#ifndef INCG_IRIS_FndIEEE_H_ |
| 18 |
#define INCG_IRIS_FndIEEE_H_ |
| 19 |
|
| 20 |
//====================================================================== |
| 21 |
// include |
| 22 |
#include "../../iris_object.h" |
| 23 |
#include "../../iris_debug.h" |
| 24 |
#include "../../ml/iml_math.hpp" |
| 25 |
|
| 26 |
namespace iris { |
| 27 |
namespace fnd |
| 28 |
{ |
| 29 |
|
| 30 |
//====================================================================== |
| 31 |
// declare |
| 32 |
template<typename ttTN, int tiSIGN, int tiEXP, int tiFRAC, int tiBIAS>class CIEEE754; |
| 33 |
|
| 34 |
//====================================================================== |
| 35 |
// typedef |
| 36 |
typedef CIEEE754<u32, 1, 8, 23, 127> CIEEEBinary32; |
| 37 |
typedef CIEEE754<u64, 1, 11, 52, 1023> CIEEEBinary64; |
| 38 |
|
| 39 |
|
| 40 |
//====================================================================== |
| 41 |
// class |
| 42 |
/** |
| 43 |
* @brief IEEE 754 •‚“®�¬�”“_ƒNƒ‰ƒX |
| 44 |
* @tparam ttTN = Ši”[‚·‚é�®�”Œ^ |
| 45 |
* @tparam tiSIGN = •„�†•”‚̃rƒbƒg�”(0 or 1) |
| 46 |
* @tparam tiEXP = Žw�”•” |
| 47 |
* @tparam tiFRAC = ‰¼�”•” |
| 48 |
* @tparam tiBIAS = Žw�”•”‚̃oƒCƒAƒX |
| 49 |
*/ |
| 50 |
template<typename ttTN, int tiSIGN, int tiEXP, int tiFRAC, int tiBIAS = ::iml::static_pow<2, tiEXP-1>::value-1 > |
| 51 |
class CIEEE754 : public IIrisObject |
| 52 |
{ |
| 53 |
typedef ttTN value_type; |
| 54 |
typedef CIEEE754<ttTN, tiSIGN, tiEXP, tiFRAC, tiBIAS> _Myt; |
| 55 |
typedef CIEEEBinary32 floatType; |
| 56 |
typedef CIEEEBinary64 doubleType; |
| 57 |
|
| 58 |
IRIS_STATIC_ASSERT( tiSIGN == 0 || tiSIGN == 1 ); |
| 59 |
public: |
| 60 |
static const int SIGN = tiSIGN; //!< •„�†•”‚̃rƒbƒg�” |
| 61 |
static const int EXP = tiEXP; //!< Žw�”•”‚̃rƒbƒg�” |
| 62 |
static const int FRAC = tiFRAC; //!< ‰¼�”•”‚̃rƒbƒg�” |
| 63 |
static const int BIAS = tiBIAS; //!< Žw�”•”‚̃oƒCƒAƒX’l |
| 64 |
static const size_t BITSIZE = SIGN + EXP + FRAC; |
| 65 |
IRIS_STATIC_ASSERT( BITSIZE <= (sizeof(value_type)*8) ); |
| 66 |
|
| 67 |
public: |
| 68 |
static const value_type PINF = static_cast<value_type>(iml::static_mask<EXP , FRAC >::value); //!< + –³ŒÀ‘å |
| 69 |
static const value_type NINF = static_cast<value_type>(iml::static_mask<EXP+SIGN , FRAC >::value); //!< - –³ŒÀ‘å |
| 70 |
static const value_type PNAN = static_cast<value_type>(iml::static_mask<EXP , FRAC>::value | 0x1); //!< + NAN |
| 71 |
static const value_type NNAN = static_cast<value_type>(iml::static_mask<EXP+SIGN , FRAC>::value | 0x1); //!< - NAN |
| 72 |
static const value_type PQNAN = static_cast<value_type>(iml::static_mask<EXP+1 , FRAC-1>::value); //!< + QNAN |
| 73 |
static const value_type NQNAN = static_cast<value_type>(iml::static_mask<EXP+SIGN+1 , FRAC-1>::value); //!< - QNAN |
| 74 |
|
| 75 |
private: |
| 76 |
value_type m_value; //!< ’l |
| 77 |
|
| 78 |
public: |
| 79 |
/** |
| 80 |
* @name ƒRƒ“ƒXƒgƒ‰ƒNƒ^ |
| 81 |
* @{ |
| 82 |
*/ |
| 83 |
CIEEE754(void) : m_value(0) {} |
| 84 |
CIEEE754(float f) : m_value(0) { cast_from_float(f); } |
| 85 |
CIEEE754(const _Myt& rhs) : m_value(rhs.m_value) {} |
| 86 |
template<typename ttXTN, int tiXSIGN, int tiXEXP, int tiXFRAC, int tiXBIAS> |
| 87 |
CIEEE754(const CIEEE754<ttXTN, tiXSIGN, tiXEXP, tiXFRAC, tiXBIAS>& ieee) : m_value(0) { cast_from_ieee(ieee); } |
| 88 |
/** |
| 89 |
* @} |
| 90 |
*/ |
| 91 |
public: |
| 92 |
/** |
| 93 |
* @name operator |
| 94 |
* @{ |
| 95 |
*/ |
| 96 |
_Myt& operator = (float rhs) { cast_from_float(rhs); return *this; } |
| 97 |
template<typename _XTN, int _XSIGN, int _XEXP, int _XFRAC, int _XBIAS> |
| 98 |
_Myt& operator = (const CIEEE754<_XTN, _XSIGN, _XEXP, _XFRAC, _XBIAS>& ieee) { cast_from_ieee(ieee); return *this; } |
| 99 |
|
| 100 |
operator float (void) const { return cast_to_float(); } |
| 101 |
operator double (void) const { return cast_to_double(); } |
| 102 |
/** |
| 103 |
* @} |
| 104 |
*/ |
| 105 |
|
| 106 |
public: |
| 107 |
//! ’l‚̎擾 |
| 108 |
value_type& value(void) { return m_value; } |
| 109 |
value_type value(void) const { return m_value; } |
| 110 |
|
| 111 |
private: |
| 112 |
// ƒLƒƒƒXƒg |
| 113 |
void cast_from_float(float f) |
| 114 |
{ |
| 115 |
IrisFInt fi = f; |
| 116 |
|
| 117 |
value_type exp = (fi.iv >> floatType::FRAC) & iml::static_mask<floatType::EXP>::value; |
| 118 |
if( exp == iml::static_mask<floatType::EXP>::value ) |
| 119 |
{ |
| 120 |
exp = iml::static_mask<EXP>::value; |
| 121 |
} |
| 122 |
else if( exp != 0 ) |
| 123 |
{ |
| 124 |
exp = exp - floatType::BIAS + BIAS; |
| 125 |
if( exp >= iml::static_lshift<1, EXP>::value ) |
| 126 |
{ |
| 127 |
// INF |
| 128 |
m_value = (((exp>>(sizeof(exp)-1))&0x1)<<EXP) | iml::static_mask<EXP>::value; |
| 129 |
m_value <<= FRAC; |
| 130 |
return; |
| 131 |
} |
| 132 |
} |
| 133 |
m_value = (value_type)(iml::signed_rshift<(floatType::FRAC+floatType::EXP)-(FRAC+EXP)>::shift(fi.iv) & iml::static_mask<1, EXP+FRAC>::value); |
| 134 |
m_value |= exp << FRAC; |
| 135 |
m_value |= iml::signed_rshift<floatType::FRAC-FRAC>::shift( static_cast<IrisU32>(fi.iv & iml::static_mask<floatType::FRAC>::value) ); |
| 136 |
} |
| 137 |
template<typename XTN_, int XSIGN_, int XEXP_, int XFRAC_, int XBIAS_> |
| 138 |
void cast_from_ieee(const CIEEE754<XTN_, XSIGN_, XEXP_, XFRAC_, XBIAS_>& ieee) |
| 139 |
{ |
| 140 |
XTN_ value = ieee.value(); |
| 141 |
value_type exp = static_cast<value_type>((value >> XFRAC_) & iml::static_mask<XEXP_>::value); |
| 142 |
if( exp == iml::static_mask<XEXP_>::value ) |
| 143 |
{ |
| 144 |
exp = iml::static_mask<EXP>::value; |
| 145 |
} |
| 146 |
else if( exp != 0 ) |
| 147 |
{ |
| 148 |
exp = exp - ieee.BIAS + BIAS; |
| 149 |
if( exp >= static_cast<value_type>(iml::static_lshift<1, EXP>::value) ) |
| 150 |
{ |
| 151 |
// INF |
| 152 |
m_value = (((exp>>(sizeof(exp)-1))&0x1)<<EXP) | iml::static_mask<EXP>::value; |
| 153 |
m_value <<= FRAC; |
| 154 |
return; |
| 155 |
} |
| 156 |
} |
| 157 |
m_value = static_cast<value_type>(iml::signed_rshift<(XFRAC_+XEXP_)-(FRAC+EXP)>::shift(static_cast<value_type>(value)) & iml::static_mask<1, EXP+FRAC>::value); |
| 158 |
m_value |= exp << FRAC; |
| 159 |
m_value |= iml::signed_rshift<XFRAC_-FRAC>::shift( static_cast<value_type>(value & iml::static_mask<XFRAC_>::value) ); |
| 160 |
} |
| 161 |
|
| 162 |
float cast_to_float(void) const |
| 163 |
{ |
| 164 |
floatType ieee(*this); |
| 165 |
IrisFInt fi = ieee.value(); |
| 166 |
return fi.fv; |
| 167 |
} |
| 168 |
double cast_to_double(void) const |
| 169 |
{ |
| 170 |
doubleType ieee(*this); |
| 171 |
IrisF64Int fi = ieee.value(); |
| 172 |
return fi.fv; |
| 173 |
} |
| 174 |
|
| 175 |
public: |
| 176 |
// •„�†•” |
| 177 |
value_type sign(void) { return (m_value >> (EXP+FRAC)) & iml::static_mask<SIGN>::value; } |
| 178 |
void sign(value_type s) { m_value &= iml::static_mask<EXP+FRAC>::value; m_value |= ((s&1) << (EXP+FRAC)); } |
| 179 |
|
| 180 |
// Žw�”•” |
| 181 |
value_type exp(void) { return (m_value >> FRAC) & iml::static_mask<EXP>::value; } |
| 182 |
void exp(value_type e) { m_value &= ~iml::static_mask<EXP, FRAC>::value; m_value |= (e&iml::static_mask<EXP>::value) << FRAC; } |
| 183 |
|
| 184 |
// ‰¼�”•” |
| 185 |
value_type frac(void) { return m_value & iml::static_mask<FRAC>::value; } |
| 186 |
void frac(value_type f) { m_value &= ~iml::static_mask<FRAC>::value; m_value |= f&iml::static_mask<FRAC>::value; } |
| 187 |
}; |
| 188 |
|
| 189 |
} // end of namespace fnd |
| 190 |
} // end of namespace iris |
| 191 |
|
| 192 |
#endif |