From 64dc65dd54c2c572781baed7259684e1f97f5c90 Mon Sep 17 00:00:00 2001 From: Vaivaswatha Nagaraj Date: Mon, 10 Feb 2020 21:43:17 +0530 Subject: [PATCH 1/3] Add support for negative numbers in string conversion --- src/wideint.h | 42 +++++++++++++++++++++++++++++------------- tests/test_wideint.cc | 9 +++++++++ 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/wideint.h b/src/wideint.h index a5199ba..4cb3fe2 100644 --- a/src/wideint.h +++ b/src/wideint.h @@ -299,7 +299,7 @@ struct wideint } /*! bitwise not */ - wideint& op_not() const + wideint& op_not() { for (size_t i = 0; i < lc; i++) { limbs[i] = ~limbs[i] & limb_mask(i); @@ -308,7 +308,7 @@ struct wideint } /*! negate */ - wideint& op_neg() const + wideint& op_neg() { for (size_t i = 0; i < lc; i++) { limbs[i] = ~limbs[i] & limb_mask(i); @@ -641,15 +641,19 @@ struct wideint case 10: { if (*this == 0) return "0"; - std::string s; + std::string s, sign_str; wideint v = *this, t = 10, q, r; + if (sign_bit()) { + sign_str = "-"; + v.op_neg(); + } do { op_divrem(v, t, q, r); s.push_back('0' + char(r.limbs[0])); v = q; } while (v != 0); - return std::string(s.rbegin(), s.rend());; + return sign_str + std::string(s.rbegin(), s.rend());; } case 2: { if (*this == 0) return "0b0"; @@ -702,15 +706,24 @@ struct wideint { static const wideint tenp18{0xde0b6b3a7640000ull}; static const wideint twop64{0,1}; - if (len > 2) { - if (strncmp(str, "0b", 2) == 0) { - radix = 2; - str += 2; - len -= 2; - } else if (strncmp(str, "0x", 2) == 0) { - radix = 16; - str += 2; - len -= 2; + bool isneg = false; + + if (len > 1) { + if (strncmp(str, "-", 1) == 0) { + radix = 10; + str += 1; + len -= 1; + isneg = true; + } else if (len > 2) { + if (strncmp(str, "0b", 2) == 0) { + radix = 2; + str += 2; + len -= 2; + } else if (strncmp(str, "0x", 2) == 0) { + radix = 16; + str += 2; + len -= 2; + } } } if (radix == 0) { @@ -729,6 +742,9 @@ struct wideint } *this += wideint{ulimb_t(num)}; } + if (isneg) { + this->op_neg(); + } break; } case 2: { diff --git a/tests/test_wideint.cc b/tests/test_wideint.cc index 0ecc707..11a5268 100644 --- a/tests/test_wideint.cc +++ b/tests/test_wideint.cc @@ -198,6 +198,15 @@ void test_string() assert(int256_t("0xff") == 0xff); assert(int256_t("0x807060504030201") == (int256_t{0x0807060504030201ull})); assert(int256_t("0x100f0e0d0c0b0a090807060504030201") == (int256_t{0x0807060504030201ull,0x100f0e0d0c0b0a09ull})); + assert(int256_t("-1") == int256_t("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); + assert(int256_t("-1").to_string() == "-1"); + assert(int256_t("0").to_string() == "0"); + // int256_t max value + assert(int256_t("57896044618658097711785492504343953926634992332820282019728792003956564819967").to_string() == + "57896044618658097711785492504343953926634992332820282019728792003956564819967"); + // int256_t min value. + assert(int256_t("-57896044618658097711785492504343953926634992332820282019728792003956564819968").to_string() == + "-57896044618658097711785492504343953926634992332820282019728792003956564819968"); } int main(int argc, char const *argv[]) From d947039f18b1991d4a3b054091459c51ee51b09b Mon Sep 17 00:00:00 2001 From: Vaivaswatha N Date: Sat, 25 Apr 2020 11:07:03 +0530 Subject: [PATCH 2/3] Add explicit default assignment operator --- src/wideint.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wideint.h b/src/wideint.h index 4cb3fe2..5369c23 100644 --- a/src/wideint.h +++ b/src/wideint.h @@ -83,6 +83,8 @@ struct wideint /*! signed copy constructor */ inline wideint(const wideint &o) : limbs(o.limbs) {}; + inline wideint& operator=(const wideint &rhs) = default; + /*! different size copy constructor */ template inline wideint(const wideint &o) From 7faa4421957413acd738976a8980a1721fab3c2b Mon Sep 17 00:00:00 2001 From: Vaivaswatha Nagaraj Date: Tue, 19 Jan 2021 15:19:04 +0530 Subject: [PATCH 3/3] Provide max and min values for wideint --- src/wideint.h | 31 +++++++++++++++++++++++++++++++ tests/test_wideint.cc | 16 ++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/wideint.h b/src/wideint.h index 4cb3fe2..0426d4a 100644 --- a/src/wideint.h +++ b/src/wideint.h @@ -83,6 +83,8 @@ struct wideint /*! signed copy constructor */ inline wideint(const wideint &o) : limbs(o.limbs) {}; + inline wideint& operator=(const wideint &rhs) = default; + /*! different size copy constructor */ template inline wideint(const wideint &o) @@ -181,6 +183,35 @@ struct wideint return is_signed && bits > 0 ? test_bit(bits - 1) : 0; } + static constexpr wideint one() + { + wideint m; // 0 + m.set_bit(0); + return m; + } + + static constexpr wideint min() + { + if (is_signed) { + wideint m; // 0 + m.set_bit(bits - 1); // min + return m; + } else { + return wideint(); // 0 + } + } + + static constexpr wideint max() + { + if (is_signed) { + wideint m = min(); + return m - one(); + } else { + wideint m; // 0 + m.op_not(); // all 1s + return m; + } + } /*---------------------------------------------. | add, subtract, shifts and logical operators. | diff --git a/tests/test_wideint.cc b/tests/test_wideint.cc index 11a5268..011a410 100644 --- a/tests/test_wideint.cc +++ b/tests/test_wideint.cc @@ -202,11 +202,19 @@ void test_string() assert(int256_t("-1").to_string() == "-1"); assert(int256_t("0").to_string() == "0"); // int256_t max value - assert(int256_t("57896044618658097711785492504343953926634992332820282019728792003956564819967").to_string() == - "57896044618658097711785492504343953926634992332820282019728792003956564819967"); + std::string int256_max_s = "57896044618658097711785492504343953926634992332820282019728792003956564819967"; + assert(int256_t(int256_max_s).to_string() == int256_max_s); + assert(int256_t::max() == int256_t(int256_max_s)); + // int256_t min value. - assert(int256_t("-57896044618658097711785492504343953926634992332820282019728792003956564819968").to_string() == - "-57896044618658097711785492504343953926634992332820282019728792003956564819968"); + std::string int256_min_s = "-57896044618658097711785492504343953926634992332820282019728792003956564819968"; + assert(int256_t(int256_min_s).to_string() == int256_min_s); + assert(int256_t::min() == int256_t(int256_min_s)); + + std::string uint256_max_s = "115792089237316195423570985008687907853269984665640564039457584007913129639935"; + assert(uint256_t::max() == uint256_t(uint256_max_s)); + std::string uint256_min_s = "0"; + assert(uint256_t::min() == uint256_t(uint256_min_s)); } int main(int argc, char const *argv[])