From 6364c8e5ab1b9b5df01df25ff102d1c48aa0d389 Mon Sep 17 00:00:00 2001 From: escherstair Date: Tue, 4 Aug 2020 10:01:44 +0200 Subject: [PATCH 1/6] fix _BitScanReverse() usage for CE6 --- include/rapidjson/internal/clzll.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/include/rapidjson/internal/clzll.h b/include/rapidjson/internal/clzll.h index 6cd7923..f43e6a7 100644 --- a/include/rapidjson/internal/clzll.h +++ b/include/rapidjson/internal/clzll.h @@ -17,7 +17,7 @@ #include "../rapidjson.h" -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(UNDER_CE) #include #if defined(_WIN64) #pragma intrinsic(_BitScanReverse64) @@ -38,6 +38,27 @@ inline uint32_t clzll(uint64_t x) { unsigned long r = 0; #if defined(_WIN64) _BitScanReverse64(&r, x); +#elif defined(UNDER_CE) + // Scan the high 32 bits. + uint32_t high = static_cast(x >> 32); + if (high != 0) + { + unsigned long index = 31; + while((high & (1U<(x & 0xFFFFFFFF); + unsigned long index = 31; + while((low & (1U<(x >> 32))) From 91940e84b139db8d098e7182ae836595c677b115 Mon Sep 17 00:00:00 2001 From: escherstair Date: Tue, 4 Aug 2020 14:38:45 +0200 Subject: [PATCH 2/6] fallback to the naive version for CE6 --- include/rapidjson/internal/clzll.h | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/include/rapidjson/internal/clzll.h b/include/rapidjson/internal/clzll.h index f43e6a7..73a54f6 100644 --- a/include/rapidjson/internal/clzll.h +++ b/include/rapidjson/internal/clzll.h @@ -34,31 +34,10 @@ inline uint32_t clzll(uint64_t x) { // infinite loop in the software implementation. RAPIDJSON_ASSERT(x != 0); -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(UNDER_CE) unsigned long r = 0; #if defined(_WIN64) _BitScanReverse64(&r, x); -#elif defined(UNDER_CE) - // Scan the high 32 bits. - uint32_t high = static_cast(x >> 32); - if (high != 0) - { - unsigned long index = 31; - while((high & (1U<(x & 0xFFFFFFFF); - unsigned long index = 31; - while((low & (1U<(x >> 32))) From aa5dd6086519717342cafd846f70737cba315aa7 Mon Sep 17 00:00:00 2001 From: escherstair Date: Tue, 4 Aug 2020 14:39:19 +0200 Subject: [PATCH 3/6] fix naive version implementation --- include/rapidjson/internal/clzll.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/internal/clzll.h b/include/rapidjson/internal/clzll.h index 73a54f6..9de8c49 100644 --- a/include/rapidjson/internal/clzll.h +++ b/include/rapidjson/internal/clzll.h @@ -53,10 +53,10 @@ inline uint32_t clzll(uint64_t x) { return static_cast(__builtin_clzll(x)); #else // naive version - uint32_t r; + uint32_t r = 63; while (!(x & (static_cast(1) << 63))) { x <<= 1; - ++r; + --r; } return r; From 58e29648561e47f6fc11ee2c2bbf8628ffc46f57 Mon Sep 17 00:00:00 2001 From: escherstair Date: Thu, 6 Aug 2020 14:57:39 +0200 Subject: [PATCH 4/6] add unit test for clzll() --- test/unittest/CMakeLists.txt | 1 + test/unittest/clzlltest.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 test/unittest/clzlltest.cpp diff --git a/test/unittest/CMakeLists.txt b/test/unittest/CMakeLists.txt index 072b7b1..fc8803e 100644 --- a/test/unittest/CMakeLists.txt +++ b/test/unittest/CMakeLists.txt @@ -3,6 +3,7 @@ include(CheckCXXCompilerFlag) set(UNITTEST_SOURCES allocatorstest.cpp bigintegertest.cpp + clzlltest.cpp cursorstreamwrappertest.cpp documenttest.cpp dtoatest.cpp diff --git a/test/unittest/clzlltest.cpp b/test/unittest/clzlltest.cpp new file mode 100644 index 0000000..9c52812 --- /dev/null +++ b/test/unittest/clzlltest.cpp @@ -0,0 +1,34 @@ +// 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. + +#include "unittest.h" +#include "rapidjson/internal/clzll.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +#endif + +using namespace rapidjson::internal; + +TEST(clzll, normal) { + EXPECT_EQ(clzll(1), 0U); + EXPECT_EQ(clzll(2), 1U); + EXPECT_EQ(clzll(12), 3U); + EXPECT_EQ(clzll(0x0000000080000001UL), 31U); + EXPECT_EQ(clzll(0x8000000000000001UL), 63U); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif From 7f559ec80ab4d129e3c3a3eb109fe5049e751e98 Mon Sep 17 00:00:00 2001 From: escherstair Date: Thu, 6 Aug 2020 15:55:26 +0200 Subject: [PATCH 5/6] fix naive implementation for clzll() --- include/rapidjson/internal/clzll.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/internal/clzll.h b/include/rapidjson/internal/clzll.h index 9de8c49..47bb7ab 100644 --- a/include/rapidjson/internal/clzll.h +++ b/include/rapidjson/internal/clzll.h @@ -53,10 +53,10 @@ inline uint32_t clzll(uint64_t x) { return static_cast(__builtin_clzll(x)); #else // naive version - uint32_t r = 63; + uint32_t r = 0; while (!(x & (static_cast(1) << 63))) { x <<= 1; - --r; + ++r; } return r; From 5fbf8bf89cec8154c4b0be0c5c529694e8477bf2 Mon Sep 17 00:00:00 2001 From: escherstair Date: Thu, 6 Aug 2020 15:55:42 +0200 Subject: [PATCH 6/6] fix unit test --- test/unittest/clzlltest.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/unittest/clzlltest.cpp b/test/unittest/clzlltest.cpp index 9c52812..a5b3e2e 100644 --- a/test/unittest/clzlltest.cpp +++ b/test/unittest/clzlltest.cpp @@ -22,11 +22,11 @@ RAPIDJSON_DIAG_PUSH using namespace rapidjson::internal; TEST(clzll, normal) { - EXPECT_EQ(clzll(1), 0U); - EXPECT_EQ(clzll(2), 1U); - EXPECT_EQ(clzll(12), 3U); - EXPECT_EQ(clzll(0x0000000080000001UL), 31U); - EXPECT_EQ(clzll(0x8000000000000001UL), 63U); + EXPECT_EQ(clzll(1), 63U); + EXPECT_EQ(clzll(2), 62U); + EXPECT_EQ(clzll(12), 60U); + EXPECT_EQ(clzll(0x0000000080000001UL), 32U); + EXPECT_EQ(clzll(0x8000000000000001UL), 0U); } #ifdef __GNUC__