colorutils_rs/
sigmoidal.rs1use crate::Rgb;
8use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign};
9
10#[derive(Debug, PartialOrd, PartialEq, Copy, Clone)]
11pub struct Sigmoidal {
15 pub sr: f32,
16 pub sg: f32,
17 pub sb: f32,
18}
19
20#[inline]
21fn to_sigmoidal(x: f32) -> f32 {
22 let den = 1f32 + (-x).exp();
23 if den == 0f32 {
24 return 0f32;
25 }
26 1f32 / den
27}
28
29#[inline]
30fn inverse_sigmoidal(x: f32) -> f32 {
31 let den = 1f32 - x;
32 if den == 0f32 {
33 return 0f32;
34 }
35 let k = x / den;
36 if k <= 0f32 {
37 return 0f32;
38 }
39 k.ln()
40}
41
42impl Sigmoidal {
43 #[inline]
44 pub fn new(sr: f32, sg: f32, sb: f32) -> Self {
45 Sigmoidal { sr, sg, sb }
46 }
47
48 #[inline]
49 pub fn from_rgb(rgb: Rgb<u8>) -> Self {
50 let normalized = rgb.to_rgb_f32();
51 Sigmoidal::new(
52 to_sigmoidal(normalized.r),
53 to_sigmoidal(normalized.g),
54 to_sigmoidal(normalized.b),
55 )
56 }
57
58 #[inline]
59 pub fn to_rgb(&self) -> Rgb<u8> {
60 let rgb_normalized = Rgb::new(
61 inverse_sigmoidal(self.sr),
62 inverse_sigmoidal(self.sg),
63 inverse_sigmoidal(self.sb),
64 );
65 rgb_normalized.into()
66 }
67}
68
69impl From<Rgb<u8>> for Sigmoidal {
70 #[inline]
71 fn from(value: Rgb<u8>) -> Self {
72 Sigmoidal::from_rgb(value)
73 }
74}
75
76impl From<Rgb<f32>> for Sigmoidal {
77 #[inline]
78 fn from(value: Rgb<f32>) -> Self {
79 Sigmoidal::new(
80 to_sigmoidal(value.r),
81 to_sigmoidal(value.g),
82 to_sigmoidal(value.b),
83 )
84 }
85}
86
87impl Index<usize> for Sigmoidal {
88 type Output = f32;
89
90 fn index(&self, index: usize) -> &f32 {
91 match index {
92 0 => &self.sr,
93 1 => &self.sg,
94 2 => &self.sb,
95 _ => panic!("Index out of bounds for Sigmoidal"),
96 }
97 }
98}
99
100impl IndexMut<usize> for Sigmoidal {
101 fn index_mut(&mut self, index: usize) -> &mut f32 {
102 match index {
103 0 => &mut self.sr,
104 1 => &mut self.sg,
105 2 => &mut self.sb,
106 _ => panic!("Index out of bounds for Sigmoidal"),
107 }
108 }
109}
110
111impl Add<f32> for Sigmoidal {
112 type Output = Sigmoidal;
113
114 #[inline]
115 fn add(self, rhs: f32) -> Self::Output {
116 Sigmoidal::new(self.sr + rhs, self.sg + rhs, self.sb + rhs)
117 }
118}
119
120impl Sub<f32> for Sigmoidal {
121 type Output = Sigmoidal;
122
123 #[inline]
124 fn sub(self, rhs: f32) -> Self::Output {
125 Sigmoidal::new(self.sr - rhs, self.sg - rhs, self.sb - rhs)
126 }
127}
128
129impl Mul<f32> for Sigmoidal {
130 type Output = Sigmoidal;
131
132 #[inline]
133 fn mul(self, rhs: f32) -> Self::Output {
134 Sigmoidal::new(self.sr * rhs, self.sg * rhs, self.sb * rhs)
135 }
136}
137
138impl Div<f32> for Sigmoidal {
139 type Output = Sigmoidal;
140
141 #[inline]
142 fn div(self, rhs: f32) -> Self::Output {
143 Sigmoidal::new(self.sr / rhs, self.sg / rhs, self.sb / rhs)
144 }
145}
146
147impl Add<Sigmoidal> for Sigmoidal {
148 type Output = Sigmoidal;
149
150 #[inline]
151 fn add(self, rhs: Sigmoidal) -> Self::Output {
152 Sigmoidal::new(self.sr + rhs.sr, self.sg + rhs.sg, self.sb + rhs.sb)
153 }
154}
155
156impl Sub<Sigmoidal> for Sigmoidal {
157 type Output = Sigmoidal;
158
159 #[inline]
160 fn sub(self, rhs: Sigmoidal) -> Self::Output {
161 Sigmoidal::new(self.sr - rhs.sr, self.sg - rhs.sg, self.sb - rhs.sb)
162 }
163}
164
165impl Mul<Sigmoidal> for Sigmoidal {
166 type Output = Sigmoidal;
167
168 #[inline]
169 fn mul(self, rhs: Sigmoidal) -> Self::Output {
170 Sigmoidal::new(self.sr * rhs.sr, self.sg * rhs.sg, self.sb * rhs.sb)
171 }
172}
173
174impl Div<Sigmoidal> for Sigmoidal {
175 type Output = Sigmoidal;
176
177 #[inline]
178 fn div(self, rhs: Sigmoidal) -> Self::Output {
179 Sigmoidal::new(self.sr / rhs.sr, self.sg / rhs.sg, self.sb / rhs.sb)
180 }
181}
182
183impl AddAssign<Sigmoidal> for Sigmoidal {
184 #[inline]
185 fn add_assign(&mut self, rhs: Sigmoidal) {
186 self.sr += rhs.sr;
187 self.sg += rhs.sg;
188 self.sb += rhs.sb;
189 }
190}
191
192impl SubAssign<Sigmoidal> for Sigmoidal {
193 #[inline]
194 fn sub_assign(&mut self, rhs: Sigmoidal) {
195 self.sr -= rhs.sr;
196 self.sg -= rhs.sg;
197 self.sb -= rhs.sb;
198 }
199}
200
201impl MulAssign<Sigmoidal> for Sigmoidal {
202 #[inline]
203 fn mul_assign(&mut self, rhs: Sigmoidal) {
204 self.sr *= rhs.sr;
205 self.sg *= rhs.sg;
206 self.sb *= rhs.sb;
207 }
208}
209
210impl DivAssign<Sigmoidal> for Sigmoidal {
211 #[inline]
212 fn div_assign(&mut self, rhs: Sigmoidal) {
213 self.sr /= rhs.sr;
214 self.sg /= rhs.sg;
215 self.sb /= rhs.sb;
216 }
217}
218
219impl AddAssign<f32> for Sigmoidal {
220 #[inline]
221 fn add_assign(&mut self, rhs: f32) {
222 self.sr += rhs;
223 self.sg += rhs;
224 self.sb += rhs;
225 }
226}
227
228impl SubAssign<f32> for Sigmoidal {
229 #[inline]
230 fn sub_assign(&mut self, rhs: f32) {
231 self.sr -= rhs;
232 self.sg -= rhs;
233 self.sb -= rhs;
234 }
235}
236
237impl MulAssign<f32> for Sigmoidal {
238 #[inline]
239 fn mul_assign(&mut self, rhs: f32) {
240 self.sr *= rhs;
241 self.sg *= rhs;
242 self.sb *= rhs;
243 }
244}
245
246impl DivAssign<f32> for Sigmoidal {
247 #[inline]
248 fn div_assign(&mut self, rhs: f32) {
249 self.sr /= rhs;
250 self.sg /= rhs;
251 self.sb /= rhs;
252 }
253}