Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,32 @@ matrix:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
- g++-8
- libunittest++-dev
- python
env:
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
after_success:
- make coverage
- coveralls
- pip install --user --upgrade pip
- pip install --user git+http://github.com/eddyxu/cpp-coveralls.git
- coveralls --gcov /usr/bin/gcov-8 -e /usr/
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-6.0
- sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-6.0 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages:
- g++-5
- clang-6.0
- libunittest++-dev
env:
- MATRIX_EVAL="CC=clang && CXX=clang++"

before_install:
- eval "${MATRIX_EVAL}"
- pip install --user cpp-coveralls
- export UNITTEST_CPP_INCLUDE=/usr/include/unittest++

script:
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ifneq (,$(findstring g++,$(CXX)))
CXXFLAGS += --coverage
endif

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

HEADERS = $(shell find include/ -type f)
Expand Down
11 changes: 4 additions & 7 deletions include/FixedPoint/FixedPoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,14 @@ class FixedPoint
StorageType v;

constexpr FixedPoint() : v(int64_t(0)) {}
constexpr FixedPoint(float v);
constexpr FixedPoint(double v);
constexpr FixedPoint(long double v);
constexpr FixedPoint(int v);
constexpr FixedPoint(long int v);
constexpr FixedPoint(long long int v);
constexpr FixedPoint(unsigned long long int v);
constexpr FixedPoint(FixedPoint const &o);
constexpr FixedPoint(StorageType const &s);
template<int oiw, int ofw, typename otherStorageType> constexpr FixedPoint(FixedPoint<oiw,ofw,otherStorageType> const &o);

template<typename T>
constexpr FixedPoint(T const & v);

static constexpr FP _maxVal();
static constexpr FP _minVal();
static constexpr FP _smallestVal();
Expand All @@ -52,7 +49,7 @@ class FixedPoint
constexpr FP& operator*=(FP const &o);
constexpr FP& operator*=(int64_t const &o);
constexpr FP& operator/=(FP const &o);
constexpr FP& operator/=(int64_t const &o);
constexpr FP& operator/=(int64_t const &o);
constexpr FP& operator%=(FP const &o);

constexpr FP operator-() const;
Expand Down
24 changes: 12 additions & 12 deletions include/FixedPoint/FixedPointConstructors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,20 @@ constexpr void FixedPoint<integerWidth, fractionalWidth, storageType>::construct
}
}

#define CONSTRUCTOR template<int integerWidth, int fractionalWidth, typename storageType> constexpr FixedPoint<integerWidth, fractionalWidth, storageType>::FixedPoint

