Intrepid
/usr/src/RPM/BUILD/trilinos-11.12.1/packages/intrepid/src/Shared/MiniTensor/Intrepid_MiniTensor_Utilities.i.h
00001 // @HEADER
00002 // ************************************************************************
00003 //
00004 //                           Intrepid Package
00005 //                 Copyright (2007) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions: Alejandro Mota (amota@sandia.gov)
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 
00042 #if !defined(Intrepid_MiniTensor_Utilities_i_h)
00043 #define Intrepid_MiniTensor_Utilities_i_h
00044 
00045 #include <cmath>
00046 #include <limits>
00047 
00048 namespace Intrepid {
00049 
00050 //
00051 // Sign function
00052 //
00053 template <typename T>
00054 inline
00055 int
00056 sgn(T const & s)
00057 {
00058   return (T(0) < s) - (s < T(0));
00059 }
00060 
00061 //
00062 // Copysign function
00063 //
00064 template<typename T>
00065 inline
00066 T
00067 copysign(T const & a, T const & b)
00068 {
00069   return b >= 0 ? std::abs(a) : -std::abs(a);
00070 }
00071 
00072 //
00073 // NaN function. Necessary to choose the proper underlying NaN
00074 // for non-floating-point types.
00075 // Assumption: non-floating-point types have a typedef that
00076 // determines the underlying floating-point type.
00077 //
00078 template<typename T>
00079 inline
00080 typename Sacado::ScalarType<T>::type
00081 not_a_number()
00082 {
00083   return
00084       std::numeric_limits<typename Sacado::ScalarType<T>::type>::quiet_NaN();
00085 }
00086 
00087 //
00088 // Machine epsilon function. Necessary to choose the proper underlying
00089 // machine epsilon for non-floating-point types.
00090 // Assumption: non-floating-point types have a typedef that
00091 // determines the underlying floating-point type.
00092 //
00093 template<typename T>
00094 inline
00095 typename Sacado::ScalarType<T>::type
00096 machine_epsilon()
00097 {
00098   return
00099       std::numeric_limits<typename Sacado::ScalarType<T>::type>::epsilon();
00100 }
00101 
00102 //
00103 // The circle constant
00104 //
00105 template<typename T>
00106 typename Sacado::ScalarType<T>::type
00107 tau()
00108 {
00109   typedef typename Sacado::ScalarType<T>::type S;
00110   return static_cast<S>(
00111       6.283185307179586476925286766559005768394338798750211641949889185
00112   );
00113 }
00114 
00115 //
00116 // Random number generation. Teuchos [-1,1]
00117 //
00118 template<typename T>
00119 inline
00120 typename Sacado::ScalarType<T>::type
00121 random()
00122 {
00123   typedef typename Sacado::ScalarType<T>::type S;
00124   return Teuchos::ScalarTraits<S>().random();
00125 }
00126 
00127 //
00128 // Uniform [0,1] random number generation.
00129 //
00130 template<typename T>
00131 inline
00132 typename Sacado::ScalarType<T>::type
00133 random_uniform()
00134 {
00135   typedef typename Sacado::ScalarType<T>::type S;
00136   return static_cast<S>(0.5 * random<S>() + 0.5);
00137 }
00138 
00139 //
00140 // Normal N(0,1) random number generation.
00141 //
00142 template<typename T>
00143 inline
00144 typename Sacado::ScalarType<T>::type
00145 random_normal()
00146 {
00147   typedef typename Sacado::ScalarType<T>::type S;
00148 
00149   S const
00150   R = random_uniform<S>();
00151 
00152   S const
00153   Theta = tau<S>() * random_uniform<S>();
00154 
00155   return static_cast<S>(std::sqrt(-2.0 * std::log(R)) * cos(Theta));
00156 }
00157 
00158 //
00159 // Compute a non-negative integer power by binary manipulation.
00160 //
00161 template<typename T>
00162 T
00163 integer_power(T const & X, Index const exponent)
00164 {
00165   if (X == 0 || X == 1) return X;
00166 
00167   switch (exponent) {
00168     default:
00169       break;
00170     case 0:
00171       return 1;
00172       break;
00173     case 1:
00174       return X;
00175       break;
00176     case 2:
00177       return X * X;
00178       break;
00179     case 3:
00180       return X * X * X;
00181       break;
00182     case 4:
00183     {
00184       T const Y = X * X;
00185       return Y * Y;
00186     }
00187     break;
00188   }
00189 
00190   Index const
00191   rightmost_bit = 1;
00192 
00193   Index const
00194   number_digits = std::numeric_limits<Index>::digits;
00195 
00196   Index const
00197   leftmost_bit = rightmost_bit << (number_digits - 1);
00198 
00199   Index
00200   t = 0;
00201 
00202   for (Index j = 0; j < number_digits; ++j) {
00203 
00204     if (((exponent << j) & leftmost_bit) != 0) {
00205 
00206       t = number_digits - j - 1;
00207       break;
00208 
00209     }
00210 
00211   }
00212 
00213   T
00214   P = X;
00215 
00216   Index
00217   i = 0;
00218 
00219   Index
00220   m = exponent;
00221 
00222   while ((m & rightmost_bit) == 0) {
00223     P = P * P;
00224     ++i;
00225     m = m >> 1;
00226   }
00227 
00228   T
00229   Y = P;
00230 
00231   for (Index j = i + 1; j <= t; ++j) {
00232     P = P * P;
00233 
00234     if (((exponent >> j) & rightmost_bit) != 0) {
00235       Y = Y * P;
00236     }
00237   }
00238 
00239   return Y;
00240 }
00241 
00242 } // namespace Intrepid
00243 
00244 #endif // Intrepid_MiniTensor_Utilities_i_h