diff --git a/include/CppCore.Test/Encoding.h b/include/CppCore.Test/Encoding.h index eb1df186..a1eb6853 100644 --- a/include/CppCore.Test/Encoding.h +++ b/include/CppCore.Test/Encoding.h @@ -141,6 +141,141 @@ namespace CppCore { namespace Test // TODO: More than Base10 return true; } + INLINE static bool parse8() + { + uint8_t r; + CppCore::BaseX::parse("", r, CPPCORE_ALPHABET_B10); if (r != 0) return false; + CppCore::BaseX::parse("0", r, CPPCORE_ALPHABET_B10); if (r != 0) return false; + CppCore::BaseX::parse("1", r, CPPCORE_ALPHABET_B10); if (r != 1) return false; + CppCore::BaseX::parse("143", r, CPPCORE_ALPHABET_B10); if (r != 143) return false; + CppCore::BaseX::parse("255", r, CPPCORE_ALPHABET_B10); if (r != 255) return false; + CppCore::BaseX::parse("256", r, CPPCORE_ALPHABET_B10); if (r != 0) return false; + return true; + } + INLINE static bool parse16() + { + uint16_t r; + CppCore::BaseX::parse("", r, CPPCORE_ALPHABET_B10); if (r != 0) return false; + CppCore::BaseX::parse("0", r, CPPCORE_ALPHABET_B10); if (r != 0) return false; + CppCore::BaseX::parse("1", r, CPPCORE_ALPHABET_B10); if (r != 1) return false; + CppCore::BaseX::parse("143", r, CPPCORE_ALPHABET_B10); if (r != 143) return false; + CppCore::BaseX::parse("255", r, CPPCORE_ALPHABET_B10); if (r != 255) return false; + CppCore::BaseX::parse("65535", r, CPPCORE_ALPHABET_B10); if (r != 65535) return false; + CppCore::BaseX::parse("65536", r, CPPCORE_ALPHABET_B10); if (r != 0) return false; + return true; + } + INLINE static bool parse32() + { + uint32_t r; + CppCore::BaseX::parse("", r, CPPCORE_ALPHABET_B10); if (r != 0U) return false; + CppCore::BaseX::parse("0", r, CPPCORE_ALPHABET_B10); if (r != 0U) return false; + CppCore::BaseX::parse("1", r, CPPCORE_ALPHABET_B10); if (r != 1U) return false; + CppCore::BaseX::parse("143", r, CPPCORE_ALPHABET_B10); if (r != 143U) return false; + CppCore::BaseX::parse("255", r, CPPCORE_ALPHABET_B10); if (r != 255U) return false; + CppCore::BaseX::parse("65535", r, CPPCORE_ALPHABET_B10); if (r != 65535U) return false; + CppCore::BaseX::parse("4294967295", r, CPPCORE_ALPHABET_B10); if (r != 4294967295U) return false; + CppCore::BaseX::parse("4294967296", r, CPPCORE_ALPHABET_B10); if (r != 0) return false; + return true; + } + INLINE static bool parse64() + { + uint64_t r; + CppCore::BaseX::parse("", r, CPPCORE_ALPHABET_B10); if (r != 0U) return false; + CppCore::BaseX::parse("0", r, CPPCORE_ALPHABET_B10); if (r != 0U) return false; + CppCore::BaseX::parse("1", r, CPPCORE_ALPHABET_B10); if (r != 1U) return false; + CppCore::BaseX::parse("143", r, CPPCORE_ALPHABET_B10); if (r != 143U) return false; + CppCore::BaseX::parse("255", r, CPPCORE_ALPHABET_B10); if (r != 255U) return false; + CppCore::BaseX::parse("65535", r, CPPCORE_ALPHABET_B10); if (r != 65535U) return false; + CppCore::BaseX::parse("4294967295", r, CPPCORE_ALPHABET_B10); if (r != 4294967295U) return false; + CppCore::BaseX::parse("18446744073709551615", r, CPPCORE_ALPHABET_B10); if (r != 18446744073709551615ULL) return false; + CppCore::BaseX::parse("18446744073709551616", r, CPPCORE_ALPHABET_B10); if (r != 0) return false; + return true; + } + INLINE static bool parse128() + { + uint64_t r[2]; + CppCore::BaseX::parse("", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 0U) return false; + CppCore::BaseX::parse("0", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 0U) return false; + CppCore::BaseX::parse("1", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 1U) return false; + CppCore::BaseX::parse("143", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 143U) return false; + CppCore::BaseX::parse("255", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 255U) return false; + CppCore::BaseX::parse("65535", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 65535U) return false; + CppCore::BaseX::parse("4294967295", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 4294967295U) return false; + CppCore::BaseX::parse("18446744073709551615", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 18446744073709551615ULL) return false; + CppCore::BaseX::parse("340282366920938463463374607431768211455", r, CPPCORE_ALPHABET_B10); if (r[1] != 0xFFFFFFFFFFFFFFFFULL || r[0] != 0xFFFFFFFFFFFFFFFFULL) return false; + CppCore::BaseX::parse("340282366920938463463374607431768211456", r, CPPCORE_ALPHABET_B10); if (r[1] != 0U || r[0] != 0U) return false; + return true; + } + INLINE static bool tryparse8() + { + uint8_t r; + if (!CppCore::BaseX::tryparse("0", r, CPPCORE_ALPHABET_B10) || r != 0) return false; + if (!CppCore::BaseX::tryparse("1", r, CPPCORE_ALPHABET_B10) || r != 1) return false; + if (!CppCore::BaseX::tryparse("143", r, CPPCORE_ALPHABET_B10) || r != 143) return false; + if (!CppCore::BaseX::tryparse("255", r, CPPCORE_ALPHABET_B10) || r != 255) return false; + if ( CppCore::BaseX::tryparse("256", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("x", r, CPPCORE_ALPHABET_B10)) return false; + return true; + } + INLINE static bool tryparse16() + { + uint16_t r; + if (!CppCore::BaseX::tryparse("0", r, CPPCORE_ALPHABET_B10) || r != 0) return false; + if (!CppCore::BaseX::tryparse("1", r, CPPCORE_ALPHABET_B10) || r != 1) return false; + if (!CppCore::BaseX::tryparse("143", r, CPPCORE_ALPHABET_B10) || r != 143) return false; + if (!CppCore::BaseX::tryparse("255", r, CPPCORE_ALPHABET_B10) || r != 255) return false; + if (!CppCore::BaseX::tryparse("65535", r, CPPCORE_ALPHABET_B10) || r != 65535) return false; + if ( CppCore::BaseX::tryparse("65536", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("x", r, CPPCORE_ALPHABET_B10)) return false; + return true; + } + INLINE static bool tryparse32() + { + uint32_t r; + if (!CppCore::BaseX::tryparse("0", r, CPPCORE_ALPHABET_B10) || r != 0) return false; + if (!CppCore::BaseX::tryparse("1", r, CPPCORE_ALPHABET_B10) || r != 1) return false; + if (!CppCore::BaseX::tryparse("143", r, CPPCORE_ALPHABET_B10) || r != 143) return false; + if (!CppCore::BaseX::tryparse("255", r, CPPCORE_ALPHABET_B10) || r != 255) return false; + if (!CppCore::BaseX::tryparse("65535", r, CPPCORE_ALPHABET_B10) || r != 65535) return false; + if (!CppCore::BaseX::tryparse("4294967295", r, CPPCORE_ALPHABET_B10) || r != 4294967295U) return false; + if ( CppCore::BaseX::tryparse("4294967296", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("x", r, CPPCORE_ALPHABET_B10)) return false; + return true; + } + INLINE static bool tryparse64() + { + uint64_t r; + if (!CppCore::BaseX::tryparse("0", r, CPPCORE_ALPHABET_B10) || r != 0) return false; + if (!CppCore::BaseX::tryparse("1", r, CPPCORE_ALPHABET_B10) || r != 1) return false; + if (!CppCore::BaseX::tryparse("143", r, CPPCORE_ALPHABET_B10) || r != 143) return false; + if (!CppCore::BaseX::tryparse("255", r, CPPCORE_ALPHABET_B10) || r != 255) return false; + if (!CppCore::BaseX::tryparse("65535", r, CPPCORE_ALPHABET_B10) || r != 65535) return false; + if (!CppCore::BaseX::tryparse("4294967295", r, CPPCORE_ALPHABET_B10) || r != 4294967295U) return false; + if (!CppCore::BaseX::tryparse("18446744073709551615", r, CPPCORE_ALPHABET_B10) || r != 18446744073709551615ULL) return false; + if ( CppCore::BaseX::tryparse("18446744073709551616", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("x", r, CPPCORE_ALPHABET_B10)) return false; + return true; + } + INLINE static bool tryparse128() + { + uint64_t r[2]; + if (!CppCore::BaseX::tryparse("0", r, CPPCORE_ALPHABET_B10) || r[1] != 0U || r[0] != 0U) return false; + if (!CppCore::BaseX::tryparse("1", r, CPPCORE_ALPHABET_B10) || r[1] != 0U || r[0] != 1U) return false; + if (!CppCore::BaseX::tryparse("143", r, CPPCORE_ALPHABET_B10) || r[1] != 0U || r[0] != 143U) return false; + if (!CppCore::BaseX::tryparse("255", r, CPPCORE_ALPHABET_B10) || r[1] != 0U || r[0] != 255U) return false; + if (!CppCore::BaseX::tryparse("65535", r, CPPCORE_ALPHABET_B10) || r[1] != 0U || r[0] != 65535U) return false; + if (!CppCore::BaseX::tryparse("4294967295", r, CPPCORE_ALPHABET_B10) || r[1] != 0U || r[0] != 4294967295U) return false; + if (!CppCore::BaseX::tryparse("18446744073709551615", r, CPPCORE_ALPHABET_B10) || r[1] != 0U || r[0] != 18446744073709551615ULL) return false; + if (!CppCore::BaseX::tryparse("340282366920938463463374607431768211455", r, CPPCORE_ALPHABET_B10) || r[1] != 0xFFFFFFFFFFFFFFFFULL || r[0] != 0xFFFFFFFFFFFFFFFFULL) return false; + if ( CppCore::BaseX::tryparse("340282366920938463463374607431768211456", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("", r, CPPCORE_ALPHABET_B10)) return false; + if ( CppCore::BaseX::tryparse("x", r, CPPCORE_ALPHABET_B10)) return false; + return true; + } }; class Hex { @@ -910,6 +1045,16 @@ namespace CppCore { namespace Test { namespace VS TEST_METHOD(BASEX_TOSTRING16) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::tostring16()); } TEST_METHOD(BASEX_TOSTRING32) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::tostring32()); } TEST_METHOD(BASEX_TOSTRING64) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::tostring64()); } + TEST_METHOD(BASEX_PARSE8) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::parse8()); } + TEST_METHOD(BASEX_PARSE16) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::parse16()); } + TEST_METHOD(BASEX_PARSE32) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::parse32()); } + TEST_METHOD(BASEX_PARSE64) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::parse64()); } + TEST_METHOD(BASEX_PARSE128) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::parse128()); } + TEST_METHOD(BASEX_TRYPARSE8) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::tryparse8()); } + TEST_METHOD(BASEX_TRYPARSE16) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::tryparse16()); } + TEST_METHOD(BASEX_TRYPARSE32) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::tryparse32()); } + TEST_METHOD(BASEX_TRYPARSE64) { Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::tryparse64()); } + TEST_METHOD(BASEX_TRYPARSE128){ Assert::AreEqual(true, CppCore::Test::Encoding::BaseX::tryparse128()); } TEST_METHOD(HEX_BYTETOHEXSTR) { Assert::AreEqual(true, CppCore::Test::Encoding::Hex::Util::bytetohexstr()); } TEST_METHOD(HEX_TOSTRING) { Assert::AreEqual(true, CppCore::Test::Encoding::Hex::tostring()); } TEST_METHOD(HEX_TOSTRING16) { Assert::AreEqual(true, CppCore::Test::Encoding::Hex::tostring16()); } diff --git a/include/CppCore/Encoding.h b/include/CppCore/Encoding.h index 384d4639..f11eeeb3 100644 --- a/include/CppCore/Encoding.h +++ b/include/CppCore/Encoding.h @@ -213,18 +213,18 @@ namespace CppCore { assert(::strlen(alphabet) >= 2); uint8_t tbl[256]; - size_t n = 0; + uint8_t n = 0; CppCore::clear(r); CppCore::clear(tbl); while (const char c = *alphabet++) - tbl[c] = (uint8_t)n++; + tbl[c] = n++; if (const char c = *input++) { *(uint8_t*)&r = tbl[c]; while (const char c = *input++) { CppCore::umul(r, n, r); - CppCore::uadd(r, (size_t)tbl[c], r); + CppCore::uadd(r, tbl[c], r); } } } @@ -239,10 +239,10 @@ namespace CppCore if (!input || !alphabet) return false; // null pointer uint8_t tbl[256]; - size_t n = 0; + uint8_t n = 0; CppCore::bytedup(0xFF, tbl); while (const char c = *alphabet++) - tbl[c] = (uint8_t)n++; + tbl[c] = n++; if (n < 2U) CPPCORE_UNLIKELY return false; // alphabet too short if (const char first = *input++) CPPCORE_LIKELY @@ -262,7 +262,7 @@ namespace CppCore if (t.of != 0U) CPPCORE_UNLIKELY return false; // mul overflow uint8_t carry = 0; - CppCore::addcarry(t.v, (size_t)idx, r, carry); + CppCore::addcarry(t.v, idx, r, carry); if (carry != 0) CPPCORE_UNLIKELY return false; // add overflow } diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h index 61ffd4e6..aa9fa6f5 100644 --- a/include/CppCore/Math/Util.h +++ b/include/CppCore/Math/Util.h @@ -639,8 +639,8 @@ namespace CppCore template INLINE static void addcarry(const UINT1& x, const UINT2& y, UINT3& z, uint8_t& c) { - static_assert(sizeof(UINT1) % 4 == 0); - static_assert(sizeof(UINT2) % 4 == 0); + static_assert(sizeof(UINT1) % 4 == 0 || sizeof(UINT1) < sizeof(size_t)); + static_assert(sizeof(UINT2) % 4 == 0 || sizeof(UINT2) < sizeof(size_t)); static_assert(sizeof(UINT3) % 4 == 0); constexpr size_t MAXSIZE = MAX(sizeof(UINT1), sizeof(UINT2)); constexpr size_t MINSIZE = MIN(sizeof(UINT1), sizeof(UINT2)); @@ -663,8 +663,11 @@ namespace CppCore for (size_t i = NMIN; i < NUINT2; i++) CppCore::addcarry64(0ULL, py[i], pz[i], c); } - else + else if + #else + if #endif + constexpr (sizeof(UINT1) % 4 == 0 && sizeof(UINT2) % 4 == 0 && sizeof(UINT3) % 4 == 0) { constexpr size_t NUINT1 = sizeof(UINT1) / 4; constexpr size_t NUINT2 = sizeof(UINT2) / 4; @@ -681,6 +684,9 @@ namespace CppCore for (size_t i = NMIN; i < NUINT2; i++) CppCore::addcarry32(0U, py[i], pz[i], c); } + else if constexpr (sizeof(UINT1) < sizeof(size_t)) { addcarry((size_t)x, y, z, c); } + else if constexpr (sizeof(UINT2) < sizeof(size_t)) { addcarry(x, (size_t)y, z, c); } + else throw; } /// @@ -691,6 +697,14 @@ namespace CppCore CppCore::addcarry8(x, y, r, c); } + /// + /// Template Specialization for 16+8=16 + /// + template<> INLINE void addcarry(const uint16_t& x, const uint8_t& y, uint16_t& r, uint8_t& c) + { + CppCore::addcarry16(x, y, r, c); + } + /// /// Template Specialization for 16+16=16 /// @@ -699,6 +713,22 @@ namespace CppCore CppCore::addcarry16(x, y, r, c); } + /// + /// Template Specialization for 32+8=32 + /// + template<> INLINE void addcarry(const uint32_t& x, const uint8_t& y, uint32_t& r, uint8_t& c) + { + CppCore::addcarry32(x, y, r, c); + } + + /// + /// Template Specialization for 32+16=32 + /// + template<> INLINE void addcarry(const uint32_t& x, const uint16_t& y, uint32_t& r, uint8_t& c) + { + CppCore::addcarry32(x, y, r, c); + } + /// /// Template Specialization for 32+32=32 /// @@ -707,6 +737,30 @@ namespace CppCore CppCore::addcarry32(x, y, r, c); } + /// + /// Template Specialization for 64+8=64 + /// + template<> INLINE void addcarry(const uint64_t& x, const uint8_t& y, uint64_t& r, uint8_t& c) + { + CppCore::addcarry64(x, y, r, c); + } + + /// + /// Template Specialization for 64+16=64 + /// + template<> INLINE void addcarry(const uint64_t& x, const uint16_t& y, uint64_t& r, uint8_t& c) + { + CppCore::addcarry64(x, y, r, c); + } + + /// + /// Template Specialization for 64+32=64 + /// + template<> INLINE void addcarry(const uint64_t& x, const uint32_t& y, uint64_t& r, uint8_t& c) + { + CppCore::addcarry64(x, y, r, c); + } + /// /// Template Specialization for 64+64=64 /// @@ -768,8 +822,10 @@ namespace CppCore template INLINE static void uadd(const UINT1& x, const UINT2& y, UINT3& r) { - uint8_t c = 0; - CppCore::addcarry(x, y, r, c); + if constexpr (sizeof(UINT1) < sizeof(size_t)) { CppCore::uadd((size_t)x, y, r); } + else if constexpr (sizeof(UINT2) < sizeof(size_t)) { CppCore::uadd(x, (size_t)y, r); } + else if constexpr (sizeof(UINT3) < sizeof(size_t)) { size_t t; CppCore::uadd(x, y, t); r = (UINT3)t; } + else { uint8_t c = 0; CppCore::addcarry(x, y, r, c); } } /// diff --git a/src/CppCore.Test/Test.cpp b/src/CppCore.Test/Test.cpp index fbd16972..f6872a32 100644 --- a/src/CppCore.Test/Test.cpp +++ b/src/CppCore.Test/Test.cpp @@ -700,6 +700,16 @@ int main() TEST(CppCore::Test::Encoding::BaseX::tostring16, "tostring16: ", std::endl); TEST(CppCore::Test::Encoding::BaseX::tostring32, "tostring32: ", std::endl); TEST(CppCore::Test::Encoding::BaseX::tostring64, "tostring64: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::parse8, "parse8: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::parse16, "parse16: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::parse32, "parse32: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::parse64, "parse64: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::parse128, "parse128: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::tryparse8, "tryparse8: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::tryparse16, "tryparse16: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::tryparse32, "tryparse32: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::tryparse64, "tryparse64: ", std::endl); + TEST(CppCore::Test::Encoding::BaseX::tryparse128,"tryparse128:", std::endl); std::cout << "-------------------------------" << std::endl; std::cout << " CppCore::Encoding::Decimal " << std::endl;