local one_over_log2 = 1.0 / math.log(2) function bit.lsb(v) local k = bit.band(v, bit.bnot(v-1)) return math.log(k) * one_over_log2 end local math_floor = math.floor local dummy = {rotate = 0, mask = 0} local get_absolute_offset = function(self, size, offset) local block_rotate_size = 1 local block_start_offset = 0 for level=1,30 do local rotate = (self[level] or dummy).rotate offset = offset + rotate * block_rotate_size -- Return if this offset is inside this block if offset - block_start_offset < block_rotate_size * size then return offset end block_rotate_size = block_rotate_size * size block_start_offset = block_start_offset + block_rotate_size end end amt_queue = {} local metatable = { __index = amt_queue } local zero_schedule = {0} function amt_queue.new(size) size = size or 30 assert(size <= 30, tostring(size).." exceeds maximum amt_queue size of 30") local pc = {size = size, mask = 0} setmetatable(pc, metatable) return pc end function amt_queue.insert(self, item, offset) local size = self.size offset = get_absolute_offset(self, size, offset) local schedule if offset == 0 then schedule = zero_schedule else schedule = {} local first = true while offset > 0 do if not first then offset = offset - 1 end first = false schedule[#schedule + 1] = offset % size offset = math_floor(offset / size) end end local section = self[#schedule] or {rotate = 0, mask = 0} self[#schedule] = section self.mask = bit.bor(self.mask, bit.lshift(1,#schedule - 1)) for i=#schedule,2,-1 do local s = schedule[i] local next_section = section[s] or {rotate = 0, mask = 0} section[s] = next_section section.mask = bit.bor(section.mask, bit.lshift(1,s)) section = next_section end local s = schedule[1] local next_item = section[s] item.next = next_item if next_item then item.last = next_item.last --next_item.prev = item else item.last = item end section.mask = bit.bor(section.mask, bit.lshift(1,s)) section[s] = item end local function pop_from_level(self, level) local level_table = self[level] or {rotate = 0, mask = 0} local offset = level_table.rotate local res = level_table[offset] level_table[offset] = nil level_table.mask = bit.band(level_table.mask, bit.bnot(bit.lshift(1,offset))) level_table.rotate = offset + 1 self[level] = level_table local level_bit = bit.lshift(1, level - 1) if level_table.mask == 0 then self.mask = bit.band(self.mask, bit.bnot(level_bit)) else self.mask = bit.bor(self.mask, level_bit) end if offset == self.size - 1 then self[level] = pop_from_level(self, level+1) end return res end function amt_queue.pop(self) return pop_from_level(self, 1) end local function has_items(self) return self.mask ~= 0 end amt_queue.has_items = has_items function amt_queue.advance_to_next(self) if self.mask == 0 then return end local level = bit.lsb(self.mask) + 1 local level_table = self[level] or dummy level_table.rotate = bit.lsb(level_table.mask) for i = (level-1),1,-1 do level_table = self[i] if level_table then level_table.rotate = self.size - 1 else self[i] = {mask = 0, rotate = self.size - 1} end local new_level_table = pop_from_level(self, i+1) if new_level_table then new_level_table.rotate = bit.lsb(new_level_table.mask) end self[i] = new_level_table end end return amt_queue