```python
def retry_delays(attempts, base, cap):
    if isinstance(attempts, bool) or not isinstance(attempts, int):
        raise TypeError("attempts must be a non-negative integer")
    if attempts < 0:
        raise ValueError("attempts must be non-negative")
    if base < 0:
        raise ValueError("base must be non-negative")
    if cap < 0:
        raise ValueError("cap must be non-negative")
    
    result = []
    for i in range(attempts):
        # Compute base * 2**i without converting huge int to float
        # If base is 0, delay is 0
        if base == 0:
            delay = 0.0
        else:
            # Check if base * 2**i exceeds cap
            # We can compare using integer arithmetic if base is an integer,
            # but base can be a float. To avoid overflow, we check if 2**i is
            # so large that base * 2**i > cap.
            # Since cap is non-negative, if base > 0 and 2**i > cap / base,
            # then min(cap, base * 2**i) = cap.
            # But cap / base might be problematic if base is very small.
            # Alternative: compute step by step or use logarithms?
            # Simpler: if base * 2**i would overflow, it's definitely > cap (since cap is finite).
            # We can check if 2**i > cap / base when base > 0.
            # However, cap / base could be inf if base is very small, but that's fine.
            # Actually, the issue is that 2**i becomes a huge int, and multiplying by float base
            # causes OverflowError when converting int to float.
            # Solution: if base is a float, we can check if 2**i is too large.
            # If base == 0, delay = 0.
            # If base > 0, we want min(cap, base * 2**i).
            # If base * 2**i > cap, result is cap.
            # We can determine this without computing base * 2**i directly.
            # If base is an int, base * 2**i is an int, and we can compare with cap (float).
            # But cap is a float, so comparing int with float is fine unless int is too large.
            # Actually, comparing a huge int with a float works in Python (it converts float to int? No, it converts int to float for comparison, which can overflow).
            # Better approach: use logarithms or check if 2**i > cap / base.
            # But cap / base can be computed safely if base > 0.
            # If base > 0 and 2**i > cap / base, then base * 2**i > cap, so delay = cap.
            # Otherwise, delay = base * 2**i.
            # We need to handle the case where base * 2**i is small enough to compute safely.
            # Let's use a threshold: if i is large enough that 2**i > cap / base, return cap.
            # Compute threshold = cap / base if base > 0.
            # If base == 0, delay = 0.
            if base == 0:
                delay = 0.0
            else:
                # Check if 2**i > cap / base
                # cap / base is a float. 2**i is an int.
                # We can compare int with float safely if the int is not too large.
                # But 2**i can be huge. So we need to avoid converting 2**i to float.
                # Instead, we can check if i is large enough.
                # If cap / base is finite, find the smallest i such that 2**i > cap / base.
                # But we can just check: if base * 2**i > cap, use cap.
                # To avoid overflow, we can use logarithms:
                # log2(base * 2**i) = log2(base) + i
                # log2(cap) = log2(cap)
                # If log2(base) + i > log2(cap), then base * 2**i > cap.
                # But log2(base) can be negative if base < 1.
                # Let's use math.log2? But we can't import math.
                # Alternative: use bit_length or iterative check.
                # Sim