@@ -14,6 +14,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
1414use std:: sync:: mpsc:: { Receiver , Sender , channel} ;
1515use std:: thread;
1616
17+ const MOD : usize = 0x7fffffff ;
1718const PART_ONE : usize = 40_000_000 ;
1819const PART_TWO : usize = 5_000_000 ;
1920const BLOCK : usize = 50_000 ;
@@ -63,8 +64,8 @@ fn sender(shared: &Shared, tx: &Sender<Block>) {
6364 while !shared. done . load ( Ordering :: Relaxed ) {
6465 // Start at any point in the sequence using modular exponentiation.
6566 let start = shared. start . fetch_add ( BLOCK , Ordering :: Relaxed ) ;
66- let mut first = shared. first * 16807 . mod_pow ( start, 0x7fffffff ) ;
67- let mut second = shared. second * 48271 . mod_pow ( start, 0x7fffffff ) ;
67+ let mut first = shared. first * 16807 . mod_pow ( start, MOD ) ;
68+ let mut second = shared. second * 48271 . mod_pow ( start, MOD ) ;
6869
6970 // Estimate capacity at one quarter or one eight, plus a little extra for variance.
7071 let mut ones = 0 ;
@@ -73,8 +74,8 @@ fn sender(shared: &Shared, tx: &Sender<Block>) {
7374
7475 // Check part one pairs immediately while queueing part two pairs.
7576 for _ in 0 ..BLOCK {
76- first = ( first * 16807 ) % 0x7fffffff ;
77- second = ( second * 48271 ) % 0x7fffffff ;
77+ first = fast_mod ( first * 16807 ) ;
78+ second = fast_mod ( second * 48271 ) ;
7879
7980 let left = first as u16 ;
8081 let right = second as u16 ;
@@ -167,3 +168,11 @@ fn receiver(shared: &Shared, rx: &Receiver<Block>) -> (u32, u32) {
167168 let part_one = blocks. iter ( ) . take ( PART_ONE / BLOCK ) . map ( |p| p. ones ) . sum ( ) ;
168169 ( part_one, part_two)
169170}
171+
172+ #[ inline]
173+ fn fast_mod ( n : usize ) -> usize {
174+ let low = n & MOD ;
175+ let high = n >> 31 ;
176+ let sum = low + high;
177+ if sum < MOD { sum } else { sum - MOD }
178+ }
0 commit comments