libMesh
utility.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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 // When looking for a complicated suffix to a filename, we only want
384 // to consider the base name, without any preceding path name.
385 // "/tmp/foo.e25ad0/mesh.msh" is not ExodusII.
386 std::string_view basename_of(const std::string & fullname);
387 
388 
392 bool contains(std::string_view superstring,
393  std::string_view substring);
394 
395 
399 bool ends_with(std::string_view superstring,
400  std::string_view suffix);
401 
402 
403 // Utility functions useful when dealing with complex numbers.
404 
405 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
406 
412 std::string complex_filename (std::string basename,
413  unsigned int r_o_c=0);
414 
418 void prepare_complex_data (const std::vector<Complex> & source,
419  std::vector<Real> & real_part,
420  std::vector<Real> & imag_part);
421 
422 #endif // #ifdef LIBMESH_USE_COMPLEX_NUMBERS
423 
424 
428 int mkdir(const char* pathname);
429 
430 
438 std::string unzip_file (std::string_view name);
439 
440 
450 {
451 public:
452 
457  explicit
458  ReverseBytes (const bool dr);
459 
464  template <typename T>
465  T operator () (T & data) const;
466 
467 private:
468 
472  bool reverse () const { return _do_reverse; }
473 
477  const bool _do_reverse;
478 };
479 
480 
481 
482 // ReverseBytes inline members
483 inline
484 ReverseBytes::ReverseBytes (const bool rb) :
485  _do_reverse (rb)
486 {}
487 
488 
489 template <typename T>
490 inline
491 T ReverseBytes::operator() (T & data) const
492 {
493  // Possibly reverse the byte ordering
494  if (this->reverse())
495  {
496  unsigned char * b = (unsigned char *) &data;
497 
498  int i=0;
499  int j=(sizeof(T) - 1);
500 
501  while (i < j)
502  {
503  std::swap (b[i], b[j]);
504  i++; j--;
505  }
506  }
507 
508  return data;
509 }
510 
511 
512 
518 {
524  using is_transparent = void;
525 
530  template <class T>
531  bool operator()(const std::unique_ptr<T> & a, const std::unique_ptr<T> & b) const
532  {
533  return a.get() < b.get();
534  }
535 
539  template <class T>
540  bool operator()(const std::unique_ptr<T> & a, const T * const & b) const
541  {
542  return a.get() < b;
543  }
544 
548  template <class T>
549  bool operator()(const T * const & a, const std::unique_ptr<T> & b) const
550  {
551  return a < b.get();
552  }
553 };
554 
555 } // namespace Utility
556 
557 } // namespace libMesh
558 
559 #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:449
const bool _do_reverse
flag
Definition: utility.h:477
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
bool ends_with(std::string_view superstring, std::string_view suffix)
Look for a substring at the very end of a string.
Definition: utility.C:213
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:524
int mkdir(const char *pathname)
Create a directory.
Definition: utility.C:152
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:491
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:164
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:531
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:133
std::string complex_filename(std::string basename, unsigned int r_o_c=0)
Definition: utility.C:119
bool contains(std::string_view superstring, std::string_view substring)
Look for a substring within a string.
Definition: utility.C:205
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:549
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:540
std::string_view basename_of(const std::string &fullname)
Definition: utility.C:108
Struct which defines a custom comparison object that can be used with std::sets of std::unique_ptrs...
Definition: utility.h:517
unsigned int factorial(unsigned int n)
A simple implementation of the factorial.
Definition: utility.h:337
static const bool value
Definition: xdr_io.C:55
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:484
T binomial(T n, T k)
Definition: utility.h:354