diff --git a/spec/std/big/big_int_spec.cr b/spec/std/big/big_int_spec.cr index 8a86939efbac..68eba643a571 100644 --- a/spec/std/big/big_int_spec.cr +++ b/spec/std/big/big_int_spec.cr @@ -283,6 +283,34 @@ describe "BigInt" do -5.to_big_i.remainder(-3).should eq(-2) end + it "#bit" do + x = 123.to_big_i + x.bit(-10.to_big_i ** 99).should eq(0) + x.bit(-(2.to_big_i ** 64)).should eq(0) + x.bit(-1).should eq(0) + x.bit(0).should eq(1) + x.bit(2).should eq(0) + x.bit(3).should eq(1) + x.bit(6).should eq(1) + x.bit(7).should eq(0) + x.bit(64).should eq(0) + x.bit(2.to_big_i ** 64).should eq(0) + x.bit(10.to_big_i ** 99).should eq(0) + + x = ~(123.to_big_i) + x.bit(-10.to_big_i ** 99).should eq(0) + x.bit(-(2.to_big_i ** 64)).should eq(0) + x.bit(-1).should eq(0) + x.bit(0).should eq(0) + x.bit(2).should eq(1) + x.bit(3).should eq(0) + x.bit(6).should eq(0) + x.bit(7).should eq(1) + x.bit(64).should eq(1) + x.bit(2.to_big_i ** 64).should eq(1) + x.bit(10.to_big_i ** 99).should eq(1) + end + it "does bitwise and" do (123.to_big_i & 321).should eq(65) (BigInt.new("96238761238973286532") & 86325735648).should eq(69124358272) diff --git a/src/big/big_int.cr b/src/big/big_int.cr index decf7a0828ff..ad92a1e2cd39 100644 --- a/src/big/big_int.cr +++ b/src/big/big_int.cr @@ -385,6 +385,12 @@ struct BigInt < Int BigInt.new { |mpz| LibGMP.com(mpz, self) } end + def bit(bit : Int) + return 0 if bit < 0 + return self < 0 ? 1 : 0 if bit > LibGMP::BitcntT::MAX + LibGMP.tstbit(self, LibGMP::BitcntT.new!(bit)) + end + def &(other : Int) : BigInt BigInt.new { |mpz| LibGMP.and(mpz, self, other.to_big_i) } end diff --git a/src/big/lib_gmp.cr b/src/big/lib_gmp.cr index 9caf408f1494..3cae0de64b77 100644 --- a/src/big/lib_gmp.cr +++ b/src/big/lib_gmp.cr @@ -116,6 +116,8 @@ lib LibGMP fun xor = __gmpz_xor(rop : MPZ*, op1 : MPZ*, op2 : MPZ*) fun com = __gmpz_com(rop : MPZ*, op : MPZ*) + fun tstbit = __gmpz_tstbit(op : MPZ*, bit_index : BitcntT) : Int + fun fdiv_q_2exp = __gmpz_fdiv_q_2exp(q : MPZ*, n : MPZ*, b : BitcntT) fun mul_2exp = __gmpz_mul_2exp(rop : MPZ*, op1 : MPZ*, op2 : BitcntT)