github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/big/float_test.go (about)

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