package big
// implemented in arith_$GOARCH.s
+
+//go:noescape
func addVV(z, x, y []Word) (c Word)
+
+//go:noescape
func subVV(z, x, y []Word) (c Word)
+
+//go:noescape
func addVW(z, x []Word, y Word) (c Word)
+
+//go:noescape
func subVW(z, x []Word, y Word) (c Word)
+
+//go:noescape
func shlVU(z, x []Word, s uint) (c Word)
+
+//go:noescape
func shrVU(z, x []Word, s uint) (c Word)
+
+//go:noescape
func mulAddVWW(z, x []Word, y, r Word) (c Word)
+
+//go:noescape
func addMulVVW(z, x []Word, y Word) (c Word)
// NewInt allocates and returns a new Int set to x.
func NewInt(x int64) *Int {
- return new(Int).SetInt64(x)
+ // This code is arranged to be inlineable and produce
+ // zero allocations when inlined. See issue 29951.
+ u := uint64(x)
+ if x < 0 {
+ u = -u
+ }
+ var abs []Word
+ if x == 0 {
+ } else if _W == 32 && u>>32 != 0 {
+ abs = []Word{Word(u), Word(u >> 32)}
+ } else {
+ abs = []Word{Word(u)}
+ }
+ return &Int{neg: x < 0, abs: abs}
}
// Set sets z to x and returns z.
"bytes"
"encoding/hex"
"fmt"
+ "math"
"math/rand"
"strconv"
"strings"
t.Errorf("%s%v is not normalized", msg, z)
}
if (&z).Cmp(a.z) != 0 {
- t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, &z, a.z)
+ t.Errorf("%v %s %v\n\tgot z = %v; want %v", a.x, msg, a.y, &z, a.z)
}
}
})
}
}
+
+func TestNewIntMinInt64(t *testing.T) {
+ // Test for uint64 cast in NewInt.
+ want := int64(math.MinInt64)
+ if got := NewInt(want).Int64(); got != want {
+ t.Fatalf("wanted %d, got %d", want, got)
+ }
+}
+
+func TestNewIntAllocs(t *testing.T) {
+ for _, n := range []int64{0, 7, -7, 1 << 30, -1 << 30, 1 << 50, -1 << 50} {
+ x := NewInt(3)
+ got := testing.AllocsPerRun(100, func() {
+ // NewInt should inline, and all its allocations
+ // can happen on the stack. Passing the result of NewInt
+ // to Add should not cause any of those allocations to escape.
+ x.Add(x, NewInt(n))
+ })
+ if got != 0 {
+ t.Errorf("x.Add(x, NewInt(%d)), wanted 0 allocations, got %f", n, got)
+ }
+ }
+}