Skip to main content

sc_neurocore_engine/neurons/trivial/
sigma_delta.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Commercial license available
3// © Concepts 1996–2026 Miroslav Šotek. All rights reserved.
4// © Code 2020–2026 Miroslav Šotek. All rights reserved.
5// ORCID: 0009-0009-3560-0851
6// Contact: www.anulum.li | protoscience@anulum.li
7// SC-NeuroCore — Sigma-Delta Neuron
8
9/// Sigma-Delta neuron — first-order delta modulation.
10#[derive(Clone, Debug)]
11pub struct SigmaDeltaNeuron {
12    pub sigma: f64,
13    pub v_threshold: f64,
14}
15
16impl SigmaDeltaNeuron {
17    pub fn new(v_threshold: f64) -> Self {
18        Self {
19            sigma: 0.0,
20            v_threshold,
21        }
22    }
23
24    pub fn step(&mut self, current: f64) -> i32 {
25        self.sigma += current;
26        if self.sigma >= self.v_threshold {
27            self.sigma -= self.v_threshold;
28            1
29        } else if self.sigma <= -self.v_threshold {
30            self.sigma += self.v_threshold;
31            -1
32        } else {
33            0
34        }
35    }
36
37    pub fn reset(&mut self) {
38        self.sigma = 0.0;
39    }
40}
41
42impl Default for SigmaDeltaNeuron {
43    fn default() -> Self {
44        Self::new(1.0)
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn sigma_delta_encodes() {
54        let mut n = SigmaDeltaNeuron::default();
55        let total: i32 = (0..10).map(|_| n.step(0.3)).sum();
56        assert!(total > 0);
57    }
58    #[test]
59    fn sd_reset_clears_state() {
60        let mut n = SigmaDeltaNeuron::default();
61        for _ in 0..10 {
62            n.step(0.3);
63        }
64        n.reset();
65        assert!((n.sigma - 0.0).abs() < 1e-10);
66    }
67    #[test]
68    fn sd_bounded() {
69        let mut n = SigmaDeltaNeuron::default();
70        for _ in 0..1000 {
71            n.step(100.0);
72        }
73        assert!(n.sigma.is_finite());
74    }
75    #[test]
76    fn sd_nan_no_panic() {
77        SigmaDeltaNeuron::default().step(f64::NAN);
78    }
79}