class ExponentialDelay extends Delay {

    private final Duration lower;

    private final Duration upper;

    private final int powersOf;

    private final TimeUnit targetTimeUnit;

    ExponentialDelay(Duration lower, Duration upper, int powersOf, TimeUnit targetTimeUnit) {

        this.lower = lower;
        this.upper = upper;
        this.powersOf = powersOf;
        this.targetTimeUnit = targetTimeUnit;
    }

    @Override
    public Duration createDelay(long attempt) {

        long delay;
        if (attempt <= 0) { // safeguard against underflow
            delay = 0;
        } else if (powersOf == 2) {
            delay = calculatePowerOfTwo(attempt);
        } else {
            delay = calculateAlternatePower(attempt);
        }

        return applyBounds(Duration.ofNanos(targetTimeUnit.toNanos(delay)));
    }

    /**
     * Apply bounds to the given {@code delay}.
     *
     * @param delay the delay
     * @return the delay normalized to its lower and upper bounds.
     */
    protected Duration applyBounds(Duration delay) {
        return applyBounds(delay, lower, upper);
    }

    private long calculateAlternatePower(long attempt) {<FILL_FUNCTION_BODY>}

    // fastpath with bitwise operator
    protected static long calculatePowerOfTwo(long attempt) {

        if (attempt <= 0) { // safeguard against underflow
            return 0L;
        } else if (attempt >= 63) { // safeguard against overflow in the bitshift operation
            return Long.MAX_VALUE - 1;
        } else {
            return 1L << (attempt - 1);
        }
    }

}


        // round will cap at Long.MAX_VALUE and pow should prevent overflows
        double step = Math.pow(powersOf, attempt - 1); // attempt > 0
        return Math.round(step);
    
<methods>public static io.lettuce.core.resource.Delay constant(java.time.Duration) ,public static io.lettuce.core.resource.Delay constant(int, java.util.concurrent.TimeUnit) ,public abstract java.time.Duration createDelay(long) ,public static Supplier<io.lettuce.core.resource.Delay> decorrelatedJitter() ,public static Supplier<io.lettuce.core.resource.Delay> decorrelatedJitter(java.time.Duration, java.time.Duration, long, java.util.concurrent.TimeUnit) ,public static Supplier<io.lettuce.core.resource.Delay> decorrelatedJitter(long, long, long, java.util.concurrent.TimeUnit) ,public static io.lettuce.core.resource.Delay equalJitter() ,public static io.lettuce.core.resource.Delay equalJitter(java.time.Duration, java.time.Duration, long, java.util.concurrent.TimeUnit) ,public static io.lettuce.core.resource.Delay equalJitter(long, long, long, java.util.concurrent.TimeUnit) ,public static io.lettuce.core.resource.Delay exponential() ,public static io.lettuce.core.resource.Delay exponential(java.time.Duration, java.time.Duration, int, java.util.concurrent.TimeUnit) ,public static io.lettuce.core.resource.Delay exponential(long, long, java.util.concurrent.TimeUnit, int) ,public static io.lettuce.core.resource.Delay fullJitter() ,public static io.lettuce.core.resource.Delay fullJitter(java.time.Duration, java.time.Duration, long, java.util.concurrent.TimeUnit) ,public static io.lettuce.core.resource.Delay fullJitter(long, long, long, java.util.concurrent.TimeUnit) <variables>private static java.time.Duration DEFAULT_LOWER_BOUND,private static int DEFAULT_POWER_OF,private static java.util.concurrent.TimeUnit DEFAULT_TIMEUNIT,private static java.time.Duration DEFAULT_UPPER_BOUND