Working on optimisation but I'm still losing to std::to_string()
This commit is contained in:
parent
420257f578
commit
9dbabcb5c4
6 changed files with 52 additions and 20 deletions
|
@ -41,6 +41,10 @@ target_compile_definitions(${PROJECT_NAME}
|
|||
INTERFACE SPROUT_USE_TEMPLATE_ALIASES
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME}
|
||||
INTERFACE -mprfchw
|
||||
)
|
||||
|
||||
if (BUILD_TESTING)
|
||||
add_subdirectory(test/unit)
|
||||
endif()
|
||||
|
|
|
@ -104,11 +104,26 @@ namespace dhandy {
|
|||
|
||||
template <typename L>
|
||||
[[gnu::pure,gnu::always_inline]]
|
||||
static constexpr L abs(L in) { return (not BecomesUnsigned and std::numeric_limits<L>::is_signed and in < L(0) ? -in : in); }
|
||||
static constexpr L abs(L v);
|
||||
[[gnu::pure,gnu::always_inline]]
|
||||
static constexpr CastedType cast (I in) { return static_cast<CastedType>(in); }
|
||||
};
|
||||
|
||||
template <typename I, std::size_t Base, bool IsSigned, bool ForceUnsigned>
|
||||
template <typename L>
|
||||
[[gnu::const,gnu::always_inline]]
|
||||
inline constexpr L NumberAdaptation<I, Base, IsSigned, ForceUnsigned>::abs(L v) {
|
||||
if constexpr (not BecomesUnsigned and std::numeric_limits<L>::is_signed) {
|
||||
//https://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
|
||||
const L mask = v >> (sizeof(L) * CHAR_BIT - 1);
|
||||
const UnsignedType r = (v + mask) ^ mask;
|
||||
return static_cast<L>(r);
|
||||
}
|
||||
else {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename I, unsigned int Base, typename Tr, typename=void>
|
||||
struct IntConversion {
|
||||
static constexpr RevArray<I, Base, Tr> to_ary (I in) {
|
||||
|
@ -156,18 +171,21 @@ namespace dhandy {
|
|||
const bool was_negative = implem::is_negative<I, 10>(in);
|
||||
|
||||
RetType arr;
|
||||
if (not std::is_constant_evaluated())
|
||||
__builtin_prefetch(arr.base_ptr(), 1, 3);
|
||||
arr.push_front(Tr::NullChar);
|
||||
while (Num::abs(in) >= static_cast<I>(100)) {
|
||||
const auto index = (Num::abs(in) % 100) * 2;
|
||||
in = Num::abs(in);
|
||||
while (in >= static_cast<I>(100)) {
|
||||
const auto index = (in % 100) * 2;
|
||||
arr.push_front(Tr::to_digit(static_cast<int>(lookup[index + 1])));
|
||||
arr.push_front(Tr::to_digit(static_cast<int>(lookup[index + 0])));
|
||||
in = static_cast<I>(in / static_cast<I>(100));
|
||||
};
|
||||
if (Num::abs(in) < static_cast<I>(10)) {
|
||||
arr.push_front(Tr::to_digit(static_cast<int>(Num::abs(in))));
|
||||
if (in < static_cast<I>(10)) {
|
||||
arr.push_front(Tr::to_digit(static_cast<int>(in)));
|
||||
}
|
||||
else {
|
||||
const auto index = Num::abs(in) * 2;
|
||||
const auto index = in * 2;
|
||||
arr.push_front(Tr::to_digit(static_cast<int>(lookup[index + 1])));
|
||||
arr.push_front(Tr::to_digit(static_cast<int>(lookup[index + 0])));
|
||||
}
|
||||
|
@ -301,17 +319,24 @@ namespace dhandy {
|
|||
static const constexpr unsigned int DigitCount = DCount;
|
||||
|
||||
static constexpr C to_digit (unsigned int num) {
|
||||
return (num < DigitCount ?
|
||||
static_cast<C>(num + FirstDigit) :
|
||||
static_cast<C>(num + FirstLetter - DigitCount)
|
||||
);
|
||||
constexpr const C ret[2] = {FirstDigit, FirstLetter - DigitCount};
|
||||
#if 0
|
||||
//https://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching
|
||||
const bool f = num >= DigitCount;
|
||||
constexpr const unsigned int m = 1;
|
||||
const unsigned int w = (-f & m);
|
||||
#else
|
||||
const auto w = (DigitCount - 1 - num) >> (sizeof(unsigned int) * CHAR_BIT - 1);
|
||||
#endif
|
||||
return num + ret[w];
|
||||
}
|
||||
|
||||
static constexpr int from_digit (C dig) {
|
||||
return (dig < FirstLetter ?
|
||||
dig - FirstDigit :
|
||||
dig - FirstLetter + DigitCount
|
||||
);
|
||||
//return (dig < FirstLetter ? dig - FirstDigit : dig - FirstLetter + DigitCount);
|
||||
typedef typename std::make_unsigned<C>::type UC;
|
||||
constexpr const C ret[2] = {FirstLetter - DigitCount, FirstDigit};
|
||||
const auto w = static_cast<UC>(dig - FirstLetter) >> (sizeof(UC) * CHAR_BIT - 1);
|
||||
return dig - ret[w];
|
||||
}
|
||||
};
|
||||
template <typename C>
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace dhandy {
|
|||
constexpr T& operator[] (std::size_t idx) { if (idx >= size()) throw std::out_of_range("Out of bound array access"); return m_data[idx + m_curr + 1]; }
|
||||
constexpr void push_front (const T& itm) { if (size() == S) throw std::length_error("ReversedSizedArray is full"); m_data[m_curr--] = itm; }
|
||||
constexpr const T* data() const { return m_data.data() + m_curr + 1; }
|
||||
constexpr const T* base_ptr() const { return m_data.data(); }
|
||||
constexpr iterator begin() { return m_data.begin() + m_curr + 1; }
|
||||
constexpr iterator end() { return m_data.end(); }
|
||||
constexpr const T& back() const { return *(m_data.data() + S - 1); }
|
||||
|
@ -62,6 +63,8 @@ namespace dhandy {
|
|||
bool operator!= (const std::basic_string<T>& other) const { return not operator==(other); }
|
||||
bool operator== (const T* other) const { return to_string_view() == std::basic_string_view<T>(other); }
|
||||
bool operator!= (const T* other) const { return not operator==(other); }
|
||||
|
||||
std::string to_string() const { return to<std::basic_string<T>>(); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
|
@ -91,9 +91,9 @@ namespace dhandy {
|
|||
};
|
||||
} //namespace implem
|
||||
|
||||
template <typename To, typename From>
|
||||
constexpr inline To int_conv (const From& from, bool all_caps=false) {
|
||||
if (all_caps)
|
||||
template <typename To, typename From, bool AllCaps=false>
|
||||
constexpr inline To int_conv (const From& from, std::integral_constant<bool, AllCaps> = std::integral_constant<bool, AllCaps>{}) {
|
||||
if constexpr (AllCaps)
|
||||
return implem::IntConv<To, From, ASCIITranslatorUpcase<char>>::conv(from);
|
||||
else
|
||||
return implem::IntConv<To, From, ASCIITranslator<char>>::conv(from);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
project(dhandy_unit_test CXX)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
int_conv_test.cpp
|
||||
main.cpp
|
||||
endianness_test.cpp
|
||||
int_conv_test.cpp
|
||||
reversed_sized_array_test.cpp
|
||||
bitfield_pack_test.cpp
|
||||
resource_pool_test.cpp
|
||||
|
|
|
@ -266,11 +266,11 @@ TEST_CASE ("Check upcase/downcase int to array conversions", "[i2s][int_conv]")
|
|||
}
|
||||
|
||||
TEST_CASE ("Try int conv with non-char", "[s2i][int_conv]") {
|
||||
using dhandy::int_to_ary;
|
||||
using dhandy::buildtime_int_to_ary;
|
||||
using dhandy::ASCIITranslator;
|
||||
|
||||
std::wstring_view exp1(L"235713");
|
||||
auto val1 = int_to_ary<int, 10, ASCIITranslator<wchar_t>>(235713).to_string_view();
|
||||
auto val1 = buildtime_int_to_ary<int, 235713, 10, ASCIITranslator<wchar_t>>().to_string_view();
|
||||
CHECK(exp1 == val1);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue