Skip to content

Commit

Permalink
src/cmd/compile/internal/gc: re-vendor math/big, manually adjust mpar…
Browse files Browse the repository at this point in the history
…ith3.go

The only unreviewed change is in mparith3.go.

Change-Id: Iec0885e7688981cbaed04c152dc9b1c7032677e6
Reviewed-on: https://go-review.googlesource.com/10665
Reviewed-by: Alan Donovan <[email protected]>
Run-TryBot: Robert Griesemer <[email protected]>
  • Loading branch information
griesemer committed Jun 3, 2015
1 parent c1fed84 commit 1e48683
Show file tree
Hide file tree
Showing 12 changed files with 631 additions and 379 deletions.
21 changes: 18 additions & 3 deletions src/cmd/compile/internal/big/arith.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,34 @@ func log2(x Word) int {
return bitLen(x) - 1
}

// Number of leading zeros in x.
func leadingZeros(x Word) uint {
// nlz returns the number of leading zeros in x.
func nlz(x Word) uint {
return uint(_W - bitLen(x))
}

// nlz64 returns the number of leading zeros in x.
func nlz64(x uint64) uint {
switch _W {
case 32:
w := x >> 32
if w == 0 {
return 32 + nlz(Word(x))
}
return nlz(Word(w))
case 64:
return nlz(Word(x))
}
panic("unreachable")
}

// q = (u1<<_W + u0 - r)/y
// Adapted from Warren, Hacker's Delight, p. 152.
func divWW_g(u1, u0, v Word) (q, r Word) {
if u1 >= v {
return 1<<_W - 1, 1<<_W - 1
}

s := leadingZeros(v)
s := nlz(v)
v <<= s

vn1 := v >> _W2
Expand Down
22 changes: 11 additions & 11 deletions src/cmd/compile/internal/big/bits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,21 +203,21 @@ func TestFromBits(t *testing.T) {
}{
// all different bit numbers
{nil, "0"},
{Bits{0}, "0x.8p1"},
{Bits{1}, "0x.8p2"},
{Bits{-1}, "0x.8p0"},
{Bits{63}, "0x.8p64"},
{Bits{33, -30}, "0x.8000000000000001p34"},
{Bits{255, 0}, "0x.8000000000000000000000000000000000000000000000000000000000000001p256"},
{Bits{0}, "0x.8p+1"},
{Bits{1}, "0x.8p+2"},
{Bits{-1}, "0x.8p+0"},
{Bits{63}, "0x.8p+64"},
{Bits{33, -30}, "0x.8000000000000001p+34"},
{Bits{255, 0}, "0x.8000000000000000000000000000000000000000000000000000000000000001p+256"},

// multiple equal bit numbers
{Bits{0, 0}, "0x.8p2"},
{Bits{0, 0, 0, 0}, "0x.8p3"},
{Bits{0, 1, 0}, "0x.8p3"},
{append(Bits{2, 1, 0} /* 7 */, Bits{3, 1} /* 10 */ ...), "0x.88p5" /* 17 */},
{Bits{0, 0}, "0x.8p+2"},
{Bits{0, 0, 0, 0}, "0x.8p+3"},
{Bits{0, 1, 0}, "0x.8p+3"},
{append(Bits{2, 1, 0} /* 7 */, Bits{3, 1} /* 10 */ ...), "0x.88p+5" /* 17 */},
} {
f := test.bits.Float()
if got := f.Format('p', 0); got != test.want {
if got := f.Text('p', 0); got != test.want {
t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want)
}
}
Expand Down
14 changes: 10 additions & 4 deletions src/cmd/compile/internal/big/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@

package big

// A decimal represents a floating-point number in decimal representation.
// The value of a decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
// with the most-significant mantissa digit at index 0.
// A decimal represents an unsigned floating-point number in decimal representation.
// The value of a non-zero decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
// with the most-significant mantissa digit at index 0. For the zero decimal, the
// mantissa length and exponent are 0.
// The zero value for decimal represents a ready-to-use 0.0.
type decimal struct {
mant []byte // mantissa ASCII digits, big-endian
exp int // exponent, valid if len(mant) > 0
exp int // exponent
}

// Maximum shift amount that can be done in one pass without overflow.
Expand All @@ -46,6 +48,7 @@ func (x *decimal) init(m nat, shift int) {
// special case 0
if len(m) == 0 {
x.mant = x.mant[:0]
x.exp = 0
return
}

Expand Down Expand Up @@ -255,4 +258,7 @@ func trim(x *decimal) {
i--
}
x.mant = x.mant[:i]
if i == 0 {
x.exp = 0
}
}
89 changes: 44 additions & 45 deletions src/cmd/compile/internal/big/float.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"math"
)

const debugFloat = true // enable for debugging
const debugFloat = false // enable for debugging

// A nonzero finite Float represents a multi-precision floating point number
//
Expand Down Expand Up @@ -363,7 +363,7 @@ func (x *Float) validate() {
}
const msb = 1 << (_W - 1)
if x.mant[m-1]&msb == 0 {
panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.Format('p', 0)))
panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.Text('p', 0)))
}
if x.prec == 0 {
panic("zero precision finite number")
Expand All @@ -381,14 +381,11 @@ func (x *Float) validate() {
func (z *Float) round(sbit uint) {
if debugFloat {
z.validate()
if z.form > finite {
panic(fmt.Sprintf("round called for non-finite value %s", z))
}
}
// z.form <= finite

z.acc = Exact
if z.form == zero {
if z.form != finite {
// ±0 or ±Inf => nothing left to do
return
}
// z.form == finite && len(z.mant) > 0
Expand Down Expand Up @@ -525,25 +522,6 @@ func (z *Float) round(sbit uint) {
return
}

// nlz returns the number of leading zero bits in x.
func nlz(x Word) uint {
return _W - uint(bitLen(x))
}

func nlz64(x uint64) uint {
// TODO(gri) this can be done more nicely
if _W == 32 {
if x>>32 == 0 {
return 32 + nlz(Word(x))
}
return nlz(Word(x >> 32))
}
if _W == 64 {
return nlz(Word(x))
}
panic("unreachable")
}

func (z *Float) setBits64(neg bool, x uint64) *Float {
if z.prec == 0 {
z.prec = 64
Expand Down Expand Up @@ -732,25 +710,44 @@ func (z *Float) Copy(x *Float) *Float {
return z
}

func high32(x nat) uint32 {
// TODO(gri) This can be done more efficiently on 32bit platforms.
return uint32(high64(x) >> 32)
// msb32 returns the 32 most significant bits of x.
func msb32(x nat) uint32 {
i := len(x) - 1
if i < 0 {
return 0
}
if debugFloat && x[i]&(1<<(_W-1)) == 0 {
panic("x not normalized")
}
switch _W {
case 32:
return uint32(x[i])
case 64:
return uint32(x[i] >> 32)
}
panic("unreachable")
}

func high64(x nat) uint64 {
i := len(x)
if i == 0 {
// msb64 returns the 64 most significant bits of x.
func msb64(x nat) uint64 {
i := len(x) - 1
if i < 0 {
return 0
}
// i > 0
v := uint64(x[i-1])
if _W == 32 {
v <<= 32
if i > 1 {
v |= uint64(x[i-2])
if debugFloat && x[i]&(1<<(_W-1)) == 0 {
panic("x not normalized")
}
switch _W {
case 32:
v := uint64(x[i]) << 32
if i > 0 {
v |= uint64(x[i-1])
}
return v
case 64:
return uint64(x[i])
}
return v
panic("unreachable")
}

// Uint64 returns the unsigned integer resulting from truncating x
Expand All @@ -776,7 +773,7 @@ func (x *Float) Uint64() (uint64, Accuracy) {
// 1 <= x < Inf
if x.exp <= 64 {
// u = trunc(x) fits into a uint64
u := high64(x.mant) >> (64 - uint32(x.exp))
u := msb64(x.mant) >> (64 - uint32(x.exp))
if x.MinPrec() <= 64 {
return u, Exact
}
Expand Down Expand Up @@ -821,7 +818,7 @@ func (x *Float) Int64() (int64, Accuracy) {
// 1 <= |x| < +Inf
if x.exp <= 63 {
// i = trunc(x) fits into an int64 (excluding math.MinInt64)
i := int64(high64(x.mant) >> (64 - uint32(x.exp)))
i := int64(msb64(x.mant) >> (64 - uint32(x.exp)))
if x.neg {
i = -i
}
Expand Down Expand Up @@ -913,6 +910,7 @@ func (x *Float) Float32() (float32, Accuracy) {
}
return float32(math.Inf(+1)), Above
}
// e <= emax

// Determine sign, biased exponent, and mantissa.
var sign, bexp, mant uint32
Expand All @@ -933,11 +931,11 @@ func (x *Float) Float32() (float32, Accuracy) {
return 0.0, Below
}
// bexp = 0
mant = high32(r.mant) >> (fbits - r.prec)
mant = msb32(r.mant) >> (fbits - r.prec)
} else {
// normal number: emin <= e <= emax
bexp = uint32(e+bias) << mbits
mant = high32(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
mant = msb32(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
}

return math.Float32frombits(sign | bexp | mant), r.acc
Expand Down Expand Up @@ -1019,6 +1017,7 @@ func (x *Float) Float64() (float64, Accuracy) {
}
return math.Inf(+1), Above
}
// e <= emax

// Determine sign, biased exponent, and mantissa.
var sign, bexp, mant uint64
Expand All @@ -1039,11 +1038,11 @@ func (x *Float) Float64() (float64, Accuracy) {
return 0.0, Below
}
// bexp = 0
mant = high64(r.mant) >> (fbits - r.prec)
mant = msb64(r.mant) >> (fbits - r.prec)
} else {
// normal number: emin <= e <= emax
bexp = uint64(e+bias) << mbits
mant = high64(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
mant = msb64(r.mant) >> ebits & (1<<mbits - 1) // cut off msb (implicit 1 bit)
}

return math.Float64frombits(sign | bexp | mant), r.acc
Expand Down
Loading

0 comments on commit 1e48683

Please sign in to comment.