Skip to content

Commit

Permalink
allow Modf to not set arguments
Browse files Browse the repository at this point in the history
This closes the linked issue because it is now trivial to implement
trunc and not worth a whole function to do it that's just a wrapper of
modf.

Closes #24
  • Loading branch information
maddyblue committed Jul 1, 2017
1 parent a37c15a commit 5850e16
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 16 deletions.
60 changes: 44 additions & 16 deletions decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,37 +680,65 @@ func (d *Decimal) IsZero() bool {
}

// Modf sets integ to the integral part of d and frac to the fractional part
// such that d = integ+frac. If d is negative, both integ or frac will be
// either 0 or negative. integ.Exponent will be >= 0; frac.Exponent will be
// <= 0.
// such that d = integ+frac. If d is negative, both integ or frac will be either
// 0 or negative. integ.Exponent will be >= 0; frac.Exponent will be <= 0.
// Either argument can be nil, preventing it from being set.
func (d *Decimal) Modf(integ, frac *Decimal) {
if integ == nil && frac == nil {
return
}

neg := d.Negative

// No fractional part.
if d.Exponent > 0 {
frac.Negative = neg
frac.Exponent = 0
frac.Coeff.SetInt64(0)
integ.Set(d)
if frac != nil {
frac.Negative = neg
frac.Exponent = 0
frac.Coeff.SetInt64(0)
}
if integ != nil {
integ.Set(d)
}
return
}
nd := d.NumDigits()
exp := -int64(d.Exponent)
// d < 0 because exponent is larger than number of digits.
if exp > nd {
integ.Negative = neg
integ.Exponent = 0
integ.Coeff.SetInt64(0)
frac.Set(d)
if integ != nil {
integ.Negative = neg
integ.Exponent = 0
integ.Coeff.SetInt64(0)
}
if frac != nil {
frac.Set(d)
}
return
}

e := tableExp10(exp, nil)
integ.Coeff.QuoRem(&d.Coeff, e, &frac.Coeff)
integ.Exponent = 0
frac.Exponent = d.Exponent
frac.Negative = neg
integ.Negative = neg

var icoeff *big.Int
if integ != nil {
icoeff = &integ.Coeff
integ.Exponent = 0
integ.Negative = neg
} else {
// This is the integ == nil branch, and we already checked if both integ and
// frac were nil above, so frac can never be nil in this branch.
icoeff = new(big.Int)
}

if frac != nil {
icoeff.QuoRem(&d.Coeff, e, &frac.Coeff)
frac.Exponent = d.Exponent
frac.Negative = neg
} else {
// This is the frac == nil, which means integ must not be nil since they both
// can't be due to the check above.
icoeff.Quo(&d.Coeff, e)
}
}

// Neg sets d to -x and returns d.
Expand Down
14 changes: 14 additions & 0 deletions decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,22 @@ func TestModf(t *testing.T) {
if frac.Exponent > 0 {
t.Fatal(frac.Exponent)
}

integ2, frac2 := new(Decimal), new(Decimal)
x.Modf(integ2, nil)
x.Modf(nil, frac2)
if integ.CmpTotal(integ2) != 0 {
t.Fatalf("got %s, expected %s", integ2, integ)
}
if frac.CmpTotal(frac2) != 0 {
t.Fatalf("got %s, expected %s", frac2, frac)
}
})
}

// Ensure we don't panic on both nil.
a := new(Decimal)
a.Modf(nil, nil)
}

func TestInt64(t *testing.T) {
Expand Down

0 comments on commit 5850e16

Please sign in to comment.