def test_clamp(x, lower_bound, upper_bound): if lower_bound > upper_bound: lower_bound, upper_bound = upper_bound, lower_bound new_x = clamp(x, lower_bound, upper_bound) # If x was already between the bounds, it shouldn't have changed if lower_bound <= x <= upper_bound: assert new_x == x assert lower_bound <= new_x <= upper_bound
def _calc_offsets(off, src_size, dst_size): """ >>> _calc_offsets(11, 10, 12) # no overlap (10, 0, 0) >>> _calc_offsets(-11, 12, 10) # no overlap (0, 10, 0) >>> _calc_offsets(5, 10, 12) # overlap (5, 0, 5) >>> _calc_offsets(-5, 12, 10) # overlap (0, 5, 5) >>> _calc_offsets(5, 10, 4) # containment (5, 0, 4) >>> _calc_offsets(-5, 4, 10) # containment (0, 5, 4) """ read_off = clamp(off, 0, src_size) write_off = clamp(-off, 0, dst_size) size = min(src_size - read_off, dst_size - write_off) return read_off, write_off, size
def _calc_offsets_impl(off, scale, src_size, dst_size): assert scale >= 1 - 1e-5 if off >= 0: write_off = 0 else: write_off = math.ceil((-off - 0.5) / scale) read_off = round((write_off + 0.5) * scale - 0.5 + off) - round( 0.5 * (scale - 1.0)) # assuming read_size/write_size ~= scale if read_off >= src_size: return 0, 0, 0, 0 write_end = dst_size write_size = write_end - write_off read_end = read_off + round(write_size * scale) if read_end > src_size: # +0.5 below is a fudge that will return last row in more situations, but will change the scale more write_end = math.floor((src_size - off + 0.5) / scale) write_size = write_end - write_off read_end = clamp(read_off + round(write_size * scale), read_off, src_size) read_size = read_end - read_off return int(read_off), int(write_off), int(read_size), int(write_size)