#define CONSTRUCT_WITH_FUNCTION(T, FUN) \
CONSTRUCTOR(T v) { \
FUN<T>(v);\
template<int integerWidth, int fractionalWidth, typename storageType>
template<typename T>
constexpr FixedPoint<integerWidth, fractionalWidth, storageType>::FixedPoint(T const &v) {
constexpr bool is_floating_type = FixedPointHelpers::is_one_of<T, float, double, long double>::value;
constexpr bool is_signed_int_type = FixedPointHelpers::is_one_of<T, char, short, int, long, long long>::value;
static_assert(is_floating_type || is_signed_int_type, "T must be floating point or signed integer type");
if constexpr(is_floating_type) {
construct_from_float<T>(v);
} else if constexpr(is_signed_int_type) {
construct_from_int<T>(v);
}
}

CONSTRUCT_WITH_FUNCTION(float, construct_from_float)
CONSTRUCT_WITH_FUNCTION(double, construct_from_float)
CONSTRUCT_WITH_FUNCTION(long double, construct_from_float)
CONSTRUCT_WITH_FUNCTION(int, construct_from_int)
CONSTRUCT_WITH_FUNCTION(long int, construct_from_int)
CONSTRUCT_WITH_FUNCTION(long long int, construct_from_int)
#define CONSTRUCTOR template<int integerWidth, int fractionalWidth, typename storageType> constexpr FixedPoint<integerWidth, fractionalWidth, storageType>::FixedPoint

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

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

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

#undef CONSTRUCT_WITH_FUNCTION
#undef CONSTRUCTOR

template<int integerWidth, int fractionalWidth, typename storageType>
Expand Down
13 changes: 13 additions & 0 deletions include/FixedPoint/FixedPointHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ namespace FixedPointHelpers {
template<> class make_bigger<uint16_t> { public: typedef uint32_t type; };
template<> class make_bigger<uint32_t> { public: typedef uint64_t type; };

template<typename T, typename... Args>
struct is_one_of;

template<typename T, typename U, typename... Us>
struct is_one_of<T, U, Us...> {
static constexpr bool value = std::is_same<T, U>::value || is_one_of<T, Us...>::value;
};
template<typename T>
struct is_one_of<T> {
static constexpr bool value = false;
};


template<typename T>
constexpr unsigned nlz_constexpr(T x_) {
typedef typename std::make_unsigned<T>::type UT;
Expand Down
19 changes: 8 additions & 11 deletions include/FixedPoint/MultiwordInteger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,15 @@ class MultiwordInteger
constexpr MultiwordInteger() : s{0} {}
template<unsigned otherSize> constexpr MultiwordInteger(MultiwordInteger<otherSize, storageType> const &o);
constexpr MultiwordInteger(storageType const &v);

/**
* This constructor accepts an int*_t, unsigned long long, float, double, or long double
*/
template<typename T>
constexpr MultiwordInteger(T v);

constexpr MultiwordInteger(int8_t v);
constexpr MultiwordInteger(int16_t v);
constexpr MultiwordInteger(int32_t v);
constexpr MultiwordInteger(int64_t v);
template<typename U = _storageType, typename EN = std::enable_if<std::is_same<U, unsigned long long>::value == false>>
constexpr MultiwordInteger(unsigned long long int v, typename EN::type * = 0);
constexpr MultiwordInteger(float v);
constexpr MultiwordInteger(double v);
constexpr MultiwordInteger(long double v);

template<unsigned otherSize, typename otherStorageType> constexpr MultiwordInteger(MultiwordInteger<otherSize, otherStorageType> const &o);
template<unsigned otherSize, typename otherStorageType>
constexpr MultiwordInteger(MultiwordInteger<otherSize, otherStorageType> const &o);

constexpr MultiwordInteger<size, storageType>& operator+=(MultiwordInteger<size, storageType> const &o);
constexpr MultiwordInteger<size, storageType>& operator-=(MultiwordInteger<size, storageType> const &o);
Expand Down
137 changes: 65 additions & 72 deletions include/FixedPoint/MultiwordIntegerConstructors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include "MultiwordInteger.hpp"
#include "FixedPointHelpers.hpp"

template<unsigned size, typename storageType> template<unsigned otherSize> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(MultiwordInteger<otherSize, storageType> const &o) : s{0} {
template<unsigned size, typename storageType>
template<unsigned otherSize>
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(MultiwordInteger<otherSize, storageType> const &o) : s{0} {
unsigned num = size > otherSize ? otherSize : size;
for (unsigned i = 0; i < num; i++) {
s[i] = o.s[i];
Expand All @@ -22,83 +24,19 @@ template<unsigned size, typename storageType> template<unsigned otherSize> const
}
}
}
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(storageType const &v) : s{v} {

template<unsigned size, typename storageType>
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(storageType const &v) : s{v} {
if (static_cast<signedType>(v) < 0) {
for (unsigned i = 1; i < size; i++) {
s[i] = static_cast<signedType>(-1);
}
}
}
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(int8_t v) : s{0} {
*this = MultiwordInteger<size, std::make_unsigned<decltype(v)>::type>(v);
}
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(int16_t v) : s{0} {
*this = MultiwordInteger<size, std::make_unsigned<decltype(v)>::type>(v);
}
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(int32_t v) : s{0} {
*this = MultiwordInteger<size, std::make_unsigned<decltype(v)>::type>(v);
}
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(int64_t v) : s{0} {
uint64_t uv = v;
unsigned i = 0;
for (; i < size && uv; i++) {
s[i] = uv;
uv >>= storageSize;
}
for (; i < size; i++) {
s[i] = 0;
}
if(v < 0) {
fill_leading_bits(leading_zeros());
}
}
template<unsigned size, typename storageType>
template<typename U, typename EN>
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(unsigned long long int v, typename EN::type *) {
*this = MultiwordInteger<size, storageType>((long long)v);
}
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(float v) : s{0} {
if (v != 0.) {
if (v > INT32_MIN && v < INT32_MAX) {
int32_t i = int32_t(v);
*this = i;
} else {
int lg = FixedPointHelpers::ilogb(v);
v *= FixedPointHelpers::dipow<float>(2, 30-lg);
*this = int64_t(v);
*this <<= lg - 30;
}
}
}
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(double v) : s{0} {
if (v != 0.) {
if (v > double(INT64_MIN) && v < double(INT64_MAX)) {
int64_t i = int64_t(v);
*this = i;
} else {
int lg = FixedPointHelpers::ilogb(v);
v *= FixedPointHelpers::dipow<double>(2, 62-lg);
*this = MultiwordInteger(int64_t(v));
*this <<= lg - 62;
}
}
}
template<unsigned size, typename storageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(long double v) : s{0} {
if (v != 0.) {
if (v > INT64_MIN && v < INT64_MAX) {
int64_t i = int64_t(v);
*this = i;
} else {
while (std::abs(v) >= 1) {
double tv = v;
MultiwordInteger<size, storageType> tmwi = tv;
*this += tmwi;
v -= tv;
}
}
}
}
template<unsigned size, typename storageType> template<unsigned otherSize, typename otherStorageType> constexpr MultiwordInteger<size, storageType>::MultiwordInteger(MultiwordInteger<otherSize, otherStorageType> const &o) : s{0} {

template<unsigned size, typename storageType>
template<unsigned otherSize, typename otherStorageType>
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(MultiwordInteger<otherSize, otherStorageType> const &o) : s{0} {
static_assert((sizeof(storageType) % sizeof(otherStorageType)) == 0
|| (sizeof(otherStorageType) % sizeof(storageType)) == 0,
"Types must fit into each other without remainder.");
Expand Down Expand Up @@ -155,4 +93,59 @@ template<unsigned size, typename storageType> template<unsigned otherSize, typen
}
}

template<unsigned size, typename storageType>
template<typename T>
constexpr MultiwordInteger<size, storageType>::MultiwordInteger(T v) : s{0} {
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");
if constexpr (FixedPointHelpers::is_one_of<T, int8_t, int16_t, int32_t>::value) {
*this = MultiwordInteger<size, typename std::make_unsigned<T>::type>(v);
}
else if constexpr(FixedPointHelpers::is_one_of<T, int64_t>::value) {
uint64_t uv = v;
unsigned i = 0;
for (; i < size && uv; i++) {
s[i] = uv;
uv >>= storageSize;
}
for (; i < size; i++) {
s[i] = 0;
}
if(v < 0) {
fill_leading_bits(leading_zeros());
}
}
else if constexpr(FixedPointHelpers::is_one_of<T, float, double>::value) {
if (v != 0.) {
using IntType = typename std::conditional<std::is_same<T, float>::value, int32_t, int64_t>::type;
if (v > std::numeric_limits<IntType>::min() && v < std::numeric_limits<IntType>::max()) {
IntType i = IntType(v);
*this = i;
} else {
int lg = FixedPointHelpers::ilogb(v);
v *= FixedPointHelpers::dipow<T>(2, sizeof(IntType)*8-2-lg);
*this = MultiwordInteger(int64_t(v));
*this <<= lg + 2 - sizeof(IntType)*8;
}
}
}
else if constexpr(FixedPointHelpers::is_one_of<T, long double>::value) {
if (v != 0.) {
if (v > INT64_MIN && v < INT64_MAX) {
int64_t i = int64_t(v);
*this = i;
} else {
while (std::abs(v) >= 1) {
double tv = v;
MultiwordInteger<size, storageType> tmwi = tv;
*this += tmwi;
v -= tv;
}
}
}
}
else if constexpr(FixedPointHelpers::is_one_of<T, unsigned long long>::value) {
*this = MultiwordInteger<size, storageType>((long long)v);
}
}

#endif // MULTIWORDINTEGERCONSTRUCTORS_HPP