---
title: "ClikaRT::ops::gated_delta_update"
sidebar_label: "gated_delta_update"
description: "Gated delta-rule recurrence step: per token, the [B, HV, K, V] Float32 state decays by exp(g), takes the delta-rule rank-1 update (beta·k) ⊗ (v − Sᵀk), and emits o = (scale·q)ᵀ S, updated IN PLACE."
---

<!-- Generated by tools/doxygen2mdx from Doxygen XML. Do not edit. -->

<span class="api-kind api-kind--function">function</span>

## gated\_delta\_update() {#gated_delta_update}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`gated_delta_update`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `query`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `key`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `value`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `beta`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `gate`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `state`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `seq_lens` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `slot_ids` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::optional<double>` `scale` `=` `std::nullopt`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `gate_bias` `=` `{}`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`OptionalTensor`](../../index.md#OptionalTensor) `gate_scale` `=` `{}`<br />
)

</div>

Gated delta-rule recurrence step: per token, the `[B, HV, K, V]` Float32 `state` decays by `exp(g)`, takes the delta-rule rank-1 update `(beta·k) ⊗ (v − Sᵀk)`, and emits `o = (scale·q)ᵀ S`, updated IN PLACE. The gate's RANK picks the family: `[B, T, HV]` = one scalar per value head; `[B, T, HV, K]` = per key dim. q/k `[B, T, H, K]` (HV % H == 0, grouped heads), v `[B, T, HV, V]`, beta `[B, T, HV]`; `scale` defaults to K^-1/2; `seq_lens` (`[B]` Int32) bounds ragged prefill rows. `slot_ids` (`[B]` Int32, device-resident) addresses `state` as a SLAB `[num_slots, HV, K, V]`: batch row `b` reads/updates slab row `slot_ids[b]` in place (ids in range and DISTINCT per call, the caller's contract); absent keeps state row `b`. TWO gate forms, told apart by which inputs are bound: with `gate_bias` and `gate_scale` absent, `gate` IS the log-space decay (Float32 or the activations' dtype); with both bound (Float32 `gate_bias` `[HV]` beside a `[B, T, HV]` gate or `[HV, K]` beside a `[B, T, HV, K]` one, the checkpoint's `dt_bias`; Float32 `gate_scale` `[HV]`, the once-folded `-exp(A_log)`), `gate` is the RAW gate projection slice at the activations' dtype and the kernel forms the decay `gate_scale * `[`softplus`](./softplus.md#softplus)`(g + gate_bias)` in fp32 registers, so no add / softplus / mul pass and no fp32 transient precede the call. One without the other rejects; a backend without the raw-gate arm declines it typed.

<div class="api-declared">

Declared in `ClikaRT/compute/ops.h`, line 3870

</div>
