@triton.jit
def bwd_sequential_scan_complex(grad_output_real, grad_output_imag, v_real,
    v_imag, f_real, f_imag, hidden_real, hidden_imag, B, L, C, BLOCK_M: tl.
    constexpr):
    offset_b = tl.program_id(0)
    if offset_b >= B:
        return
    offset_n = tl.program_id(1)
    ptr = tl.arange(0, BLOCK_M) + offset_b * L * C + (L - 1
        ) * C + offset_n * BLOCK_M
    grad_h_real = tl.zeros([BLOCK_M], dtype=tl.float32)
    grad_h_imag = tl.zeros([BLOCK_M], dtype=tl.float32)
    for time_step in range(L - 1, -1, -1):
        grad_real = tl.load(grad_output_real + ptr).to(tl.float32)
        grad_imag = tl.load(grad_output_imag + ptr).to(tl.float32)
        grad_h_real += grad_real
        grad_h_imag += grad_imag
        decay_real = tl.load(f_real + ptr).to(tl.float32)
        decay_imag = tl.load(f_imag + ptr).to(tl.float32)
        h_real = tl.load(hidden_real + ptr - C, mask=ptr >= offset_b * L *
            C + C, other=0.0).to(tl.float32)
        h_imag = tl.load(hidden_imag + ptr - C, mask=ptr >= offset_b * L *
            C + C, other=0.0).to(tl.float32)
        grad_f_real = grad_h_real * h_real + grad_h_imag * h_imag
        grad_f_imag = grad_h_imag * h_real - grad_h_real * h_imag
        tl.store(f_real + ptr, grad_f_real.to(f_real.dtype.element_ty))
        tl.store(f_imag + ptr, grad_f_imag.to(f_real.dtype.element_ty))
        tl.store(v_real + ptr, grad_h_real.to(v_real.dtype.element_ty))
        tl.store(v_imag + ptr, grad_h_imag.to(v_real.dtype.element_ty))
        grad_h_real_new = grad_h_real * decay_real + grad_h_imag * decay_imag
        grad_h_imag_new = grad_h_imag * decay_real - grad_h_real * decay_imag
        grad_h_real = grad_h_real_new
        grad_h_imag = grad_h_imag_new
        ptr -= C
