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