PBRT
|
00001 00002 // 00003 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas 00004 // Digital Ltd. LLC 00005 // 00006 // All rights reserved. 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are 00010 // met: 00011 // * Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // * Redistributions in binary form must reproduce the above 00014 // copyright notice, this list of conditions and the following disclaimer 00015 // in the documentation and/or other materials provided with the 00016 // distribution. 00017 // * Neither the name of Industrial Light & Magic nor the names of 00018 // its contributors may be used to endorse or promote products derived 00019 // from this software without specific prior written permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00034 00035 00036 00037 #ifndef INCLUDED_IMATHMATH_H 00038 #define INCLUDED_IMATHMATH_H 00039 00040 //---------------------------------------------------------------------------- 00041 // 00042 // ImathMath.h 00043 // 00044 // This file contains template functions which call the double- 00045 // precision math functions defined in math.h (sin(), sqrt(), 00046 // exp() etc.), with specializations that call the faster 00047 // single-precision versions (sinf(), sqrtf(), expf() etc.) 00048 // when appropriate. 00049 // 00050 // Example: 00051 // 00052 // double x = Math<double>::sqrt (3); // calls ::sqrt(double); 00053 // float y = Math<float>::sqrt (3); // calls ::sqrtf(float); 00054 // 00055 // When would I want to use this? 00056 // 00057 // You may be writing a template which needs to call some function 00058 // defined in math.h, for example to extract a square root, but you 00059 // don't know whether to call the single- or the double-precision 00060 // version of this function (sqrt() or sqrtf()): 00061 // 00062 // template <class T> 00063 // T 00064 // glorp (T x) 00065 // { 00066 // return sqrt (x + 1); // should call ::sqrtf(float) 00067 // } // if x is a float, but we 00068 // // don't know if it is 00069 // 00070 // Using the templates in this file, you can make sure that 00071 // the appropriate version of the math function is called: 00072 // 00073 // template <class T> 00074 // T 00075 // glorp (T x, T y) 00076 // { 00077 // return Math<T>::sqrt (x + 1); // calls ::sqrtf(float) if x 00078 // } // is a float, ::sqrt(double) 00079 // // otherwise 00080 // 00081 //---------------------------------------------------------------------------- 00082 00083 #include "ImathPlatform.h" 00084 #include "ImathLimits.h" 00085 #include <math.h> 00086 00087 namespace Imath { 00088 00089 00090 template <class T> 00091 struct Math 00092 { 00093 static T acos (T x) {return ::acos (double(x));} 00094 static T asin (T x) {return ::asin (double(x));} 00095 static T atan (T x) {return ::atan (double(x));} 00096 static T atan2 (T x, T y) {return ::atan2 (double(x), double(y));} 00097 static T cos (T x) {return ::cos (double(x));} 00098 static T sin (T x) {return ::sin (double(x));} 00099 static T tan (T x) {return ::tan (double(x));} 00100 static T cosh (T x) {return ::cosh (double(x));} 00101 static T sinh (T x) {return ::sinh (double(x));} 00102 static T tanh (T x) {return ::tanh (double(x));} 00103 static T exp (T x) {return ::exp (double(x));} 00104 static T log (T x) {return ::log (double(x));} 00105 static T log10 (T x) {return ::log10 (double(x));} 00106 static T modf (T x, T *iptr) 00107 { 00108 double ival; 00109 T rval( ::modf (double(x),&ival)); 00110 *iptr = ival; 00111 return rval; 00112 } 00113 static T pow (T x, T y) {return ::pow (double(x), double(y));} 00114 static T sqrt (T x) {return ::sqrt (double(x));} 00115 static T ceil (T x) {return ::ceil (double(x));} 00116 static T fabs (T x) {return ::fabs (double(x));} 00117 static T floor (T x) {return ::floor (double(x));} 00118 static T fmod (T x, T y) {return ::fmod (double(x), double(y));} 00119 static T hypot (T x, T y) {return ::hypot (double(x), double(y));} 00120 }; 00121 00122 00123 template <> 00124 struct Math<float> 00125 { 00126 static float acos (float x) {return ::acosf (x);} 00127 static float asin (float x) {return ::asinf (x);} 00128 static float atan (float x) {return ::atanf (x);} 00129 static float atan2 (float x, float y) {return ::atan2f (x, y);} 00130 static float cos (float x) {return ::cosf (x);} 00131 static float sin (float x) {return ::sinf (x);} 00132 static float tan (float x) {return ::tanf (x);} 00133 static float cosh (float x) {return ::coshf (x);} 00134 static float sinh (float x) {return ::sinhf (x);} 00135 static float tanh (float x) {return ::tanhf (x);} 00136 static float exp (float x) {return ::expf (x);} 00137 static float log (float x) {return ::logf (x);} 00138 static float log10 (float x) {return ::log10f (x);} 00139 static float modf (float x, float *y) {return ::modff (x, y);} 00140 static float pow (float x, float y) {return ::powf (x, y);} 00141 static float sqrt (float x) {return ::sqrtf (x);} 00142 static float ceil (float x) {return ::ceilf (x);} 00143 static float fabs (float x) {return ::fabsf (x);} 00144 static float floor (float x) {return ::floorf (x);} 00145 static float fmod (float x, float y) {return ::fmodf (x, y);} 00146 #if !defined(_MSC_VER) 00147 static float hypot (float x, float y) {return ::hypotf (x, y);} 00148 #else 00149 static float hypot (float x, float y) {return ::sqrtf(x*x + y*y);} 00150 #endif 00151 }; 00152 00153 00154 //-------------------------------------------------------------------------- 00155 // Don Hatch's version of sin(x)/x, which is accurate for very small x. 00156 // Returns 1 for x == 0. 00157 //-------------------------------------------------------------------------- 00158 00159 template <class T> 00160 inline T 00161 sinx_over_x (T x) 00162 { 00163 if (x * x < limits<T>::epsilon()) 00164 return T (1); 00165 else 00166 return Math<T>::sin (x) / x; 00167 } 00168 00169 00170 //-------------------------------------------------------------------------- 00171 // Compare two numbers and test if they are "approximately equal": 00172 // 00173 // equalWithAbsError (x1, x2, e) 00174 // 00175 // Returns true if x1 is the same as x2 with an absolute error of 00176 // no more than e, 00177 // 00178 // abs (x1 - x2) <= e 00179 // 00180 // equalWithRelError (x1, x2, e) 00181 // 00182 // Returns true if x1 is the same as x2 with an relative error of 00183 // no more than e, 00184 // 00185 // abs (x1 - x2) <= e * x1 00186 // 00187 //-------------------------------------------------------------------------- 00188 00189 template <class T> 00190 inline bool 00191 equalWithAbsError (T x1, T x2, T e) 00192 { 00193 return ((x1 > x2)? x1 - x2: x2 - x1) <= e; 00194 } 00195 00196 00197 template <class T> 00198 inline bool 00199 equalWithRelError (T x1, T x2, T e) 00200 { 00201 return ((x1 > x2)? x1 - x2: x2 - x1) <= e * ((x1 > 0)? x1: -x1); 00202 } 00203 00204 00205 00206 } // namespace Imath 00207 00208 #endif