def rescale(self, now):
        """ "A common feature of the above techniques—indeed, the key technique
        that allows us to track the decayed weights efficiently—is that they
        maintain counts and other quantities based on g(ti − L), and only scale
        by g(t − L) at query time. But while g(ti −L)/g(t−L) is guaranteed to
        lie between zero and one, the intermediate values of g(ti − L) could
        become very large. For polynomial functions, these values should not
        grow too large, and should be effectively represented in practice by
        floating point values without loss of precision. For exponential
        functions, these values could grow quite large as new values of
        (ti − L) become large, and potentially exceed the capacity of common
        floating point types. However, since the values stored by the
        algorithms are linear combinations of g values (scaled sums), they
        can be rescaled relative to a new landmark. That is, by the analysis
        of exponential decay in Section VI-A, the choice of L does not affect
        the final result. We can therefore multiply each value based on L by a
        factor of exp(−α(L′ − L)), and obtain the correct value as if we had
        instead computed relative to a new landmark L′ (and then use this new
        L′ at query time). This can be done with a linear pass over whatever
        data structure is being used."
        """

        old_start_time = self.start_time
        self.start_time = self.current_time_in_fractional_seconds()
        self.next_scale_time = now + RESCALE_THRESHOLD_S
        new_values = treap.treap()
        for key in self.values.keys():
            new_key = key * math.exp(
                -self.alpha * (self.start_time - old_start_time))
            new_values[new_key] = self.values[key]
        self.values = new_values