mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-26 13:50:33 +05:00
161 lines
4.1 KiB
C++
161 lines
4.1 KiB
C++
#ifndef NETGEN_CORE_UTILS_HPP
|
|
#define NETGEN_CORE_UTILS_HPP
|
|
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <map>
|
|
#include <ostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#ifdef WIN32
|
|
#include <intrin.h> // for __rdtsc() CPU time step counter
|
|
#else
|
|
#include <x86intrin.h> // for __rdtsc() CPU time step counter
|
|
#endif // WIN32
|
|
|
|
#include "ngcore_api.hpp" // for NGCORE_API
|
|
|
|
namespace ngcore
|
|
{
|
|
// MPI rank, nranks TODO: Rename
|
|
extern NGCORE_API int id, ntasks;
|
|
|
|
NGCORE_API std::string Demangle(const char* typeinfo);
|
|
|
|
#if defined(__GNUC__)
|
|
inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); }
|
|
inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); }
|
|
#else
|
|
inline bool likely (bool x) { return x; }
|
|
inline bool unlikely (bool x) { return x; }
|
|
#endif
|
|
|
|
using TClock = std::chrono::system_clock;
|
|
extern NGCORE_API const std::chrono::time_point<TClock> wall_time_start;
|
|
|
|
// Time in seconds since program start
|
|
inline double WallTime () noexcept
|
|
{
|
|
std::chrono::time_point<TClock> now = TClock::now();
|
|
std::chrono::duration<double> elapsed_seconds = now-wall_time_start;
|
|
return elapsed_seconds.count();
|
|
}
|
|
|
|
// High precision clock counter register
|
|
using TTimePoint = size_t;
|
|
extern NGCORE_API double ticks_per_second;
|
|
|
|
inline TTimePoint GetTimeCounter() noexcept
|
|
{
|
|
return TTimePoint(__rdtsc());
|
|
}
|
|
|
|
template <class T>
|
|
inline std::string ToString (const T& t)
|
|
{
|
|
std::stringstream ss;
|
|
ss << t;
|
|
return ss.str();
|
|
}
|
|
|
|
template<typename T1, typename T2>
|
|
std::ostream& operator << (std::ostream& ost, const std::map<T1,T2>& map)
|
|
{
|
|
for(auto& val : map)
|
|
ost << "\n" << val.first << ": " << val.second;
|
|
return ost;
|
|
}
|
|
|
|
template <class T>
|
|
NETGEN_INLINE void Swap (T & a, T & b)
|
|
{
|
|
T temp = std::move(a);
|
|
a = std::move(b);
|
|
b = std::move(temp);
|
|
}
|
|
|
|
template <typename T>
|
|
class AlignedAlloc
|
|
{
|
|
protected:
|
|
static void * aligned_malloc(size_t s)
|
|
{
|
|
// Assume 16 byte alignment of standard library
|
|
if(alignof(T)<=16)
|
|
return malloc(s);
|
|
else
|
|
return _mm_malloc(s, alignof(T));
|
|
}
|
|
|
|
static void aligned_free(void *p)
|
|
{
|
|
if(alignof(T)<=16)
|
|
free(p);
|
|
else
|
|
_mm_free(p);
|
|
}
|
|
|
|
public:
|
|
void * operator new (size_t s, void *p) { return p; }
|
|
void * operator new (size_t s) { return aligned_malloc(s); }
|
|
void * operator new[] (size_t s) { return aligned_malloc(s); }
|
|
void operator delete (void * p) { aligned_free(p); }
|
|
void operator delete[] (void * p) { aligned_free(p); }
|
|
};
|
|
|
|
// checks if string starts with sequence
|
|
inline bool StartsWith(const std::string& str, const std::string& start)
|
|
{
|
|
if(start.size() > str.size())
|
|
return false;
|
|
return std::equal(start.begin(), start.end(), str.begin());
|
|
}
|
|
|
|
// checks if string ends with sequence
|
|
inline bool EndsWith(const std::string& str, const std::string& end)
|
|
{
|
|
if(end.size() > str.size())
|
|
return false;
|
|
return std::equal(end.rbegin(), end.rend(), str.rbegin());
|
|
}
|
|
|
|
template<typename T>
|
|
NETGEN_INLINE std::atomic<T> & AsAtomic (T & d)
|
|
{
|
|
return reinterpret_cast<std::atomic<T>&> (d);
|
|
}
|
|
|
|
NETGEN_INLINE double AtomicAdd( double & sum, double val )
|
|
{
|
|
std::atomic<double> & asum = AsAtomic(sum);
|
|
double current = asum.load();
|
|
while (!asum.compare_exchange_weak(current, current + val))
|
|
;
|
|
return current;
|
|
}
|
|
|
|
template<typename T>
|
|
NETGEN_INLINE T AtomicMin( T & minval, T val )
|
|
{
|
|
std::atomic<T> & aminval = AsAtomic(minval);
|
|
T current = aminval.load();
|
|
while (!aminval.compare_exchange_weak(current, std::min(current, val)))
|
|
;
|
|
return current;
|
|
}
|
|
|
|
template<typename T>
|
|
NETGEN_INLINE T AtomicMax( T & maxval, T val )
|
|
{
|
|
std::atomic<T> & amaxval = AsAtomic(maxval);
|
|
T current = amaxval.load();
|
|
while (!amaxval.compare_exchange_weak(current, std::max(current, val)))
|
|
;
|
|
return current;
|
|
}
|
|
|
|
} // namespace ngcore
|
|
|
|
#endif // NETGEN_CORE_UTILS_HPP
|