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 library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00018 // MA  02110-1301, USA
00020 #ifndef SHHALFALIMPL_HPP
00021 #define SHHALFALIMPL_HPP
00022 
00023 #include <iostream>
00024 #include <cmath>
00025 #include "ShMath.hpp"
00026 #include "ShHalf.hpp"
00027 
00028 namespace SH {
00029 
00030 inline
00031 ShHalf::ShHalf()
00032 {}
00033 
00034 inline
00035 ShHalf::ShHalf(double value)
00036   : m_val(to_val(value))
00037 {
00038 }
00039 
00040 inline
00041 ShHalf::operator double() const
00042 {
00043   return get_double();
00044 }
00045 
00046 
00048 inline
00049 ShHalf& ShHalf::operator=(double value)
00050 {
00051   m_val = to_val(value);
00052   return *this;
00053 }
00054 
00055 inline
00056 ShHalf& ShHalf::operator=(const ShHalf& other)
00057 {
00058   m_val = other.m_val;
00059   return *this;
00060 }
00061 
00062 inline
00063 ShHalf& ShHalf::operator+=(double value)
00064 {
00065   set_val(get_double() + value); 
00066   return *this;
00067 }
00068 
00069 inline
00070 ShHalf& ShHalf::operator+=(const ShHalf& other)
00071 {
00072   set_val(get_double() + other.get_double());
00073   return *this;
00074 }
00075 
00076 inline
00077 ShHalf& ShHalf::operator-=(double value)
00078 {
00079   set_val(get_double() - value);
00080   return *this; 
00081 }
00082 
00083 inline
00084 ShHalf& ShHalf::operator-=(const ShHalf& other)
00085 {
00086   set_val(get_double() - other.get_double());
00087   return *this; 
00088 }
00089 
00090 inline
00091 ShHalf& ShHalf::operator*=(double value)
00092 {
00093   set_val(get_double() * value);
00094   return *this; 
00095 }
00096 
00097 inline
00098 ShHalf& ShHalf::operator*=(const ShHalf& other)
00099 {
00100   set_val(get_double() * other.get_double());
00101   return *this;
00102 }
00103 
00104 inline
00105 ShHalf& ShHalf::operator/=(double value)
00106 {
00107   set_val(get_double() / value);
00108   return *this; 
00109 }
00110 
00111 inline
00112 ShHalf& ShHalf::operator/=(const ShHalf& other)
00113 {
00114   set_val(get_double() / other.get_double());
00115   return *this;
00116 }
00117 
00118 inline
00119 ShHalf& ShHalf::operator%=(double value)
00120 {
00121   set_val(std::fmod(get_double(), value));
00122   return *this; 
00123 }
00124 
00125 inline
00126 ShHalf& ShHalf::operator%=(const ShHalf& other)
00127 {
00128   set_val(std::fmod(get_double(), other.get_double()));
00129   return *this;
00130 }
00131 
00133 inline
00134 ShHalf ShHalf::operator-() const 
00135 {
00136   //twiddle sign bit
00137   T result = m_val ^ S;
00138   return make_half(result);
00139 }
00140 
00141 inline
00142 std::ostream& operator<<(std::ostream &out, const ShHalf &value)
00143 {
00144   out << double(value); 
00145   return out;
00146 }
00147 
00148 inline
00149 std::istream& operator>>(std::istream &in, ShHalf &value)
00150 {
00151   double temp;
00152   in >> temp;
00153   value = temp;
00154   return in;
00155 }
00156 
00157 inline
00158 ShHalf ShHalf::make_half(T value)
00159 {
00160   ShHalf result;
00161   result.m_val = value; 
00162   return result;
00163 }
00164 
00165 inline
00166 ShHalf::T ShHalf::to_val(double value) {
00167   int exponent;
00168   double fraction = frexp(value, &exponent);
00169   short sign = fraction < 0;
00170   fraction = sign ? -fraction : fraction;
00171   T result;
00172 
00173   // @todo range - use OpenEXR's version since this doesn't handle NaN and 
00174   // INF in value, and is rather slow. 
00175   result = (sign << 15);
00176   if(fraction == 0) { // zero
00177   } else if(fabs(value) > 65504) { // INF
00178     result |= 31 << 10;
00179   } else if(exponent < -13) { // denormalized 
00180     int significand = (int)(fraction * (1LL << (exponent + 24)));
00181     result |= significand;
00182   } else { // normalized 
00183     int significand = (int)((fraction - 0.5) * (1 << 11));
00184     result |= ((exponent + 14) << 10) | significand;
00185   }
00186   return result;
00187 }
00188 
00189 inline
00190 void ShHalf::set_val(double value) {
00191   m_val = to_val(value);
00192 }
00193 
00194 inline
00195 double ShHalf::get_double() const {
00196   // @todo range - use OpenEXR's version since this is probably slow
00197   short sign = -((m_val >> 14) & 2) + 1; // -1 for negative, +1 for positive                   
00198   short exponent = (m_val >> 10) & 0x1F;
00199   short significand = m_val & 0x3FF;
00200   double fraction = sign * ((exponent ? 1 : 0) + significand / (double)(1 << 10));
00201 
00202   return ldexp(fraction, (exponent ? exponent - 15 : -14));
00203 }
00204 
00205 }
00206 
00207 #endif

Generated on Thu Jul 28 17:33:02 2005 for Sh by  doxygen 1.4.3-20050530