1use crate::float::Float;
3use num_complex::Complex;
4use std::mem::MaybeUninit;
5
6pub const CHUNK: usize = 4096;
8
9pub const fn running(size: usize) -> usize {
11 let wasm = cfg!(target_arch = "wasm32");
12 if size >= 16 { if wasm { 8 } else { 16 } } else if wasm && size == 8 { 16 } else { 32 }
13}
14
15#[derive(Clone, Copy, Debug)]
17pub enum Arg<'a, T> { One(T), Many(&'a [T]) }
18
19impl<'a, T: Copy> Arg<'a, T> {
20 pub fn of(items: &'a [T]) -> Self { if let [x] = *items { Arg::One(x) } else { Arg::Many(items) } }
22 #[inline(always)]
24 pub fn nth(self, i: usize) -> T { match self { Arg::One(v) => v, Arg::Many(s) => s[i] } }
25 #[inline(always)]
27 pub fn one(self) -> Option<T> { match self { Arg::One(v) => Some(v), Arg::Many(_) => None } }
28 #[inline]
30 pub fn converted<'b, A>(self, start: usize, n: usize, buf: &'b mut Vec<A>, f: impl Fn(T) -> A) -> Arg<'b, A> {
31 match self.part(start, n) {
32 Arg::One(v) => Arg::One(f(v)),
33 Arg::Many(items) => {
34 buf.clear();
35 buf.extend(items.iter().map(|&v| f(v)));
36 Arg::Many(buf)
37 }
38 }
39 }
40
41 #[inline(always)]
43 pub fn part(self, start: usize, n: usize) -> Self { match self { Arg::One(v) => Arg::One(v), Arg::Many(s) => Arg::Many(&s[start..start + n]) } }
44}
45
46pub trait KernelItem: Copy + Send + Sync {
48 const NAN: bool;
50 fn has_nan(self) -> bool;
52}
53
54macro_rules! nan_items { ($($t:ty),+) => {$( impl KernelItem for $t { const NAN: bool = true; #[inline(always)] fn has_nan(self) -> bool { self.is_nan() } } )+} }
55nan_items!(f32, f64, half::f16, Complex<f32>, Complex<f64>);
56macro_rules! exact_items { ($($t:ty),+) => {$( impl KernelItem for $t { const NAN: bool = false; #[inline(always)] fn has_nan(self) -> bool { false } } )+} }
57exact_items!(u8, i16, i32, i64, bool, char, std::cmp::Ordering);
58
59pub trait Results<T, const N: usize> {
61 type Out: KernelItem;
63 const TOTAL: bool;
65}
66
67macro_rules! arities {
69 ($($(#[$doc:meta])* $name:ident<$n:literal>($($x:ident),+);)+) => {$(
70 $(#[$doc])*
71 pub unsafe trait $name<T>: Results<T, $n> + Sync {
75 fn one(&self, $($x: T),+) -> Self::Out;
76 fn judged(&self, $($x: T),+) -> (Self::Out, bool);
77 fn slice(&self, args: [Arg<'_, T>; $n], n: usize, out: &mut [MaybeUninit<Self::Out>]) -> bool;
78 #[inline]
79 fn checked(&self, $($x: T),+) -> Option<Self::Out> { let (r, ok) = self.judged($($x),+); ok.then_some(r) }
80 fn many(&self, $($x: Arg<'_, T>,)+ n: usize, out: &mut Vec<Self::Out>) -> bool where T: Copy + Sync {
81 unsafe { appended(out, n, |slots| crate::parallel::split(slots, CHUNK, &|start, slots| {
82 crate::parallel::in_chunks(start, slots, |at, part| self.slice([$($x.part(at, part.len())),+], part.len(), part))
83 })) }
84 }
85 fn many_into(&self, $($x: Arg<'_, T>,)+ n: usize, out: &mut crate::parallel::Slots<'_, Self::Out>) -> bool where T: Copy {
86 unsafe { out.fill(n, |slots| crate::parallel::in_chunks(0, slots, |at, part| self.slice([$($x.part(at, part.len())),+], part.len(), part))) }
88 }
89 }
90 )+};
91}
92
93arities! {
94 Unary<1>(x);
96 Binary<2>(x, y);
98 Ternary<3>(x, y, z);
100}
101
102#[derive(Clone, Copy, Debug)]
104pub struct Flipped<K>(pub K);
105
106impl<T, K: Results<T, 2>> Results<T, 2> for Flipped<K> {
107 type Out = K::Out;
108 const TOTAL: bool = K::TOTAL;
109}
110unsafe impl<T, K: Binary<T>> Binary<T> for Flipped<K> {
111 fn one(&self, x: T, y: T) -> K::Out { self.0.one(y, x) }
112 fn judged(&self, x: T, y: T) -> (K::Out, bool) { self.0.judged(y, x) }
113 fn slice(&self, [x, y]: [Arg<'_, T>; 2], n: usize, out: &mut [MaybeUninit<K::Out>]) -> bool { self.0.slice([y, x], n, out) }
114}
115
116#[derive(Clone, Copy, Debug)]
118pub struct Wrapped<K>(pub K);
119
120impl<T, K: Results<T, N>, const N: usize> Results<T, N> for Wrapped<K> {
121 type Out = K::Out;
122 const TOTAL: bool = true;
123}
124macro_rules! wrapped {
125 ($arity:ident, $n:literal, $($x:ident),+) => {
126 unsafe impl<T: KernelItem, K: $arity<T>> $arity<T> for Wrapped<K> {
127 fn one(&self, $($x: T),+) -> K::Out { self.0.one($($x),+) }
128 fn judged(&self, $($x: T),+) -> (K::Out, bool) { (self.0.one($($x),+), true) }
129 fn slice(&self, x: [Arg<'_, T>; $n], n: usize, out: &mut [MaybeUninit<K::Out>]) -> bool {
130 each(x, n, out, #[inline(always)] |[$($x),+]| Total(self.0.one($($x),+)))
131 }
132 }
133 };
134}
135wrapped!(Unary, 1, x);
136wrapped!(Binary, 2, x, y);
137wrapped!(Ternary, 3, x, y, z);
138
139#[inline(always)]
141pub(crate) fn kept<O: KernelItem, E: KernelItem, const N: usize>(r: O, args: [E; N]) -> bool { !r.has_nan() | args.iter().any(|a| a.has_nan()) }
142
143pub(crate) trait Outcome<O: KernelItem>: Sized {
145 const RESCUE: bool;
147 const TOTAL: bool;
149 fn value(self) -> O;
151 fn split(self) -> (O, bool);
153 #[inline(always)]
155 fn judged<E: KernelItem, const N: usize>(self, args: [E; N]) -> (O, bool) { let (r, ok) = self.split(); (r, ok || (Self::RESCUE && kept(r, args))) }
156}
157
158impl<O: KernelItem> Outcome<O> for O {
159 const RESCUE: bool = true;
160 const TOTAL: bool = !O::NAN;
161 #[inline(always)]
162 fn value(self) -> O { self }
163 #[inline(always)]
164 fn split(self) -> (O, bool) { (self, !self.has_nan()) }
165}
166
167impl<O: KernelItem + Default> Outcome<O> for Option<O> {
168 const RESCUE: bool = false;
169 const TOTAL: bool = false;
170 #[inline(always)]
171 fn value(self) -> O { self.expect("the result doesn't fit the output type") }
172 #[inline(always)]
173 fn split(self) -> (O, bool) { (self.unwrap_or_default(), self.is_some()) }
174}
175
176impl<O: KernelItem> Outcome<O> for (O, bool) {
178 const RESCUE: bool = false;
179 const TOTAL: bool = false;
180 #[inline(always)]
181 fn value(self) -> O { self.0 }
182 #[inline(always)]
183 fn split(self) -> (O, bool) { self }
184}
185
186#[derive(Clone, Copy)]
188pub(crate) struct Total<O>(pub O);
189
190impl<O: KernelItem> Outcome<O> for Total<O> {
191 const RESCUE: bool = false;
192 const TOTAL: bool = true;
193 #[inline(always)]
194 fn value(self) -> O { self.0 }
195 #[inline(always)]
196 fn split(self) -> (O, bool) { (self.0, true) }
197}
198
199pub(crate) const fn total<K, E, O: KernelItem, R: Outcome<O>, const N: usize>(_: fn(&K, [E; N]) -> R) -> bool { R::TOTAL }
201
202#[inline(always)]
204fn items<E: Copy, const N: usize>(x: &[Arg<'_, E>; N], i: usize) -> [E; N] { std::array::from_fn(|k| x[k].nth(i)) }
205
206#[inline(always)]
208pub fn mapped<E: Copy, O, const N: usize>(x: &[Arg<'_, E>; N], n: usize, out: &mut [MaybeUninit<O>], f: impl Fn([E; N]) -> (O, bool)) -> bool {
209 if const { N == 1 } { pairs_into(x[0], Arg::One(()), n, out, #[inline(always)] |a, ()| f([a; N])) }
210 else if const { N == 2 } {
211 pairs_into(x[0], x[1], n, out, #[inline(always)] |a, b| f(std::array::from_fn(|k| if k == 0 { a } else { b })))
212 } else if const { N == 3 } {
213 triples_into(x[0], x[1], x[2], n, out, #[inline(always)] |a, b, c| {
214 f(std::array::from_fn(|k| match k { 0 => a, 1 => b, _ => c }))
215 })
216 } else { unreachable!("function objects take one to three arguments") }
217}
218
219#[inline(always)]
221pub(crate) fn each<E: KernelItem, O: KernelItem, R: Outcome<O>, const N: usize>(
222 x: [Arg<'_, E>; N], n: usize, out: &mut [MaybeUninit<O>], f: impl Fn([E; N]) -> R) -> bool {
223 mapped(
224 &x, n, out, #[inline(always)] |a| f(a).split()
225 ) || (R::RESCUE && unsafe { written(&mut out[..n]) }.iter().enumerate().all(|(i, &r)| kept(r, items(&x, i))))
226}
227
228pub(crate) fn none<E, O>() -> (impl Fn(E) -> bool, impl Fn(E) -> O) { (|_| false, |_| unreachable!("`none` accepts no item")) }
230
231#[inline(always)]
233pub(crate) fn blocks<E: Copy, O, const BLOCK: usize>(
234 xs: &[E], out: &mut [MaybeUninit<O>], uniform: impl Fn(&[E; BLOCK]) -> (bool, bool), first: impl Fn(E) -> O, second: impl Fn(E) -> O,
235 mut mixed: impl FnMut(&[E], &mut [MaybeUninit<O>]) -> bool) -> bool {
236 let (blocks, rest) = xs.as_chunks::<BLOCK>();
237 let (slots, last) = out[..xs.len()].split_at_mut(blocks.len() * BLOCK);
238 let mut ok = true;
239 for (b, o) in blocks.iter().zip(slots.as_chunks_mut::<BLOCK>().0) {
240 let (one, two) = uniform(b);
241 if one { for k in 0..BLOCK { o[k].write(first(b[k])); } } else if two { for k in 0..BLOCK { o[k].write(second(b[k])); } } else { ok &= mixed(b, o) }
242 }
243 ok & mixed(rest, last)
244}
245
246#[inline(always)]
248pub(crate) fn each_usual<E: KernelItem, O: KernelItem, R: Outcome<O>>(
249 x: Arg<'_, E>, n: usize, out: &mut [MaybeUninit<O>], usual: (impl Fn(E) -> bool, impl Fn(E) -> O), rare: (impl Fn(E) -> bool, impl Fn(E) -> O),
250 body: impl Fn(E) -> R) -> bool {
251 let Arg::Many(xs) = x else { return each([x], n, out, #[inline(always)] |[x]| body(x)); };
252 blocks::<_, _, 64>(
254 &xs[..n], out, #[inline(always)] |b| b.iter().fold((true, true), |(one, two), &v| (one & (usual.0)(v), two & (rare.0)(v))), usual.1, rare.1,
255 #[inline(always)] |b, o| {
256 each([Arg::Many(b)], b.len(), o, #[inline(always)] |[x]| body(x))
257 })
258}
259
260macro_rules! usual_object {
262 ($(#[doc = $doc:literal])* $object:ident: $name:ident, $usual:expr => $fast:expr $(, $rare:expr => $value:expr)? $(; $outcome:ident)?) => {
263 $(#[doc = $doc])*
264 #[derive(Clone, Copy, Debug)]
265 pub struct $object;
266 forms!($object at real: |_, [x]| usual_object!(@outcome [$($outcome)?], $name::<_, { crate::FUSED }>(x)),
267 many |_, [x], n, out| crate::slice::each_usual(x, n, out, ($usual, $fast), usual_object!(@rare $($rare, $value)?),
268 #[inline(always)] |x| usual_object!(@outcome [$($outcome)?], $name::<_, { crate::FUSED }>(x))));
269 };
270 (@rare) => { crate::slice::none() };
271 (@rare $rare:expr, $value:expr) => { ($rare, $value) };
272 (@outcome [], $e:expr) => { $e };
273 (@outcome [total], $e:expr) => { crate::slice::Total($e) };
274}
275
276macro_rules! each {
278 ($x:expr, $n:expr, $out:expr, |$args:pat_param| $body:expr $(,)?) => {
279 crate::slice::each(
280 $x, $n, $out, #[inline(always)] |$args| $body,
281 )
282 };
283}
284
285macro_rules! forms {
297 ($(#[$($m:tt)+])* $object:ident at real $(=> $o:ty)? : |$k:pat_param, $args:tt| $body:expr $(, many |$mk:pat_param, $margs:tt, $n:ident, $out:ident| $many:expr)?) => {
298 forms!(@types [$(#[$($m)+])*], $object, $k, $args, $body, [$((|$mk, $margs, $n, $out| $many))?], [f32 $(=> $o)?, f64 $(=> $o)?]);
299 forms!(@half [$(#[$($m)+])*], $object, forms!(@out half::f16 $(, $o)?), forms!(@narrow $($o)?), $args);
300 };
301 ($(#[$($m:tt)+])* $object:ident at $($e:ty $(=> $o:ty)?),+ : |$k:pat_param, $args:tt| $body:expr $(, many |$mk:pat_param, $margs:tt, $n:ident, $out:ident| $many:expr)?) => {
302 forms!(@types [$(#[$($m)+])*], $object, $k, $args, $body, [$((|$mk, $margs, $n, $out| $many))?], [$($e $(=> $o)?),+]);
303 };
304 ($(#[$($m:tt)+])* [$object:ty] at $($e:ty $(=> $o:ty)?),+ : |$k:pat_param, $args:tt| $body:expr $(, many |$mk:pat_param, $margs:tt, $n:ident, $out:ident| $many:expr)?) => {
306 forms!(@types [$(#[$($m)+])*], $object, $k, $args, $body, [$((|$mk, $margs, $n, $out| $many))?], [$($e $(=> $o)?),+]);
307 };
308 (@types $attrs:tt, $object:ty, $k:pat_param, $args:tt, $body:expr, $many:tt, [$e:ty $(=> $o:ty)? $(, $($rest:tt)+)?]) => {
310 forms!(@concrete $attrs, $object, $e, forms!(@out $e $(, $o)?), $k, $args, $body, $many);
311 $(forms!(@types $attrs, $object, $k, $args, $body, $many, [$($rest)+]);)?
312 };
313 (@concrete $attrs:tt, $object:ty, $e:ty, $o:ty, $k:pat_param, [$x:ident], $body:expr, $many:tt) => {
314 forms!(@impl $attrs, $object, Unary, 1, $e, $o, $k, [$x], $body, $many);
315 };
316 (@concrete $attrs:tt, $object:ty, $e:ty, $o:ty, $k:pat_param, [$x:ident, $y:ident], $body:expr, $many:tt) => {
317 forms!(@impl $attrs, $object, Binary, 2, $e, $o, $k, [$x, $y], $body, $many);
318 };
319 (@concrete $attrs:tt, $object:ty, $e:ty, $o:ty, $k:pat_param, [$x:ident, $y:ident, $z:ident], $body:expr, $many:tt) => {
320 forms!(@impl $attrs, $object, Ternary, 3, $e, $o, $k, [$x, $y, $z], $body, $many);
321 };
322 (@impl [$(#[$($m:tt)+])*], $object:ty, $arity:ident, $arity_n:literal, $e:ty, $o:ty, $k:pat_param, [$($x:ident),+], $body:expr, $many:tt) => {
323 impl crate::slice::Results<$e, $arity_n> for $object {
324 type Out = $o;
325 const TOTAL: bool = crate::slice::total::<Self, $e, $o, _, $arity_n>(|$k, [$($x),+]| $body);
326 }
327 unsafe impl crate::slice::$arity<$e> for $object {
328 $(#[$($m)+])*
329 fn one(&self, $($x: $e),+) -> $o {
330 let $k = self;
331 crate::slice::Outcome::<$o>::value($body)
332 }
333 $(#[$($m)+])*
334 fn judged(&self, $($x: $e),+) -> ($o, bool) {
335 let $k = self;
336 crate::slice::Outcome::<$o>::judged($body, [$($x),+])
337 }
338 forms!(@slice $e => $o, $k, [$($x),+], $body, $many);
339 }
340 };
341 (@slice $e:ty => $o:ty, $k:pat_param, [$($x:ident),+], $body:expr, []) => {
342 fn slice(&self, args: [crate::Arg<'_, $e>; forms!(@n $($x),+)], n: usize, out: &mut [std::mem::MaybeUninit<$o>]) -> bool {
343 let $k = self;
344 each!(args, n, out, |[$($x),+]| $body)
345 }
346 };
347 (@slice $e:ty => $o:ty, $k:pat_param, $args:tt, $body:expr, [(|$mk:pat_param, [$($mx:ident),+], $n:ident, $out:ident| $many:expr)]) => {
348 fn slice(&self, [$($mx),+]: [crate::Arg<'_, $e>; forms!(@n $($mx),+)], $n: usize, $out: &mut [std::mem::MaybeUninit<$o>]) -> bool {
349 let $mk = self;
350 $many
351 }
352 };
353 (@half $attrs:tt, $object:ty, $o:ty, $narrow:expr, [$x:ident]) => { forms!(@half_impl $attrs, $object, Unary, 1, $o, $narrow, [$x]); };
354 (@half $attrs:tt, $object:ty, $o:ty, $narrow:expr, [$x:ident, $y:ident]) => { forms!(@half_impl $attrs, $object, Binary, 2, $o, $narrow, [$x, $y]); };
355 (@half $attrs:tt, $object:ty, $o:ty, $narrow:expr, [$x:ident, $y:ident, $z:ident]) => { forms!(@half_impl $attrs, $object, Ternary, 3, $o, $narrow, [$x, $y, $z]); };
356 (@half_impl [$(#[$($m:tt)+])*], $object:ty, $arity:ident, $arity_n:literal, $o:ty, $narrow:expr, [$($x:ident),+]) => {
357 impl crate::slice::Results<half::f16, $arity_n> for $object {
358 type Out = $o;
359 const TOTAL: bool = <Self as crate::slice::Results<f32, $arity_n>>::TOTAL;
360 }
361 unsafe impl crate::slice::$arity<half::f16> for $object {
362 $(#[$($m)+])*
363 fn one(&self, $($x: half::f16),+) -> $o { ($narrow)(crate::slice::$arity::<f32>::one(self, $($x.to_f32()),+)) }
364 $(#[$($m)+])*
365 fn judged(&self, $($x: half::f16),+) -> ($o, bool) {
366 let (r, ok) = crate::slice::$arity::<f32>::judged(self, $($x.to_f32()),+);
367 (($narrow)(r), ok)
368 }
369 fn slice(&self, x: [crate::Arg<'_, half::f16>; $arity_n], n: usize, out: &mut [std::mem::MaybeUninit<$o>]) -> bool {
370 crate::slice::working(x, n, out, |x, m, o| crate::slice::$arity::<f32>::slice(self, x, m, o), $narrow)
371 }
372 }
373 };
374 (@out $e:ty) => { $e };
375 (@out $e:ty, $o:ty) => { $o };
376 (@narrow) => { half::f16::from_f32 };
377 (@narrow $o:ty) => { std::convert::identity };
378 (@n $($x:ident),+) => { [$(stringify!($x)),+].len() };
379}
380
381macro_rules! each_pair {
383 ($x:expr, $y:expr, $n:expr, |$i:ident, $a:ident, $b:ident| $body:expr) => {{
384 let n = $n;
385 match ($x, $y) {
386 (Arg::One($a), Arg::One($b)) => {
387 for $i in 0..n {
388 $body
389 }
390 }
391 (Arg::One($a), Arg::Many(ys)) => {
392 let ys = &ys[..n];
393 for $i in 0..n {
394 let $b = ys[$i];
395 $body
396 }
397 }
398 (Arg::Many(xs), Arg::One($b)) => {
399 let xs = &xs[..n];
400 for $i in 0..n {
401 let $a = xs[$i];
402 $body
403 }
404 }
405 (Arg::Many(xs), Arg::Many(ys)) => {
406 let (xs, ys) = (&xs[..n], &ys[..n]);
407 for $i in 0..n {
408 let ($a, $b) = (xs[$i], ys[$i]);
409 $body
410 }
411 }
412 }
413 }};
414}
415
416macro_rules! each_triple {
418 ($x:expr, $y:expr, $z:expr, $n:expr, |$i:ident, $a:ident, $b:ident, $c:ident| $body:expr) => {{
419 let n = $n;
420 match $x {
421 Arg::One($a) => each_pair!($y, $z, n, |$i, $b, $c| $body),
422 Arg::Many(firsts) => {
423 let firsts = &firsts[..n];
424 each_pair!($y, $z, n, |$i, $b, $c| {
425 let $a = firsts[$i];
426 $body
427 })
428 }
429 }
430 }};
431}
432
433#[inline(never)]
435pub fn pairs<X: Copy + Sync, Y: Copy + Sync, B: Send>(x: Arg<'_, X>, y: Arg<'_, Y>, n: usize, out: &mut Vec<B>, f: impl Fn(X, Y) -> (B, bool) + Sync) -> bool {
436 unsafe {
437 appended(out, n, |slots| {
438 crate::parallel::split(slots, CHUNK, &|start, slots| {
439 pairs_into(x.part(start, slots.len()), y.part(start, slots.len()), slots.len(), slots, |a, b| f(a, b))
440 })
441 })
442 }
443}
444
445#[inline]
447pub(crate) fn pairs_into<X: Copy, Y: Copy, B>(x: Arg<'_, X>, y: Arg<'_, Y>, n: usize, out: &mut [MaybeUninit<B>], f: impl Fn(X, Y) -> (B, bool)) -> bool {
448 triples_into(Arg::One(()), x, y, n, out, #[inline(always)] |(), a, b| f(a, b))
449}
450
451#[inline]
453pub(crate) fn triples_into<X: Copy, Y: Copy, Z: Copy, B>(
454 x: Arg<'_, X>, y: Arg<'_, Y>, z: Arg<'_, Z>, n: usize, out: &mut [MaybeUninit<B>], f: impl Fn(X, Y, Z) -> (B, bool)) -> bool {
455 let (out, mut ok) = (&mut out[..n], true);
456 each_triple!(x, y, z, n, |i, a, b, c| {
457 let (r, good) = f(a, b, c);
458 out[i].write(r);
459 ok &= good;
460 });
461 ok
462}
463
464#[inline(always)]
466pub fn judged<E: Copy, O: Copy, const N: usize>(x: &[Arg<'_, E>; N], out: &[O], valid: impl Fn([E; N], O) -> bool) -> bool {
467 let (n, mut bad) = (out.len(), 0u8);
468 if const { N == 1 } { each_pair!(x[0], Arg::Many(out), n, |_i, a, r| bad |= u8::from(!valid([a; N], r))); }
469 else if const { N == 2 } {
470 each_triple!(x[0], x[1], Arg::Many(out), n, |_i, a, b, r| bad |= u8::from(!valid(std::array::from_fn(|k| if k == 0 { a } else { b }), r)));
471 } else { for i in 0..n { bad |= u8::from(!valid(items(x, i), out[i])); } }
472 bad == 0
473}
474
475#[inline(always)]
480pub unsafe fn appended<B, T>(out: &mut Vec<B>, n: usize, write: impl FnOnce(&mut [MaybeUninit<B>]) -> T) -> T {
481 out.reserve(n);
482 let result = write(&mut out.spare_capacity_mut()[..n]);
483 unsafe { out.set_len(out.len() + n) }
485 result
486}
487
488#[inline(always)]
493pub unsafe fn written<B>(out: &mut [MaybeUninit<B>]) -> &mut [B] {
494 unsafe { &mut *(std::ptr::from_mut(out) as *mut [B]) }
496}
497
498#[inline(always)]
500pub(crate) fn two_pass<R, O, const N: usize>(
501 x: [Arg<'_, R>; N], n: usize, out: &mut [MaybeUninit<O>], fast: impl Fn([R; N]) -> Option<R>, f: impl Fn([R; N]) -> R) -> bool where
502 R: crate::Float + crate::buffer::Source<O>, O: crate::Float {
503 let out = &mut out[..n];
504 let first = mapped(&x, n, out, #[inline(always)] |a| {
505 let r = <R as crate::buffer::Source<O>>::read(fast(a).unwrap_or(R::nan()));
506 (r, !r.is_nan())
507 });
508 if first { return true; }
509 let mut ok = true;
510 for (i, r) in unsafe { written(out) }.iter_mut().enumerate().filter(|(_, r)| r.is_nan()) {
511 let a = items(&x, i);
512 *r = <R as crate::buffer::Source<O>>::read(f(a));
513 ok &= kept(*r, a);
514 }
515 ok
516}
517
518pub(crate) fn working<F: Float, O: Copy, P, const N: usize>(
520 x: [Arg<'_, F>; N], n: usize, out: &mut [MaybeUninit<P>], f: impl Fn([Arg<'_, F::Working>; N], usize, &mut [MaybeUninit<O>]) -> bool,
521 narrow: impl Fn(O) -> P) -> bool {
522 let mut bufs = [(); N].map(|()| Vec::new());
523 let mut next = bufs.each_mut().into_iter();
524 unsafe { buffered(n, out, |o| f(x.map(|a| a.converted(0, n, next.next().unwrap(), F::working)), n, o), narrow) }
525}
526
527pub unsafe fn buffered<O: Copy, P>(n: usize, out: &mut [MaybeUninit<P>], f: impl FnOnce(&mut [MaybeUninit<O>]) -> bool, each: impl Fn(O) -> P) -> bool {
532 let mut rs = Vec::new();
533 let ok = unsafe { appended(&mut rs, n, f) };
534 pairs_into(Arg::Many(&rs), Arg::One(()), n, &mut out[..n], |r, ()| (each(r), true));
535 ok
536}