// rl_inventory_variance_update.cu — Layer 3 (inventory penalty) input EMA.
//
// Tracks running variance of |net_position| across batches. Layer 3's β
// controller scales the penalty so that at ~2σ inventory the penalty
// equals ~1% of typical reward magnitude.
// Spec: docs/superpowers/specs/2026-05-30-adaptive-risk-management-design.md
//
// Inputs:
//   net_position_per_batch[b]  signed contracts (current_lots, i32)
//
// Output: ISV[RL_INVENTORY_VARIANCE_EMA_INDEX = 675]
//
// EMA over the batch variance of |net_position|; sentinel-zero bootstrap.
// This is NOT a true Welford triple — we collapse the batch into a single
// scalar (batch variance) then EMA across steps with a constant alpha.
// The β controller treats this slot as σ² directly.
//
// Per `feedback_no_atomicadd`: single-thread single-block, sums sequentially.
// Per `feedback_cpu_is_read_only`: pure device kernel.
// Per `feedback_isv_for_adaptive_bounds`: Welford-EMA α is a structural
// smoothing parameter, matching ema_update_per_step convention.

#include <stdint.h>

#define RL_INVENTORY_VARIANCE_EMA_INDEX 675
#define WELFORD_ALPHA                   0.01f  // slower EMA than Kelly inputs

extern "C" __global__ void rl_inventory_variance_update(
    float*       __restrict__ isv,
    const int*   __restrict__ net_position_per_batch,    // [b_size] signed contracts (i32)
    int                       b_size
) {
    if (threadIdx.x != 0 || threadIdx.y != 0 || threadIdx.z != 0) return;
    if (blockIdx.x  != 0 || blockIdx.y  != 0 || blockIdx.z  != 0) return;

    if (b_size <= 0) return;

    // Compute batch mean + variance of |net_position|.
    float sum    = 0.0f;
    float sum_sq = 0.0f;
    for (int b = 0; b < b_size; ++b) {
        const int   lots = net_position_per_batch[b];
        const float v    = (float)((lots < 0) ? -lots : lots);
        sum    += v;
        sum_sq += v * v;
    }
    const float n    = (float)b_size;
    const float mean = sum / n;
    const float var  = (sum_sq / n) - (mean * mean);
    if (var < 0.0f) return;  // numerical safety: should not happen but defend

    const float prev = isv[RL_INVENTORY_VARIANCE_EMA_INDEX];
    if (prev == 0.0f) {
        isv[RL_INVENTORY_VARIANCE_EMA_INDEX] = var;
    } else {
        isv[RL_INVENTORY_VARIANCE_EMA_INDEX] =
            (1.0f - WELFORD_ALPHA) * prev + WELFORD_ALPHA * var;
    }
}
