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 (c) 2003 University of Waterloo Computer Graphics Laboratory
00004 // Project administrator: Michael D. McCool
00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
00006 //          Michael D. McCool
00007 // 
00008 // This software is provided 'as-is', without any express or implied
00009 // warranty. In no event will the authors be held liable for any damages
00010 // arising from the use of this software.
00011 // 
00012 // Permission is granted to anyone to use this software for any purpose,
00013 // including commercial applications, and to alter it and redistribute it
00014 // freely, subject to the following restrictions:
00015 // 
00016 // 1. The origin of this software must not be misrepresented; you must
00017 // not claim that you wrote the original software. If you use this
00018 // software in a product, an acknowledgment in the product documentation
00019 // would be appreciated but is not required.
00020 // 
00021 // 2. Altered source versions must be plainly marked as such, and must
00022 // not be misrepresented as being the original software.
00023 // 
00024 // 3. This notice may not be removed or altered from any source
00025 // distribution.
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   //twiddle sign bit
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   // @todo range - use OpenEXR's version since this doesn't handle NaN and 
00180   // INF in value, and is rather slow. 
00181   result = (sign << 15);
00182   if(fraction == 0) { // zero
00183   } else if(fabsf(value) > 65504) { // INF
00184     result |= 31 << 10;
00185   } else if(exponent < -13) { // denormalized 
00186     int significand = (int)(fraction * (1LL << (exponent + 24)));
00187     result |= significand;
00188   } else { // normalized 
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   // @todo range - use OpenEXR's version since this is probably slow
00203   short sign = -((m_val >> 14) & 2) + 1; // -1 for negative, +1 for positive                   
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

Generated on Mon Jan 24 18:36:32 2005 for Sh by  doxygen 1.4.1