Skip to content

Commit

Permalink
Implement left-shifted mantissa
Browse files Browse the repository at this point in the history
  • Loading branch information
db47h committed May 3, 2020
1 parent 5c6a4c2 commit 8b88c09
Show file tree
Hide file tree
Showing 8 changed files with 609 additions and 104 deletions.
85 changes: 74 additions & 11 deletions arith_dec.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,80 @@ func shr10VU(z, x dec, s uint) (r Word) {
return r
}

// The resulting carry c is either 0 or 1.
func add10VW(z, x []Word, y Word) (c Word) {
c = y
for i := 0; i < len(z) && i < len(x); i++ {
zi, cc := bits.Add(uint(x[i]), uint(c), 0)
if zi >= _BD {
zi -= _BD
c = 1
func decTrailingZeros(n uint) uint {
if bits.UintSize == 32 {
return dec32TrailingZeros(n)
}
return dec64TrailingZeros(uint64(n))
}

func dec32TrailingZeros(n uint) uint {
var d uint
if n%100000000 == 0 {
n /= 100000000
d += 8
}
if n%10000 == 0 {
n /= 10000
d += 4
}
if n%100 == 0 {
n /= 100
d += 2
}
if n%10 == 0 {
d += 1
}
return d
}

func dec64TrailingZeros(n uint64) uint {
var d uint
if n%10000000000000000 == 0 {
n /= 10000000000000000
d += 16
}
if n%100000000 == 0 {
n /= 100000000
d += 8
}
if n%10000 == 0 {
n /= 10000
d += 4
}
if n%100 == 0 {
n /= 100
d += 2
}
if n%10 == 0 {
d += 1
}
return d
}

// addW adds y to x. The resulting carry c is either 0 or 1.
func add10VW(z, x dec, y Word) (c Word) {
s := x[0] + y
if (s < y) || s >= _BD {
z[0] = s - _BD
c = 1
} else {
z[0] = s
}
// propagate carry
for i := 1; i < len(z) && i < len(x); i++ {
s = x[i] + c
if s == _BD {
z[i] = 0
continue
}
// c = 0 from this point
z[i] = s
// copy remaining digits if not adding in-place
if !same(z, x) {
copy(z[i+1:], x[i+1:])
}
z[i] = Word(zi)
c = Word(cc)
return 0
}
return
return c
}
70 changes: 42 additions & 28 deletions dec.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package decimal

import (
"math/big"
"math/bits"
"sync"
)

Expand Down Expand Up @@ -42,7 +43,7 @@ func (z dec) norm() (dec, uint) {
}
z = z[:i]
if len(z) == 0 {
return z, ls
return z, 0
}
// partial shift
if s := _WD - mag(uint(z[len(z)-1])); s != 0 {
Expand Down Expand Up @@ -89,31 +90,24 @@ func (z dec) shr10(s uint) (d dec, r Word, tnz bool) {
return z, r, tnz || m != 0
}

func (x dec) digit(n uint) uint {
n, m := n/_WD, n%_WD
return (uint(x[n]) / pow10(m)) % 10
}

func (x dec) digits() uint {
// const H = 9
// const P = 1000000000
for i, w := range x {
if w != 0 {
// TODO(db47h): is there a way to optimize this?
var d uint
// if w%P == 0 {
// w /= P
// d += H
// }
for ; w%10 != 0; w /= 10 {
d++
}
return uint(len(x)-i)*_WD - d
return uint(len(x)-i)*_WD - decTrailingZeros(uint(w))
}
}
return 0
}

func (x dec) digit(i uint) uint {
j, i := bits.Div(0, i, _WD)
if j >= uint(len(x)) {
return 0
}
// 0 <= j < len(x)
return (uint(x[j]) / pow10(i)) % 10
}

func (z dec) set(x dec) dec {
z = z.make(len(x))
copy(z, x)
Expand All @@ -134,19 +128,39 @@ func (z dec) make(n int) dec {
return make(dec, n, n+e)
}

func (z dec) setInt(x *big.Int) dec {
// setInt sets z such that z*10**exp = x with 0 < z <= 1.
// Returns z and exp.
func (z dec) setInt(x *big.Int) (dec, uint) {
b := new(big.Int).Set(x).Bits()
n := len(b)
i := 0
for ; n > 0; i++ {
z[i] = Word(divWVW_g(b, 0, b, big.Word(_BD)))
n = len(b)
for n > 0 && b[n-1] == 0 {
n--
var i int
for i = 0; i < len(z) && len(b) > 0; i++ {
z[i] = Word(divWVW(b, 0, b, big.Word(_BD)))
}
z = z[:i]
z, s := z.norm()
return z, uint(i)*_WD - s
}

// sticky returns 1 if there's a non zero digit within the
// i least significant digits, otherwise it returns 0.
func (x dec) sticky(i uint) uint {
j, i := bits.Div(0, i, _WD)
if j >= uint(len(x)) {
if len(x) == 0 {
return 0
}
return 1
}
// 0 <= j < len(x)
for _, x := range x[:j] {
if x != 0 {
return 1
}
b = b[0:n]
}
return z[:i]
if uint(x[j])%pow10(i) != 0 {
return 1
}
return 0
}

// getDec returns a *dec of len n. The contents may not be zero.
Expand Down
7 changes: 7 additions & 0 deletions dec_conv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package decimal

import "io"

func (z dec) scan(r io.ByteScanner, base int, fracOk bool) (res dec, b, count int, err error) {
panic("not implemented")
}
Loading

0 comments on commit 8b88c09

Please sign in to comment.