github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/math/big/float_test.go (about)

     1  // Copyright 2014 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  	"math"
    10  	"strconv"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  // Verify that ErrNaN implements the error interface.
    16  var _ error = ErrNaN{}
    17  
    18  func (x *Float) uint64() uint64 {
    19  	u, acc := x.Uint64()
    20  	if acc != Exact {
    21  		panic(fmt.Sprintf("%s is not a uint64", x.Format('g', 10)))
    22  	}
    23  	return u
    24  }
    25  
    26  func (x *Float) int64() int64 {
    27  	i, acc := x.Int64()
    28  	if acc != Exact {
    29  		panic(fmt.Sprintf("%s is not an int64", x.Format('g', 10)))
    30  	}
    31  	return i
    32  }
    33  
    34  func TestFloatZeroValue(t *testing.T) {
    35  	// zero (uninitialized) value is a ready-to-use 0.0
    36  	var x Float
    37  	if s := x.Format('f', 1); s != "0.0" {
    38  		t.Errorf("zero value = %s; want 0.0", s)
    39  	}
    40  
    41  	// zero value has precision 0
    42  	if prec := x.Prec(); prec != 0 {
    43  		t.Errorf("prec = %d; want 0", prec)
    44  	}
    45  
    46  	// zero value can be used in any and all positions of binary operations
    47  	make := func(x int) *Float {
    48  		var f Float
    49  		if x != 0 {
    50  			f.SetInt64(int64(x))
    51  		}
    52  		// x == 0 translates into the zero value
    53  		return &f
    54  	}
    55  	for _, test := range []struct {
    56  		z, x, y, want int
    57  		opname        rune
    58  		op            func(z, x, y *Float) *Float
    59  	}{
    60  		{0, 0, 0, 0, '+', (*Float).Add},
    61  		{0, 1, 2, 3, '+', (*Float).Add},
    62  		{1, 2, 0, 2, '+', (*Float).Add},
    63  		{2, 0, 1, 1, '+', (*Float).Add},
    64  
    65  		{0, 0, 0, 0, '-', (*Float).Sub},
    66  		{0, 1, 2, -1, '-', (*Float).Sub},
    67  		{1, 2, 0, 2, '-', (*Float).Sub},
    68  		{2, 0, 1, -1, '-', (*Float).Sub},
    69  
    70  		{0, 0, 0, 0, '*', (*Float).Mul},
    71  		{0, 1, 2, 2, '*', (*Float).Mul},
    72  		{1, 2, 0, 0, '*', (*Float).Mul},
    73  		{2, 0, 1, 0, '*', (*Float).Mul},
    74  
    75  		// {0, 0, 0, 0, '/', (*Float).Quo}, // panics
    76  		{0, 2, 1, 2, '/', (*Float).Quo},
    77  		{1, 2, 0, 0, '/', (*Float).Quo}, // = +Inf
    78  		{2, 0, 1, 0, '/', (*Float).Quo},
    79  	} {
    80  		z := make(test.z)
    81  		test.op(z, make(test.x), make(test.y))
    82  		got := 0
    83  		if !z.IsInf() {
    84  			got = int(z.int64())
    85  		}
    86  		if got != test.want {
    87  			t.Errorf("%d %c %d = %d; want %d", test.x, test.opname, test.y, got, test.want)
    88  		}
    89  	}
    90  
    91  	// TODO(gri) test how precision is set for zero value results
    92  }
    93  
    94  func makeFloat(s string) *Float {
    95  	var x Float
    96  
    97  	switch s {
    98  	case "0":
    99  		return &x
   100  	case "-0":
   101  		return x.Neg(&x)
   102  	case "Inf", "+Inf":
   103  		return x.SetInf(false)
   104  	case "-Inf":
   105  		return x.SetInf(true)
   106  	}
   107  
   108  	x.SetPrec(1000)
   109  	if _, ok := x.SetString(s); !ok {
   110  		panic(fmt.Sprintf("%q is not a valid float", s))
   111  	}
   112  	return &x
   113  }
   114  
   115  func TestFloatSetPrec(t *testing.T) {
   116  	for _, test := range []struct {
   117  		x    string
   118  		prec uint
   119  		want string
   120  		acc  Accuracy
   121  	}{
   122  		// prec 0
   123  		{"0", 0, "0", Exact},
   124  		{"-0", 0, "-0", Exact},
   125  		{"-Inf", 0, "-Inf", Exact},
   126  		{"+Inf", 0, "+Inf", Exact},
   127  		{"123", 0, "0", Below},
   128  		{"-123", 0, "-0", Above},
   129  
   130  		// prec at upper limit
   131  		{"0", MaxPrec, "0", Exact},
   132  		{"-0", MaxPrec, "-0", Exact},
   133  		{"-Inf", MaxPrec, "-Inf", Exact},
   134  		{"+Inf", MaxPrec, "+Inf", Exact},
   135  
   136  		// just a few regular cases - general rounding is tested elsewhere
   137  		{"1.5", 1, "2", Above},
   138  		{"-1.5", 1, "-2", Below},
   139  		{"123", 1e6, "123", Exact},
   140  		{"-123", 1e6, "-123", Exact},
   141  	} {
   142  		x := makeFloat(test.x).SetPrec(test.prec)
   143  		prec := test.prec
   144  		if prec > MaxPrec {
   145  			prec = MaxPrec
   146  		}
   147  		if got := x.Prec(); got != prec {
   148  			t.Errorf("%s.SetPrec(%d).Prec() == %d; want %d", test.x, test.prec, got, prec)
   149  		}
   150  		if got, acc := x.String(), x.Acc(); got != test.want || acc != test.acc {
   151  			t.Errorf("%s.SetPrec(%d) = %s (%s); want %s (%s)", test.x, test.prec, got, acc, test.want, test.acc)
   152  		}
   153  	}
   154  }
   155  
   156  func TestFloatMinPrec(t *testing.T) {
   157  	const max = 100
   158  	for _, test := range []struct {
   159  		x    string
   160  		want uint
   161  	}{
   162  		{"0", 0},
   163  		{"-0", 0},
   164  		{"+Inf", 0},
   165  		{"-Inf", 0},
   166  		{"1", 1},
   167  		{"2", 1},
   168  		{"3", 2},
   169  		{"0x8001", 16},
   170  		{"0x8001p-1000", 16},
   171  		{"0x8001p+1000", 16},
   172  		{"0.1", max},
   173  	} {
   174  		x := makeFloat(test.x).SetPrec(max)
   175  		if got := x.MinPrec(); got != test.want {
   176  			t.Errorf("%s.MinPrec() = %d; want %d", test.x, got, test.want)
   177  		}
   178  	}
   179  }
   180  
   181  func TestFloatSign(t *testing.T) {
   182  	for _, test := range []struct {
   183  		x string
   184  		s int
   185  	}{
   186  		{"-Inf", -1},
   187  		{"-1", -1},
   188  		{"-0", 0},
   189  		{"+0", 0},
   190  		{"+1", +1},
   191  		{"+Inf", +1},
   192  	} {
   193  		x := makeFloat(test.x)
   194  		s := x.Sign()
   195  		if s != test.s {
   196  			t.Errorf("%s.Sign() = %d; want %d", test.x, s, test.s)
   197  		}
   198  	}
   199  }
   200  
   201  // alike(x, y) is like x.Cmp(y) == 0 but also considers the sign of 0 (0 != -0).
   202  func alike(x, y *Float) bool {
   203  	return x.Cmp(y) == 0 && x.Signbit() == y.Signbit()
   204  }
   205  
   206  func TestFloatMantExp(t *testing.T) {
   207  	for _, test := range []struct {
   208  		x    string
   209  		mant string
   210  		exp  int
   211  	}{
   212  		{"0", "0", 0},
   213  		{"+0", "0", 0},
   214  		{"-0", "-0", 0},
   215  		{"Inf", "+Inf", 0},
   216  		{"+Inf", "+Inf", 0},
   217  		{"-Inf", "-Inf", 0},
   218  		{"1.5", "0.75", 1},
   219  		{"1.024e3", "0.5", 11},
   220  		{"-0.125", "-0.5", -2},
   221  	} {
   222  		x := makeFloat(test.x)
   223  		mant := makeFloat(test.mant)
   224  		m := new(Float)
   225  		e := x.MantExp(m)
   226  		if !alike(m, mant) || e != test.exp {
   227  			t.Errorf("%s.MantExp() = %s, %d; want %s, %d", test.x, m.Format('g', 10), e, test.mant, test.exp)
   228  		}
   229  	}
   230  }
   231  
   232  func TestFloatMantExpAliasing(t *testing.T) {
   233  	x := makeFloat("0.5p10")
   234  	if e := x.MantExp(x); e != 10 {
   235  		t.Fatalf("Float.MantExp aliasing error: got %d; want 10", e)
   236  	}
   237  	if want := makeFloat("0.5"); !alike(x, want) {
   238  		t.Fatalf("Float.MantExp aliasing error: got %s; want %s", x.Format('g', 10), want.Format('g', 10))
   239  	}
   240  }
   241  
   242  func TestFloatSetMantExp(t *testing.T) {
   243  	for _, test := range []struct {
   244  		frac string
   245  		exp  int
   246  		z    string
   247  	}{
   248  		{"0", 0, "0"},
   249  		{"+0", 0, "0"},
   250  		{"-0", 0, "-0"},
   251  		{"Inf", 1234, "+Inf"},
   252  		{"+Inf", -1234, "+Inf"},
   253  		{"-Inf", -1234, "-Inf"},
   254  		{"0", MinExp, "0"},
   255  		{"0.25", MinExp, "+0"},    // exponent underflow
   256  		{"-0.25", MinExp, "-0"},   // exponent underflow
   257  		{"1", MaxExp, "+Inf"},     // exponent overflow
   258  		{"2", MaxExp - 1, "+Inf"}, // exponent overflow
   259  		{"0.75", 1, "1.5"},
   260  		{"0.5", 11, "1024"},
   261  		{"-0.5", -2, "-0.125"},
   262  		{"32", 5, "1024"},
   263  		{"1024", -10, "1"},
   264  	} {
   265  		frac := makeFloat(test.frac)
   266  		want := makeFloat(test.z)
   267  		var z Float
   268  		z.SetMantExp(frac, test.exp)
   269  		if !alike(&z, want) {
   270  			t.Errorf("SetMantExp(%s, %d) = %s; want %s", test.frac, test.exp, z.Format('g', 10), test.z)
   271  		}
   272  		// test inverse property
   273  		mant := new(Float)
   274  		if z.SetMantExp(mant, want.MantExp(mant)).Cmp(want) != 0 {
   275  			t.Errorf("Inverse property not satisfied: got %s; want %s", z.Format('g', 10), test.z)
   276  		}
   277  	}
   278  }
   279  
   280  func TestFloatPredicates(t *testing.T) {
   281  	for _, test := range []struct {
   282  		x            string
   283  		sign         int
   284  		signbit, inf bool
   285  	}{
   286  		{x: "-Inf", sign: -1, signbit: true, inf: true},
   287  		{x: "-1", sign: -1, signbit: true},
   288  		{x: "-0", signbit: true},
   289  		{x: "0"},
   290  		{x: "1", sign: 1},
   291  		{x: "+Inf", sign: 1, inf: true},
   292  	} {
   293  		x := makeFloat(test.x)
   294  		if got := x.Signbit(); got != test.signbit {
   295  			t.Errorf("(%s).Signbit() = %v; want %v", test.x, got, test.signbit)
   296  		}
   297  		if got := x.Sign(); got != test.sign {
   298  			t.Errorf("(%s).Sign() = %d; want %d", test.x, got, test.sign)
   299  		}
   300  		if got := x.IsInf(); got != test.inf {
   301  			t.Errorf("(%s).IsInf() = %v; want %v", test.x, got, test.inf)
   302  		}
   303  	}
   304  }
   305  
   306  func TestFloatIsInt(t *testing.T) {
   307  	for _, test := range []string{
   308  		"0 int",
   309  		"-0 int",
   310  		"1 int",
   311  		"-1 int",
   312  		"0.5",
   313  		"1.23",
   314  		"1.23e1",
   315  		"1.23e2 int",
   316  		"0.000000001e+8",
   317  		"0.000000001e+9 int",
   318  		"1.2345e200 int",
   319  		"Inf",
   320  		"+Inf",
   321  		"-Inf",
   322  	} {
   323  		s := strings.TrimSuffix(test, " int")
   324  		want := s != test
   325  		if got := makeFloat(s).IsInt(); got != want {
   326  			t.Errorf("%s.IsInt() == %t", s, got)
   327  		}
   328  	}
   329  }
   330  
   331  func fromBinary(s string) int64 {
   332  	x, err := strconv.ParseInt(s, 2, 64)
   333  	if err != nil {
   334  		panic(err)
   335  	}
   336  	return x
   337  }
   338  
   339  func toBinary(x int64) string {
   340  	return strconv.FormatInt(x, 2)
   341  }
   342  
   343  func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) {
   344  	// verify test data
   345  	var ok bool
   346  	switch mode {
   347  	case ToNearestEven, ToNearestAway:
   348  		ok = true // nothing to do for now
   349  	case ToZero:
   350  		if x < 0 {
   351  			ok = r >= x
   352  		} else {
   353  			ok = r <= x
   354  		}
   355  	case AwayFromZero:
   356  		if x < 0 {
   357  			ok = r <= x
   358  		} else {
   359  			ok = r >= x
   360  		}
   361  	case ToNegativeInf:
   362  		ok = r <= x
   363  	case ToPositiveInf:
   364  		ok = r >= x
   365  	default:
   366  		panic("unreachable")
   367  	}
   368  	if !ok {
   369  		t.Fatalf("incorrect test data for prec = %d, %s: x = %s, r = %s", prec, mode, toBinary(x), toBinary(r))
   370  	}
   371  
   372  	// compute expected accuracy
   373  	a := Exact
   374  	switch {
   375  	case r < x:
   376  		a = Below
   377  	case r > x:
   378  		a = Above
   379  	}
   380  
   381  	// round
   382  	f := new(Float).SetMode(mode).SetInt64(x).SetPrec(prec)
   383  
   384  	// check result
   385  	r1 := f.int64()
   386  	p1 := f.Prec()
   387  	a1 := f.Acc()
   388  	if r1 != r || p1 != prec || a1 != a {
   389  		t.Errorf("round %s (%d bits, %s) incorrect: got %s (%d bits, %s); want %s (%d bits, %s)",
   390  			toBinary(x), prec, mode,
   391  			toBinary(r1), p1, a1,
   392  			toBinary(r), prec, a)
   393  		return
   394  	}
   395  
   396  	// g and f should be the same
   397  	// (rounding by SetPrec after SetInt64 using default precision
   398  	// should be the same as rounding by SetInt64 after setting the
   399  	// precision)
   400  	g := new(Float).SetMode(mode).SetPrec(prec).SetInt64(x)
   401  	if !alike(g, f) {
   402  		t.Errorf("round %s (%d bits, %s) not symmetric: got %s and %s; want %s",
   403  			toBinary(x), prec, mode,
   404  			toBinary(g.int64()),
   405  			toBinary(r1),
   406  			toBinary(r),
   407  		)
   408  		return
   409  	}
   410  
   411  	// h and f should be the same
   412  	// (repeated rounding should be idempotent)
   413  	h := new(Float).SetMode(mode).SetPrec(prec).Set(f)
   414  	if !alike(h, f) {
   415  		t.Errorf("round %s (%d bits, %s) not idempotent: got %s and %s; want %s",
   416  			toBinary(x), prec, mode,
   417  			toBinary(h.int64()),
   418  			toBinary(r1),
   419  			toBinary(r),
   420  		)
   421  		return
   422  	}
   423  }
   424  
   425  // TestFloatRound tests basic rounding.
   426  func TestFloatRound(t *testing.T) {
   427  	for _, test := range []struct {
   428  		prec                        uint
   429  		x, zero, neven, naway, away string // input, results rounded to prec bits
   430  	}{
   431  		{5, "1000", "1000", "1000", "1000", "1000"},
   432  		{5, "1001", "1001", "1001", "1001", "1001"},
   433  		{5, "1010", "1010", "1010", "1010", "1010"},
   434  		{5, "1011", "1011", "1011", "1011", "1011"},
   435  		{5, "1100", "1100", "1100", "1100", "1100"},
   436  		{5, "1101", "1101", "1101", "1101", "1101"},
   437  		{5, "1110", "1110", "1110", "1110", "1110"},
   438  		{5, "1111", "1111", "1111", "1111", "1111"},
   439  
   440  		{4, "1000", "1000", "1000", "1000", "1000"},
   441  		{4, "1001", "1001", "1001", "1001", "1001"},
   442  		{4, "1010", "1010", "1010", "1010", "1010"},
   443  		{4, "1011", "1011", "1011", "1011", "1011"},
   444  		{4, "1100", "1100", "1100", "1100", "1100"},
   445  		{4, "1101", "1101", "1101", "1101", "1101"},
   446  		{4, "1110", "1110", "1110", "1110", "1110"},
   447  		{4, "1111", "1111", "1111", "1111", "1111"},
   448  
   449  		{3, "1000", "1000", "1000", "1000", "1000"},
   450  		{3, "1001", "1000", "1000", "1010", "1010"},
   451  		{3, "1010", "1010", "1010", "1010", "1010"},
   452  		{3, "1011", "1010", "1100", "1100", "1100"},
   453  		{3, "1100", "1100", "1100", "1100", "1100"},
   454  		{3, "1101", "1100", "1100", "1110", "1110"},
   455  		{3, "1110", "1110", "1110", "1110", "1110"},
   456  		{3, "1111", "1110", "10000", "10000", "10000"},
   457  
   458  		{3, "1000001", "1000000", "1000000", "1000000", "1010000"},
   459  		{3, "1001001", "1000000", "1010000", "1010000", "1010000"},
   460  		{3, "1010001", "1010000", "1010000", "1010000", "1100000"},
   461  		{3, "1011001", "1010000", "1100000", "1100000", "1100000"},
   462  		{3, "1100001", "1100000", "1100000", "1100000", "1110000"},
   463  		{3, "1101001", "1100000", "1110000", "1110000", "1110000"},
   464  		{3, "1110001", "1110000", "1110000", "1110000", "10000000"},
   465  		{3, "1111001", "1110000", "10000000", "10000000", "10000000"},
   466  
   467  		{2, "1000", "1000", "1000", "1000", "1000"},
   468  		{2, "1001", "1000", "1000", "1000", "1100"},
   469  		{2, "1010", "1000", "1000", "1100", "1100"},
   470  		{2, "1011", "1000", "1100", "1100", "1100"},
   471  		{2, "1100", "1100", "1100", "1100", "1100"},
   472  		{2, "1101", "1100", "1100", "1100", "10000"},
   473  		{2, "1110", "1100", "10000", "10000", "10000"},
   474  		{2, "1111", "1100", "10000", "10000", "10000"},
   475  
   476  		{2, "1000001", "1000000", "1000000", "1000000", "1100000"},
   477  		{2, "1001001", "1000000", "1000000", "1000000", "1100000"},
   478  		{2, "1010001", "1000000", "1100000", "1100000", "1100000"},
   479  		{2, "1011001", "1000000", "1100000", "1100000", "1100000"},
   480  		{2, "1100001", "1100000", "1100000", "1100000", "10000000"},
   481  		{2, "1101001", "1100000", "1100000", "1100000", "10000000"},
   482  		{2, "1110001", "1100000", "10000000", "10000000", "10000000"},
   483  		{2, "1111001", "1100000", "10000000", "10000000", "10000000"},
   484  
   485  		{1, "1000", "1000", "1000", "1000", "1000"},
   486  		{1, "1001", "1000", "1000", "1000", "10000"},
   487  		{1, "1010", "1000", "1000", "1000", "10000"},
   488  		{1, "1011", "1000", "1000", "1000", "10000"},
   489  		{1, "1100", "1000", "10000", "10000", "10000"},
   490  		{1, "1101", "1000", "10000", "10000", "10000"},
   491  		{1, "1110", "1000", "10000", "10000", "10000"},
   492  		{1, "1111", "1000", "10000", "10000", "10000"},
   493  
   494  		{1, "1000001", "1000000", "1000000", "1000000", "10000000"},
   495  		{1, "1001001", "1000000", "1000000", "1000000", "10000000"},
   496  		{1, "1010001", "1000000", "1000000", "1000000", "10000000"},
   497  		{1, "1011001", "1000000", "1000000", "1000000", "10000000"},
   498  		{1, "1100001", "1000000", "10000000", "10000000", "10000000"},
   499  		{1, "1101001", "1000000", "10000000", "10000000", "10000000"},
   500  		{1, "1110001", "1000000", "10000000", "10000000", "10000000"},
   501  		{1, "1111001", "1000000", "10000000", "10000000", "10000000"},
   502  	} {
   503  		x := fromBinary(test.x)
   504  		z := fromBinary(test.zero)
   505  		e := fromBinary(test.neven)
   506  		n := fromBinary(test.naway)
   507  		a := fromBinary(test.away)
   508  		prec := test.prec
   509  
   510  		testFloatRound(t, x, z, prec, ToZero)
   511  		testFloatRound(t, x, e, prec, ToNearestEven)
   512  		testFloatRound(t, x, n, prec, ToNearestAway)
   513  		testFloatRound(t, x, a, prec, AwayFromZero)
   514  
   515  		testFloatRound(t, x, z, prec, ToNegativeInf)
   516  		testFloatRound(t, x, a, prec, ToPositiveInf)
   517  
   518  		testFloatRound(t, -x, -a, prec, ToNegativeInf)
   519  		testFloatRound(t, -x, -z, prec, ToPositiveInf)
   520  	}
   521  }
   522  
   523  // TestFloatRound24 tests that rounding a float64 to 24 bits
   524  // matches IEEE-754 rounding to nearest when converting a
   525  // float64 to a float32 (excluding denormal numbers).
   526  func TestFloatRound24(t *testing.T) {
   527  	const x0 = 1<<26 - 0x10 // 11...110000 (26 bits)
   528  	for d := 0; d <= 0x10; d++ {
   529  		x := float64(x0 + d)
   530  		f := new(Float).SetPrec(24).SetFloat64(x)
   531  		got, _ := f.Float32()
   532  		want := float32(x)
   533  		if got != want {
   534  			t.Errorf("Round(%g, 24) = %g; want %g", x, got, want)
   535  		}
   536  	}
   537  }
   538  
   539  func TestFloatSetUint64(t *testing.T) {
   540  	for _, want := range []uint64{
   541  		0,
   542  		1,
   543  		2,
   544  		10,
   545  		100,
   546  		1<<32 - 1,
   547  		1 << 32,
   548  		1<<64 - 1,
   549  	} {
   550  		var f Float
   551  		f.SetUint64(want)
   552  		if got := f.uint64(); got != want {
   553  			t.Errorf("got %#x (%s); want %#x", got, f.Format('p', 0), want)
   554  		}
   555  	}
   556  
   557  	// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
   558  	const x uint64 = 0x8765432187654321 // 64 bits needed
   559  	for prec := uint(1); prec <= 64; prec++ {
   560  		f := new(Float).SetPrec(prec).SetMode(ToZero).SetUint64(x)
   561  		got := f.uint64()
   562  		want := x &^ (1<<(64-prec) - 1) // cut off (round to zero) low 64-prec bits
   563  		if got != want {
   564  			t.Errorf("got %#x (%s); want %#x", got, f.Format('p', 0), want)
   565  		}
   566  	}
   567  }
   568  
   569  func TestFloatSetInt64(t *testing.T) {
   570  	for _, want := range []int64{
   571  		0,
   572  		1,
   573  		2,
   574  		10,
   575  		100,
   576  		1<<32 - 1,
   577  		1 << 32,
   578  		1<<63 - 1,
   579  	} {
   580  		for i := range [2]int{} {
   581  			if i&1 != 0 {
   582  				want = -want
   583  			}
   584  			var f Float
   585  			f.SetInt64(want)
   586  			if got := f.int64(); got != want {
   587  				t.Errorf("got %#x (%s); want %#x", got, f.Format('p', 0), want)
   588  			}
   589  		}
   590  	}
   591  
   592  	// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
   593  	const x int64 = 0x7654321076543210 // 63 bits needed
   594  	for prec := uint(1); prec <= 63; prec++ {
   595  		f := new(Float).SetPrec(prec).SetMode(ToZero).SetInt64(x)
   596  		got := f.int64()
   597  		want := x &^ (1<<(63-prec) - 1) // cut off (round to zero) low 63-prec bits
   598  		if got != want {
   599  			t.Errorf("got %#x (%s); want %#x", got, f.Format('p', 0), want)
   600  		}
   601  	}
   602  }
   603  
   604  func TestFloatSetFloat64(t *testing.T) {
   605  	for _, want := range []float64{
   606  		0,
   607  		1,
   608  		2,
   609  		12345,
   610  		1e10,
   611  		1e100,
   612  		3.14159265e10,
   613  		2.718281828e-123,
   614  		1.0 / 3,
   615  		math.MaxFloat32,
   616  		math.MaxFloat64,
   617  		math.SmallestNonzeroFloat32,
   618  		math.SmallestNonzeroFloat64,
   619  		math.Inf(-1),
   620  		math.Inf(0),
   621  		-math.Inf(1),
   622  	} {
   623  		for i := range [2]int{} {
   624  			if i&1 != 0 {
   625  				want = -want
   626  			}
   627  			var f Float
   628  			f.SetFloat64(want)
   629  			if got, acc := f.Float64(); got != want || acc != Exact {
   630  				t.Errorf("got %g (%s, %s); want %g (Exact)", got, f.Format('p', 0), acc, want)
   631  			}
   632  		}
   633  	}
   634  
   635  	// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
   636  	const x uint64 = 0x8765432143218 // 53 bits needed
   637  	for prec := uint(1); prec <= 52; prec++ {
   638  		f := new(Float).SetPrec(prec).SetMode(ToZero).SetFloat64(float64(x))
   639  		got, _ := f.Float64()
   640  		want := float64(x &^ (1<<(52-prec) - 1)) // cut off (round to zero) low 53-prec bits
   641  		if got != want {
   642  			t.Errorf("got %g (%s); want %g", got, f.Format('p', 0), want)
   643  		}
   644  	}
   645  
   646  	// test NaN
   647  	defer func() {
   648  		if p, ok := recover().(ErrNaN); !ok {
   649  			t.Errorf("got %v; want ErrNaN panic", p)
   650  		}
   651  	}()
   652  	var f Float
   653  	f.SetFloat64(math.NaN())
   654  	// should not reach here
   655  	t.Errorf("got %s; want ErrNaN panic", f.Format('p', 0))
   656  }
   657  
   658  func TestFloatSetInt(t *testing.T) {
   659  	for _, want := range []string{
   660  		"0",
   661  		"1",
   662  		"-1",
   663  		"1234567890",
   664  		"123456789012345678901234567890",
   665  		"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
   666  	} {
   667  		var x Int
   668  		_, ok := x.SetString(want, 0)
   669  		if !ok {
   670  			t.Errorf("invalid integer %s", want)
   671  			continue
   672  		}
   673  		n := x.BitLen()
   674  
   675  		var f Float
   676  		f.SetInt(&x)
   677  
   678  		// check precision
   679  		if n < 64 {
   680  			n = 64
   681  		}
   682  		if prec := f.Prec(); prec != uint(n) {
   683  			t.Errorf("got prec = %d; want %d", prec, n)
   684  		}
   685  
   686  		// check value
   687  		got := f.Format('g', 100)
   688  		if got != want {
   689  			t.Errorf("got %s (%s); want %s", got, f.Format('p', 0), want)
   690  		}
   691  	}
   692  
   693  	// TODO(gri) test basic rounding behavior
   694  }
   695  
   696  func TestFloatSetRat(t *testing.T) {
   697  	for _, want := range []string{
   698  		"0",
   699  		"1",
   700  		"-1",
   701  		"1234567890",
   702  		"123456789012345678901234567890",
   703  		"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
   704  		"1.2",
   705  		"3.14159265",
   706  		// TODO(gri) expand
   707  	} {
   708  		var x Rat
   709  		_, ok := x.SetString(want)
   710  		if !ok {
   711  			t.Errorf("invalid fraction %s", want)
   712  			continue
   713  		}
   714  		n := max(x.Num().BitLen(), x.Denom().BitLen())
   715  
   716  		var f1, f2 Float
   717  		f2.SetPrec(1000)
   718  		f1.SetRat(&x)
   719  		f2.SetRat(&x)
   720  
   721  		// check precision when set automatically
   722  		if n < 64 {
   723  			n = 64
   724  		}
   725  		if prec := f1.Prec(); prec != uint(n) {
   726  			t.Errorf("got prec = %d; want %d", prec, n)
   727  		}
   728  
   729  		got := f2.Format('g', 100)
   730  		if got != want {
   731  			t.Errorf("got %s (%s); want %s", got, f2.Format('p', 0), want)
   732  		}
   733  	}
   734  }
   735  
   736  func TestFloatSetInf(t *testing.T) {
   737  	var f Float
   738  	for _, test := range []struct {
   739  		signbit bool
   740  		prec    uint
   741  		want    string
   742  	}{
   743  		{false, 0, "+Inf"},
   744  		{true, 0, "-Inf"},
   745  		{false, 10, "+Inf"},
   746  		{true, 30, "-Inf"},
   747  	} {
   748  		x := f.SetPrec(test.prec).SetInf(test.signbit)
   749  		if got := x.String(); got != test.want || x.Prec() != test.prec {
   750  			t.Errorf("SetInf(%v) = %s (prec = %d); want %s (prec = %d)", test.signbit, got, x.Prec(), test.want, test.prec)
   751  		}
   752  	}
   753  }
   754  
   755  func TestFloatUint64(t *testing.T) {
   756  	for _, test := range []struct {
   757  		x   string
   758  		out uint64
   759  		acc Accuracy
   760  	}{
   761  		{"-Inf", 0, Above},
   762  		{"-1", 0, Above},
   763  		{"-1e-1000", 0, Above},
   764  		{"-0", 0, Exact},
   765  		{"0", 0, Exact},
   766  		{"1e-1000", 0, Below},
   767  		{"1", 1, Exact},
   768  		{"1.000000000000000000001", 1, Below},
   769  		{"12345.0", 12345, Exact},
   770  		{"12345.000000000000000000001", 12345, Below},
   771  		{"18446744073709551615", 18446744073709551615, Exact},
   772  		{"18446744073709551615.000000000000000000001", math.MaxUint64, Below},
   773  		{"18446744073709551616", math.MaxUint64, Below},
   774  		{"1e10000", math.MaxUint64, Below},
   775  		{"+Inf", math.MaxUint64, Below},
   776  	} {
   777  		x := makeFloat(test.x)
   778  		out, acc := x.Uint64()
   779  		if out != test.out || acc != test.acc {
   780  			t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc)
   781  		}
   782  	}
   783  }
   784  
   785  func TestFloatInt64(t *testing.T) {
   786  	for _, test := range []struct {
   787  		x   string
   788  		out int64
   789  		acc Accuracy
   790  	}{
   791  		{"-Inf", math.MinInt64, Above},
   792  		{"-1e10000", math.MinInt64, Above},
   793  		{"-9223372036854775809", math.MinInt64, Above},
   794  		{"-9223372036854775808.000000000000000000001", math.MinInt64, Above},
   795  		{"-9223372036854775808", -9223372036854775808, Exact},
   796  		{"-9223372036854775807.000000000000000000001", -9223372036854775807, Above},
   797  		{"-9223372036854775807", -9223372036854775807, Exact},
   798  		{"-12345.000000000000000000001", -12345, Above},
   799  		{"-12345.0", -12345, Exact},
   800  		{"-1.000000000000000000001", -1, Above},
   801  		{"-1.5", -1, Above},
   802  		{"-1", -1, Exact},
   803  		{"-1e-1000", 0, Above},
   804  		{"0", 0, Exact},
   805  		{"1e-1000", 0, Below},
   806  		{"1", 1, Exact},
   807  		{"1.000000000000000000001", 1, Below},
   808  		{"1.5", 1, Below},
   809  		{"12345.0", 12345, Exact},
   810  		{"12345.000000000000000000001", 12345, Below},
   811  		{"9223372036854775807", 9223372036854775807, Exact},
   812  		{"9223372036854775807.000000000000000000001", math.MaxInt64, Below},
   813  		{"9223372036854775808", math.MaxInt64, Below},
   814  		{"1e10000", math.MaxInt64, Below},
   815  		{"+Inf", math.MaxInt64, Below},
   816  	} {
   817  		x := makeFloat(test.x)
   818  		out, acc := x.Int64()
   819  		if out != test.out || acc != test.acc {
   820  			t.Errorf("%s: got %d (%s); want %d (%s)", test.x, out, acc, test.out, test.acc)
   821  		}
   822  	}
   823  }
   824  
   825  func TestFloatFloat32(t *testing.T) {
   826  	for _, test := range []struct {
   827  		x   string
   828  		out float32
   829  		acc Accuracy
   830  	}{
   831  		{"-Inf", float32(math.Inf(-1)), Exact},
   832  		{"-0x1.ffffff0p2147483646", float32(-math.Inf(+1)), Below}, // overflow in rounding
   833  		{"-1e10000", float32(math.Inf(-1)), Below},                 // overflow
   834  		{"-0x1p128", float32(math.Inf(-1)), Below},                 // overflow
   835  		{"-0x1.ffffff0p127", float32(-math.Inf(+1)), Below},        // overflow
   836  		{"-0x1.fffffe8p127", -math.MaxFloat32, Above},
   837  		{"-0x1.fffffe0p127", -math.MaxFloat32, Exact},
   838  		{"-12345.000000000000000000001", -12345, Above},
   839  		{"-12345.0", -12345, Exact},
   840  		{"-1.000000000000000000001", -1, Above},
   841  		{"-1", -1, Exact},
   842  		{"-0x0.000002p-126", -math.SmallestNonzeroFloat32, Exact},
   843  		{"-0x0.000002p-127", -0, Above}, // underflow
   844  		{"-1e-1000", -0, Above},         // underflow
   845  		{"0", 0, Exact},
   846  		{"1e-1000", 0, Below},         // underflow
   847  		{"0x0.000002p-127", 0, Below}, // underflow
   848  		{"0x0.000002p-126", math.SmallestNonzeroFloat32, Exact},
   849  		{"1", 1, Exact},
   850  		{"1.000000000000000000001", 1, Below},
   851  		{"12345.0", 12345, Exact},
   852  		{"12345.000000000000000000001", 12345, Below},
   853  		{"0x1.fffffe0p127", math.MaxFloat32, Exact},
   854  		{"0x1.fffffe8p127", math.MaxFloat32, Below},
   855  		{"0x1.ffffff0p127", float32(math.Inf(+1)), Above},        // overflow
   856  		{"0x1p128", float32(math.Inf(+1)), Above},                // overflow
   857  		{"1e10000", float32(math.Inf(+1)), Above},                // overflow
   858  		{"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding
   859  		{"+Inf", float32(math.Inf(+1)), Exact},
   860  	} {
   861  		// conversion should match strconv where syntax is agreeable
   862  		if f, err := strconv.ParseFloat(test.x, 32); err == nil && float32(f) != test.out {
   863  			t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out)
   864  		}
   865  
   866  		x := makeFloat(test.x)
   867  		out, acc := x.Float32()
   868  		if out != test.out || acc != test.acc {
   869  			t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), test.acc)
   870  		}
   871  
   872  		// test that x.SetFloat64(float64(f)).Float32() == f
   873  		var x2 Float
   874  		out2, acc2 := x2.SetFloat64(float64(out)).Float32()
   875  		if out2 != out || acc2 != Exact {
   876  			t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
   877  		}
   878  	}
   879  }
   880  
   881  func TestFloatFloat64(t *testing.T) {
   882  	const smallestNormalFloat64 = 2.2250738585072014e-308 // 1p-1022
   883  	for _, test := range []struct {
   884  		x   string
   885  		out float64
   886  		acc Accuracy
   887  	}{
   888  		{"-Inf", math.Inf(-1), Exact},
   889  		{"-0x1.fffffffffffff8p2147483646", -math.Inf(+1), Below}, // overflow in rounding
   890  		{"-1e10000", math.Inf(-1), Below},                        // overflow
   891  		{"-0x1p1024", math.Inf(-1), Below},                       // overflow
   892  		{"-0x1.fffffffffffff8p1023", -math.Inf(+1), Below},       // overflow
   893  		{"-0x1.fffffffffffff4p1023", -math.MaxFloat64, Above},
   894  		{"-0x1.fffffffffffff0p1023", -math.MaxFloat64, Exact},
   895  		{"-12345.000000000000000000001", -12345, Above},
   896  		{"-12345.0", -12345, Exact},
   897  		{"-1.000000000000000000001", -1, Above},
   898  		{"-1", -1, Exact},
   899  		{"-0x0.0000000000001p-1022", -math.SmallestNonzeroFloat64, Exact},
   900  		{"-0x0.0000000000001p-1023", -0, Above}, // underflow
   901  		{"-1e-1000", -0, Above},                 // underflow
   902  		{"0", 0, Exact},
   903  		{"1e-1000", 0, Below},                 // underflow
   904  		{"0x0.0000000000001p-1023", 0, Below}, // underflow
   905  		{"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact},
   906  		{"1", 1, Exact},
   907  		{"1.000000000000000000001", 1, Below},
   908  		{"12345.0", 12345, Exact},
   909  		{"12345.000000000000000000001", 12345, Below},
   910  		{"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact},
   911  		{"0x1.fffffffffffff4p1023", math.MaxFloat64, Below},
   912  		{"0x1.fffffffffffff8p1023", math.Inf(+1), Above},       // overflow
   913  		{"0x1p1024", math.Inf(+1), Above},                      // overflow
   914  		{"1e10000", math.Inf(+1), Above},                       // overflow
   915  		{"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding
   916  		{"+Inf", math.Inf(+1), Exact},
   917  
   918  		// selected denormalized values that were handled incorrectly in the past
   919  		{"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
   920  		{"4503599627370495p-1074", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact},
   921  
   922  		// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
   923  		{"2.2250738585072011e-308", 2.225073858507201e-308, Below},
   924  		// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
   925  		{"2.2250738585072012e-308", 2.2250738585072014e-308, Above},
   926  	} {
   927  		// conversion should match strconv where syntax is agreeable
   928  		if f, err := strconv.ParseFloat(test.x, 64); err == nil && f != test.out {
   929  			t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out)
   930  		}
   931  
   932  		x := makeFloat(test.x)
   933  		out, acc := x.Float64()
   934  		if out != test.out || acc != test.acc {
   935  			t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), test.acc)
   936  		}
   937  
   938  		// test that x.SetFloat64(f).Float64() == f
   939  		var x2 Float
   940  		out2, acc2 := x2.SetFloat64(out).Float64()
   941  		if out2 != out || acc2 != Exact {
   942  			t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
   943  		}
   944  	}
   945  }
   946  
   947  func TestFloatInt(t *testing.T) {
   948  	for _, test := range []struct {
   949  		x    string
   950  		want string
   951  		acc  Accuracy
   952  	}{
   953  		{"0", "0", Exact},
   954  		{"+0", "0", Exact},
   955  		{"-0", "0", Exact},
   956  		{"Inf", "nil", Below},
   957  		{"+Inf", "nil", Below},
   958  		{"-Inf", "nil", Above},
   959  		{"1", "1", Exact},
   960  		{"-1", "-1", Exact},
   961  		{"1.23", "1", Below},
   962  		{"-1.23", "-1", Above},
   963  		{"123e-2", "1", Below},
   964  		{"123e-3", "0", Below},
   965  		{"123e-4", "0", Below},
   966  		{"1e-1000", "0", Below},
   967  		{"-1e-1000", "0", Above},
   968  		{"1e+10", "10000000000", Exact},
   969  		{"1e+100", "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", Exact},
   970  	} {
   971  		x := makeFloat(test.x)
   972  		res, acc := x.Int(nil)
   973  		got := "nil"
   974  		if res != nil {
   975  			got = res.String()
   976  		}
   977  		if got != test.want || acc != test.acc {
   978  			t.Errorf("%s: got %s (%s); want %s (%s)", test.x, got, acc, test.want, test.acc)
   979  		}
   980  	}
   981  
   982  	// check that supplied *Int is used
   983  	for _, f := range []string{"0", "1", "-1", "1234"} {
   984  		x := makeFloat(f)
   985  		i := new(Int)
   986  		if res, _ := x.Int(i); res != i {
   987  			t.Errorf("(%s).Int is not using supplied *Int", f)
   988  		}
   989  	}
   990  }
   991  
   992  func TestFloatRat(t *testing.T) {
   993  	for _, test := range []struct {
   994  		x, want string
   995  		acc     Accuracy
   996  	}{
   997  		{"0", "0/1", Exact},
   998  		{"+0", "0/1", Exact},
   999  		{"-0", "0/1", Exact},
  1000  		{"Inf", "nil", Below},
  1001  		{"+Inf", "nil", Below},
  1002  		{"-Inf", "nil", Above},
  1003  		{"1", "1/1", Exact},
  1004  		{"-1", "-1/1", Exact},
  1005  		{"1.25", "5/4", Exact},
  1006  		{"-1.25", "-5/4", Exact},
  1007  		{"1e10", "10000000000/1", Exact},
  1008  		{"1p10", "1024/1", Exact},
  1009  		{"-1p-10", "-1/1024", Exact},
  1010  		{"3.14159265", "7244019449799623199/2305843009213693952", Exact},
  1011  	} {
  1012  		x := makeFloat(test.x).SetPrec(64)
  1013  		res, acc := x.Rat(nil)
  1014  		got := "nil"
  1015  		if res != nil {
  1016  			got = res.String()
  1017  		}
  1018  		if got != test.want {
  1019  			t.Errorf("%s: got %s; want %s", test.x, got, test.want)
  1020  			continue
  1021  		}
  1022  		if acc != test.acc {
  1023  			t.Errorf("%s: got %s; want %s", test.x, acc, test.acc)
  1024  			continue
  1025  		}
  1026  
  1027  		// inverse conversion
  1028  		if res != nil {
  1029  			got := new(Float).SetPrec(64).SetRat(res)
  1030  			if got.Cmp(x) != 0 {
  1031  				t.Errorf("%s: got %s; want %s", test.x, got, x)
  1032  			}
  1033  		}
  1034  	}
  1035  
  1036  	// check that supplied *Rat is used
  1037  	for _, f := range []string{"0", "1", "-1", "1234"} {
  1038  		x := makeFloat(f)
  1039  		r := new(Rat)
  1040  		if res, _ := x.Rat(r); res != r {
  1041  			t.Errorf("(%s).Rat is not using supplied *Rat", f)
  1042  		}
  1043  	}
  1044  }
  1045  
  1046  func TestFloatAbs(t *testing.T) {
  1047  	for _, test := range []string{
  1048  		"0",
  1049  		"1",
  1050  		"1234",
  1051  		"1.23e-2",
  1052  		"1e-1000",
  1053  		"1e1000",
  1054  		"Inf",
  1055  	} {
  1056  		p := makeFloat(test)
  1057  		a := new(Float).Abs(p)
  1058  		if !alike(a, p) {
  1059  			t.Errorf("%s: got %s; want %s", test, a.Format('g', 10), test)
  1060  		}
  1061  
  1062  		n := makeFloat("-" + test)
  1063  		a.Abs(n)
  1064  		if !alike(a, p) {
  1065  			t.Errorf("-%s: got %s; want %s", test, a.Format('g', 10), test)
  1066  		}
  1067  	}
  1068  }
  1069  
  1070  func TestFloatNeg(t *testing.T) {
  1071  	for _, test := range []string{
  1072  		"0",
  1073  		"1",
  1074  		"1234",
  1075  		"1.23e-2",
  1076  		"1e-1000",
  1077  		"1e1000",
  1078  		"Inf",
  1079  	} {
  1080  		p1 := makeFloat(test)
  1081  		n1 := makeFloat("-" + test)
  1082  		n2 := new(Float).Neg(p1)
  1083  		p2 := new(Float).Neg(n2)
  1084  		if !alike(n2, n1) {
  1085  			t.Errorf("%s: got %s; want %s", test, n2.Format('g', 10), n1.Format('g', 10))
  1086  		}
  1087  		if !alike(p2, p1) {
  1088  			t.Errorf("%s: got %s; want %s", test, p2.Format('g', 10), p1.Format('g', 10))
  1089  		}
  1090  	}
  1091  }
  1092  
  1093  func TestFloatInc(t *testing.T) {
  1094  	const n = 10
  1095  	for _, prec := range precList {
  1096  		if 1<<prec < n {
  1097  			continue // prec must be large enough to hold all numbers from 0 to n
  1098  		}
  1099  		var x, one Float
  1100  		x.SetPrec(prec)
  1101  		one.SetInt64(1)
  1102  		for i := 0; i < n; i++ {
  1103  			x.Add(&x, &one)
  1104  		}
  1105  		if x.Cmp(new(Float).SetInt64(n)) != 0 {
  1106  			t.Errorf("prec = %d: got %s; want %d", prec, &x, n)
  1107  		}
  1108  	}
  1109  }
  1110  
  1111  // Selected precisions with which to run various tests.
  1112  var precList = [...]uint{1, 2, 5, 8, 10, 16, 23, 24, 32, 50, 53, 64, 100, 128, 500, 511, 512, 513, 1000, 10000}
  1113  
  1114  // Selected bits with which to run various tests.
  1115  // Each entry is a list of bits representing a floating-point number (see fromBits).
  1116  var bitsList = [...]Bits{
  1117  	{},           // = 0
  1118  	{0},          // = 1
  1119  	{1},          // = 2
  1120  	{-1},         // = 1/2
  1121  	{10},         // = 2**10 == 1024
  1122  	{-10},        // = 2**-10 == 1/1024
  1123  	{100, 10, 1}, // = 2**100 + 2**10 + 2**1
  1124  	{0, -1, -2, -10},
  1125  	// TODO(gri) add more test cases
  1126  }
  1127  
  1128  // TestFloatAdd tests Float.Add/Sub by comparing the result of a "manual"
  1129  // addition/subtraction of arguments represented by Bits values with the
  1130  // respective Float addition/subtraction for a variety of precisions
  1131  // and rounding modes.
  1132  func TestFloatAdd(t *testing.T) {
  1133  	for _, xbits := range bitsList {
  1134  		for _, ybits := range bitsList {
  1135  			// exact values
  1136  			x := xbits.Float()
  1137  			y := ybits.Float()
  1138  			zbits := xbits.add(ybits)
  1139  			z := zbits.Float()
  1140  
  1141  			for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
  1142  				for _, prec := range precList {
  1143  					got := new(Float).SetPrec(prec).SetMode(mode)
  1144  					got.Add(x, y)
  1145  					want := zbits.round(prec, mode)
  1146  					if got.Cmp(want) != 0 {
  1147  						t.Errorf("i = %d, prec = %d, %s:\n\t     %s %v\n\t+    %s %v\n\t=    %s\n\twant %s",
  1148  							i, prec, mode, x, xbits, y, ybits, got, want)
  1149  					}
  1150  
  1151  					got.Sub(z, x)
  1152  					want = ybits.round(prec, mode)
  1153  					if got.Cmp(want) != 0 {
  1154  						t.Errorf("i = %d, prec = %d, %s:\n\t     %s %v\n\t-    %s %v\n\t=    %s\n\twant %s",
  1155  							i, prec, mode, z, zbits, x, xbits, got, want)
  1156  					}
  1157  				}
  1158  			}
  1159  		}
  1160  	}
  1161  }
  1162  
  1163  // TestFloatAdd32 tests that Float.Add/Sub of numbers with
  1164  // 24bit mantissa behaves like float32 addition/subtraction
  1165  // (excluding denormal numbers).
  1166  func TestFloatAdd32(t *testing.T) {
  1167  	// chose base such that we cross the mantissa precision limit
  1168  	const base = 1<<26 - 0x10 // 11...110000 (26 bits)
  1169  	for d := 0; d <= 0x10; d++ {
  1170  		for i := range [2]int{} {
  1171  			x0, y0 := float64(base), float64(d)
  1172  			if i&1 != 0 {
  1173  				x0, y0 = y0, x0
  1174  			}
  1175  
  1176  			x := NewFloat(x0)
  1177  			y := NewFloat(y0)
  1178  			z := new(Float).SetPrec(24)
  1179  
  1180  			z.Add(x, y)
  1181  			got, acc := z.Float32()
  1182  			want := float32(y0) + float32(x0)
  1183  			if got != want || acc != Exact {
  1184  				t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want)
  1185  			}
  1186  
  1187  			z.Sub(z, y)
  1188  			got, acc = z.Float32()
  1189  			want = float32(want) - float32(y0)
  1190  			if got != want || acc != Exact {
  1191  				t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want)
  1192  			}
  1193  		}
  1194  	}
  1195  }
  1196  
  1197  // TestFloatAdd64 tests that Float.Add/Sub of numbers with
  1198  // 53bit mantissa behaves like float64 addition/subtraction.
  1199  func TestFloatAdd64(t *testing.T) {
  1200  	// chose base such that we cross the mantissa precision limit
  1201  	const base = 1<<55 - 0x10 // 11...110000 (55 bits)
  1202  	for d := 0; d <= 0x10; d++ {
  1203  		for i := range [2]int{} {
  1204  			x0, y0 := float64(base), float64(d)
  1205  			if i&1 != 0 {
  1206  				x0, y0 = y0, x0
  1207  			}
  1208  
  1209  			x := NewFloat(x0)
  1210  			y := NewFloat(y0)
  1211  			z := new(Float).SetPrec(53)
  1212  
  1213  			z.Add(x, y)
  1214  			got, acc := z.Float64()
  1215  			want := x0 + y0
  1216  			if got != want || acc != Exact {
  1217  				t.Errorf("d = %d: %g + %g = %g (%s); want %g (Exact)", d, x0, y0, got, acc, want)
  1218  			}
  1219  
  1220  			z.Sub(z, y)
  1221  			got, acc = z.Float64()
  1222  			want -= y0
  1223  			if got != want || acc != Exact {
  1224  				t.Errorf("d = %d: %g - %g = %g (%s); want %g (Exact)", d, x0+y0, y0, got, acc, want)
  1225  			}
  1226  		}
  1227  	}
  1228  }
  1229  
  1230  // TestFloatMul tests Float.Mul/Quo by comparing the result of a "manual"
  1231  // multiplication/division of arguments represented by Bits values with the
  1232  // respective Float multiplication/division for a variety of precisions
  1233  // and rounding modes.
  1234  func TestFloatMul(t *testing.T) {
  1235  	for _, xbits := range bitsList {
  1236  		for _, ybits := range bitsList {
  1237  			// exact values
  1238  			x := xbits.Float()
  1239  			y := ybits.Float()
  1240  			zbits := xbits.mul(ybits)
  1241  			z := zbits.Float()
  1242  
  1243  			for i, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
  1244  				for _, prec := range precList {
  1245  					got := new(Float).SetPrec(prec).SetMode(mode)
  1246  					got.Mul(x, y)
  1247  					want := zbits.round(prec, mode)
  1248  					if got.Cmp(want) != 0 {
  1249  						t.Errorf("i = %d, prec = %d, %s:\n\t     %s %v\n\t*    %s %v\n\t=    %s\n\twant %s",
  1250  							i, prec, mode, x, xbits, y, ybits, got, want)
  1251  					}
  1252  
  1253  					if x.Sign() == 0 {
  1254  						continue // ignore div-0 case (not invertable)
  1255  					}
  1256  					got.Quo(z, x)
  1257  					want = ybits.round(prec, mode)
  1258  					if got.Cmp(want) != 0 {
  1259  						t.Errorf("i = %d, prec = %d, %s:\n\t     %s %v\n\t/    %s %v\n\t=    %s\n\twant %s",
  1260  							i, prec, mode, z, zbits, x, xbits, got, want)
  1261  					}
  1262  				}
  1263  			}
  1264  		}
  1265  	}
  1266  }
  1267  
  1268  // TestFloatMul64 tests that Float.Mul/Quo of numbers with
  1269  // 53bit mantissa behaves like float64 multiplication/division.
  1270  func TestFloatMul64(t *testing.T) {
  1271  	for _, test := range []struct {
  1272  		x, y float64
  1273  	}{
  1274  		{0, 0},
  1275  		{0, 1},
  1276  		{1, 1},
  1277  		{1, 1.5},
  1278  		{1.234, 0.5678},
  1279  		{2.718281828, 3.14159265358979},
  1280  		{2.718281828e10, 3.14159265358979e-32},
  1281  		{1.0 / 3, 1e200},
  1282  	} {
  1283  		for i := range [8]int{} {
  1284  			x0, y0 := test.x, test.y
  1285  			if i&1 != 0 {
  1286  				x0 = -x0
  1287  			}
  1288  			if i&2 != 0 {
  1289  				y0 = -y0
  1290  			}
  1291  			if i&4 != 0 {
  1292  				x0, y0 = y0, x0
  1293  			}
  1294  
  1295  			x := NewFloat(x0)
  1296  			y := NewFloat(y0)
  1297  			z := new(Float).SetPrec(53)
  1298  
  1299  			z.Mul(x, y)
  1300  			got, _ := z.Float64()
  1301  			want := x0 * y0
  1302  			if got != want {
  1303  				t.Errorf("%g * %g = %g; want %g", x0, y0, got, want)
  1304  			}
  1305  
  1306  			if y0 == 0 {
  1307  				continue // avoid division-by-zero
  1308  			}
  1309  			z.Quo(z, y)
  1310  			got, _ = z.Float64()
  1311  			want /= y0
  1312  			if got != want {
  1313  				t.Errorf("%g / %g = %g; want %g", x0*y0, y0, got, want)
  1314  			}
  1315  		}
  1316  	}
  1317  }
  1318  
  1319  func TestIssue6866(t *testing.T) {
  1320  	for _, prec := range precList {
  1321  		two := new(Float).SetPrec(prec).SetInt64(2)
  1322  		one := new(Float).SetPrec(prec).SetInt64(1)
  1323  		three := new(Float).SetPrec(prec).SetInt64(3)
  1324  		msix := new(Float).SetPrec(prec).SetInt64(-6)
  1325  		psix := new(Float).SetPrec(prec).SetInt64(+6)
  1326  
  1327  		p := new(Float).SetPrec(prec)
  1328  		z1 := new(Float).SetPrec(prec)
  1329  		z2 := new(Float).SetPrec(prec)
  1330  
  1331  		// z1 = 2 + 1.0/3*-6
  1332  		p.Quo(one, three)
  1333  		p.Mul(p, msix)
  1334  		z1.Add(two, p)
  1335  
  1336  		// z2 = 2 - 1.0/3*+6
  1337  		p.Quo(one, three)
  1338  		p.Mul(p, psix)
  1339  		z2.Sub(two, p)
  1340  
  1341  		if z1.Cmp(z2) != 0 {
  1342  			t.Fatalf("prec %d: got z1 = %s != z2 = %s; want z1 == z2\n", prec, z1, z2)
  1343  		}
  1344  		if z1.Sign() != 0 {
  1345  			t.Errorf("prec %d: got z1 = %s; want 0", prec, z1)
  1346  		}
  1347  		if z2.Sign() != 0 {
  1348  			t.Errorf("prec %d: got z2 = %s; want 0", prec, z2)
  1349  		}
  1350  	}
  1351  }
  1352  
  1353  func TestFloatQuo(t *testing.T) {
  1354  	// TODO(gri) make the test vary these precisions
  1355  	preci := 200 // precision of integer part
  1356  	precf := 20  // precision of fractional part
  1357  
  1358  	for i := 0; i < 8; i++ {
  1359  		// compute accurate (not rounded) result z
  1360  		bits := Bits{preci - 1}
  1361  		if i&3 != 0 {
  1362  			bits = append(bits, 0)
  1363  		}
  1364  		if i&2 != 0 {
  1365  			bits = append(bits, -1)
  1366  		}
  1367  		if i&1 != 0 {
  1368  			bits = append(bits, -precf)
  1369  		}
  1370  		z := bits.Float()
  1371  
  1372  		// compute accurate x as z*y
  1373  		y := NewFloat(3.14159265358979323e123)
  1374  
  1375  		x := new(Float).SetPrec(z.Prec() + y.Prec()).SetMode(ToZero)
  1376  		x.Mul(z, y)
  1377  
  1378  		// leave for debugging
  1379  		// fmt.Printf("x = %s\ny = %s\nz = %s\n", x, y, z)
  1380  
  1381  		if got := x.Acc(); got != Exact {
  1382  			t.Errorf("got acc = %s; want exact", got)
  1383  		}
  1384  
  1385  		// round accurate z for a variety of precisions and
  1386  		// modes and compare against result of x / y.
  1387  		for _, mode := range [...]RoundingMode{ToZero, ToNearestEven, AwayFromZero} {
  1388  			for d := -5; d < 5; d++ {
  1389  				prec := uint(preci + d)
  1390  				got := new(Float).SetPrec(prec).SetMode(mode).Quo(x, y)
  1391  				want := bits.round(prec, mode)
  1392  				if got.Cmp(want) != 0 {
  1393  					t.Errorf("i = %d, prec = %d, %s:\n\t     %s\n\t/    %s\n\t=    %s\n\twant %s",
  1394  						i, prec, mode, x, y, got, want)
  1395  				}
  1396  			}
  1397  		}
  1398  	}
  1399  }
  1400  
  1401  // TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n];
  1402  // it serves as a smoke test for basic correctness of division.
  1403  func TestFloatQuoSmoke(t *testing.T) {
  1404  	n := 1000
  1405  	if testing.Short() {
  1406  		n = 10
  1407  	}
  1408  
  1409  	const dprec = 3         // max. precision variation
  1410  	const prec = 10 + dprec // enough bits to hold n precisely
  1411  	for x := -n; x <= n; x++ {
  1412  		for y := -n; y < n; y++ {
  1413  			if y == 0 {
  1414  				continue
  1415  			}
  1416  
  1417  			a := float64(x)
  1418  			b := float64(y)
  1419  			c := a / b
  1420  
  1421  			// vary operand precision (only ok as long as a, b can be represented correctly)
  1422  			for ad := -dprec; ad <= dprec; ad++ {
  1423  				for bd := -dprec; bd <= dprec; bd++ {
  1424  					A := new(Float).SetPrec(uint(prec + ad)).SetFloat64(a)
  1425  					B := new(Float).SetPrec(uint(prec + bd)).SetFloat64(b)
  1426  					C := new(Float).SetPrec(53).Quo(A, B) // C has float64 mantissa width
  1427  
  1428  					cc, acc := C.Float64()
  1429  					if cc != c {
  1430  						t.Errorf("%g/%g = %s; want %.5g\n", a, b, C.Format('g', 5), c)
  1431  						continue
  1432  					}
  1433  					if acc != Exact {
  1434  						t.Errorf("%g/%g got %s result; want exact result", a, b, acc)
  1435  					}
  1436  				}
  1437  			}
  1438  		}
  1439  	}
  1440  }
  1441  
  1442  // TestFloatArithmeticSpecialValues tests that Float operations produce the
  1443  // correct results for combinations of zero (±0), finite (±1 and ±2.71828),
  1444  // and infinite (±Inf) operands.
  1445  func TestFloatArithmeticSpecialValues(t *testing.T) {
  1446  	zero := 0.0
  1447  	args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
  1448  	xx := new(Float)
  1449  	yy := new(Float)
  1450  	got := new(Float)
  1451  	want := new(Float)
  1452  	for i := 0; i < 4; i++ {
  1453  		for _, x := range args {
  1454  			xx.SetFloat64(x)
  1455  			// check conversion is correct
  1456  			// (no need to do this for y, since we see exactly the
  1457  			// same values there)
  1458  			if got, acc := xx.Float64(); got != x || acc != Exact {
  1459  				t.Errorf("Float(%g) == %g (%s)", x, got, acc)
  1460  			}
  1461  			for _, y := range args {
  1462  				yy.SetFloat64(y)
  1463  				var (
  1464  					op string
  1465  					z  float64
  1466  					f  func(z, x, y *Float) *Float
  1467  				)
  1468  				switch i {
  1469  				case 0:
  1470  					op = "+"
  1471  					z = x + y
  1472  					f = (*Float).Add
  1473  				case 1:
  1474  					op = "-"
  1475  					z = x - y
  1476  					f = (*Float).Sub
  1477  				case 2:
  1478  					op = "*"
  1479  					z = x * y
  1480  					f = (*Float).Mul
  1481  				case 3:
  1482  					op = "/"
  1483  					z = x / y
  1484  					f = (*Float).Quo
  1485  				default:
  1486  					panic("unreachable")
  1487  				}
  1488  				var errnan bool // set if execution of f panicked with ErrNaN
  1489  				// protect execution of f
  1490  				func() {
  1491  					defer func() {
  1492  						if p := recover(); p != nil {
  1493  							_ = p.(ErrNaN) // re-panic if not ErrNaN
  1494  							errnan = true
  1495  						}
  1496  					}()
  1497  					f(got, xx, yy)
  1498  				}()
  1499  				if math.IsNaN(z) {
  1500  					if !errnan {
  1501  						t.Errorf("%5g %s %5g = %5s; want ErrNaN panic", x, op, y, got)
  1502  					}
  1503  					continue
  1504  				}
  1505  				if errnan {
  1506  					t.Errorf("%5g %s %5g panicked with ErrNan; want %5s", x, op, y, want)
  1507  					continue
  1508  				}
  1509  				want.SetFloat64(z)
  1510  				if !alike(got, want) {
  1511  					t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want)
  1512  				}
  1513  			}
  1514  		}
  1515  	}
  1516  }
  1517  
  1518  func TestFloatArithmeticOverflow(t *testing.T) {
  1519  	for _, test := range []struct {
  1520  		prec       uint
  1521  		mode       RoundingMode
  1522  		op         byte
  1523  		x, y, want string
  1524  		acc        Accuracy
  1525  	}{
  1526  		{4, ToNearestEven, '+', "0", "0", "0", Exact},                // smoke test
  1527  		{4, ToNearestEven, '+', "0x.8p0", "0x.8p0", "0x.8p1", Exact}, // smoke test
  1528  
  1529  		{4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p2147483647", Exact},
  1530  		{4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p2147483647", Below}, // rounded to zero
  1531  		{4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above},            // exponent overflow in +
  1532  		{4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below},          // exponent overflow in +
  1533  		{4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below},           // exponent overflow in -
  1534  
  1535  		{4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp2147483647", Below}, // rounded to zero
  1536  		{4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above},     // exponent overflow in rounding
  1537  		{4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above},      // exponent overflow in rounding
  1538  
  1539  		{4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below},       // exponent overflow in rounding
  1540  		{4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below},      // exponent overflow in rounding
  1541  		{4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp2147483647", Above}, // rounded to zero
  1542  
  1543  		{4, ToNearestEven, '+', "0", "0x.8p-2147483648", "0x.8p-2147483648", Exact},
  1544  		{4, ToNearestEven, '+', "0x.8p-2147483648", "0x.8p-2147483648", "0x.8p-2147483647", Exact},
  1545  
  1546  		{4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p2147483647", Exact},
  1547  		{4, ToNearestEven, '*', "2", "0x.8p2147483647", "+Inf", Above},  // exponent overflow in *
  1548  		{4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in *
  1549  
  1550  		{4, ToNearestEven, '/', "0.5", "0x.8p2147483647", "0x.8p-2147483646", Exact},
  1551  		{4, ToNearestEven, '/', "0x.8p0", "0x.8p2147483647", "0x.8p-2147483646", Exact},
  1552  		{4, ToNearestEven, '/', "0x.8p-1", "0x.8p2147483647", "0x.8p-2147483647", Exact},
  1553  		{4, ToNearestEven, '/', "0x.8p-2", "0x.8p2147483647", "0x.8p-2147483648", Exact},
  1554  		{4, ToNearestEven, '/', "0x.8p-3", "0x.8p2147483647", "0", Below}, // exponent underflow in /
  1555  	} {
  1556  		x := makeFloat(test.x)
  1557  		y := makeFloat(test.y)
  1558  		z := new(Float).SetPrec(test.prec).SetMode(test.mode)
  1559  		switch test.op {
  1560  		case '+':
  1561  			z.Add(x, y)
  1562  		case '-':
  1563  			z.Sub(x, y)
  1564  		case '*':
  1565  			z.Mul(x, y)
  1566  		case '/':
  1567  			z.Quo(x, y)
  1568  		default:
  1569  			panic("unreachable")
  1570  		}
  1571  		if got := z.Format('p', 0); got != test.want || z.Acc() != test.acc {
  1572  			t.Errorf(
  1573  				"prec = %d (%s): %s %c %s = %s (%s); want %s (%s)",
  1574  				test.prec, test.mode, x.Format('p', 0), test.op, y.Format('p', 0), got, z.Acc(), test.want, test.acc,
  1575  			)
  1576  		}
  1577  	}
  1578  }
  1579  
  1580  // TODO(gri) Add tests that check correctness in the presence of aliasing.
  1581  
  1582  // For rounding modes ToNegativeInf and ToPositiveInf, rounding is affected
  1583  // by the sign of the value to be rounded. Test that rounding happens after
  1584  // the sign of a result has been set.
  1585  // This test uses specific values that are known to fail if rounding is
  1586  // "factored" out before setting the result sign.
  1587  func TestFloatArithmeticRounding(t *testing.T) {
  1588  	for _, test := range []struct {
  1589  		mode       RoundingMode
  1590  		prec       uint
  1591  		x, y, want int64
  1592  		op         byte
  1593  	}{
  1594  		{ToZero, 3, -0x8, -0x1, -0x8, '+'},
  1595  		{AwayFromZero, 3, -0x8, -0x1, -0xa, '+'},
  1596  		{ToNegativeInf, 3, -0x8, -0x1, -0xa, '+'},
  1597  
  1598  		{ToZero, 3, -0x8, 0x1, -0x8, '-'},
  1599  		{AwayFromZero, 3, -0x8, 0x1, -0xa, '-'},
  1600  		{ToNegativeInf, 3, -0x8, 0x1, -0xa, '-'},
  1601  
  1602  		{ToZero, 3, -0x9, 0x1, -0x8, '*'},
  1603  		{AwayFromZero, 3, -0x9, 0x1, -0xa, '*'},
  1604  		{ToNegativeInf, 3, -0x9, 0x1, -0xa, '*'},
  1605  
  1606  		{ToZero, 3, -0x9, 0x1, -0x8, '/'},
  1607  		{AwayFromZero, 3, -0x9, 0x1, -0xa, '/'},
  1608  		{ToNegativeInf, 3, -0x9, 0x1, -0xa, '/'},
  1609  	} {
  1610  		var x, y, z Float
  1611  		x.SetInt64(test.x)
  1612  		y.SetInt64(test.y)
  1613  		z.SetPrec(test.prec).SetMode(test.mode)
  1614  		switch test.op {
  1615  		case '+':
  1616  			z.Add(&x, &y)
  1617  		case '-':
  1618  			z.Sub(&x, &y)
  1619  		case '*':
  1620  			z.Mul(&x, &y)
  1621  		case '/':
  1622  			z.Quo(&x, &y)
  1623  		default:
  1624  			panic("unreachable")
  1625  		}
  1626  		if got, acc := z.Int64(); got != test.want || acc != Exact {
  1627  			t.Errorf("%s, %d bits: %d %c %d = %d (%s); want %d (Exact)",
  1628  				test.mode, test.prec, test.x, test.op, test.y, got, acc, test.want,
  1629  			)
  1630  		}
  1631  	}
  1632  }
  1633  
  1634  // TestFloatCmpSpecialValues tests that Cmp produces the correct results for
  1635  // combinations of zero (±0), finite (±1 and ±2.71828), and infinite (±Inf)
  1636  // operands.
  1637  func TestFloatCmpSpecialValues(t *testing.T) {
  1638  	zero := 0.0
  1639  	args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
  1640  	xx := new(Float)
  1641  	yy := new(Float)
  1642  	for i := 0; i < 4; i++ {
  1643  		for _, x := range args {
  1644  			xx.SetFloat64(x)
  1645  			// check conversion is correct
  1646  			// (no need to do this for y, since we see exactly the
  1647  			// same values there)
  1648  			if got, acc := xx.Float64(); got != x || acc != Exact {
  1649  				t.Errorf("Float(%g) == %g (%s)", x, got, acc)
  1650  			}
  1651  			for _, y := range args {
  1652  				yy.SetFloat64(y)
  1653  				got := xx.Cmp(yy)
  1654  				want := 0
  1655  				switch {
  1656  				case x < y:
  1657  					want = -1
  1658  				case x > y:
  1659  					want = +1
  1660  				}
  1661  				if got != want {
  1662  					t.Errorf("(%g).Cmp(%g) = %s; want %s", x, y, got, want)
  1663  				}
  1664  			}
  1665  		}
  1666  	}
  1667  }