1#![no_std]
6
7use core::convert::TryInto;
8use core::fmt::Debug;
9use num_integer::Integer;
10use num_traits::{PrimInt, Unsigned, WrappingShr};
11
12#[derive(Copy, Clone, Eq, PartialEq, Debug)]
13pub struct DividerInner<T> {
14 magic: T,
15 more: u8,
16}
17
18#[derive(Copy, Clone, Eq, PartialEq, Debug)]
19#[repr(transparent)]
20pub struct Divider<T: PrimInt>(DividerInner<T>);
21
22#[derive(Copy, Clone, Eq, PartialEq, Debug)]
23#[repr(transparent)]
24pub struct BranchFreeDivider<T: PrimInt>(DividerInner<T>);
25
26impl<T> DividerInner<T> {
59 #[inline]
60 fn new(magic: T, more: u8) -> Self {
61 Self { magic, more }
62 }
63}
64
65const SHIFT_MASK_32: u8 = 0x1F;
66const SHIFT_MASK_64: u8 = 0x3F;
67const ADD_MARKER: u8 = 0x40;
68const NEGATIVE_DIVISOR: u8 = 0x80;
69
70#[derive(thiserror::Error, Debug)]
71pub enum DividerError {
72 #[error("divider must be != 0")]
73 Zero,
74 #[error("branchfree divider must be != 1")]
75 BranchFreeOne,
76}
77
78pub trait DividerInt: PrimInt
79where
80 <Self::Double as TryInto<Self>>::Error: Debug,
81{
82 const SHIFT_MASK: u8;
83 const BITS: u32;
84 const SIGNED: bool;
85 type Double: PrimInt + From<Self> + TryInto<Self>;
86 type Unsigned: PrimInt + Unsigned;
87 type UnsignedDouble: PrimInt + Unsigned;
88
89 #[inline]
90 fn mullhi(x: Self, y: Self) -> Self {
93 let x = Self::Double::from(x);
94 let y = Self::Double::from(y);
95 let r = x * y;
96 (r >> Self::BITS as usize).try_into().unwrap()
98 }
99 fn internal_gen(self, branchfree: bool) -> Result<DividerInner<Self>, DividerError>;
100 fn gen(self) -> Result<DividerInner<Self>, DividerError> {
101 self.internal_gen(false)
102 }
103 fn branchfree_gen(self) -> Result<DividerInner<Self>, DividerError> {
104 if Self::SIGNED {
105 self.internal_gen(true)
106 } else {
107 if self == Self::one() {
108 return Err(DividerError::BranchFreeOne);
109 }
110 let mut inner = self.internal_gen(true)?;
111 inner.more &= Self::SHIFT_MASK;
112 Ok(inner)
113 }
114 }
115 fn recover(denom: &DividerInner<Self>) -> Self;
116 fn branchfree_recover(denom: &DividerInner<Self>) -> Self;
117
118 fn unsigned_div_by(self, denom: &Divider<Self>) -> Self {
119 let numer = self;
120 let magic = denom.0.magic;
121 let more = denom.0.more;
122 if magic.is_zero() {
123 numer.shr(more as usize)
124 } else {
125 let q = Self::mullhi(magic, numer);
126 if (more & ADD_MARKER) != 0 {
127 let t = ((numer - q) >> 1) + q;
128 t.shr((more & Self::SHIFT_MASK) as usize)
129 } else {
130 q.shr(more as usize)
133 }
134 }
135 }
136
137 fn unsigned_branchfree_div_by(self, denom: &BranchFreeDivider<Self>) -> Self
138 where
139 Self: WrappingShr,
140 {
141 let numer = self;
142 let q = Self::mullhi(denom.0.magic, numer);
143 let t = ((numer - q) >> 1) + q;
144 t.wrapping_shr(denom.0.more as u32)
145 }
146}
147
148impl DividerInt for u32 {
149 const SHIFT_MASK: u8 = SHIFT_MASK_32;
150 const BITS: u32 = 32;
151 const SIGNED: bool = false;
152 type Double = u64;
153 type Unsigned = Self;
154 type UnsignedDouble = Self::Double;
155
156 fn internal_gen(self, branchfree: bool) -> Result<DividerInner<Self>, DividerError> {
157 let d = self;
158 if d == 0 {
159 return Err(DividerError::Zero);
160 }
161
162 let floor_log_2_d = (Self::BITS - 1) - d.leading_zeros();
163
164 Ok(if (d & (d - 1)) == 0 {
166 DividerInner::new(0, (floor_log_2_d - u32::from(branchfree)) as u8)
171 } else {
172 let (proposed_m, rem) = (1u64 << (floor_log_2_d + 32)).div_rem(&(d as u64));
173 let mut proposed_m = proposed_m as u32;
174 let rem = rem as u32;
175 assert!(rem > 0 && rem < d);
176
177 let e = d - rem;
178
179 let more = if !branchfree && (e < (1 << floor_log_2_d)) {
181 floor_log_2_d as u8
183 } else {
184 proposed_m = proposed_m.wrapping_add(proposed_m);
190 let twice_rem = rem.wrapping_add(rem);
191 if twice_rem >= d || twice_rem < rem {
192 proposed_m += 1;
193 }
194 (floor_log_2_d as u8) | ADD_MARKER
195 };
196 DividerInner::new(1 + proposed_m, more)
197 })
203 }
204
205 fn recover(denom: &DividerInner<Self>) -> Self {
206 let more = denom.more;
207 let shift = more & Self::SHIFT_MASK;
208
209 if 0 == denom.magic {
210 1 << shift
211 } else if 0 == (more & ADD_MARKER) {
212 let dividend: Self::Double = 1 << (shift as u32 + Self::BITS);
218 1 + (dividend / denom.magic as Self::Double) as Self
219 } else {
220 let half_n: Self::Double = 1 << (32 + shift);
226 let d = (1 << 32) | denom.magic as Self::Double;
227 let (half_q, rem) = half_n.div_rem(&d);
230 let half_q = half_q as Self;
231 let full_q = half_q + half_q + Self::from((rem << 1) >= d);
236
237 full_q + 1
239 }
240 }
241
242 fn branchfree_recover(denom: &DividerInner<Self>) -> Self {
243 let more = denom.more;
244 let shift = more & Self::SHIFT_MASK;
245
246 if 0 == denom.magic {
247 1 << (shift + 1)
248 } else {
249 let half_n: Self::Double = 1 << (Self::BITS + shift as u32);
255 let d = (1 << Self::BITS) | denom.magic as Self::Double;
256 let (half_q, rem) = half_n.div_rem(&d);
259 let half_q = half_q as Self;
260 let full_q = half_q + half_q + Self::from((rem << 1) >= d);
265
266 full_q + 1
268 }
269 }
270}
271
272impl DividerInt for i32 {
273 const SHIFT_MASK: u8 = SHIFT_MASK_32;
274 const BITS: u32 = 32;
275 const SIGNED: bool = true;
276 type Double = i64;
277 type Unsigned = u32;
278 type UnsignedDouble = u64;
279
280 fn internal_gen(self, branchfree: bool) -> Result<DividerInner<Self>, DividerError> {
281 let d = self;
282
283 if d == 0 {
284 return Err(DividerError::Zero);
285 }
286
287 let abs_d = (if d < 0 { d.wrapping_neg() } else { d }) as Self::Unsigned;
294 let floor_log_2_d = (Self::BITS - 1) - abs_d.leading_zeros();
295 Ok(if (abs_d & (abs_d - 1)) == 0 {
298 DividerInner::new(
300 0,
301 floor_log_2_d as u8 | if d < 0 { NEGATIVE_DIVISOR } else { 0 },
302 )
303 } else {
304 assert!(floor_log_2_d >= 1);
305
306 let (proposed_m, rem) =
309 (1u64 << (floor_log_2_d - 1 + Self::BITS)).div_rem(&(abs_d as u64));
310 let mut proposed_m = proposed_m as Self::Unsigned;
311 let rem = rem as Self::Unsigned;
312 let e = abs_d - rem;
313
314 let mut more = if !branchfree && e < (1 << floor_log_2_d) {
317 (floor_log_2_d - 1) as u8
319 } else {
320 proposed_m = proposed_m.wrapping_add(proposed_m);
324 let twice_rem = rem.wrapping_add(rem);
325 if twice_rem >= abs_d || twice_rem < rem {
326 proposed_m += 1;
327 }
328 floor_log_2_d as u8 | ADD_MARKER
329 };
330
331 proposed_m += 1;
332 let mut magic = proposed_m as Self;
333
334 if d < 0 {
337 more |= NEGATIVE_DIVISOR;
338 if !branchfree {
339 magic = -magic;
340 }
341 }
342 DividerInner::new(magic, more)
343 })
344 }
345
346 fn recover(denom: &DividerInner<Self>) -> Self {
347 let more = denom.more;
348 let shift = more & Self::SHIFT_MASK;
349 if 0 == denom.magic {
350 let mut abs_d: Self = 1 << shift;
351 if 0 != (more & NEGATIVE_DIVISOR) {
352 abs_d = abs_d.wrapping_neg();
353 }
354 abs_d
355 } else {
356 let negative_divisor = 0 != (more & NEGATIVE_DIVISOR);
364 let magic_was_negated = if 0 != (more & ADD_MARKER) {
365 denom.magic > 0
366 } else {
367 denom.magic < 0
368 };
369
370 let result = if denom.magic == 0 {
372 1 << shift
373 } else {
374 let d = (if magic_was_negated {
375 -denom.magic
376 } else {
377 denom.magic
378 }) as Self::Unsigned;
379 let n = 1u64 << (32 + shift); let q = (n / d as u64) as Self::Unsigned;
381 q as Self + 1
382 };
383 if negative_divisor {
384 -result
385 } else {
386 result
387 }
388 }
389 }
390
391 #[inline]
392 fn branchfree_recover(denom: &DividerInner<Self>) -> Self {
393 Self::recover(denom)
394 }
395}
396
397impl DividerInt for u64 {
398 const SHIFT_MASK: u8 = SHIFT_MASK_64;
399 const BITS: u32 = 64;
400 const SIGNED: bool = false;
401 type Double = u128;
402 type Unsigned = Self;
403 type UnsignedDouble = Self::Double;
404
405 fn internal_gen(self, branchfree: bool) -> Result<DividerInner<Self>, DividerError> {
406 let d = self;
407
408 if d == 0 {
409 return Err(DividerError::Zero);
410 }
411 let floor_log_2_d: u32 = 63 - d.leading_zeros();
412
413 Ok(if (d & (d - 1)) == 0 {
415 DividerInner::new(0, (floor_log_2_d - u32::from(branchfree)) as u8)
420 } else {
421 let (proposed_m, rem) = (1u128 << (floor_log_2_d + 64)).div_rem(&(d as u128));
423 let mut proposed_m = proposed_m as u64;
424 let rem = rem as u64;
425 assert!(rem > 0 && rem < d);
426
427 let e = d - rem;
428
429 let more = if !branchfree && e < (1 << floor_log_2_d) {
431 floor_log_2_d as u8
433 } else {
434 proposed_m = proposed_m.wrapping_add(proposed_m);
440 let twice_rem = rem.wrapping_add(rem);
441 if twice_rem >= d || twice_rem < rem {
442 proposed_m += 1;
443 }
444 (floor_log_2_d as u8) | ADD_MARKER
445 };
446
447 DividerInner::new(1 + proposed_m, more)
448 })
455 }
456
457 fn recover(denom: &DividerInner<Self>) -> Self {
458 let more = denom.more;
459 let shift = more & Self::SHIFT_MASK;
460
461 if 0 == denom.magic {
462 1 << shift
463 } else if 0 == (more & ADD_MARKER) {
464 let dividend = 1u128 << (shift + 64);
470 1 + (dividend / denom.magic as u128) as u64
471 } else {
472 let half_n = 1u128 << (shift + 64);
481 let d = (1 << 64) | denom.magic as u128;
483 let (half_q, r) = half_n.div_rem(&d);
486 let half_q = half_q as u64;
487 let dr = r.wrapping_add(r);
492 let dr_exceeds_d = dr > d;
493 let full_q = half_q + half_q + u64::from(dr_exceeds_d);
494 full_q + 1
495 }
496 }
497
498 fn branchfree_recover(denom: &DividerInner<Self>) -> Self {
499 let more = denom.more;
500 let shift = more & Self::SHIFT_MASK;
501 if denom.magic == 0 {
502 1 << (shift + 1)
503 } else {
504 let half_n = 1u128 << (shift + 64);
513 let d = (1 << 64) + denom.magic as u128;
515 let (half_q, r) = half_n.div_rem(&d);
518 let half_q = half_q as u64;
519 let dr = r.wrapping_add(r);
524 let dr_exceeds_d = dr > d;
525 let full_q = half_q + half_q + u64::from(dr_exceeds_d);
526 full_q + 1
527 }
528 }
529}
530
531impl DividerInt for i64 {
532 const SHIFT_MASK: u8 = SHIFT_MASK_64;
533 const BITS: u32 = 64;
534 const SIGNED: bool = true;
535 type Double = i128;
536 type Unsigned = u64;
537 type UnsignedDouble = u128;
538
539 fn internal_gen(self, branchfree: bool) -> Result<DividerInner<Self>, DividerError> {
540 let d = self;
541
542 if d == 0 {
543 return Err(DividerError::Zero);
544 }
545
546 let abs_d = (if d < 0 { d.wrapping_neg() } else { d }) as Self::Unsigned;
553 let floor_log_2_d = (Self::BITS - 1) - abs_d.leading_zeros();
554 Ok(if (abs_d & (abs_d - 1)) == 0 {
557 DividerInner::new(
559 0,
560 floor_log_2_d as u8 | if d < 0 { NEGATIVE_DIVISOR } else { 0 },
561 )
562 } else {
563 assert!(floor_log_2_d >= 1);
564
565 let (proposed_m, rem) =
568 (1u128 << (floor_log_2_d - 1 + Self::BITS)).div_rem(&(abs_d as u128));
569 let mut proposed_m = proposed_m as Self::Unsigned;
570 let rem = rem as Self::Unsigned;
571 let e = abs_d - rem;
572
573 let mut more = if !branchfree && e < (1 << floor_log_2_d) {
576 (floor_log_2_d - 1) as u8
578 } else {
579 proposed_m = proposed_m.wrapping_add(proposed_m);
583 let twice_rem = rem.wrapping_add(rem);
584 if twice_rem >= abs_d || twice_rem < rem {
585 proposed_m += 1;
586 }
587 floor_log_2_d as u8 | ADD_MARKER
588 };
589
590 proposed_m += 1;
591 let mut magic = proposed_m as Self;
592
593 if d < 0 {
596 more |= NEGATIVE_DIVISOR;
597 if !branchfree {
598 magic = -magic;
599 }
600 }
601 DividerInner::new(magic, more)
602 })
603 }
604
605 fn recover(denom: &DividerInner<Self>) -> Self {
606 let more = denom.more;
607 let shift = more & Self::SHIFT_MASK;
608 if 0 == denom.magic {
609 let mut abs_d = 1i64 << shift;
610 if 0 != (more & NEGATIVE_DIVISOR) {
611 abs_d = abs_d.wrapping_neg();
612 }
613 abs_d
614 } else {
615 let negative_divisor = 0 != (more & NEGATIVE_DIVISOR);
617 let magic_was_negated = if 0 != (more & ADD_MARKER) {
618 denom.magic > 0
619 } else {
620 denom.magic < 0
621 };
622
623 let d = if magic_was_negated {
624 -denom.magic
625 } else {
626 denom.magic
627 } as Self::Unsigned;
628 let n = 1u128 << (shift as u32 + Self::BITS);
629 let q = (n / d as u128) as u64;
630 let mut result = (q + 1) as Self;
631 if negative_divisor {
632 result = -result;
633 }
634 result
635 }
636 }
637
638 #[inline]
639 fn branchfree_recover(denom: &DividerInner<Self>) -> Self {
640 Self::recover(denom)
641 }
642}
643
644impl<T: DividerInt> From<T> for Divider<T> {
645 fn from(d: T) -> Self {
646 Self::new(d).unwrap()
647 }
648}
649
650impl<T: DividerInt> Divider<T> {
651 pub fn new(d: T) -> Result<Self, DividerError> {
652 d.gen().map(Self)
653 }
654
655 pub fn recover(&self) -> T {
656 T::recover(&self.0)
657 }
658}
659
660impl<T: DividerInt> From<T> for BranchFreeDivider<T> {
661 fn from(d: T) -> Self {
662 Self::new(d).unwrap()
663 }
664}
665
666impl<T: DividerInt> BranchFreeDivider<T> {
667 pub fn new(d: T) -> Result<Self, DividerError> {
668 d.branchfree_gen().map(Self)
669 }
670
671 pub fn recover(&self) -> T {
672 T::branchfree_recover(&self.0)
673 }
674}
675
676impl core::ops::Div<&Divider<Self>> for u32 {
677 type Output = Self;
678
679 #[inline]
680 fn div(self, denom: &Divider<Self>) -> Self::Output {
681 self.unsigned_div_by(denom)
682 }
683}
684
685impl core::ops::Div<&BranchFreeDivider<Self>> for u32 {
686 type Output = Self;
687
688 #[inline]
689 fn div(self, denom: &BranchFreeDivider<Self>) -> Self::Output {
690 self.unsigned_branchfree_div_by(denom)
691 }
692}
693
694impl core::ops::Div<&Divider<Self>> for i32 {
695 type Output = Self;
696
697 #[inline]
698 fn div(self, denom: &Divider<Self>) -> Self::Output {
699 let numer = self;
700 let more = denom.0.more;
701 let shift = more & Self::SHIFT_MASK;
702
703 if 0 == denom.0.magic {
704 let sign = (more as i8 >> 7) as u32;
705 let mask = (1u32 << shift) - 1;
706 let uq = (numer as u32).wrapping_add((numer >> 31) as u32 & mask);
707 let mut q = uq as Self;
708 q >>= shift;
709 q = (q as u32 ^ sign).wrapping_sub(sign) as Self;
710 q
711 } else {
712 let mut uq = Self::mullhi(denom.0.magic, numer) as u32;
713 if 0 != (more & ADD_MARKER) {
714 let sign = (more as i8 >> 7) as Self;
716 uq = uq.wrapping_add(((numer as u32) ^ (sign as u32)).wrapping_sub(sign as u32));
719 }
720 let mut q = uq as Self;
721 q >>= shift;
722 q += Self::from(q < 0);
723 q
724 }
725 }
726}
727
728impl core::ops::Div<&BranchFreeDivider<Self>> for i32 {
729 type Output = Self;
730
731 #[inline]
732 fn div(self, denom: &BranchFreeDivider<Self>) -> Self::Output {
733 let numer = self;
734 let more = denom.0.more;
735 let shift = more & Self::SHIFT_MASK;
736 let sign = (more as i8 >> 7) as Self;
738 let magic = denom.0.magic;
739 let mut q = Self::mullhi(magic, numer);
740 q += numer;
741
742 let is_power_of_2 = u32::from(magic == 0);
746 let q_sign = (q >> 31) as u32;
747 q += (q_sign & ((1 << shift) - is_power_of_2)) as Self;
748
749 q >>= shift;
751 q = (q ^ sign).wrapping_sub(sign);
753
754 q
755 }
756}
757
758impl core::ops::Div<&Divider<Self>> for u64 {
759 type Output = Self;
760
761 #[inline]
762 fn div(self, denom: &Divider<Self>) -> Self::Output {
763 self.unsigned_div_by(denom)
764 }
765}
766
767impl core::ops::Div<&BranchFreeDivider<Self>> for u64 {
768 type Output = Self;
769
770 #[inline]
771 fn div(self, denom: &BranchFreeDivider<Self>) -> Self::Output {
772 self.unsigned_branchfree_div_by(denom)
773 }
774}
775
776impl core::ops::Div<&Divider<Self>> for i64 {
777 type Output = Self;
778
779 #[inline]
780 fn div(self, denom: &Divider<Self>) -> Self::Output {
781 let numer = self;
782 let more = denom.0.more;
783 let shift = more & Self::SHIFT_MASK;
784
785 if 0 == denom.0.magic {
786 let sign = (more as i8 >> 7) as u64;
787 let mask = (1u64 << shift) - 1;
788 let uq = (numer as u64).wrapping_add((numer >> 63) as u64 & mask);
789 let mut q = uq as Self;
790 q >>= shift;
791 q = (q as u64 ^ sign).wrapping_sub(sign) as Self;
792 q
793 } else {
794 let mut uq = Self::mullhi(denom.0.magic, numer) as u64;
795 if 0 != (more & ADD_MARKER) {
796 let sign = (more as i8 >> 7) as Self;
798 uq = uq.wrapping_add(((numer as u64) ^ (sign as u64)).wrapping_sub(sign as u64));
801 }
802 let mut q = uq as Self;
803 q >>= shift;
804 q += Self::from(q < 0);
805 q
806 }
807 }
808}
809
810impl core::ops::Div<&BranchFreeDivider<Self>> for i64 {
811 type Output = Self;
812
813 #[inline]
814 fn div(self, denom: &BranchFreeDivider<Self>) -> Self::Output {
815 let numer = self;
816 let more = denom.0.more;
817 let shift = more & Self::SHIFT_MASK;
818 let sign = (more as i8 >> 7) as Self;
820 let magic = denom.0.magic;
821 let mut q = Self::mullhi(magic, numer);
822 q += numer;
823
824 let is_power_of_2 = u64::from(magic == 0);
828 let q_sign = (q >> 63) as u64;
829 q += (q_sign & ((1 << shift) - is_power_of_2)) as Self;
830
831 q >>= shift;
833 q = (q ^ sign).wrapping_sub(sign);
835
836 q
837 }
838}