Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for negative numbers in string conversion #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 60 additions & 13 deletions src/wideint.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ struct wideint
/*! signed copy constructor */
inline wideint(const wideint<bits,true,limb_bits> &o) : limbs(o.limbs) {};

inline wideint& operator=(const wideint &rhs) = default;

/*! different size copy constructor */
template <size_t o_bits, bool o_signed, size_t o_limb_bits>
inline wideint(const wideint<o_bits,o_signed,o_limb_bits> &o)
Expand Down Expand Up @@ -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. |
Expand Down Expand Up @@ -299,7 +330,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);
Expand All @@ -308,7 +339,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);
Expand Down Expand Up @@ -641,15 +672,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";
Expand Down Expand Up @@ -702,15 +737,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) {
Expand All @@ -729,6 +773,9 @@ struct wideint
}
*this += wideint{ulimb_t(num)};
}
if (isneg) {
this->op_neg();
}
break;
}
case 2: {
Expand Down
17 changes: 17 additions & 0 deletions tests/test_wideint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,23 @@ 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
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.
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[])
Expand Down