Add case sensitivity support to sse conversion
This commit is contained in:
parent
094f7fc679
commit
a675624cab
2 changed files with 63 additions and 7 deletions
|
@ -18,7 +18,8 @@
|
|||
#ifndef id4754A95F12BE4ADEA65642A056A51907
|
||||
#define id4754A95F12BE4ADEA65642A056A51907
|
||||
|
||||
#include "duckhandy/implem/reversed_sized_array_bt.hpp"
|
||||
#include "reversed_sized_array_bt.hpp"
|
||||
#include "../has_method.hpp"
|
||||
#include <sprout/math/log10.hpp>
|
||||
#include <sprout/math/abs.hpp>
|
||||
#include <sprout/math/ceil.hpp>
|
||||
|
@ -51,6 +52,14 @@ namespace dhandy {
|
|||
}
|
||||
} //unnamed namespace
|
||||
|
||||
//Used for checking ASCIITranslator::AltLetter
|
||||
define_has_enum(AltLetter, AltLetter);
|
||||
|
||||
template <typename Tr, bool=HasAltLetterEnum<Tr>::value != 0>
|
||||
inline auto g_AltLetterOrZero = Tr::AltLetter;
|
||||
template <typename Tr>
|
||||
inline auto g_AltLetterOrZero<Tr, false> = Tr::NullChar;
|
||||
|
||||
template <typename T, typename C, unsigned int Base, typename Tr>
|
||||
T to_integer_sse (const C* s, std::size_t l);
|
||||
|
||||
|
@ -202,7 +211,7 @@ namespace dhandy {
|
|||
};
|
||||
|
||||
template <typename I, unsigned int Base, typename Tr>
|
||||
struct AryConversion<I, Base, Tr, false, typename std::enable_if<Tr::BehavesLikeASCII and std::is_integral<I>::value and not std::is_same<I, bool>::value and sizeof(I) <= sizeof(std::uint32_t)>::type> {
|
||||
struct AryConversion<I, Base, Tr, false, typename std::enable_if<std::is_integral<I>::value and not std::is_same<I, bool>::value and sizeof(I) <= sizeof(std::uint32_t)>::type> {
|
||||
constexpr static const bool is_sse = true;
|
||||
template <typename C> static I from_ary (C* beg, C* end) { return to_integer_sse<I, C, Base, Tr>(beg, end - beg); }
|
||||
};
|
||||
|
@ -246,13 +255,24 @@ namespace dhandy {
|
|||
__m128i factor = _mm_set_epi32(base3, base2, base1, 1);
|
||||
__m128i res = _mm_set1_epi32(0);
|
||||
const __m128i char_0 = _mm_set1_epi32(Tr::FirstDigit);
|
||||
const __m128i char_a = _mm_set1_epi32(Tr::FirstLetter);
|
||||
const __m128i char_befo_a = _mm_set1_epi32(Tr::FirstLetter - 1);
|
||||
const __m128i char_past_f = _mm_set1_epi32(Tr::FirstLetter + Base - 10);
|
||||
std::size_t idx = 0;
|
||||
const std::size_t cap = l bitand -4;
|
||||
do {
|
||||
const __m128i digits = _mm_set_epi32(s[cap - idx - 3 - 1], s[cap - idx - 2 - 1], s[cap - idx - 1 - 1], s[cap - idx - 0 - 1]);
|
||||
const __m128i mask = _mm_cmplt_epi32(digits, char_a);
|
||||
const __m128i addend = _mm_add_epi32(_mm_andnot_si128(mask, _mm_sub_epi32(char_a, _mm_set1_epi32(10))), _mm_and_si128(mask, char_0));
|
||||
__m128i mask = _mm_and_si128(_mm_cmpgt_epi32(digits, char_befo_a), _mm_cmplt_epi32(digits, char_past_f));
|
||||
__m128i offs = _mm_and_si128(mask, _mm_set1_epi32(Tr::FirstLetter - 10));
|
||||
|
||||
if constexpr (HasAltLetterEnum<Tr>::value) {
|
||||
const __m128i char_befo_A = _mm_set1_epi32(g_AltLetterOrZero<Tr> - 1);
|
||||
const __m128i char_past_F = _mm_set1_epi32(g_AltLetterOrZero<Tr> + Base - 10);
|
||||
const __m128i alt_mask = _mm_and_si128(_mm_cmpgt_epi32(digits, char_befo_A), _mm_cmplt_epi32(digits, char_past_F));
|
||||
const __m128i alt_offs = _mm_and_si128(alt_mask, _mm_set1_epi32(g_AltLetterOrZero<Tr> - 10));
|
||||
offs = _mm_add_epi32(alt_offs, offs);
|
||||
mask = _mm_or_si128(mask, alt_mask);
|
||||
}
|
||||
const __m128i addend = _mm_add_epi32(offs, _mm_andnot_si128(mask, char_0));
|
||||
res = _mm_add_epi32(res, muly(_mm_sub_epi32(digits, addend), factor));
|
||||
factor = muly(factor, _mm_set1_epi32(base4));
|
||||
idx += 4;
|
||||
|
@ -261,7 +281,7 @@ namespace dhandy {
|
|||
{
|
||||
res = _mm_add_epi32(res, _mm_srli_si128(res, 8));
|
||||
res = _mm_add_epi32(res, _mm_srli_si128(res, 4));
|
||||
const std::array<int, 4> scale {1, base1, base2, base3};
|
||||
constexpr const std::array<int, 4> scale {1, base1, base2, base3};
|
||||
return negated_ifn(to_integer_sse<T, C, Base, Tr>(s + idx, l - idx) + _mm_cvtsi128_si32(res) * scale[l - idx], was_negative);
|
||||
}
|
||||
}
|
||||
|
@ -272,9 +292,9 @@ namespace dhandy {
|
|||
template <typename C, C FDigit='0', C FLetter='a', C CPlus='+', C CMinus='-', C CNull='\0'>
|
||||
struct ASCIITranslator {
|
||||
typedef C char_type;
|
||||
static const constexpr bool BehavesLikeASCII = true;
|
||||
static const constexpr C FirstDigit = FDigit;
|
||||
static const constexpr C FirstLetter = FLetter;
|
||||
//static const constexpr C AltLetter = FAltLetter;
|
||||
static const constexpr C Plus = CPlus;
|
||||
static const constexpr C Minus = CMinus;
|
||||
static const constexpr C NullChar = CNull;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue