libMesh
utility.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2024 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 #ifndef LIBMESH_UTILITY_H
20 #define LIBMESH_UTILITY_H
21 
22 // LibMesh includes
23 #include "libmesh/libmesh_common.h" // for Real
24 
25 // C++ includes
26 #include <string>
27 #include <vector>
28 #include <algorithm> // is_sorted, lower_bound
29 #include <memory> // unique_ptr
30 
31 namespace libMesh
32 {
33 
39 #define libmesh_map_find(map, key) libMesh::Utility::map_find((map), (key), __FILE__, __LINE__)
40 
46 #define libmesh_vector_at(vec, idx) libMesh::Utility::vector_at((vec), (idx), __FILE__, __LINE__)
47 
48 // ------------------------------------------------------------
49 // The Utility namespace is for functions
50 // which are useful but don't necessarily belong anywhere else.
51 
52 namespace Utility
53 {
54 
59 std::string system_info();
60 
64 template <typename T>
66 {
67  template <typename U> // must be template to get SFINAE fall-through...
68  static auto test(const U* u) -> decltype(std::cout << *u);
69 
70  static auto test(...) -> std::false_type;
71 
72 public:
74 };
75 
85 #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
86 #if (__GNUC__ > 12)
87 #pragma GCC diagnostic push
88 #pragma GCC diagnostic ignored "-Wdangling-reference"
89 #endif
90 #endif
91 
101 template<typename Map, typename Key,
102  typename std::enable_if<!is_streamable<Key>::value, Key>::type* = nullptr>
103 inline
104 typename Map::mapped_type &
105 map_find(Map & map,
106  const Key & key,
107  const char * filename,
108  int line_number)
109 {
110  auto it = map.find(key);
111  libmesh_error_msg_if(it == map.end(),
112  "map_find() error: key not found in file "
113  << filename << " on line " << line_number);
114  return it->second;
115 }
116 
120 template<typename Map, typename Key,
121  typename std::enable_if<!is_streamable<Key>::value, Key>::type* = nullptr>
122 inline
123 const typename Map::mapped_type &
124 map_find(const Map & map,
125  const Key & key,
126  const char * filename,
127  int line_number)
128 {
129  auto it = map.find(key);
130  libmesh_error_msg_if(it == map.end(),
131  "map_find() error: key not found in file "
132  << filename << " on line " << line_number);
133  return it->second;
134 }
135 
140 template<typename Map, typename Key,
141  typename std::enable_if<is_streamable<Key>::value, Key>::type* = nullptr>
142 inline
143 typename Map::mapped_type &
144 map_find(Map & map,
145  const Key & key,
146  const char * filename,
147  int line_number)
148 {
149  auto it = map.find(key);
150  libmesh_error_msg_if(it == map.end(),
151  "map_find() error: key \"" << key << "\" not found in file "
152  << filename << " on line " << line_number);
153  return it->second;
154 }
155 
159 template<typename Map, typename Key,
160  typename std::enable_if<is_streamable<Key>::value, Key>::type* = nullptr>
161 inline
162 const typename Map::mapped_type &
163 map_find(const Map & map,
164  const Key & key,
165  const char * filename,
166  int line_number)
167 {
168  auto it = map.find(key);
169  libmesh_error_msg_if(it == map.end(),
170  "map_find() error: key \"" << key << "\" not found in file "
171  << filename << " on line " << line_number);
172  return it->second;
173 }
174 
175 // The map_find functions are our only dangling-reference false positives
176 
177 #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
178 #if (__GNUC__ > 12)
179 #pragma GCC diagnostic pop
180 #endif
181 #endif
182 
183 
189 template<typename Vector>
190 inline
191 typename Vector::reference &
192 vector_at(Vector & vec,
193  typename Vector::size_type i,
194  const char * filename,
195  int line_number)
196 {
197  libmesh_error_msg_if(i >= vec.size(),
198  "vec_at() error: Index " << i <<
199  " past end of vector in file " << filename <<
200  " on line " << line_number);
201  return vec[i];
202 }
203 
207 template<typename Vector>
208 inline
209 typename Vector::const_reference &
210 vector_at(const Vector & vec,
211  typename Vector::size_type i,
212  const char * filename,
213  int line_number)
214 {
215  libmesh_error_msg_if(i >= vec.size(),
216  "vec_at() error: Index " << i <<
217  " past end of vector in file " << filename <<
218  " on line " << line_number);
219  return vec[i];
220 }
221 
222 
223 #ifdef LIBMESH_ENABLE_DEPRECATED
224 
228 template <typename ForwardIter, typename T>
229 void iota (ForwardIter first, ForwardIter last, T value)
230 {
231  // Use std::iota instead!
232  libmesh_deprecated();
233 
234  while (first != last)
235  {
236  *first = value++;
237  ++first;
238  }
239 }
240 
241 
246 template<class InputIterator >
247 bool is_sorted(InputIterator first, InputIterator last)
248 {
249  libmesh_deprecated();
250  return std::is_sorted(first, last);
251 }
252 #endif // LIBMESH_ENABLE_DEPRECATED
253 
254 
264 template<class ForwardIterator, class T>
265 ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T & value)
266 {
267  ForwardIterator it = std::lower_bound(first, last, value);
268  return (it == last || value < *it) ? last : it;
269 }
270 
274 template<class ForwardIterator, class T, class Compare>
275 ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T & value, Compare comp)
276 {
277  ForwardIterator it = std::lower_bound(first, last, value, comp);
278  return (it == last || comp(value,*it)) ? last : it;
279 }
280 
281 
286 template <int N, typename T>
287 struct do_pow {
288  static inline T apply (const T & x)
289  {
290  libmesh_assert(N>1);
291 
292  if (N%2) // odd exponent
293  return x * do_pow<N-1,T>::apply(x);
294 
295  const T xNover2 = do_pow<N/2,T>::apply(x);
296 
297  return xNover2*xNover2;
298  }
299 };
300 
301 // An efficient compiler would distill N=6 down to 3
302 // multiplications, but an inefficient one (or a complicated
303 // T::operator*) might do worse, so we'll specialize here.
304 template <typename T>
305 struct do_pow<6,T> {
306  static inline T apply (const T & x)
307  {
308  const T x2 = x*x,
309  x4 = x2*x2;
310 
311  return x4*x2;
312  }
313 };
314 
315 template <typename T>
316 struct do_pow<1,T> {
317  static inline T apply (const T & x) { return x; }
318 };
319 
320 template <typename T>
321 struct do_pow<0,T> {
322  static inline T apply (const T &) { return 1; }
323 };
324 
325 
326 template <int N, typename T>
327 inline
328 T pow(const T & x)
329 {
330  return do_pow<N,T>::apply(x);
331 }
332 
336 inline
337 unsigned int factorial(unsigned int n)
338 {
339 
340  unsigned int factorial_n = 1;
341 
342  if (n==0)
343  return factorial_n;
344 
345  for (unsigned int i=1; i<n; i++)
346  factorial_n *= i+1;
347 
348  return factorial_n;
349 }
350 
351 
352 // Simple function to compute "n choose k", aka the binomial coefficient.
353 template <typename T>
354 T binomial(T n, T k)
355 {
356  T ret = 1;
357 
358  // Binomial function is "symmetric" in k, C(n, k) = C(n, n-k).
359  if (k > n - k)
360  k = n - k;
361 
362  // Compute n * (n-1) * ... * (n-k+1) / (k * (k-1) * ... * 1)
363  for (T i = 0; i < k; ++i)
364  {
365  ret *= (n - i);
366  ret /= (i + 1);
367  }
368 
369  return ret;
370 }
371 
372 
376 template <typename T>
377 void deallocate (std::vector<T> & vec)
378 {
379  std::vector<T>().swap(vec);
380 }
381 
382 
383 // Utility functions useful when dealing with complex numbers.
384 
385 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
386 
392 std::string complex_filename (std::string basename,
393  unsigned int r_o_c=0);
394 
398 void prepare_complex_data (const std::vector<Complex> & source,
399  std::vector<Real> & real_part,
400  std::vector<Real> & imag_part);
401 
402 #endif // #ifdef LIBMESH_USE_COMPLEX_NUMBERS
403 
404 
408 int mkdir(const char* pathname);
409 
410 
418 std::string unzip_file (std::string_view name);
419 
420 
430 {
431 public:
432 
437  explicit
438  ReverseBytes (const bool dr);
439 
444  template <typename T>
445  T operator () (T & data) const;
446 
447 private:
448 
452  bool reverse () const { return _do_reverse; }
453 
457  const bool _do_reverse;
458 };
459 
460 
461 
462 // ReverseBytes inline members
463 inline
464 ReverseBytes::ReverseBytes (const bool rb) :
465  _do_reverse (rb)
466 {}
467 
468 
469 template <typename T>
470 inline
471 T ReverseBytes::operator() (T & data) const
472 {
473  // Possibly reverse the byte ordering
474  if (this->reverse())
475  {
476  unsigned char * b = (unsigned char *) &data;
477 
478  int i=0;
479  int j=(sizeof(T) - 1);
480 
481  while (i < j)
482  {
483  std::swap (b[i], b[j]);
484  i++; j--;
485  }
486  }
487 
488  return data;
489 }
490 
491 
492 
498 {
504  using is_transparent = void;
505 
510  template <class T>
511  bool operator()(const std::unique_ptr<T> & a, const std::unique_ptr<T> & b) const
512  {
513  return a.get() < b.get();
514  }
515 
519  template <class T>
520  bool operator()(const std::unique_ptr<T> & a, const T * const & b) const
521  {
522  return a.get() < b;
523  }
524 
528  template <class T>
529  bool operator()(const T * const & a, const std::unique_ptr<T> & b) const
530  {
531  return a < b.get();
532  }
533 };
534 
535 
536 }
537 
538 } // namespace libMesh
539 
540 #endif // LIBMESH_UTILITY_H
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
This Functor simply takes an object and reverses its byte representation.
Definition: utility.h:429
const bool _do_reverse
flag
Definition: utility.h:457
Map::mapped_type & map_find(Map &map, const Key &key, const char *filename, int line_number)
-Wdangling-reference was nowhere near ready to add to -Wall in gcc 13.
Definition: utility.h:105
void deallocate(std::vector< T > &vec)
A convenient method to truly empty a vector using the "swap trick".
Definition: utility.h:377
Vector::reference & vector_at(Vector &vec, typename Vector::size_type i, const char *filename, int line_number)
A replacement for std::vector::at(i) which is meant to be used with a macro, and, unlike at()...
Definition: utility.h:192
void is_transparent
As of C++14, std::set::find() can be a templated overload.
Definition: utility.h:504
int mkdir(const char *pathname)
Create a directory.
Definition: utility.C:144
The libMesh namespace provides an interface to certain functionality in the library.
std::string system_info()
Definition: utility.C:63
void iota(ForwardIter first, ForwardIter last, T value)
Utility::iota was created back when std::iota was just an SGI STL extension.
Definition: utility.h:229
static T apply(const T &)
Definition: utility.h:322
static T apply(const T &x)
Definition: utility.h:317
T pow(const T &x)
Definition: utility.h:328
T operator()(T &data) const
Functor.
Definition: utility.h:471
std::string unzip_file(std::string_view name)
Create an unzipped copy of a bz2 or xz file, returning the name of the now-unzipped file that can be ...
Definition: utility.C:156
libmesh_assert(ctx)
bool operator()(const std::unique_ptr< T > &a, const std::unique_ptr< T > &b) const
This is already what the default operator< comparison for std::unique_ptrs does, we are not adding an...
Definition: utility.h:511
void prepare_complex_data(const std::vector< Complex > &source, std::vector< Real > &real_part, std::vector< Real > &imag_part)
Prepare complex data for writing.
Definition: utility.C:125
std::string complex_filename(std::string basename, unsigned int r_o_c=0)
Definition: utility.C:111
An efficient template instantiation for raising to an arbitrary integer power.
Definition: utility.h:287
static T apply(const T &x)
Definition: utility.h:288
bool operator()(const T *const &a, const std::unique_ptr< T > &b) const
operator< comparison when lhs is a dumb pointer
Definition: utility.h:529
static T apply(const T &x)
Definition: utility.h:306
bool operator()(const std::unique_ptr< T > &a, const T *const &b) const
operator< comparison when rhs is a dumb pointer
Definition: utility.h:520
Struct which defines a custom comparison object that can be used with std::sets of std::unique_ptrs...
Definition: utility.h:497
unsigned int factorial(unsigned int n)
A simple implementation of the factorial.
Definition: utility.h:337
static const bool value
Definition: xdr_io.C:54
bool is_sorted(InputIterator first, InputIterator last)
Utility::is_sorted was created back when std::is_sorted was just an SGI STL extension.
Definition: utility.h:247
ForwardIterator binary_find(ForwardIterator first, ForwardIterator last, const T &value)
The STL provides std::binary_search() which returns true or false depending on whether the searched-f...
Definition: utility.h:265
static auto test(const U *u) -> decltype(std::cout<< *u)
Helper struct for enabling template metaprogramming/SFINAE.
Definition: utility.h:65
ReverseBytes(const bool dr)
Constructor.
Definition: utility.h:464
T binomial(T n, T k)
Definition: utility.h:354