core/array_mirror.rb
module Rubinius
class Mirror
class Array < Mirror
self.subject = ::Array
def self.reflect(object)
m = super(object)
if Rubinius::Type.object_kind_of? m.object, ::Array
m
elsif ary = Rubinius::Type.try_convert(m.object, ::Array, :to_ary)
super(ary)
else
message = "expected Array, given #{Rubinius::Type.object_class(object)}"
raise TypeError, message
end
end
# TODO: implement mirror_attribute :name
def total
Rubinius.invoke_primitive :object_get_ivar, @object, :@total
end
def total=(value)
Rubinius.invoke_primitive :object_set_ivar, @object, :@total, value
end
def tuple
Rubinius.invoke_primitive :object_get_ivar, @object, :@tuple
end
def tuple=(value)
Rubinius.invoke_primitive :object_set_ivar, @object, :@tuple, value
end
def start
Rubinius.invoke_primitive :object_get_ivar, @object, :@start
end
def start=(value)
Rubinius.invoke_primitive :object_set_ivar, @object, :@start, value
end
# Implementation based on the binomial_coefficient
# implemented on MRI array.c.
def binomial_coefficient(comb, size)
comb = size-comb if (comb > size-comb)
return 0 if comb < 0
descending_factorial(size, comb) / descending_factorial(comb, comb)
end
# Implementation based on the rb_ary_combination_size
# implemented on MRI array.c.
def combination_size(num)
binomial_coefficient(num, @object.size)
end
# Implementation based on the descending_factorial
# implemented on MRI array.c.
# Comment from there:
# Returns the product of from, from-1, ..., from - how_many + 1.
# http://en.wikipedia.org/wiki/Pochhammer_symbol
def descending_factorial(from, how_many)
cnt = how_many >= 0 ? 1 : 0
while (how_many) > 0
cnt = cnt*(from)
from -= 1
how_many -= 1
end
cnt
end
# Implementation based on the rb_ary_permutation_size
# implemented on MRI array.c.
def permutation_size(num)
n = @object.size
if undefined.equal? num
k = @object.size
else
k = Rubinius::Type.coerce_to_collection_index num
end
descending_factorial(n, k)
end
def repeated_combination_size(combination_size)
return 1 if combination_size == 0
return binomial_coefficient(combination_size, @object.size + combination_size - 1)
end
def repeated_permutation_size(combination_size)
return 0 if combination_size < 0
@object.size ** combination_size
end
end
end
end