$extrastylesheet
utility.h
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 #ifndef LIBMESH_UTILITY_H
00020 #define LIBMESH_UTILITY_H
00021 
00022 // Local includes
00023 #include "libmesh/libmesh_common.h" // for Real
00024 
00025 // System includes
00026 #include <string>
00027 #include <vector>
00028 #include <algorithm> // for std::lower_bound
00029 
00030 namespace libMesh
00031 {
00032 
00033 
00034 // ------------------------------------------------------------
00035 // The Utility namespace is for functions
00036 // which are useful but don't necessarily belong anywhere else.
00037 
00038 namespace Utility
00039 {
00040 //-------------------------------------------------------------------
00045 std::string system_info();
00046 
00047 
00048 
00049 //-------------------------------------------------------------------
00057 template <typename ForwardIter, typename T>
00058 void iota (ForwardIter first, ForwardIter last, T value)
00059 {
00060   while (first != last)
00061     {
00062       *first = value++;
00063       ++first;
00064     }
00065 }
00066 
00067 
00074 template< class InputIterator >
00075 bool is_sorted(InputIterator first, InputIterator last)
00076 {
00077   if ( first == last )
00078     return true;
00079 
00080   // "prev" always points to the entry just to the left of "first"
00081   //  [-    -    -    -    -    -]
00082   //   ^    ^
00083   // prev first
00084   //
00085   //  [-    -    -    -    -    -]
00086   //        ^    ^
00087   //      prev first
00088   //
00089   //  [-    -    -    -    -    -]
00090   //             ^    ^
00091   //           prev first
00092   InputIterator prev( first );
00093   for ( ++first; first != last; ++prev, ++first )
00094     if ( *first < *prev  )    // Note: this is the same as *prev > *first,
00095       return false;        // but we only require op< to be defined.
00096 
00097   // If we haven't returned yet, it's sorted!
00098   return true;
00099 
00100 
00101   // A one-liner version using adjacent_find.  This doesn't work for
00102   // C-style arrays, since their pointers do not have a value_type.
00103   //
00104   // Works by checking to see if adjacent entries satisfy *i >
00105   // *(i+1) and returns the first one which does.  If "last" is
00106   // returned, no such pair was found, and therefore the range must
00107   // be in non-decreasing order.
00108   //
00109   // return (last ==
00110   // std::adjacent_find(first, last,
00111   // std::greater< typename InputIterator::value_type >()));
00112 
00113   // A second one-linear attempt.  This one checks for a **strictly
00114   // increasing** (no duplicate entries) range.  Also doesn't work
00115   // with C-style arrays.
00116   //
00117   // return (last ==
00118   // std::adjacent_find(first, last,
00119   // std::not2(std::less<typename InputIterator::value_type>())));
00120 }
00121 
00122 
00129 template<class ForwardIterator, class T>
00130 ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T& value)
00131 {
00132   ForwardIterator it = std::lower_bound(first, last, value);
00133   return (it == last || value < *it) ? last : it;
00134 }
00135 
00139 template<class ForwardIterator, class T, class Compare>
00140 ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T& value, Compare comp)
00141 {
00142   ForwardIterator it = std::lower_bound(first, last, value, comp);
00143   return (it == last || comp(value,*it)) ? last : it;
00144 }
00145 
00146 
00147 //-------------------------------------------------------------------
00152 template <int N, typename T>
00153 struct do_pow {
00154   static inline T apply (const T& x)
00155   {
00156     libmesh_assert(N>1);
00157 
00158     if (N%2) // odd exponent
00159       return x * do_pow<N-1,T>::apply(x);
00160 
00161     const T xNover2 = do_pow<N/2,T>::apply(x);
00162 
00163     return xNover2*xNover2;
00164   }
00165 };
00166 
00167 // An efficient compiler would distill N=6 down to 3
00168 // multiplications, but an inefficient one (or a complicated
00169 // T::operator*) might do worse, so we'll specialize here.
00170 template <typename T>
00171 struct do_pow<6,T> {
00172   static inline T apply (const T& x)
00173   {
00174     const T x2 = x*x,
00175       x4 = x2*x2;
00176 
00177     return x4*x2;
00178   }
00179 };
00180 
00181 template <typename T>
00182 struct do_pow<1,T> {
00183   static inline T apply (const T& x) { return x; }
00184 };
00185 
00186 template <typename T>
00187 struct do_pow<0,T> {
00188   static inline T apply (const T&) { return 1; }
00189 };
00190 
00191 
00192 template <int N, typename T>
00193 inline
00194 T pow(const T& x)
00195 {
00196   return do_pow<N,T>::apply(x);
00197 }
00198 
00199 //-------------------------------------------------------------------
00203 inline
00204 unsigned int factorial(unsigned int n)
00205 {
00206 
00207   unsigned int factorial_n = 1;
00208 
00209   if (n==0)
00210     return factorial_n;
00211 
00212   for (unsigned int i=1; i<n; i++)
00213     factorial_n *= i+1;
00214 
00215   return factorial_n;
00216 }
00217 
00218 
00219 //-------------------------------------------------------------------
00223 template <typename T>
00224 void deallocate (std::vector<T> &vec)
00225 {
00226   std::vector<T>().swap(vec);
00227 }
00228 
00229 
00230 //-------------------------------------------------------------------
00231 // Utility functions useful when dealing with complex numbers.
00232 
00233 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00234 
00240 std::string complex_filename (const std::string& basename,
00241                               unsigned int r_o_c=0);
00242 
00246 void prepare_complex_data (const std::vector<Complex>& source,
00247                            std::vector<Real>& real_part,
00248                            std::vector<Real>& imag_part);
00249 
00250 #endif // #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00251 
00252 
00253 
00254 //-------------------------------------------------------------------
00263 class ReverseBytes
00264 {
00265 public:
00266 
00271   explicit
00272   ReverseBytes (const bool dr);
00273 
00278   template <typename T>
00279   T operator () (T& data) const;
00280 
00281 private:
00282 
00286   bool reverse () const { return _do_reverse; }
00287 
00291   const bool _do_reverse;
00292 };
00293 
00294 
00295 
00296 //---------------------------------------------------------
00297 // ReverseBytes inline members
00298 inline
00299 ReverseBytes::ReverseBytes (const bool rb) :
00300   _do_reverse (rb)
00301 {}
00302 
00303 
00304 template <typename T>
00305 inline
00306 T ReverseBytes::operator() (T& data) const
00307 {
00308   // Possibly reverse the byte ordering
00309   if (this->reverse())
00310     {
00311       unsigned char* b = (unsigned char*) &data;
00312 
00313       int i=0;
00314       int j=(sizeof(T) - 1);
00315 
00316       while (i < j)
00317         {
00318           std::swap (b[i], b[j]);
00319           i++; j--;
00320         }
00321     }
00322 
00323   return data;
00324 }
00325 
00326 
00327 }
00328 
00329 } // namespace libMesh
00330 
00331 #endif // LIBMESH_UTILITY_H