diff options
author | Charles Milette <me@charlesmilette.net> | 2019-07-25 23:21:11 +0300 |
---|---|---|
committer | Charles Milette <me@charlesmilette.net> | 2019-07-25 23:38:34 +0300 |
commit | d5d7171f6d21f2894e67bbe47c9a48e01114700f (patch) | |
tree | 8b20f8e4b0b33719e432e8564f2f3d8b7303ef8a /include/rapidjson/internal | |
parent | d87b698d0fcc10a5f632ecbc80a9cb2a8fa094a5 (diff) |
Fix ARM NEON under MSVC
Diffstat (limited to 'include/rapidjson/internal')
-rw-r--r-- | include/rapidjson/internal/clzll.h | 72 | ||||
-rw-r--r-- | include/rapidjson/internal/diyfp.h | 18 |
2 files changed, 74 insertions, 16 deletions
diff --git a/include/rapidjson/internal/clzll.h b/include/rapidjson/internal/clzll.h new file mode 100644 index 00000000..7c2fa48f --- /dev/null +++ b/include/rapidjson/internal/clzll.h @@ -0,0 +1,72 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// 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. + +#ifndef RAPIDJSON_CLZLL_H_ +#define RAPIDJSON_CLZLL_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) +#include <intrin.h> +#if defined(_WIN64) +#pragma intrinsic(_BitScanReverse64) +#else +#pragma intrinsic(_BitScanReverse) +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#if defined(__has_builtin) && __has_builtin(__builtin_clzll) +#define RAPIDJSON_CLZLL __builtin_clzll +#else + +inline uint32_t clzll(uint64_t x) { + // Passing 0 to __builtin_clzll is UB in GCC and results in an + // infinite loop in the software implementation. + RAPIDJSON_ASSERT(x != 0); + +#ifdef _MSC_VER + unsigned long r = 0; +#ifdef _WIN64 + _BitScanReverse64(&r, x); +#else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) + return 63 - (r + 32); + + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF)); +#endif // _WIN64 + + return 63 - r; +#else + uint32_t r; + while (!(x & (static_cast<uint64_t>(1) << 63))) { + x <<= 1; + ++r; + } + + return r; +#endif // _MSC_VER +} + +#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll +#endif // defined(__has_builtin) && __has_builtin(__builtin_clzll) + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_CLZLL_H_
\ No newline at end of file diff --git a/include/rapidjson/internal/diyfp.h b/include/rapidjson/internal/diyfp.h index b6c2cf56..ab5ee071 100644 --- a/include/rapidjson/internal/diyfp.h +++ b/include/rapidjson/internal/diyfp.h @@ -20,11 +20,11 @@ #define RAPIDJSON_DIYFP_H_ #include "../rapidjson.h" +#include "clzll.h" #include <limits> #if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) #include <intrin.h> -#pragma intrinsic(_BitScanReverse64) #pragma intrinsic(_umul128) #endif @@ -100,22 +100,8 @@ struct DiyFp { } DiyFp Normalize() const { - RAPIDJSON_ASSERT(f != 0); // https://stackoverflow.com/a/26809183/291737 -#if defined(_MSC_VER) && defined(_M_AMD64) - unsigned long index; - _BitScanReverse64(&index, f); - return DiyFp(f << (63 - index), e - (63 - index)); -#elif defined(__GNUC__) && __GNUC__ >= 4 - int s = __builtin_clzll(f); + uint32_t s = RAPIDJSON_CLZLL(f); return DiyFp(f << s, e - s); -#else - DiyFp res = *this; - while (!(res.f & (static_cast<uint64_t>(1) << 63))) { - res.f <<= 1; - res.e--; - } - return res; -#endif } DiyFp NormalizeBoundary() const { |