Exemplo n.º 1
0
    def shuffle_evict(self, leaf):
        """ Evict using oblivious shuffling etc """
        evict_debug = False
        levels = [None] * len(self.temp_storage)

        bucket_sizes = Array(self.D + 2, cint)
        for i in range(self.D + 2):
            bucket_sizes[i] = regint(0)

        Program.prog.curr_tape.start_new_basicblock()
        leaf = self.state.read().reveal()

        if evict_debug:
            print_ln('\tEviction leaf: %s', leaf)

        for i,(entry, depth) in enumerate(zip(self.temp_storage, self.temp_levels)):
            lca_lev, cbits = self.compute_lca(entry.x[0], leaf, 1 - entry.empty())

            level_bits = self.adjust_lca(cbits, depth, 1 - entry.empty())
            # last bit indicates stash
            levels[i] = [sum(level_bits[j]*j for j in range(self.D+2)), level_bits[-1]]

            if evict_debug:
                @if_(1 - entry.empty().reveal())
                def f():
                    print_ln('entry (%s, %s) going to level %s', entry.v.reveal(), entry.x[0].reveal(), levels[i][0].reveal())
                    print_ln('%s ' * len(level_bits), *[b.reveal() for b in level_bits])
        if evict_debug:
            print_ln("")
        
        # sort entries+levels by emptiness: buckets already sorted so just perform a
        # sequence of merges on these and the stash
        buckets = [[[self.temp_storage[j]] + levels[j] for j in range(self.bucket_size*i,self.bucket_size*(i+1))] for i in range(self.D+1)]
        stash = [None] * (self.stash_capacity)
        
        for i in range(self.stash_capacity):
            j = i+self.bucket_size*(self.D+1)
            stash[i] = [self.temp_storage[j]] + levels[j]

        merged_entries = buckets + [stash]
        
        merged_entries = [m for sl in merged_entries for m in sl]
        me_len = len(merged_entries)
        while len(merged_entries) & (len(merged_entries)-1) != 0:
            merged_entries.append(None)
        # sort taking into account stash etc. (GF(2^n) ONLY atm)
        permutation.odd_even_merge_sort(merged_entries, lambda a,b: a[0].empty() * (a[-1] - 1 + b[-1]) + 1 - a[-1])
        
        merged_entries = merged_entries[:me_len]

        # and sort assigned positions by emptiness (non-empty first)
        empty_bits_and_levels = [[0]*self.bucket_size for i in range(self.D+1)]
        stash_bits = 0

        if evict_debug:
            print_str('Size bits: ')

        # convert bucket size bits to bits flagging emptiness for each position
        for j in range(self.D+1):
            s = self.size_bits[j]
            #for b in s:
            #    b.reveal().print_reg('u%d' % j)
            if self.bucket_size == 4:
                c = s[0]*s[1]
                if self.value_type == sgf2n:
                    empty_bits_and_levels[j][0] = [1 - self.value_type.bit_type(s[0] + s[1] + s[2] + c), self.value_type.clear_type(j)]
                    empty_bits_and_levels[j][1] = [1 - self.value_type.bit_type(s[1] + s[2]), self.value_type.clear_type(j)]
                    empty_bits_and_levels[j][2] = [1 - self.value_type.bit_type(c + s[2]), self.value_type.clear_type(j)]
                    empty_bits_and_levels[j][3] = [1 - self.value_type.bit_type(s[2]), self.value_type.clear_type(j)]
                else:
                    empty_bits_and_levels[j][0] = [1 - self.value_type.bit_type(s[0] + s[1] - c + s[2]), self.value_type.clear_type(j)]
                    empty_bits_and_levels[j][1] = [1 - self.value_type.bit_type(s[1] + s[2]), self.value_type.clear_type(j)]
                    empty_bits_and_levels[j][2] = [1 - self.value_type.bit_type(c + s[2]), self.value_type.clear_type(j)]
                    empty_bits_and_levels[j][3] = [1 - self.value_type.bit_type(s[2]), self.value_type.clear_type(j)]
            elif self.bucket_size == 2:
                if evict_debug:
                    print_str('%s,%s,', s[0].reveal(), s[1].reveal())
                empty_bits_and_levels[j][0] = [1 - self.value_type.bit_type(s[0] + s[1]), self.value_type.clear_type(j)]
                empty_bits_and_levels[j][1] = [1 - self.value_type.bit_type(s[1]), self.value_type.clear_type(j)]
            elif self.bucket_size == 3:
                c = s[0]*s[1]
                empty_bits_and_levels[j][0] = [1 - self.value_type.bit_type(s[0] + s[1] - c), self.value_type.clear_type(j)]
                empty_bits_and_levels[j][1] = [1 - self.value_type.bit_type(s[1]), self.value_type.clear_type(j)]
                empty_bits_and_levels[j][2] = [1 - self.value_type.bit_type(c), self.value_type.clear_type(j)]

        if evict_debug:
            print_ln()

        empty_bits_and_levels = [x for sl in empty_bits_and_levels for x in sl]
        while len(empty_bits_and_levels) & (len(empty_bits_and_levels)-1) != 0:
            empty_bits_and_levels.append(None)

        permutation.odd_even_merge_sort(empty_bits_and_levels, permutation.bitwise_list_comparator)

        empty_bits_and_levels = [e for e in empty_bits_and_levels if e is not None]

        # assign levels to empty positions
        stash_level = self.value_type.clear_type(self.D + 1)


        if evict_debug:
            print_ln('Bits and levels: ')
        for i, entrylev in enumerate(merged_entries):
            entry = entrylev[0]
            level = entrylev[1]

            if i < len(empty_bits_and_levels):
                new_level = (empty_bits_and_levels[i][1] - level) * entry.empty() + level
                if evict_debug:
                    print_ln('\t(empty pos %s, entry %s: empty lev %s, entry %s: new %s)', empty_bits_and_levels[i][0].reveal(), entry.empty().reveal(),
                        empty_bits_and_levels[i][1].reveal(), level.reveal(), new_level.reveal())
            else:
                new_level = level + stash_level * entry.empty()
                if evict_debug:
                    print_ln('\t(entry %s: level %s: new %s)', entry.empty().reveal(),
                        level.reveal(), new_level.reveal())
            merged_entries[i] = [entry, new_level]
        if evict_debug:
            print_ln()
        
        # shuffle entries and levels
        while len(merged_entries) & (len(merged_entries)-1) != 0:
            merged_entries.append(None) #self.root.bucket.empty_entry(False))
        permutation.rec_shuffle(merged_entries, value_type=self.value_type)
        merged_entries = [e for e in merged_entries if e is not None]

        # need to copy entries/levels to memory for re-positioning
        entries_ram = RAM(self.temp_size, self.entry_type, self.get_array)
        levels_array = Array(self.temp_size, cint)
        
        for i,entrylev in enumerate(merged_entries):
            if entrylev is not None:
                entries_ram[i] = entrylev[0]
                levels_array[i] = entrylev[1].reveal()
        Program.prog.curr_tape.start_new_basicblock()

        # reveal shuffled levels
        @for_range(self.temp_size)
        def f(i):
            level = regint(levels_array[i])
            sz = regint(bucket_sizes[level])
            self.temp_storage[level*self.bucket_size + sz] = entries_ram[i]
            bucket_sizes[level] += 1

        if evict_debug:
            for i in range(self.D+1):
                @if_(bucket_sizes[i] != self.bucket_size)
                def f():
                    print_str('Sizes: ')
                    for i in range(self.D+2):
                        print_str('%s,', bucket_sizes[i])
                    print_ln()
                    runtime_error('Incorrect bucket sizes')

        Program.prog.curr_tape.start_new_basicblock()
        for i, ram_indices in enumerate(self.bucket_indices_on_path_to(leaf)):
            for j, ram_index in enumerate(ram_indices):
                self.buckets[ram_index] = self.temp_storage[i*self.bucket_size + j]
        for i in range(self.stash_capacity):
            self.stash.ram[i] = self.temp_storage[i + (self.D+1)*self.bucket_size]
Exemplo n.º 2
0
    def shuffle_evict(self, leaf):
        """ Evict using oblivious shuffling etc """
        evict_debug = False
        levels = [None] * len(self.temp_storage)

        bucket_sizes = Array(self.D + 2, cint)
        for i in range(self.D + 2):
            bucket_sizes[i] = regint(0)

        Program.prog.curr_tape.start_new_basicblock()
        leaf = self.state.read().reveal()

        if evict_debug:
            print_ln('\tEviction leaf: %s', leaf)

        for i, (entry,
                depth) in enumerate(zip(self.temp_storage, self.temp_levels)):
            lca_lev, cbits = self.compute_lca(entry.x[0], leaf,
                                              1 - entry.empty())

            level_bits = self.adjust_lca(cbits, depth, 1 - entry.empty())
            # last bit indicates stash
            levels[i] = [
                sum(level_bits[j] * j for j in range(self.D + 2)),
                level_bits[-1]
            ]

            if evict_debug:

                @if_(1 - entry.empty().reveal())
                def f():
                    print_ln('entry (%s, %s) going to level %s',
                             entry.v.reveal(), entry.x[0].reveal(),
                             levels[i][0].reveal())
                    print_ln('%s ' * len(level_bits),
                             *[b.reveal() for b in level_bits])

        if evict_debug:
            print_ln("")

        # sort entries+levels by emptiness: buckets already sorted so just perform a
        # sequence of merges on these and the stash
        buckets = [[[self.temp_storage[j]] + levels[j]
                    for j in range(self.bucket_size *
                                   i, self.bucket_size * (i + 1))]
                   for i in range(self.D + 1)]
        stash = [None] * (self.stash_capacity)

        for i in range(self.stash_capacity):
            j = i + self.bucket_size * (self.D + 1)
            stash[i] = [self.temp_storage[j]] + levels[j]

        merged_entries = buckets + [stash]

        merged_entries = [m for sl in merged_entries for m in sl]
        me_len = len(merged_entries)
        while len(merged_entries) & (len(merged_entries) - 1) != 0:
            merged_entries.append(None)
        # sort taking into account stash etc. (GF(2^n) ONLY atm)
        permutation.odd_even_merge_sort(
            merged_entries, lambda a, b: a[0].empty() *
            (a[-1] - 1 + b[-1]) + 1 - a[-1])

        merged_entries = merged_entries[:me_len]

        # and sort assigned positions by emptiness (non-empty first)
        empty_bits_and_levels = [[0] * self.bucket_size
                                 for i in range(self.D + 1)]
        stash_bits = 0

        if evict_debug:
            print_str('Size bits: ')

        # convert bucket size bits to bits flagging emptiness for each position
        for j in range(self.D + 1):
            s = self.size_bits[j]
            #for b in s:
            #    b.reveal().print_reg('u%d' % j)
            if self.bucket_size == 4:
                c = s[0] * s[1]
                if self.value_type == sgf2n:
                    empty_bits_and_levels[j][0] = [
                        1 - self.value_type.bit_type(s[0] + s[1] + s[2] + c),
                        self.value_type.clear_type(j)
                    ]
                    empty_bits_and_levels[j][1] = [
                        1 - self.value_type.bit_type(s[1] + s[2]),
                        self.value_type.clear_type(j)
                    ]
                    empty_bits_and_levels[j][2] = [
                        1 - self.value_type.bit_type(c + s[2]),
                        self.value_type.clear_type(j)
                    ]
                    empty_bits_and_levels[j][3] = [
                        1 - self.value_type.bit_type(s[2]),
                        self.value_type.clear_type(j)
                    ]
                else:
                    empty_bits_and_levels[j][0] = [
                        1 - self.value_type.bit_type(s[0] + s[1] - c + s[2]),
                        self.value_type.clear_type(j)
                    ]
                    empty_bits_and_levels[j][1] = [
                        1 - self.value_type.bit_type(s[1] + s[2]),
                        self.value_type.clear_type(j)
                    ]
                    empty_bits_and_levels[j][2] = [
                        1 - self.value_type.bit_type(c + s[2]),
                        self.value_type.clear_type(j)
                    ]
                    empty_bits_and_levels[j][3] = [
                        1 - self.value_type.bit_type(s[2]),
                        self.value_type.clear_type(j)
                    ]
            elif self.bucket_size == 2:
                if evict_debug:
                    print_str('%s,%s,', s[0].reveal(), s[1].reveal())
                empty_bits_and_levels[j][0] = [
                    1 - self.value_type.bit_type(s[0] + s[1]),
                    self.value_type.clear_type(j)
                ]
                empty_bits_and_levels[j][1] = [
                    1 - self.value_type.bit_type(s[1]),
                    self.value_type.clear_type(j)
                ]
            elif self.bucket_size == 3:
                c = s[0] * s[1]
                empty_bits_and_levels[j][0] = [
                    1 - self.value_type.bit_type(s[0] + s[1] - c),
                    self.value_type.clear_type(j)
                ]
                empty_bits_and_levels[j][1] = [
                    1 - self.value_type.bit_type(s[1]),
                    self.value_type.clear_type(j)
                ]
                empty_bits_and_levels[j][2] = [
                    1 - self.value_type.bit_type(c),
                    self.value_type.clear_type(j)
                ]

        if evict_debug:
            print_ln()

        empty_bits_and_levels = [x for sl in empty_bits_and_levels for x in sl]
        while len(empty_bits_and_levels) & (len(empty_bits_and_levels) -
                                            1) != 0:
            empty_bits_and_levels.append(None)

        permutation.odd_even_merge_sort(empty_bits_and_levels,
                                        permutation.bitwise_list_comparator)

        empty_bits_and_levels = [
            e for e in empty_bits_and_levels if e is not None
        ]

        # assign levels to empty positions
        stash_level = self.value_type.clear_type(self.D + 1)

        if evict_debug:
            print_ln('Bits and levels: ')
        for i, entrylev in enumerate(merged_entries):
            entry = entrylev[0]
            level = entrylev[1]

            if i < len(empty_bits_and_levels):
                new_level = (empty_bits_and_levels[i][1] -
                             level) * entry.empty() + level
                if evict_debug:
                    print_ln(
                        '\t(empty pos %s, entry %s: empty lev %s, entry %s: new %s)',
                        empty_bits_and_levels[i][0].reveal(),
                        entry.empty().reveal(),
                        empty_bits_and_levels[i][1].reveal(), level.reveal(),
                        new_level.reveal())
            else:
                new_level = level + stash_level * entry.empty()
                if evict_debug:
                    print_ln('\t(entry %s: level %s: new %s)',
                             entry.empty().reveal(), level.reveal(),
                             new_level.reveal())
            merged_entries[i] = [entry, new_level]
        if evict_debug:
            print_ln()

        # shuffle entries and levels
        while len(merged_entries) & (len(merged_entries) - 1) != 0:
            merged_entries.append(None)  #self.root.bucket.empty_entry(False))
        permutation.rec_shuffle(merged_entries, value_type=self.value_type)
        merged_entries = [e for e in merged_entries if e is not None]

        # need to copy entries/levels to memory for re-positioning
        entries_ram = RAM(self.temp_size, self.entry_type)
        levels_array = Array(self.temp_size, cint)

        for i, entrylev in enumerate(merged_entries):
            if entrylev is not None:
                entries_ram[i] = entrylev[0]
                levels_array[i] = entrylev[1].reveal()
        Program.prog.curr_tape.start_new_basicblock()

        # reveal shuffled levels
        @for_range(self.temp_size)
        def f(i):
            level = regint(levels_array[i])
            sz = regint(bucket_sizes[level])
            self.temp_storage[level * self.bucket_size + sz] = entries_ram[i]
            bucket_sizes[level] += 1

        if evict_debug:
            for i in range(self.D + 1):

                @if_(bucket_sizes[i] != self.bucket_size)
                def f():
                    print_str('Sizes: ')
                    for i in range(self.D + 2):
                        print_str('%s,', bucket_sizes[i])
                    print_ln()
                    runtime_error('Incorrect bucket sizes')

        Program.prog.curr_tape.start_new_basicblock()
        for i, ram_indices in enumerate(self.bucket_indices_on_path_to(leaf)):
            for j, ram_index in enumerate(ram_indices):
                self.buckets[ram_index] = self.temp_storage[i *
                                                            self.bucket_size +
                                                            j]
        for i in range(self.stash_capacity):
            self.stash.ram[i] = self.temp_storage[i + (self.D + 1) *
                                                  self.bucket_size]
Exemplo n.º 3
0
def default_shuffle(values, config, reverse=False, use_iter=True):
    """Shuffles values in place using default shuffle algorithm."""
    if use_iter:
        shuffle(values, config=config, value_type=sint, reverse=reverse)
    else:
        rec_shuffle(values, config=config, value_type=sint, reverse=reverse)