=begin

	MetaRuby
	file: BitArray (sample for HollowArray usage)

	Copyright (c) 2001 by Mathieu Bouchard
	Licensed under the same license as Ruby.
=end

require "Hollow/Array"

# usage: BitArray.new(n,chunksize=28)

# values other than 0 and 1 are converted:
# nil,false,0.0 become 0, others become 1

# inserting/deleting is faster when the difference in the number of elements
# is a multiple of chunksize.

module BitArrayImpl

	def initialize(n=0,chunksize=3)
		@length = 0
		raise ArgumentError "chunksize too small" if chunksize < 1
		@chunksize = chunksize
		@array = []
		super(n)
	end

	attr_reader :chunksize
	def t; @array; end

	def length; @length; end

	def get(i)
		@array[i/chunksize][i%chunksize]
	end

	# this could be faster
	def get_seq(i,n); (i...i+n).map {|x| get x }; end

	def put(i,v)
		v = Numeric===v ? (v.to_i != 0 ? 1 : 0) : (v ? 1 : 0)
		mask = 1 << (i%@chunksize)
		@array[i/@chunksize] = (@array[i/@chunksize] & ~mask) | ((-v) & mask)
		nil
	end

	def put_seq(i,n,v)
		diff = v.length-n

	# slow working version:

		top = length-1
		@length += diff if diff > 0
		@array << 0 while @array.length*@chunksize < @length
		if diff > 0 then
			top.downto(i)     {|x| put x+diff, get x }
		else
			(i+n).upto(top)   {|x| put x+diff, get x }
		end
		v.each_with_index {|a,x| put i+x,a }
		@length += diff if diff < 0
		return nil

	# fast buggy version:

=begin
		#!@#$ bugs when v.length > n ?
		#!@#$ bugs when v.length < n ?
		# step 1: insert #{bit_off} dummy elements
		bit_off = diff % @chunksize
		if bit_off != 0 then
			@array << 0
			(@array.length-1).downto(i/@chunksize) {|x|
				@array[x] = (@array[x] << bit_off) |
					(@array[x-1] >> (@chunksize-bit_off))
			}
		end

		# step 2: insert #{cell_off} dummy elements
		cell_off = (diff+@chunksize-1) / @chunksize
		@array[i/@chunksize,0] = [@array[i/@chunksize]]*cell_off

		# step 3: update length
		@length += v.length-n
		size = (@length+@chunksize-1)/@chunksize
		@array[size, @array.length-size] = []

		# step 4: write new elements
		v.each_with_index {|a,j| put i+j,a }

		return nil
=end
	end

	def dup
		foo = type.new(0,chunksize).replace(self)
		foo.taint if tainted?
		foo
	end
end

class BitArray

	class<<self; def [](*v); new.replace v; end; end

	include HollowArray
	include BitArrayImpl
	include SimpleArrayP::Contract # for safety
end

=begin
$a = BitArray.new
$a[0,0]=[0,1,1,0,1,0,0,1]
p $a
$a[0,0]=[0,0,0,0]
p $a
$a[3..7]=[]
p $a
=end
