summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/ptypes.h
blob: d34651b9f7005f95c50c9fc2ee4b12f3b708ac7b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// license:GPL-2.0+
// copyright-holders:Couriersud

#ifndef PTYPES_H_
#define PTYPES_H_

///
/// \file ptypes.h
///

#include "pconfig.h"

#include <limits>
#include <string>
#include <type_traits>

// noexcept on move operator -> issue with macosx clang
#define COPYASSIGNMOVE(name, def)  \
		name(const name &) = def; \
		name(name &&) noexcept = def; \
		name &operator=(const name &) = def; \
		name &operator=(name &&) noexcept = def;

#define COPYASSIGN(name, def)  \
		name(const name &) = def; \
		name &operator=(const name &) = def; \

namespace plib
{
	template<typename T> struct is_integral : public std::is_integral<T> { };
	template<typename T> struct numeric_limits : public std::numeric_limits<T> { };

	// 128 bit support at least on GCC is not fully supported
#if PHAS_INT128
	template<> struct is_integral<UINT128> { static constexpr bool value = true; };
	template<> struct is_integral<INT128> { static constexpr bool value = true; };
	template<> struct numeric_limits<UINT128>
	{
		static constexpr UINT128 max() noexcept
		{
			return ~((UINT128)0);
		}
	};
	template<> struct numeric_limits<INT128>
	{
		static constexpr INT128 max() noexcept
		{
			return (~((UINT128)0)) >> 1;
		}
	};
#endif

	//============================================================
	// prevent implicit copying
	//============================================================

	struct nocopyassignmove
	{
		nocopyassignmove(const nocopyassignmove &) = delete;
		nocopyassignmove(nocopyassignmove &&) = delete;
		nocopyassignmove &operator=(const nocopyassignmove &) = delete;
		nocopyassignmove &operator=(nocopyassignmove &&) = delete;
	protected:
		nocopyassignmove() = default;
		~nocopyassignmove() = default;
	};

	struct nocopyassign
	{
		nocopyassign(const nocopyassign &) = delete;
		nocopyassign &operator=(const nocopyassign &) = delete;
	protected:
		nocopyassign() = default;
		~nocopyassign() = default;
		nocopyassign(nocopyassign &&) = default;
		nocopyassign &operator=(nocopyassign &&) = default;
	};

	//============================================================
	// Avoid unused variable warnings
	//============================================================
	template<typename... Ts>
	inline void unused_var(Ts&&...) noexcept {}

	//============================================================
	// is_pow2
	//============================================================
	template <typename T>
	constexpr bool is_pow2(T v) noexcept
	{
		static_assert(is_integral<T>::value, "is_pow2 needs integer arguments");
		return !(v & (v-1));
	}

	//============================================================
	// abs, lcd, gcm
	//============================================================

	template<typename T>
	constexpr
	typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type
	abs(T v) noexcept
	{
		return v < 0 ? -v : v;
	}

	template<typename T>
	constexpr
	typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, T>::type
	abs(T v) noexcept
	{
		return v;
	}

	template<typename M, typename N>
	constexpr typename std::common_type<M, N>::type
	gcd(M m, N n) noexcept
	{
		static_assert(std::is_integral<M>::value, "gcd: M must be an integer");
		static_assert(std::is_integral<N>::value, "gcd: N must be an integer");

		return m == 0 ? plib::abs(n)
			 : n == 0 ? plib::abs(m)
			 : gcd(n, m % n);
	}

	template<typename M, typename N>
	constexpr typename std::common_type<M, N>::type
	lcm(M m, N n) noexcept
	{
		static_assert(std::is_integral<M>::value, "lcm: M must be an integer");
		static_assert(std::is_integral<N>::value, "lcm: N must be an integer");

		return (m != 0 && n != 0) ? (plib::abs(m) / gcd(m, n)) * plib::abs(n) : 0;
	}

} // namespace plib

//============================================================
// Define a "has member" trait.
//============================================================

#define PDEFINE_HAS_MEMBER(name, member)                                        \
	template <typename T> class name                                            \
	{                                                                           \
		template <typename U> static long test(decltype(&U:: member));          \
		template <typename U> static char  test(...);                           \
	public:                                                                     \
		static constexpr const bool value = sizeof(test<T>(nullptr)) == sizeof(long);   \
	}

#endif // PTYPES_H_