Skip to content

Commit

Permalink
Merge pull request #2362 from natalie-lang/bigint-fixnum
Browse files Browse the repository at this point in the history
  • Loading branch information
seven1m authored Dec 2, 2024
2 parents a1de4cc + d0455fc commit 1150a89
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 8 deletions.
2 changes: 1 addition & 1 deletion include/natalie/bigint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ struct BigInt {
return strtol(buf, nullptr, 10);
}

long to_long_long() const {
long long to_long_long() const {
char buf[32];
bigint_write(buf, 32, data);
return strtoll(buf, nullptr, 10);
Expand Down
39 changes: 32 additions & 7 deletions src/integer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ Integer::Integer(double other) {
}
}

Integer::Integer(const TM::String &other)
: m_bignum(new BigInt(other))
, m_is_fixnum(false) {
Integer::Integer(const TM::String &other) {
auto bigint = BigInt(other);
if (bigint >= NAT_MIN_FIXNUM && bigint <= NAT_MAX_FIXNUM) {
m_is_fixnum = true;
m_fixnum = bigint.to_long_long();
} else {
m_is_fixnum = false;
m_bignum = new BigInt(bigint);
}
}

Integer::Integer(const BigInt &other) {
Expand Down Expand Up @@ -251,9 +257,20 @@ Integer &Integer::operator--() {
}

bool Integer::operator<(const Integer &other) const {
if (is_bignum() || other.is_bignum()) {
return to_bigint() < other.to_bigint();
if (is_bignum()) {
if (other.is_bignum())
return *m_bignum < *other.m_bignum;
else if (m_bignum->is_negative())
return true;
else
return false;
} else if (other.is_bignum()) {
if (other.is_negative())
return false;
else
return true;
}

return m_fixnum < other.m_fixnum;
}

Expand All @@ -270,8 +287,14 @@ bool Integer::operator>=(const Integer &other) const {
}

bool Integer::operator==(const Integer &other) const {
if (is_bignum() || other.is_bignum())
return to_bigint() == other.to_bigint();
if (is_bignum()) {
if (other.is_bignum())
return *m_bignum == *other.m_bignum;
else
return false;
} else if (other.is_bignum()) {
return false;
}

return m_fixnum == other.m_fixnum;
}
Expand Down Expand Up @@ -307,12 +330,14 @@ bool Integer::operator>=(const double &other) const {
bool Integer::operator==(const double &other) const {
if (is_bignum())
return to_bigint() == other;

return to_double() == other;
}

bool Integer::operator!=(const double &other) const {
if (is_bignum())
return to_bigint() != other;

return to_double() != other;
}

Expand Down
37 changes: 37 additions & 0 deletions test/natalie/integer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,20 @@
(1 == Rational(1, 2)).should == false
(1 == Rational(1, 1)).should == true
end

it 'handles bignums correctly' do
(1 == bignum_value).should == false
(0 == bignum_value).should == false
(-1 == bignum_value).should == false

(bignum_value == 1).should == false
(bignum_value == 0).should == false
(bignum_value == -1).should == false

(bignum_value == bignum_value).should == true
(-bignum_value == -bignum_value).should == true
(-bignum_value == bignum_value - 1).should == false
end
end

describe 'eql?' do
Expand Down Expand Up @@ -196,6 +210,29 @@
(1 < Rational(1, 2)).should == false
(1 < Rational(1, 1)).should == false
end

it 'handles bignums correctly' do
(1 < bignum_value).should == true
(0 < bignum_value).should == true
(-1 < bignum_value).should == true

(1 < -bignum_value).should == false
(0 < -bignum_value).should == false
(-1 < -bignum_value).should == false

(bignum_value < 1).should == false
(bignum_value < 0).should == false
(bignum_value < -1).should == false

(-bignum_value < 1).should == true
(-bignum_value < 0).should == true
(-bignum_value < -1).should == true

(-bignum_value < bignum_value).should == true
(bignum_value < -bignum_value).should == false
(bignum_value < bignum_value - 1).should == false
(bignum_value - 1 < bignum_value).should == true
end
end

describe '<=' do
Expand Down

0 comments on commit 1150a89

Please sign in to comment.