Black Lives Matter. Support the Equal Justice Initiative.

Source file src/math/big/float_test.go

Documentation: math/big

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

View as plain text