| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you under the Apache License, Version 2.0 (the | |
| // "License"); you may not use this file except in compliance | |
| // with the License. You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, | |
| // software distributed under the License is distributed on an | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| // KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations | |
| // under the License. | |
| #pragma once | |
| #include <stdint.h> | |
| #include <iostream> | |
| #include <string> | |
| #include "util/sse_util.hpp" | |
| // the code refer: https://clickhouse.tech/codebrowser/html_report//ClickHouse/src/Functions/LowerUpperImpl.h.html | |
| // Doris only handle one character at a time, this function use SIMD to more characters at a time | |
| namespace doris::simd { | |
| template <char not_case_lower_bound, char not_case_upper_bound> | |
| class LowerUpperImpl { | |
| public: | |
| static void transfer(const uint8_t* src, const uint8_t* src_end, uint8_t* dst) { | |
| const auto flip_case_mask = 'A' ^ 'a'; | |
| #if defined(__SSE2__) || defined(__aarch64__) | |
| const auto bytes_sse = sizeof(__m128i); | |
| const auto src_end_sse = src_end - (src_end - src) % bytes_sse; | |
| const auto v_not_case_lower_bound = _mm_set1_epi8(not_case_lower_bound - 1); | |
| const auto v_not_case_upper_bound = _mm_set1_epi8(not_case_upper_bound + 1); | |
| const auto v_flip_case_mask = _mm_set1_epi8(flip_case_mask); | |
| for (; src < src_end_sse; src += bytes_sse, dst += bytes_sse) { | |
| const auto chars = _mm_loadu_si128(reinterpret_cast<const __m128i*>(src)); | |
| const auto is_not_case = _mm_and_si128(_mm_cmpgt_epi8(chars, v_not_case_lower_bound), | |
| _mm_cmplt_epi8(chars, v_not_case_upper_bound)); | |
| const auto xor_mask = _mm_and_si128(v_flip_case_mask, is_not_case); | |
| const auto cased_chars = _mm_xor_si128(chars, xor_mask); | |
| _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), cased_chars); | |
| } | |
| #endif | |
| for (; src < src_end; ++src, ++dst) | |
| if (*src >= not_case_lower_bound && *src <= not_case_upper_bound) | |
| *dst = *src ^ flip_case_mask; | |
| else | |
| *dst = *src; | |
| } | |
| }; | |
| } // namespace doris::simd |