import torch

def memory_forward(x_seq, Wq, Wk, Wv, W0, eta_w, eta_max=1.0):
    """One sequence: x_seq [T, d], T > 0.
    Wq/Wk [d, dk]; Wv [d, dv]; W0 [dk, dv]; eta_w [d].
    All tensors use a compatible floating dtype and device.
    """
    W = W0.clone()
    outputs = []
    for x in x_seq:
        q, k, v = x @ Wq, x @ Wk, x @ Wv
        eta = eta_max * torch.sigmoid(x @ eta_w)
        predicted = k @ W
        error = predicted - v
        grad_W = torch.outer(k, error)
        W = W - eta * grad_W
        outputs.append(q @ W)
    return torch.stack(outputs), W

# Outer training: send outputs through the rest of the LM;
# compute next-token cross-entropy, then loss.backward()
# and take an optimizer step on the slow parameters.
# Inference: torch.no_grad() is valid for THIS analytic
# implementation. The arithmetic memory write still runs.