truth_values/lib.rs
1//! Tiny, zero-dependency, zero-allocation*, `no_std` library for generating all possible
2//! combinations of `n` [`bool`]s. Useful for testing [boolean functions],
3//! verifying [logical equivalence], and generating [truth tables].
4//! _\*Optional `alloc` feature for [`Vec`] related functions._
5//!
6//! [boolean functions]: https://en.wikipedia.org/wiki/Boolean_function
7//! [logical equivalence]: https://en.wikipedia.org/wiki/Logical_equivalence
8//! [truth tables]: https://en.wikipedia.org/wiki/Truth_table
9//!
10//! # Example - `each()` and `each_const()`
11//!
12//! Consider implementing an interpreter or optimizer, and now you
13//! want to assert [logical equivalence] between expressions, e.g.
14//! asserting [De Morgan's laws]:
15//!
16//! - not (A or B) = (not A) and (not B)
17//! - not (A and B) = (not A) or (not B)
18//!
19//! [De Morgan's laws]: https://en.wikipedia.org/wiki/De_Morgan%27s_laws
20//!
21//! Using [const generic variant](crate::each_const), i.e. where `N` is const:
22//!
23//! ```
24//! # use truth_values::each_const;
25//! each_const(|[a, b]| {
26//! assert_eq!(!(a || b), !a && !b);
27//! assert_eq!(!(a && b), !a || !b);
28//! });
29//! // The closure is called for each combination of 2 `bool`s, i.e.:
30//! // [false, false]
31//! // [true, false]
32//! // [false, true]
33//! // [true, true]
34//! ```
35//!
36//! Using [non-const generic variant](crate::each), i.e. where `n` can be dynamic:
37//!
38//! ```
39//! # use truth_values::each;
40//! each(2, |bools| match bools {
41//! &[a, b] => {
42//! assert_eq!(!(a || b), !a && !b);
43//! assert_eq!(!(a && b), !a || !b);
44//! }
45//! _ => unreachable!(),
46//! });
47//! // The closure is called for each combination of 2 `bool`s, i.e.:
48//! // &[false, false]
49//! // &[true, false]
50//! // &[false, true]
51//! // &[true, true]
52//! ```
53//!
54//! # Example - `gen()` and `gen_const()`
55//!
56//! Alternatively, use [`gen()` functions](crate#functions) to obtain
57//! an [`Iterator`] for generating all combinations. This could be used
58//! to e.g. map each combination into an `Expr` for an [AST], to easily
59//! generate all `Expr` combinations to verify their evaluation.
60//!
61//! [AST]: https://en.wikipedia.org/wiki/Abstract_syntax_tree
62//!
63//! Using [const generic variant](crate::gen_const), i.e. where `N` is const:
64//!
65//! ```
66//! #[derive(PartialEq, Debug)]
67//! enum Expr {
68//! Bool(bool),
69//! And(Box<Self>, Box<Self>),
70//! // ...
71//! }
72//!
73//! impl Expr {
74//! fn and(lhs: Self, rhs: Self) -> Self {
75//! Self::And(Box::new(lhs), Box::new(rhs))
76//! }
77//! }
78//!
79//! let exprs = truth_values::gen_const()
80//! .map(|[a, b]| {
81//! Expr::and(Expr::Bool(a), Expr::Bool(b))
82//! })
83//! .collect::<Vec<_>>();
84//!
85//! assert_eq!(
86//! exprs,
87//! [
88//! Expr::and(Expr::Bool(false), Expr::Bool(false)),
89//! Expr::and(Expr::Bool(true), Expr::Bool(false)),
90//! Expr::and(Expr::Bool(false), Expr::Bool(true)),
91//! Expr::and(Expr::Bool(true), Expr::Bool(true)),
92//! ]
93//! );
94//! ```
95//!
96//! Using [non-const generic variant](crate::gen_slice), i.e. where `n` can be dynamic:
97//!
98//! ```
99//! # #[derive(PartialEq, Debug)]
100//! # enum Expr {
101//! # Bool(bool),
102//! # And(Box<Self>, Box<Self>),
103//! # }
104//! #
105//! # impl Expr {
106//! # fn and(lhs: Expr, rhs: Expr) -> Expr {
107//! # Expr::And(Box::new(lhs), Box::new(rhs))
108//! # }
109//! # }
110//! #
111//! let exprs = truth_values::gen_slice(2, |bools| {
112//! match bools {
113//! &[a, b] => {
114//! Expr::and(Expr::Bool(a), Expr::Bool(b))
115//! }
116//! _ => unreachable!(),
117//! }
118//! })
119//! .collect::<Vec<_>>();
120//!
121//! assert_eq!(
122//! exprs,
123//! [
124//! Expr::and(Expr::Bool(false), Expr::Bool(false)),
125//! Expr::and(Expr::Bool(true), Expr::Bool(false)),
126//! Expr::and(Expr::Bool(false), Expr::Bool(true)),
127//! Expr::and(Expr::Bool(true), Expr::Bool(true)),
128//! ]
129//! );
130//! ```
131//!
132//! # Combinations of 1, 2, 3, 4 `bool`s
133//!
134//! <table>
135//! <tr>
136//! <td style="text-align: center;">
137//!
138//! ```
139//! # use truth_values::gen_const;
140//! gen_const::<1>()
141//! # ;
142//! ```
143//!
144//! </td>
145//! <td style="text-align: center;">
146//!
147//! ```
148//! # use truth_values::gen_const;
149//! gen_const::<2>()
150//! # ;
151//! ```
152//!
153//! </td>
154//! <td style="text-align: center;">
155//!
156//! ```
157//! # use truth_values::gen_const;
158//! gen_const::<3>()
159//! # ;
160//! ```
161//!
162//! </td>
163//! <td style="text-align: center;">
164//!
165//! ```
166//! # use truth_values::gen_const;
167//! gen_const::<4>()
168//! # ;
169//! ```
170//!
171//! </td>
172//! </tr>
173//! <tr>
174//! <td style="vertical-align: top;">
175//!
176//! ```
177//! # [
178//! [false]
179//! # ,
180//! [true]
181//! # ];
182//! ```
183//!
184//! </td>
185//! <td style="vertical-align: top;">
186//!
187//! ```
188//! # [
189//! [false, false]
190//! # ,
191//! [true, false]
192//! # ,
193//! [false, true]
194//! # ,
195//! [true, true]
196//! # ];
197//! ```
198//!
199//! </td>
200//! <td style="vertical-align: top;">
201//!
202//! ```
203//! # [
204//! [false, false, false]
205//! # ,
206//! [true, false, false]
207//! # ,
208//! [false, true, false]
209//! # ,
210//! [true, true, false]
211//! # ,
212//! [false, false, true]
213//! # ,
214//! [true, false, true]
215//! # ,
216//! [false, true, true]
217//! # ,
218//! [true, true, true]
219//! # ];
220//! ```
221//!
222//! </td>
223//! <td style="vertical-align: top;">
224//!
225//! ```
226//! # [
227//! [false, false, false, false]
228//! # ,
229//! [true, false, false, false]
230//! # ,
231//! [false, true, false, false]
232//! # ,
233//! [true, true, false, false]
234//! # ,
235//! [false, false, true, false]
236//! # ,
237//! [true, false, true, false]
238//! # ,
239//! [false, true, true, false]
240//! # ,
241//! [true, true, true, false]
242//! # ,
243//! [false, false, false, true]
244//! # ,
245//! [true, false, false, true]
246//! # ,
247//! [false, true, false, true]
248//! # ,
249//! [true, true, false, true]
250//! # ,
251//! [false, false, true, true]
252//! # ,
253//! [true, false, true, true]
254//! # ,
255//! [false, true, true, true]
256//! # ,
257//! [true, true, true, true]
258//! # ];
259//! ```
260//!
261//! </td>
262//! </tr>
263//! </table>
264//!
265//! # Implementation
266//!
267//! The [`gen()` functions](crate#functions) return an [`Iterator`], which
268//! additionally specializes [`size_hint()`], [`count()`], [`nth()`], [`last()`].
269//!
270//! The [`Iterator`] also implements:
271//!
272//! - [`DoubleEndedIterator`] implementing [`next_back()`] and [`nth_back()`]
273//! - [`ExactSizeIterator`] implementing [`len()`]
274//! - [`FusedIterator`]
275//!
276//! # Warning
277//!
278//! The amount of combinations is exponential!
279//! The number of combinations for `N` boolean variables is <code>2<sup>N</sup></code>.
280//! In short, **10 variables** produce **1024 combinations**, but **20 variables**
281//! produce over **1 million combinations**.
282//!
283//! _Just alone exhausting the generator for **30 variables**, i.e. over **1 billion
284//! combinations**, takes a handful of seconds on my machine._
285//!
286//! Ideally, if used to test expressions, then there will likely only be a handful of
287//! variables. However, if user input is accepted, then it might be worth guarding and
288//! limiting the number of variables.
289//!
290//! So even though up to [`MAX`] (`63`) variables for 64-bit platforms
291//! is supported, it is probably undesirable to even attempt to process
292//! that many variables.
293//!
294//! [`MAX`]: crate::MAX
295//!
296//! [`size_hint()`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.size_hint
297//! [`count()`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.count
298//! [`nth()`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.nth
299//! [`last()`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.last
300//! [`next_back()`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#tymethod.next_back
301//! [`nth_back()`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.nth_back
302//! [`len()`]: https://doc.rust-lang.org/std/iter/trait.ExactSizeIterator.html#method.len
303
304#![no_std]
305#![forbid(unsafe_code)]
306#![forbid(elided_lifetimes_in_paths)]
307#![cfg_attr(debug_assertions, allow(missing_docs, missing_debug_implementations,))]
308#![warn(clippy::all)]
309
310#[cfg(feature = "alloc")]
311extern crate alloc;
312
313use core::array;
314use core::iter::FusedIterator;
315use core::ops::Range;
316
317#[cfg(feature = "alloc")]
318use alloc::{vec, vec::Vec};
319
320/// Maximum number of variables supported by
321/// [`gen()` functions](crate#functions).
322///
323/// - `15` variables is supported on 16-bit targets
324/// - `31` variables is supported on 32-bit targets
325/// - `63` variables is supported on 64-bit targets
326///
327/// ```
328/// // Assuming `usize` is 64 bits, i.e. `u64`
329/// assert_eq!(truth_values::MAX, 63);
330/// ```
331///
332/// Use <code>[count]\(n)</code> to calculate how many
333/// combinations `n` variables produces.
334///
335/// See [warning notice in crate root](crate#warning).
336pub const MAX: usize = (usize::BITS - 1) as usize;
337
338/// Returns `true` if `n` variables is supported
339/// by [`gen()` functions](crate#functions), i.e.
340/// <code>n <= [MAX]</code>.
341///
342/// - `15` variables is supported on 16-bit targets
343/// - `31` variables is supported on 32-bit targets
344/// - `63` variables is supported on 64-bit targets
345///
346/// ```
347/// // Assuming `usize` is 64 bits, i.e. `u64`
348/// assert_eq!(truth_values::is_supported(63), true);
349/// assert_eq!(truth_values::is_supported(64), false);
350/// ```
351///
352/// See [warning notice in crate root](crate#warning).
353#[inline]
354pub const fn is_supported(n: usize) -> bool {
355 n <= MAX
356}
357
358/// Returns `Some` with the number of combinations that `n` variables produces.
359///
360/// Returns `None` if `n` variables would produce more than what can be represented.
361///
362/// - `1` variable produces `2` combinations
363/// - `2` variables produces `4` combinations
364/// - `3` variables produces `8` combinations
365/// - `4` variables produces `16` combinations
366/// - [`MAX`] variables produces <code>[count]\([MAX])</code> combinations
367///
368/// Use <code>[is_supported]\(n)</code> or <code>[count]\(n).is_some()</code>
369/// to check if `n` variables is supported.
370///
371/// - `15` variables is supported on 16-bit targets
372/// - `31` variables is supported on 32-bit targets
373/// - `63` variables is supported on 64-bit targets
374///
375/// See [warning notice in crate root](crate#warning).
376///
377/// # Example
378///
379/// ```
380/// # use truth_values::count;
381/// assert_eq!(count(0), Some(0));
382///
383/// assert_eq!(count(1), Some(2));
384/// assert_eq!(count(2), Some(4));
385/// assert_eq!(count(3), Some(8));
386/// assert_eq!(count(4), Some(16));
387/// assert_eq!(count(5), Some(32));
388/// assert_eq!(count(6), Some(64));
389/// assert_eq!(count(7), Some(128));
390/// assert_eq!(count(8), Some(256));
391/// assert_eq!(count(9), Some(512));
392/// assert_eq!(count(10), Some(1024));
393/// assert_eq!(count(11), Some(2048));
394/// assert_eq!(count(12), Some(4096));
395/// assert_eq!(count(13), Some(8192));
396/// assert_eq!(count(14), Some(16384));
397///
398/// assert_eq!(count(100), None);
399/// ```
400#[inline]
401pub const fn count(n: usize) -> Option<usize> {
402 if n == 0 {
403 Some(0)
404 } else if n > MAX {
405 None
406 } else {
407 let n = n as u32;
408 1_usize.checked_shl(n)
409 }
410}
411
412/// Returns an [`Iterator`] producing all possible combinations of `[bool; N]`.
413///
414/// See also [`gen()`] for non-const generic variant.
415///
416/// See also [implementation](crate#implementation) for more information
417/// about the [`Iterator`] implementation.
418///
419/// # Panics
420///
421/// Panics if `N` is larger than the [`MAX`] number of supported variables.
422/// _However, you likely have other problems, if you encounter this._
423///
424/// See also <code>[count]\(N)</code> and <code>[is_supported]\(N)</code>.
425///
426/// # Example
427///
428/// See [crate root](crate) for more examples.
429///
430/// ```
431/// let combinations = truth_values::gen_const()
432/// .map(|[a, b]| {
433/// (a, b)
434/// })
435/// .collect::<Vec<_>>();
436///
437/// assert_eq!(
438/// combinations,
439/// [
440/// (false, false),
441/// (true, false),
442/// (false, true),
443/// (true, true),
444/// ]
445/// );
446/// ```
447#[inline]
448pub fn gen_const<const N: usize>(
449) -> impl DoubleEndedIterator<Item = [bool; N]> + ExactSizeIterator + FusedIterator {
450 ConstBoolsGenerator::new()
451}
452
453/// Returns an [`Iterator`] producing all possible combinations of `n` [`bool`]s,
454/// in the form of individual [`Bools`] iterators.
455///
456/// Alternatively, use [`gen_slice()`] or [`gen_vec_slice()`]
457/// to receives `&[bool]` instead, where <code>[len()] == n</code>.
458///
459/// See also [`gen_const()`] for const generic variant.
460///
461/// See also [implementation](crate#implementation) for more information
462/// about the [`Iterator`] implementation.
463///
464/// # Panics
465///
466/// Panics if `n` is larger than the [`MAX`] number of supported variables.
467/// _However, you likely have other problems, if you encounter this._
468///
469/// See also <code>[count]\(n)</code> and <code>[is_supported]\(n)</code>.
470///
471/// # Example
472///
473/// See [crate root](crate) for more examples.
474///
475/// ```
476/// let n = 2;
477/// let combinations = truth_values::gen(n)
478/// .map(|mut bools| {
479/// (bools.next().unwrap(), bools.next().unwrap())
480/// })
481/// .collect::<Vec<_>>();
482///
483/// assert_eq!(
484/// combinations,
485/// [
486/// (false, false),
487/// (true, false),
488/// (false, true),
489/// (true, true),
490/// ]
491/// );
492/// ```
493///
494/// [len()]: slice::len
495#[inline]
496pub fn gen(n: usize) -> impl DoubleEndedIterator<Item = Bools> + ExactSizeIterator + FusedIterator {
497 BoolsGenerator::new(n)
498}
499
500/// Returns an [`Iterator`] producing `T` for each possible combinations
501/// of `n` [`bool`]s.
502///
503/// Each combination is mapped from `&[bool] -> T` using `f`,
504/// where `f` receives `&[bool]` where <code>[len()] == n</code>.
505///
506/// See also [`gen_const()`] for const generic variant.
507///
508/// See also [implementation](crate#implementation) for more information
509/// about the [`Iterator`] implementation.
510///
511/// # Memory
512///
513/// The returned [`Iterator`] stores a <code>[bool; [MAX]]</code> on the stack.
514///
515/// Alternatively, [`gen_vec_slice()`] stores a
516/// <code>[Vec]\<bool>::[with_capacity]\(n)</code>
517/// on the stack.
518///
519/// See also [`gen_with_buffer()`] for using a custom buffer.
520///
521/// # Panics
522///
523/// Panics if `n` is larger than the [`MAX`] number of supported variables.
524/// _However, you likely have other problems, if you encounter this._
525///
526/// See also <code>[count]\(n)</code> and <code>[is_supported]\(n)</code>.
527///
528/// # Example
529///
530/// See [crate root](crate) for more examples.
531///
532/// ```
533/// let n = 2;
534/// let combinations = truth_values::gen_slice(n, |bools| {
535/// match bools {
536/// &[a, b] => (a, b),
537/// _ => unreachable!(),
538/// }
539/// })
540/// .collect::<Vec<_>>();
541///
542/// assert_eq!(
543/// combinations,
544/// [
545/// (false, false),
546/// (true, false),
547/// (false, true),
548/// (true, true),
549/// ]
550/// );
551/// ```
552///
553/// [with_capacity]: Vec::with_capacity
554/// [len()]: slice::len
555#[inline]
556pub fn gen_slice<T, F>(
557 n: usize,
558 mut f: F,
559) -> impl DoubleEndedIterator<Item = T> + ExactSizeIterator + FusedIterator
560where
561 for<'a> F: FnMut(&[bool]) -> T,
562{
563 let mut bools = [false; MAX];
564 gen(n).map(move |values| {
565 let bools = values.fill_bools_into(&mut bools);
566 f(bools)
567 })
568}
569
570/// Returns an [`Iterator`] producing <code>[Vec]<[bool]></code>
571/// for each possible combinations of `n` [`bool`]s.
572///
573/// **Note:** If a <code>[Vec]<[bool]></code> is **not needed**
574/// for **each combination**, then consider using [`gen_slice()`]
575/// or [`gen_vec_slice()`] instead.
576///
577/// See also [implementation](crate#implementation) for more information
578/// about the [`Iterator`] implementation.
579///
580/// # Panics
581///
582/// Panics if `n` is larger than the [`MAX`] number of supported variables.
583/// _However, you likely have other problems, if you encounter this._
584///
585/// See also <code>[count]\(n)</code> and <code>[is_supported]\(n)</code>.
586///
587/// # Example
588///
589/// See [crate root](crate) for more examples.
590///
591/// ```
592/// let n = 2;
593/// let combinations = truth_values::gen_vec(n).collect::<Vec<_>>();
594///
595/// assert_eq!(
596/// combinations,
597/// [
598/// vec![false, false],
599/// vec![true, false],
600/// vec![false, true],
601/// vec![true, true],
602/// ]
603/// );
604/// ```
605#[cfg(feature = "alloc")]
606#[inline]
607pub fn gen_vec(
608 n: usize,
609) -> impl DoubleEndedIterator<Item = Vec<bool>> + ExactSizeIterator + FusedIterator {
610 gen(n).map(Iterator::collect)
611}
612
613/// Returns an [`Iterator`] producing `T` for each possible combinations
614/// of `n` [`bool`]s.
615///
616/// Each combination is mapped from `&[bool] -> T` using `f`,
617/// where `f` receives `&[bool]` where <code>[len()] == n</code>.
618///
619/// See also [`gen_const()`] for const generic variant.
620///
621/// See also [implementation](crate#implementation) for more information
622/// about the [`Iterator`] implementation.
623///
624/// # Memory
625///
626/// The returned [`Iterator`] stores a
627/// <code>[Vec]\<bool>::[with_capacity]\(n)</code>
628/// on the stack.
629///
630/// Alternatively, [`gen_slice()`] stores a <code>[bool; [MAX]]</code>
631/// on the stack.
632///
633/// See also [`gen_with_buffer()`] for using a custom buffer.
634///
635/// # Panics
636///
637/// Panics if `n` is larger than the [`MAX`] number of supported variables.
638/// _However, you likely have other problems, if you encounter this._
639///
640/// See also <code>[count]\(n)</code> and <code>[is_supported]\(n)</code>.
641///
642/// # Example
643///
644/// See [crate root](crate) for more examples.
645///
646/// ```
647/// let n = 2;
648/// let combinations = truth_values::gen_vec_slice(n, |bools| {
649/// match bools {
650/// &[a, b] => (a, b),
651/// _ => unreachable!(),
652/// }
653/// })
654/// .collect::<Vec<_>>();
655///
656/// assert_eq!(
657/// combinations,
658/// [
659/// (false, false),
660/// (true, false),
661/// (false, true),
662/// (true, true),
663/// ]
664/// );
665/// ```
666///
667/// [with_capacity]: Vec::with_capacity
668/// [len()]: slice::len
669#[cfg(feature = "alloc")]
670#[inline]
671pub fn gen_vec_slice<T, F>(
672 n: usize,
673 mut f: F,
674) -> impl DoubleEndedIterator<Item = T> + ExactSizeIterator + FusedIterator
675where
676 for<'a> F: FnMut(&[bool]) -> T,
677{
678 let mut bools = vec![false; n];
679 gen(n).map(move |mut values| {
680 let bools = bools.as_mut();
681 values.fill_into(bools);
682 f(bools)
683 })
684}
685
686/// Returns an [`Iterator`] producing `T` for each possible combinations
687/// of `n` [`bool`]s.
688///
689/// Each combination is mapped from `&[bool] -> T` using `f`,
690/// where `f` receives `&[bool]` where <code>[len()] == n</code>.
691///
692/// The `buffer` only needs to be as big as the largest used `n`.
693/// Whereas [`gen_slice()`] which always uses a
694/// <code>[[bool]; [MAX]]</code>.
695///
696/// See also [implementation](crate#implementation) for more information
697/// about the [`Iterator`] implementation.
698///
699/// # Panics
700///
701/// - Panics if <code>buffer.[len()] < n</code>
702/// - Panics if `n` is larger than the [`MAX`] number of supported variables.
703/// _However, you likely have other problems, if you encounter this._
704///
705/// See also <code>[count]\(n)</code> and <code>[is_supported]\(n)</code>.
706///
707/// # Example
708///
709/// See [crate root](crate) for more examples.
710///
711/// ```
712/// // buffer only needs to be as big as the largest `n`
713/// let mut buffer = [false; 5];
714///
715/// // `3 <= buffer.len()` so `buffer` can be used
716/// let n = 3;
717/// let combinations = truth_values::gen_with_buffer(n, &mut buffer, |bools| {
718/// match bools {
719/// &[a, b, c] => (a, b, c),
720/// _ => unreachable!(),
721/// }
722/// })
723/// .collect::<Vec<_>>();
724///
725/// assert_eq!(
726/// combinations,
727/// [
728/// (false, false, false),
729/// (true, false, false),
730/// (false, true, false),
731/// (true, true, false),
732/// (false, false, true),
733/// (true, false, true),
734/// (false, true, true),
735/// (true, true, true),
736/// ]
737/// );
738///
739/// // `2 <= buffer.len()` so `buffer` can be reused
740/// let n = 2;
741/// let combinations = truth_values::gen_with_buffer(n, &mut buffer, |bools| {
742/// match bools {
743/// &[a, b] => (a, b),
744/// _ => unreachable!(),
745/// }
746/// })
747/// .collect::<Vec<_>>();
748///
749/// assert_eq!(
750/// combinations,
751/// [
752/// (false, false),
753/// (true, false),
754/// (false, true),
755/// (true, true),
756/// ]
757/// );
758/// ```
759///
760/// [len()]: slice::len
761pub fn gen_with_buffer<'a, T, F>(
762 n: usize,
763 buffer: &'a mut [bool],
764 mut f: F,
765) -> impl DoubleEndedIterator<Item = T> + ExactSizeIterator + FusedIterator + 'a
766where
767 for<'b> F: FnMut(&'b [bool]) -> T + 'a,
768{
769 if n > buffer.len() {
770 panic!("buffer too small {n} > {}", buffer.len());
771 }
772 let buffer = &mut buffer[..n];
773
774 gen(n).map(move |mut values| {
775 values.fill_into(buffer);
776 f(buffer)
777 })
778}
779
780/// Shorthand for <code>[gen_const]\().[for_each]\(f)</code>.
781///
782/// See [`gen_const()`] for more information.
783///
784/// See [`each()`] for the non-const generic variant.
785///
786/// # Example
787///
788/// See [crate root](crate) for more examples.
789///
790/// ```
791/// # use truth_values::each_const;
792/// #
793/// each_const(|[a]| {
794/// println!("{a}");
795/// });
796/// // Outputs:
797/// // false
798/// // true
799///
800/// each_const(|[a, b]| {
801/// println!("{a} {b}");
802/// });
803/// // Outputs:
804/// // false false
805/// // true false
806/// // false true
807/// // true true
808///
809/// each_const(|[a, b, c, d]| {
810/// println!("{a} {b} {c} {d}");
811/// });
812/// // Outputs:
813/// // false false false false
814/// // true false false false
815/// // false true false false
816/// // true true false false
817/// // false false true false
818/// // true false true false
819/// // false true true false
820/// // true true true false
821/// // false false false true
822/// // true false false true
823/// // false true false true
824/// // true true false true
825/// // false false true true
826/// // true false true true
827/// // false true true true
828/// // true true true true
829/// ```
830///
831/// [for_each]: Iterator::for_each
832#[inline]
833pub fn each_const<const N: usize, F>(f: F)
834where
835 F: FnMut([bool; N]),
836{
837 gen_const::<N>().for_each(f)
838}
839
840/// Shorthand for <code>[gen_slice]\(n, f).[for_each]\(|_| ())</code>.
841///
842/// See [`gen_slice()`] for more information.
843///
844/// See [`each_const()`] for the const generic variant.
845///
846/// # Example
847///
848/// See [crate root](crate) for more examples.
849///
850/// ```
851/// # use truth_values::each;
852/// each(1, |bools| {
853/// println!("{:?}", bools);
854/// });
855/// // Outputs:
856/// // [false]
857/// // [true]
858///
859/// each(2, |bools| {
860/// println!("{:?}", bools);
861/// });
862/// // Outputs:
863/// // [false, false]
864/// // [true, false]
865/// // [false, true]
866/// // [true, true]
867///
868/// each(4, |bools| {
869/// println!("{:?}", bools);
870/// });
871/// // Outputs:
872/// // [false, false, false, false]
873/// // [true, false, false, false]
874/// // [false, true, false, false]
875/// // [true, true, false, false]
876/// // [false, false, true, false]
877/// // [true, false, true, false]
878/// // [false, true, true, false]
879/// // [true, true, true, false]
880/// // [false, false, false, true]
881/// // [true, false, false, true]
882/// // [false, true, false, true]
883/// // [true, true, false, true]
884/// // [false, false, true, true]
885/// // [true, false, true, true]
886/// // [false, true, true, true]
887/// // [true, true, true, true]
888/// ```
889///
890/// [for_each]: Iterator::for_each
891#[inline]
892pub fn each<F>(n: usize, f: F)
893where
894 for<'a> F: FnMut(&'a [bool]),
895{
896 gen_slice(n, f).for_each(drop);
897}
898
899/// Shorthand for <code>[gen_vec_slice]\(n, f).[for_each]\(|_| ())</code>.
900///
901/// See [`gen_vec_slice()`] for more information.
902///
903/// See [`each_const()`] for the const generic variant.
904///
905/// # Example
906///
907/// See [crate root](crate) for more examples.
908///
909/// ```
910/// # use truth_values::each_vec_slice;
911/// each_vec_slice(1, |bools| {
912/// println!("{:?}", bools);
913/// });
914/// // Outputs:
915/// // [false]
916/// // [true]
917///
918/// each_vec_slice(2, |bools| {
919/// println!("{:?}", bools);
920/// });
921/// // Outputs:
922/// // [false, false]
923/// // [true, false]
924/// // [false, true]
925/// // [true, true]
926///
927/// each_vec_slice(4, |bools| {
928/// println!("{:?}", bools);
929/// });
930/// // Outputs:
931/// // [false, false, false, false]
932/// // [true, false, false, false]
933/// // [false, true, false, false]
934/// // [true, true, false, false]
935/// // [false, false, true, false]
936/// // [true, false, true, false]
937/// // [false, true, true, false]
938/// // [true, true, true, false]
939/// // [false, false, false, true]
940/// // [true, false, false, true]
941/// // [false, true, false, true]
942/// // [true, true, false, true]
943/// // [false, false, true, true]
944/// // [true, false, true, true]
945/// // [false, true, true, true]
946/// // [true, true, true, true]
947/// ```
948///
949/// [for_each]: Iterator::for_each
950#[cfg(feature = "alloc")]
951#[inline]
952pub fn each_vec_slice<F>(n: usize, f: F)
953where
954 for<'a> F: FnMut(&[bool]),
955{
956 let mut bools = vec![false; n];
957 each_with_buffer(n, &mut bools, f);
958}
959
960/// Shorthand for <code>[gen_with_buffer]\(n, buffer, f).[for_each]\(|_| ())</code>.
961///
962/// See [`each_with_buffer()`] for more information.
963///
964/// # Example
965///
966/// See [crate root](crate) for more examples.
967///
968/// ```
969/// # use truth_values::each_with_buffer;
970/// #
971/// // Buffer only needs to be as big as the largest `n`
972/// let mut buffer = [false; 5];
973///
974/// each_with_buffer(1, &mut buffer, |bools| {
975/// println!("{:?}", bools);
976/// });
977/// // Outputs:
978/// // [false]
979/// // [true]
980///
981/// each_with_buffer(2, &mut buffer, |bools| {
982/// println!("{:?}", bools);
983/// });
984/// // Outputs:
985/// // [false, false]
986/// // [true, false]
987/// // [false, true]
988/// // [true, true]
989///
990/// each_with_buffer(4, &mut buffer, |bools| {
991/// println!("{:?}", bools);
992/// });
993/// // Outputs:
994/// // [false, false, false, false]
995/// // [true, false, false, false]
996/// // [false, true, false, false]
997/// // [true, true, false, false]
998/// // [false, false, true, false]
999/// // [true, false, true, false]
1000/// // [false, true, true, false]
1001/// // [true, true, true, false]
1002/// // [false, false, false, true]
1003/// // [true, false, false, true]
1004/// // [false, true, false, true]
1005/// // [true, true, false, true]
1006/// // [false, false, true, true]
1007/// // [true, false, true, true]
1008/// // [false, true, true, true]
1009/// // [true, true, true, true]
1010/// ```
1011///
1012/// [for_each]: Iterator::for_each
1013#[inline]
1014pub fn each_with_buffer<F>(n: usize, buffer: &mut [bool], f: F)
1015where
1016 for<'a> F: FnMut(&'a [bool]),
1017{
1018 gen_with_buffer(n, buffer, f).for_each(drop);
1019}
1020
1021#[derive(PartialEq, Eq, Hash, Clone, Debug)]
1022struct ConstBoolsGenerator<const N: usize> {
1023 index: Range<usize>,
1024}
1025
1026impl<const N: usize> ConstBoolsGenerator<N> {
1027 pub fn new() -> Self {
1028 struct AssertLeMax<const N: usize>;
1029 impl<const N: usize> AssertLeMax<N> {
1030 const ASSERT: () = assert!(N <= MAX, "too many variables");
1031 }
1032 #[allow(clippy::let_unit_value)]
1033 {
1034 _ = AssertLeMax::<N>::ASSERT;
1035 }
1036
1037 // Safe to unwrap otherwise the above
1038 // assert would have triggered
1039 let count = count(N).unwrap();
1040
1041 Self { index: 0..count }
1042 }
1043
1044 #[inline]
1045 fn to_bools(index: usize) -> [bool; N] {
1046 array::from_fn(|var| ((index >> var) & 1) != 0)
1047 }
1048}
1049
1050impl<const N: usize> Iterator for ConstBoolsGenerator<N> {
1051 type Item = [bool; N];
1052
1053 #[inline]
1054 fn next(&mut self) -> Option<Self::Item> {
1055 self.index.next().map(Self::to_bools)
1056 }
1057
1058 #[inline]
1059 fn size_hint(&self) -> (usize, Option<usize>) {
1060 self.index.size_hint()
1061 }
1062
1063 #[inline]
1064 fn count(self) -> usize
1065 where
1066 Self: Sized,
1067 {
1068 self.index.count()
1069 }
1070
1071 #[inline]
1072 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1073 self.index.nth(n).map(Self::to_bools)
1074 }
1075
1076 #[inline]
1077 fn last(mut self) -> Option<Self::Item>
1078 where
1079 Self: Sized,
1080 {
1081 self.next_back()
1082 }
1083
1084 #[inline]
1085 fn min(mut self) -> Option<Self::Item>
1086 where
1087 Self::Item: Ord,
1088 {
1089 self.next()
1090 }
1091
1092 #[inline]
1093 fn max(mut self) -> Option<Self::Item>
1094 where
1095 Self::Item: Ord,
1096 {
1097 self.next_back()
1098 }
1099}
1100
1101impl<const N: usize> DoubleEndedIterator for ConstBoolsGenerator<N> {
1102 #[inline]
1103 fn next_back(&mut self) -> Option<Self::Item> {
1104 self.index.next_back().map(Self::to_bools)
1105 }
1106
1107 #[inline]
1108 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1109 self.index.nth_back(n).map(Self::to_bools)
1110 }
1111}
1112
1113impl<const N: usize> ExactSizeIterator for ConstBoolsGenerator<N> {
1114 #[inline]
1115 fn len(&self) -> usize {
1116 self.index.len()
1117 }
1118}
1119
1120impl<const N: usize> FusedIterator for ConstBoolsGenerator<N> {}
1121
1122#[derive(PartialEq, Eq, Hash, Clone, Debug)]
1123struct BoolsGenerator {
1124 index: Range<usize>,
1125 /// Number of variables.
1126 n: u8,
1127}
1128
1129impl BoolsGenerator {
1130 #[inline]
1131 pub fn new(n: usize) -> Self {
1132 Self::new_checked(n).expect("too many variables")
1133 }
1134
1135 #[inline]
1136 pub fn new_checked(n: usize) -> Option<Self> {
1137 let count = count(n)?;
1138
1139 // Safe to unwrap, as even with a `u128`,
1140 // there could only be at most 127 variables,
1141 // i.e. `count()` returning at most 127 for `u128`
1142 let n = u8::try_from(n).unwrap();
1143
1144 Some(Self { n, index: 0..count })
1145 }
1146
1147 #[inline]
1148 fn to_bools(&self, index: usize) -> Bools {
1149 Bools::new(self.n, index)
1150 }
1151}
1152
1153impl Iterator for BoolsGenerator {
1154 type Item = Bools;
1155
1156 #[inline]
1157 fn next(&mut self) -> Option<Self::Item> {
1158 let index = self.index.next()?;
1159 Some(self.to_bools(index))
1160 }
1161
1162 #[inline]
1163 fn size_hint(&self) -> (usize, Option<usize>) {
1164 self.index.size_hint()
1165 }
1166
1167 #[inline]
1168 fn count(self) -> usize
1169 where
1170 Self: Sized,
1171 {
1172 self.index.count()
1173 }
1174
1175 #[inline]
1176 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1177 let index = self.index.nth(n)?;
1178 Some(self.to_bools(index))
1179 }
1180
1181 #[inline]
1182 fn last(mut self) -> Option<Self::Item>
1183 where
1184 Self: Sized,
1185 {
1186 self.next_back()
1187 }
1188}
1189
1190impl DoubleEndedIterator for BoolsGenerator {
1191 #[inline]
1192 fn next_back(&mut self) -> Option<Self::Item> {
1193 let index = self.index.next_back()?;
1194 Some(self.to_bools(index))
1195 }
1196
1197 #[inline]
1198 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1199 let index = self.index.nth_back(n)?;
1200 Some(self.to_bools(index))
1201 }
1202}
1203
1204impl ExactSizeIterator for BoolsGenerator {
1205 #[inline]
1206 fn len(&self) -> usize {
1207 self.index.len()
1208 }
1209}
1210
1211impl FusedIterator for BoolsGenerator {}
1212
1213/// An [`Iterator`] that produces exactly `n` [`bool`]s.
1214///
1215/// See [`gen()`] for more information.
1216#[derive(PartialEq, Eq, Hash, Clone, Debug)]
1217pub struct Bools {
1218 variables: Range<u8>,
1219 index: usize,
1220}
1221
1222impl Bools {
1223 #[inline]
1224 fn new(n: u8, index: usize) -> Self {
1225 Self {
1226 variables: 0..n,
1227 index,
1228 }
1229 }
1230
1231 #[inline]
1232 fn fill_into(&mut self, bools: &mut [bool]) {
1233 for (b, val) in bools.iter_mut().zip(self.by_ref()) {
1234 *b = val;
1235 }
1236 }
1237
1238 #[inline]
1239 fn fill_bools_into(mut self, bools: &mut [bool; MAX]) -> &[bool] {
1240 let n = self.variables.len();
1241
1242 // Safe as `gen()` panics if `n > MAX`
1243 let bools = &mut bools[..n];
1244
1245 // Safe to unwrap as `self` produces exactly `n` items
1246 bools.fill_with(|| self.next().unwrap());
1247
1248 bools
1249 }
1250
1251 #[inline]
1252 fn to_bool(&self, var: u8) -> bool {
1253 ((self.index >> var) & 1) != 0
1254 }
1255}
1256
1257impl Iterator for Bools {
1258 type Item = bool;
1259
1260 #[inline]
1261 fn next(&mut self) -> Option<Self::Item> {
1262 let var = self.variables.next()?;
1263 Some(self.to_bool(var))
1264 }
1265
1266 #[inline]
1267 fn size_hint(&self) -> (usize, Option<usize>) {
1268 self.variables.size_hint()
1269 }
1270
1271 #[inline]
1272 fn count(self) -> usize
1273 where
1274 Self: Sized,
1275 {
1276 self.variables.count()
1277 }
1278
1279 #[inline]
1280 fn nth(&mut self, n: usize) -> Option<Self::Item> {
1281 let index = self.variables.nth(n)?;
1282 Some(self.to_bool(index))
1283 }
1284
1285 #[inline]
1286 fn last(mut self) -> Option<Self::Item>
1287 where
1288 Self: Sized,
1289 {
1290 self.next_back()
1291 }
1292
1293 #[inline]
1294 fn min(mut self) -> Option<Self::Item>
1295 where
1296 Self::Item: Ord,
1297 {
1298 self.next()
1299 }
1300
1301 #[inline]
1302 fn max(mut self) -> Option<Self::Item>
1303 where
1304 Self::Item: Ord,
1305 {
1306 self.next_back()
1307 }
1308}
1309
1310impl DoubleEndedIterator for Bools {
1311 #[inline]
1312 fn next_back(&mut self) -> Option<Self::Item> {
1313 let var = self.variables.next_back()?;
1314 Some(self.to_bool(var))
1315 }
1316
1317 #[inline]
1318 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
1319 let var = self.variables.nth_back(n)?;
1320 Some(self.to_bool(var))
1321 }
1322}
1323
1324impl ExactSizeIterator for Bools {
1325 #[inline]
1326 fn len(&self) -> usize {
1327 self.variables.len()
1328 }
1329}
1330
1331impl FusedIterator for Bools {}
1332
1333#[cfg(test)]
1334mod tests {
1335 use alloc::boxed::Box;
1336 use alloc::vec;
1337
1338 use super::*;
1339
1340 #[test]
1341 fn test_is_supported() {
1342 for n in 0..=MAX {
1343 assert!(is_supported(n));
1344 }
1345
1346 assert!(!is_supported(MAX + 1));
1347 }
1348
1349 #[test]
1350 fn test_count() {
1351 assert_eq!(count(0), Some(0));
1352 assert_eq!(count(1), Some(2));
1353 assert_eq!(count(2), Some(4));
1354 assert_eq!(count(3), Some(8));
1355 assert_eq!(count(4), Some(16));
1356 assert_eq!(count(5), Some(32));
1357 assert_eq!(count(6), Some(64));
1358 assert_eq!(count(7), Some(128));
1359 assert_eq!(count(8), Some(256));
1360 assert_eq!(count(9), Some(512));
1361 assert_eq!(count(10), Some(1024));
1362
1363 assert_eq!(count(usize::MAX), None);
1364 }
1365
1366 #[test]
1367 fn test_count_max() {
1368 assert!(count(MAX).is_some());
1369 }
1370
1371 #[test]
1372 #[cfg_attr(not(target_pointer_width = "16"), ignore)]
1373 fn test_count_16() {
1374 assert_eq!(count(15), Some(32768));
1375 assert_eq!(count(16), None);
1376 }
1377
1378 #[test]
1379 #[cfg_attr(not(target_pointer_width = "32"), ignore)]
1380 fn test_count_32() {
1381 assert_eq!(count(31), Some(2147483648));
1382 assert_eq!(count(32), None);
1383 }
1384
1385 #[test]
1386 #[cfg_attr(not(target_pointer_width = "64"), ignore)]
1387 fn test_count_64() {
1388 assert_eq!(count(63), Some(9223372036854775808));
1389 assert_eq!(count(64), None);
1390 }
1391
1392 macro_rules! test_gen {
1393 ($test_name:ident, $n:literal $(, $($case:expr),* $(,)?)?) => {
1394 #[test]
1395 fn $test_name() {
1396 let n = $n;
1397 let mut iter = gen_vec(n);
1398
1399 let cases = &[$($($case.as_slice()),*)?];
1400
1401 assert_eq!(count(n), Some(cases.len()));
1402
1403 for (i, &case) in cases.iter().enumerate() {
1404 assert_eq!(iter.next().as_deref(), Some(case), "index {i}");
1405 }
1406
1407 assert_eq!(iter.next(), None);
1408 }
1409 };
1410 }
1411
1412 test_gen!(test_gen_0, 0);
1413 test_gen!(test_gen_1, 1, [false], [true]);
1414 test_gen!(
1415 test_gen_2,
1416 2,
1417 [false, false],
1418 [true, false],
1419 [false, true],
1420 [true, true],
1421 );
1422 test_gen!(
1423 test_gen_3,
1424 3,
1425 [false, false, false],
1426 [true, false, false],
1427 [false, true, false],
1428 [true, true, false],
1429 [false, false, true],
1430 [true, false, true],
1431 [false, true, true],
1432 [true, true, true],
1433 );
1434 test_gen!(
1435 test_gen_4,
1436 4,
1437 [false, false, false, false],
1438 [true, false, false, false],
1439 [false, true, false, false],
1440 [true, true, false, false],
1441 [false, false, true, false],
1442 [true, false, true, false],
1443 [false, true, true, false],
1444 [true, true, true, false],
1445 [false, false, false, true],
1446 [true, false, false, true],
1447 [false, true, false, true],
1448 [true, true, false, true],
1449 [false, false, true, true],
1450 [true, false, true, true],
1451 [false, true, true, true],
1452 [true, true, true, true],
1453 );
1454
1455 #[test]
1456 fn test_gen_max_ends() {
1457 for n in 0..=MAX {
1458 let mut iter = gen(n).map(Iterator::collect::<Vec<_>>);
1459
1460 assert_eq!(count(n), Some(iter.len()));
1461
1462 if iter.len() == 0 {
1463 continue;
1464 }
1465
1466 assert_eq!(iter.next().unwrap(), vec![false; n]);
1467 assert_eq!(iter.next_back().unwrap(), vec![true; n]);
1468 }
1469 }
1470
1471 #[derive(PartialEq, Clone, Debug)]
1472 enum Expr {
1473 Bool(bool),
1474 And(Box<Self>, Box<Self>),
1475 Or(Box<Self>, Box<Self>),
1476 }
1477
1478 impl From<bool> for Expr {
1479 fn from(b: bool) -> Self {
1480 Expr::Bool(b)
1481 }
1482 }
1483
1484 fn and(lhs: impl Into<Expr>, rhs: impl Into<Expr>) -> Expr {
1485 Expr::And(Box::new(lhs.into()), Box::new(rhs.into()))
1486 }
1487
1488 fn or(lhs: impl Into<Expr>, rhs: impl Into<Expr>) -> Expr {
1489 Expr::Or(Box::new(lhs.into()), Box::new(rhs.into()))
1490 }
1491
1492 #[test]
1493 fn test_gen_const() {
1494 const N: usize = 3;
1495
1496 let exprs = gen_const::<N>()
1497 .map(|[a, b, c]| and(a, or(b, c)))
1498 .collect::<Vec<_>>();
1499
1500 assert_eq!(count(N), Some(exprs.len()));
1501
1502 let mut exprs = exprs.into_iter();
1503 assert_eq!(exprs.next().unwrap(), and(false, or(false, false)));
1504 assert_eq!(exprs.next().unwrap(), and(true, or(false, false)));
1505 assert_eq!(exprs.next().unwrap(), and(false, or(true, false)));
1506 assert_eq!(exprs.next().unwrap(), and(true, or(true, false)));
1507 assert_eq!(exprs.next().unwrap(), and(false, or(false, true)));
1508 assert_eq!(exprs.next().unwrap(), and(true, or(false, true)));
1509 assert_eq!(exprs.next().unwrap(), and(false, or(true, true)));
1510 assert_eq!(exprs.next().unwrap(), and(true, or(true, true)));
1511 assert_eq!(exprs.next(), None);
1512 }
1513
1514 #[test]
1515 fn test_gen_slice() {
1516 const N: usize = 3;
1517
1518 let exprs = gen_slice(N, |bools| and(bools[0], or(bools[1], bools[2]))).collect::<Vec<_>>();
1519
1520 assert_eq!(count(N), Some(exprs.len()));
1521
1522 let mut exprs = exprs.into_iter();
1523 assert_eq!(exprs.next().unwrap(), and(false, or(false, false)));
1524 assert_eq!(exprs.next().unwrap(), and(true, or(false, false)));
1525 assert_eq!(exprs.next().unwrap(), and(false, or(true, false)));
1526 assert_eq!(exprs.next().unwrap(), and(true, or(true, false)));
1527 assert_eq!(exprs.next().unwrap(), and(false, or(false, true)));
1528 assert_eq!(exprs.next().unwrap(), and(true, or(false, true)));
1529 assert_eq!(exprs.next().unwrap(), and(false, or(true, true)));
1530 assert_eq!(exprs.next().unwrap(), and(true, or(true, true)));
1531 assert_eq!(exprs.next(), None);
1532 }
1533
1534 #[test]
1535 fn test_gen_const_rev() {
1536 const N: usize = 3;
1537
1538 let mut combinations = gen_const::<N>().collect::<Vec<_>>();
1539 combinations.reverse();
1540
1541 let combinations2 = gen_const::<N>().rev().collect::<Vec<_>>();
1542
1543 assert_eq!(combinations, combinations2);
1544 }
1545
1546 #[test]
1547 fn test_gen_rev() {
1548 const N: usize = 3;
1549
1550 let mut combinations = gen_vec(N).collect::<Vec<_>>();
1551 combinations.reverse();
1552
1553 let combinations2 = gen_vec(N).rev().collect::<Vec<_>>();
1554
1555 assert_eq!(combinations, combinations2);
1556 }
1557
1558 #[test]
1559 fn test_each_const() {
1560 const N: usize = 3;
1561
1562 let mut iter = gen_vec(N);
1563
1564 each_const::<N, _>(|bools| {
1565 assert_eq!(bools, iter.next().unwrap().as_slice());
1566 });
1567
1568 assert_eq!(iter.next(), None);
1569 }
1570
1571 #[test]
1572 fn test_each() {
1573 const N: usize = 3;
1574
1575 let mut iter = gen_vec(N);
1576
1577 each(N, |bools| {
1578 assert_eq!(bools, iter.next().unwrap());
1579 });
1580
1581 assert_eq!(iter.next(), None);
1582 }
1583
1584 #[test]
1585 fn test_each_vec_slice() {
1586 const N: usize = 3;
1587
1588 let mut iter = gen_vec(N);
1589
1590 each_vec_slice(N, |bools| {
1591 assert_eq!(bools, iter.next().unwrap());
1592 });
1593
1594 assert_eq!(iter.next(), None);
1595 }
1596
1597 #[test]
1598 fn test_each_with_buffer() {
1599 const N: usize = 3;
1600
1601 let mut iter = gen_vec(N);
1602
1603 let mut buf = [false; N];
1604 each_with_buffer(N, &mut buf, |bools| {
1605 assert_eq!(bools, iter.next().unwrap());
1606 });
1607
1608 assert_eq!(iter.next(), None);
1609 }
1610}