luma_tensor/device/cpu/kernels/
element.rs1use std::iter::{Product, Sum};
8
9pub trait CpuNum:
11 Copy
12 + PartialOrd
13 + Send
14 + Sync
15 + 'static
16 + std::ops::Add<Output = Self>
17 + std::ops::Sub<Output = Self>
18 + std::ops::Mul<Output = Self>
19 + std::ops::Div<Output = Self>
20 + Sum
21 + Product
22{
23 const ZERO: Self;
24 const ONE: Self;
25
26 fn from_f64(v: f64) -> Self;
27 fn to_f64(self) -> f64;
28 fn from_usize(v: usize) -> Self;
29 fn to_usize(self) -> usize;
30
31 fn minimum(a: Self, b: Self) -> Self {
32 if a > b { b } else { a }
33 }
34 fn maximum(a: Self, b: Self) -> Self {
35 if a < b { b } else { a }
36 }
37 fn abs(self) -> Self;
38 fn signum(self) -> Self;
39}
40
41pub trait CpuFloat: CpuNum + std::ops::Neg<Output = Self> {
43 fn exp(self) -> Self;
44 fn ln(self) -> Self;
45 fn sin(self) -> Self;
46 fn cos(self) -> Self;
47 fn tanh(self) -> Self;
48 fn sqrt(self) -> Self;
49 fn floor(self) -> Self;
50 fn ceil(self) -> Self;
51 fn round(self) -> Self;
52 fn powf(self, e: Self) -> Self;
53 fn recip(self) -> Self;
54 fn erf(self) -> Self;
55
56 fn sqr(self) -> Self {
57 self * self
58 }
59 fn relu(self) -> Self {
60 Self::maximum(self, Self::ZERO)
61 }
62 fn leaky_relu(self, negative_slope: Self) -> Self {
63 if self > Self::ZERO { self } else { self * negative_slope }
64 }
65 fn sigmoid(self) -> Self {
66 Self::ONE / (Self::ONE + (-self).exp())
67 }
68 fn silu(self) -> Self {
69 self / (Self::ONE + (-self).exp())
70 }
71 fn gelu(self) -> Self {
73 let sqrt_2_over_pi = Self::from_f64(0.797_884_560_802_865_4);
74 let coef = Self::from_f64(0.044715);
75 let half = Self::from_f64(0.5);
76 let x3 = self * self * self;
77 let inner = sqrt_2_over_pi * (self + coef * x3);
78 half * self * (Self::ONE + inner.tanh())
79 }
80 fn gelu_erf(self) -> Self {
82 let frac_1_sqrt_2 = Self::from_f64(std::f64::consts::FRAC_1_SQRT_2);
83 let half = Self::from_f64(0.5);
84 half * self * (Self::ONE + (self * frac_1_sqrt_2).erf())
85 }
86}
87
88pub trait CpuInt: CpuNum + Ord + Eq {
91 const MAX: Self;
92}
93
94macro_rules! impl_cpu_float {
96 ($t:ty, $erf:path) => {
97 impl CpuNum for $t {
98 const ZERO: Self = 0.0;
99 const ONE: Self = 1.0;
100 fn from_f64(v: f64) -> Self {
101 v as $t
102 }
103 fn to_f64(self) -> f64 {
104 self as f64
105 }
106 fn from_usize(v: usize) -> Self {
107 v as $t
108 }
109 fn to_usize(self) -> usize {
110 self as usize
111 }
112 fn abs(self) -> Self {
113 <$t>::abs(self)
114 }
115 fn signum(self) -> Self {
116 <$t>::signum(self)
117 }
118 }
119 impl CpuFloat for $t {
120 fn exp(self) -> Self {
121 <$t>::exp(self)
122 }
123 fn ln(self) -> Self {
124 <$t>::ln(self)
125 }
126 fn sin(self) -> Self {
127 <$t>::sin(self)
128 }
129 fn cos(self) -> Self {
130 <$t>::cos(self)
131 }
132 fn tanh(self) -> Self {
133 <$t>::tanh(self)
134 }
135 fn sqrt(self) -> Self {
136 <$t>::sqrt(self)
137 }
138 fn floor(self) -> Self {
139 <$t>::floor(self)
140 }
141 fn ceil(self) -> Self {
142 <$t>::ceil(self)
143 }
144 fn round(self) -> Self {
145 <$t>::round(self)
146 }
147 fn powf(self, e: Self) -> Self {
148 <$t>::powf(self, e)
149 }
150 fn recip(self) -> Self {
151 <$t>::recip(self)
152 }
153 fn erf(self) -> Self {
154 $erf(self)
155 }
156 }
157 };
158}
159
160impl_cpu_float!(f32, libm::erff);
161impl_cpu_float!(f64, libm::erf);
162
163macro_rules! impl_cpu_int {
165 ($t:ty) => {
166 impl CpuNum for $t {
167 const ZERO: Self = 0;
168 const ONE: Self = 1;
169 fn from_f64(v: f64) -> Self {
170 v as $t
171 }
172 fn to_f64(self) -> f64 {
173 self as f64
174 }
175 fn from_usize(v: usize) -> Self {
176 v as $t
177 }
178 fn to_usize(self) -> usize {
179 self as usize
180 }
181 fn abs(self) -> Self {
182 #[allow(unused_comparisons)]
184 if self < 0 { Self::ZERO.wrapping_sub(self) } else { self }
185 }
186 fn signum(self) -> Self {
187 #[allow(unused_comparisons)]
188 if self > 0 {
189 Self::ONE
190 } else if self < 0 {
191 Self::ZERO.wrapping_sub(Self::ONE)
193 } else {
194 Self::ZERO
195 }
196 }
197 }
198 impl CpuInt for $t {
199 const MAX: Self = <$t>::MAX;
200 }
201 };
202}
203
204impl_cpu_int!(i32);
205impl_cpu_int!(u32);
206impl_cpu_int!(u8);