+++ /dev/null
-// 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.
-
-package gc
-
-// Transmogrify slow integer division into fast multiplication using magic.
-
-// argument passing to/from
-// smagic and umagic
-type Magic struct {
- W int // input for both - width
- S int // output for both - shift
- Bad int // output for both - unexpected failure
-
- // magic multiplier for signed literal divisors
- Sd int64 // input - literal divisor
- Sm int64 // output - multiplier
-
- // magic multiplier for unsigned literal divisors
- Ud uint64 // input - literal divisor
- Um uint64 // output - multiplier
- Ua int // output - adder
-}
-
-// magic number for signed division
-// see hacker's delight chapter 10
-func smagic(m *Magic) {
- var mask uint64
-
- m.Bad = 0
- switch m.W {
- default:
- m.Bad = 1
- return
-
- case 8:
- mask = 0xff
-
- case 16:
- mask = 0xffff
-
- case 32:
- mask = 0xffffffff
-
- case 64:
- mask = 0xffffffffffffffff
- }
-
- two31 := mask ^ (mask >> 1)
-
- p := m.W - 1
- ad := uint64(m.Sd)
- if m.Sd < 0 {
- ad = -uint64(m.Sd)
- }
-
- // bad denominators
- if ad == 0 || ad == 1 || ad == two31 {
- m.Bad = 1
- return
- }
-
- t := two31
- ad &= mask
-
- anc := t - 1 - t%ad
- anc &= mask
-
- q1 := two31 / anc
- r1 := two31 - q1*anc
- q1 &= mask
- r1 &= mask
-
- q2 := two31 / ad
- r2 := two31 - q2*ad
- q2 &= mask
- r2 &= mask
-
- var delta uint64
- for {
- p++
- q1 <<= 1
- r1 <<= 1
- q1 &= mask
- r1 &= mask
- if r1 >= anc {
- q1++
- r1 -= anc
- q1 &= mask
- r1 &= mask
- }
-
- q2 <<= 1
- r2 <<= 1
- q2 &= mask
- r2 &= mask
- if r2 >= ad {
- q2++
- r2 -= ad
- q2 &= mask
- r2 &= mask
- }
-
- delta = ad - r2
- delta &= mask
- if q1 < delta || (q1 == delta && r1 == 0) {
- continue
- }
-
- break
- }
-
- m.Sm = int64(q2 + 1)
- if uint64(m.Sm)&two31 != 0 {
- m.Sm |= ^int64(mask)
- }
- m.S = p - m.W
-}
-
-// magic number for unsigned division
-// see hacker's delight chapter 10
-func umagic(m *Magic) {
- var mask uint64
-
- m.Bad = 0
- m.Ua = 0
-
- switch m.W {
- default:
- m.Bad = 1
- return
-
- case 8:
- mask = 0xff
-
- case 16:
- mask = 0xffff
-
- case 32:
- mask = 0xffffffff
-
- case 64:
- mask = 0xffffffffffffffff
- }
-
- two31 := mask ^ (mask >> 1)
-
- m.Ud &= mask
- if m.Ud == 0 || m.Ud == two31 {
- m.Bad = 1
- return
- }
-
- nc := mask - (-m.Ud&mask)%m.Ud
- p := m.W - 1
-
- q1 := two31 / nc
- r1 := two31 - q1*nc
- q1 &= mask
- r1 &= mask
-
- q2 := (two31 - 1) / m.Ud
- r2 := (two31 - 1) - q2*m.Ud
- q2 &= mask
- r2 &= mask
-
- var delta uint64
- for {
- p++
- if r1 >= nc-r1 {
- q1 <<= 1
- q1++
- r1 <<= 1
- r1 -= nc
- } else {
- q1 <<= 1
- r1 <<= 1
- }
-
- q1 &= mask
- r1 &= mask
- if r2+1 >= m.Ud-r2 {
- if q2 >= two31-1 {
- m.Ua = 1
- }
-
- q2 <<= 1
- q2++
- r2 <<= 1
- r2++
- r2 -= m.Ud
- } else {
- if q2 >= two31 {
- m.Ua = 1
- }
-
- q2 <<= 1
- r2 <<= 1
- r2++
- }
-
- q2 &= mask
- r2 &= mask
-
- delta = m.Ud - 1 - r2
- delta &= mask
-
- if p < m.W+m.W {
- if q1 < delta || (q1 == delta && r1 == 0) {
- continue
- }
- }
-
- break
- }
-
- m.Um = q2 + 1
- m.S = p - m.W
-}