00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #ifndef SHHALFALIMPL_HPP
00028 #define SHHALFALIMPL_HPP
00029
00030 #include <cmath>
00031 #include "ShMath.hpp"
00032 #include "ShHalf.hpp"
00033
00034 namespace SH {
00035
00036 inline
00037 ShHalf::ShHalf()
00038 {}
00039
00040 inline
00041 ShHalf::ShHalf(double value)
00042 : m_val(to_val(value))
00043 {
00044 }
00045
00046 inline
00047 ShHalf::operator double() const
00048 {
00049 return get_double();
00050 }
00051
00052
00054 inline
00055 ShHalf& ShHalf::operator=(double value)
00056 {
00057 m_val = to_val(value);
00058 return *this;
00059 }
00060
00061 inline
00062 ShHalf& ShHalf::operator=(const ShHalf& other)
00063 {
00064 m_val = other.m_val;
00065 return *this;
00066 }
00067
00068 inline
00069 ShHalf& ShHalf::operator+=(double value)
00070 {
00071 set_val(get_double() + value);
00072 return *this;
00073 }
00074
00075 inline
00076 ShHalf& ShHalf::operator+=(const ShHalf& other)
00077 {
00078 set_val(get_double() + other.get_double());
00079 return *this;
00080 }
00081
00082 inline
00083 ShHalf& ShHalf::operator-=(double value)
00084 {
00085 set_val(get_double() - value);
00086 return *this;
00087 }
00088
00089 inline
00090 ShHalf& ShHalf::operator-=(const ShHalf& other)
00091 {
00092 set_val(get_double() - other.get_double());
00093 return *this;
00094 }
00095
00096 inline
00097 ShHalf& ShHalf::operator*=(double value)
00098 {
00099 set_val(get_double() * value);
00100 return *this;
00101 }
00102
00103 inline
00104 ShHalf& ShHalf::operator*=(const ShHalf& other)
00105 {
00106 set_val(get_double() * other.get_double());
00107 return *this;
00108 }
00109
00110 inline
00111 ShHalf& ShHalf::operator/=(double value)
00112 {
00113 set_val(get_double() / value);
00114 return *this;
00115 }
00116
00117 inline
00118 ShHalf& ShHalf::operator/=(const ShHalf& other)
00119 {
00120 set_val(get_double() / other.get_double());
00121 return *this;
00122 }
00123
00124 inline
00125 ShHalf& ShHalf::operator%=(double value)
00126 {
00127 set_val(std::fmod(get_double(), value));
00128 return *this;
00129 }
00130
00131 inline
00132 ShHalf& ShHalf::operator%=(const ShHalf& other)
00133 {
00134 set_val(std::fmod(get_double(), other.get_double()));
00135 return *this;
00136 }
00137
00139 inline
00140 ShHalf ShHalf::operator-() const
00141 {
00142
00143 T result = m_val ^ S;
00144 return make_half(result);
00145 }
00146
00147 inline
00148 std::ostream& operator<<(std::ostream &out, const ShHalf &value)
00149 {
00150 out << double(value);
00151 return out;
00152 }
00153
00154 inline
00155 std::istream& operator>>(std::istream &in, ShHalf &value)
00156 {
00157 double temp;
00158 in >> temp;
00159 value = temp;
00160 return in;
00161 }
00162
00163 inline
00164 ShHalf ShHalf::make_half(T value)
00165 {
00166 ShHalf result;
00167 result.m_val = value;
00168 return result;
00169 }
00170
00171 inline
00172 ShHalf::T ShHalf::to_val(double value) {
00173 int exponent;
00174 double fraction = frexp(value, &exponent);
00175 short sign = fraction < 0;
00176 fraction = sign ? -fraction : fraction;
00177 T result;
00178
00179
00180
00181 result = (sign << 15);
00182 if(fraction == 0) {
00183 } else if(fabsf(value) > 65504) {
00184 result |= 31 << 10;
00185 } else if(exponent < -13) {
00186 int significand = (int)(fraction * (1LL << (exponent + 24)));
00187 result |= significand;
00188 } else {
00189 int significand = (int)((fraction - 0.5) * (1 << 11));
00190 result |= ((exponent + 14) << 10) | significand;
00191 }
00192 return result;
00193 }
00194
00195 inline
00196 void ShHalf::set_val(double value) {
00197 m_val = to_val(value);
00198 }
00199
00200 inline
00201 double ShHalf::get_double() const {
00202
00203 short sign = -((m_val >> 14) & 2) + 1;
00204 short exponent = (m_val >> 10) & 0x1F;
00205 short significand = m_val & 0x3FF;
00206 double fraction = sign * ((exponent ? 1 : 0) + significand / (double)(1 << 10));
00207
00208 return ldexp(fraction, (exponent ? exponent - 15 : -14));
00209 }
00210
00211 }
00212
00213 #endif