diff --git a/.travis.yml b/.travis.yml index 18498a2..3488016 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/Makefile b/Makefile index fcc39ef..2d74dd0 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/include/FixedPoint/FixedPoint.hpp b/include/FixedPoint/FixedPoint.hpp index 07b9830..d86872b 100644 --- a/include/FixedPoint/FixedPoint.hpp +++ b/include/FixedPoint/FixedPoint.hpp @@ -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 constexpr FixedPoint(FixedPoint const &o); + template + constexpr FixedPoint(T const & v); + static constexpr FP _maxVal(); static constexpr FP _minVal(); static constexpr FP _smallestVal(); @@ -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; diff --git a/include/FixedPoint/FixedPointConstructors.hpp b/include/FixedPoint/FixedPointConstructors.hpp index 9713f1b..00da633 100644 --- a/include/FixedPoint/FixedPointConstructors.hpp +++ b/include/FixedPoint/FixedPointConstructors.hpp @@ -35,19 +35,20 @@ constexpr void FixedPoint::construct } } -#define CONSTRUCTOR template constexpr FixedPoint::FixedPoint - -#define CONSTRUCT_WITH_FUNCTION(T, FUN) \ -CONSTRUCTOR(T v) { \ - FUN(v);\ +template +template +constexpr FixedPoint::FixedPoint(T const &v) { + constexpr bool is_floating_type = FixedPointHelpers::is_one_of::value; + constexpr bool is_signed_int_type = FixedPointHelpers::is_one_of::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(v); + } else if constexpr(is_signed_int_type) { + construct_from_int(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 constexpr FixedPoint::FixedPoint CONSTRUCTOR(StorageType const &s) : v(s) {} @@ -58,7 +59,6 @@ CONSTRUCTOR(unsigned long long int v) CONSTRUCTOR(FixedPoint const &o) : v(o.v) {} -#undef CONSTRUCT_WITH_FUNCTION #undef CONSTRUCTOR template diff --git a/include/FixedPoint/FixedPointHelpers.hpp b/include/FixedPoint/FixedPointHelpers.hpp index 3772040..bda5a9f 100644 --- a/include/FixedPoint/FixedPointHelpers.hpp +++ b/include/FixedPoint/FixedPointHelpers.hpp @@ -14,6 +14,19 @@ namespace FixedPointHelpers { template<> class make_bigger { public: typedef uint32_t type; }; template<> class make_bigger { public: typedef uint64_t type; }; + template + struct is_one_of; + + template + struct is_one_of { + static constexpr bool value = std::is_same::value || is_one_of::value; + }; + template + struct is_one_of { + static constexpr bool value = false; + }; + + template constexpr unsigned nlz_constexpr(T x_) { typedef typename std::make_unsigned::type UT; diff --git a/include/FixedPoint/MultiwordInteger.hpp b/include/FixedPoint/MultiwordInteger.hpp index 8bc9fa5..47d0d7b 100644 --- a/include/FixedPoint/MultiwordInteger.hpp +++ b/include/FixedPoint/MultiwordInteger.hpp @@ -36,18 +36,15 @@ class MultiwordInteger constexpr MultiwordInteger() : s{0} {} template constexpr MultiwordInteger(MultiwordInteger const &o); constexpr MultiwordInteger(storageType const &v); + + /** + * This constructor accepts an int*_t, unsigned long long, float, double, or long double + */ + template + 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::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 constexpr MultiwordInteger(MultiwordInteger const &o); + template + constexpr MultiwordInteger(MultiwordInteger const &o); constexpr MultiwordInteger& operator+=(MultiwordInteger const &o); constexpr MultiwordInteger& operator-=(MultiwordInteger const &o); diff --git a/include/FixedPoint/MultiwordIntegerConstructors.hpp b/include/FixedPoint/MultiwordIntegerConstructors.hpp index ad6f131..b82494e 100644 --- a/include/FixedPoint/MultiwordIntegerConstructors.hpp +++ b/include/FixedPoint/MultiwordIntegerConstructors.hpp @@ -7,7 +7,9 @@ #include "MultiwordInteger.hpp" #include "FixedPointHelpers.hpp" -template template constexpr MultiwordInteger::MultiwordInteger(MultiwordInteger const &o) : s{0} { +template +template +constexpr MultiwordInteger::MultiwordInteger(MultiwordInteger const &o) : s{0} { unsigned num = size > otherSize ? otherSize : size; for (unsigned i = 0; i < num; i++) { s[i] = o.s[i]; @@ -22,83 +24,19 @@ template template const } } } -template constexpr MultiwordInteger::MultiwordInteger(storageType const &v) : s{v} { + +template +constexpr MultiwordInteger::MultiwordInteger(storageType const &v) : s{v} { if (static_cast(v) < 0) { for (unsigned i = 1; i < size; i++) { s[i] = static_cast(-1); } } } -template constexpr MultiwordInteger::MultiwordInteger(int8_t v) : s{0} { - *this = MultiwordInteger::type>(v); -} -template constexpr MultiwordInteger::MultiwordInteger(int16_t v) : s{0} { - *this = MultiwordInteger::type>(v); -} -template constexpr MultiwordInteger::MultiwordInteger(int32_t v) : s{0} { - *this = MultiwordInteger::type>(v); -} -template constexpr MultiwordInteger::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 -template -constexpr MultiwordInteger::MultiwordInteger(unsigned long long int v, typename EN::type *) { - *this = MultiwordInteger((long long)v); -} -template constexpr MultiwordInteger::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(2, 30-lg); - *this = int64_t(v); - *this <<= lg - 30; - } - } -} -template constexpr MultiwordInteger::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(2, 62-lg); - *this = MultiwordInteger(int64_t(v)); - *this <<= lg - 62; - } - } -} -template constexpr MultiwordInteger::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 tmwi = tv; - *this += tmwi; - v -= tv; - } - } - } -} -template template constexpr MultiwordInteger::MultiwordInteger(MultiwordInteger const &o) : s{0} { + +template +template +constexpr MultiwordInteger::MultiwordInteger(MultiwordInteger const &o) : s{0} { static_assert((sizeof(storageType) % sizeof(otherStorageType)) == 0 || (sizeof(otherStorageType) % sizeof(storageType)) == 0, "Types must fit into each other without remainder."); @@ -155,4 +93,59 @@ template template +template +constexpr MultiwordInteger::MultiwordInteger(T v) : s{0} { + static_assert(FixedPointHelpers::is_one_of::value, "T must be a signed int or floating point type, or unsigned long long"); + if constexpr (FixedPointHelpers::is_one_of::value) { + *this = MultiwordInteger::type>(v); + } + else if constexpr(FixedPointHelpers::is_one_of::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::value) { + if (v != 0.) { + using IntType = typename std::conditional::value, int32_t, int64_t>::type; + if (v > std::numeric_limits::min() && v < std::numeric_limits::max()) { + IntType i = IntType(v); + *this = i; + } else { + int lg = FixedPointHelpers::ilogb(v); + v *= FixedPointHelpers::dipow(2, sizeof(IntType)*8-2-lg); + *this = MultiwordInteger(int64_t(v)); + *this <<= lg + 2 - sizeof(IntType)*8; + } + } + } + else if constexpr(FixedPointHelpers::is_one_of::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 tmwi = tv; + *this += tmwi; + v -= tv; + } + } + } + } + else if constexpr(FixedPointHelpers::is_one_of::value) { + *this = MultiwordInteger((long long)v); + } +} + #endif // MULTIWORDINTEGERCONSTRUCTORS_HPP