1#![doc = include_str!("../README.md")]
2#![no_std]
3#![deny(clippy::missing_inline_in_public_items, missing_docs)]
4#![cfg_attr(nightly, feature(portable_simd))]
5
6mod nzp;
7#[cfg(nightly)]
8pub use nzp::LanesMult;
9pub use nzp::NonZeroPow2;
10
11pub mod traits;
12use traits::Multiplier;
13
14#[inline(always)]
16pub fn down<M: Multiplier>(
17 value: M::Number, multiplier: M
18) -> M::Number {
19 multiplier.down(value)
20}
21
22#[inline(always)]
26pub fn up<M: Multiplier>(
27 value: M::Number, multiplier: M
28) -> Option<M::Number> {
29 multiplier.up(value)
30}
31
32#[cfg(test)]
33mod test {
34 use core::num::NonZeroU8;
35
36 use quickcheck::TestResult;
37 use quickcheck_macros::quickcheck;
38
39 use super::*;
40
41 #[quickcheck]
42 fn mult2_down_round_mult_is_identity(value: NonZeroPow2<u8>) -> bool {
43 down(value.get(), value) == value.get()
44 }
45
46 #[quickcheck]
47 fn mult2_up_round_mult_is_identity(value: NonZeroPow2<u8>) -> bool {
48 up(value.get(), value) == Some(value.get())
49 }
50
51 #[quickcheck]
52 fn mult_down_round_mult_is_identity(value: NonZeroU8) -> bool {
53 down(value.get(), value) == value.get()
54 }
55
56 #[quickcheck]
57 fn mult_up_round_mult_is_identity(value: NonZeroU8) -> bool {
58 up(value.get(), value) == Some(value.get())
59 }
60
61 #[quickcheck]
62 fn mult_up_overflow_is_none(value: u8, mult: NonZeroU8) -> TestResult {
63 if
64 value % mult.get() != 0 &&
65 u8::MAX - ((value / mult) * mult.get()) < mult.get()
66 {
67 TestResult::from_bool(up(value, mult).is_none())
68 } else {
69 TestResult::discard()
70 }
71 }
72
73 #[quickcheck]
74 fn mult2_up_overflow_is_none(
75 value: u8, mult: NonZeroPow2<u8>
76 ) -> TestResult {
77 if
78 value % mult.get() != 0 &&
79 u8::MAX - ((value / mult.get()) * mult.get()) < mult.get()
80 {
81 TestResult::from_bool(up(value, mult).is_none())
82 } else {
83 TestResult::discard()
84 }
85 }
86
87 #[quickcheck]
88 fn mult2_down_is_correct(value: u8, mult: NonZeroPow2<u8>) -> bool {
89 down(value, mult) == (value / mult.get()) * mult.get()
90 }
91
92 #[quickcheck]
93 fn mult_down_is_correct(value: u8, mult: NonZeroU8) -> bool {
94 down(value, mult) == (value / mult.get()) * mult.get()
95 }
96
97 #[test]
98 fn up_12_4_identity() {
99 assert_eq!(
100 up(12_usize, NonZeroPow2::new(4).unwrap()).unwrap(),
101 12
102 );
103 }
104
105 #[test]
106 fn down_12_4() {
107 assert_eq!(
108 down(12_usize, NonZeroPow2::new(4).unwrap()),
109 12
110 );
111 }
112}