Skip to main content

teeny_core/nn/activation/
hard.rs

1/*
2 * Copyright (c) 2026 Teenygrad.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *   http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use core::marker::PhantomData;
18
19use crate::{
20    dtype::{EagerTensor, Float, Tensor},
21    nn::Layer,
22};
23
24/// Hardtanh activation layer: clamps input to `[min_val, max_val]`.
25pub struct Hardtanh<D: Float, T, const RANK: usize> {
26    /// Lower clamp bound.
27    pub min_val: f64,
28    /// Upper clamp bound.
29    pub max_val: f64,
30    _pd: PhantomData<(D, T)>,
31}
32
33impl<D: Float, T, const RANK: usize> Hardtanh<D, T, RANK> {
34    /// Creates a new `Hardtanh` layer clamping to `[min_val, max_val]`.
35    pub fn new(min_val: f64, max_val: f64) -> Self {
36        Self {
37            min_val,
38            max_val,
39            _pd: PhantomData,
40        }
41    }
42}
43
44impl<D: Float, T: Tensor<D, RANK> + EagerTensor, const RANK: usize> Layer<T>
45    for Hardtanh<D, T, RANK>
46{
47    type Output = T;
48    fn call(&self, _input: T) -> Self::Output {
49        todo!()
50    }
51}
52
53/// ReLU6 activation layer: `min(max(0, x), 6)`.
54pub struct Relu6<D: Float, T, const RANK: usize> {
55    _pd: PhantomData<(D, T)>,
56}
57
58impl<D: Float, T, const RANK: usize> Relu6<D, T, RANK> {
59    /// Creates a new `Relu6` layer.
60    pub fn new() -> Self {
61        Self { _pd: PhantomData }
62    }
63}
64
65impl<D: Float, T, const RANK: usize> Default for Relu6<D, T, RANK> {
66    fn default() -> Self {
67        Self::new()
68    }
69}
70
71impl<D: Float, T: Tensor<D, RANK> + EagerTensor, const RANK: usize> Layer<T> for Relu6<D, T, RANK> {
72    type Output = T;
73    fn call(&self, _input: T) -> Self::Output {
74        todo!()
75    }
76}
77
78/// Hard-sigmoid activation layer: a piecewise-linear sigmoid approximation.
79pub struct Hardsigmoid<D: Float, T, const RANK: usize> {
80    _pd: PhantomData<(D, T)>,
81}
82
83impl<D: Float, T, const RANK: usize> Hardsigmoid<D, T, RANK> {
84    /// Creates a new `Hardsigmoid` layer.
85    pub fn new() -> Self {
86        Self { _pd: PhantomData }
87    }
88}
89
90impl<D: Float, T, const RANK: usize> Default for Hardsigmoid<D, T, RANK> {
91    fn default() -> Self {
92        Self::new()
93    }
94}
95
96impl<D: Float, T: Tensor<D, RANK> + EagerTensor, const RANK: usize> Layer<T>
97    for Hardsigmoid<D, T, RANK>
98{
99    type Output = T;
100    fn call(&self, _input: T) -> Self::Output {
101        todo!()
102    }
103}
104
105/// Hard-swish activation layer: a piecewise-linear swish approximation.
106pub struct Hardswish<D: Float, T, const RANK: usize> {
107    _pd: PhantomData<(D, T)>,
108}
109
110impl<D: Float, T, const RANK: usize> Hardswish<D, T, RANK> {
111    /// Creates a new `Hardswish` layer.
112    pub fn new() -> Self {
113        Self { _pd: PhantomData }
114    }
115}
116
117impl<D: Float, T, const RANK: usize> Default for Hardswish<D, T, RANK> {
118    fn default() -> Self {
119        Self::new()
120    }
121}
122
123impl<D: Float, T: Tensor<D, RANK> + EagerTensor, const RANK: usize> Layer<T>
124    for Hardswish<D, T, RANK>
125{
126    type Output = T;
127    fn call(&self, _input: T) -> Self::Output {
128        todo!()
129    }
130}
131
132/// Hardshrink activation layer: zeroes values in `[-lambda, lambda]`.
133pub struct Hardshrink<D: Float, T, const RANK: usize> {
134    /// The shrinkage threshold.
135    pub lambda: f64,
136    _pd: PhantomData<(D, T)>,
137}
138
139impl<D: Float, T, const RANK: usize> Hardshrink<D, T, RANK> {
140    /// Creates a new `Hardshrink` layer with the given `lambda`.
141    pub fn new(lambda: f64) -> Self {
142        Self {
143            lambda,
144            _pd: PhantomData,
145        }
146    }
147}
148
149impl<D: Float, T: Tensor<D, RANK> + EagerTensor, const RANK: usize> Layer<T>
150    for Hardshrink<D, T, RANK>
151{
152    type Output = T;
153    fn call(&self, _input: T) -> Self::Output {
154        todo!()
155    }
156}