A sequence implemented as a linked list of arrays.
This data structure is similar to the List but it can benefit from
better cache performance, lower data overhead for the nodes metadata and
it spares the GC to allocate many small nodes.
more_collections :: UnrolledList :: nodes_length
Desired capacity for each nodesmore_collections :: UnrolledList :: nodes_length=
Desired capacity for each nodesmore_collections $ UnrolledList :: SELF
Type of this instance, automatically specialized in every classmore_collections $ UnrolledList :: []
Return the index-th element of the sequence.more_collections $ UnrolledList :: core_serialize_to
Actual serialization ofself to serializer
			more_collections $ UnrolledList :: from_deserializer
Create an instance of this class from thedeserializer
			more_collections $ UnrolledList :: insert
Insert an element at a given position, following elements are shifted.more_collections $ UnrolledList :: iterator
Get a new iterator on the collection.more_collections $ UnrolledList :: remove_at
Remove the item atindex and shift all following elements
			more_collections $ UnrolledList :: unshift
Add an item before the first one.core :: Collection :: CONCURRENT
Type of the concurrent variant of this collectionserialization :: Serializable :: accept_json_serializer
Refinable service to customize the serialization of this class to JSONserialization :: Serializable :: accept_msgpack_attribute_counter
Hook to customize the behavior of theAttributeCounter
			serialization :: Serializable :: accept_msgpack_serializer
Hook to customize the serialization of this class to MessagePackserialization :: Serializable :: add_to_bundle
Called by[]= to dynamically choose the appropriate method according
			core :: Object :: class_factory
Implementation used byget_class to create the specific class.
			core :: Collection :: combinations
Allr-length combinations on self (in same order) without repeated elements.
			core :: Collection :: combinations_with_replacement
Allr-length combination on self (in same order) with repeated elements.
			serialization :: Serializable :: core_serialize_to
Actual serialization ofself to serializer
			core :: SimpleCollection :: defaultinit
core :: Sequence :: defaultinit
core :: Object :: defaultinit
core :: Collection :: defaultinit
core :: SequenceRead :: defaultinit
serialization :: Serializable :: from_deserializer
Create an instance of this class from thedeserializer
			core :: SequenceRead :: get_or_default
Try to get an element, returndefault if the index is invalid.
			core :: SequenceRead :: get_or_null
Try to get an element, returnnull if the index is invalid.
			core :: Collection :: has_all
Does the collection contain at least each element ofother?
			core :: Collection :: has_any
Does the collection contain at least one element ofother?
			core :: Collection :: has_exactly
Does the collection contain exactly all the elements ofother?
			core :: SequenceRead :: index_of_from
The index of the first occurrence ofitem, starting from pos.
			core :: Sequence :: insert_all
Insert all elements at a given position, following elements are shifted.core :: Object :: is_same_instance
Return true ifself and other are the same instance (i.e. same identity).
			core :: Object :: is_same_serialized
Isself the same as other in a serialization context?
			core :: Object :: is_same_type
Return true ifself and other have the same dynamic type.
			core :: SequenceRead :: iterator_from
Gets a new Iterator starting at positionpos
			core :: SequenceRead :: last_index_of
The index of the last occurrence ofitem.
			core :: SequenceRead :: last_index_of_from
The index of the last occurrence ofitem starting from pos and decrementing.
			core :: SequenceRead :: modulo_index
Returns the real index for a modulo index.serialization :: Serializable :: msgpack_extra_array_items
Hook to request a larger than usual metadata arraymore_collections :: UnrolledList :: nodes_length
Desired capacity for each nodesmore_collections :: UnrolledList :: nodes_length=
Desired capacity for each nodescore :: Object :: output_class_name
Display class name on stdout (debug only).core :: Collection :: permutations
Allr-length permutations on self (all possible ordering) without repeated elements.
			core :: Collection :: product
Cartesian product, overr times self.
			core :: RemovableCollection :: remove
Remove an occurrence ofitem
			core :: RemovableCollection :: remove_all
Remove all occurrences ofitem
			core :: SequenceRead :: reverse_iterator
Gets an iterator starting at the end and going backwardscore :: SequenceRead :: reverse_iterator_from
Gets an iterator on the chars of self starting frompos
			serialization :: Serializable :: serialize_msgpack
Serializeself to MessagePack bytes
			serialization :: Serializable :: serialize_to
Serializeself to serializer
			serialization :: Serializable :: serialize_to_json
Serializeself to JSON
			core :: Collection :: to_concurrent
Wrapsself in a thread-safe collection
			core :: Collection :: to_counter
