From 9dd818e0101a93f32a862fd9f7ebc115ff1be5fa Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Wed, 11 Dec 2024 22:59:46 +0800 Subject: [PATCH 01/12] wip --- src/big_uint.hpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/big_uint.hpp diff --git a/src/big_uint.hpp b/src/big_uint.hpp new file mode 100644 index 0000000..c2f795e --- /dev/null +++ b/src/big_uint.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include + +namespace big_uint { + +template +struct big_uint { + template + friend constexpr auto operator+(const big_uint& u, const big_uint& v) + -> big_uint<(N1 > N2) ? N1 : N2>; + + using word_type_ = unsigned int; + static constexpr size_t word_size_ = sizeof(word_type_); + static constexpr size_t digit_count_ = Nbits / word_size_ + \ + (((1u << word_size_) - 1) & Nbits) > 0 ? 1 : 0; + std::array digits_; +}; + +template +inline constexpr void add(big_uint& w, const big_uint& u, const big_uint& v) +{ + static_assert(N3 >= N1); + static_assert(N3 >= N2); + static_assert(N1 >= N2); + + typename std::remove_reference_t::word_type_ carry = 0; + for (int i = 0; i < v.digits_.size(); ++i) { + w.digits_[i] = u.digits_[i] + carry; + //carry + } +} + +template +inline constexpr auto operator+(const big_uint& u, const big_uint& v) + -> big_uint<(N1 > N2) ? N1 : N2> +{ + if constexpr (N1 > N2) { + big_uint w { 0 }; + add(w, u, v); + return w; + } else { + big_uint w { 0 }; + add(w, v, u); + return w; + } +} + +} From 3eb2a2a9c5b526a9c565a177cc48a531a740b4c8 Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Tue, 17 Dec 2024 18:27:12 +0800 Subject: [PATCH 02/12] wip --- src/big_uint.hpp | 2 ++ src/details/big_uint.hpp | 72 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/details/big_uint.hpp diff --git a/src/big_uint.hpp b/src/big_uint.hpp index c2f795e..3801316 100644 --- a/src/big_uint.hpp +++ b/src/big_uint.hpp @@ -1,5 +1,7 @@ #pragma once +#include "details/big_uint.hpp" + #include #include #include diff --git a/src/details/big_uint.hpp b/src/details/big_uint.hpp new file mode 100644 index 0000000..6e22c11 --- /dev/null +++ b/src/details/big_uint.hpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +namespace details::big_uint { + +template +struct big_uint { + using value_type = Word; + static constexpr std::size_t value_type_nbits = sizeof(value_type) * CHAR_BIT; + static constexpr value_type bitmask_msb = (1u << (Nbits % value_type_nbits)) - 1u; + std::array digits; + + constexpr value_type& operator[](std::size_t i) + { + return digits[i]; + } +}; + +template +constexpr bool add(big_uint& u, const big_uint& v, const big_uint& w) noexcept + requires (N1 >= N2) +{ + T c = 0u; + std::size_t i; + for (i = 0; i < w.digits.size(); ++i) { + u[i] = v[i] + c; + c = u[i] < c ? 1u : 0u; + u[i] += w[i]; + if (u[i] < w[i]) { + c++; + } + } + + if constexpr (N1 > N2) { + for (; i < v.digits.size(); ++i) { + u[i] = v[i] + c; + c = u[i] < c ? 1u : 0u; + } + } + + if constexpr (u.bitmask_msb > 0) { + u.digits.back() &= u.bitmask_msb; + } + + return c; +} + +template +constexpr bool substract(big_uint& u, const big_uint& v, const big_uint& w) noexcept + requires (N1 >= N2) +{ + T b = 0; + return b; +} + +template +constexpr void complement(big_uint& u, const big_uint& v) noexcept +{ + for (std::size_t i = 0u; i < v.digits.size(); ++i) { + u[i] = ~v[i]; + } + + if constexpr (u.bitmask_msb > 0) { + u.digits.back() &= u.bitmask_msb; + } +} + +} From 6ca2955993c517983671b9e1d873a7d64aa43503 Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Wed, 18 Dec 2024 23:42:00 +0800 Subject: [PATCH 03/12] wip --- src/big_uint.hpp | 62 +++++++++++++++------------------- src/details/big_uint.hpp | 72 ---------------------------------------- 2 files changed, 27 insertions(+), 107 deletions(-) delete mode 100644 src/details/big_uint.hpp diff --git a/src/big_uint.hpp b/src/big_uint.hpp index 3801316..ab7cc00 100644 --- a/src/big_uint.hpp +++ b/src/big_uint.hpp @@ -1,6 +1,6 @@ #pragma once -#include "details/big_uint.hpp" +#include "detail/big_uint.hpp" #include #include @@ -8,46 +8,38 @@ namespace big_uint { -template -struct big_uint { - template - friend constexpr auto operator+(const big_uint& u, const big_uint& v) - -> big_uint<(N1 > N2) ? N1 : N2>; - - using word_type_ = unsigned int; - static constexpr size_t word_size_ = sizeof(word_type_); - static constexpr size_t digit_count_ = Nbits / word_size_ + \ - (((1u << word_size_) - 1) & Nbits) > 0 ? 1 : 0; - std::array digits_; +template +struct big_uint : detail::big_uint::big_uint { + template + constexpr auto operator+( + const big_uint& u) const + -> big_uint Np) ? N : Np>; + + template + constexpr auto operator-( + const big_uint& u) const + -> big_uint Np) ? N : Np>; }; -template -inline constexpr void add(big_uint& w, const big_uint& u, const big_uint& v) +template +template +inline constexpr auto big_uint::operator+( + const big_uint& u) const + -> big_uint Np) ? N : Np> { - static_assert(N3 >= N1); - static_assert(N3 >= N2); - static_assert(N1 >= N2); - - typename std::remove_reference_t::word_type_ carry = 0; - for (int i = 0; i < v.digits_.size(); ++i) { - w.digits_[i] = u.digits_[i] + carry; - //carry - } + auto w = big_uint Np) ? N : Np>{ 0 }; + detail::big_uint::add(w, *this, u); + return w; } -template -inline constexpr auto operator+(const big_uint& u, const big_uint& v) - -> big_uint<(N1 > N2) ? N1 : N2> +template +template +inline constexpr auto big_uint::operator-( + const big_uint& u) const + -> big_uint Np) ? N : Np> { - if constexpr (N1 > N2) { - big_uint w { 0 }; - add(w, u, v); - return w; - } else { - big_uint w { 0 }; - add(w, v, u); - return w; - } + auto w = big_uint Np) ? N : Np>{ 0 }; + detail::big_uint::substract(w, *this, u); } } diff --git a/src/details/big_uint.hpp b/src/details/big_uint.hpp deleted file mode 100644 index 6e22c11..0000000 --- a/src/details/big_uint.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace details::big_uint { - -template -struct big_uint { - using value_type = Word; - static constexpr std::size_t value_type_nbits = sizeof(value_type) * CHAR_BIT; - static constexpr value_type bitmask_msb = (1u << (Nbits % value_type_nbits)) - 1u; - std::array digits; - - constexpr value_type& operator[](std::size_t i) - { - return digits[i]; - } -}; - -template -constexpr bool add(big_uint& u, const big_uint& v, const big_uint& w) noexcept - requires (N1 >= N2) -{ - T c = 0u; - std::size_t i; - for (i = 0; i < w.digits.size(); ++i) { - u[i] = v[i] + c; - c = u[i] < c ? 1u : 0u; - u[i] += w[i]; - if (u[i] < w[i]) { - c++; - } - } - - if constexpr (N1 > N2) { - for (; i < v.digits.size(); ++i) { - u[i] = v[i] + c; - c = u[i] < c ? 1u : 0u; - } - } - - if constexpr (u.bitmask_msb > 0) { - u.digits.back() &= u.bitmask_msb; - } - - return c; -} - -template -constexpr bool substract(big_uint& u, const big_uint& v, const big_uint& w) noexcept - requires (N1 >= N2) -{ - T b = 0; - return b; -} - -template -constexpr void complement(big_uint& u, const big_uint& v) noexcept -{ - for (std::size_t i = 0u; i < v.digits.size(); ++i) { - u[i] = ~v[i]; - } - - if constexpr (u.bitmask_msb > 0) { - u.digits.back() &= u.bitmask_msb; - } -} - -} From a89927a7cfcb17fe7657bdaa20bfd66703d5a862 Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Thu, 19 Dec 2024 22:46:45 +0800 Subject: [PATCH 04/12] wip --- src/big_uint.hpp | 26 +++++++ src/detail/big_uint.hpp | 159 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 src/detail/big_uint.hpp diff --git a/src/big_uint.hpp b/src/big_uint.hpp index ab7cc00..46c18f6 100644 --- a/src/big_uint.hpp +++ b/src/big_uint.hpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include namespace big_uint { @@ -40,6 +42,30 @@ inline constexpr auto big_uint::operator-( { auto w = big_uint Np) ? N : Np>{ 0 }; detail::big_uint::substract(w, *this, u); + return w; +} + +template +inline constexpr big_uint from_string(std::string_view s) +{ + auto v = big_uint{ 0 }; + detail::big_uint::from_string(v, s); + return v; } } + +template +struct std::formatter> { + constexpr auto parse(std::format_parse_context& context) + { + return context.begin(); + } + + auto format(const big_uint::big_uint& v, std::format_context& context) const + { + std::string s; + detail::big_uint::to_string(s, v); + return std::format_to(context.out(), "{}", s); + } +}; diff --git a/src/detail/big_uint.hpp b/src/detail/big_uint.hpp new file mode 100644 index 0000000..a11eba9 --- /dev/null +++ b/src/detail/big_uint.hpp @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace detail::big_uint { + +template + requires (N > 0) +struct big_uint : std::array { + using word_type = T; + static constexpr std::size_t word_nbits = sizeof(word_type) * CHAR_BIT; + static constexpr std::size_t word_hbytes = sizeof(word_type) * 2u; + static constexpr word_type bitmask_msb = (1u << (N % word_nbits)) - 1u; +}; + +template +inline constexpr bool add( + big_uint N2) ? N1 : N2>& u, + const big_uint& v, + const big_uint& w) noexcept +{ + T c = 0u; + std::size_t i = 0u; + constexpr std::size_t s = v.size() < w.size() ? v.size() : w.size(); + for ( ; i < s; ++i) { + u[i] = v[i] + c; + c = u[i] < c ? 1u : 0u; + u[i] += w[i]; + if (u[i] < w[i]) { + c++; + } + } + + if constexpr (N1 > N2) { + for ( ; i < v.size(); ++i) { + u[i] = v[i] + c; + c = u[i] < c ? 1u : 0u; + } + } else { + for ( ; i < w.size(); ++i) { + u[i] = w[i] + c; + c = u[i] < c ? 1u : 0u; + } + } + + if constexpr (u.bitmask_msb > 0) { + u.back() &= u.bitmask_msb; + } + + return c; +} + +template +inline constexpr bool substract( + big_uint N2) ? N1 : N2>& u, + const big_uint& v, + const big_uint& w) noexcept +{ + T b = 0u; + std::size_t i = 0u; + constexpr std::size_t s = v.size() < w.size() ? v.size() : w.size(); + for ( ; i < s; ++i) { + u[i] = v[i] - b; + b = (u[i] > std::numeric_limits::max() - b) ? 1u : 0u; + u[i] -= w[i]; + if (u[i] > std::numeric_limits::max() - w[i]) { + b++; + } + } + + if constexpr (v.size() > w.size()) { + for ( ; i < v.size(); ++i) { + u[i] = v[i] - b; + b = (u[i] > std::numeric_limits::max() - b) ? 1u : 0u; + } + } else { + for ( ; i < w.size(); ++i) { + u[i] = - b; + b = (u[i] > std::numeric_limits::max() - b) ? 1u : 0u; + u[i] -= w[i]; + if (u[i] > std::numeric_limits::max() - w[i]) { + b++; + } + } + } + + if constexpr (u.bitmask_msb > 0) { + u.back() &= u.bitmask_msb; + } + + return b; +} + +template +inline constexpr void complement(big_uint& u, const big_uint& v) noexcept +{ + for (std::size_t i = 0u; i < v.size(); ++i) { + u[i] = ~v[i]; + } + + if constexpr (u.bitmask_msb > 0) { + u.back() &= u.bitmask_msb; + } +} + +inline constexpr bool compile_time_assert(bool pred) noexcept +{ + return true; +} + +#define ASSERT(pred) \ + do { \ + if constexpr(compile_time_assert((pred))) { \ + static_assert((pred)); \ + } else { \ + assert(pred); \ + } \ + } while (0) + +template +inline constexpr void from_string(big_uint& u, std::string_view s) noexcept +{ + ASSERT((u.size() * (sizeof(T) << 1u)) > s.length()); +// std::size_t i = 0; +// for (auto rit = std::cbegin(s); rit != std::cend(s); ++rit) { +// char c = *rit; +// T v; +// if (c >= '0' && c <= '9') { +// v = c - '0'; +// } else if (c >= 'a' && c <= 'z') { +// v = c - 'a'; +// } else if (c >= 'A' && c <= 'Z') { +// v = c - 'A'; +// } else { +// ASSERT(false); +// } +// +// u[i / u.word_hbytes] |= v << (i % u.word_hbytes * 4u); +// i++; +// } +} + +template +inline constexpr void to_string(std::string& s, const big_uint& u) +{ + for (auto rit = std::crbegin(u); rit != std::crend(u); ++rit) { + s.append(std::format("{1:0>{0}x}", sizeof(T) * 2, *rit)); + } +} + +} From 330e24878b0cb44ee872d50913f7bcc66d14595a Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Wed, 1 Jan 2025 23:30:25 +0800 Subject: [PATCH 05/12] wip --- src/big_uint.hpp | 16 +++++++++++++++ src/detail/big_uint.hpp | 45 ++++++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/big_uint.hpp b/src/big_uint.hpp index 46c18f6..80bca70 100644 --- a/src/big_uint.hpp +++ b/src/big_uint.hpp @@ -21,6 +21,11 @@ struct big_uint : detail::big_uint::big_uint { constexpr auto operator-( const big_uint& u) const -> big_uint Np) ? N : Np>; + + template + constexpr auto operator*( + const big_uint& u) const + -> big_uint Np) ? N : Np>; }; template @@ -45,6 +50,17 @@ inline constexpr auto big_uint::operator-( return w; } +template +template +inline constexpr auto big_uint::operator*( + const big_uint& u) const + -> big_uint Np) ? N : Np> +{ + auto w = big_uint Np) ? N : Np>{ 0 }; + detail::big_uint::multiply(w, *this, u); + return w; +} + template inline constexpr big_uint from_string(std::string_view s) { diff --git a/src/detail/big_uint.hpp b/src/detail/big_uint.hpp index a11eba9..72d5a38 100644 --- a/src/detail/big_uint.hpp +++ b/src/detail/big_uint.hpp @@ -99,6 +99,15 @@ inline constexpr bool substract( return b; } +template +inline constexpr bool multiply( + big_uint N2) ? N1 : N2>& u, + const big_uint& v, + const big_uint& w) noexcept +{ + return false; +} + template inline constexpr void complement(big_uint& u, const big_uint& v) noexcept { @@ -128,24 +137,24 @@ inline constexpr bool compile_time_assert(bool pred) noexcept template inline constexpr void from_string(big_uint& u, std::string_view s) noexcept { - ASSERT((u.size() * (sizeof(T) << 1u)) > s.length()); -// std::size_t i = 0; -// for (auto rit = std::cbegin(s); rit != std::cend(s); ++rit) { -// char c = *rit; -// T v; -// if (c >= '0' && c <= '9') { -// v = c - '0'; -// } else if (c >= 'a' && c <= 'z') { -// v = c - 'a'; -// } else if (c >= 'A' && c <= 'Z') { -// v = c - 'A'; -// } else { -// ASSERT(false); -// } -// -// u[i / u.word_hbytes] |= v << (i % u.word_hbytes * 4u); -// i++; -// } + //ASSERT((u.size() * (sizeof(T) << 1u)) > s.length()); + std::size_t i = 0; + for (auto rit = std::crbegin(s); rit != std::crend(s); ++rit) { + char c = *rit; + T v; + if (c >= '0' && c <= '9') { + v = c - '0'; + } else if (c >= 'a' && c <= 'z') { + v = c - 'a' + 10; + } else if (c >= 'A' && c <= 'Z') { + v = c - 'A' + 10; + } else { + //ASSERT(false); + } + + u[i / u.word_hbytes] |= v << ((i % u.word_hbytes) * 4u); + i++; + } } template From 3e1db608e2e2a5ebdfa5918b5010e53cbb259334 Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Wed, 21 May 2025 22:34:25 +0800 Subject: [PATCH 06/12] Under development --- src/Makefile | 48 ++++++++++++++++++ src/big_int.hpp | 90 +++++++++++++++++++++++++++++++++ src/big_uint.hpp | 50 ++++++++----------- src/detail/big_uint.hpp | 107 +++++++++++++++++++++++----------------- 4 files changed, 219 insertions(+), 76 deletions(-) create mode 100644 src/Makefile create mode 100644 src/big_int.hpp diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..e5761e9 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,48 @@ +BUILD ?= debug +TARGET := test_bigint +CXX := g++ +CXXFLAGS := -std=c++23 +LDFLAGS := +CXXFLAGS += -MMD -MP +CXXFLAGS += -fstrict-aliasing -Wstrict-aliasing \ + -Wold-style-cast +# 预处理标志 +CPPFLAGS := + +ifeq ($(BUILD), debug) +# 为了获取完整的栈回溯 +CXXFLAGS += -g -fno-omit-frame-pointer +# AddressSanitizer 是 LeakSanitizer 的超集。 +# 检测内存的 LeakSanitizer 是集成在 AddressSanitizer 中的一个相对独立的工具,它 +# 工作在检查过程的最后阶段。 +CXXFLAGS += -fsanitize=address +LDFLAGS += -static-libasan -fsanitize=address +# UBSanitizer 也变成运行时检查 +CXXFLAGS += -fsanitize=undefined +LDFLAGS += -fsanitize=undefined +else +# assert() 开关 +CXXFLAGS += -DNDEBUG +endif + +SRCS := $(wildcard *.cpp) +OBJS := $(SRCS:.cpp=.o) +ASMS := $(SRCS:.cpp=.s) +DEPS := $(OBJS:.o=.d) + +.PHONY: all clean insight + +all: $(TARGET) +$(TARGET): $(OBJS) + $(CXX) $(LDFLAGS) $^ -o $@ + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ -MF $*.d + +-include $(DEPS) + +insight: $(SRCS) + $(CXX) $(CXXFLAGS) -S -fverbose-asm $^ + +clean: + rm -rf $(TARGET) $(OBJS) $(ASMS) $(DEPS) diff --git a/src/big_int.hpp b/src/big_int.hpp new file mode 100644 index 0000000..c24a1c1 --- /dev/null +++ b/src/big_int.hpp @@ -0,0 +1,90 @@ +#pragma once + +#include "big_uint.hpp" + +#include +#include +#include +#include + +namespace big_int { + +template +struct big_int : big_uint::big_uint +{ + constexpr bool sign() const noexcept + { + return detail::big_uint::msb(*this); + } +}; + +template +constexpr big_int operator+( + const big_int& u, + const big_int& v) noexcept +{ + using bint = big_int; + using buint = big_uint::big_uint; + auto& up = static_cast(u); + auto& vp = static_cast(v); + return static_cast(up + vp); +} + +/* +template +template +inline constexpr auto big_uint::operator-( + const big_uint& u) const + -> big_uint Np) ? N : Np> +{ + auto w = big_uint Np) ? N : Np>{ 0 }; + detail::big_uint::substract(w, *this, u); + return w; +} + +template +template +inline constexpr auto big_uint::operator*( + const big_uint& u) const + -> big_uint Np) ? N : Np> +{ + auto w = big_uint Np) ? N : Np>{ 0 }; + detail::big_uint::multiply(w, *this, u); + return w; +} + +*/ +template +constexpr big_int from_string(std::string_view s) noexcept +{ + auto v = big_int{ 0 }; + bool sign = (s[0] == '-'); + detail::big_uint::from_string(v, sign ? s.substr(1) : s); + if (sign) + detail::big_uint::two_complement(v); + return v; +} +} + +template +struct std::formatter> +{ + constexpr auto parse(std::format_parse_context& context) + { + return context.begin(); + } + + auto format(const big_int::big_int& v, std::format_context& context) const + { + std::string s; + char sign = v.sign() ? '-' : '+'; + if (v.sign()) { + auto w = v; + detail::big_uint::two_complement(w); + detail::big_uint::to_string(s, w); + } else { + detail::big_uint::to_string(s, v); + } + return std::format_to(context.out(), "{}{}", sign, s); + } +}; diff --git a/src/big_uint.hpp b/src/big_uint.hpp index 80bca70..be455b6 100644 --- a/src/big_uint.hpp +++ b/src/big_uint.hpp @@ -10,35 +10,24 @@ namespace big_uint { -template -struct big_uint : detail::big_uint::big_uint { - template - constexpr auto operator+( - const big_uint& u) const - -> big_uint Np) ? N : Np>; - - template - constexpr auto operator-( - const big_uint& u) const - -> big_uint Np) ? N : Np>; - - template - constexpr auto operator*( - const big_uint& u) const - -> big_uint Np) ? N : Np>; +template +struct big_uint : detail::big_uint::big_uint +{ }; -template -template -inline constexpr auto big_uint::operator+( - const big_uint& u) const - -> big_uint Np) ? N : Np> +template +constexpr big_uint operator+( + const big_uint& u, + const big_uint& v) noexcept { - auto w = big_uint Np) ? N : Np>{ 0 }; - detail::big_uint::add(w, *this, u); + big_uint w; + detail::big_uint::add(w, u, v); return w; } + + +/* template template inline constexpr auto big_uint::operator-( @@ -61,24 +50,25 @@ inline constexpr auto big_uint::operator*( return w; } -template -inline constexpr big_uint from_string(std::string_view s) +*/ +template +constexpr big_uint from_string(std::string_view s) noexcept { - auto v = big_uint{ 0 }; + auto v = big_uint{ 0 }; detail::big_uint::from_string(v, s); return v; } - } -template -struct std::formatter> { +template +struct std::formatter> +{ constexpr auto parse(std::format_parse_context& context) { return context.begin(); } - auto format(const big_uint::big_uint& v, std::format_context& context) const + auto format(const big_uint::big_uint& v, std::format_context& context) const { std::string s; detail::big_uint::to_string(s, v); diff --git a/src/detail/big_uint.hpp b/src/detail/big_uint.hpp index 72d5a38..2431e8b 100644 --- a/src/detail/big_uint.hpp +++ b/src/detail/big_uint.hpp @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -12,52 +14,65 @@ namespace detail::big_uint { -template - requires (N > 0) -struct big_uint : std::array { - using word_type = T; - static constexpr std::size_t word_nbits = sizeof(word_type) * CHAR_BIT; - static constexpr std::size_t word_hbytes = sizeof(word_type) * 2u; - static constexpr word_type bitmask_msb = (1u << (N % word_nbits)) - 1u; +consteval std::size_t ceil(std::size_t value, std::size_t base) +{ + return (value + base - 1) / base; +} + +template +struct big_uint : std::array +{ + static constexpr std::size_t digit_nbits = sizeof(DigitType) * CHAR_BIT; + static_assert(N % digit_nbits == 0); + static constexpr std::size_t digit_nhbytes = (sizeof(DigitType) << 1u); }; -template -inline constexpr bool add( - big_uint N2) ? N1 : N2>& u, - const big_uint& v, - const big_uint& w) noexcept +template +constexpr bool msb(const big_uint& u) noexcept { - T c = 0u; - std::size_t i = 0u; - constexpr std::size_t s = v.size() < w.size() ? v.size() : w.size(); - for ( ; i < s; ++i) { - u[i] = v[i] + c; - c = u[i] < c ? 1u : 0u; - u[i] += w[i]; - if (u[i] < w[i]) { - c++; - } + constexpr unsigned pos_msb = u.digit_nbits - 1; + return (u.back() >> pos_msb & 0x1u); +} + +template +constexpr bool increment(big_uint& u) noexcept +{ + DigitType c = 1u; + for (unsigned i = 0u; i < u.size(); ++i) { + DigitType v = u[i]; + u[i] = v + c; + c = u[i] < v; } - if constexpr (N1 > N2) { - for ( ; i < v.size(); ++i) { - u[i] = v[i] + c; - c = u[i] < c ? 1u : 0u; - } - } else { - for ( ; i < w.size(); ++i) { - u[i] = w[i] + c; - c = u[i] < c ? 1u : 0u; - } + return c; +} + +template +constexpr void two_complement(big_uint& u) noexcept +{ + for (unsigned i = 0u; i < u.size(); ++i) { + u[i] = ~u[i]; } - if constexpr (u.bitmask_msb > 0) { - u.back() &= u.bitmask_msb; + increment(u); +} + +template +constexpr bool add( + big_uint& u, + const big_uint& v, + const big_uint& w) noexcept +{ + DigitType c = 0u; + for (unsigned i = 0u; i < u.size(); ++i) { + u[i] = v[i] + w[i] + c; + c = (!c && (u[i] < v[i])) || (c && (u[i] <= v[i])); } return c; } +/* template inline constexpr bool substract( big_uint N2) ? N1 : N2>& u, @@ -66,7 +81,7 @@ inline constexpr bool substract( { T b = 0u; std::size_t i = 0u; - constexpr std::size_t s = v.size() < w.size() ? v.size() : w.size(); + std::size_t s = v.size() < w.size() ? v.size() : w.size(); for ( ; i < s; ++i) { u[i] = v[i] - b; b = (u[i] > std::numeric_limits::max() - b) ? 1u : 0u; @@ -125,23 +140,23 @@ inline constexpr bool compile_time_assert(bool pred) noexcept return true; } +*/ #define ASSERT(pred) \ do { \ - if constexpr(compile_time_assert((pred))) { \ + if constexpr (std::is_constant_evaluated()) { \ static_assert((pred)); \ } else { \ assert(pred); \ } \ } while (0) -template -inline constexpr void from_string(big_uint& u, std::string_view s) noexcept +template +constexpr void from_string(big_uint& u, std::string_view s) noexcept { - //ASSERT((u.size() * (sizeof(T) << 1u)) > s.length()); - std::size_t i = 0; + unsigned i = 0; for (auto rit = std::crbegin(s); rit != std::crend(s); ++rit) { char c = *rit; - T v; + DigitType v; if (c >= '0' && c <= '9') { v = c - '0'; } else if (c >= 'a' && c <= 'z') { @@ -149,19 +164,19 @@ inline constexpr void from_string(big_uint& u, std::string_view s) noexcep } else if (c >= 'A' && c <= 'Z') { v = c - 'A' + 10; } else { - //ASSERT(false); + // how? } - u[i / u.word_hbytes] |= v << ((i % u.word_hbytes) * 4u); + u[i / u.digit_nhbytes] |= v << ((i % u.digit_nhbytes) * 4u); i++; } } -template -inline constexpr void to_string(std::string& s, const big_uint& u) +template +constexpr void to_string(std::string& s, const big_uint& u) { for (auto rit = std::crbegin(u); rit != std::crend(u); ++rit) { - s.append(std::format("{1:0>{0}x}", sizeof(T) * 2, *rit)); + s.append(std::format("{1:0>{0}x}", sizeof(DigitType) << 1u, *rit)); } } From 3fbf388b67d8720c6005fd7f0a360bc40bac52d6 Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Wed, 21 May 2025 22:39:18 +0800 Subject: [PATCH 07/12] Rename template parameter DigitType to T --- src/big_int.hpp | 28 ++++++++++++------------ src/big_uint.hpp | 26 +++++++++++------------ src/detail/big_uint.hpp | 47 +++++++++++++++++++++-------------------- 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/src/big_int.hpp b/src/big_int.hpp index c24a1c1..4fb1b29 100644 --- a/src/big_int.hpp +++ b/src/big_int.hpp @@ -9,8 +9,8 @@ namespace big_int { -template -struct big_int : big_uint::big_uint +template +struct big_int : big_uint::big_uint { constexpr bool sign() const noexcept { @@ -18,13 +18,13 @@ struct big_int : big_uint::big_uint } }; -template -constexpr big_int operator+( - const big_int& u, - const big_int& v) noexcept +template +constexpr big_int operator+( + const big_int& u, + const big_int& v) noexcept { - using bint = big_int; - using buint = big_uint::big_uint; + using bint = big_int; + using buint = big_uint::big_uint; auto& up = static_cast(u); auto& vp = static_cast(v); return static_cast(up + vp); @@ -54,10 +54,10 @@ inline constexpr auto big_uint::operator*( } */ -template -constexpr big_int from_string(std::string_view s) noexcept +template +constexpr big_int from_string(std::string_view s) noexcept { - auto v = big_int{ 0 }; + auto v = big_int{ 0 }; bool sign = (s[0] == '-'); detail::big_uint::from_string(v, sign ? s.substr(1) : s); if (sign) @@ -66,15 +66,15 @@ constexpr big_int from_string(std::string_view s) noexcept } } -template -struct std::formatter> +template +struct std::formatter> { constexpr auto parse(std::format_parse_context& context) { return context.begin(); } - auto format(const big_int::big_int& v, std::format_context& context) const + auto format(const big_int::big_int& v, std::format_context& context) const { std::string s; char sign = v.sign() ? '-' : '+'; diff --git a/src/big_uint.hpp b/src/big_uint.hpp index be455b6..890c901 100644 --- a/src/big_uint.hpp +++ b/src/big_uint.hpp @@ -10,17 +10,17 @@ namespace big_uint { -template -struct big_uint : detail::big_uint::big_uint +template +struct big_uint : detail::big_uint::big_uint { }; -template -constexpr big_uint operator+( - const big_uint& u, - const big_uint& v) noexcept +template +constexpr big_uint operator+( + const big_uint& u, + const big_uint& v) noexcept { - big_uint w; + big_uint w; detail::big_uint::add(w, u, v); return w; } @@ -51,24 +51,24 @@ inline constexpr auto big_uint::operator*( } */ -template -constexpr big_uint from_string(std::string_view s) noexcept +template +constexpr big_uint from_string(std::string_view s) noexcept { - auto v = big_uint{ 0 }; + auto v = big_uint{ 0 }; detail::big_uint::from_string(v, s); return v; } } -template -struct std::formatter> +template +struct std::formatter> { constexpr auto parse(std::format_parse_context& context) { return context.begin(); } - auto format(const big_uint::big_uint& v, std::format_context& context) const + auto format(const big_uint::big_uint& v, std::format_context& context) const { std::string s; detail::big_uint::to_string(s, v); diff --git a/src/detail/big_uint.hpp b/src/detail/big_uint.hpp index 2431e8b..70f0572 100644 --- a/src/detail/big_uint.hpp +++ b/src/detail/big_uint.hpp @@ -19,27 +19,28 @@ consteval std::size_t ceil(std::size_t value, std::size_t base) return (value + base - 1) / base; } -template -struct big_uint : std::array +template +struct big_uint : std::array { - static constexpr std::size_t digit_nbits = sizeof(DigitType) * CHAR_BIT; + using digit_type = T; + static constexpr std::size_t digit_nbits = sizeof(T) * CHAR_BIT; static_assert(N % digit_nbits == 0); - static constexpr std::size_t digit_nhbytes = (sizeof(DigitType) << 1u); + static constexpr std::size_t digit_nhbytes = (sizeof(T) << 1u); }; -template -constexpr bool msb(const big_uint& u) noexcept +template +constexpr bool msb(const big_uint& u) noexcept { constexpr unsigned pos_msb = u.digit_nbits - 1; return (u.back() >> pos_msb & 0x1u); } -template -constexpr bool increment(big_uint& u) noexcept +template +constexpr bool increment(big_uint& u) noexcept { - DigitType c = 1u; + T c = 1u; for (unsigned i = 0u; i < u.size(); ++i) { - DigitType v = u[i]; + T v = u[i]; u[i] = v + c; c = u[i] < v; } @@ -47,8 +48,8 @@ constexpr bool increment(big_uint& u) noexcept return c; } -template -constexpr void two_complement(big_uint& u) noexcept +template +constexpr void two_complement(big_uint& u) noexcept { for (unsigned i = 0u; i < u.size(); ++i) { u[i] = ~u[i]; @@ -57,13 +58,13 @@ constexpr void two_complement(big_uint& u) noexcept increment(u); } -template +template constexpr bool add( - big_uint& u, - const big_uint& v, - const big_uint& w) noexcept + big_uint& u, + const big_uint& v, + const big_uint& w) noexcept { - DigitType c = 0u; + T c = 0u; for (unsigned i = 0u; i < u.size(); ++i) { u[i] = v[i] + w[i] + c; c = (!c && (u[i] < v[i])) || (c && (u[i] <= v[i])); @@ -150,13 +151,13 @@ inline constexpr bool compile_time_assert(bool pred) noexcept } \ } while (0) -template -constexpr void from_string(big_uint& u, std::string_view s) noexcept +template +constexpr void from_string(big_uint& u, std::string_view s) noexcept { unsigned i = 0; for (auto rit = std::crbegin(s); rit != std::crend(s); ++rit) { char c = *rit; - DigitType v; + T v; if (c >= '0' && c <= '9') { v = c - '0'; } else if (c >= 'a' && c <= 'z') { @@ -172,11 +173,11 @@ constexpr void from_string(big_uint& u, std::string_view s) noexce } } -template -constexpr void to_string(std::string& s, const big_uint& u) +template +constexpr void to_string(std::string& s, const big_uint& u) { for (auto rit = std::crbegin(u); rit != std::crend(u); ++rit) { - s.append(std::format("{1:0>{0}x}", sizeof(DigitType) << 1u, *rit)); + s.append(std::format("{1:0>{0}x}", sizeof(T) << 1u, *rit)); } } From 26a419bc0351ee20543a69e6310a7ddb9821377e Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Fri, 23 May 2025 21:12:29 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20main.cpp=20=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/main.cpp diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..ca50b30 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,51 @@ +#include "big_int.hpp" +#include "big_uint.hpp" + +#include +#include +#include + +#include + +using namespace std::literals; + +int main(int argc, char *arg[]) +{ + constexpr big_int::big_int u { 5 }; + constexpr big_int::big_int v { 1 }; + constexpr auto w = u + v; + std::cout << std::format("{}", u) << std::endl; + std::cout << std::format("{}", v) << std::endl; + std::cout << std::format("{}", w) << std::endl; + constexpr auto y = big_int::from_string("-123456789abcdef123456fafafafff"sv); + constexpr auto z = big_int::from_string("-123456789abcdef123456fafafafff"sv); + constexpr auto x = y + z; + std::cout << std::format("{}", x) << std::endl; + + constexpr big_uint::big_uint uu { 5 }; + constexpr big_uint::big_uint uv { 1 }; + constexpr auto uw = uu + uv; + std::cout << std::format(" {}", uu) << std::endl; + std::cout << std::format(" {}", uv) << std::endl; + std::cout << std::format(" {}", uw) << std::endl; + constexpr auto uy = big_uint::from_string("123456789abcdef123456fafafafff"sv); + constexpr auto uz = big_uint::from_string("123456789abcdef123456fafafafff"sv); + constexpr auto ux = uy + uz; + std::cout << std::format(" {}", uy + uz) << std::endl; + constexpr auto uyy = big_uint::from_string("ffffffffffffffffffffffffffffff"sv); + constexpr auto uzz = big_uint::from_string("ffffffffffffffffffffffffffffff"sv); + constexpr auto uxx = uyy + uzz; + std::cout << std::format(" {}", uxx) << std::endl; + /* + std::cout << std::format("{} {} {} {} {:b}", u[0], u.size(), u.word_nbits, + u.word_hbytes, w.bitmask_msb) << std::endl; + std::cout << std::format("{} {}", w[0], w.size()) << std::endl; + constexpr auto x = u - v; + std::cout << std::format("{}", x) << std::endl; + constexpr auto y = v - u; + std::cout << std::format("{}", y) << std::endl; + z = z + z + z + z; + std::cout << std::format("{}", z) << std::endl; + */ + return 0; +} From 7eece5924e35cd59ff3c77ea6426652081156ef5 Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Tue, 27 May 2025 00:33:16 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E7=AE=80=E5=8C=96=E5=87=8F=E6=B3=95?= =?UTF-8?q?=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/big_int.hpp | 6 ++-- src/big_uint.hpp | 23 ++++++++------ src/detail/big_uint.hpp | 69 ++++++++++++++--------------------------- src/main.cpp | 12 +++++++ 4 files changed, 53 insertions(+), 57 deletions(-) diff --git a/src/big_int.hpp b/src/big_int.hpp index 4fb1b29..8090397 100644 --- a/src/big_int.hpp +++ b/src/big_int.hpp @@ -61,7 +61,7 @@ constexpr big_int from_string(std::string_view s) noexcept bool sign = (s[0] == '-'); detail::big_uint::from_string(v, sign ? s.substr(1) : s); if (sign) - detail::big_uint::two_complement(v); + detail::big_uint::two_complement(v, v); return v; } } @@ -79,8 +79,8 @@ struct std::formatter> std::string s; char sign = v.sign() ? '-' : '+'; if (v.sign()) { - auto w = v; - detail::big_uint::two_complement(w); + big_uint::big_uint w; + detail::big_uint::two_complement(w, v); detail::big_uint::to_string(s, w); } else { detail::big_uint::to_string(s, v); diff --git a/src/big_uint.hpp b/src/big_uint.hpp index 890c901..457f3f3 100644 --- a/src/big_uint.hpp +++ b/src/big_uint.hpp @@ -25,20 +25,25 @@ constexpr big_uint operator+( return w; } - - -/* template -template -inline constexpr auto big_uint::operator-( - const big_uint& u) const - -> big_uint Np) ? N : Np> +constexpr big_uint operator-( + const big_uint& u, + const big_uint& v) noexcept { - auto w = big_uint Np) ? N : Np>{ 0 }; - detail::big_uint::substract(w, *this, u); + big_uint w; + detail::big_uint::substract(w, u, v); return w; } +template +constexpr big_uint two_complement(const big_uint& u) noexcept +{ + big_uint v; + detail::big_uint::two_complement(v, u); + return v; +} + +/* template template inline constexpr auto big_uint::operator*( diff --git a/src/detail/big_uint.hpp b/src/detail/big_uint.hpp index 70f0572..1a31f56 100644 --- a/src/detail/big_uint.hpp +++ b/src/detail/big_uint.hpp @@ -36,26 +36,31 @@ constexpr bool msb(const big_uint& u) noexcept } template -constexpr bool increment(big_uint& u) noexcept +constexpr bool add_digit( + big_uint& u, + const big_uint& v, + T w) noexcept { - T c = 1u; - for (unsigned i = 0u; i < u.size(); ++i) { - T v = u[i]; - u[i] = v + c; - c = u[i] < v; + T c = w; + for (unsigned i = 0u; i < v.size() && c > 0; ++i) { + T temp = v[i]; + u[i] = temp + c; + c = u[i] < temp; } return c; } template -constexpr void two_complement(big_uint& u) noexcept +constexpr void two_complement( + big_uint& u, + const big_uint& v) noexcept { - for (unsigned i = 0u; i < u.size(); ++i) { - u[i] = ~u[i]; + for (unsigned i = 0u; i < v.size(); ++i) { + u[i] = ~v[i]; } - increment(u); + add_digit(u, u, 1u); } template @@ -73,48 +78,22 @@ constexpr bool add( return c; } -/* -template -inline constexpr bool substract( - big_uint N2) ? N1 : N2>& u, - const big_uint& v, - const big_uint& w) noexcept +template +constexpr bool substract( + big_uint& u, + const big_uint& v, + const big_uint& w) noexcept { T b = 0u; - std::size_t i = 0u; - std::size_t s = v.size() < w.size() ? v.size() : w.size(); - for ( ; i < s; ++i) { - u[i] = v[i] - b; - b = (u[i] > std::numeric_limits::max() - b) ? 1u : 0u; - u[i] -= w[i]; - if (u[i] > std::numeric_limits::max() - w[i]) { - b++; - } - } - - if constexpr (v.size() > w.size()) { - for ( ; i < v.size(); ++i) { - u[i] = v[i] - b; - b = (u[i] > std::numeric_limits::max() - b) ? 1u : 0u; - } - } else { - for ( ; i < w.size(); ++i) { - u[i] = - b; - b = (u[i] > std::numeric_limits::max() - b) ? 1u : 0u; - u[i] -= w[i]; - if (u[i] > std::numeric_limits::max() - w[i]) { - b++; - } - } - } - - if constexpr (u.bitmask_msb > 0) { - u.back() &= u.bitmask_msb; + for (unsigned i = 0u ; i < v.size(); ++i) { + u[i] = v[i] - w[i] - b; + b = (!b && u[i] > v[i]) || (b && u[i] >= v[i]); } return b; } +/* template inline constexpr bool multiply( big_uint N2) ? N1 : N2>& u, diff --git a/src/main.cpp b/src/main.cpp index ca50b30..3c2ae3e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,18 @@ int main(int argc, char *arg[]) constexpr auto uzz = big_uint::from_string("ffffffffffffffffffffffffffffff"sv); constexpr auto uxx = uyy + uzz; std::cout << std::format(" {}", uxx) << std::endl; + + std::cout << "==" << std::endl; + constexpr auto a = big_uint::from_string("86f6050d979544fe39e7142446a40b3"sv); + constexpr auto b = big_uint::from_string("ab5a0c4d00312f392c0edc2878d6d8a"sv); + constexpr auto c = b - a; + constexpr auto d = a - b; + constexpr auto e = big_uint::two_complement(d); + std::cout << std::format(" {}", a) << std::endl; + std::cout << std::format(" {}", b) << std::endl; + std::cout << std::format(" {}", c) << std::endl; + std::cout << std::format(" {}", d) << std::endl; + std::cout << std::format(" {}", e) << std::endl; /* std::cout << std::format("{} {} {} {} {:b}", u[0], u.size(), u.word_nbits, u.word_hbytes, w.bitmask_msb) << std::endl; From b561732e61853cdcfc9cc26139b3bd6b3a4ff79e Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Fri, 30 May 2025 16:15:34 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B9=98=E6=B3=95?= =?UTF-8?q?=E8=BF=90=E7=AE=97=E5=92=8C=E5=87=8F=E6=B3=95=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/big_int.hpp | 12 ++++++++++ src/big_uint.hpp | 13 +++++------ src/detail/big_uint.hpp | 50 +++++++++++++++++++++++++++++++++++------ src/main.cpp | 48 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/big_int.hpp b/src/big_int.hpp index 8090397..8c96138 100644 --- a/src/big_int.hpp +++ b/src/big_int.hpp @@ -30,6 +30,18 @@ constexpr big_int operator+( return static_cast(up + vp); } +template +constexpr big_int operator-( + const big_int& u, + const big_int& v) noexcept +{ + using bint = big_int; + using buint = big_uint::big_uint; + auto& up = static_cast(u); + auto& vp = static_cast(v); + return static_cast(up - vp); +} + /* template template diff --git a/src/big_uint.hpp b/src/big_uint.hpp index 457f3f3..6add9bc 100644 --- a/src/big_uint.hpp +++ b/src/big_uint.hpp @@ -43,18 +43,17 @@ constexpr big_uint two_complement(const big_uint& u) noexcept return v; } -/* template -template -inline constexpr auto big_uint::operator*( - const big_uint& u) const - -> big_uint Np) ? N : Np> +constexpr big_uint operator*( + const big_uint& u, + const big_uint& v) noexcept { - auto w = big_uint Np) ? N : Np>{ 0 }; - detail::big_uint::multiply(w, *this, u); + auto w = big_uint{ 0 }; + detail::big_uint::multiply(w, u, v); return w; } +/* */ template constexpr big_uint from_string(std::string_view s) noexcept diff --git a/src/detail/big_uint.hpp b/src/detail/big_uint.hpp index 1a31f56..66108e8 100644 --- a/src/detail/big_uint.hpp +++ b/src/detail/big_uint.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -93,16 +94,51 @@ constexpr bool substract( return b; } -/* -template -inline constexpr bool multiply( - big_uint N2) ? N1 : N2>& u, - const big_uint& v, - const big_uint& w) noexcept +template +concept digit_promotable = std::unsigned_integral + && (std::same_as || std::same_as + || std::same_as || std::same_as); + +template +struct large_digit_from_digit; + +#define DEFINE_LARGE_DIGIT_FROM_DIGIT(digit, large_digit) \ + template<> \ + struct large_digit_from_digit \ + { \ + using type = large_digit; \ + } + +DEFINE_LARGE_DIGIT_FROM_DIGIT(std::uint8_t, std::uint16_t); +DEFINE_LARGE_DIGIT_FROM_DIGIT(std::uint16_t, std::uint32_t); +DEFINE_LARGE_DIGIT_FROM_DIGIT(std::uint32_t, std::uint64_t); +DEFINE_LARGE_DIGIT_FROM_DIGIT(std::uint64_t, unsigned __int128); + +template::type> +constexpr LargeDigit digit_multiply(Digit a, Digit b) noexcept +{ + return static_cast(a) * b; +} + +template +constexpr void multiply( + big_uint& u, + const big_uint& v, + const big_uint& w) noexcept { - return false; + for (unsigned i = 0; i < std::size(v); ++i) { + T c = 0u; + for (unsigned j = 0, k = i; j < std::size(w) && k < std::size(u); ++j, ++k) { + auto r = digit_multiply(v[i], w[j]); + r = r + u[k] + c; + u[k] = std::numeric_limits::max() & r; + c = std::numeric_limits::max() & (r >> (sizeof(T) << 3)); + } + } } +/* template inline constexpr void complement(big_uint& u, const big_uint& v) noexcept { diff --git a/src/main.cpp b/src/main.cpp index 3c2ae3e..dba60e7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,6 +48,54 @@ int main(int argc, char *arg[]) std::cout << std::format(" {}", c) << std::endl; std::cout << std::format(" {}", d) << std::endl; std::cout << std::format(" {}", e) << std::endl; + + std::cout << "==" << std::endl; + constexpr auto ap = big_uint::from_string("0"sv); + constexpr auto bp = big_uint::from_string("0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f"sv); + constexpr auto cp = bp - ap; + constexpr auto dp = ap - bp; + constexpr auto ep = big_uint::two_complement(dp); + std::cout << std::format(" {}", ap) << std::endl; + std::cout << std::format(" {}", bp) << std::endl; + std::cout << std::format(" {}", cp) << std::endl; + std::cout << std::format(" {}", dp) << std::endl; + std::cout << std::format(" {}", ep) << std::endl; + + std::cout << "==" << std::endl; + constexpr auto k = big_uint::from_string("0645d91e97ca853ad4fa29c"sv); + constexpr auto l = big_uint::from_string("33b2e3c9fd0803ce7ffffff"sv); + constexpr auto ik = big_int::from_string("0645d91e97ca853ad4fa29c"sv); + constexpr auto il = big_int::from_string("33b2e3c9fd0803ce7ffffff"sv); + constexpr auto kl = k - l; + constexpr auto lk = l - k; + constexpr auto klp = big_uint::two_complement(kl); + constexpr auto ikl = ik - il; + constexpr auto ilk = il - ik; + constexpr auto iklp = big_uint::two_complement(ikl); + std::cout << std::format(" {}", k) << std::endl; + std::cout << std::format(" {}", l) << std::endl; + std::cout << std::format(" {}", kl) << std::endl; + std::cout << std::format(" {}", lk) << std::endl; + std::cout << std::format(" {}", klp) << std::endl; + std::cout << "----" << std::endl; + std::cout << std::format(" {}", ik) << std::endl; + std::cout << std::format(" {}", il) << std::endl; + std::cout << std::format(" {}", ikl) << std::endl; + std::cout << std::format(" {}", ilk) << std::endl; + std::cout << std::format(" {}", iklp) << std::endl; + + std::cout << "==" << std::endl; + constexpr auto s = big_uint::from_string("5e4b9f99b2b05d64"sv); + constexpr auto t = big_uint::from_string("33b2e3c9fd0803ce"sv); + constexpr auto sp = big_uint::from_string("0645d91e97ca853ad4fa29c"sv); + constexpr auto tp = big_uint::from_string("33b2e3c9fd0803ce7ffffff"sv); + constexpr auto sxt = s * t; + constexpr auto kxl = k * l; + constexpr auto spxtp = sp * tp; + std::cout << std::format(" {}", sxt) << std::endl; + std::cout << std::format(" {}", kxl) << std::endl; + std::cout << std::format(" {}", spxtp) << std::endl; + /* std::cout << std::format("{} {} {} {} {:b}", u[0], u.size(), u.word_nbits, u.word_hbytes, w.bitmask_msb) << std::endl; From f228b95cae45a5dedfd62583e37e4ba8ebc0f67c Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Fri, 30 May 2025 17:41:58 +0800 Subject: [PATCH 11/12] Adding `large_digit` template --- src/detail/big_uint.hpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/detail/big_uint.hpp b/src/detail/big_uint.hpp index 66108e8..69475f8 100644 --- a/src/detail/big_uint.hpp +++ b/src/detail/big_uint.hpp @@ -114,11 +114,13 @@ DEFINE_LARGE_DIGIT_FROM_DIGIT(std::uint16_t, std::uint32_t); DEFINE_LARGE_DIGIT_FROM_DIGIT(std::uint32_t, std::uint64_t); DEFINE_LARGE_DIGIT_FROM_DIGIT(std::uint64_t, unsigned __int128); -template::type> -constexpr LargeDigit digit_multiply(Digit a, Digit b) noexcept +template +using large_digit = large_digit_from_digit::type; + +template +constexpr large_digit digit_multiply(T a, T b) noexcept { - return static_cast(a) * b; + return static_cast>(a) * b; } template @@ -130,7 +132,7 @@ constexpr void multiply( for (unsigned i = 0; i < std::size(v); ++i) { T c = 0u; for (unsigned j = 0, k = i; j < std::size(w) && k < std::size(u); ++j, ++k) { - auto r = digit_multiply(v[i], w[j]); + large_digit r = digit_multiply(v[i], w[j]); r = r + u[k] + c; u[k] = std::numeric_limits::max() & r; c = std::numeric_limits::max() & (r >> (sizeof(T) << 3)); From ebec601f5fa67d5c76afca8254489fc42d70277a Mon Sep 17 00:00:00 2001 From: ohyusheng Date: Fri, 30 May 2025 17:54:22 +0800 Subject: [PATCH 12/12] Add constexpr variable `digit_mask` --- src/detail/big_uint.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/detail/big_uint.hpp b/src/detail/big_uint.hpp index 69475f8..907028b 100644 --- a/src/detail/big_uint.hpp +++ b/src/detail/big_uint.hpp @@ -27,6 +27,7 @@ struct big_uint : std::array static constexpr std::size_t digit_nbits = sizeof(T) * CHAR_BIT; static_assert(N % digit_nbits == 0); static constexpr std::size_t digit_nhbytes = (sizeof(T) << 1u); + static constexpr T digit_mask = static_cast(-1); }; template @@ -129,13 +130,14 @@ constexpr void multiply( const big_uint& v, const big_uint& w) noexcept { - for (unsigned i = 0; i < std::size(v); ++i) { + std::size_t size = u.size(); + for (unsigned i = 0; i < size; ++i) { T c = 0u; - for (unsigned j = 0, k = i; j < std::size(w) && k < std::size(u); ++j, ++k) { + for (unsigned j = 0, k = i; j < size && k < size; ++j, ++k) { large_digit r = digit_multiply(v[i], w[j]); r = r + u[k] + c; - u[k] = std::numeric_limits::max() & r; - c = std::numeric_limits::max() & (r >> (sizeof(T) << 3)); + u[k] = u.digit_mask & r; + c = u.digit_mask & (r >> u.digit_nbits); } } }