@triton.jit
def rz_linear_backward_input_grad_core(a_ptr, b_ptr, c_ptr, init_factor, M,
    N, K, H, stride_am, stride_an, stride_cm, stride_ck, R7: int, R6: int,
    R5: int, R4: int, R3: int, R2: int, R1: int, R0: int, allow_tf32: tl.
    constexpr, BLOCK_SIZE_M: tl.constexpr, BLOCK_SIZE_N: tl.constexpr,
    BLOCK_SIZE_K: tl.constexpr, GROUP_SIZE: tl.constexpr):
    """Kernel for computing the matmul C = (A x B^T)
    A has shape (M, N), B has shape H->(K, N) and C has shape (M, K)
    """
    pid = tl.program_id(axis=0)
    num_pid_k = tl.cdiv(K, BLOCK_SIZE_K)
    num_pid_m = tl.cdiv(M, BLOCK_SIZE_M)
    pid_m = pid // num_pid_k
    pid_k = pid % num_pid_k
    offs_am = pid_m * BLOCK_SIZE_M + tl.arange(0, BLOCK_SIZE_M)
    offs_an = tl.arange(0, BLOCK_SIZE_N)
    a_ptrs = a_ptr + offs_am[:, None] * stride_am + offs_an[None, :
        ] * stride_an
    b_offset = b_ptr + tl.arange(0, BLOCK_SIZE_N)[:, None] + tl.arange(0,
        BLOCK_SIZE_K)[None, :] * BLOCK_SIZE_N
    b_ptrs = b_offset + ((pid_k * R3 + 0 * R2 + R1) % R0 * R0 + (pid_k * R7 +
        0 * R5 + R4) % R0) % (H - BLOCK_SIZE_K * BLOCK_SIZE_N)
    offs_cm = pid_m * BLOCK_SIZE_M + tl.arange(0, BLOCK_SIZE_M)
    offs_ck = pid_k * BLOCK_SIZE_K + tl.arange(0, BLOCK_SIZE_K)
    a_zero = tl.zeros((BLOCK_SIZE_M, BLOCK_SIZE_N), dtype=tl.float32)
    b_zero = tl.zeros((BLOCK_SIZE_N, BLOCK_SIZE_K), dtype=tl.float32)
    c = tl.zeros((BLOCK_SIZE_M, BLOCK_SIZE_K), dtype=tl.float32)
    for n in range(0, tl.cdiv(N, BLOCK_SIZE_N)):
        offs_n = n * BLOCK_SIZE_N + tl.arange(0, BLOCK_SIZE_N)
        a_mask = (offs_cm[:, None] < M) & (offs_n[None, :] < N)
        b_mask = (offs_n[:, None] < N) & (offs_ck[None, :] < K)
        a = tl.load(a_ptrs, mask=a_mask, other=a_zero)
        b = tl.load(b_ptrs, mask=b_mask, other=b_zero)
        c += tl.dot(a, b, allow_tf32=allow_tf32)
        a_ptrs += BLOCK_SIZE_N * stride_an
        b_ptrs = b_offset + ((pid_k * R3 + (n + 1) * R2 + R1) % R0 * R0 + (
            pid_k * R7 + (n + 1) * R5 + R4) % R0) % (H - BLOCK_SIZE_K *
            BLOCK_SIZE_N)
    offs_ck = pid_k * BLOCK_SIZE_K + tl.arange(0, BLOCK_SIZE_K)
    offs_cm = pid_m * BLOCK_SIZE_M + tl.arange(0, BLOCK_SIZE_M)
    c_ptrs = c_ptr + stride_cm * offs_cm[:, None] + stride_ck * offs_ck[None, :
        ]
    c_mask = (offs_cm[:, None] < M) & (offs_ck[None, :] < K)
    tl.store(c_ptrs, c * init_factor, mask=c_mask)
