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