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

     1  // Copyright (c) 2016 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  	"fmt"
     9  	"math/big"
    10  	"testing"
    11  )
    12  
    13  func TestNewFloat(t *testing.T) {
    14  	for i, v := range []struct {
    15  		n0, f0 int
    16  		n, f   int
    17  	}{
    18  		{1, 0, 1, 0},
    19  		{2, 0, 2, 0},
    20  		{2, 1, 1, 0},
    21  		{3, 0, 3, 0},
    22  		{3, 1, 3, 1},
    23  		{4, 0, 4, 0},
    24  		{4, 1, 2, 0},
    25  		{4, 2, 1, 0},
    26  	} {
    27  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 10)
    28  		if g, e := f.n.Int64(), int64(v.n); g != e {
    29  			t.Fatal(i, "n", g, e)
    30  		}
    31  
    32  		if g, e := f.fracBits, v.f; g != e {
    33  			t.Fatal(i, "fracBits", g, e)
    34  		}
    35  	}
    36  }
    37  
    38  func TestFloatDiv2(t *testing.T) {
    39  	for i, v := range []struct {
    40  		n0, f0 int
    41  		n, f   int
    42  	}{
    43  		{1, 0, 1, 1},
    44  		{2, 0, 1, 0},
    45  		{2, 1, 1, 1},
    46  		{3, 0, 3, 1},
    47  		{3, 1, 3, 2},
    48  		{4, 0, 2, 0},
    49  		{4, 1, 1, 0},
    50  		{4, 2, 1, 1},
    51  		{5, 0, 5, 1},
    52  		{5, 1, 5, 2},
    53  		{5, 2, 5, 3},
    54  		{6, 0, 3, 0},
    55  		{6, 1, 3, 1},
    56  		{6, 2, 3, 2},
    57  		{7, 0, 7, 1},
    58  		{7, 1, 7, 2},
    59  		{7, 2, 7, 3},
    60  		{8, 0, 4, 0},
    61  		{8, 1, 2, 0},
    62  		{8, 2, 1, 0},
    63  		{8, 3, 1, 1},
    64  	} {
    65  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 10)
    66  		f.div2()
    67  		if g, e := f.n.Int64(), int64(v.n); g != e {
    68  			t.Fatal(i, "n", g, e)
    69  		}
    70  
    71  		if g, e := f.fracBits, v.f; g != e {
    72  			t.Fatal(i, "fracBits", g, e)
    73  		}
    74  	}
    75  }
    76  
    77  func TestFloatSqr(t *testing.T) {
    78  	for i, v := range []struct {
    79  		n0, f0 int
    80  		n, f   int
    81  	}{
    82  		{1, 1, 1, 2},
    83  		{1, 0, 1, 0},
    84  		{2, 0, 4, 0},
    85  		{2, 1, 1, 0},
    86  		{3, 0, 9, 0},
    87  		{3, 1, 9, 2},
    88  		{4, 0, 16, 0},
    89  		{4, 1, 4, 0},
    90  		{4, 2, 1, 0},
    91  		{5, 0, 25, 0},
    92  		{5, 1, 25, 2},
    93  		{5, 2, 25, 4},
    94  		{6, 0, 36, 0},
    95  		{6, 1, 9, 0},
    96  		{6, 2, 9, 2},
    97  		{7, 0, 49, 0},
    98  		{7, 1, 49, 2},
    99  		{7, 2, 49, 4},
   100  		{8, 0, 64, 0},
   101  		{8, 1, 16, 0},
   102  		{8, 2, 4, 0},
   103  		{8, 3, 1, 0},
   104  		{9, 0, 81, 0},
   105  		{9, 1, 81, 2},
   106  	} {
   107  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 10)
   108  		f.sqr()
   109  		if g, e := f.n.Int64(), int64(v.n); g != e {
   110  			t.Fatal(i, "n", g, e)
   111  		}
   112  
   113  		if g, e := f.fracBits, v.f; g != e {
   114  			t.Fatal(i, "fracBits", g, e)
   115  		}
   116  	}
   117  }
   118  
   119  func TestFloatEq1(t *testing.T) {
   120  	for i, v := range []struct {
   121  		n0, f0 int
   122  		b      bool
   123  	}{
   124  		{1, 1, false},
   125  		{1, 0, true},
   126  		{2, 0, false},
   127  		{2, 1, true},
   128  		{3, 0, false},
   129  		{3, 1, false},
   130  		{4, 0, false},
   131  		{4, 1, false},
   132  		{4, 2, true},
   133  		{5, 0, false},
   134  		{5, 1, false},
   135  		{5, 2, false},
   136  	} {
   137  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 10)
   138  		if g, e := f.eq1(), v.b; g != e {
   139  			t.Fatal(i, g, e)
   140  		}
   141  	}
   142  }
   143  
   144  func TestFloatGe2(t *testing.T) {
   145  	for i, v := range []struct {
   146  		n0, f0 int
   147  		b      bool
   148  	}{
   149  		{1, 1, false},
   150  		{1, 0, false},
   151  		{2, 0, true},
   152  		{2, 1, false},
   153  		{3, 0, true},
   154  		{3, 1, false},
   155  		{4, 0, true},
   156  		{4, 1, true},
   157  		{4, 2, false},
   158  		{5, 0, true},
   159  		{5, 1, true},
   160  		{5, 2, false},
   161  	} {
   162  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 10)
   163  		if g, e := f.ge2(), v.b; g != e {
   164  			t.Fatal(i, g, e)
   165  		}
   166  	}
   167  }
   168  
   169  func TestFloatMaxFracBits(t *testing.T) {
   170  	for i, v := range []struct {
   171  		n0, f0 int
   172  		n, f   int
   173  	}{
   174  		{1, 0, 1, 0},
   175  		{2, 0, 4, 0},
   176  		{3, 0, 9, 0},
   177  	} {
   178  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 0)
   179  		f.sqr()
   180  		if g, e := f.n.Int64(), int64(v.n); g != e {
   181  			t.Fatal(i, "n", g, e)
   182  		}
   183  
   184  		if g, e := f.fracBits, v.f; g != e {
   185  			t.Fatal(i, "fracBits", g, e)
   186  		}
   187  	}
   188  	for i, v := range []struct {
   189  		n0, f0 int
   190  		n, f   int
   191  	}{
   192  		{1, 0, 1, 0},
   193  		{2, 0, 4, 0},
   194  		{2, 1, 1, 0},
   195  		{3, 0, 9, 0},
   196  		{3, 1, 5, 1},
   197  		{4, 0, 16, 0},
   198  		{4, 1, 4, 0},
   199  		{5, 0, 25, 0},
   200  		{5, 1, 13, 1},
   201  		{6, 0, 36, 0},
   202  		{6, 1, 9, 0},
   203  		{7, 0, 49, 0},
   204  		{7, 1, 25, 1},
   205  		{8, 0, 64, 0},
   206  		{8, 1, 16, 0},
   207  	} {
   208  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 1)
   209  		f.sqr()
   210  		if g, e := f.n.Int64(), int64(v.n); g != e {
   211  			t.Fatal(i, "n", g, e)
   212  		}
   213  
   214  		if g, e := f.fracBits, v.f; g != e {
   215  			t.Fatal(i, "fracBits", g, e)
   216  		}
   217  	}
   218  	for i, v := range []struct {
   219  		n0, f0 int
   220  		n, f   int
   221  	}{
   222  		{1, 0, 1, 0},
   223  		{2, 0, 4, 0},
   224  		{2, 1, 1, 0},
   225  		{3, 0, 9, 0},
   226  		{3, 1, 9, 2},
   227  		{4, 0, 16, 0},
   228  		{4, 1, 4, 0},
   229  		{4, 2, 1, 0},
   230  		{5, 0, 25, 0},
   231  		{5, 1, 25, 2},
   232  		{5, 2, 3, 1},
   233  		{6, 0, 36, 0},
   234  		{6, 1, 9, 0},
   235  		{6, 2, 9, 2},
   236  		{7, 0, 49, 0},
   237  		{7, 1, 49, 2},
   238  		{7, 2, 3, 0},
   239  		{8, 0, 64, 0},
   240  		{8, 1, 16, 0},
   241  		{8, 2, 4, 0},
   242  		{9, 0, 81, 0},
   243  		{9, 1, 81, 2},
   244  		{9, 2, 5, 0},
   245  	} {
   246  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 2)
   247  		f.sqr()
   248  		if g, e := f.n.Int64(), int64(v.n); g != e {
   249  			t.Fatal(i, "n", g, e)
   250  		}
   251  
   252  		if g, e := f.fracBits, v.f; g != e {
   253  			t.Fatal(i, "fracBits", g, e)
   254  		}
   255  	}
   256  	for i, v := range []struct {
   257  		n0, f0 int
   258  		n, f   int
   259  	}{
   260  		{1, 0, 1, 0},
   261  		{2, 0, 4, 0},
   262  		{2, 1, 1, 0},
   263  		{3, 0, 9, 0},
   264  		{3, 1, 9, 2},
   265  		{4, 0, 16, 0},
   266  		{4, 1, 4, 0},
   267  		{4, 2, 1, 0},
   268  		{5, 0, 25, 0},
   269  		{5, 1, 25, 2},
   270  		{5, 2, 13, 3},
   271  		{6, 0, 36, 0},
   272  		{6, 1, 9, 0},
   273  		{6, 2, 9, 2},
   274  		{7, 0, 49, 0},
   275  		{7, 1, 49, 2},
   276  		{7, 2, 25, 3},
   277  		{8, 0, 64, 0},
   278  		{8, 1, 16, 0},
   279  		{8, 2, 4, 0},
   280  		{8, 3, 1, 0},
   281  		{9, 0, 81, 0},
   282  		{9, 1, 81, 2},
   283  		{9, 2, 41, 3},
   284  		{9, 3, 5, 2},
   285  		{10, 0, 100, 0},
   286  		{10, 1, 25, 0},
   287  		{10, 2, 25, 2},
   288  		{10, 3, 13, 3},
   289  		{11, 0, 121, 0},
   290  		{11, 1, 121, 2},
   291  		{11, 2, 61, 3},
   292  		{11, 3, 15, 3},
   293  	} {
   294  		f := newFloat(big.NewInt(int64(v.n0)), v.f0, 3)
   295  		f.sqr()
   296  		if g, e := f.n.Int64(), int64(v.n); g != e {
   297  			t.Fatal(i, "n", g, e)
   298  		}
   299  
   300  		if g, e := f.fracBits, v.f; g != e {
   301  			t.Fatal(i, "fracBits", g, e)
   302  		}
   303  	}
   304  }
   305  
   306  func TestBinaryLog(t *testing.T) {
   307  	for i, v := range []struct {
   308  		n, b int
   309  		c    int
   310  		m    string
   311  	}{
   312  		{1, 0, 0, "0"},
   313  		{1, 1, 0, "0"},
   314  		{2, 0, 1, "0"},
   315  		{2, 1, 1, "0"},
   316  		{3, 0, 1, "0"},
   317  		{3, 1, 1, "1"},
   318  		{3, 2, 1, "10"},
   319  		{3, 3, 1, "100"},
   320  		{3, 4, 1, "1001"},
   321  		{3, 20, 1, "10010101110000000001"},
   322  		{42, 20, 5, "1100100011011101110"},
   323  		{700, 20, 9, "1110011100000101001"},
   324  	} {
   325  		c, m := BinaryLog(big.NewInt(int64(v.n)), v.b)
   326  		if g, e := c, v.c; g != e {
   327  			t.Fatalf("characteristic[%v]: %v %v", i, g, e)
   328  		}
   329  
   330  		if g, e := fmt.Sprintf("%b", m), v.m; g != e {
   331  			t.Fatalf("mantissa[%v]: %v %v", i, g, e)
   332  		}
   333  	}
   334  }
   335  
   336  func ExampleBinaryLog() {
   337  	const mantBits = 257
   338  	x, _ := big.NewInt(0).SetString("89940344608680314083397671686667731393131665861770496634981932531495305005604", 10)
   339  	c, m := BinaryLog(x, mantBits)
   340  	f := big.NewFloat(0).SetPrec(mantBits).SetInt(m)
   341  	f = f.SetMantExp(f, -mantBits)
   342  	f.Add(f, big.NewFloat(float64(c)))
   343  	f.Quo(f, big.NewFloat(4))
   344  	fmt.Printf("%.75f", f)
   345  	// Output:
   346  	// 63.908875905794799149011030723455843229394283193466612998787786375106246936971
   347  }