github.com/cznic/mathutil@v0.0.0-20181122101859-297441e03548/int_test.go (about)

     1  // Copyright (c) 2018 The mathutil 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 mathutil
     6  
     7  import (
     8  	"math/big"
     9  	"math/rand"
    10  	"testing"
    11  )
    12  
    13  const bits128 = 128
    14  
    15  var (
    16  	rnd    = rand.New(rand.NewSource(42))
    17  	off128 *big.Int
    18  	mod128 *big.Int
    19  )
    20  
    21  func init() {
    22  	mod128 = big.NewInt(0)
    23  	mod128.SetBit(mod128, bits128, 1)
    24  	off128 = big.NewInt(0)
    25  	off128.SetBit(off128, bits128-1, 1)
    26  }
    27  
    28  func rnd128() *big.Int {
    29  	var n big.Int
    30  	n.SetBit(&n, bits128, 1)
    31  	n.Rand(rnd, &n)
    32  	n.Sub(&n, off128)
    33  	return &n
    34  }
    35  
    36  func TestMaxInt128(t *testing.T) {
    37  	if g, e := MaxInt128.String(), "170141183460469231731687303715884105727"; g != e {
    38  		t.Fatal(g, e)
    39  	}
    40  }
    41  
    42  func TestMinInt128(t *testing.T) {
    43  	if g, e := MinInt128.String(), "-170141183460469231731687303715884105728"; g != e {
    44  		t.Fatal(g, e)
    45  	}
    46  }
    47  
    48  func testInt128Add(t *testing.T, a, b *big.Int) {
    49  	var x, y Int128
    50  	if _, err := x.SetBigInt(a); err != nil {
    51  		t.Fatal(a, err)
    52  	}
    53  
    54  	if _, err := y.SetBigInt(b); err != nil {
    55  		t.Fatal(b, err)
    56  	}
    57  
    58  	z, gc := x.Add(y)
    59  	g := z.BigInt()
    60  	e := big.NewInt(0)
    61  	e.Add(a, b)
    62  	ec := e.Cmp(MaxInt128) > 0 || e.Cmp(MinInt128) < 0
    63  	if gc != ec {
    64  		t.Fatal(a, b, g, e, gc, ec)
    65  	}
    66  
    67  	if gc {
    68  		switch {
    69  		case e.Cmp(MaxInt128) > 0:
    70  			g.Add(g, mod128)
    71  		case e.Cmp(MinInt128) < 0:
    72  			g.Sub(g, mod128)
    73  		default:
    74  			t.Fatal()
    75  		}
    76  	}
    77  
    78  	if g.Cmp(e) != 0 {
    79  		t.Fatal(a, b, g, e, gc, ec)
    80  	}
    81  }
    82  
    83  func TestInt128Add(t *testing.T) {
    84  	a := []string{
    85  		"0x0",
    86  		"0x1",
    87  		"0x3fffffffffffffff",
    88  		"0x7fffffffffffffff",
    89  		"0xffffffffffffffff",
    90  		"0x3fffffffffffffffffffffffffffffff",
    91  		"0x7fffffffffffffffffffffffffffffff",
    92  	}
    93  	for _, i := range []int{-1, 1} {
    94  		bi := big.NewInt(int64(i))
    95  		for _, j := range []int{-1, 1} {
    96  			bj := big.NewInt(int64(j))
    97  			for _, k := range a {
    98  				bk, ok := big.NewInt(0).SetString(k, 0)
    99  				if !ok {
   100  					t.Fatal()
   101  				}
   102  
   103  				for _, l := range a {
   104  					bl, ok := big.NewInt(0).SetString(l, 0)
   105  					if !ok {
   106  						t.Fatal()
   107  					}
   108  
   109  					testInt128Add(t, bk.Mul(bk, bi), bl.Mul(bl, bj))
   110  					continue
   111  				}
   112  			}
   113  		}
   114  	}
   115  }
   116  
   117  func TestInt128Add2(t *testing.T) {
   118  	const n = 500000
   119  	for i := 0; i < n; i++ {
   120  		testInt128Add(t, rnd128(), rnd128())
   121  	}
   122  }
   123  
   124  func TestInt128BigInt(t *testing.T) {
   125  	for _, v := range []int64{-128, -1, 0, 1, 127} {
   126  		a := big.NewInt(v)
   127  		var b Int128
   128  		if _, err := b.SetBigInt(a); err != nil {
   129  			t.Fatal(v)
   130  		}
   131  
   132  		c := b.BigInt()
   133  		if a.Cmp(c) != 0 {
   134  			t.Fatal(a, c)
   135  		}
   136  	}
   137  }
   138  
   139  func TestInt128BigInt2(t *testing.T) {
   140  	const n = 1000000
   141  	for i := 0; i < n; i++ {
   142  		a := rnd128()
   143  		var b Int128
   144  		if _, err := b.SetBigInt(a); err != nil {
   145  			t.Fatal(a)
   146  		}
   147  
   148  		c := b.BigInt()
   149  		if a.Cmp(c) != 0 {
   150  			t.Fatal(a, c)
   151  		}
   152  	}
   153  }
   154  
   155  func testInt128Cmp(t *testing.T, a, b *big.Int) {
   156  	var x, y Int128
   157  	if _, err := x.SetBigInt(a); err != nil {
   158  		t.Fatal(a, err)
   159  	}
   160  
   161  	if _, err := y.SetBigInt(b); err != nil {
   162  		t.Fatal(b, err)
   163  	}
   164  
   165  	if g, e := x.Cmp(y), a.Cmp(b); g != e {
   166  		t.Fatal(a, b, g, e)
   167  	}
   168  }
   169  
   170  func TestInt128Cmp(t *testing.T) {
   171  	a := []string{
   172  		"0x0",
   173  		"0x1",
   174  		"0x3fffffffffffffff",
   175  		"0x7fffffffffffffff",
   176  		"0xffffffffffffffff",
   177  		"0x3fffffffffffffffffffffffffffffff",
   178  		"0x7fffffffffffffffffffffffffffffff",
   179  	}
   180  	for _, i := range []int{-1, 1} {
   181  		bi := big.NewInt(int64(i))
   182  		for _, j := range []int{-1, 1} {
   183  			bj := big.NewInt(int64(j))
   184  			for _, k := range a {
   185  				bk, ok := big.NewInt(0).SetString(k, 0)
   186  				if !ok {
   187  					t.Fatal()
   188  				}
   189  
   190  				for _, l := range a {
   191  					bl, ok := big.NewInt(0).SetString(l, 0)
   192  					if !ok {
   193  						t.Fatal()
   194  					}
   195  
   196  					testInt128Cmp(t, bk.Mul(bk, bi), bl.Mul(bl, bj))
   197  				}
   198  			}
   199  		}
   200  	}
   201  }
   202  
   203  func TestInt128Cmp2(t *testing.T) {
   204  	const n = 1000000
   205  	for i := 0; i < n; i++ {
   206  		testInt128Cmp(t, rnd128(), rnd128())
   207  	}
   208  }
   209  
   210  func testInt128Neg(t *testing.T, a *big.Int) {
   211  	var x Int128
   212  	if _, err := x.SetBigInt(a); err != nil {
   213  		t.Fatal(a, err)
   214  	}
   215  
   216  	eok := a.Cmp(MinInt128) != 0
   217  	y, gok := x.Neg()
   218  	if g, e := gok, eok; g != e {
   219  		t.Fatal(a, x, y, gok, eok)
   220  	}
   221  
   222  	if gok {
   223  		a.Neg(a)
   224  	}
   225  	if g, e := y.BigInt(), a; g.Cmp(e) != 0 {
   226  		t.Fatal(g, e, gok, eok)
   227  	}
   228  }
   229  
   230  func TestInt128Neg(t *testing.T) {
   231  	a := []string{
   232  		"0x0",
   233  		"0x1",
   234  		"0x3fffffffffffffff",
   235  		"0x7fffffffffffffff",
   236  		"0xffffffffffffffff",
   237  		"0x3fffffffffffffffffffffffffffffff",
   238  		"0x7fffffffffffffffffffffffffffffff",
   239  	}
   240  	for _, i := range []int{-1, 1} {
   241  		bi := big.NewInt(int64(i))
   242  		for _, k := range a {
   243  			bk, ok := big.NewInt(0).SetString(k, 0)
   244  			if !ok {
   245  				t.Fatal()
   246  			}
   247  
   248  			testInt128Neg(t, bk.Mul(bk, bi))
   249  		}
   250  	}
   251  }
   252  
   253  func TestInt128Neg2(t *testing.T) {
   254  	const n = 1000000
   255  	for i := 0; i < n; i++ {
   256  		testInt128Neg(t, rnd128())
   257  	}
   258  }
   259  
   260  func TestInt128SetInt64(t *testing.T) {
   261  	const n = 1000000
   262  	for i := 0; i < n; i++ {
   263  		r := big.NewInt(0).SetInt64(rnd128().Int64())
   264  		var x Int128
   265  		y := x.SetInt64(r.Int64())
   266  		if x.Cmp(y) != 0 {
   267  			t.Fatal(r, x, y)
   268  		}
   269  
   270  		if g, e := x.BigInt(), r; g.Cmp(e) != 0 {
   271  			t.Fatal(r, x, g)
   272  		}
   273  	}
   274  }
   275  
   276  func TestInt128SetUint64(t *testing.T) {
   277  	const n = 1000000
   278  	for i := 0; i < n; i++ {
   279  		r := big.NewInt(0).SetUint64(rnd128().Uint64())
   280  		var x Int128
   281  		y := x.SetUint64(r.Uint64())
   282  		if x.Cmp(y) != 0 {
   283  			t.Fatal(r, x, y)
   284  		}
   285  
   286  		if g, e := x.BigInt(), r; g.Cmp(e) != 0 {
   287  			t.Fatal(r, x, g)
   288  		}
   289  	}
   290  }