Home | History | Annotate | Download | only in big
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package big
      6 
      7 import (
      8 	"fmt"
      9 	"runtime"
     10 	"strings"
     11 	"testing"
     12 )
     13 
     14 var cmpTests = []struct {
     15 	x, y nat
     16 	r    int
     17 }{
     18 	{nil, nil, 0},
     19 	{nil, nat(nil), 0},
     20 	{nat(nil), nil, 0},
     21 	{nat(nil), nat(nil), 0},
     22 	{nat{0}, nat{0}, 0},
     23 	{nat{0}, nat{1}, -1},
     24 	{nat{1}, nat{0}, 1},
     25 	{nat{1}, nat{1}, 0},
     26 	{nat{0, _M}, nat{1}, 1},
     27 	{nat{1}, nat{0, _M}, -1},
     28 	{nat{1, _M}, nat{0, _M}, 1},
     29 	{nat{0, _M}, nat{1, _M}, -1},
     30 	{nat{16, 571956, 8794, 68}, nat{837, 9146, 1, 754489}, -1},
     31 	{nat{34986, 41, 105, 1957}, nat{56, 7458, 104, 1957}, 1},
     32 }
     33 
     34 func TestCmp(t *testing.T) {
     35 	for i, a := range cmpTests {
     36 		r := a.x.cmp(a.y)
     37 		if r != a.r {
     38 			t.Errorf("#%d got r = %v; want %v", i, r, a.r)
     39 		}
     40 	}
     41 }
     42 
     43 type funNN func(z, x, y nat) nat
     44 type argNN struct {
     45 	z, x, y nat
     46 }
     47 
     48 var sumNN = []argNN{
     49 	{},
     50 	{nat{1}, nil, nat{1}},
     51 	{nat{1111111110}, nat{123456789}, nat{987654321}},
     52 	{nat{0, 0, 0, 1}, nil, nat{0, 0, 0, 1}},
     53 	{nat{0, 0, 0, 1111111110}, nat{0, 0, 0, 123456789}, nat{0, 0, 0, 987654321}},
     54 	{nat{0, 0, 0, 1}, nat{0, 0, _M}, nat{0, 0, 1}},
     55 }
     56 
     57 var prodNN = []argNN{
     58 	{},
     59 	{nil, nil, nil},
     60 	{nil, nat{991}, nil},
     61 	{nat{991}, nat{991}, nat{1}},
     62 	{nat{991 * 991}, nat{991}, nat{991}},
     63 	{nat{0, 0, 991 * 991}, nat{0, 991}, nat{0, 991}},
     64 	{nat{1 * 991, 2 * 991, 3 * 991, 4 * 991}, nat{1, 2, 3, 4}, nat{991}},
     65 	{nat{4, 11, 20, 30, 20, 11, 4}, nat{1, 2, 3, 4}, nat{4, 3, 2, 1}},
     66 	// 3^100 * 3^28 = 3^128
     67 	{
     68 		natFromString("11790184577738583171520872861412518665678211592275841109096961"),
     69 		natFromString("515377520732011331036461129765621272702107522001"),
     70 		natFromString("22876792454961"),
     71 	},
     72 	// z = 111....1 (70000 digits)
     73 	// x = 10^(99*700) + ... + 10^1400 + 10^700 + 1
     74 	// y = 111....1 (700 digits, larger than Karatsuba threshold on 32-bit and 64-bit)
     75 	{
     76 		natFromString(strings.Repeat("1", 70000)),
     77 		natFromString("1" + strings.Repeat(strings.Repeat("0", 699)+"1", 99)),
     78 		natFromString(strings.Repeat("1", 700)),
     79 	},
     80 	// z = 111....1 (20000 digits)
     81 	// x = 10^10000 + 1
     82 	// y = 111....1 (10000 digits)
     83 	{
     84 		natFromString(strings.Repeat("1", 20000)),
     85 		natFromString("1" + strings.Repeat("0", 9999) + "1"),
     86 		natFromString(strings.Repeat("1", 10000)),
     87 	},
     88 }
     89 
     90 func natFromString(s string) nat {
     91 	x, _, _, err := nat(nil).scan(strings.NewReader(s), 0, false)
     92 	if err != nil {
     93 		panic(err)
     94 	}
     95 	return x
     96 }
     97 
     98 func TestSet(t *testing.T) {
     99 	for _, a := range sumNN {
    100 		z := nat(nil).set(a.z)
    101 		if z.cmp(a.z) != 0 {
    102 			t.Errorf("got z = %v; want %v", z, a.z)
    103 		}
    104 	}
    105 }
    106 
    107 func testFunNN(t *testing.T, msg string, f funNN, a argNN) {
    108 	z := f(nil, a.x, a.y)
    109 	if z.cmp(a.z) != 0 {
    110 		t.Errorf("%s%+v\n\tgot z = %v; want %v", msg, a, z, a.z)
    111 	}
    112 }
    113 
    114 func TestFunNN(t *testing.T) {
    115 	for _, a := range sumNN {
    116 		arg := a
    117 		testFunNN(t, "add", nat.add, arg)
    118 
    119 		arg = argNN{a.z, a.y, a.x}
    120 		testFunNN(t, "add symmetric", nat.add, arg)
    121 
    122 		arg = argNN{a.x, a.z, a.y}
    123 		testFunNN(t, "sub", nat.sub, arg)
    124 
    125 		arg = argNN{a.y, a.z, a.x}
    126 		testFunNN(t, "sub symmetric", nat.sub, arg)
    127 	}
    128 
    129 	for _, a := range prodNN {
    130 		arg := a
    131 		testFunNN(t, "mul", nat.mul, arg)
    132 
    133 		arg = argNN{a.z, a.y, a.x}
    134 		testFunNN(t, "mul symmetric", nat.mul, arg)
    135 	}
    136 }
    137 
    138 var mulRangesN = []struct {
    139 	a, b uint64
    140 	prod string
    141 }{
    142 	{0, 0, "0"},
    143 	{1, 1, "1"},
    144 	{1, 2, "2"},
    145 	{1, 3, "6"},
    146 	{10, 10, "10"},
    147 	{0, 100, "0"},
    148 	{0, 1e9, "0"},
    149 	{1, 0, "1"},                    // empty range
    150 	{100, 1, "1"},                  // empty range
    151 	{1, 10, "3628800"},             // 10!
    152 	{1, 20, "2432902008176640000"}, // 20!
    153 	{1, 100,
    154 		"933262154439441526816992388562667004907159682643816214685929" +
    155 			"638952175999932299156089414639761565182862536979208272237582" +
    156 			"51185210916864000000000000000000000000", // 100!
    157 	},
    158 }
    159 
    160 func TestMulRangeN(t *testing.T) {
    161 	for i, r := range mulRangesN {
    162 		prod := string(nat(nil).mulRange(r.a, r.b).utoa(10))
    163 		if prod != r.prod {
    164 			t.Errorf("#%d: got %s; want %s", i, prod, r.prod)
    165 		}
    166 	}
    167 }
    168 
    169 // allocBytes returns the number of bytes allocated by invoking f.
    170 func allocBytes(f func()) uint64 {
    171 	var stats runtime.MemStats
    172 	runtime.ReadMemStats(&stats)
    173 	t := stats.TotalAlloc
    174 	f()
    175 	runtime.ReadMemStats(&stats)
    176 	return stats.TotalAlloc - t
    177 }
    178 
    179 // TestMulUnbalanced tests that multiplying numbers of different lengths
    180 // does not cause deep recursion and in turn allocate too much memory.
    181 // Test case for issue 3807.
    182 func TestMulUnbalanced(t *testing.T) {
    183 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
    184 	x := rndNat(50000)
    185 	y := rndNat(40)
    186 	allocSize := allocBytes(func() {
    187 		nat(nil).mul(x, y)
    188 	})
    189 	inputSize := uint64(len(x)+len(y)) * _S
    190 	if ratio := allocSize / uint64(inputSize); ratio > 10 {
    191 		t.Errorf("multiplication uses too much memory (%d > %d times the size of inputs)", allocSize, ratio)
    192 	}
    193 }
    194 
    195 func rndNat(n int) nat {
    196 	return nat(rndV(n)).norm()
    197 }
    198 
    199 func BenchmarkMul(b *testing.B) {
    200 	mulx := rndNat(1e4)
    201 	muly := rndNat(1e4)
    202 	b.ResetTimer()
    203 	for i := 0; i < b.N; i++ {
    204 		var z nat
    205 		z.mul(mulx, muly)
    206 	}
    207 }
    208 
    209 func TestNLZ(t *testing.T) {
    210 	var x Word = _B >> 1
    211 	for i := 0; i <= _W; i++ {
    212 		if int(nlz(x)) != i {
    213 			t.Errorf("failed at %x: got %d want %d", x, nlz(x), i)
    214 		}
    215 		x >>= 1
    216 	}
    217 }
    218 
    219 type shiftTest struct {
    220 	in    nat
    221 	shift uint
    222 	out   nat
    223 }
    224 
    225 var leftShiftTests = []shiftTest{
    226 	{nil, 0, nil},
    227 	{nil, 1, nil},
    228 	{natOne, 0, natOne},
    229 	{natOne, 1, natTwo},
    230 	{nat{1 << (_W - 1)}, 1, nat{0}},
    231 	{nat{1 << (_W - 1), 0}, 1, nat{0, 1}},
    232 }
    233 
    234 func TestShiftLeft(t *testing.T) {
    235 	for i, test := range leftShiftTests {
    236 		var z nat
    237 		z = z.shl(test.in, test.shift)
    238 		for j, d := range test.out {
    239 			if j >= len(z) || z[j] != d {
    240 				t.Errorf("#%d: got: %v want: %v", i, z, test.out)
    241 				break
    242 			}
    243 		}
    244 	}
    245 }
    246 
    247 var rightShiftTests = []shiftTest{
    248 	{nil, 0, nil},
    249 	{nil, 1, nil},
    250 	{natOne, 0, natOne},
    251 	{natOne, 1, nil},
    252 	{natTwo, 1, natOne},
    253 	{nat{0, 1}, 1, nat{1 << (_W - 1)}},
    254 	{nat{2, 1, 1}, 1, nat{1<<(_W-1) + 1, 1 << (_W - 1)}},
    255 }
    256 
    257 func TestShiftRight(t *testing.T) {
    258 	for i, test := range rightShiftTests {
    259 		var z nat
    260 		z = z.shr(test.in, test.shift)
    261 		for j, d := range test.out {
    262 			if j >= len(z) || z[j] != d {
    263 				t.Errorf("#%d: got: %v want: %v", i, z, test.out)
    264 				break
    265 			}
    266 		}
    267 	}
    268 }
    269 
    270 type modWTest struct {
    271 	in       string
    272 	dividend string
    273 	out      string
    274 }
    275 
    276 var modWTests32 = []modWTest{
    277 	{"23492635982634928349238759823742", "252341", "220170"},
    278 }
    279 
    280 var modWTests64 = []modWTest{
    281 	{"6527895462947293856291561095690465243862946", "524326975699234", "375066989628668"},
    282 }
    283 
    284 func runModWTests(t *testing.T, tests []modWTest) {
    285 	for i, test := range tests {
    286 		in, _ := new(Int).SetString(test.in, 10)
    287 		d, _ := new(Int).SetString(test.dividend, 10)
    288 		out, _ := new(Int).SetString(test.out, 10)
    289 
    290 		r := in.abs.modW(d.abs[0])
    291 		if r != out.abs[0] {
    292 			t.Errorf("#%d failed: got %d want %s", i, r, out)
    293 		}
    294 	}
    295 }
    296 
    297 func TestModW(t *testing.T) {
    298 	if _W >= 32 {
    299 		runModWTests(t, modWTests32)
    300 	}
    301 	if _W >= 64 {
    302 		runModWTests(t, modWTests64)
    303 	}
    304 }
    305 
    306 func TestTrailingZeroBits(t *testing.T) {
    307 	// test 0 case explicitly
    308 	if n := trailingZeroBits(0); n != 0 {
    309 		t.Errorf("got trailingZeroBits(0) = %d; want 0", n)
    310 	}
    311 
    312 	x := Word(1)
    313 	for i := uint(0); i < _W; i++ {
    314 		n := trailingZeroBits(x)
    315 		if n != i {
    316 			t.Errorf("got trailingZeroBits(%#x) = %d; want %d", x, n, i%_W)
    317 		}
    318 		x <<= 1
    319 	}
    320 
    321 	// test 0 case explicitly
    322 	if n := nat(nil).trailingZeroBits(); n != 0 {
    323 		t.Errorf("got nat(nil).trailingZeroBits() = %d; want 0", n)
    324 	}
    325 
    326 	y := nat(nil).set(natOne)
    327 	for i := uint(0); i <= 3*_W; i++ {
    328 		n := y.trailingZeroBits()
    329 		if n != i {
    330 			t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.utoa(16), n, i)
    331 		}
    332 		y = y.shl(y, 1)
    333 	}
    334 }
    335 
    336 var montgomeryTests = []struct {
    337 	x, y, m      string
    338 	k0           uint64
    339 	out32, out64 string
    340 }{
    341 	{
    342 		"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
    343 		"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
    344 		"0xfffffffffffffffffffffffffffffffffffffffffffffffff",
    345 		1,
    346 		"0x1000000000000000000000000000000000000000000",
    347 		"0x10000000000000000000000000000000000",
    348 	},
    349 	{
    350 		"0x000000000ffffff5",
    351 		"0x000000000ffffff0",
    352 		"0x0000000010000001",
    353 		0xff0000000fffffff,
    354 		"0x000000000bfffff4",
    355 		"0x0000000003400001",
    356 	},
    357 	{
    358 		"0x0000000080000000",
    359 		"0x00000000ffffffff",
    360 		"0x1000000000000001",
    361 		0xfffffffffffffff,
    362 		"0x0800000008000001",
    363 		"0x0800000008000001",
    364 	},
    365 	{
    366 		"0x0000000080000000",
    367 		"0x0000000080000000",
    368 		"0xffffffff00000001",
    369 		0xfffffffeffffffff,
    370 		"0xbfffffff40000001",
    371 		"0xbfffffff40000001",
    372 	},
    373 	{
    374 		"0x0000000080000000",
    375 		"0x0000000080000000",
    376 		"0x00ffffff00000001",
    377 		0xfffffeffffffff,
    378 		"0xbfffff40000001",
    379 		"0xbfffff40000001",
    380 	},
    381 	{
    382 		"0x0000000080000000",
    383 		"0x0000000080000000",
    384 		"0x0000ffff00000001",
    385 		0xfffeffffffff,
    386 		"0xbfff40000001",
    387 		"0xbfff40000001",
    388 	},
    389 	{
    390 		"0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
    391 		"0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
    392 		"0x33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
    393 		0xdecc8f1249812adf,
    394 		"0x04eb0e11d72329dc0915f86784820fc403275bf2f6620a20e0dd344c5cd0875e50deb5",
    395 		"0x0d7144739a7d8e11d72329dc0915f86784820fc403275bf2f61ed96f35dd34dbb3d6a0",
    396 	},
    397 	{
    398 		"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
    399 		"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
    400 		"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
    401 		0xdecc8f1249812adf,
    402 		"0x5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d7a11c7772cba02c22f9711078d51a3797eb18e691295293284d988e349fa6deba46b25a4ecd9f715",
    403 		"0x92fcad4b5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d799c32fe2f3cc5422f9711078d51a3797eb18e691295293284d8f5e69caf6decddfe1df6",
    404 	},
    405 }
    406 
    407 func TestMontgomery(t *testing.T) {
    408 	one := NewInt(1)
    409 	_B := new(Int).Lsh(one, _W)
    410 	for i, test := range montgomeryTests {
    411 		x := natFromString(test.x)
    412 		y := natFromString(test.y)
    413 		m := natFromString(test.m)
    414 		for len(x) < len(m) {
    415 			x = append(x, 0)
    416 		}
    417 		for len(y) < len(m) {
    418 			y = append(y, 0)
    419 		}
    420 
    421 		if x.cmp(m) > 0 {
    422 			_, r := nat(nil).div(nil, x, m)
    423 			t.Errorf("#%d: x > m (0x%s > 0x%s; use 0x%s)", i, x.utoa(16), m.utoa(16), r.utoa(16))
    424 		}
    425 		if y.cmp(m) > 0 {
    426 			_, r := nat(nil).div(nil, x, m)
    427 			t.Errorf("#%d: y > m (0x%s > 0x%s; use 0x%s)", i, y.utoa(16), m.utoa(16), r.utoa(16))
    428 		}
    429 
    430 		var out nat
    431 		if _W == 32 {
    432 			out = natFromString(test.out32)
    433 		} else {
    434 			out = natFromString(test.out64)
    435 		}
    436 
    437 		// t.Logf("#%d: len=%d\n", i, len(m))
    438 
    439 		// check output in table
    440 		xi := &Int{abs: x}
    441 		yi := &Int{abs: y}
    442 		mi := &Int{abs: m}
    443 		p := new(Int).Mod(new(Int).Mul(xi, new(Int).Mul(yi, new(Int).ModInverse(new(Int).Lsh(one, uint(len(m))*_W), mi))), mi)
    444 		if out.cmp(p.abs.norm()) != 0 {
    445 			t.Errorf("#%d: out in table=0x%s, computed=0x%s", i, out.utoa(16), p.abs.norm().utoa(16))
    446 		}
    447 
    448 		// check k0 in table
    449 		k := new(Int).Mod(&Int{abs: m}, _B)
    450 		k = new(Int).Sub(_B, k)
    451 		k = new(Int).Mod(k, _B)
    452 		k0 := Word(new(Int).ModInverse(k, _B).Uint64())
    453 		if k0 != Word(test.k0) {
    454 			t.Errorf("#%d: k0 in table=%#x, computed=%#x\n", i, test.k0, k0)
    455 		}
    456 
    457 		// check montgomery with correct k0 produces correct output
    458 		z := nat(nil).montgomery(x, y, m, k0, len(m))
    459 		z = z.norm()
    460 		if z.cmp(out) != 0 {
    461 			t.Errorf("#%d: got 0x%s want 0x%s", i, z.utoa(16), out.utoa(16))
    462 		}
    463 	}
    464 }
    465 
    466 var expNNTests = []struct {
    467 	x, y, m string
    468 	out     string
    469 }{
    470 	{"0", "0", "0", "1"},
    471 	{"0", "0", "1", "0"},
    472 	{"1", "1", "1", "0"},
    473 	{"2", "1", "1", "0"},
    474 	{"2", "2", "1", "0"},
    475 	{"10", "100000000000", "1", "0"},
    476 	{"0x8000000000000000", "2", "", "0x40000000000000000000000000000000"},
    477 	{"0x8000000000000000", "2", "6719", "4944"},
    478 	{"0x8000000000000000", "3", "6719", "5447"},
    479 	{"0x8000000000000000", "1000", "6719", "1603"},
    480 	{"0x8000000000000000", "1000000", "6719", "3199"},
    481 	{
    482 		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
    483 		"298472983472983471903246121093472394872319615612417471234712061",
    484 		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
    485 		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
    486 	},
    487 	{
    488 		"11521922904531591643048817447554701904414021819823889996244743037378330903763518501116638828335352811871131385129455853417360623007349090150042001944696604737499160174391019030572483602867266711107136838523916077674888297896995042968746762200926853379",
    489 		"426343618817810911523",
    490 		"444747819283133684179",
    491 		"42",
    492 	},
    493 }
    494 
    495 func TestExpNN(t *testing.T) {
    496 	for i, test := range expNNTests {
    497 		x := natFromString(test.x)
    498 		y := natFromString(test.y)
    499 		out := natFromString(test.out)
    500 
    501 		var m nat
    502 		if len(test.m) > 0 {
    503 			m = natFromString(test.m)
    504 		}
    505 
    506 		z := nat(nil).expNN(x, y, m)
    507 		if z.cmp(out) != 0 {
    508 			t.Errorf("#%d got %s want %s", i, z.utoa(10), out.utoa(10))
    509 		}
    510 	}
    511 }
    512 
    513 func BenchmarkExp3Power(b *testing.B) {
    514 	const x = 3
    515 	for _, y := range []Word{
    516 		0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000,
    517 	} {
    518 		b.Run(fmt.Sprintf("%#x", y), func(b *testing.B) {
    519 			var z nat
    520 			for i := 0; i < b.N; i++ {
    521 				z.expWW(x, y)
    522 			}
    523 		})
    524 	}
    525 }
    526 
    527 func fibo(n int) nat {
    528 	switch n {
    529 	case 0:
    530 		return nil
    531 	case 1:
    532 		return nat{1}
    533 	}
    534 	f0 := fibo(0)
    535 	f1 := fibo(1)
    536 	var f2 nat
    537 	for i := 1; i < n; i++ {
    538 		f2 = f2.add(f0, f1)
    539 		f0, f1, f2 = f1, f2, f0
    540 	}
    541 	return f1
    542 }
    543 
    544 var fiboNums = []string{
    545 	"0",
    546 	"55",
    547 	"6765",
    548 	"832040",
    549 	"102334155",
    550 	"12586269025",
    551 	"1548008755920",
    552 	"190392490709135",
    553 	"23416728348467685",
    554 	"2880067194370816120",
    555 	"354224848179261915075",
    556 }
    557 
    558 func TestFibo(t *testing.T) {
    559 	for i, want := range fiboNums {
    560 		n := i * 10
    561 		got := string(fibo(n).utoa(10))
    562 		if got != want {
    563 			t.Errorf("fibo(%d) failed: got %s want %s", n, got, want)
    564 		}
    565 	}
    566 }
    567 
    568 func BenchmarkFibo(b *testing.B) {
    569 	for i := 0; i < b.N; i++ {
    570 		fibo(1e0)
    571 		fibo(1e1)
    572 		fibo(1e2)
    573 		fibo(1e3)
    574 		fibo(1e4)
    575 		fibo(1e5)
    576 	}
    577 }
    578 
    579 var bitTests = []struct {
    580 	x    string
    581 	i    uint
    582 	want uint
    583 }{
    584 	{"0", 0, 0},
    585 	{"0", 1, 0},
    586 	{"0", 1000, 0},
    587 
    588 	{"0x1", 0, 1},
    589 	{"0x10", 0, 0},
    590 	{"0x10", 3, 0},
    591 	{"0x10", 4, 1},
    592 	{"0x10", 5, 0},
    593 
    594 	{"0x8000000000000000", 62, 0},
    595 	{"0x8000000000000000", 63, 1},
    596 	{"0x8000000000000000", 64, 0},
    597 
    598 	{"0x3" + strings.Repeat("0", 32), 127, 0},
    599 	{"0x3" + strings.Repeat("0", 32), 128, 1},
    600 	{"0x3" + strings.Repeat("0", 32), 129, 1},
    601 	{"0x3" + strings.Repeat("0", 32), 130, 0},
    602 }
    603 
    604 func TestBit(t *testing.T) {
    605 	for i, test := range bitTests {
    606 		x := natFromString(test.x)
    607 		if got := x.bit(test.i); got != test.want {
    608 			t.Errorf("#%d: %s.bit(%d) = %v; want %v", i, test.x, test.i, got, test.want)
    609 		}
    610 	}
    611 }
    612 
    613 var stickyTests = []struct {
    614 	x    string
    615 	i    uint
    616 	want uint
    617 }{
    618 	{"0", 0, 0},
    619 	{"0", 1, 0},
    620 	{"0", 1000, 0},
    621 
    622 	{"0x1", 0, 0},
    623 	{"0x1", 1, 1},
    624 
    625 	{"0x1350", 0, 0},
    626 	{"0x1350", 4, 0},
    627 	{"0x1350", 5, 1},
    628 
    629 	{"0x8000000000000000", 63, 0},
    630 	{"0x8000000000000000", 64, 1},
    631 
    632 	{"0x1" + strings.Repeat("0", 100), 400, 0},
    633 	{"0x1" + strings.Repeat("0", 100), 401, 1},
    634 }
    635 
    636 func TestSticky(t *testing.T) {
    637 	for i, test := range stickyTests {
    638 		x := natFromString(test.x)
    639 		if got := x.sticky(test.i); got != test.want {
    640 			t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i, got, test.want)
    641 		}
    642 		if test.want == 1 {
    643 			// all subsequent i's should also return 1
    644 			for d := uint(1); d <= 3; d++ {
    645 				if got := x.sticky(test.i + d); got != 1 {
    646 					t.Errorf("#%d: %s.sticky(%d) = %v; want %v", i, test.x, test.i+d, got, 1)
    647 				}
    648 			}
    649 		}
    650 	}
    651 }
    652