// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This file provides a generic Go implementation of uint128 divided by uint64. // The code is derived from Go's generic math/big.divWW_g // (src/math/big/arith.go), but is only used on ARM64. package time import "math/bits" type word uint const ( _W = bits.UintSize // word size in bits _W2 = _W / 2 // half word size in bits _B2 = 1 << _W2 // half digit base _M2 = _B2 - 1 // half digit mask ) // nlz returns the number of leading zeros in x. // Wraps bits.LeadingZeros call for convenience. func nlz(x word) uint { return uint(bits.LeadingZeros(uint(x))) } // q = (u1<<_W + u0 - r)/y // Adapted from Warren, Hacker's Delight, p. 152. func divWW(u1, u0, v word) (q, r word) { if u1 >= v { return 1<<_W - 1, 1<<_W - 1 } s := nlz(v) v <<= s vn1 := v >> _W2 vn0 := v & _M2 un32 := u1<>(_W-s) un10 := u0 << s un1 := un10 >> _W2 un0 := un10 & _M2 q1 := un32 / vn1 rhat := un32 - q1*vn1 for q1 >= _B2 || q1*vn0 > _B2*rhat+un1 { q1-- rhat += vn1 if rhat >= _B2 { break } } un21 := un32*_B2 + un1 - q1*v q0 := un21 / vn1 rhat = un21 - q0*vn1 for q0 >= _B2 || q0*vn0 > _B2*rhat+un0 { q0-- rhat += vn1 if rhat >= _B2 { break } } return q1*_B2 + q0, (un21*_B2 + un0 - q0*v) >> s }