From 5c680366b0597cdec0607a7e2ee00d4e34a11d38 Mon Sep 17 00:00:00 2001 From: uselessgoddess Date: Sun, 18 Jul 2021 15:14:27 +0300 Subject: [PATCH] Preview translation to C++ without tests --- cpp/CMakeLists.txt | 15 ++++++++ cpp/Platform.Numbers.Tests/AllTests.cpp | 1 + cpp/Platform.Numbers/Bit.h | 32 ++++++++++++++++ cpp/Platform.Numbers/Math.h | 51 +++++++++++++++++++++++++ cpp/Platform.Numbers/Platform.Numbers.h | 11 ++++++ cpp/conanfile.txt | 5 +++ 6 files changed, 115 insertions(+) create mode 100644 cpp/CMakeLists.txt create mode 100644 cpp/Platform.Numbers.Tests/AllTests.cpp create mode 100644 cpp/Platform.Numbers/Bit.h create mode 100644 cpp/Platform.Numbers/Math.h create mode 100644 cpp/Platform.Numbers/Platform.Numbers.h create mode 100644 cpp/conanfile.txt diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt new file mode 100644 index 0000000..909bfea --- /dev/null +++ b/cpp/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.8) + +project(Platform.Numbers) +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup(TARGETS) + +add_library(${PROJECT_NAME}.Library INTERFACE) +target_include_directories(${PROJECT_NAME}.Library INTERFACE ${PROJECT_NAME}) + +if((DEFINED LINKS_PLATFORM_TESTS) AND (${LINKS_PLATFORM_TESTS})) + add_executable(${PROJECT_NAME}.Tests ${PROJECT_NAME}.Tests/AllTests.cpp) + set_target_properties(${PROJECT_NAME}.Tests PROPERTIES CXX_STANDARD 20) + target_link_libraries(${PROJECT_NAME}.Tests PUBLIC CONAN_PKG::gtest) + target_link_libraries(${PROJECT_NAME}.Tests PUBLIC ${PROJECT_NAME}.Library) +endif() \ No newline at end of file diff --git a/cpp/Platform.Numbers.Tests/AllTests.cpp b/cpp/Platform.Numbers.Tests/AllTests.cpp new file mode 100644 index 0000000..2c32edb --- /dev/null +++ b/cpp/Platform.Numbers.Tests/AllTests.cpp @@ -0,0 +1 @@ +#include diff --git a/cpp/Platform.Numbers/Bit.h b/cpp/Platform.Numbers/Bit.h new file mode 100644 index 0000000..eb710f8 --- /dev/null +++ b/cpp/Platform.Numbers/Bit.h @@ -0,0 +1,32 @@ +namespace Platform::Numbers::Bit +{ + constexpr auto Count(std::unsigned_integral auto x) noexcept { return std::popcount(x); } + + constexpr auto GetLowestPosition(std::unsigned_integral auto value) noexcept { return (value == 0) ? -1 : std::countr_zero(value); } + + template + constexpr auto PartialRead(T target, int shift, int limit) noexcept + { + constexpr auto bits = sizeof(T) * 8; + shift = shift + bits * (shift < 0); + limit = limit + bits * (limit < 0); + + constexpr auto max_value = std::numeric_limits::max(); + auto sourceMask = ~(max_value << limit) & max_value; + auto targetMask = sourceMask << shift; + return (target & targetMask) >> shift; + } + + template + constexpr auto PartialWrite(T target, T source, int shift, int limit) noexcept + { + constexpr auto bits = sizeof(T) * 8; + shift = shift + bits * (shift < 0); + limit = limit + bits * (limit < 0); + + constexpr auto max_value = std::numeric_limits::max(); + auto sourceMask = ~(max_value << limit) & max_value; + auto targetMask = ~(sourceMask << shift); + return target & targetMask | (source & sourceMask) << shift; + } +} diff --git a/cpp/Platform.Numbers/Math.h b/cpp/Platform.Numbers/Math.h new file mode 100644 index 0000000..d3395a9 --- /dev/null +++ b/cpp/Platform.Numbers/Math.h @@ -0,0 +1,51 @@ +namespace Platform::Numbers::Math +{ + namespace Internal + { + constexpr std::uint64_t _factorials[] = + { + 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, + 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, + 355687428096000, 6402373705728000, 121645100408832000, 2432902008176640000 + }; + + constexpr std::uint64_t _catalans[] = + { + 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, + 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, + 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, + 18367353072152, 69533550916004, 263747951750360, 1002242216651368, 3814986502092304, + 14544636039226909, 55534064877048198, 212336130412243110, 812944042149730764, 3116285494907301262, 11959798385860453492UL + }; + } + + constexpr auto MaximumFactorialNumber = std::size(Internal::_factorials) - 1; + + constexpr auto MaximumCatalanIndex = std::size(Internal::_catalans) - 1; + + constexpr std::uint64_t Factorial(std::uint64_t n) + { + if (n <= MaximumFactorialNumber) + { + return Internal::_factorials[n]; + } + else + { + throw std::out_of_range(std::string("Only numbers from 0 to ").append(std::to_string(MaximumFactorialNumber)).append("are supported by unsigned integer with 64 bits length.")); + } + } + + constexpr std::uint64_t Catalan(std::size_t n) + { + if (n <= MaximumCatalanIndex) + { + return Internal::_catalans[n]; + } + else + { + throw std::out_of_range(std::string("Only numbers from 0 to ").append(std::to_string(MaximumCatalanIndex)).append("are supported by unsigned integer with 64 bits length.")); + } + } + + constexpr bool IsPowerOfTwo(std::size_t x) { return std::has_single_bit(x); } +} \ No newline at end of file diff --git a/cpp/Platform.Numbers/Platform.Numbers.h b/cpp/Platform.Numbers/Platform.Numbers.h new file mode 100644 index 0000000..685b72e --- /dev/null +++ b/cpp/Platform.Numbers/Platform.Numbers.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "Bit.h" +#include "Math.h" diff --git a/cpp/conanfile.txt b/cpp/conanfile.txt new file mode 100644 index 0000000..b9d4a73 --- /dev/null +++ b/cpp/conanfile.txt @@ -0,0 +1,5 @@ +[requires] +gtest/cci.20210126 + +[generators] +cmake