Create and fill up a counter with the elements of `self.core :: Collection :: to_curlslist
Convert Collection[String] to CURLSListserialization :: Serializable :: to_pretty_json
Serializeself to plain pretty JSON
			core :: Collection :: to_shuffle
Return a new array made of elements in a random order.Serializer::serialize
			
# An unrolled linked list
#
# A sequence implemented as a linked list of arrays.
#
# This data structure is similar to the `List` but it can benefit from
# better cache performance, lower data overhead for the nodes metadata and
# it spares the GC to allocate many small nodes.
class UnrolledList[E]
	super Sequence[E]
	# Desired capacity for each nodes
	#
	# By default at `32`, it can be increased for very large lists.
	#
	# It can be modified anytime, but newly created nodes may still be assigned
	# the same capacity of old nodes when created by `insert`.
	var nodes_length = 32 is writable
	private var head_node: UnrolledNode[E] = new UnrolledNode[E](nodes_length)
	private var tail_node: UnrolledNode[E] = head_node
	redef var length = 0
	redef fun clear
	do
		head_node = new UnrolledNode[E](nodes_length)
		tail_node = head_node
		length = 0
	end
	# Out parameter of `node_at`
	private var index_within_node = 0
	private fun node_at(index: Int): UnrolledNode[E]
	do
		assert index >= 0 and index < length
		var node = head_node
		while index >= node.length do
			index -= node.length
			node = node.next.as(not null)
		end
		index_within_node = index
		return node
	end
	private fun insert_node(node: UnrolledNode[E], prev, next: nullable UnrolledNode[E])
	do
		if prev != null then
			prev.next = node
		else head_node = node
		if next != null then
			next.prev = node
		else tail_node = node
		node.next = next
		node.prev = prev
	end
	redef fun [](index)
	do
		var node = node_at(index)
		index = index_within_node + node.head_index
		return node.items[index]
	end
	redef fun []=(index, value)
	do
		var node = node_at(index)
		index = index_within_node + node.head_index
		node.items[index] = value
	end
	redef fun push(item)
	do
		var node = tail_node
		if not node.full then
			if node.tail_index < node.capacity then
				# There's room at the tail
				node.tail_index += 1
			else
				# Move everything over by `d`
				assert node.head_index > 0
				var d = node.head_index / 2 + 1
				node.move_head(node.length, d)
				for i in d.times do node.items[node.tail_index - i] = null
				node.head_index -= d
				node.tail_index += -d+1
			end
			node.items[node.tail_index-1] = item
		else
			# New node!
			node = new UnrolledNode[E](nodes_length)
			insert_node(node, tail_node, null)
			node.tail_index = 1
			node.items[0] = item
		end
		length += 1
	end
	redef fun unshift(item)
	do
		var node = head_node
		if not node.full then
			if node.head_index > 0 then
				# There's room at the head
				node.head_index -= 1
			else
				# Move everything over by `d`
				assert node.tail_index < node.capacity
				var d = (node.capacity-node.tail_index) / 2 + 1
				node.move_tail(0, d)
				for i in d.times do node.items[node.head_index+i] = null
				node.head_index += d-1
				node.tail_index += d
			end
			node.items[node.head_index] = item
		else
			# New node!
			node = new UnrolledNode[E](nodes_length)
			insert_node(node, null, head_node)
			node.head_index = node.capacity-1
			node.tail_index = node.capacity
			node.items[node.capacity-1] = item
		end
		length += 1
	end
	redef fun pop
	do
		assert not_empty
		var node = tail_node
		while node.length == 0 do
			# Delete empty node
			var nullable_node = node.prev
			assert is_not_empty: nullable_node != null
			node = nullable_node
			node.next = null
			self.tail_node = node
		end
		var item = node.items[node.tail_index-1]
		node.tail_index -= 1
		length -= 1
		return item
	end
	redef fun shift
	do
		assert not_empty
		var node = head_node
		while node.length == 0 do
			# Delete empty node
			var nullable_node = node.next
			assert is_not_empty: nullable_node != null
			node = nullable_node
			node.prev = null
			self.head_node = node
		end
		var item = node.items[node.head_index]
		node.head_index += 1
		length -= 1
		return item
	end
	redef fun insert(item, index)
	do
		if index == length then
			push item
			return
		end
		var node = node_at(index)
		index = index_within_node
		if node.full then
			# Move half to a new node
			var new_node = new UnrolledNode[E](nodes_length.max(node.capacity))
			# Plug in the new node
			var next_node = node.next
			insert_node(new_node, node, next_node)
			# Move items at and after `index` to the new node
			var to_displace = node.length-index
			var offset = (new_node.capacity-to_displace)/2
			for i in [0..to_displace[ do
				new_node.items[offset+i] = node.items[index+i]
				node.items[index+i] = null
			end
			new_node.head_index = offset
			new_node.tail_index = offset + to_displace
			node.tail_index -= to_displace
			# Store `item`
			if index > node.capacity / 2 then
				new_node.items[offset-1] = item
				new_node.head_index -= 1
			else
				node.items[node.head_index+index] = item
				node.tail_index += 1
			end
		else
			if node.tail_index < node.capacity then
				# Move items towards the tail
				node.move_tail(index, 1)
				node.tail_index += 1
				node.items[node.head_index + index] = item
			else
				# Move items towards the head
				node.move_head(index, 1)
				node.items[node.head_index + index-1] = item
				node.head_index -= 1
			end
		end
		length += 1
	end
	redef fun remove_at(index)
	do
		var node = node_at(index)
		index = index_within_node + node.head_index
		# Shift left all the elements after `index`
		for i in [index+1 .. node.tail_index[ do
			node.items[i-1] = node.items[i]
		end
		node.tail_index -= 1
		node.items[node.tail_index] = null
		length -= 1
		var next_node = node.next
		var prev_node = node.prev
		if node.is_empty and (next_node != null or prev_node != null) then
			# Empty and non-head or tail node, delete
			if next_node != null then
				next_node.prev = node.prev
			else tail_node = prev_node.as(not null)
			if prev_node != null then
				prev_node.next = node.next
			else head_node = next_node.as(not null)
		end
	end
	redef fun iterator do return new UnrolledIterator[E](self)
end
					lib/more_collections/more_collections.nit:351,1--603,3