Esempio n. 1
0
    def __init__(self, content, lowest=1, highest=1):
        self.content = content
        self.content_length = content.__len__()
        self.length = fastdivmod.powersum(self.content_length, lowest, highest)
        self.lowest = lowest
        self.highest = highest

        def arbitrary_entry(i):
            return (fastdivmod.powersum(self.content_length, lowest,
                                        i + lowest - 1), i + lowest)

        def entry_from_prev(i, prev):
            return (prev[0] + (self.content_length**prev[1]), prev[1] + 1)

        self.offsets = cachingseq.CachingFuncSequence(arbitrary_entry,
                                                      highest - lowest + 1,
                                                      entry_from_prev)
        # This needs to be a constant in order to reuse caclulations in future
        # calls to bisect (a moving target will produce more misses).
        if self.offsets[-1][0] > sys.maxint:
            i = 0
            while i + 2 < len(self.offsets):
                if self.offsets[i + 1][0] > sys.maxint:
                    self.index_of_offset = i
                    self.offset_break = self.offsets[i][0]
                    break
                i += 1
        else:
            self.index_of_offset = len(self.offsets)
            self.offset_break = sys.maxint
Esempio n. 2
0
    def testIter(self):
        c = cachingseq.CachingFuncSequence(lambda i: i, 10)
        # Cache empty on construction
        self.assertEquals(0, len(c._cache))

        self.assertEquals(10, len(c))
        self.assertEquals(range(10), list(c))

        # Cache full after iteration
        self.assertEquals(10, len(c._cache))
Esempio n. 3
0
    def testIncFunc(self):
        def first_func(x):
            assert x == 0
            return 1

        def inc_func(i, prev):
            return prev * 2

        c = cachingseq.CachingFuncSequence(first_func, 10, inc_func)
        self.assertEquals([1, 2, 4, 8, 16, 32, 64, 128, 256, 512], list(c))
Esempio n. 4
0
    def testLimits(self):
        c = cachingseq.CachingFuncSequence(lambda i: i, 10)
        self.assertEquals(9, c[9])
        self.assertEquals(9, c[-1])
        self.assertEquals(0, c[0])
        self.assertEquals(0, c[-10])
        self.assertRaises(IndexError, lambda: c[10])
        self.assertRaises(IndexError, lambda: c[11])
        self.assertRaises(IndexError, lambda: c[-11])
        self.assertRaises(IndexError, lambda: c[-12])
        self.assertEquals(2, len(c._cache))

        # Make sure .func is settable at runtime...
        c.func = lambda i: 'bbb'
        self.assertEquals('bbb', c[1])
        # ...and that we don't call it again.
        self.assertEquals(0, c[0])
Esempio n. 5
0
    def __init__(self, content, lowest=1, highest=1):
        self.content = content
        self.content_length = content.__len__()
        self.length = fastdivmod.powersum(self.content_length, lowest, highest)
        self.lowest = lowest
        self.highest = highest

        def arbitrary_entry(i):
            return (
                fastdivmod.powersum(self.content_length, lowest,
                                    i + lowest - 1),
                i + lowest,
            )

        def entry_from_prev(i, prev):
            return (prev[0] + (self.content_length**prev[1]), prev[1] + 1)

        self.offsets = cachingseq.CachingFuncSequence(arbitrary_entry,
                                                      highest - lowest + 1,
                                                      entry_from_prev)

        # `offset_break` is an optimization around bisect, which would normally
        # choose the "middle" value to bisect on, which does a lot of work
        # that's unnecessary at the bottom of the range (say, the first 256
        # entries).
        #
        # A good choice of OFFSET_BREAK_THRESHOLD minimizes the wasted work up
        # front (we have to calculate all the offsets now up to it), and is
        # still larger than most performant lookups will need.  Anything above
        # that will result in a big penalty as we get into arbitrary-precision
        # integers and use the standard bisect logic.

        if self.offsets[-1][0] > OFFSET_BREAK_THRESHOLD:
            for i in range(len(self.offsets) - 1):
                if self.offsets[i + 1][0] > OFFSET_BREAK_THRESHOLD:
                    self.index_of_offset = i
                    self.offset_break = self.offsets[i][0]
                    return

        self.index_of_offset = len(self.offsets)
        self.offset_break = self.offsets[-1][0] + 1