Last active
January 16, 2017 13:22
-
-
Save asterite/7eba3e4af44bd3edc9bc61b8118f2e1f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "big_int" | |
require "benchmark" | |
lib LibGMP | |
fun sizeinbase = __gmpz_sizeinbase(op : MPZ*, base : Int32) : Int32 | |
fun export = __gmpz_export(rop : Void*, countp : Int32*, order : Int32, size : Int32, endian : Int32, nails : Int32, op : MPZ*) : UInt8* | |
end | |
struct BigInt | |
def size | |
LibGMP.sizeinbase(self, 256) | |
end | |
def bytes(format : IO::ByteFormat = IO::ByteFormat::SystemEndian) : Slice(UInt8) | |
e = format == IO::ByteFormat::BigEndian ? 1 : -1 | |
Slice(UInt8).new(size).tap { |s| LibGMP.export s, nil, e, 1, 1, 0, self } | |
end | |
end | |
def to_hex_bytes_original(hex_str) | |
bytes = Bytes.new(hex_str.size / 2) | |
(0..hex_str.size - 2).step(2).with_index do |pos, i| | |
bytes[i] = hex_str[pos, 2].to_i(16).to_u8 | |
end | |
bytes | |
end | |
def to_hex_bytes(string) | |
Bytes.new(string.bytesize / 2) do |i| | |
((string.to_slice[i*2].chr.to_i(16)) * 16 + | |
string.to_slice[i*2 + 1].chr.to_i(16)).to_u8 | |
end | |
end | |
def from_base_16(value) | |
if '0' <= value <= '9' | |
(value - '0').to_u8 | |
elsif 'A' <= value <= 'F' | |
10_u8 + (value - 'A') | |
elsif 'a' <= value <= 'f' | |
10_u8 + (value - 'a') | |
else | |
raise "Not an hex digit!" | |
end | |
end | |
def to_hex_bytes_improved(string) | |
Bytes.new(string.bytesize / 2) do |i| | |
from_base_16(string.to_slice[i*2].chr)*16 + | |
from_base_16(string.to_slice[i*2 + 1].chr) | |
end | |
end | |
def to_hex_bytes_big_int(string) | |
BigInt.new(string, 16).bytes(IO::ByteFormat::BigEndian) | |
end | |
string = "1F877C" * 100 | |
bytes1 = to_hex_bytes_original(string) | |
bytes2 = to_hex_bytes(string) | |
bytes3 = to_hex_bytes_big_int(string) | |
bytes4 = to_hex_bytes_improved(string) | |
unless bytes1 == bytes2 == bytes3 == bytes4 | |
abort "Bug in one implementation" | |
end | |
Benchmark.ips do |x| | |
x.report("original") do | |
to_hex_bytes_original(string) | |
end | |
x.report("big_int") do | |
to_hex_bytes_big_int(string) | |
end | |
x.report("normal") do | |
to_hex_bytes(string) | |
end | |
x.report("improved") do | |
to_hex_bytes_improved(string) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
original 46.3k ( 21.6µs) (± 2.24%) 21.10× slower | |
big_int 249.98k ( 4.0µs) (± 2.33%) 3.91× slower | |
normal 363.38k ( 2.75µs) (± 2.73%) 2.69× slower | |
improved 976.77k ( 1.02µs) (± 2.46%) fastest |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment