├── .gitignore ├── benchmark_fibonacci.rb ├── benchmark_table.rb ├── benchmark_tarai.rb ├── Makefile ├── ruby_example.rb └── extension_with_crystal.cr /.gitignore: -------------------------------------------------------------------------------- 1 | *.bundle 2 | *.o 3 | bc_flags 4 | -------------------------------------------------------------------------------- /benchmark_fibonacci.rb: -------------------------------------------------------------------------------- 1 | require 'benchmark' 2 | require_relative 'ruby_example' 3 | require_relative 'extension_with_crystal' 4 | 5 | Benchmark.bm 18 do |r| 6 | r.report "fibonacci (ruby)" do 7 | fibonacci(40) 8 | end 9 | r.report "fibonacci (crystal)" do 10 | fibonacci_cr(40) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /benchmark_table.rb: -------------------------------------------------------------------------------- 1 | require 'benchmark' 2 | require_relative 'ruby_example' 3 | require_relative 'extension_with_crystal' 4 | 5 | Benchmark.bm 16 do |r| 6 | r.report "table (ruby)" do 7 | Table.new.generate("woot", 100, 500) 8 | end 9 | r.report "table (crystal)" do 10 | TableCr.new.generate("woot", 100, 500) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /benchmark_tarai.rb: -------------------------------------------------------------------------------- 1 | require 'benchmark' 2 | require_relative 'ruby_example' 3 | require_relative 'extension_with_crystal' 4 | 5 | Benchmark.bm 16 do |r| 6 | r.report "tarai (ruby)" do 7 | Takeuchi.tarai(15, 5, 1) 8 | end 9 | r.report "tarai (crystal)" do 10 | TakeuchiCr.tarai(15, 5, 1) 11 | end 12 | end 13 | 14 | # 356,426,301 times function call 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CRYSTAL = crystal 2 | UNAME = "$(shell uname -ms)" 3 | LIBS = -levent -lpcl -lpcre -lgc -lpthread 4 | LDFLAGS = -Wl,-undefined,dynamic_lookup 5 | 6 | TARGET = extension_with_crystal.bundle 7 | 8 | $(TARGET): extension_with_crystal.o 9 | $(CC) -bundle -o $@ $^ $(LIBS) $(LDFLAGS) 10 | 11 | extension_with_crystal.o: extension_with_crystal.cr 12 | $(CRYSTAL) build --release --cross-compile $(UNAME) $< 13 | 14 | .PHONY: clean 15 | clean: 16 | rm -f bc_flags 17 | rm -f extension_with_crystal.o 18 | rm -f $(TARGET) 19 | -------------------------------------------------------------------------------- /ruby_example.rb: -------------------------------------------------------------------------------- 1 | def fibonacci(n) 2 | return n if n <= 1 3 | fibonacci(n - 1) + fibonacci(n - 2) 4 | end 5 | 6 | class Takeuchi 7 | def self.tarai(x, y, z) 8 | if y < x 9 | tarai( 10 | tarai(x - 1, y, z), 11 | tarai(y - 1, z, x), 12 | tarai(z - 1, x, y) 13 | ) 14 | else 15 | y 16 | end 17 | end 18 | end 19 | 20 | class Table 21 | def generate(value, col, row) 22 | table = "" 23 | 24 | row.times do |row_i| 25 | table += "\n " 26 | col.times { |col_i| table += "\n " } 27 | table += "\n " 28 | end 29 | 30 | table += "\n
(#{col_i}) #{value}
" 31 | end 32 | end 33 | 34 | ### # -*- frozen_string_literal: true -*- 35 | -------------------------------------------------------------------------------- /extension_with_crystal.cr: -------------------------------------------------------------------------------- 1 | lib LibRuby 2 | type VALUE = Void* 3 | 4 | $rb_cObject : VALUE 5 | 6 | fun rb_define_global_function(name : UInt8*, func : VALUE, VALUE -> VALUE, argc : Int32) 7 | fun rb_define_class(name : UInt8*, super : VALUE) : VALUE 8 | fun rb_define_method(klass : VALUE, name : UInt8*, func : VALUE, VALUE, VALUE, VALUE -> VALUE, argc : Int32) 9 | fun rb_define_module_function(klass : VALUE, name : UInt8*, func : VALUE, VALUE, VALUE, VALUE -> VALUE, argc : Int32) 10 | fun rb_str_to_str(str : VALUE) : VALUE 11 | fun rb_string_value_cstr(ptr : VALUE*) : UInt8* 12 | fun rb_str_new(ptr : UInt8*, len : Int32) : VALUE 13 | fun rb_num2int(value : VALUE) : Int32 14 | fun rb_int2inum(value : Int32) : VALUE 15 | end 16 | 17 | def fibonacci_cr(self : LibRuby::VALUE, value : LibRuby::VALUE) 18 | int_value = LibRuby.rb_num2int(value) 19 | LibRuby.rb_int2inum(fibonacci_cr2(int_value)) 20 | end 21 | 22 | def fibonacci_cr2(n) 23 | return n if n <= 1 24 | fibonacci_cr2(n - 1) + fibonacci_cr2(n - 2) 25 | end 26 | 27 | def tarai(self : LibRuby::VALUE, x : LibRuby::VALUE, y : LibRuby::VALUE, z : LibRuby::VALUE) 28 | int_x = LibRuby.rb_num2int(x) 29 | int_y = LibRuby.rb_num2int(y) 30 | int_z = LibRuby.rb_num2int(z) 31 | LibRuby.rb_int2inum(tarai2(int_x, int_y, int_z)) 32 | end 33 | 34 | def tarai2(x, y, z) 35 | if y < x 36 | tarai2( 37 | tarai2(x - 1, y, z), 38 | tarai2(y - 1, z, x), 39 | tarai2(z - 1, x, y) 40 | ) 41 | else 42 | y 43 | end 44 | end 45 | 46 | def generate(self : LibRuby::VALUE, value : LibRuby::VALUE, col : LibRuby::VALUE, row : LibRuby::VALUE) 47 | rb_str = LibRuby.rb_str_to_str(value) 48 | c_str = LibRuby.rb_string_value_cstr(pointerof(rb_str)) 49 | cr_str = String.new(c_str) 50 | int_col = LibRuby.rb_num2int(col) 51 | int_row = LibRuby.rb_num2int(row) 52 | 53 | table = "" 54 | 55 | int_row.times do |row_i| 56 | table += "\n " 57 | int_col.times { |col_i| table += "\n " } 58 | table += "\n " 59 | end 60 | 61 | table += "\n
(#{col_i}) #{cr_str}
" 62 | LibRuby.rb_str_new(table.to_unsafe, table.size) 63 | end 64 | 65 | fun init = Init_extension_with_crystal 66 | GC.init 67 | LibCrystalMain.__crystal_main(0, Pointer(Pointer(UInt8)).null) 68 | 69 | LibRuby.rb_define_global_function("fibonacci_cr", ->fibonacci_cr, 1); 70 | 71 | rb_class_table = LibRuby.rb_define_class("TableCr", LibRuby.rb_cObject) 72 | LibRuby.rb_define_method(rb_class_table, "generate", ->generate, 3); 73 | 74 | rb_class_takeuchi = LibRuby.rb_define_class("TakeuchiCr", LibRuby.rb_cObject) 75 | LibRuby.rb_define_module_function(rb_class_takeuchi, "tarai", ->tarai, 3); 76 | end 77 | --------------------------------------------------------------------------------