native_neural_network 0.3.1

Lib no_std Rust for native neural network (.rnn)
Documentation
use crate::tensor::TensorView;

pub fn conv3d_forward(
    input: &TensorView,
    kernel: &TensorView,
    bias: Option<&[f32]>,
    output: &mut TensorView,
    pad: (usize, usize, usize),
    stride: (usize, usize, usize),
) {
    if stride.0 == 0 || stride.1 == 0 || stride.2 == 0 {
        return;
    }
    if !input.is_valid_layout() || !kernel.is_valid_layout() || !output.is_valid_layout() {
        return;
    }

    let n = input.shape[0];
    let c = input.shape[1];
    let d = input.shape[2];
    let h = input.shape[3];
    let w = input.shape[4];
    let cout = kernel.shape[0];
    if kernel.shape[1] != c {
        return;
    }
    if output.shape[0] != n || output.shape[1] != cout {
        return;
    }
    if let Some(b) = bias {
        if b.len() < cout {
            return;
        }
    }

    let pad_d = pad.0 as isize;
    let pad_h = pad.1 as isize;
    let pad_w = pad.2 as isize;

    let d_isize = d as isize;
    let h_isize = h as isize;
    let w_isize = w as isize;

    for n in 0..n {
        for co in 0..cout {
            for od in 0..output.shape[2] {
                for oh in 0..output.shape[3] {
                    for ow in 0..output.shape[4] {
                        let mut acc = 0f32;
                        for ci in 0..c {
                            for kd in 0..kernel.shape[2] {
                                for kh in 0..kernel.shape[3] {
                                    for kw in 0..kernel.shape[4] {
                                        let id = (od * stride.0 + kd) as isize - pad_d;
                                        let ih = (oh * stride.1 + kh) as isize - pad_h;
                                        let iw = (ow * stride.2 + kw) as isize - pad_w;
                                        if id >= 0
                                            && ih >= 0
                                            && iw >= 0
                                            && id < d_isize
                                            && ih < h_isize
                                            && iw < w_isize
                                        {
                                            let idu = id as usize;
                                            let ihu = ih as usize;
                                            let iwu = iw as usize;
                                            let i = match input.idx_linear(n, ci, idu, ihu, iwu) {
                                                Some(v) => v,
                                                None => continue,
                                            };
                                            let k = match kernel.idx_linear(co, ci, kd, kh, kw) {
                                                Some(v) => v,
                                                None => continue,
                                            };
                                            acc += input.data[i] * kernel.data[k];
                                        }
                                    }
                                }
                            }
                        }
                        if let Some(out_i) = output.idx_linear(n, co, od, oh, ow) {
                            output.data[out_i] = acc + bias.map(|b| b[co]).unwrap_or(0.0);
                        }
                    }
                }
            }
        }
    }
}