def digital_method(coefficients, val, add, mul, act, power, zero, one):
    """
    Evaluate a univariate polynomial at val.

    The polynomial is given as an iterator 'coefficients' which yields
    (degree, coefficient) pair in descending order of degree.

    If the polynomial is of R-coefficients, then val should be in an
    R-algebra D.

    All operations 'add', 'mul', 'act', 'power', 'zero', 'one' should
    be explicitly given, where: 
      'add' means addition (D x D -> D),
      'mul' multiplication (D x D -> D),
      'act' action of R (R x D -> D),
      'power' powering (D x Z -> D) and
      'zero', 'one' constants in D.
    """
    result = zero
    val_pow = {0:one, 1:val}
    d = None
    for d_next, c_next in coefficients:
        if d:
            diff = d - d_next
            if diff not in val_pow:
                val_pow[diff] = power(val, diff)
            result = add(mul(result, val_pow[diff]), act(c_next, one))
        else:
            result = act(c_next, one)
        d = d_next
    if d:
        return mul(result, val_pow.get(d, power(val, d)))
    else:
        return result