1#[inline]
7pub fn gain_block_scalar(buf: &mut [f64], gain: f64) {
8 for s in buf {
9 *s *= gain;
10 }
11}
12
13#[inline]
14pub fn gain_block(buf: &mut [f64], gain: f64) {
15 #[cfg(feature = "wide-backend")]
16 {
17 use wide::f64x4;
18 let g = f64x4::splat(gain);
19 let n = buf.len();
20 let n4 = n / 4 * 4;
21 let (head, tail) = buf.split_at_mut(n4);
22 for chunk in head.chunks_exact_mut(4) {
23 let v = f64x4::from(<[f64; 4]>::try_from(&chunk[..]).unwrap_or_default());
24 chunk.copy_from_slice((v * g).as_array_ref());
25 }
26 gain_block_scalar(tail, gain);
27 }
28 #[cfg(not(feature = "wide-backend"))]
29 gain_block_scalar(buf, gain);
30}
31
32#[inline]
33pub fn scale_block_scalar(out: &mut [f64], src: &[f64], scale: f64) {
34 let n = out.len().min(src.len());
35 for i in 0..n {
36 out[i] = src[i] * scale;
37 }
38}
39
40#[inline]
41pub fn scale_block(out: &mut [f64], src: &[f64], scale: f64) {
42 #[cfg(feature = "wide-backend")]
43 {
44 use wide::f64x4;
45 let n = out.len().min(src.len());
46 let n4 = n / 4 * 4;
47 let g = f64x4::splat(scale);
48 let (out_v, out_tail) = out[..n].split_at_mut(n4);
49 let src_v = &src[..n4];
50 let src_tail = &src[n4..n];
51 for (out_chunk, src_chunk) in out_v.chunks_exact_mut(4).zip(src_v.chunks_exact(4)) {
52 let v = f64x4::from(<[f64; 4]>::try_from(src_chunk).unwrap_or_default());
53 out_chunk.copy_from_slice((v * g).as_array_ref());
54 }
55 scale_block_scalar(out_tail, src_tail, scale);
56 }
57 #[cfg(not(feature = "wide-backend"))]
58 scale_block_scalar(out, src, scale);
59}
60
61#[inline]
62pub fn mul_block_scalar(out: &mut [f64], a: &[f64], b: &[f64]) {
63 let n = out.len().min(a.len()).min(b.len());
64 for i in 0..n {
65 out[i] = a[i] * b[i];
66 }
67}
68
69#[inline]
70pub fn mul_block(out: &mut [f64], a: &[f64], b: &[f64]) {
71 #[cfg(feature = "wide-backend")]
72 {
73 use wide::f64x4;
74 let n = out.len().min(a.len()).min(b.len());
75 let n4 = n / 4 * 4;
76 let (out_v, out_tail) = out[..n].split_at_mut(n4);
77 let a_v = &a[..n4];
78 let b_v = &b[..n4];
79 let a_tail = &a[n4..n];
80 let b_tail = &b[n4..n];
81 for ((out_chunk, a_chunk), b_chunk) in out_v
82 .chunks_exact_mut(4)
83 .zip(a_v.chunks_exact(4))
84 .zip(b_v.chunks_exact(4))
85 {
86 let av = f64x4::from(<[f64; 4]>::try_from(a_chunk).unwrap_or_default());
87 let bv = f64x4::from(<[f64; 4]>::try_from(b_chunk).unwrap_or_default());
88 out_chunk.copy_from_slice((av * bv).as_array_ref());
89 }
90 mul_block_scalar(out_tail, a_tail, b_tail);
91 }
92 #[cfg(not(feature = "wide-backend"))]
93 mul_block_scalar(out, a, b);
94}
95
96#[inline]
97pub fn mac_block_scalar(out: &mut [f64], src: &[f64], scale: f64) {
98 let n = out.len().min(src.len());
99 for i in 0..n {
100 out[i] += src[i] * scale;
101 }
102}
103
104#[inline]
105pub fn mac_block(out: &mut [f64], src: &[f64], scale: f64) {
106 #[cfg(feature = "wide-backend")]
107 {
108 use wide::f64x4;
109 let n = out.len().min(src.len());
110 let n4 = n / 4 * 4;
111 let (out_v, out_tail) = out[..n].split_at_mut(n4);
112 let src_v = &src[..n4];
113 let src_tail = &src[n4..n];
114 let s = f64x4::splat(scale);
115 for (out_chunk, src_chunk) in out_v.chunks_exact_mut(4).zip(src_v.chunks_exact(4)) {
116 let ov = f64x4::from(<[f64; 4]>::try_from(&out_chunk[..]).unwrap_or_default());
117 let sv = f64x4::from(<[f64; 4]>::try_from(src_chunk).unwrap_or_default());
118 out_chunk.copy_from_slice((ov + sv * s).as_array_ref());
119 }
120 mac_block_scalar(out_tail, src_tail, scale);
121 }
122 #[cfg(not(feature = "wide-backend"))]
123 mac_block_scalar(out, src, scale);
124}
125
126#[inline]
127pub fn mix_block_scalar(out: &mut [f64], a: &[f64], gain_a: f64, b: &[f64], gain_b: f64) {
128 let n = out.len().min(a.len()).min(b.len());
129 for i in 0..n {
130 out[i] = a[i] * gain_a + b[i] * gain_b;
131 }
132}
133
134#[inline]
135pub fn mix_block(out: &mut [f64], a: &[f64], gain_a: f64, b: &[f64], gain_b: f64) {
136 #[cfg(feature = "wide-backend")]
137 {
138 use wide::f64x4;
139 let n = out.len().min(a.len()).min(b.len());
140 let n4 = n / 4 * 4;
141 let (out_v, out_tail) = out[..n].split_at_mut(n4);
142 let a_v = &a[..n4];
143 let b_v = &b[..n4];
144 let a_tail = &a[n4..n];
145 let b_tail = &b[n4..n];
146 let ga = f64x4::splat(gain_a);
147 let gb = f64x4::splat(gain_b);
148 for ((out_chunk, a_chunk), b_chunk) in out_v
149 .chunks_exact_mut(4)
150 .zip(a_v.chunks_exact(4))
151 .zip(b_v.chunks_exact(4))
152 {
153 let av = f64x4::from(<[f64; 4]>::try_from(a_chunk).unwrap_or_default());
154 let bv = f64x4::from(<[f64; 4]>::try_from(b_chunk).unwrap_or_default());
155 out_chunk.copy_from_slice((av * ga + bv * gb).as_array_ref());
156 }
157 mix_block_scalar(out_tail, a_tail, gain_a, b_tail, gain_b);
158 }
159 #[cfg(not(feature = "wide-backend"))]
160 mix_block_scalar(out, a, gain_a, b, gain_b);
161}
162
163#[inline]
164pub fn copy_block(out: &mut [f64], src: &[f64]) {
165 let n = out.len().min(src.len());
166 out[..n].copy_from_slice(&src[..n]);
167}
168
169#[inline]
170pub fn zero_block(buf: &mut [f64]) {
171 buf.fill(0.0);
172}
173
174#[inline]
175#[must_use]
176pub fn abs_max_block(buf: &[f64]) -> f64 {
177 let mut peak = 0.0_f64;
178 for &v in buf {
179 if v.is_nan() {
180 return f64::NAN;
181 }
182 let a = v.abs();
183 if a > peak {
184 peak = a;
185 }
186 }
187 peak
188}