Skip to content

Commit ec29956

Browse files
committed
Remove some copy/paste constructors and unify them in one templated constructor
1 parent 8e36d82 commit ec29956

File tree

6 files changed

+103
-103
lines changed

6 files changed

+103
-103
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ifneq (,$(findstring g++,$(CXX)))
44
CXXFLAGS += --coverage
55
endif
66

7-
CXXFLAGS += -Wall -pedantic -std=c++14 -g -I$(UNITTEST_CPP_INCLUDE) -Iinclude
7+
CXXFLAGS += -Wall -pedantic -std=c++17 -g -I$(UNITTEST_CPP_INCLUDE) -Iinclude
88
LDFLAGS = -lUnitTest++ -lgcov
99

1010
HEADERS = $(shell find include/ -type f)

include/FixedPoint/FixedPoint.hpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,14 @@ class FixedPoint
2828
StorageType v;
2929

3030
constexpr FixedPoint() : v(int64_t(0)) {}
31-
constexpr FixedPoint(float v);
32-
constexpr FixedPoint(double v);
33-
constexpr FixedPoint(long double v);
34-
constexpr FixedPoint(int v);
35-
constexpr FixedPoint(long int v);
36-
constexpr FixedPoint(long long int v);
3731
constexpr FixedPoint(unsigned long long int v);
3832
constexpr FixedPoint(FixedPoint const &o);
3933
constexpr FixedPoint(StorageType const &s);
4034
template<int oiw, int ofw, typename otherStorageType> constexpr FixedPoint(FixedPoint<oiw,ofw,otherStorageType> const &o);
4135

36+
template<typename T>
37+
constexpr FixedPoint(T const & v);
38+
4239
static constexpr FP _maxVal();
4340
static constexpr FP _minVal();
4441
static constexpr FP _smallestVal();
@@ -52,7 +49,7 @@ class FixedPoint
5249
constexpr FP& operator*=(FP const &o);
5350
constexpr FP& operator*=(int64_t const &o);
5451
constexpr FP& operator/=(FP const &o);
55-
constexpr FP& operator/=(int64_t const &o);
52+
constexpr FP& operator/=(int64_t const &o);
5653
constexpr FP& operator%=(FP const &o);
5754

5855
constexpr FP operator-() const;

include/FixedPoint/FixedPointConstructors.hpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,20 @@ constexpr void FixedPoint<integerWidth, fractionalWidth, storageType>::construct
3535
}
3636
}
3737

