[varStore.optimize] Use faster intTools.bit_count as popcount

This commit is contained in:
Behdad Esfahbod 2023-05-25 08:19:15 -06:00
parent 9cbde09cdc
commit 832f2f766f
3 changed files with 8 additions and 13 deletions

View File

@ -1,4 +1,4 @@
__all__ = ["popCount"] __all__ = ["popCount", "bit_count", "bit_indices"]
try: try:
@ -13,7 +13,7 @@ except AttributeError:
See https://docs.python.org/3.10/library/stdtypes.html#int.bit_count See https://docs.python.org/3.10/library/stdtypes.html#int.bit_count
""" """
popCount = bit_count popCount = bit_count # alias
def bit_indices(v): def bit_indices(v):

View File

@ -4,7 +4,7 @@ https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariat
NOTE: The API is experimental and subject to change. NOTE: The API is experimental and subject to change.
""" """
from fontTools.misc.dictTools import hashdict from fontTools.misc.dictTools import hashdict
from fontTools.misc.intTools import popCount from fontTools.misc.intTools import bit_count
from fontTools.ttLib import newTable from fontTools.ttLib import newTable
from fontTools.ttLib.tables import otTables as ot from fontTools.ttLib.tables import otTables as ot
from fontTools.ttLib.ttVisitor import TTVisitor from fontTools.ttLib.ttVisitor import TTVisitor
@ -190,7 +190,7 @@ def overlayFeatureVariations(conditionalSubstitutions):
# Generate output # Generate output
items = [] items = []
for box, rank in sorted( for box, rank in sorted(
boxMap.items(), key=(lambda BoxAndRank: -popCount(BoxAndRank[1])) boxMap.items(), key=(lambda BoxAndRank: -bit_count(BoxAndRank[1]))
): ):
# Skip any box that doesn't have any substitution. # Skip any box that doesn't have any substitution.
if rank == 0: if rank == 0:

View File

@ -1,4 +1,5 @@
from fontTools.misc.roundTools import noRound, otRound from fontTools.misc.roundTools import noRound, otRound
from fontTools.misc.intTools import bit_count
from fontTools.ttLib.tables import otTables as ot from fontTools.ttLib.tables import otTables as ot
from fontTools.varLib.models import supportScalar from fontTools.varLib.models import supportScalar
from fontTools.varLib.builder import ( from fontTools.varLib.builder import (
@ -360,7 +361,7 @@ ot.GPOS.remap_device_varidxes = Object_remap_device_varidxes
class _Encoding(object): class _Encoding(object):
def __init__(self, chars): def __init__(self, chars):
self.chars = chars self.chars = chars
self.width = self._popcount(chars) self.width = bit_count(chars)
self.columns = self._columns(chars) self.columns = self._columns(chars)
self.overhead = self._characteristic_overhead(self.columns) self.overhead = self._characteristic_overhead(self.columns)
self.items = set() self.items = set()
@ -400,13 +401,7 @@ class _Encoding(object):
return not (chars & ~self.chars) return not (chars & ~self.chars)
def __sub__(self, other): def __sub__(self, other):
return self._popcount(self.chars & ~other.chars) return bit_count(self.chars & ~other.chars)
@staticmethod
def _popcount(n):
# Apparently this is the fastest native way to do it...
# https://stackoverflow.com/a/9831671
return bin(n).count("1")
@staticmethod @staticmethod
def _characteristic_overhead(columns): def _characteristic_overhead(columns):
@ -429,7 +424,7 @@ class _Encoding(object):
def gain_from_merging(self, other_encoding): def gain_from_merging(self, other_encoding):
combined_chars = other_encoding.chars | self.chars combined_chars = other_encoding.chars | self.chars
combined_width = _Encoding._popcount(combined_chars) combined_width = bit_count(combined_chars)
combined_columns = self.columns | other_encoding.columns combined_columns = self.columns | other_encoding.columns
combined_overhead = _Encoding._characteristic_overhead(combined_columns) combined_overhead = _Encoding._characteristic_overhead(combined_columns)
combined_gain = ( combined_gain = (