Source file src/math/big/float_test.go

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

View as plain text