pointillism/effects/
distortion.rs1use crate::prelude::*;
7
8#[derive(Clone, Copy, Debug, Default)]
12pub struct InfClip;
13
14impl Map for InfClip {
15 type Input = f64;
16 type Output = f64;
17
18 fn eval(&self, x: f64) -> f64 {
19 x.signum()
20 }
21}
22
23impl<S: Signal> eff::PwMapSgn<S, InfClip> {
24 pub const fn inf_clip(sgn: S) -> Self {
26 Self::new_pw(sgn, InfClip)
27 }
28}
29
30#[derive(Clone, Copy, Debug)]
34pub struct Clip {
35 pub threshold: f64,
37}
38
39impl Clip {
40 #[must_use]
42 pub const fn new(threshold: f64) -> Self {
43 Self { threshold }
44 }
45}
46
47impl Default for Clip {
48 fn default() -> Self {
49 Self::new(1.0)
50 }
51}
52
53impl Map for Clip {
54 type Input = f64;
55 type Output = f64;
56
57 fn eval(&self, x: f64) -> f64 {
58 x.clamp(-self.threshold, self.threshold) / self.threshold
59 }
60}
61
62impl<S: Signal> eff::PwMapSgn<S, Clip> {
63 pub const fn clip(sgn: S, threshold: f64) -> Self {
65 Self::new_pw(sgn, Clip::new(threshold))
66 }
67}
68
69#[derive(Clone, Copy, Debug)]
73pub struct Atan {
74 pub shape: f64,
76}
77
78impl Atan {
79 #[must_use]
81 pub const fn new(shape: f64) -> Self {
82 Self { shape }
83 }
84}
85
86impl Default for Atan {
87 fn default() -> Self {
88 Self::new(1.0)
89 }
90}
91
92impl Map for Atan {
93 type Input = f64;
94 type Output = f64;
95
96 fn eval(&self, x: f64) -> f64 {
97 (self.shape * x).atan() / std::f64::consts::FRAC_PI_2
98 }
99}
100
101impl<S: Signal> eff::PwMapSgn<S, Atan> {
102 pub const fn atan(sgn: S, shape: f64) -> Self {
104 Self::new_pw(sgn, Atan::new(shape))
105 }
106}
107
108#[derive(Clone, Copy, Debug)]
110pub struct Pow {
111 pub exponent: u16,
113}
114
115impl Pow {
116 #[must_use]
118 pub const fn new(exponent: u16) -> Self {
119 Self { exponent }
120 }
121
122 #[must_use]
124 pub const fn linear() -> Self {
125 Self::new(1)
126 }
127
128 #[must_use]
130 pub const fn cubic() -> Self {
131 Self::new(3)
132 }
133}
134
135impl Default for Pow {
136 fn default() -> Self {
137 Self::linear()
138 }
139}
140
141impl Map for Pow {
142 type Input = f64;
143 type Output = f64;
144
145 fn eval(&self, x: f64) -> f64 {
146 let res = x.powi(i32::from(self.exponent));
147
148 if self.exponent % 2 == 0 {
149 map::sgn(res)
150 } else {
151 res
152 }
153 }
154}
155
156impl<S: Signal> eff::PwMapSgn<S, Pow> {
157 pub const fn pow(sgn: S, exponent: u16) -> Self {
159 Self::new_pw(sgn, Pow::new(exponent))
160 }
161
162 pub const fn cubic(sgn: S) -> Self {
164 Self::pow(sgn, 3)
165 }
166}
167
168