Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShHalfImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright 2003-2005 Serious Hack Inc.
00004 // 
00005 // This software is provided 'as-is', without any express or implied
00006 // warranty. In no event will the authors be held liable for any damages
00007 // arising from the use of this software.
00008 // 
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it
00011 // freely, subject to the following restrictions:
00012 // 
00013 // 1. The origin of this software must not be misrepresented; you must
00014 // not claim that you wrote the original software. If you use this
00015 // software in a product, an acknowledgment in the product documentation
00016 // would be appreciated but is not required.
00017 // 
00018 // 2. Altered source versions must be plainly marked as such, and must
00019 // not be misrepresented as being the original software.
00020 // 
00021 // 3. This notice may not be removed or altered from any source
00022 // distribution.
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   //twiddle sign bit
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   // @todo range - use OpenEXR's version since this doesn't handle NaN and 
00178   // INF in value, and is rather slow. 
00179   result = (sign << 15);
00180   if(fraction == 0) { // zero
00181   } else if(fabsf(value) > 65504) { // INF
00182     result |= 31 << 10;
00183   } else if(exponent < -13) { // denormalized 
00184     int significand = (int)(fraction * (1LL << (exponent + 24)));
00185     result |= significand;
00186   } else { // normalized 
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   // @todo range - use OpenEXR's version since this is probably slow
00201   short sign = -((m_val >> 14) & 2) + 1; // -1 for negative, +1 for positive                   
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

Generated on Thu Apr 21 17:32:47 2005 for Sh by  doxygen 1.4.2