// linear.mbt 鈥?linear (fully-connected / dense) layer forward.
//
// y[n, out] = sum_in weight[out, in] * x[n, in] + bias[out]
//
// Layout: row-major flat `Array[Float]`.
//
// Input: [n, in_features] length = n * in_features
// Weight: [out_features, in_features] length = out_features * in_features
// Bias: [out_features] length = out_features
// Output: [n, out_features] length = n * out_features
///|
/// Linear (Dense) parameter container. `weight` is laid out as
/// `[out_features, in_features]` row-major; `bias` is `[out_features]`.
pub struct LinearParam {
weight : Array[Float]
bias : Array[Float]
in_features : Int
out_features : Int
}
///|
/// Build a LinearParam from raw arrays. Does NOT copy the arrays.
pub fn LinearParam::new(
weight : Array[Float],
bias : Array[Float],
in_features : Int,
out_features : Int,
) -> LinearParam {
{ weight, bias, in_features, out_features }
}
///|
/// Forward pass for a linear (dense) layer.
///
/// `input` : length = n * in_features
/// returns : length = n * out_features
pub fn linear_forward(
input : Array[Float],
n : Int,
param : LinearParam,
) -> Array[Float] {
let in_f = param.in_features
let out_f = param.out_features
let out : Array[Float] = Array::make(n * out_f, 0.0F)
for batch in 0..