Project

General

Profile

« Previous | Next » 

Revision 852d0468

Added by David Sorber over 4 years ago

Modify template to include parameters for strtoXXX functions. Also begin
integrating support for 128 bit integer types.

View differences:

software/fixed/fixed.h
#include <stdexcept>
#include <type_traits>
#ifdef USE_INT128
#include "int128.h"
#endif
#if __GNUC__ >= 3
#define __unlikely(cond) __builtin_expect((cond), 0)
#define __likely(cond) __builtin_expect((cond), 1)
......
#define __likely(cond) (cond)
#endif
template<typename IntegerType, typename FractionalType>
template<typename T>
constexpr T calculateMax(size_t decimal_digits)
{
T val = 0;
for (uint32_t idx = 0; idx < decimal_digits; ++idx)
{
val *= 10;
val += 9;
}
return val;
}
template<typename IntegerType, typename FractionalType,
typename StrToIntegerTypeFunc,
typename StrToFracTypeFunc>
class fixed
{
static_assert(std::is_integral<IntegerType>::value,
......
static constexpr size_t fractional_decimal_digits =
std::floor(std::log10(std::numeric_limits<FractionalType>::max()));
static constexpr size_t MAX_INTEGER_VALUE =
(static_cast<uint64_t>(std::pow(10, integer_decimal_digits)) - 1);
static constexpr size_t MIN_INTEGER_VALUE = 0;
static constexpr IntegerType MAX_INTEGER_VALUE =
(calculateMax<IntegerType>(integer_decimal_digits));
static constexpr IntegerType MIN_INTEGER_VALUE = 0;
static constexpr size_t MAX_FRACTIONAL_VALUE =
(static_cast<uint64_t>(std::pow(10, fractional_decimal_digits)) - 1);
static constexpr size_t MIN_FRACTIONAL_VALUE = 0;
static constexpr FractionalType MAX_FRACTIONAL_VALUE =
(calculateMax<FractionalType>(fractional_decimal_digits));
static constexpr FractionalType MIN_FRACTIONAL_VALUE = 0;
static const uint64_t SCALE_VALUES[20];
......
uint32_t parse(const char* input)
{
char* endPtr = nullptr;
m_integer = __checkIntOverflow(strtoll(input, &endPtr, 10));
//~ m_integer = __checkIntOverflow(strtoll(input, &endPtr, 10));
m_integer = __checkIntOverflow(strto_inttype(input, &endPtr, 10));
m_fractional = 0;
if (std::isdigit(*endPtr))
......
{
char* fracEndPtr = nullptr;
FractionalType fracTemp =
__checkFracOverflow(strtoull(endPtr + 1, &fracEndPtr, 10));
//~ __checkFracOverflow(strtoull(endPtr + 1, &fracEndPtr, 10));
__checkFracOverflow(strto_fractype(endPtr + 1, &fracEndPtr, 10));
uint32_t fracLen = (fracEndPtr - endPtr) - 1;
fracLen = fractional_decimal_digits - fracLen;
......
inline fixed& operator/=(const fixed& y) noexcept = delete;
// Comparison operators
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
friend constexpr inline bool operator==(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept;
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
friend constexpr inline bool operator!=(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept;
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
friend constexpr inline bool operator<(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept;
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
friend constexpr inline bool operator>(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept;
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
friend constexpr inline bool operator<=(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept;
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
friend constexpr inline bool operator>=(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept;
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept;
// Output stream operator
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
friend inline std::ostream& operator<<(
std::ostream& os, const fixed<I, F>& rhs);
std::ostream& os, const fixed<I, F, STI, STF>& rhs);
private:
static StrToIntegerTypeFunc strto_inttype;
static StrToFracTypeFunc strto_fractype;
static inline IntegerType __checkIntOverflow(IntegerType integerVal)
{
if (__unlikely(integerVal > MAX_INTEGER_VALUE))
......
FractionalType m_fractional;
};
// Functor for calling std::strtoll()
struct strtoll_ftor {
inline int64_t operator()(const char* str, char** str_end, int base)
{
return std::strtoll(str, str_end, base);
}
};
// Functor for calling std::strtoull()
struct strtoull_ftor {
inline uint64_t operator()(const char* str, char** str_end, int base)
{
return std::strtoull(str, str_end, base);
}
};
#ifdef USE_INT128
// Functor for calling strtoll_128()
struct strtoll_128_ftor {
inline int64_t operator()(const char* str, char** str_end, int base)
{
//~ return strtoll_128(str, str_end, base);
return strtoll_128_b10opt(str, str_end, base);
}
};
// Functor for calling strtoull_128()
struct strtoull_128_ftor {
inline uint64_t operator()(const char* str, char** str_end, int base)
{
//~ return strtoull_128(str, str_end, base);
return strtoull_128_b10opt(str, str_end, base);
}
};
#endif
// Predefined types
using fixed_8_8 = fixed<int8_t, uint8_t>;
using fixed_8_16 = fixed<int8_t, uint16_t>;
using fixed_8_32 = fixed<int8_t, uint32_t>;
using fixed_8_64 = fixed<int8_t, uint64_t>;
using fixed_16_8 = fixed<int16_t, uint8_t>;
using fixed_16_16 = fixed<int16_t, uint16_t>;
using fixed_16_32 = fixed<int16_t, uint32_t>;
using fixed_16_64 = fixed<int16_t, uint64_t>;
using fixed_32_8 = fixed<int32_t, uint8_t>;
using fixed_32_16 = fixed<int32_t, uint16_t>;
using fixed_32_32 = fixed<int32_t, uint32_t>;
using fixed_32_64 = fixed<int32_t, uint64_t>;
using fixed_64_8 = fixed<int64_t, uint8_t>;
using fixed_64_16 = fixed<int64_t, uint16_t>;
using fixed_64_32 = fixed<int64_t, uint32_t>;
using fixed_64_64 = fixed<int64_t, uint64_t>;
using fixed_8_8 = fixed<int8_t, uint8_t, strtoll_ftor, strtoull_ftor>;
using fixed_8_16 = fixed<int8_t, uint16_t, strtoll_ftor, strtoull_ftor>;
using fixed_8_32 = fixed<int8_t, uint32_t, strtoll_ftor, strtoull_ftor>;
using fixed_8_64 = fixed<int8_t, uint64_t, strtoll_ftor, strtoull_ftor>;
using fixed_16_8 = fixed<int16_t, uint8_t, strtoll_ftor, strtoull_ftor>;
using fixed_16_16 = fixed<int16_t, uint16_t, strtoll_ftor, strtoull_ftor>;
using fixed_16_32 = fixed<int16_t, uint32_t, strtoll_ftor, strtoull_ftor>;
using fixed_16_64 = fixed<int16_t, uint64_t, strtoll_ftor, strtoull_ftor>;
using fixed_32_8 = fixed<int32_t, uint8_t, strtoll_ftor, strtoull_ftor>;
using fixed_32_16 = fixed<int32_t, uint16_t, strtoll_ftor, strtoull_ftor>;
using fixed_32_32 = fixed<int32_t, uint32_t, strtoll_ftor, strtoull_ftor>;
using fixed_32_64 = fixed<int32_t, uint64_t, strtoll_ftor, strtoull_ftor>;
using fixed_64_8 = fixed<int64_t, uint8_t, strtoll_ftor, strtoull_ftor>;
using fixed_64_16 = fixed<int64_t, uint16_t, strtoll_ftor, strtoull_ftor>;
using fixed_64_32 = fixed<int64_t, uint32_t, strtoll_ftor, strtoull_ftor>;
using fixed_64_64 = fixed<int64_t, uint64_t, strtoll_ftor, strtoull_ftor>;
#ifdef USE_INT128
using fixed_128_128 = fixed<int128_t, uint128_t, strtoll_128_ftor, strtoull_128_ftor>;
#endif
// Precomputed scale value constants
template<typename I, typename F>
const uint64_t fixed<I, F>::SCALE_VALUES[20] =
template<typename I, typename F, typename STI, typename STF>
const uint64_t fixed<I, F, STI, STF>::SCALE_VALUES[20] =
{
/* 0 */ 1ULL,
/* 1 */ 10ULL,
......
/* 19 */ 10000000000000000000ULL
};
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
constexpr inline bool operator==(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
{
return (x.m_integer == y.m_integer && x.m_fractional == y.m_fractional);
}
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
constexpr inline bool operator!=(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
{
return (! (x == y));
}
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
constexpr inline bool operator<(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
{
if (x.m_integer == y.m_integer)
{
......
return false;
}
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
constexpr inline bool operator>(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
{
if (x.m_integer == y.m_integer)
{
......
return false;
}
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
constexpr inline bool operator<=(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
{
if (x.m_integer == y.m_integer)
{
......
return false;
}
template<typename I, typename F>
template<typename I, typename F, typename STI, typename STF>
constexpr inline bool operator>=(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
{
if (x.m_integer == y.m_integer)
{
......
}
// Addition -- not yet supported
template<typename I, typename F>
constexpr inline fixed<I, F> operator+(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept = delete;
template<typename I, typename F, typename STI, typename STF>
constexpr inline fixed<I, F, STI, STF> operator+(
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept = delete;
// Subtraction -- not yet supported
template<typename I, typename F>
constexpr inline fixed<I, F> operator-(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept = delete;
template<typename I, typename F, typename STI, typename STF>
constexpr inline fixed<I, F, STI, STF> operator-(
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept = delete;
// Multiplication
template<typename I, typename F>
constexpr inline fixed<I, F> operator*(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept = delete;
template<typename I, typename F, typename STI, typename STF>
constexpr inline fixed<I, F, STI, STF> operator*(
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept = delete;
// Division -- not yet supported
template<typename I, typename F>
constexpr inline fixed<I, F> operator/(
const fixed<I, F>& x, const fixed<I, F>& y) noexcept = delete;
template<typename I, typename F, typename STI, typename STF>
constexpr inline fixed<I, F, STI, STF> operator/(
const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept = delete;
// Stream output
template<typename I, typename F>
inline std::ostream& operator<<(std::ostream& os, const fixed<I, F>& rhs)
template<typename I, typename F, typename STI, typename STF>
inline std::ostream& operator<<(std::ostream& os, const fixed<I, F, STI, STF>& rhs)
{
return os << std::fixed << rhs.m_integer << "."
<< std::setw(fixed<I, F>::fractional_decimal_digits)
<< std::setw(fixed<I, F, STI, STF>::fractional_decimal_digits)
<< std::setfill('0') << rhs.m_fractional;
}
software/fixed/fixed_util.cc
{
std::cout << "Fixed Type Test Util\n" << std::endl;
//-------------------------------------------------------------------------
fixed_64_64 foobar;
std::cout << "Type size: " << sizeof(fixed_64_64) << std::endl;
......
std::cout << "Max fractional value: " << fixed_64_64::MAX_FRACTIONAL_VALUE << std::endl;
std::cout << std::endl;
std::cout << "Value: " << foobar << std::endl;
std::cout << "Value: " << foobar << "\n\n" << std::endl;
//-------------------------------------------------------------------------
#ifdef USE_INT128
fixed_128_128 barfoo;
std::cout << "Type size: " << sizeof(barfoo) << std::endl;
std::cout << "Integer decimal digits: " << fixed_128_128::integer_decimal_digits << std::endl;
std::cout << "Fractional decimal digits: " << fixed_128_128::fractional_decimal_digits << std::endl;
std::cout << "Max integer value: " << fixed_128_128::MAX_INTEGER_VALUE << std::endl;
std::cout << "Max fractional value: " << fixed_128_128::MAX_FRACTIONAL_VALUE << std::endl;
std::cout << std::endl;
std::cout << "Value: " << barfoo << "\n\n" << std::endl;
#endif
//-------------------------------------------------------------------------
fixed_64_64 quxbar(3, 1415926353);
std::cout << "Value: " << quxbar << std::endl;
software/fixed/parse_test.cc
<< " ms" << std::endl;
}
#endif
// 5)
else if (parseType == 5)
{
std::cout << "Parse type 5: fixed_128_128" << std::endl;
auto start = std::chrono::system_clock::now();
for (auto& strValue : values)
{
fvalue.parse(strValue.c_str());
//~ std::cout << "In: " << strValue << " -- Out: " << fvalue << std::endl;
}
auto end = std::chrono::system_clock::now();
auto diff = end - start;
std::cout << "Total parse time: "
<< std::chrono::duration <double, std::milli>(diff).count()
<< " ms" << std::endl;
}
else
{
std::cerr << "ERROR: invalid parse type: " << parseType << std::endl;

Also available in: Unified diff