Module ml::tensor_nn
neural-net building blocks on top of std::ml's Tensor/Autograd::get core (tensor.h/tensor.sc): activation functions, the Adam optimizer, and 1D pooling. Separate file from tensor.sc for the same reason the GPU backends are separate — an independently useful slice of functionality, not a change to the core type or its existing ops.
Every activation below is elementwise, allocates via __tensor_alloc_uninit_like (like Tensor::relu), and links into the same Autograd::get graph via its own backward function — same shape as tensor.sc's existing Tensor::relu/Tensor::scale, just more of them.
Internal 'static' helpers (every _X_backward function) are defined right here, not in tensor_nn.sc — same reasoning as tensor.h's own header comment: each including .sc file gets its own private copy, which is what lets tensor_nn.sc and the tensor<gpu-backend>.sc family compile as separate translation units and link together at build time instead of textually pasting tensor_nn.sc's whole body into each backend.
Structs
| AdamState | Per-parameter state (first/second moment buffers, same size as the parameter) plus the shared hyperparameters and step count. One AdamState per parameter tensor (W1, W2, ... each get their own) -- unlike sgd_update (a pure function of data/grad/lr with no persistent state), Adam needs m/v carried across steps. |