File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -267,34 +267,32 @@ pub fn (u Uint128) quo_rem_64(v u64) (Uint128, u64) {
267267}
268268
269269// quo_rem returns q = u/v and r = u%v
270- pub fn (u Uint128) quo_rem (v Uint128 ) (Uint128 , Uint128 ) {
271- mut q := Uint128 {}
272- mut r := Uint128 {}
273- if v.hi == 0 {
274- mut r64 := u64 (0 )
275- q , r64 = u.quo_rem_64 (v.lo)
276- r = Uint128 {r64 , 0 }
277- } else {
278- n := bits.leading_zeros_64 (v.hi)
279- v1 := v.lsh (u32 (n))
280- u1 := v.rsh (1 )
281-
282- mut tq , _ := bits.div_64 (u1 .hi, u1 .lo, v1 .hi)
283- tq >> = u64 (64 - n)
284- if tq != 0 {
285- tq - = 1
286- }
287-
288- q = Uint128 {tq, 0 }
289- r = u - v.mul_64 (tq)
290-
291- if r.cmp (v) > = 0 {
292- q = q.add_64 (1 )
293- r = r - v
294- }
270+ pub fn (a Uint128) quo_rem (b Uint128 ) (Uint128 , Uint128 ) {
271+ if a < b {
272+ return uint128_ zero, a
295273 }
296-
297- return q, r
274+ if b.is_zero () {
275+ panic ('Division by zero' )
276+ }
277+ if b.hi == 0 {
278+ quotient , remainder := a.quo_rem_64 (b.lo)
279+ return quotient, uint128_from_64 (remainder)
280+ }
281+ shift := u32 (b.leading_zeros () - a.leading_zeros ())
282+ mut af := a
283+ mut bf := b.lsh (shift)
284+ mut quotient := uint128_ zero
285+
286+ for _ in 0 .. shift + 1 {
287+ quotient = quotient.lsh (1 )
288+ diff_result := bf.add (af.not ())
289+ s := u64 (i64 (diff_result.hi) >> 63 )
290+ quotient.lo |= s & 1
291+ mask := uint128_new (s, s)
292+ af = af.sub (bf.and (mask))
293+ bf = bf.rsh (1 )
294+ }
295+ return quotient, af
298296}
299297
300298// lsh returns u << n
Original file line number Diff line number Diff line change 1+ import math.big
12import math.unsigned
23
34fn test_str () {
@@ -193,3 +194,22 @@ fn test_rsh() {
193194 assert '1' == a.rsh (127 ).str ()
194195 assert unsigned.uint128_zero == a.rsh (200 )
195196}
197+
198+ fn test_quo_rem () {
199+ for a_lo in 0 .. 16 {
200+ for a_hi in 0 .. 16 {
201+ for b_lo in 0 .. 16 {
202+ for b_hi in 0 .. 16 {
203+ a := unsigned.uint128_new (u64 (1 << a_lo), u64 (1 << a_hi))
204+ b := unsigned.uint128_new (u64 (1 << b_lo), u64 (1 << b_hi))
205+ big_a := big.integer_from_string (a.str ())!
206+ big_b := big.integer_from_string (b.str ())!
207+ q , r := a.quo_rem (b)
208+ big_q , big_r := big_a.div_mod (big_b)
209+ assert q.str () == big_q.str ()
210+ assert r.str () == big_r.str ()
211+ }
212+ }
213+ }
214+ }
215+ }
You can’t perform that action at this time.
0 commit comments