Ejemplo n.º 1
0
def period_empirically_correct(a):
    """
    Empirically verify the period a particular array claims to have.
    
    Checks that expected repeats are literal repeated values (minus differing
    error terms).
    """
    last_values = None
    # Get the hyper-cube block of values which sample the complete period
    # of the array at various period-multiple offsets
    for offset_steps in combinations_with_replacement([-1, 0, 1, 2], a.ndim):
        offset = tuple(step * period
                       for step, period in zip(offset_steps, a.period))
        values = [
            # Since error terms will always be different, consider the
            # lower-bound case arbitrarily in order to make a fair comparison.
            affine_lower_bound(a[tuple(c + o for c, o in zip(coord, offset))])
            for coord in product(*(range(d) for d in a.period))
        ]
        print(values)

        # Every set of values should be identical
        if last_values is not None and values != last_values:
            return False

        last_values = values

    return True
Ejemplo n.º 2
0
    def test_correctness(self, stage):
        # This test checks that the filter implemented is equivalent to what
        # the VC-2 pseudocode would do
        a = SymbolArray(2, "a")
        l = LiftedArray(a, stage, 0)

        # Run the pseudocode against a random input
        rand = random.Random(0)
        input_array = [rand.randint(0, 10000) for _ in range(20)]
        pseudocode_output_array = input_array[:]
        lift = SYNTHESIS_LIFTING_FUNCTION_TYPES[stage.lift_type]
        lift(pseudocode_output_array, stage.L, stage.D, stage.taps, stage.S)

        # Check that the symbolic version gets the same answers (modulo
        # rounding errors). Check at output positions which are not affected by
        # rounding errors.
        for index in [10, 11]:
            pseudocode_output = pseudocode_output_array[index]

            # Substitute in the random inputs into symbolic answer
            output = l[index,
                       123].subs({("a", i, 123): value
                                  for i, value in enumerate(input_array)})

            lower_bound = affine_lower_bound(output)
            upper_bound = affine_upper_bound(output)

            assert (lower_bound <= pseudocode_output <= upper_bound)
Ejemplo n.º 3
0
    def test_shifting(self):
        a = SymbolArray(3, "foo")
        sa = RightShiftedArray(a, 3)

        v = a[1, 2, 3]

        sv = sa[1, 2, 3]

        assert affine_lower_bound(sv) == v / 8 - Fraction(1, 2)
        assert affine_upper_bound(sv) == v / 8 + Fraction(1, 2)
Ejemplo n.º 4
0
def synthesis_filter_bounds(expression):
    """
    Find the lower- and upper-bound reachable in a
    :py:class:`~vc2_bit_widths.linexp.LinExp` describing a synthesis filter.
    
    The filter expression must contain only affine error symbols
    (:py:class:`~vc2_bit_widths.linexp.AAError`) and symbols of the form ``((_,
    level, orient), x, y)`` representing transform coefficients.
    
    Parameters
    ==========
    expression : :py:class:`~vc2_bit_widths.linexp.LinExp`
    
    Returns
    =======
    (lower_bound, upper_bound) : :py:class:`~vc2_bit_widths.linexp.LinExp`
        Lower and upper bounds for the signal level in terms of the symbols of
        the form ``LinExp("signal_LEVEL_ORIENT_min")`` and
        ``LinExp("signal_LEVEL_ORIENT_max")``, representing the minimum and
        maximum signal levels for transform coefficients in level ``LEVEL`` and
        orientation ``ORIENT`` respectively.
    """
    # Replace all transform coefficients with affine error terms scaled to
    # appropriate ranges
    expression = LinExp(expression)

    lower_bound = affine_lower_bound(
        expression.subs({
            sym:
            ("coeff_{}_{}_min" if coeff > 0 else "coeff_{}_{}_max").format(
                sym[0][1],
                sym[0][2],
            )
            for sym, coeff in expression
            if sym is not None and not isinstance(sym, AAError)
        }))

    upper_bound = affine_upper_bound(
        expression.subs({
            sym:
            ("coeff_{}_{}_min" if coeff < 0 else "coeff_{}_{}_max").format(
                sym[0][1],
                sym[0][2],
            )
            for sym, coeff in expression
            if sym is not None and not isinstance(sym, AAError)
        }))

    return (lower_bound, upper_bound)
Ejemplo n.º 5
0
def analysis_filter_bounds(expression):
    """
    Find the lower- and upper-bound reachable in a
    :py:class:`~vc2_bit_widths.linexp.LinExp` describing an analysis filter.
    
    The filter expression must consist of only affine error symbols
    (:py:class:`~vc2_bit_widths.linexp.AAError`) and symbols of the form ``(_,
    x, y)`` representing pixel values in an input picture.
    
    Parameters
    ==========
    expression : :py:class:`~vc2_bit_widths.linexp.LinExp`
    
    Returns
    =======
    lower_bound : :py:class:`~vc2_bit_widths.linexp.LinExp`
    upper_bound : :py:class:`~vc2_bit_widths.linexp.LinExp`
        Algebraic expressions for the lower and upper bounds for the signal
        level. These expressions are given in terms of the symbols
        ``LinExp("signal_min")`` and ``LinExp("signal_max")``, which represent
        the minimum and maximum picture signal levels respectively.
    """
    signal_min = LinExp("signal_min")
    signal_max = LinExp("signal_max")

    expression = LinExp(expression)

    lower_bound = affine_lower_bound(
        expression.subs({
            sym: signal_min if coeff > 0 else signal_max
            for sym, coeff in expression
            if sym is not None and not isinstance(sym, AAError)
        }))

    upper_bound = affine_upper_bound(
        expression.subs({
            sym: signal_min if coeff < 0 else signal_max
            for sym, coeff in expression
            if sym is not None and not isinstance(sym, AAError)
        }))

    return (lower_bound, upper_bound)
Ejemplo n.º 6
0
def test_error_in_range():
    a = affine_error_with_range(-10, 123)
    assert affine_lower_bound(a) == -10
    assert affine_upper_bound(a) == 123
Ejemplo n.º 7
0
def test_affine_bounds(expr_in, lower, upper):
    assert affine_lower_bound(expr_in) == lower
    assert affine_upper_bound(expr_in) == upper
Ejemplo n.º 8
0
 def test_floordiv(self):
     a = LinExp("a")
     a_over_3 = a // 3
     assert affine_lower_bound(a_over_3) == (a / 3) - 1
     assert affine_upper_bound(a_over_3) == a / 3