38-
#define CONSTRUCTOR template<int integerWidth, int fractionalWidth, typename storageType> constexpr FixedPoint<integerWidth, fractionalWidth, storageType>::FixedPoint
39-
40-
#define CONSTRUCT_WITH_FUNCTION(T, FUN) \
41-
CONSTRUCTOR(T v) { \
42-
FUN<T>(v);\
38+
template<int integerWidth, int fractionalWidth, typename storageType>
39+
template<typename T>
40+
constexpr FixedPoint<integerWidth, fractionalWidth, storageType>::FixedPoint(T const &v) {
41+
constexpr bool is_floating_type = FixedPointHelpers::is_one_of<T, float, double, long double>::value;
42+
constexpr bool is_signed_int_type = FixedPointHelpers::is_one_of<T, char, short, int, long, long long>::value;
43+
static_assert(is_floating_type || is_signed_int_type, "T must be floating point or signed integer type");
44+
if constexpr(is_floating_type) {
45+
construct_from_float<T>(v);
46+
} else if constexpr(is_signed_int_type) {
47+
construct_from_int<T>(v);
48+
}
4349
}
4450

45-
CONSTRUCT_WITH_FUNCTION(float, construct_from_float)
46-
CONSTRUCT_WITH_FUNCTION(double, construct_from_float)
47-
CONSTRUCT_WITH_FUNCTION(long double, construct_from_float)
48-
CONSTRUCT_WITH_FUNCTION(int, construct_from_int)
49-
CONSTRUCT_WITH_FUNCTION(long int, construct_from_int)
50-
CONSTRUCT_WITH_FUNCTION(long long int, construct_from_int)
51+
#define CONSTRUCTOR template<int integerWidth, int fractionalWidth, typename storageType> constexpr FixedPoint<integerWidth, fractionalWidth, storageType>::FixedPoint
5152

5253
CONSTRUCTOR(StorageType const &s) : v(s) {}
5354

@@ -58,7 +59,6 @@ CONSTRUCTOR(unsigned long long int v)
5859

5960
CONSTRUCTOR(FixedPoint const &o) : v(o.v) {}
6061

61-
#undef CONSTRUCT_WITH_FUNCTION
6262
#undef CONSTRUCTOR
6363

6464
template<int integerWidth, int fractionalWidth, typename storageType>

include/FixedPoint/FixedPointHelpers.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@ namespace FixedPointHelpers {
1414
template<> class make_bigger<uint16_t> { public: typedef uint32_t type; };
1515
template<> class make_bigger<uint32_t> { public: typedef uint64_t type; };
1616

17+
template<typename T, typename... Args>
18+
struct is_one_of;
19+
20+
template<typename T, typename U, typename... Us>
21+
struct is_one_of<T, U, Us...> {
22+
static constexpr bool value = std::is_same<T, U>::value || is_one_of<T, Us...>::value;
23+
};
24+
template<typename T>
25+
struct is_one_of<T> {
26+
static constexpr bool value = false;
27+
};
28+
29+
1730
template<typename T>
1831
constexpr unsigned nlz_constexpr(T x_) {
1932
typedef typename std::make_unsigned<T>::type UT;

include/FixedPoint/MultiwordInteger.hpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,15 @@ class MultiwordInteger
3636
constexpr MultiwordInteger() : s{0} {}
3737
template<unsigned otherSize> constexpr MultiwordInteger(MultiwordInteger<otherSize, storageType> const &o);
3838
constexpr MultiwordInteger(storageType const &v);
39+
40+
/**
41+
* This constructor accepts an int*_t, unsigned long long, float, double, or long double
42+
*/
43+
template<typename T>
44+
constexpr MultiwordInteger(T v);
3945

40-
constexpr MultiwordInteger(int8_t v);
41-
constexpr MultiwordInteger(int16_t v);
42-
constexpr MultiwordInteger(int32_t v);
43-
constexpr MultiwordInteger(int64_t v);
44-
template<typename U = _storageType, typename EN = std::enable_if<std::is_same<U, unsigned long long>::value == false>>
45-
constexpr MultiwordInteger(unsigned long long int v, typename EN::type * = 0);
46-
constexpr MultiwordInteger(float v);
47-
constexpr MultiwordInteger(double v);
48-
constexpr MultiwordInteger(long double v);
49-
50-
template<unsigned otherSize, typename otherStorageType> constexpr MultiwordInteger(MultiwordInteger<otherSize, otherStorageType> const &o);
46+
template<unsigned otherSize, typename otherStorageType>
47+
constexpr MultiwordInteger(MultiwordInteger<otherSize, otherStorageType> const &o);
5148

5249
constexpr MultiwordInteger<size, storageType>& operator+=(MultiwordInteger<size, storageType> const &o);
5350
constexpr MultiwordInteger<size, storageType>& operator-=(MultiwordInteger<size, storageType> const &o);

include/FixedPoint/MultiwordIntegerConstructors.hpp

Lines changed: 65 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
#include "MultiwordInteger.hpp"
88
#include "FixedPointHelpers.hpp"
99

10-
template<unsigned size, typename storageType> template<unsigned otherSize> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(MultiwordInteger<otherSize, storageType> const &o) : s{0} {
10+
template<unsigned size, typename storageType>
11+
template<unsigned otherSize>
12+
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(MultiwordInteger<otherSize, storageType> const &o) : s{0} {
1113
unsigned num = size > otherSize ? otherSize : size;
1214
for (unsigned i = 0; i < num; i++) {
1315
s[i] = o.s[i];
@@ -22,83 +24,19 @@ template<unsigned size, typename storageType> template<unsigned otherSize> const
2224
}
2325
}
2426
}
25-
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(storageType const &v) : s{v} {
27+
28+
template<unsigned size, typename storageType>
29+
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(storageType const &v) : s{v} {
2630
if (static_cast<signedType>(v) < 0) {
2731
for (unsigned i = 1; i < size; i++) {
2832
s[i] = static_cast<signedType>(-1);
2933
}
3034
}
3135
}
32-
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(int8_t v) : s{0} {
33-
*this = MultiwordInteger<size, std::make_unsigned<decltype(v)>::type>(v);
34-
}
35-
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(int16_t v) : s{0} {
36-
*this = MultiwordInteger<size, std::make_unsigned<decltype(v)>::type>(v);
37-
}
38-
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(int32_t v) : s{0} {
39-
*this = MultiwordInteger<size, std::make_unsigned<decltype(v)>::type>(v);
40-
}
41-
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(int64_t v) : s{0} {
42-
uint64_t uv = v;
43-
unsigned i = 0;
44-
for (; i < size && uv; i++) {
45-
s[i] = uv;
46-
uv >>= storageSize;
47-
}
48-
for (; i < size; i++) {
49-
s[i] = 0;
50-
}
51-
if(v < 0) {
52-
fill_leading_bits(leading_zeros());
53-
}
54-
}
55-
template<unsigned size, typename storageType>
56-
template<typename U, typename EN>
57-
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(unsigned long long int v, typename EN::type *) {
58-
*this = MultiwordInteger<size, storageType>((long long)v);
59-
}
60-
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(float v) : s{0} {
61-
if (v != 0.) {
62-
if (v > INT32_MIN && v < INT32_MAX) {
63-
int32_t i = int32_t(v);
64-
*this = i;
65-
} else {
66-
int lg = FixedPointHelpers::ilogb(v);
67-
v *= FixedPointHelpers::dipow<float>(2, 30-lg);
68-
*this = int64_t(v);
69-
*this <<= lg - 30;
70-
}
71-
}
72-
}
73-
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(double v) : s{0} {
74-
if (v != 0.) {
75-
if (v > double(INT64_MIN) && v < double(INT64_MAX)) {
76-
int64_t i = int64_t(v);
77-
*this = i;
78-
} else {
79-
int lg = FixedPointHelpers::ilogb(v);
80-
v *= FixedPointHelpers::dipow<double>(2, 62-lg);
81-
*this = MultiwordInteger(int64_t(v));
82-
*this <<= lg - 62;
83-
}
84-
}
85-
}
86-
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(long double v) : s{0} {
87-
if (v != 0.) {
88-
if (v > INT64_MIN && v < INT64_MAX) {
89-
int64_t i = int64_t(v);
90-
*this = i;
91-
} else {
92-
while (std::abs(v) >= 1) {
93-
double tv = v;
94-
MultiwordInteger<size, storageType> tmwi = tv;
95-
*this += tmwi;
96-
v -= tv;
97-
}
98-
}
99-
}
100-
}
101-
template<unsigned size, typename storageType> template<unsigned otherSize, typename otherStorageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(MultiwordInteger<otherSize, otherStorageType> const &o) : s{0} {
36+
37+
template<unsigned size, typename storageType>
38+
template<unsigned otherSize, typename otherStorageType>
39+
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(MultiwordInteger<otherSize, otherStorageType> const &o) : s{0} {
10240
static_assert((sizeof(storageType) % sizeof(otherStorageType)) == 0
10341
|| (sizeof(otherStorageType) % sizeof(storageType)) == 0,
10442
"Types must fit into each other without remainder.");
@@ -155,4 +93,59 @@ template<unsigned size, typename storageType> template<unsigned otherSize, typen
15593
}
15694
}
15795

96+
template<unsigned size, typename storageType>
97+
template<typename T>
98+
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(T v) : s{0} {
99+
static_assert(FixedPointHelpers::is_one_of<T, int8_t, int16_t, int32_t, int64_t, float, double, long double, unsigned long long>::value, "T must be a signed int or floating point type, or unsigned long long");
100+
if constexpr (FixedPointHelpers::is_one_of<T, int8_t, int16_t, int32_t>::value) {
101+
*this = MultiwordInteger<size, typename std::make_unsigned<T>::type>(v);
102+
}
103+
else if constexpr(FixedPointHelpers::is_one_of<T, int64_t>::value) {
104+
uint64_t uv = v;
105+
unsigned i = 0;
106+
for (; i < size && uv; i++) {
107+
s[i] = uv;
108+
uv >>= storageSize;
109+
}
110+
for (; i < size; i++) {
111+
s[i] = 0;
112+
}
113+
if(v < 0) {
114+
fill_leading_bits(leading_zeros());
115+
}
116+
}
117+
else if constexpr(FixedPointHelpers::is_one_of<T, float, double>::value) {
118+
if (v != 0.) {
119+
using IntType = typename std::conditional<std::is_same<T, float>::value, int32_t, int64_t>::type;
120+
if (v > std::numeric_limits<IntType>::min() && v < std::numeric_limits<IntType>::max()) {
121+
IntType i = IntType(v);
122+
*this = i;
123+
} else {
124+
int lg = FixedPointHelpers::ilogb(v);
125+
v *= FixedPointHelpers::dipow<T>(2, sizeof(IntType)*8-2-lg);
126+
*this = MultiwordInteger(int64_t(v));
127+
*this <<= lg + 2 - sizeof(IntType)*8;
128+
}
129+
}
130+
}
131+
else if constexpr(FixedPointHelpers::is_one_of<T, long double>::value) {
132+
if (v != 0.) {
133+
if (v > INT64_MIN && v < INT64_MAX) {
134+
int64_t i = int64_t(v);
135+
*this = i;
136+
} else {
137+
while (std::abs(v) >= 1) {
138+
double tv = v;
139+
MultiwordInteger<size, storageType> tmwi = tv;
140+
*this += tmwi;
141+
v -= tv;
142+
}
143+
}
144+
}
145+
}
146+
else if constexpr(FixedPointHelpers::is_one_of<T, unsigned long long>::value) {
147+
*this = MultiwordInteger<size, storageType>((long long)v);
148+
}
149+
}
150+
158151
#endif // MULTIWORDINTEGERCONSTRUCTORS_HPP

0 commit comments

Comments
 (0)