Skip to content

Instantly share code, notes, and snippets.

@shyouhei
Last active January 25, 2018 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shyouhei/9f3aea1b6845dd8baeda14e4f6cd02d1 to your computer and use it in GitHub Desktop.
Save shyouhei/9f3aea1b6845dd8baeda14e4f6cd02d1 to your computer and use it in GitHub Desktop.
We can make this file beautiful and searchable if this error is corrected: Illegal quoting in line 2.
2018-01-25 22:56:13 +0900
target 0: 2.6 (ruby 2.6.0dev (2018-01-25 trunk 62035) [x86_64-darwin15]) at "../trunk@svn/miniruby"
target 1: 2.4 (ruby 2.4.4p228 (2018-01-15 revision 61854) [x86_64-darwin15]) at "../ruby_2_4@svn/miniruby"
target 2: 2.5 (ruby 2.5.0p12 (2018-01-24 revision 62023) [x86_64-darwin15]) at "../ruby_2_5@svn/miniruby"
target 3: mov (ruby 2.6.0dev (2018-01-25) [x86_64-darwin15]) at "./miniruby.move-only"
target 4: ours (ruby 2.6.0dev (2018-01-25 per-insn-annot.. 62006) [x86_64-darwin15]
last_commit=fixme PC tweak for frame-pushing instructions) at "./miniruby"
measure target: real
-----------------------------------------------------------
so_ackermann
#!/usr/bin/ruby
# -*- mode: ruby -*-
# $Id: ackermann-ruby.code,v 1.4 2004/11/13 07:40:41 bfulgham Exp $
# http://www.bagley.org/~doug/shootout/
def ack(m, n)
if m == 0 then
n + 1
elsif n == 0 then
ack(m - 1, 1)
else
ack(m - 1, ack(m, n - 1))
end
end
NUM = 9
ack(3, NUM)
2.6 0.4554562140001508
2.6 0.5460585769997124
2.6 0.48677734000011696
2.4 0.5426385809987551
2.4 0.5000252749996434
2.4 0.5233149949999643
2.5 0.5049834759993246
2.5 0.4907812910005305
2.5 0.4685020809993148
mov 0.5007250029993884
mov 0.5030296860004455
mov 0.5188449830002355
ours 0.4566567390011187
ours 0.48271287699935783
ours 0.4353388810013712
-----------------------------------------------------------
so_array
#!/usr/bin/ruby
# -*- mode: ruby -*-
# $Id: ary-ruby.code,v 1.4 2004/11/13 07:41:27 bfulgham Exp $
# http://www.bagley.org/~doug/shootout/
# with help from Paul Brannan and Mark Hubbart
n = 9000 # Integer(ARGV.shift || 1)
x = Array.new(n)
y = Array.new(n, 0)
n.times{|bi|
x[bi] = bi + 1
}
(0 .. 999).each do |e|
(n-1).step(0,-1) do |bi|
y[bi] += x.at(bi)
end
end
# puts "#{y.first} #{y.last}"
2.6 1.001565152000694
2.6 0.9968090410002333
2.6 0.9579997450000519
2.4 0.9520652720002545
2.4 0.9347633369998221
2.4 0.9071830599987152
2.5 0.9791266880001785
2.5 0.9549793690002844
2.5 0.9539940169997863
mov 0.7793143929993676
mov 0.8528579640005773
mov 0.7667878169995674
ours 0.8373816940002143
ours 0.8716633730000467
ours 0.8410910629991122
-----------------------------------------------------------
so_binary_trees
# The Computer Language Shootout Benchmarks
# http://shootout.alioth.debian.org
#
# contributed by Jesse Millikan
# disable output
alias puts_orig puts
def puts str
# disable puts
end
def item_check(tree)
if tree[0] == nil
tree[1]
else
tree[1] + item_check(tree[0]) - item_check(tree[2])
end
end
def bottom_up_tree(item, depth)
if depth > 0
item_item = 2 * item
depth -= 1
[bottom_up_tree(item_item - 1, depth), item, bottom_up_tree(item_item, depth)]
else
[nil, item, nil]
end
end
max_depth = 16 # ARGV[0].to_i
min_depth = 4
max_depth = min_depth + 2 if min_depth + 2 > max_depth
stretch_depth = max_depth + 1
stretch_tree = bottom_up_tree(0, stretch_depth)
puts "stretch tree of depth #{stretch_depth}\t check: #{item_check(stretch_tree)}"
stretch_tree = nil
long_lived_tree = bottom_up_tree(0, max_depth)
min_depth.step(max_depth + 1, 2) do |depth|
iterations = 2**(max_depth - depth + min_depth)
check = 0
for i in 1..iterations
temp_tree = bottom_up_tree(i, depth)
check += item_check(temp_tree)
temp_tree = bottom_up_tree(-i, depth)
check += item_check(temp_tree)
end
puts "#{iterations * 2}\t trees of depth #{depth}\t check: #{check}"
end
puts "long lived tree of depth #{max_depth}\t check: #{item_check(long_lived_tree)}"
undef puts
alias puts puts_orig
2.6 5.580577554999763
2.6 5.672877137998512
2.6 5.681266890000188
2.4 5.6974034150007355
2.4 5.571260650000113
2.4 5.640231679999488
2.5 5.69990062999932
2.5 5.733895809999012
2.5 5.803898205000223
mov 5.811514707000242
mov 5.8644480610000755
mov 5.676164667998819
ours 5.331443604000015
ours 5.276973361000273
ours 5.304218047998802
-----------------------------------------------------------
so_concatenate
#!/usr/bin/ruby
# -*- mode: ruby -*-
# $Id: strcat-ruby.code,v 1.4 2004/11/13 07:43:28 bfulgham Exp $
# http://www.bagley.org/~doug/shootout/
# based on code from Aristarkh A Zagorodnikov and Dat Nguyen
STUFF = "hello\n"
i = 0
while i<10
i += 1
hello = ''
4_000_000.times do |e|
hello << STUFF
end
end
# puts hello.length
2.6 4.162689265000154
2.6 4.050541177999548
2.6 3.940061029001299
2.4 3.8832351839992043
2.4 4.06592698500026
2.4 4.063692245999846
2.5 3.967408909998994
2.5 4.124347431999922
2.5 4.109010133999618
mov 3.357697522000308
mov 3.426567314998465
mov 3.360884959000032
ours 3.5874504879993765
ours 3.4942243530003907
ours 3.564860012000281
-----------------------------------------------------------
so_count_words
#!/usr/bin/ruby
# -*- mode: ruby -*-
# $Id: wc-ruby.code,v 1.4 2004/11/13 07:43:32 bfulgham Exp $
# http://www.bagley.org/~doug/shootout/
# with help from Paul Brannan
input = open(File.join(File.dirname($0), 'wc.input'), 'rb')
nl = nw = nc = 0
while true
tmp = input.read(4096) or break
data = tmp << (input.gets || "")
nc += data.length
nl += data.count("\n")
((data.strip! || data).tr!("\n", " ") || data).squeeze!
nw += data.count(" ") + 1
end
# STDERR.puts "#{nl} #{nw} #{nc}"
2.6 0.2116428770004859
2.6 0.1751734769986797
2.6 0.16015411599983054
2.4 0.18809206900004938
2.4 0.1868481969995628
2.4 0.18051345399908314
2.5 0.15815120999832288
2.5 0.15577895199930936
2.5 0.16851444699932472
mov 0.19810375300039595
mov 0.18774900899916247
mov 0.17638365699895076
ours 0.15821733499979018
ours 0.15316619599980186
ours 0.15631227900121303
-----------------------------------------------------------
so_exception
#!/usr/bin/ruby
# -*- mode: ruby -*-
# $Id: except-ruby.code,v 1.4 2004/11/13 07:41:33 bfulgham Exp $
# http://www.bagley.org/~doug/shootout/
$HI = 0
$LO = 0
NUM = 250000 # Integer(ARGV[0] || 1)
class Lo_Exception < Exception
def initialize(num)
@value = num
end
end
class Hi_Exception < Exception
def initialize(num)
@value = num
end
end
def some_function(num)
begin
hi_function(num)
rescue
print "We shouldn't get here, exception is: #{$!.type}\n"
end
end
def hi_function(num)
begin
lo_function(num)
rescue Hi_Exception
$HI = $HI + 1
end
end
def lo_function(num)
begin
blowup(num)
rescue Lo_Exception
$LO = $LO + 1
end
end
def blowup(num)
if num % 2 == 0
raise Lo_Exception.new(num)
else
raise Hi_Exception.new(num)
end
end
i = 1
max = NUM+1
while i < max
i += 1
some_function(i+1)
end
2.6 0.2500917070010473
2.6 0.2577815829990868
2.6 0.2467453930003103
2.4 0.2741440910012898
2.4 0.3024373070002184
2.4 0.2643489359998057
2.5 0.27839342600054806
2.5 0.2732393279984535
2.5 0.29030586299995775
mov 0.25994120500035933
mov 0.2585156980003376
mov 0.2854875550001452
ours 0.23863023100057035
ours 0.233121231000041
ours 0.23833293300049263
-----------------------------------------------------------
so_fannkuch
# The Computer Language Shootout
# http://shootout.alioth.debian.org/
# Contributed by Sokolov Yura
# Modified by Ryan Williams
def fannkuch(n)
maxFlips, m, r, check = 0, n-1, n, 0
count = (1..n).to_a
perm = (1..n).to_a
while true
if check < 30
puts "#{perm}"
check += 1
end
while r != 1
count[r-1] = r
r -= 1
end
if perm[0] != 1 and perm[m] != n
perml = perm.clone #.dup
flips = 0
while (k = perml.first ) != 1
perml = perml.slice!(0, k).reverse + perml
flips += 1
end
maxFlips = flips if flips > maxFlips
end
while true
if r==n then return maxFlips end
perm.insert r,perm.shift
break if (count[r] -= 1) > 0
r += 1
end
end
end
def puts *args
end
N = 9 # (ARGV[0] || 1).to_i
puts "Pfannkuchen(#{N}) = #{fannkuch(N)}"
2.6 1.0336100099993928
2.6 1.0444943120000971
2.6 1.034648062000997
2.4 1.043466446999446
2.4 1.0758836380009598
2.4 1.0880409520013927
2.5 1.0696021799994924
2.5 1.1295678669994231
2.5 1.0254586539995216
mov 1.067924678000054
mov 1.0172085699996387
mov 1.0360942509996676
ours 1.019557445000828
ours 1.056072645000313
ours 0.9758349160001671
-----------------------------------------------------------
so_fasta
# The Computer Language Shootout
# http://shootout.alioth.debian.org/
# Contributed by Sokolov Yura
$last = 42.0
def gen_random(max, im=139968, ia=3877, ic=29573)
(max * ($last = ($last * ia + ic) % im)) / im
end
alu =
"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG"+
"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA"+
"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT"+
"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA"+
"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG"+
"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC"+
"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"
iub = [
["a", 0.27],
["c", 0.12],
["g", 0.12],
["t", 0.27],
["B", 0.02],
["D", 0.02],
["H", 0.02],
["K", 0.02],
["M", 0.02],
["N", 0.02],
["R", 0.02],
["S", 0.02],
["V", 0.02],
["W", 0.02],
["Y", 0.02],
]
homosapiens = [
["a", 0.3029549426680],
["c", 0.1979883004921],
["g", 0.1975473066391],
["t", 0.3015094502008],
]
def make_repeat_fasta(id, desc, src, n)
puts ">#{id} #{desc}"
v = nil
width = 60
l = src.length
s = src * ((n / l) + 1)
s.slice!(n, l)
puts(s.scan(/.{1,#{width}}/).join("\n"))
end
def make_random_fasta(id, desc, table, n)
puts ">#{id} #{desc}"
rand, v = nil,nil
width = 60
chunk = 1 * width
prob = 0.0
table.each{|v| v[1]= (prob += v[1])}
for i in 1..(n/width)
puts((1..width).collect{
rand = gen_random(1.0)
table.find{|v| v[1]>rand}[0]
}.join)
end
if n%width != 0
puts((1..(n%width)).collect{
rand = gen_random(1.0)
table.find{|v| v[1]>rand}[0]
}.join)
end
end
n = (ARGV[0] or 250_000).to_i
make_repeat_fasta('ONE', 'Homo sapiens alu', alu, n*2)
make_random_fasta('TWO', 'IUB ambiguity codes', iub, n*3)
make_random_fasta('THREE', 'Homo sapiens frequency', homosapiens, n*5)
2.6 1.5346465650000027
2.6 1.5587319389996992
2.6 1.5562305639996339
2.4 1.4634280749996833
2.4 1.5208723189989541
2.4 1.5450861049994273
2.5 1.5067925960011053
2.5 1.5190188649994525
2.5 1.5980066030006128
mov 1.470517698000549
mov 1.4239339609994204
mov 1.4360517959994468
ours 1.4852364859998488
ours 1.5562712290011405
ours 1.497141076000844
-----------------------------------------------------------
so_k_nucleotide
# The Computer Language Shootout
# http://shootout.alioth.debian.org
#
# contributed by jose fco. gonzalez
# modified by Sokolov Yura
seq = String.new
def frecuency( seq,length )
n, table = seq.length - length + 1, Hash.new(0)
f, i = nil, nil
(0 ... length).each do |f|
(f ... n).step(length) do |i|
table[seq[i,length]] += 1
end
end
[n,table]
end
def sort_by_freq( seq,length )
n,table = frecuency( seq,length )
a, b, v = nil, nil, nil
table.sort{|a,b| b[1] <=> a[1]}.each do |v|
puts "%s %.3f" % [v[0].upcase,((v[1]*100).to_f/n)]
end
puts
end
def find_seq( seq,s )
n,table = frecuency( seq,s.length )
puts "#{table[s].to_s}\t#{s.upcase}"
end
input = open(File.join(File.dirname($0), 'fasta.output.100000'), 'rb')
line = input.gets while line !~ /^>THREE/
line = input.gets
while (line !~ /^>/) & line do
seq << line.chomp
line = input.gets
end
[1,2].each {|i| sort_by_freq( seq,i ) }
%w(ggt ggta ggtatt ggtattttaatt ggtattttaatttatagt).each{|s| find_seq( seq,s) }
2.6 1.2793361570002162
2.6 1.2651835870001378
2.6 1.1648964539999724
2.4 1.2761893210008566
2.4 1.2424752150000131
2.4 1.2707221489999938
2.5 1.2316716850000375
2.5 1.2456048450003436
2.5 1.199178054001095
mov 1.1634166130006633
mov 1.0996732419989712
mov 1.146168231000047
ours 1.1135896050000156
ours 1.1313269679994846
ours 1.1500560799995583
-----------------------------------------------------------
so_lists
#from http://www.bagley.org/~doug/shootout/bench/lists/lists.ruby
NUM = 300
SIZE = 10000
def test_lists()
# create a list of integers (Li1) from 1 to SIZE
li1 = (1..SIZE).to_a
# copy the list to li2 (not by individual items)
li2 = li1.dup
# remove each individual item from left side of li2 and
# append to right side of li3 (preserving order)
li3 = Array.new
while (not li2.empty?)
li3.push(li2.shift)
end
# li2 must now be empty
# remove each individual item from right side of li3 and
# append to right side of li2 (reversing list)
while (not li3.empty?)
li2.push(li3.pop)
end
# li3 must now be empty
# reverse li1 in place
li1.reverse!
# check that first item is now SIZE
if li1[0] != SIZE then
p "not SIZE"
0
else
# compare li1 and li2 for equality
if li1 != li2 then
return(0)
else
# return the length of the list
li1.length
end
end
end
i = 0
while i<NUM
i += 1
result = test_lists()
end
result
2.6 0.5218417550004233
2.6 0.510902490999797
2.6 0.47880745499969635
2.4 0.4924291390016151
2.4 0.5186816120003641
2.4 0.48233753299973614
2.5 0.44882155699997384
2.5 0.45768725899870333
2.5 0.4700806780001585
mov 0.506731552999554
mov 0.4655134580007143
mov 0.4916510860002745
ours 0.4514159390000714
ours 0.4717869590003829
ours 0.45853865900062374
-----------------------------------------------------------
so_mandelbrot
# The Computer Language Benchmarks Game
# http://shootout.alioth.debian.org/
#
# contributed by Karl von Laudermann
# modified by Jeremy Echols
size = 600 # ARGV[0].to_i
puts "P4\n#{size} #{size}"
ITER = 49 # Iterations - 1 for easy for..in looping
LIMIT_SQUARED = 4.0 # Presquared limit
byte_acc = 0
bit_num = 0
count_size = size - 1 # Precomputed size for easy for..in looping
# For..in loops are faster than .upto, .downto, .times, etc.
for y in 0..count_size
for x in 0..count_size
zr = 0.0
zi = 0.0
cr = (2.0*x/size)-1.5
ci = (2.0*y/size)-1.0
escape = false
# To make use of the for..in code, we use a dummy variable,
# like one would in C
for dummy in 0..ITER
tr = zr*zr - zi*zi + cr
ti = 2*zr*zi + ci
zr, zi = tr, ti
if (zr*zr+zi*zi) > LIMIT_SQUARED
escape = true
break
end
end
byte_acc = (byte_acc << 1) | (escape ? 0b0 : 0b1)
bit_num += 1
# Code is very similar for these cases, but using separate blocks
# ensures we skip the shifting when it's unnecessary, which is most cases.
if (bit_num == 8)
print byte_acc.chr
byte_acc = 0
bit_num = 0
elsif (x == count_size)
byte_acc <<= (8 - bit_num)
print byte_acc.chr
byte_acc = 0
bit_num = 0
end
end
end
2.6 2.256111303999205
2.6 2.2605629179997777
2.6 2.241643777999343
2.4 2.3938522539992846
2.4 2.4874032780007838
2.4 2.516099497999676
2.5 2.473859124998853
2.5 2.4914793590014597
2.5 2.3492270719998487
mov 2.1200521369992202
mov 2.0968204119999427
mov 2.0987915380010236
ours 2.266777340999397
ours 2.2108405149992905
ours 2.2757371539992164
-----------------------------------------------------------
so_matrix
#!/usr/bin/ruby
# -*- mode: ruby -*-
# $Id: matrix-ruby.code,v 1.4 2004/11/13 07:42:14 bfulgham Exp $
# http://www.bagley.org/~doug/shootout/
n = 60 #Integer(ARGV.shift || 1)
size = 40
def mkmatrix(rows, cols)
count = 1
mx = Array.new(rows)
(0 .. (rows - 1)).each do |bi|
row = Array.new(cols, 0)
(0 .. (cols - 1)).each do |j|
row[j] = count
count += 1
end
mx[bi] = row
end
mx
end
def mmult(rows, cols, m1, m2)
m3 = Array.new(rows)
(0 .. (rows - 1)).each do |bi|
row = Array.new(cols, 0)
(0 .. (cols - 1)).each do |j|
val = 0
(0 .. (cols - 1)).each do |k|
val += m1.at(bi).at(k) * m2.at(k).at(j)
end
row[j] = val
end
m3[bi] = row
end
m3
end
m1 = mkmatrix(size, size)
m2 = mkmatrix(size, size)
mm = Array.new
n.times do
mm = mmult(size, size, m1, m2)
end
# puts "#{mm[0][0]} #{mm[2][3]} #{mm[3][2]} #{mm[4][4]}"
2.6 0.5646408560005511
2.6 0.5596649750004872
2.6 0.5343214719996467
2.4 0.6103218059997744
2.4 0.5513107269998727
2.4 0.613436568999532
2.5 0.5668281639991619
2.5 0.5668770060001407
2.5 0.5371557170001324
mov 0.4638839500003087
mov 0.5026085760000569
mov 0.5268650039997738
ours 0.5241673550008272
ours 0.4785625139993499
ours 0.5010744080009317
-----------------------------------------------------------
so_meteor_contest
#!/usr/bin/env ruby
#
# The Computer Language Shootout
# http://shootout.alioth.debian.org
# contributed by Kevin Barnes (Ruby novice)
# PROGRAM: the main body is at the bottom.
# 1) read about the problem here: http://www-128.ibm.com/developerworks/java/library/j-javaopt/
# 2) see how I represent a board as a bitmask by reading the blank_board comments
# 3) read as your mental paths take you
def print *args
end
# class to represent all information about a particular rotation of a particular piece
class Rotation
# an array (by location) containing a bit mask for how the piece maps at the given location.
# if the rotation is invalid at that location the mask will contain false
attr_reader :start_masks
# maps a direction to a relative location. these differ depending on whether it is an even or
# odd row being mapped from
@@rotation_even_adder = { :west => -1, :east => 1, :nw => -7, :ne => -6, :sw => 5, :se => 6 }
@@rotation_odd_adder = { :west => -1, :east => 1, :nw => -6, :ne => -5, :sw => 6, :se => 7 }
def initialize( directions )
@even_offsets, @odd_offsets = normalize_offsets( get_values( directions ))
@even_mask = mask_for_offsets( @even_offsets)
@odd_mask = mask_for_offsets( @odd_offsets)
@start_masks = Array.new(60)
# create the rotational masks by placing the base mask at the location and seeing if
# 1) it overlaps the boundaries and 2) it produces a prunable board. if either of these
# is true the piece cannot be placed
0.upto(59) do | offset |
mask = is_even(offset) ? (@even_mask << offset) : (@odd_mask << offset)
if (blank_board & mask == 0 && !prunable(blank_board | mask, 0, true)) then
imask = compute_required( mask, offset)
@start_masks[offset] = [ mask, imask, imask | mask ]
else
@start_masks[offset] = false
end
end
end
def compute_required( mask, offset )
board = blank_board
0.upto(offset) { | i | board |= 1 << i }
board |= mask
return 0 if (!prunable(board | mask, offset))
board = flood_fill(board,58)
count = 0
imask = 0
0.upto(59) do | i |
if (board[i] == 0) then
imask |= (1 << i)
count += 1
end
end
(count > 0 && count < 5) ? imask : 0
end
def flood_fill( board, location)
return board if (board[location] == 1)
board |= 1 << location
row, col = location.divmod(6)
board = flood_fill( board, location - 1) if (col > 0)
board = flood_fill( board, location + 1) if (col < 4)
if (row % 2 == 0) then
board = flood_fill( board, location - 7) if (col > 0 && row > 0)
board = flood_fill( board, location - 6) if (row > 0)
board = flood_fill( board, location + 6) if (row < 9)
board = flood_fill( board, location + 5) if (col > 0 && row < 9)
else
board = flood_fill( board, location - 5) if (col < 4 && row > 0)
board = flood_fill( board, location - 6) if (row > 0)
board = flood_fill( board, location + 6) if (row < 9)
board = flood_fill( board, location + 7) if (col < 4 && row < 9)
end
board
end
# given a location, produces a list of relative locations covered by the piece at this rotation
def offsets( location)
if is_even( location) then
@even_offsets.collect { | value | value + location }
else
@odd_offsets.collect { | value | value + location }
end
end
# returns a set of offsets relative to the top-left most piece of the rotation (by even or odd rows)
# this is hard to explain. imagine we have this partial board:
# 0 0 0 0 0 x [positions 0-5]
# 0 0 1 1 0 x [positions 6-11]
# 0 0 1 0 0 x [positions 12-17]
# 0 1 0 0 0 x [positions 18-23]
# 0 1 0 0 0 x [positions 24-29]
# 0 0 0 0 0 x [positions 30-35]
# ...
# The top-left of the piece is at position 8, the
# board would be passed as a set of positions (values array) containing [8,9,14,19,25] not necessarily in that
# sorted order. Since that array starts on an odd row, the offsets for an odd row are: [0,1,6,11,17] obtained
# by subtracting 8 from everything. Now imagine the piece shifted up and to the right so it's on an even row:
# 0 0 0 1 1 x [positions 0-5]
# 0 0 1 0 0 x [positions 6-11]
# 0 0 1 0 0 x [positions 12-17]
# 0 1 0 0 0 x [positions 18-23]
# 0 0 0 0 0 x [positions 24-29]
# 0 0 0 0 0 x [positions 30-35]
# ...
# Now the positions are [3,4,8,14,19] which after subtracting the lowest value (3) gives [0,1,5,11,16] thus, the
# offsets for this particular piece are (in even, odd order) [0,1,5,11,16],[0,1,6,11,17] which is what
# this function would return
def normalize_offsets( values)
min = values.min
even_min = is_even(min)
other_min = even_min ? min + 6 : min + 7
other_values = values.collect do | value |
if is_even(value) then
value + 6 - other_min
else
value + 7 - other_min
end
end
values.collect! { | value | value - min }
if even_min then
[values, other_values]
else
[other_values, values]
end
end
# produce a bitmask representation of an array of offset locations
def mask_for_offsets( offsets )
mask = 0
offsets.each { | value | mask = mask + ( 1 << value ) }
mask
end
# finds a "safe" position that a position as described by a list of directions can be placed
# without falling off any edge of the board. the values returned a location to place the first piece
# at so it will fit after making the described moves
def start_adjust( directions )
south = east = 0;
directions.each do | direction |
east += 1 if ( direction == :sw || direction == :nw || direction == :west )
south += 1 if ( direction == :nw || direction == :ne )
end
south * 6 + east
end
# given a set of directions places the piece (as defined by a set of directions) on the board at
# a location that will not take it off the edge
def get_values( directions )
start = start_adjust(directions)
values = [ start ]
directions.each do | direction |
if (start % 12 >= 6) then
start += @@rotation_odd_adder[direction]
else
start += @@rotation_even_adder[direction]
end
values += [ start ]
end
# some moves take you back to an existing location, we'll strip duplicates
values.uniq
end
end
# describes a piece and caches information about its rotations to as to be efficient for iteration
# ATTRIBUTES:
# rotations -- all the rotations of the piece
# type -- a numeic "name" of the piece
# masks -- an array by location of all legal rotational masks (a n inner array) for that location
# placed -- the mask that this piece was last placed at (not a location, but the actual mask used)
class Piece
attr_reader :rotations, :type, :masks
attr_accessor :placed
# transform hashes that change one direction into another when you either flip or rotate a set of directions
@@flip_converter = { :west => :west, :east => :east, :nw => :sw, :ne => :se, :sw => :nw, :se => :ne }
@@rotate_converter = { :west => :nw, :east => :se, :nw => :ne, :ne => :east, :sw => :west, :se => :sw }
def initialize( directions, type )
@type = type
@rotations = Array.new();
@map = {}
generate_rotations( directions )
directions.collect! { | value | @@flip_converter[value] }
generate_rotations( directions )
# creates the masks AND a map that returns [location, rotation] for any given mask
# this is used when a board is found and we want to draw it, otherwise the map is unused
@masks = Array.new();
0.upto(59) do | i |
even = true
@masks[i] = @rotations.collect do | rotation |
mask = rotation.start_masks[i]
@map[mask[0]] = [ i, rotation ] if (mask)
mask || nil
end
@masks[i].compact!
end
end
# rotates a set of directions through all six angles and adds a Rotation to the list for each one
def generate_rotations( directions )
6.times do
rotations.push( Rotation.new(directions))
directions.collect! { | value | @@rotate_converter[value] }
end
end
# given a board string, adds this piece to the board at whatever location/rotation
# important: the outbound board string is 5 wide, the normal location notation is six wide (padded)
def fill_string( board_string)
location, rotation = @map[@placed]
rotation.offsets(location).each do | offset |
row, col = offset.divmod(6)
board_string[ row*5 + col, 1 ] = @type.to_s
end
end
end
# a blank bit board having this form:
#
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 0 0 0 0 0 1
# 1 1 1 1 1 1
#
# where left lest significant bit is the top left and the most significant is the lower right
# the actual board only consists of the 0 places, the 1 places are blockers to keep things from running
# off the edges or bottom
def blank_board
0b111111100000100000100000100000100000100000100000100000100000100000
end
def full_board
0b111111111111111111111111111111111111111111111111111111111111111111
end
# determines if a location (bit position) is in an even row
def is_even( location)
(location % 12) < 6
end
# support function that create three utility maps:
# $converter -- for each row an array that maps a five bit row (via array mapping)
# to the a five bit representation of the bits below it
# $bit_count -- maps a five bit row (via array mapping) to the number of 1s in the row
# @@new_regions -- maps a five bit row (via array mapping) to an array of "region" arrays
# a region array has three values the first is a mask of bits in the region,
# the second is the count of those bits and the third is identical to the first
# examples:
# 0b10010 => [ 0b01100, 2, 0b01100 ], [ 0b00001, 1, 0b00001]
# 0b01010 => [ 0b10000, 1, 0b10000 ], [ 0b00100, 1, 0b00100 ], [ 0b00001, 1, 0b00001]
# 0b10001 => [ 0b01110, 3, 0b01110 ]
def create_collector_support
odd_map = [0b11, 0b110, 0b1100, 0b11000, 0b10000]
even_map = [0b1, 0b11, 0b110, 0b1100, 0b11000]
all_odds = Array.new(0b100000)
all_evens = Array.new(0b100000)
bit_counts = Array.new(0b100000)
new_regions = Array.new(0b100000)
0.upto(0b11111) do | i |
bit_count = odd = even = 0
0.upto(4) do | bit |
if (i[bit] == 1) then
bit_count += 1
odd |= odd_map[bit]
even |= even_map[bit]
end
end
all_odds[i] = odd
all_evens[i] = even
bit_counts[i] = bit_count
new_regions[i] = create_regions( i)
end
$converter = []
10.times { | row | $converter.push((row % 2 == 0) ? all_evens : all_odds) }
$bit_counts = bit_counts
$regions = new_regions.collect { | set | set.collect { | value | [ value, bit_counts[value], value] } }
end
# determines if a board is punable, meaning that there is no possibility that it
# can be filled up with pieces. A board is prunable if there is a grouping of unfilled spaces
# that are not a multiple of five. The following board is an example of a prunable board:
# 0 0 1 0 0
# 0 1 0 0 0
# 1 1 0 0 0
# 0 1 0 0 0
# 0 0 0 0 0
# ...
#
# This board is prunable because the top left corner is only 3 bits in area, no piece will ever fit it
# parameters:
# board -- an initial bit board (6 bit padded rows, see blank_board for format)
# location -- starting location, everything above and to the left is already full
# slotting -- set to true only when testing initial pieces, when filling normally
# additional assumptions are possible
#
# Algorithm:
# The algorithm starts at the top row (as determined by location) and iterates a row at a time
# maintainng counts of active open areas (kept in the collector array) each collector contains
# three values at the start of an iteration:
# 0: mask of bits that would be adjacent to the collector in this row
# 1: the number of bits collected so far
# 2: a scratch space starting as zero, but used during the computation to represent
# the empty bits in the new row that are adjacent (position 0)
# The exact procedure is described in-code
def prunable( board, location, slotting = false)
collectors = []
# loop across the rows
(location / 6).to_i.upto(9) do | row_on |
# obtain a set of regions representing the bits of the current row.
regions = $regions[(board >> (row_on * 6)) & 0b11111]
converter = $converter[row_on]
# track the number of collectors at the start of the cycle so that
# we don't compute against newly created collectors, only existing collectors
initial_collector_count = collectors.length
# loop against the regions. For each region of the row
# we will see if it connects to one or more existing collectors.
# if it connects to 1 collector, the bits from the region are added to the
# bits of the collector and the mask is placed in collector[2]
# If the region overlaps more than one collector then all the collectors
# it overlaps with are merged into the first one (the others are set to nil in the array)
# if NO collectors are found then the region is copied as a new collector
regions.each do | region |
collector_found = nil
region_mask = region[2]
initial_collector_count.times do | collector_num |
collector = collectors[collector_num]
if (collector) then
collector_mask = collector[0]
if (collector_mask & region_mask != 0) then
if (collector_found) then
collector_found[0] |= collector_mask
collector_found[1] += collector[1]
collector_found[2] |= collector[2]
collectors[collector_num] = nil
else
collector_found = collector
collector[1] += region[1]
collector[2] |= region_mask
end
end
end
end
if (collector_found == nil) then
collectors.push(Array.new(region))
end
end
# check the existing collectors, if any collector overlapped no bits in the region its [2] value will
# be zero. The size of any such reaason is tested if it is not a multiple of five true is returned since
# the board is prunable. if it is a multiple of five it is removed.
# Collector that are still active have a new adjacent value [0] set based n the matched bits
# and have [2] cleared out for the next cycle.
collectors.length.times do | collector_num |
collector = collectors[collector_num]
if (collector) then
if (collector[2] == 0) then
return true if (collector[1] % 5 != 0)
collectors[collector_num] = nil
else
# if a collector matches all bits in the row then we can return unprunable early for the
# following reasons:
# 1) there can be no more unavailable bits bince we fill from the top left downward
# 2) all previous regions have been closed or joined so only this region can fail
# 3) this region must be good since there can never be only 1 region that is nuot
# a multiple of five
# this rule only applies when filling normally, so we ignore the rule if we are "slotting"
# in pieces to see what configurations work for them (the only other time this algorithm is used).
return false if (collector[2] == 0b11111 && !slotting)
collector[0] = converter[collector[2]]
collector[2] = 0
end
end
end
# get rid of all the empty converters for the next round
collectors.compact!
end
return false if (collectors.length <= 1) # 1 collector or less and the region is fine
collectors.any? { | collector | (collector[1] % 5) != 0 } # more than 1 and we test them all for bad size
end
# creates a region given a row mask. see prunable for what a "region" is
def create_regions( value )
regions = []
cur_region = 0
5.times do | bit |
if (value[bit] == 0) then
cur_region |= 1 << bit
else
if (cur_region != 0 ) then
regions.push( cur_region)
cur_region = 0;
end
end
end
regions.push(cur_region) if (cur_region != 0)
regions
end
# find up to the counted number of solutions (or all solutions) and prints the final result
def find_all
find_top( 1)
find_top( 0)
print_results
end
# show the board
def print_results
print "#{@boards_found} solutions found\n\n"
print_full_board( @min_board)
print "\n"
print_full_board( @max_board)
print "\n"
end
# finds solutions. This special version of the main function is only used for the top level
# the reason for it is basically to force a particular ordering on how the rotations are tested for
# the first piece. It is called twice, first looking for placements of the odd rotations and then
# looking for placements of the even locations.
#
# WHY?
# Since any found solution has an inverse we want to maximize finding solutions that are not already found
# as an inverse. The inverse will ALWAYS be 3 one of the piece configurations that is exactly 3 rotations away
# (an odd number). Checking even vs odd then produces a higher probability of finding more pieces earlier
# in the cycle. We still need to keep checking all the permutations, but our probability of finding one will
# diminsh over time. Since we are TOLD how many to search for this lets us exit before checking all pieces
# this bennifit is very great when seeking small numbers of solutions and is 0 when looking for more than the
# maximum number
def find_top( rotation_skip)
board = blank_board
(@pieces.length-1).times do
piece = @pieces.shift
piece.masks[0].each do | mask, imask, cmask |
if ((rotation_skip += 1) % 2 == 0) then
piece.placed = mask
find( 1, 1, board | mask)
end
end
@pieces.push(piece)
end
piece = @pieces.shift
@pieces.push(piece)
end
# the normail find routine, iterates through the available pieces, checks all rotations at the current location
# and adds any boards found. depth is achieved via recursion. the overall approach is described
# here: http://www-128.ibm.com/developerworks/java/library/j-javaopt/
# parameters:
# start_location -- where to start looking for place for the next piece at
# placed -- number of pieces placed
# board -- current state of the board
#
# see in-code comments
def find( start_location, placed, board)
# find the next location to place a piece by looking for an empty bit
while board[start_location] == 1
start_location += 1
end
@pieces.length.times do
piece = @pieces.shift
piece.masks[start_location].each do | mask, imask, cmask |
if ( board & cmask == imask) then
piece.placed = mask
if (placed == 9) then
add_board
else
find( start_location + 1, placed + 1, board | mask)
end
end
end
@pieces.push(piece)
end
end
# print the board
def print_full_board( board_string)
10.times do | row |
print " " if (row % 2 == 1)
5.times do | col |
print "#{board_string[row*5 + col,1]} "
end
print "\n"
end
end
# when a board is found we "draw it" into a string and then flip that string, adding both to
# the list (hash) of solutions if they are unique.
def add_board
board_string = "99999999999999999999999999999999999999999999999999"
@all_pieces.each { | piece | piece.fill_string( board_string ) }
save( board_string)
save( board_string.reverse)
end
# adds a board string to the list (if new) and updates the current best/worst board
def save( board_string)
if (@all_boards[board_string] == nil) then
@min_board = board_string if (board_string < @min_board)
@max_board = board_string if (board_string > @max_board)
@all_boards.store(board_string,true)
@boards_found += 1
# the exit motif is a time saver. Ideally the function should return, but those tests
# take noticeable time (performance).
if (@boards_found == @stop_count) then
print_results
exit(0)
end
end
end
##
## MAIN BODY :)
##
create_collector_support
@pieces = [
Piece.new( [ :nw, :ne, :east, :east ], 2),
Piece.new( [ :ne, :se, :east, :ne ], 7),
Piece.new( [ :ne, :east, :ne, :nw ], 1),
Piece.new( [ :east, :sw, :sw, :se ], 6),
Piece.new( [ :east, :ne, :se, :ne ], 5),
Piece.new( [ :east, :east, :east, :se ], 0),
Piece.new( [ :ne, :nw, :se, :east, :se ], 4),
Piece.new( [ :se, :se, :se, :west ], 9),
Piece.new( [ :se, :se, :east, :se ], 8),
Piece.new( [ :east, :east, :sw, :se ], 3)
];
@all_pieces = Array.new( @pieces)
@min_board = "99999999999999999999999999999999999999999999999999"
@max_board = "00000000000000000000000000000000000000000000000000"
@stop_count = ARGV[0].to_i || 2089
@all_boards = {}
@boards_found = 0
find_all ######## DO IT!!!
2.6 3.3938102409993007
2.6 3.2230731029994786
2.6 3.3083832079992135
2.4 3.333183630000349
2.4 3.1936890039996797
2.4 3.352127272999496
2.5 3.157131161000507
2.5 3.1907435260000057
2.5 3.1984603669989156
mov 2.930067057999622
mov 3.004820023999855
mov 3.0456303139999363
ours 3.0097075300000142
ours 3.029121400999429
ours 2.9827036269998644
-----------------------------------------------------------
so_nbody
# The Computer Language Shootout
# http://shootout.alioth.debian.org
#
# Optimized for Ruby by Jesse Millikan
# From version ported by Michael Neumann from the C gcc version,
# which was written by Christoph Bauer.
SOLAR_MASS = 4 * Math::PI**2
DAYS_PER_YEAR = 365.24
def _puts *args
end
class Planet
attr_accessor :x, :y, :z, :vx, :vy, :vz, :mass
def initialize(x, y, z, vx, vy, vz, mass)
@x, @y, @z = x, y, z
@vx, @vy, @vz = vx * DAYS_PER_YEAR, vy * DAYS_PER_YEAR, vz * DAYS_PER_YEAR
@mass = mass * SOLAR_MASS
end
def move_from_i(bodies, nbodies, dt, i)
while i < nbodies
b2 = bodies[i]
dx = @x - b2.x
dy = @y - b2.y
dz = @z - b2.z
distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
mag = dt / (distance * distance * distance)
b_mass_mag, b2_mass_mag = @mass * mag, b2.mass * mag
@vx -= dx * b2_mass_mag
@vy -= dy * b2_mass_mag
@vz -= dz * b2_mass_mag
b2.vx += dx * b_mass_mag
b2.vy += dy * b_mass_mag
b2.vz += dz * b_mass_mag
i += 1
end
@x += dt * @vx
@y += dt * @vy
@z += dt * @vz
end
end
def energy(bodies)
e = 0.0
nbodies = bodies.size
for i in 0 ... nbodies
b = bodies[i]
e += 0.5 * b.mass * (b.vx * b.vx + b.vy * b.vy + b.vz * b.vz)
for j in (i + 1) ... nbodies
b2 = bodies[j]
dx = b.x - b2.x
dy = b.y - b2.y
dz = b.z - b2.z
distance = Math.sqrt(dx * dx + dy * dy + dz * dz)
e -= (b.mass * b2.mass) / distance
end
end
e
end
def offset_momentum(bodies)
px, py, pz = 0.0, 0.0, 0.0
for b in bodies
m = b.mass
px += b.vx * m
py += b.vy * m
pz += b.vz * m
end
b = bodies[0]
b.vx = - px / SOLAR_MASS
b.vy = - py / SOLAR_MASS
b.vz = - pz / SOLAR_MASS
end
BODIES = [
# sun
Planet.new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
# jupiter
Planet.new(
4.84143144246472090e+00,
-1.16032004402742839e+00,
-1.03622044471123109e-01,
1.66007664274403694e-03,
7.69901118419740425e-03,
-6.90460016972063023e-05,
9.54791938424326609e-04),
# saturn
Planet.new(
8.34336671824457987e+00,
4.12479856412430479e+00,
-4.03523417114321381e-01,
-2.76742510726862411e-03,
4.99852801234917238e-03,
2.30417297573763929e-05,
2.85885980666130812e-04),
# uranus
Planet.new(
1.28943695621391310e+01,
-1.51111514016986312e+01,
-2.23307578892655734e-01,
2.96460137564761618e-03,
2.37847173959480950e-03,
-2.96589568540237556e-05,
4.36624404335156298e-05),
# neptune
Planet.new(
1.53796971148509165e+01,
-2.59193146099879641e+01,
1.79258772950371181e-01,
2.68067772490389322e-03,
1.62824170038242295e-03,
-9.51592254519715870e-05,
5.15138902046611451e-05)
]
init = 200_000 # ARGV[0]
n = Integer(init)
offset_momentum(BODIES)
puts "%.9f" % energy(BODIES)
nbodies = BODIES.size
dt = 0.01
n.times do
i = 0
while i < nbodies
b = BODIES[i]
b.move_from_i(BODIES, nbodies, dt, i + 1)
i += 1
end
end
puts "%.9f" % energy(BODIES)
2.6 1.2550447880003048
2.6 1.2584950679993199
2.6 1.2902751980000176
2.4 1.3688920330005203
2.4 1.3770301200001995
2.4 1.408765128999221
2.5 1.3036340500002552
2.5 1.3396144020007341
2.5 1.2664047769994795
mov 1.188340609000079
mov 1.2322647380005947
mov 1.2222536250010307
ours 1.2926347680004255
ours 1.3014565510002285
ours 1.315888162000192
-----------------------------------------------------------
so_nested_loop
#!/usr/bin/ruby
# -*- mode: ruby -*-
# $Id: nestedloop-ruby.code,v 1.4 2004/11/13 07:42:22 bfulgham Exp $
# http://www.bagley.org/~doug/shootout/
# from Avi Bryant
n = 16 # Integer(ARGV.shift || 1)
x = 0
n.times do
n.times do
n.times do
n.times do
n.times do
n.times do
x += 1
end
end
end
end
end
end
# puts x
2.6 1.1500995039987174
2.6 1.188764454000193
2.6 1.149731467001402
2.4 1.1660717530012334
2.4 1.1208360170003289
2.4 1.1860202200005006
2.5 1.1673170880003454
2.5 1.1572580709998874
2.5 1.1291040689993679
mov 0.8745094159985456
mov 0.9048835060002602
mov 0.9134807700011152
ours 1.0407441609986563
ours 0.9862627140009863
ours 1.0047832319996814
-----------------------------------------------------------
so_nsieve
# The Computer Language Shootout
# http://shootout.alioth.debian.org/
#
# contributed by Glenn Parker, March 2005
# modified by Evan Phoenix, Sept 2006
def sieve(m)
flags = Flags.dup[0,m]
count = 0
pmax = m - 1
p = 2
while p <= pmax
unless flags[p].zero?
count += 1
mult = p
while mult <= pmax
flags[mult] = 0
mult += p
end
end
p += 1
end
count
end
n = 9 # (ARGV[0] || 2).to_i
Flags = ("\x1" * ( 2 ** n * 10_000)).unpack("c*")
n.downto(n-2) do |exponent|
break if exponent < 0
m = (1 << exponent) * 10_000
# m = (2 ** exponent) * 10_000
count = sieve(m)
printf "Primes up to %8d %8d\n", m, count
end
2.6 1.6102409239992994
2.6 1.62961931099926
2.6 1.6875047169996833
2.4 1.6272890630007169
2.4 1.6216507210010604
2.4 1.6279327199990803
2.5 1.6880187799997657
2.5 1.6573079589998088
2.5 1.7321711929998855
mov 1.6718935949993465
mov 1.7367953619996115
mov 1.6812330209995707
ours 1.6406151089995546
ours 1.6313319809996756
ours 1.6581117320001795
-----------------------------------------------------------
so_nsieve_bits
#!/usr/bin/ruby
#coding: us-ascii
#
# The Great Computer Language Shootout
# http://shootout.alioth.debian.org/
#
# nsieve-bits in Ruby
# Contributed by Glenn Parker, March 2005
CharExponent = 3
BitsPerChar = 1 << CharExponent
LowMask = BitsPerChar - 1
def sieve(m)
items = "\xFF" * ((m / BitsPerChar) + 1)
masks = ""
BitsPerChar.times do |b|
masks << (1 << b).chr
end
count = 0
pmax = m - 1
2.step(pmax, 1) do |p|
if items[p >> CharExponent][p & LowMask] == 1
count += 1
p.step(pmax, p) do |mult|
a = mult >> CharExponent
b = mult & LowMask
items[a] -= masks[b] if items[a][b] != 0
end
end
end
count
end
n = 9 # (ARGV[0] || 2).to_i
n.step(n - 2, -1) do |exponent|
break if exponent < 0
m = 2 ** exponent * 10_000
count = sieve(m)
printf "Primes up to %8d %8d\n", m, count
end
2.6 2.2576205739987927
2.6 2.2879901549986243
2.6 2.2324862250006845
2.4 2.340885702999003
2.4 2.2873890030004986
2.4 2.252403406000667
2.5 2.239011956999093
2.5 2.2241006290005316
2.5 2.2675932780002768
mov 2.0689347650004493
mov 2.202370384999085
mov 2.124859891999222
ours 2.1029185770003096
ours 2.103586286000791
ours 2.085590255999705
-----------------------------------------------------------
so_object
#!/usr/bin/ruby
# -*- mode: ruby -*-
# $Id: objinst-ruby.code,v 1.4 2004/11/13 07:42:25 bfulgham Exp $
# http://www.bagley.org/~doug/shootout/
# with help from Aristarkh Zagorodnikov
class Toggle
def initialize(start_state)
@bool = start_state
end
def value
@bool
end
def activate
@bool = !@bool
self
end
end
class NthToggle < Toggle
def initialize(start_state, max_counter)
super start_state
@count_max = max_counter
@counter = 0
end
def activate
@counter += 1
if @counter >= @count_max
@bool = !@bool
@counter = 0
end
self
end
end
n = 1500000 # (ARGV.shift || 1).to_i
toggle = Toggle.new 1
5.times do
toggle.activate.value ? 'true' : 'false'
end
n.times do
toggle = Toggle.new 1
end
ntoggle = NthToggle.new 1, 3
8.times do
ntoggle.activate.value ? 'true' : 'false'
end
n.times do
ntoggle = NthToggle.new 1, 3
end
2.6 0.7674058560005506
2.6 0.7490566750002472
2.6 0.6997501299993019
2.4 0.7162041480005428
2.4 0.7449557740001183
2.4 0.6972389109996584
2.5 0.7059759919993667
2.5 0.7619405160003225
2.5 0.7607218379998812
mov 0.6652307590011333
mov 0.6604044569994585
mov 0.6302140660009172
ours 0.6668127670000104
ours 0.644751064999582
ours 0.6704630240001279
-----------------------------------------------------------
so_partial_sums
n = 2_500_000 # (ARGV.shift || 1).to_i
alt = 1.0 ; s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = 0.0
1.upto(n) do |d|
d = d.to_f ; d2 = d * d ; d3 = d2 * d ; ds = Math.sin(d) ; dc = Math.cos(d)
s0 += (2.0 / 3.0) ** (d - 1.0)
s1 += 1.0 / Math.sqrt(d)
s2 += 1.0 / (d * (d + 1.0))
s3 += 1.0 / (d3 * ds * ds)
s4 += 1.0 / (d3 * dc * dc)
s5 += 1.0 / d
s6 += 1.0 / d2
s7 += alt / d
s8 += alt / (2.0 * d - 1.0)
alt = -alt
end
if false
printf("%.9f\t(2/3)^k\n", s0)
printf("%.9f\tk^-0.5\n", s1)
printf("%.9f\t1/k(k+1)\n", s2)
printf("%.9f\tFlint Hills\n", s3)
printf("%.9f\tCookson Hills\n", s4)
printf("%.9f\tHarmonic\n", s5)
printf("%.9f\tRiemann Zeta\n", s6)
printf("%.9f\tAlternating Harmonic\n", s7)
printf("%.9f\tGregory\n", s8)
end
2.6 1.5522021589986252
2.6 1.6133435200008535
2.6 1.547386551001182
2.4 1.801554756000769
2.4 1.8172156929995253
2.4 1.7894713940004294
2.5 1.774220523000622
2.5 1.7445383690010203
2.5 1.7057036759997573
mov 1.5731607890011219
mov 1.5893576700000267
mov 1.502377434000664
ours 1.59014168000067
ours 1.638509640999473
ours 1.6738619050011039
-----------------------------------------------------------
so_pidigits
# The Great Computer Language Shootout
# http://shootout.alioth.debian.org/
#
# contributed by Gabriele Renzi
class PiDigitSpigot
def initialize()
@z = Transformation.new 1,0,0,1
@x = Transformation.new 0,0,0,0
@inverse = Transformation.new 0,0,0,0
end
def next!
@y = @z.extract(3)
if safe? @y
@z = produce(@y)
@y
else
@z = consume @x.next!()
next!()
end
end
def safe?(digit)
digit == @z.extract(4)
end
def produce(i)
@inverse.qrst(10,-10*i,0,1).compose(@z)
end
def consume(a)
@z.compose(a)
end
end
class Transformation
attr_reader :q, :r, :s, :t
def initialize(q, r, s, t)
@q,@r,@s,@t,@k = q,r,s,t,0
end
def next!()
@q = @k = @k + 1
@r = 4 * @k + 2
@s = 0
@t = 2 * @k + 1
self
end
def extract(j)
(@q * j + @r) / (@s * j + @t)
end
def compose(a)
self.class.new( @q * a.q,
@q * a.r + r * a.t,
@s * a.q + t * a.s,
@s * a.r + t * a.t
)
end
def qrst *args
initialize *args
self
end
end
WIDTH = 10
n = 2_500 # Integer(ARGV[0])
j = 0
digits = PiDigitSpigot.new
while n > 0
if n >= WIDTH
WIDTH.times {print digits.next!}
j += WIDTH
else
n.times {print digits.next!}
(WIDTH-n).times {print " "}
j += n
end
puts "\t:"+j.to_s
n -= WIDTH
end
2.6 1.186393894999128
2.6 1.1833510090000345
2.6 1.1735205620007036
2.4 1.1618239780000295
2.4 1.1466504959989834
2.4 1.128009963000295
2.5 1.1182356299996172
2.5 1.1632011250003416
2.5 1.1362772940010473
mov 1.107688900001449
mov 1.1241363610006374
mov 1.1140436379992025
ours 1.128270461998909
ours 1.139118449000307
ours 1.1090284120000433
-----------------------------------------------------------
so_random
# from http://www.bagley.org/~doug/shootout/bench/random/random.ruby
IM = 139968.0
IA = 3877.0
IC = 29573.0
$last = 42.0
def gen_random(max)
(max * ($last = ($last * IA + IC) % IM)) / IM
end
N = 3_000_000
i = 0
while i<N
i +=1
gen_random(100.0)
end
# "%.9f" % gen_random(100.0)
2.6 0.317847222000637
2.6 0.35848786200040195
2.6 0.3278361130014673
2.4 0.35831136900014826
2.4 0.35687618399970233
2.4 0.36264436899909924
2.5 0.3426302219995705
2.5 0.3488985969997884
2.5 0.36366021300091234
mov 0.312154618999557
mov 0.3101769739987503
mov 0.3230691739991016
ours 0.323134416999892
ours 0.3306380240010185
ours 0.3320193810013734
-----------------------------------------------------------
so_reverse_complement
#!/usr/bin/ruby
# The Great Computer Language Shootout
# http://shootout.alioth.debian.org/
#
# Contributed by Peter Bjarke Olsen
# Modified by Doug King
seq=Array.new
def revcomp(seq)
seq.reverse!.tr!('wsatugcyrkmbdhvnATUGCYRKMBDHVN','WSTAACGRYMKVHDBNTAACGRYMKVHDBN')
stringlen=seq.length
0.step(stringlen-1,60) {|x| print seq.slice(x,60) , "\n"}
end
input = open(File.join(File.dirname($0), 'fasta.output.2500000'), 'rb')
while input.gets
if $_ =~ />/
if seq.length != 0
revcomp(seq.join)
seq=Array.new
end
puts $_
else
$_.sub(/\n/,'')
seq.push $_
end
end
revcomp(seq.join)
2.6 0.5489404689997173
2.6 0.5404208580002887
2.6 0.5462583740008995
2.4 0.5680135959992185
2.4 0.5497708099992451
2.4 0.5395834880000621
2.5 0.6021959359986795
2.5 0.5516969010004686
2.5 0.5328039040014119
mov 0.5196672190013487
mov 0.562355188998481
mov 0.5638176230004319
ours 0.5843735710004694
ours 0.5236466059996019
ours 0.5464601089988719
-----------------------------------------------------------
so_sieve
# from http://www.bagley.org/~doug/shootout/bench/sieve/sieve.ruby
num = 500
count = i = j = 0
flags0 = Array.new(8192,1)
k = 0
while k < num
k += 1
count = 0
flags = flags0.dup
i = 2
while i<8192
i += 1
if flags[i]
# remove all multiples of prime: i
j = i*i
while j < 8192
j += i
flags[j] = nil
end
count += 1
end
end
end
count
2.6 0.4842971360012598
2.6 0.5040317860002688
2.6 0.5510640459997376
2.4 0.5387039269990055
2.4 0.48529543000040576
2.4 0.4990145820011094
2.5 0.5582072289998905
2.5 0.5150585970004613
2.5 0.5386602559992753
mov 0.5062628030009364
mov 0.5450196470010269
mov 0.4803183030016953
ours 0.4742865630014421
ours 0.48345261299982667
ours 0.5337589640002989
-----------------------------------------------------------
so_spectralnorm
# The Computer Language Shootout
# http://shootout.alioth.debian.org/
# Contributed by Sokolov Yura
def eval_A(i,j)
return 1.0/((i+j)*(i+j+1)/2+i+1)
end
def eval_A_times_u(u)
v, i = nil, nil
(0..u.length-1).collect { |i|
v = 0
for j in 0..u.length-1
v += eval_A(i,j)*u[j]
end
v
}
end
def eval_At_times_u(u)
v, i = nil, nil
(0..u.length-1).collect{|i|
v = 0
for j in 0..u.length-1
v += eval_A(j,i)*u[j]
end
v
}
end
def eval_AtA_times_u(u)
return eval_At_times_u(eval_A_times_u(u))
end
n = 500 # ARGV[0].to_i
u=[1]*n
for i in 1..10
v=eval_AtA_times_u(u)
u=eval_AtA_times_u(v)
end
vBv=0
vv=0
for i in 0..n-1
vBv += u[i]*v[i]
vv += v[i]*v[i]
end
str = "%0.9f" % (Math.sqrt(vBv/vv)), "\n"
# print str
2.6 1.7904831409996405
2.6 1.7761573030002182
2.6 1.8563808070011873
2.4 1.7850994399996125
2.4 1.8125653629995213
2.4 1.7561759210002492
2.5 1.878547381998942
2.5 1.9038954099996772
2.5 1.8342162690005352
mov 1.6627514379997592
mov 1.6737254840008973
mov 1.6937658000006195
ours 1.8152416390003054
ours 1.841645762000553
ours 1.6931533690003562
-----------------------------------------------------------
raw data:
[["so_ackermann",
[[0.4554562140001508, 0.5460585769997124, 0.48677734000011696],
[0.5426385809987551, 0.5000252749996434, 0.5233149949999643],
[0.5049834759993246, 0.4907812910005305, 0.4685020809993148],
[0.5007250029993884, 0.5030296860004455, 0.5188449830002355],
[0.4566567390011187, 0.48271287699935783, 0.4353388810013712]]],
["so_array",
[[1.001565152000694, 0.9968090410002333, 0.9579997450000519],
[0.9520652720002545, 0.9347633369998221, 0.9071830599987152],
[0.9791266880001785, 0.9549793690002844, 0.9539940169997863],
[0.7793143929993676, 0.8528579640005773, 0.7667878169995674],
[0.8373816940002143, 0.8716633730000467, 0.8410910629991122]]],
["so_binary_trees",
[[5.580577554999763, 5.672877137998512, 5.681266890000188],
[5.6974034150007355, 5.571260650000113, 5.640231679999488],
[5.69990062999932, 5.733895809999012, 5.803898205000223],
[5.811514707000242, 5.8644480610000755, 5.676164667998819],
[5.331443604000015, 5.276973361000273, 5.304218047998802]]],
["so_concatenate",
[[4.162689265000154, 4.050541177999548, 3.940061029001299],
[3.8832351839992043, 4.06592698500026, 4.063692245999846],
[3.967408909998994, 4.124347431999922, 4.109010133999618],
[3.357697522000308, 3.426567314998465, 3.360884959000032],
[3.5874504879993765, 3.4942243530003907, 3.564860012000281]]],
["so_count_words",
[[0.2116428770004859, 0.1751734769986797, 0.16015411599983054],
[0.18809206900004938, 0.1868481969995628, 0.18051345399908314],
[0.15815120999832288, 0.15577895199930936, 0.16851444699932472],
[0.19810375300039595, 0.18774900899916247, 0.17638365699895076],
[0.15821733499979018, 0.15316619599980186, 0.15631227900121303]]],
["so_exception",
[[0.2500917070010473, 0.2577815829990868, 0.2467453930003103],
[0.2741440910012898, 0.3024373070002184, 0.2643489359998057],
[0.27839342600054806, 0.2732393279984535, 0.29030586299995775],
[0.25994120500035933, 0.2585156980003376, 0.2854875550001452],
[0.23863023100057035, 0.233121231000041, 0.23833293300049263]]],
["so_fannkuch",
[[1.0336100099993928, 1.0444943120000971, 1.034648062000997],
[1.043466446999446, 1.0758836380009598, 1.0880409520013927],
[1.0696021799994924, 1.1295678669994231, 1.0254586539995216],
[1.067924678000054, 1.0172085699996387, 1.0360942509996676],
[1.019557445000828, 1.056072645000313, 0.9758349160001671]]],
["so_fasta",
[[1.5346465650000027, 1.5587319389996992, 1.5562305639996339],
[1.4634280749996833, 1.5208723189989541, 1.5450861049994273],
[1.5067925960011053, 1.5190188649994525, 1.5980066030006128],
[1.470517698000549, 1.4239339609994204, 1.4360517959994468],
[1.4852364859998488, 1.5562712290011405, 1.497141076000844]]],
["so_k_nucleotide",
[[1.2793361570002162, 1.2651835870001378, 1.1648964539999724],
[1.2761893210008566, 1.2424752150000131, 1.2707221489999938],
[1.2316716850000375, 1.2456048450003436, 1.199178054001095],
[1.1634166130006633, 1.0996732419989712, 1.146168231000047],
[1.1135896050000156, 1.1313269679994846, 1.1500560799995583]]],
["so_lists",
[[0.5218417550004233, 0.510902490999797, 0.47880745499969635],
[0.4924291390016151, 0.5186816120003641, 0.48233753299973614],
[0.44882155699997384, 0.45768725899870333, 0.4700806780001585],
[0.506731552999554, 0.4655134580007143, 0.4916510860002745],
[0.4514159390000714, 0.4717869590003829, 0.45853865900062374]]],
["so_mandelbrot",
[[2.256111303999205, 2.2605629179997777, 2.241643777999343],
[2.3938522539992846, 2.4874032780007838, 2.516099497999676],
[2.473859124998853, 2.4914793590014597, 2.3492270719998487],
[2.1200521369992202, 2.0968204119999427, 2.0987915380010236],
[2.266777340999397, 2.2108405149992905, 2.2757371539992164]]],
["so_matrix",
[[0.5646408560005511, 0.5596649750004872, 0.5343214719996467],
[0.6103218059997744, 0.5513107269998727, 0.613436568999532],
[0.5668281639991619, 0.5668770060001407, 0.5371557170001324],
[0.4638839500003087, 0.5026085760000569, 0.5268650039997738],
[0.5241673550008272, 0.4785625139993499, 0.5010744080009317]]],
["so_meteor_contest",
[[3.3938102409993007, 3.2230731029994786, 3.3083832079992135],
[3.333183630000349, 3.1936890039996797, 3.352127272999496],
[3.157131161000507, 3.1907435260000057, 3.1984603669989156],
[2.930067057999622, 3.004820023999855, 3.0456303139999363],
[3.0097075300000142, 3.029121400999429, 2.9827036269998644]]],
["so_nbody",
[[1.2550447880003048, 1.2584950679993199, 1.2902751980000176],
[1.3688920330005203, 1.3770301200001995, 1.408765128999221],
[1.3036340500002552, 1.3396144020007341, 1.2664047769994795],
[1.188340609000079, 1.2322647380005947, 1.2222536250010307],
[1.2926347680004255, 1.3014565510002285, 1.315888162000192]]],
["so_nested_loop",
[[1.1500995039987174, 1.188764454000193, 1.149731467001402],
[1.1660717530012334, 1.1208360170003289, 1.1860202200005006],
[1.1673170880003454, 1.1572580709998874, 1.1291040689993679],
[0.8745094159985456, 0.9048835060002602, 0.9134807700011152],
[1.0407441609986563, 0.9862627140009863, 1.0047832319996814]]],
["so_nsieve",
[[1.6102409239992994, 1.62961931099926, 1.6875047169996833],
[1.6272890630007169, 1.6216507210010604, 1.6279327199990803],
[1.6880187799997657, 1.6573079589998088, 1.7321711929998855],
[1.6718935949993465, 1.7367953619996115, 1.6812330209995707],
[1.6406151089995546, 1.6313319809996756, 1.6581117320001795]]],
["so_nsieve_bits",
[[2.2576205739987927, 2.2879901549986243, 2.2324862250006845],
[2.340885702999003, 2.2873890030004986, 2.252403406000667],
[2.239011956999093, 2.2241006290005316, 2.2675932780002768],
[2.0689347650004493, 2.202370384999085, 2.124859891999222],
[2.1029185770003096, 2.103586286000791, 2.085590255999705]]],
["so_object",
[[0.7674058560005506, 0.7490566750002472, 0.6997501299993019],
[0.7162041480005428, 0.7449557740001183, 0.6972389109996584],
[0.7059759919993667, 0.7619405160003225, 0.7607218379998812],
[0.6652307590011333, 0.6604044569994585, 0.6302140660009172],
[0.6668127670000104, 0.644751064999582, 0.6704630240001279]]],
["so_partial_sums",
[[1.5522021589986252, 1.6133435200008535, 1.547386551001182],
[1.801554756000769, 1.8172156929995253, 1.7894713940004294],
[1.774220523000622, 1.7445383690010203, 1.7057036759997573],
[1.5731607890011219, 1.5893576700000267, 1.502377434000664],
[1.59014168000067, 1.638509640999473, 1.6738619050011039]]],
["so_pidigits",
[[1.186393894999128, 1.1833510090000345, 1.1735205620007036],
[1.1618239780000295, 1.1466504959989834, 1.128009963000295],
[1.1182356299996172, 1.1632011250003416, 1.1362772940010473],
[1.107688900001449, 1.1241363610006374, 1.1140436379992025],
[1.128270461998909, 1.139118449000307, 1.1090284120000433]]],
["so_random",
[[0.317847222000637, 0.35848786200040195, 0.3278361130014673],
[0.35831136900014826, 0.35687618399970233, 0.36264436899909924],
[0.3426302219995705, 0.3488985969997884, 0.36366021300091234],
[0.312154618999557, 0.3101769739987503, 0.3230691739991016],
[0.323134416999892, 0.3306380240010185, 0.3320193810013734]]],
["so_reverse_complement",
[[0.5489404689997173, 0.5404208580002887, 0.5462583740008995],
[0.5680135959992185, 0.5497708099992451, 0.5395834880000621],
[0.6021959359986795, 0.5516969010004686, 0.5328039040014119],
[0.5196672190013487, 0.562355188998481, 0.5638176230004319],
[0.5843735710004694, 0.5236466059996019, 0.5464601089988719]]],
["so_sieve",
[[0.4842971360012598, 0.5040317860002688, 0.5510640459997376],
[0.5387039269990055, 0.48529543000040576, 0.4990145820011094],
[0.5582072289998905, 0.5150585970004613, 0.5386602559992753],
[0.5062628030009364, 0.5450196470010269, 0.4803183030016953],
[0.4742865630014421, 0.48345261299982667, 0.5337589640002989]]],
["so_spectralnorm",
[[1.7904831409996405, 1.7761573030002182, 1.8563808070011873],
[1.7850994399996125, 1.8125653629995213, 1.7561759210002492],
[1.878547381998942, 1.9038954099996772, 1.8342162690005352],
[1.6627514379997592, 1.6737254840008973, 1.6937658000006195],
[1.8152416390003054, 1.841645762000553, 1.6931533690003562]]]]
Elapsed time: 516.706142 (sec)
-----------------------------------------------------------
benchmark results:
minimum results in each 3 measurements.
Execution time (sec)
name 2.6 2.4 2.5 mov ours
so_ackermann 0.455 0.500 0.469 0.501 0.435
so_array 0.958 0.907 0.954 0.767 0.837
so_binary_trees 5.581 5.571 5.700 5.676 5.277
so_concatenate 3.940 3.883 3.967 3.358 3.494
so_count_words 0.160 0.181 0.156 0.176 0.153
so_exception 0.247 0.264 0.273 0.259 0.233
so_fannkuch 1.034 1.043 1.025 1.017 0.976
so_fasta 1.535 1.463 1.507 1.424 1.485
so_k_nucleotide 1.165 1.242 1.199 1.100 1.114
so_lists 0.479 0.482 0.449 0.466 0.451
so_mandelbrot 2.242 2.394 2.349 2.097 2.211
so_matrix 0.534 0.551 0.537 0.464 0.479
so_meteor_contest 3.223 3.194 3.157 2.930 2.983
so_nbody 1.255 1.369 1.266 1.188 1.293
so_nested_loop 1.150 1.121 1.129 0.875 0.986
so_nsieve 1.610 1.622 1.657 1.672 1.631
so_nsieve_bits 2.232 2.252 2.224 2.069 2.086
so_object 0.700 0.697 0.706 0.630 0.645
so_partial_sums 1.547 1.789 1.706 1.502 1.590
so_pidigits 1.174 1.128 1.118 1.108 1.109
so_random 0.318 0.357 0.343 0.310 0.323
so_reverse_complement 0.540 0.540 0.533 0.520 0.524
so_sieve 0.484 0.485 0.515 0.480 0.474
so_spectralnorm 1.776 1.756 1.834 1.663 1.693
Speedup ratio: compare with the result of `2.6' (greater is better)
name 2.4 2.5 mov ours
so_ackermann 0.911 0.972 0.910 1.046
so_array 1.056 1.004 1.249 1.144
so_binary_trees 1.002 0.979 0.983 1.058
so_concatenate 1.015 0.993 1.173 1.128
so_count_words 0.887 1.028 0.908 1.046
so_exception 0.933 0.903 0.954 1.058
so_fannkuch 0.991 1.008 1.016 1.059
so_fasta 1.049 1.018 1.078 1.033
so_k_nucleotide 0.938 0.971 1.059 1.046
so_lists 0.993 1.067 1.029 1.061
so_mandelbrot 0.936 0.954 1.069 1.014
so_matrix 0.969 0.995 1.152 1.117
so_meteor_contest 1.009 1.021 1.100 1.081
so_nbody 0.917 0.991 1.056 0.971
so_nested_loop 1.026 1.018 1.315 1.166
so_nsieve 0.993 0.972 0.963 0.987
so_nsieve_bits 0.991 1.004 1.079 1.070
so_object 1.004 0.991 1.110 1.085
so_partial_sums 0.865 0.907 1.030 0.973
so_pidigits 1.040 1.049 1.059 1.058
so_random 0.891 0.928 1.025 0.984
so_reverse_complement 1.002 1.014 1.040 1.032
so_sieve 0.998 0.940 1.008 1.021
so_spectralnorm 1.011 0.968 1.068 1.049
Log file: bmlog-20180125-225613.88896.tsv
From 32ef51da53321aab69be1fe9d760c1b6f132b999 Mon Sep 17 00:00:00 2001
From: "Urabe, Shyouhei" <shyouhei@ruby-lang.org>
Date: Thu, 21 Dec 2017 13:56:40 +0900
Subject: [PATCH] move ADD_PC around to optimize PC manipluiations
This commit introduces new attribute handles_flame and if that is
_not_ the case, places ADD_PC right before INC_SP. This prevents
unnecessary PC manipulations for most opt_* instructions and as a
result, reduces the size of vm_exec_core from 27,184 bytes to
25,536 bytes.
Signed-off-by: Urabe, Shyouhei <shyouhei@ruby-lang.org>
---
insns.def | 3 +++
tool/ruby_vm/models/bare_instructions.rb | 13 ++++++++++---
tool/ruby_vm/views/_insn_entry.erb | 9 ++++++++-
3 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/insns.def b/insns.def
index 8f43e55b8a..cad686fee6 100644
--- a/insns.def
+++ b/insns.def
@@ -680,6 +680,7 @@ defineclass
(ID id, ISEQ class_iseq, rb_num_t flags)
(VALUE cbase, VALUE super)
(VALUE val)
+// attr bool handles_frame = true;
{
VALUE klass = vm_find_or_create_class_by_id(id, flags, cbase, super);
@@ -829,6 +830,7 @@ leave
()
(VALUE val)
(VALUE val)
+// attr bool handles_frame = true;
{
if (OPT_CHECKED_RUN) {
const VALUE *const bp = vm_base_ptr(reg_cfp);
@@ -1380,6 +1382,7 @@ opt_call_c_function
(rb_insn_func_t funcptr)
()
()
+// attr bool handles_frame = true;
{
reg_cfp = (funcptr)(ec, reg_cfp);
diff --git a/tool/ruby_vm/models/bare_instructions.rb b/tool/ruby_vm/models/bare_instructions.rb
index 16d5782e2f..5ed27520ea 100644
--- a/tool/ruby_vm/models/bare_instructions.rb
+++ b/tool/ruby_vm/models/bare_instructions.rb
@@ -33,6 +33,7 @@ def initialize opts = {}
h[a.key] = a
}
@attrs_orig = @attrs.dup
+ predefine_attributes
end
def pretty_name
@@ -109,8 +110,8 @@ def operands_info
}.join
end
- def pushs_frame?
- opes.any? {|o| /CALL_INFO/ =~ o[:type] }
+ def handles_frame?
+ /\b(false|0)\b/ !~ @attrs['handles_frame'].expr.expr
end
def inspect
@@ -126,7 +127,13 @@ def generate_attribute k, t, v
type: t, \
location: [], \
expr: v.to_s + ';'
- return @attrs[k] = attr
+ return @attrs[k] ||= attr
+ end
+
+ def predefine_attributes
+ generate_attribute 'sp_inc', 'rb_snum_t', rets.size - pops.size
+ generate_attribute 'handles_frame', 'bool', \
+ opes.any? {|o| /CALL_INFO/ =~ o[:type] }
end
def typesplit a
diff --git a/tool/ruby_vm/views/_insn_entry.erb b/tool/ruby_vm/views/_insn_entry.erb
index cebca8b8d0..c0199c5463 100644
--- a/tool/ruby_vm/views/_insn_entry.erb
+++ b/tool/ruby_vm/views/_insn_entry.erb
@@ -9,6 +9,7 @@
/* insn <%= insn.pretty_name %> */
#define NAME_OF_CURRENT_INSN <%= insn.name %>
+#define WIDTH_OF_CURRENT_INSN <%= insn.width %>
INSN_ENTRY(<%= insn.name %>)
{
% unless insn.declarations.empty?
@@ -28,8 +29,9 @@ INSN_ENTRY(<%= insn.name %>)
<%= pop[:name] %> = <%= insn.cast_from_VALUE pop, "TOPN(#{i})"%>;
% end
DEBUG_ENTER_INSN(<%=cstr insn.name %>);
+% if insn.handles_frame?
ADD_PC(<%= insn.width %>);
- PREFETCH(GET_PC());
+% end
% unless insn.pops.empty?
POPN(<%= insn.pops.size %>);
% end
@@ -38,6 +40,10 @@ INSN_ENTRY(<%= insn.name %>)
COLLECT_USAGE_OPERAND(<%= insn.bin %>, <%= i %>, <%= ope[:name] %>);
% end
<%= render_c_expr insn.expr -%>
+% unless insn.handles_frame?
+ ADD_PC(<%= insn.width %>);
+ PREFETCH(GET_PC());
+% end
% unless insn.rets.empty?
CHECK_VM_STACK_OVERFLOW_FOR_INSN(VM_REG_CFP, <%= insn.rets.size %>);
% insn.rets.each_with_index do |ret, i|
@@ -47,4 +53,5 @@ INSN_ENTRY(<%= insn.name %>)
%
END_INSN(<%= insn.name %>);
}
+#undef WIDTH_OF_CURRENT_INSN
#undef NAME_OF_CURRENT_INSN
--
2.15.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment