def buildVarData(varRegionIndices, items, optimize=True): self = ot.VarData() self.VarRegionIndex = list(varRegionIndices) regionCount = self.VarRegionCount = len(self.VarRegionIndex) records = self.Item = [] if items: for item in items: assert len(item) == regionCount records.append(list(item)) self.ItemCount = len(self.Item) self.calculateNumShorts(optimize=optimize) return self
def buildVarData(varRegionIndices, items, optimize=True): self = ot.VarData() self.VarRegionIndex = list(varRegionIndices) regionCount = self.VarRegionCount = len(self.VarRegionIndex) records = self.Item = [] if items: for item in items: assert len(item) == regionCount records.append(list(item)) self.ItemCount = len(self.Item) if items and optimize: optimizeVarData(self) return self
def VarStore_optimize(self): """Optimize storage. Returns mapping from old VarIdxes to new ones.""" # TODO # Check that no two VarRegions are the same; if they are, fold them. n = len(self.VarRegionList.Region) # Number of columns zeroes = array('h', [0]*n) front_mapping = {} # Map from old VarIdxes to full row tuples encodings = _EncodingDict() # Collect all items into a set of full rows (with lots of zeroes.) for major,data in enumerate(self.VarData): regionIndices = data.VarRegionIndex for minor,item in enumerate(data.Item): row = array('h', zeroes) for regionIdx,v in zip(regionIndices, item): row[regionIdx] += v row = tuple(row) encodings.add_row(row) front_mapping[(major<<16)+minor] = row # Separate encodings that have no gain (are decided) and those having # possible gain (possibly to be merged into others.) encodings = sorted(encodings.values(), key=_Encoding.__len__, reverse=True) done_by_width = defaultdict(list) todo = [] for encoding in encodings: if not encoding.gain: done_by_width[encoding.width].append(encoding) else: todo.append(encoding) # For each encoding that is possibly to be merged, find the best match # in the decided encodings, and record that. todo.sort(key=_Encoding.get_room) for encoding in todo: encoding._find_yourself_best_new_encoding(done_by_width) # Walk through todo encodings, for each, see if merging it with # another todo encoding gains more than each of them merging with # their best decided encoding. If yes, merge them and add resulting # encoding back to todo queue. If not, move the enconding to decided # list. Repeat till done. while todo: encoding = todo.pop() best_idx = None best_gain = 0 for i,other_encoding in enumerate(todo): combined_chars = other_encoding.chars | encoding.chars combined_width = _Encoding._popcount(combined_chars) combined_overhead = _Encoding._characteristic_overhead(combined_chars) combined_gain = ( + encoding.overhead + other_encoding.overhead - combined_overhead - (combined_width - encoding.width) * len(encoding) - (combined_width - other_encoding.width) * len(other_encoding) ) this_gain = 0 if encoding.best_new_encoding is None else ( + encoding.overhead - (encoding.best_new_encoding.width - encoding.width) * len(encoding) ) other_gain = 0 if other_encoding.best_new_encoding is None else ( + other_encoding.overhead - (other_encoding.best_new_encoding.width - other_encoding.width) * len(other_encoding) ) separate_gain = this_gain + other_gain if combined_gain > separate_gain: best_idx = i best_gain = combined_gain - separate_gain if best_idx is None: # Encoding is decided as is done_by_width[encoding.width].append(encoding) else: other_encoding = todo[best_idx] combined_chars = other_encoding.chars | encoding.chars combined_encoding = _Encoding(combined_chars) combined_encoding.extend(encoding.items) combined_encoding.extend(other_encoding.items) combined_encoding._find_yourself_best_new_encoding(done_by_width) del todo[best_idx] todo.append(combined_encoding) # Assemble final store. back_mapping = {} # Mapping from full rows to new VarIdxes encodings = sum(done_by_width.values(), []) encodings.sort(key=_Encoding.sort_key) self.VarData = [] for major,encoding in enumerate(encodings): data = ot.VarData() self.VarData.append(data) data.VarRegionIndex = range(n) data.VarRegionCount = len(data.VarRegionIndex) data.Item = sorted(encoding.items) for minor,item in enumerate(data.Item): back_mapping[item] = (major<<16)+minor # Compile final mapping. varidx_map = {} for k,v in front_mapping.items(): varidx_map[k] = back_mapping[v] # Remove unused regions. self.prune_regions() # Recalculate things and go home. self.VarRegionList.RegionCount = len(self.VarRegionList.Region) self.VarDataCount = len(self.VarData) for data in self.VarData: data.ItemCount = len(data.Item) data.optimize() return varidx_map