Add case sensitivity support to sse conversion

This commit is contained in:
King_DuckZ 2021-05-29 12:01:01 +02:00
parent 094f7fc679
commit a675624cab
2 changed files with 63 additions and 7 deletions

View file

@ -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;