mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
math/big: permit passing of an *Int to Float.Int to avoid allocation
Change-Id: I50e83248357928e56c94b88a8764de828f4f5c76 Reviewed-on: https://go-review.googlesource.com/5890 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
4100f7d95c
commit
88cbe09202
2 changed files with 28 additions and 11 deletions
|
|
@ -788,13 +788,14 @@ func (x *Float) Float64() (float64, Accuracy) {
|
||||||
// Int returns the result of truncating x towards zero; or nil
|
// Int returns the result of truncating x towards zero; or nil
|
||||||
// if x is an infinity. The result is Exact if x.IsInt();
|
// if x is an infinity. The result is Exact if x.IsInt();
|
||||||
// otherwise it is Below for x > 0, and Above for x < 0.
|
// otherwise it is Below for x > 0, and Above for x < 0.
|
||||||
func (x *Float) Int() (res *Int, acc Accuracy) {
|
// If a non-nil *Int argument z is provided, it is used to store
|
||||||
// TODO(gri) accept z argument for result storage (see Float.Rat below)
|
// the result; otherwise a new Int is allocated.
|
||||||
|
func (x *Float) Int(z *Int) (*Int, Accuracy) {
|
||||||
if debugFloat {
|
if debugFloat {
|
||||||
validate(x)
|
validate(x)
|
||||||
}
|
}
|
||||||
// accuracy for inexact results
|
// accuracy for inexact results
|
||||||
acc = Below // truncation
|
acc := Below // truncation
|
||||||
if x.neg {
|
if x.neg {
|
||||||
acc = Above
|
acc = Above
|
||||||
}
|
}
|
||||||
|
|
@ -807,7 +808,11 @@ func (x *Float) Int() (res *Int, acc Accuracy) {
|
||||||
if len(x.mant) == 0 {
|
if len(x.mant) == 0 {
|
||||||
acc = Exact // ±0
|
acc = Exact // ±0
|
||||||
}
|
}
|
||||||
return new(Int), acc // ±0.xxx
|
// ±0.xxx
|
||||||
|
if z == nil {
|
||||||
|
return new(Int), acc
|
||||||
|
}
|
||||||
|
return z.SetUint64(0), acc
|
||||||
}
|
}
|
||||||
// x.exp > 0
|
// x.exp > 0
|
||||||
// x.mant[len(x.mant)-1] != 0
|
// x.mant[len(x.mant)-1] != 0
|
||||||
|
|
@ -818,17 +823,20 @@ func (x *Float) Int() (res *Int, acc Accuracy) {
|
||||||
acc = Exact
|
acc = Exact
|
||||||
}
|
}
|
||||||
// shift mantissa as needed
|
// shift mantissa as needed
|
||||||
res = &Int{neg: x.neg}
|
if z == nil {
|
||||||
|
z = new(Int)
|
||||||
|
}
|
||||||
|
z.neg = x.neg
|
||||||
// TODO(gri) should have a shift that takes positive and negative shift counts
|
// TODO(gri) should have a shift that takes positive and negative shift counts
|
||||||
switch {
|
switch {
|
||||||
case exp > allBits:
|
case exp > allBits:
|
||||||
res.abs = res.abs.shl(x.mant, exp-allBits)
|
z.abs = z.abs.shl(x.mant, exp-allBits)
|
||||||
default:
|
default:
|
||||||
res.abs = res.abs.set(x.mant)
|
z.abs = z.abs.set(x.mant)
|
||||||
case exp < allBits:
|
case exp < allBits:
|
||||||
res.abs = res.abs.shr(x.mant, allBits-exp)
|
z.abs = z.abs.shr(x.mant, allBits-exp)
|
||||||
}
|
}
|
||||||
return
|
return z, acc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rat returns x converted into an exact fraction; or nil if x is an infinity.
|
// Rat returns x converted into an exact fraction; or nil if x is an infinity.
|
||||||
|
|
|
||||||
|
|
@ -714,7 +714,7 @@ func TestFloatInt(t *testing.T) {
|
||||||
{"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact},
|
{"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact},
|
||||||
} {
|
} {
|
||||||
x := makeFloat(test.x)
|
x := makeFloat(test.x)
|
||||||
res, acc := x.Int()
|
res, acc := x.Int(nil)
|
||||||
got := "nil"
|
got := "nil"
|
||||||
if res != nil {
|
if res != nil {
|
||||||
got = res.String()
|
got = res.String()
|
||||||
|
|
@ -723,6 +723,15 @@ func TestFloatInt(t *testing.T) {
|
||||||
t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc)
|
t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check that supplied *Int is used
|
||||||
|
for _, f := range []string{"0", "1", "-1", "1234"} {
|
||||||
|
x := makeFloat(f)
|
||||||
|
i := new(Int)
|
||||||
|
if res, _ := x.Int(i); res != i {
|
||||||
|
t.Errorf("(%s).Int is not using supplied *Int", f)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFloatRat(t *testing.T) {
|
func TestFloatRat(t *testing.T) {
|
||||||
|
|
@ -765,7 +774,7 @@ func TestFloatRat(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that supplied *Rat is used
|
// check that supplied *Rat is used
|
||||||
for _, f := range []string{"0", "1"} {
|
for _, f := range []string{"0", "1", "-1", "1234"} {
|
||||||
x := makeFloat(f)
|
x := makeFloat(f)
|
||||||
r := new(Rat)
|
r := new(Rat)
|
||||||
if res := x.Rat(r); res != r {
|
if res := x.Rat(r); res != r {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue