Skip to content

Commit

Permalink
dec: refactor digits -> ntz
Browse files Browse the repository at this point in the history
  • Loading branch information
db47h committed May 4, 2020
1 parent 7a29e90 commit cb1bfec
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 19 deletions.
11 changes: 9 additions & 2 deletions dec.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,18 @@ func (z dec) norm() dec {
return z[0:i]
}

// TODO(db47h): change this to retun # of trailing zeroes.
// digits returns the number of digits of x.
func (x dec) digits() uint {
if i := len(x) - 1; i >= 0 {
return uint(i*_W) + decDigits(uint(x[i]))
}
return 0
}

func (x dec) ntz() uint {
for i, w := range x {
if w != 0 {
return uint(len(x)-i)*_WD - decTrailingZeros(uint(w))
return uint(i)*_WD + decTrailingZeros(uint(w))
}
}
return 0
Expand Down
13 changes: 7 additions & 6 deletions arith_dec.go → dec_arith.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ var maxDigits = [...]uint{
15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20,
}

// mag returns the magnitude of x such that 10**(mag-1) <= x < 10**mag.
// decDigits returns n such that of x such that 10**(n-1) <= x < 10**n.
// In other words, n the number of digits required to represent n.
// Returns 0 for x == 0.
func mag(x uint) uint {
d := maxDigits[bits.Len(x)]
if x < pow10(d-1) {
d--
func decDigits(x uint) (n uint) {
n = maxDigits[bits.Len(x)]
if x < pow10(n-1) {
n--
}
return d
return n
}

// shl10VU sets z to x*(10**s), s < _WD
Expand Down
13 changes: 6 additions & 7 deletions dec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,21 @@ import (
"time"
)

func Test_dec_digits(t *testing.T) {
func TestDec_ntz(t *testing.T) {
rand.Seed(time.Now().UnixNano())
for i := 0; i < 10000; i++ {
again:
w := uint(rand.Uint64()) % _BD
// ignore anything divisible by ten since mag(10) = 2 but dec{100000000...}.digits() = 1
// TODO: WTF? ignore anything divisible by ten since decDigits(10) = 2 but dec{100000000...}.digits() = 1
if w%10 == 0 {
goto again
}
e := uint(rand.Intn(_WD + 1))
h, l := bits.Mul(w, pow10(e))
h, l = bits.Div(h, l, _BD)
d := dec{Word(l), Word(h)}.norm()
dnorm(d)
if d.digits() != mag(w) {
t.Fatalf("dec{%d}.digits() = %d, expected %d", d[0], d.digits(), mag(w))
if d.ntz() != e {
t.Fatalf("dec{%v}.digits() = %d, expected %d", d, d.ntz(), e)
}
}
}
Expand All @@ -37,7 +36,7 @@ func Test_mag(t *testing.T) {
for m := n; m != 0; m /= 10 {
d++
}
if dd := mag(n); dd != d {
if dd := decDigits(n); dd != d {
t.Fatalf("mag(%d) = %d, expected %d", n, dd, d)
}
}
Expand Down Expand Up @@ -124,7 +123,7 @@ var (
func Benchmark_mag(b *testing.B) {
rand.Seed(0xdeadbeefbadf00d)
for i := 0; i < b.N; i++ {
benchU = mag(uint(rand.Uint64()) % _BD)
benchU = decDigits(uint(rand.Uint64()) % _BD)
}
}

Expand Down
4 changes: 2 additions & 2 deletions decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (x *Decimal) MinPrec() uint {
if x.form != finite {
return 0
}
return x.mant.digits()
return uint(len(x.mant))*_WD - x.mant.ntz()
}

// Mode returns the rounding mode of x.
Expand Down Expand Up @@ -446,7 +446,7 @@ func dnorm(m dec) int64 {
if debugDecimal && (len(m) == 0 || m[len(m)-1] == 0) {
panic("msw of mantissa is 0")
}
s := _WD - mag(uint(m[len(m)-1]))
s := _WD - decDigits(uint(m[len(m)-1]))
// partial shift
if s > 0 {
c := shl10VU(m, m, s)
Expand Down
4 changes: 2 additions & 2 deletions decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ func TestDnorm(t *testing.T) {
dd := dec{}.set(d)
s := dnorm(dd)
// d should now have a single element with e shifted left
ew := w * pow10(_WD-mag(w))
es := int64(uint(len(d)*_WD) - (mag(w) + e))
ew := w * pow10(_WD-decDigits(w))
es := int64(uint(len(d)*_WD) - (decDigits(w) + e))
if dd[len(dd)-1] != Word(ew) || s != es {
t.Fatalf("%ve%v => dnorm(%v) = %v, %v --- Expected %d, %d",
w, e, d, dd, s, w, es)
Expand Down

0 comments on commit cb1bfec

Please sign in to comment.