orx_parallel/option_use/par.rs
1// TODO: remove this
2#![allow(clippy::type_complexity)]
3
4use crate::infallible_use::fun::{UFnCloned, UFnCopied};
5use crate::infallible_use::{
6 FilMapOf, FilOf, FlatMapOf, FlattenOf, InsOf, MapOf, MappedOf, XapUse,
7};
8use crate::option_use::ParUseOptionIter;
9use crate::option_use::par_core::ParUseOptionCore;
10use crate::runner::ParRunner;
11use crate::sizes::{OneOne, SizePair};
12use crate::{ChunkSize, IterationOrder, NumThreads, ParExtend, Sum};
13use core::cmp::Ordering;
14use orx_concurrent_iter::ExactSizeConcurrentIter;
15
16/// Fallible parallel iterator with worker-local mutable state.
17///
18/// `ParUseOption` combines:
19/// - fallible processing (`Option`-based short-circuiting), and
20/// - mutable worker-local state (`&mut Use` passed to closures).
21///
22/// You can enter this mode from [`ParOption`](crate::ParOption) via
23/// [`use_new`](crate::ParOption::use_new),
24/// [`use_vec`](crate::ParOption::use_vec), or
25/// [`use_slice`](crate::ParOption::use_slice).
26///
27/// Similar to using `?`, this trait keeps pipeline logic focused on successful
28/// values while the computation short-circuits to `None` when any element
29/// evaluates to `None`.
30///
31/// Related traits:
32/// - [`ParOption`](crate::ParOption) for `Option`-fallible pipelines without worker-local state,
33/// - [`ParUse`](crate::ParUse) for worker-local state in infallible pipelines.
34///
35/// # Examples
36///
37/// Reusing a per-worker buffer:
38///
39/// ```
40/// use core::fmt::Write;
41/// use orx_parallel::*;
42///
43/// let out: Option<Vec<usize>> = (0..16usize)
44/// .into_par()
45/// .map(Some)
46/// .into_optional()
47/// .use_new(|_| String::with_capacity(32))
48/// .map(|buffer, x| {
49/// buffer.clear();
50/// write!(buffer, "{x}").unwrap();
51/// buffer.parse::<usize>().unwrap()
52/// })
53/// .collect();
54///
55/// assert_eq!(out, Some((0..16).collect::<Vec<_>>()));
56/// ```
57///
58/// Using RNG as mutable worker-local state:
59///
60/// ```
61/// use orx_parallel::*;
62/// use rand::prelude::*;
63/// use rand_chacha::ChaCha8Rng;
64///
65/// let out: Option<Vec<usize>> = (0..32usize)
66/// .into_par()
67/// .map(Some)
68/// .into_optional()
69/// .use_new(|thread_idx| ChaCha8Rng::seed_from_u64(100 + thread_idx as u64))
70/// .map(|rng, x| x + rng.random_range(0..10))
71/// .collect();
72///
73/// assert_eq!(out.as_ref().map(Vec::len), Some(32));
74/// assert!(out.unwrap().into_iter().enumerate().all(|(i, v)| v >= i));
75/// ```
76pub trait ParUseOption: Sized + ParUseOptionCore {
77 // configuration
78
79 /// Replaces the current parallel runner with `runner`.
80 ///
81 /// # Examples
82 ///
83 /// ```
84 /// use orx_parallel::*;
85 ///
86 /// let par = ["1", "2", "3"]
87 /// .into_par()
88 /// .map(|s| s.parse::<usize>().ok())
89 /// .into_optional()
90 /// .use_new(|_| ());
91 ///
92 /// let par = par.runner(Runner::fixed());
93 ///
94 /// let out: Option<Vec<_>> = par.collect();
95 /// assert_eq!(out, Some(vec![1, 2, 3]));
96 /// ```
97 fn runner<Q: ParRunner>(
98 self,
99 runner: Q,
100 ) -> impl ParUseOption<
101 Elem = Self::Elem,
102 Use = Self::Use,
103 Xap1 = Self::Xap1,
104 M = Self::M,
105 Xap2 = Self::Xap2,
106 Input = Self::Input,
107 Size = Self::Size,
108 >;
109
110 /// Wraps the current runner with diagnostics-enabled execution.
111 ///
112 /// # Examples
113 ///
114 /// ```
115 /// use orx_parallel::*;
116 ///
117 /// let par = ["1", "2", "3"]
118 /// .into_par()
119 /// .map(|s| s.parse::<usize>().ok())
120 /// .into_optional()
121 /// .use_new(|_| ());
122 ///
123 /// #[cfg(feature = "std")]
124 /// let par = par.runner_with_diagnostics();
125 ///
126 /// let out: Option<Vec<_>> = par.collect();
127 /// assert_eq!(out, Some(vec![1, 2, 3]));
128 /// ```
129 #[cfg(feature = "std")]
130 fn runner_with_diagnostics(
131 self,
132 ) -> impl ParUseOption<
133 Elem = Self::Elem,
134 Use = Self::Use,
135 Xap1 = Self::Xap1,
136 M = Self::M,
137 Xap2 = Self::Xap2,
138 Input = Self::Input,
139 Size = Self::Size,
140 >;
141
142 /// Sets the maximum number of worker threads for this computation.
143 ///
144 /// # Examples
145 ///
146 /// ```
147 /// use orx_parallel::*;
148 ///
149 /// let out: Option<Vec<_>> = (1..6)
150 /// .into_par()
151 /// .map(Some)
152 /// .into_optional()
153 /// .use_new(|_| ())
154 /// .num_threads(1)
155 /// .collect();
156 ///
157 /// assert_eq!(out, Some(vec![1, 2, 3, 4, 5]));
158 /// ```
159 fn num_threads(self, num_threads: impl Into<NumThreads>) -> Self;
160
161 /// Sets chunk size used when pulling items from the concurrent input.
162 ///
163 /// # Examples
164 ///
165 /// ```
166 /// use orx_parallel::*;
167 ///
168 /// let out: Option<Vec<_>> = (0..8)
169 /// .into_par()
170 /// .map(Some)
171 /// .into_optional()
172 /// .use_new(|_| ())
173 /// .chunk_size(2)
174 /// .collect();
175 ///
176 /// assert_eq!(out, Some((0..8).collect::<Vec<_>>()));
177 /// ```
178 fn chunk_size(self, chunk_size: impl Into<ChunkSize>) -> Self;
179
180 /// Sets iteration-order semantics for order-sensitive operations.
181 ///
182 /// # Examples
183 ///
184 /// ```
185 /// use orx_parallel::*;
186 ///
187 /// let ordered = (1..10_000)
188 /// .into_par()
189 /// .map(Some)
190 /// .into_optional()
191 /// .use_new(|_| ())
192 /// .iteration_order(IterationOrder::Ordered)
193 /// .find(|_, x| x % 3421 == 0);
194 /// assert_eq!(ordered, Some(Some(3421)));
195 /// ```
196 fn iteration_order(self, iteration_order: IterationOrder) -> Self;
197
198 // kind transformations
199
200 /// Copies elements of a reference iterator on the success path.
201 ///
202 /// # Examples
203 ///
204 /// ```
205 /// use orx_parallel::*;
206 ///
207 /// let data = vec![1, 2, 3];
208 /// let out: Option<Vec<_>> = data
209 /// .par()
210 /// .map(Some)
211 /// .into_optional()
212 /// .use_new(|_| ())
213 /// .copied()
214 /// .collect();
215 ///
216 /// assert_eq!(out, Some(vec![1, 2, 3]));
217 /// ```
218 fn copied<'a, O>(
219 self,
220 ) -> impl ParUseOption<
221 Elem = O,
222 Use = Self::Use,
223 Xap1 = Self::Xap1,
224 M = Self::M,
225 Xap2 = MappedOf<Self::Xap2, UFnCopied<'a, Self::Use, O>>,
226 Input = Self::Input,
227 Size = Self::Size,
228 >
229 where
230 Self: ParUseOption<Elem = &'a O>,
231 O: Copy + 'a,
232 Self::Use: 'a,
233 {
234 let (u, iter, x1, x2, exe, _, params) = self.destruct();
235 ParUseOptionIter::new(u, iter, x1, x2.mapped(UFnCopied::new()), exe, params)
236 }
237
238 /// Clones elements of a reference iterator on the success path.
239 ///
240 /// # Examples
241 ///
242 /// ```
243 /// use orx_parallel::*;
244 ///
245 /// let data = vec!["a".to_string(), "b".to_string()];
246 /// let out: Option<Vec<_>> = data
247 /// .par()
248 /// .map(Some)
249 /// .into_optional()
250 /// .use_new(|_| ())
251 /// .cloned()
252 /// .collect();
253 ///
254 /// assert_eq!(out, Some(vec!["a".to_string(), "b".to_string()]));
255 /// ```
256 fn cloned<'a, O>(
257 self,
258 ) -> impl ParUseOption<
259 Elem = O,
260 Use = Self::Use,
261 Xap1 = Self::Xap1,
262 M = Self::M,
263 Xap2 = MappedOf<Self::Xap2, UFnCloned<'a, Self::Use, O>>,
264 Input = Self::Input,
265 Size = Self::Size,
266 >
267 where
268 Self: ParUseOption<Elem = &'a O>,
269 O: Clone + 'a,
270 Self::Use: 'a,
271 {
272 let (u, iter, x1, x2, exe, _, params) = self.destruct();
273 ParUseOptionIter::new(u, iter, x1, x2.mapped(UFnCloned::new()), exe, params)
274 }
275
276 // transformations
277
278 /// Maps each successful element with closure `h`.
279 ///
280 /// # Examples
281 ///
282 /// ```
283 /// use orx_parallel::*;
284 ///
285 /// let out: Option<Vec<_>> = (1..4)
286 /// .into_par()
287 /// .map(Some)
288 /// .into_optional()
289 /// .use_new(|_| ())
290 /// .map(|_, x| 2 * x)
291 /// .collect();
292 ///
293 /// assert_eq!(out, Some(vec![2, 4, 6]));
294 /// ```
295 fn map<Q, H>(
296 self,
297 h: H,
298 ) -> impl ParUseOption<
299 Elem = Q,
300 Use = Self::Use,
301 Xap1 = Self::Xap1,
302 M = Self::M,
303 Xap2 = MapOf<Self::Xap2, Q, H>,
304 Input = Self::Input,
305 Size = Self::Size,
306 >
307 where
308 H: Fn(&mut Self::Use, Self::Elem) -> Q + Copy + Send;
309
310 /// Runs `h` on each successful element and forwards the item unchanged.
311 ///
312 /// # Examples
313 ///
314 /// ```
315 /// use orx_parallel::*;
316 ///
317 /// let mut use_vec = UseVec::new(|_| 0usize);
318 /// let out: Option<Vec<_>> = (1..5)
319 /// .into_par()
320 /// .map(Some)
321 /// .into_optional()
322 /// .use_vec(&mut use_vec)
323 /// .inspect(|count, _| *count += 1)
324 /// .collect();
325 ///
326 /// assert_eq!(out, Some(vec![1, 2, 3, 4]));
327 /// assert_eq!(use_vec.into_vec().into_iter().sum::<usize>(), 4);
328 /// ```
329 fn inspect<H>(
330 self,
331 h: H,
332 ) -> impl ParUseOption<
333 Elem = Self::Elem,
334 Use = Self::Use,
335 Xap1 = Self::Xap1,
336 M = Self::M,
337 Xap2 = InsOf<Self::Xap2, H>,
338 Input = Self::Input,
339 Size = Self::Size,
340 >
341 where
342 H: Fn(&mut Self::Use, &Self::Elem) + Copy + Send;
343
344 /// Keeps successful elements satisfying predicate `h`.
345 ///
346 /// # Examples
347 ///
348 /// ```
349 /// use orx_parallel::*;
350 ///
351 /// let out: Option<Vec<_>> = (1..7)
352 /// .into_par()
353 /// .map(Some)
354 /// .into_optional()
355 /// .use_new(|_| ())
356 /// .filter(|_, x| x % 2 == 1)
357 /// .collect();
358 ///
359 /// assert_eq!(out, Some(vec![1, 3, 5]));
360 /// ```
361 fn filter<H>(
362 self,
363 h: H,
364 ) -> impl ParUseOption<
365 Elem = Self::Elem,
366 Use = Self::Use,
367 Xap1 = Self::Xap1,
368 M = Self::M,
369 Xap2 = FilOf<Self::Xap2, H>,
370 Input = Self::Input,
371 Size = <Self::Size as SizePair>::ThenBin,
372 >
373 where
374 H: Fn(&mut Self::Use, &Self::Elem) -> bool + Copy + Send;
375
376 /// Maps and filters successful elements in one pass.
377 ///
378 /// # Examples
379 ///
380 /// ```
381 /// use orx_parallel::*;
382 ///
383 /// let out: Option<Vec<_>> = ["1", "x", "5"]
384 /// .into_par()
385 /// .map(|s| Some(s))
386 /// .into_optional()
387 /// .use_new(|_| ())
388 /// .filter_map(|_, s| s.parse::<usize>().ok())
389 /// .collect();
390 ///
391 /// assert_eq!(out, Some(vec![1, 5]));
392 /// ```
393 fn filter_map<Q, H>(
394 self,
395 h: H,
396 ) -> impl ParUseOption<
397 Elem = Q,
398 Use = Self::Use,
399 Xap1 = Self::Xap1,
400 M = Self::M,
401 Xap2 = FilMapOf<Self::Xap2, Q, H>,
402 Input = Self::Input,
403 Size = <Self::Size as SizePair>::ThenBin,
404 >
405 where
406 H: Fn(&mut Self::Use, Self::Elem) -> Option<Q> + Copy + Send;
407
408 /// Maps each successful element to an iterator and flattens one level.
409 ///
410 /// # Examples
411 ///
412 /// ```
413 /// use orx_parallel::*;
414 ///
415 /// let out: Option<Vec<_>> = (1..4)
416 /// .into_par()
417 /// .map(Some)
418 /// .into_optional()
419 /// .use_new(|_| ())
420 /// .flat_map(|_, x| [x, x + 10])
421 /// .collect();
422 ///
423 /// assert_eq!(out, Some(vec![1, 11, 2, 12, 3, 13]));
424 /// ```
425 fn flat_map<V, H>(
426 self,
427 h: H,
428 ) -> impl ParUseOption<
429 Elem = V::Item,
430 Use = Self::Use,
431 Xap1 = Self::Xap1,
432 M = Self::M,
433 Xap2 = FlatMapOf<Self::Xap2, V, H>,
434 Input = Self::Input,
435 Size = <Self::Size as SizePair>::ThenMany,
436 >
437 where
438 V: IntoIterator,
439 H: Fn(&mut Self::Use, Self::Elem) -> V + Copy + Send;
440
441 /// Flattens one level of nested iterables on the success path.
442 ///
443 /// # Examples
444 ///
445 /// ```
446 /// use orx_parallel::*;
447 ///
448 /// let nested = vec![vec![1, 2], vec![3, 4]];
449 /// let out: Option<Vec<_>> = nested
450 /// .into_par()
451 /// .map(Some)
452 /// .into_optional()
453 /// .use_new(|_| ())
454 /// .flatten()
455 /// .collect();
456 ///
457 /// assert_eq!(out, Some(vec![1, 2, 3, 4]));
458 /// ```
459 fn flatten(
460 self,
461 ) -> impl ParUseOption<
462 Elem = <Self::Elem as IntoIterator>::Item,
463 Use = Self::Use,
464 Xap1 = Self::Xap1,
465 M = Self::M,
466 Xap2 = FlattenOf<Self::Xap2>,
467 Input = Self::Input,
468 Size = <Self::Size as SizePair>::ThenMany,
469 >
470 where
471 Self::Elem: IntoIterator;
472
473 /// Returns a lower and optional upper bound on the number of successful output items.
474 ///
475 /// The bounds follow the usual [`Iterator::size_hint`] convention.
476 /// The upper bound includes items that may be removed by filtering or short-circuiting.
477 ///
478 /// # Examples
479 ///
480 /// ```
481 /// use orx_parallel::*;
482 ///
483 /// let values = (0..4)
484 /// .into_par()
485 /// .map(Some)
486 /// .into_optional()
487 /// .use_new(|_| ())
488 /// .filter(|_, x| x % 2 == 0);
489 ///
490 /// assert_eq!(values.size_hint(), (0, Some(4)));
491 /// ```
492 fn size_hint(&self) -> (usize, Option<usize>);
493
494 /// Returns the exact number of output items.
495 fn len(&self) -> usize
496 where
497 Self::Input: ExactSizeConcurrentIter,
498 Self: ParUseOption<Size = OneOne>,
499 {
500 self.size_hint().0
501 }
502
503 /// Returns `true` when the parallel iterator has no output items.
504 fn is_empty(&self) -> bool
505 where
506 Self::Input: ExactSizeConcurrentIter,
507 Self: ParUseOption<Size = OneOne>,
508 {
509 self.len() == 0
510 }
511
512 // compute
513
514 /// Returns the first successful item according to iteration order.
515 ///
516 /// Returns:
517 /// - `None` if computation short-circuits due to a failure
518 /// - `Some(None)` if no successful element exists
519 /// - `Some(Some(x))` for the first successful element
520 ///
521 /// # Examples
522 ///
523 /// ```
524 /// use orx_parallel::*;
525 ///
526 /// let ok = (1..4)
527 /// .into_par()
528 /// .map(Some)
529 /// .into_optional()
530 /// .use_new(|_| ())
531 /// .first();
532 /// assert_eq!(ok, Some(Some(1)));
533 ///
534 /// let fail = vec![None, Some(1), Some(3)]
535 /// .into_par()
536 /// .into_optional()
537 /// .use_new(|_| ())
538 /// .first();
539 /// assert_eq!(fail, None);
540 /// ```
541 fn first(self) -> Option<Option<Self::Elem>>
542 where
543 Self::Elem: Send;
544
545 /// Reduces successful items into one value using `f`.
546 ///
547 /// Returns `None` on short-circuit failure.
548 ///
549 /// # Examples
550 ///
551 /// ```
552 /// use orx_parallel::*;
553 ///
554 /// let ok = (1..6)
555 /// .into_par()
556 /// .map(Some)
557 /// .into_optional()
558 /// .use_new(|_| ())
559 /// .reduce(|_, a, b| a + b);
560 /// assert_eq!(ok, Some(Some(15)));
561 ///
562 /// let fail = vec![Some(1), None, Some(3)]
563 /// .into_par()
564 /// .into_optional()
565 /// .use_new(|_| ())
566 /// .reduce(|_, a, b| a + b);
567 /// assert_eq!(fail, None);
568 /// ```
569 fn reduce<F>(self, f: F) -> Option<Option<Self::Elem>>
570 where
571 F: Fn(&mut Self::Use, Self::Elem, Self::Elem) -> Self::Elem + Send + Copy,
572 Self::Elem: Send;
573
574 /// Collects successful items into `dst`.
575 ///
576 /// Returns `None` on short-circuit failure.
577 ///
578 /// # Examples
579 ///
580 /// ```
581 /// use orx_parallel::*;
582 ///
583 /// let mut dst = vec![10usize];
584 /// let ok = (0..3)
585 /// .into_par()
586 /// .map(Some)
587 /// .into_optional()
588 /// .use_new(|_| ())
589 /// .collect_into(&mut dst);
590 /// assert_eq!(ok, Some(()));
591 /// assert_eq!(dst, vec![10, 0, 1, 2]);
592 /// ```
593 fn collect_into<P>(self, dst: &mut P) -> Option<()>
594 where
595 P: ParExtend<Self::Elem>,
596 Self::Elem: Send;
597
598 /// Collects successful items into a new collection.
599 ///
600 /// Returns `None` on short-circuit failure.
601 ///
602 /// # Examples
603 ///
604 /// ```
605 /// use orx_parallel::*;
606 ///
607 /// let out: Option<Vec<_>> = (1..4)
608 /// .into_par()
609 /// .map(Some)
610 /// .into_optional()
611 /// .use_new(|_| ())
612 /// .collect();
613 ///
614 /// assert_eq!(out, Some(vec![1, 2, 3]));
615 /// ```
616 fn collect<P>(self) -> Option<P>
617 where
618 P: ParExtend<Self::Elem> + Default,
619 Self::Elem: Send,
620 {
621 let mut dst = P::default();
622 self.collect_into(&mut dst)?;
623 Some(dst)
624 }
625
626 // compute - derived
627
628 /// Returns `Some(true)` if all successful items satisfy `f`.
629 ///
630 /// Returns `None` on short-circuit failure.
631 ///
632 /// # Examples
633 ///
634 /// ```
635 /// use orx_parallel::*;
636 ///
637 /// let ok = (1..5)
638 /// .into_par()
639 /// .map(Some)
640 /// .into_optional()
641 /// .use_new(|_| ())
642 /// .all(|_, x| x > &0);
643 /// assert_eq!(ok, Some(true));
644 ///
645 /// let fail = vec![Some(1), None, Some(3)]
646 /// .into_par()
647 /// .into_optional()
648 /// .use_new(|_| ())
649 /// .all(|_, x| x > &0);
650 /// assert_eq!(fail, None);
651 /// ```
652 fn all<F>(self, f: F) -> Option<bool>
653 where
654 Self::Elem: Send,
655 F: Fn(&mut Self::Use, &Self::Elem) -> bool + Sync,
656 {
657 self.map(|u, x| f(u, &x))
658 .find(|_, x| !*x)
659 .map(|x| x.is_none())
660 }
661
662 /// Returns `Some(true)` if any successful item satisfies `f`.
663 ///
664 /// Returns `None` on short-circuit failure.
665 ///
666 /// # Examples
667 ///
668 /// ```
669 /// use orx_parallel::*;
670 ///
671 /// let ok = (1..5)
672 /// .into_par()
673 /// .map(Some)
674 /// .into_optional()
675 /// .use_new(|_| ())
676 /// .any(|_, x| x % 2 == 0);
677 /// assert_eq!(ok, Some(true));
678 ///
679 /// let fail = vec![Some(1), None, Some(3)]
680 /// .into_par()
681 /// .into_optional()
682 /// .use_new(|_| ())
683 /// .any(|_, x| x % 2 == 0);
684 /// assert_eq!(fail, None);
685 /// ```
686 fn any<F>(self, f: F) -> Option<bool>
687 where
688 Self::Elem: Send,
689 F: Fn(&mut Self::Use, &Self::Elem) -> bool + Sync,
690 {
691 self.map(|u, x| f(u, &x))
692 .find(|_, x| *x)
693 .map(|x| x.is_some())
694 }
695
696 /// Counts successful elements.
697 ///
698 /// Returns `None` on short-circuit failure.
699 ///
700 /// # Examples
701 ///
702 /// ```
703 /// use orx_parallel::*;
704 ///
705 /// let ok = (1..11)
706 /// .into_par()
707 /// .map(Some)
708 /// .into_optional()
709 /// .use_new(|_| ())
710 /// .filter(|_, x| x % 3 == 0)
711 /// .count();
712 /// assert_eq!(ok, Some(3));
713 /// ```
714 fn count(self) -> Option<usize> {
715 self.map(|_, _| 1)
716 .reduce(|_, a, b| a + b)
717 .map(|x| x.unwrap_or(0))
718 }
719
720 /// Finds first (ordered) or any (arbitrary) successful item satisfying `f`.
721 ///
722 /// Returns `None` on short-circuit failure.
723 ///
724 /// # Examples
725 ///
726 /// ```
727 /// use orx_parallel::*;
728 ///
729 /// let found = (1..101)
730 /// .into_par()
731 /// .map(Some)
732 /// .into_optional()
733 /// .use_new(|_| ())
734 /// .find(|_, x| x % 17 == 0);
735 /// assert_eq!(found, Some(Some(17)));
736 /// ```
737 fn find<F>(self, f: F) -> Option<Option<Self::Elem>>
738 where
739 Self::Elem: Send,
740 F: Fn(&mut Self::Use, &Self::Elem) -> bool + Sync,
741 {
742 self.filter(&f).first()
743 }
744
745 /// Executes `f` for each successful element.
746 ///
747 /// Returns `None` on short-circuit failure.
748 ///
749 /// # Examples
750 ///
751 /// ```
752 /// use orx_parallel::*;
753 ///
754 /// let mut sums = UseVec::new(|_| 0usize);
755 ///
756 /// let result = (1..5)
757 /// .into_par()
758 /// .map(Some)
759 /// .into_optional()
760 /// .use_vec(&mut sums)
761 /// .for_each(|local, x| *local += x);
762 ///
763 /// assert_eq!(result, Some(()));
764 /// assert_eq!(sums.into_vec().into_iter().sum::<usize>(), 10);
765 /// ```
766 fn for_each<F>(self, f: F) -> Option<()>
767 where
768 F: Fn(&mut Self::Use, Self::Elem) + Send + Copy,
769 {
770 self.map(f).reduce(|_, _, _| {}).map(|_| ())
771 }
772
773 /// Returns maximum successful element.
774 ///
775 /// Returns `None` on short-circuit failure.
776 ///
777 /// # Examples
778 ///
779 /// ```
780 /// use orx_parallel::*;
781 ///
782 /// let m = (1..5)
783 /// .into_par()
784 /// .map(Some)
785 /// .into_optional()
786 /// .use_new(|_| ())
787 /// .max();
788 /// assert_eq!(m, Some(Some(4)));
789 /// ```
790 fn max(self) -> Option<Option<Self::Elem>>
791 where
792 Self::Elem: Ord + Send,
793 {
794 self.reduce(|_, a, b| Ord::max(a, b))
795 }
796
797 /// Returns successful element considered maximum by comparator `f`.
798 ///
799 /// Returns `None` on short-circuit failure.
800 ///
801 /// # Examples
802 ///
803 /// ```
804 /// use orx_parallel::*;
805 ///
806 /// let x = vec![-3_i32, 0, 1, 5, -10]
807 /// .into_par()
808 /// .map(Some)
809 /// .into_optional()
810 /// .use_new(|_| ())
811 /// .max_by(|_, a, b| a.cmp(b));
812 /// assert_eq!(x, Some(Some(5)));
813 /// ```
814 fn max_by<F>(self, f: F) -> Option<Option<Self::Elem>>
815 where
816 Self::Elem: Send,
817 F: Fn(&mut Self::Use, &Self::Elem, &Self::Elem) -> Ordering + Sync,
818 {
819 let reduce = |u: &mut Self::Use, x, y| match f(u, &x, &y) {
820 Ordering::Greater | Ordering::Equal => x,
821 Ordering::Less => y,
822 };
823 self.reduce(reduce)
824 }
825
826 /// Returns successful element with maximum key value.
827 ///
828 /// Returns `None` on short-circuit failure.
829 ///
830 /// # Examples
831 ///
832 /// ```
833 /// use orx_parallel::*;
834 ///
835 /// let x = vec![-3_i32, 0, 1, 5, -10]
836 /// .into_par()
837 /// .map(Some)
838 /// .into_optional()
839 /// .use_new(|_| ())
840 /// .max_by_key(|_, x| x.abs());
841 /// assert_eq!(x, Some(Some(-10)));
842 /// ```
843 fn max_by_key<B, F>(self, f: F) -> Option<Option<Self::Elem>>
844 where
845 Self::Elem: Send,
846 B: Ord,
847 F: Fn(&mut Self::Use, &Self::Elem) -> B + Sync,
848 {
849 let reduce = |u: &mut Self::Use, x, y| match f(u, &x).cmp(&f(u, &y)) {
850 Ordering::Greater | Ordering::Equal => x,
851 Ordering::Less => y,
852 };
853 self.reduce(reduce)
854 }
855
856 /// Returns minimum successful element.
857 ///
858 /// Returns `None` on short-circuit failure.
859 ///
860 /// # Examples
861 ///
862 /// ```
863 /// use orx_parallel::*;
864 ///
865 /// let m = (1..5)
866 /// .into_par()
867 /// .map(Some)
868 /// .into_optional()
869 /// .use_new(|_| ())
870 /// .min();
871 /// assert_eq!(m, Some(Some(1)));
872 /// ```
873 fn min(self) -> Option<Option<Self::Elem>>
874 where
875 Self::Elem: Ord + Send,
876 {
877 self.reduce(|_, a, b| Ord::min(a, b))
878 }
879
880 /// Returns successful element considered minimum by comparator `f`.
881 ///
882 /// Returns `None` on short-circuit failure.
883 ///
884 /// # Examples
885 ///
886 /// ```
887 /// use orx_parallel::*;
888 ///
889 /// let x = vec![-3_i32, 0, 1, 5, -10]
890 /// .into_par()
891 /// .map(Some)
892 /// .into_optional()
893 /// .use_new(|_| ())
894 /// .min_by(|_, a, b| a.cmp(b));
895 /// assert_eq!(x, Some(Some(-10)));
896 /// ```
897 fn min_by<F>(self, f: F) -> Option<Option<Self::Elem>>
898 where
899 Self::Elem: Send,
900 F: Fn(&mut Self::Use, &Self::Elem, &Self::Elem) -> Ordering + Sync,
901 {
902 let reduce = |u: &mut Self::Use, x, y| match f(u, &x, &y) {
903 Ordering::Less | Ordering::Equal => x,
904 Ordering::Greater => y,
905 };
906 self.reduce(reduce)
907 }
908
909 /// Returns successful element with minimum key value.
910 ///
911 /// Returns `None` on short-circuit failure.
912 ///
913 /// # Examples
914 ///
915 /// ```
916 /// use orx_parallel::*;
917 ///
918 /// let x = vec![-3_i32, 0, 1, 5, -10]
919 /// .into_par()
920 /// .map(Some)
921 /// .into_optional()
922 /// .use_new(|_| ())
923 /// .min_by_key(|_, x| x.abs());
924 /// assert_eq!(x, Some(Some(0)));
925 /// ```
926 fn min_by_key<B, F>(self, f: F) -> Option<Option<Self::Elem>>
927 where
928 Self::Elem: Send,
929 B: Ord,
930 F: Fn(&mut Self::Use, &Self::Elem) -> B + Sync,
931 {
932 let reduce = |u: &mut Self::Use, x, y| match f(u, &x).cmp(&f(u, &y)) {
933 Ordering::Less | Ordering::Equal => x,
934 Ordering::Greater => y,
935 };
936 self.reduce(reduce)
937 }
938
939 /// Sums successful elements using [`Sum`] implementation.
940 ///
941 /// Returns `None` on short-circuit failure.
942 ///
943 /// # Examples
944 ///
945 /// ```
946 /// use orx_parallel::*;
947 ///
948 /// let s: Option<usize> = (1..5)
949 /// .into_par()
950 /// .map(Some)
951 /// .into_optional()
952 /// .use_new(|_| ())
953 /// .sum();
954 /// assert_eq!(s, Some(10));
955 /// ```
956 fn sum<S>(self) -> Option<S>
957 where
958 Self::Elem: Sum<S>,
959 S: Send,
960 {
961 self.map(|_, x| Self::Elem::owned(x))
962 .reduce(|_, a, b| Self::Elem::add(a, b))
963 .map(|x| x.unwrap_or(Self::Elem::zero()))
964 }
965}