...

Source file src/runtime/softfloat64_test.go

Documentation: runtime

		 1  // Copyright 2010 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 runtime_test
		 6  
		 7  import (
		 8  	"math"
		 9  	"math/rand"
		10  	. "runtime"
		11  	"testing"
		12  )
		13  
		14  // turn uint64 op into float64 op
		15  func fop(f func(x, y uint64) uint64) func(x, y float64) float64 {
		16  	return func(x, y float64) float64 {
		17  		bx := math.Float64bits(x)
		18  		by := math.Float64bits(y)
		19  		return math.Float64frombits(f(bx, by))
		20  	}
		21  }
		22  
		23  func add(x, y float64) float64 { return x + y }
		24  func sub(x, y float64) float64 { return x - y }
		25  func mul(x, y float64) float64 { return x * y }
		26  func div(x, y float64) float64 { return x / y }
		27  
		28  func TestFloat64(t *testing.T) {
		29  	base := []float64{
		30  		0,
		31  		math.Copysign(0, -1),
		32  		-1,
		33  		1,
		34  		math.NaN(),
		35  		math.Inf(+1),
		36  		math.Inf(-1),
		37  		0.1,
		38  		1.5,
		39  		1.9999999999999998,		 // all 1s mantissa
		40  		1.3333333333333333,		 // 1.010101010101...
		41  		1.1428571428571428,		 // 1.001001001001...
		42  		1.112536929253601e-308, // first normal
		43  		2,
		44  		4,
		45  		8,
		46  		16,
		47  		32,
		48  		64,
		49  		128,
		50  		256,
		51  		3,
		52  		12,
		53  		1234,
		54  		123456,
		55  		-0.1,
		56  		-1.5,
		57  		-1.9999999999999998,
		58  		-1.3333333333333333,
		59  		-1.1428571428571428,
		60  		-2,
		61  		-3,
		62  		1e-200,
		63  		1e-300,
		64  		1e-310,
		65  		5e-324,
		66  		1e-105,
		67  		1e-305,
		68  		1e+200,
		69  		1e+306,
		70  		1e+307,
		71  		1e+308,
		72  	}
		73  	all := make([]float64, 200)
		74  	copy(all, base)
		75  	for i := len(base); i < len(all); i++ {
		76  		all[i] = rand.NormFloat64()
		77  	}
		78  
		79  	test(t, "+", add, fop(Fadd64), all)
		80  	test(t, "-", sub, fop(Fsub64), all)
		81  	if GOARCH != "386" { // 386 is not precise!
		82  		test(t, "*", mul, fop(Fmul64), all)
		83  		test(t, "/", div, fop(Fdiv64), all)
		84  	}
		85  }
		86  
		87  // 64 -hw-> 32 -hw-> 64
		88  func trunc32(f float64) float64 {
		89  	return float64(float32(f))
		90  }
		91  
		92  // 64 -sw->32 -hw-> 64
		93  func to32sw(f float64) float64 {
		94  	return float64(math.Float32frombits(F64to32(math.Float64bits(f))))
		95  }
		96  
		97  // 64 -hw->32 -sw-> 64
		98  func to64sw(f float64) float64 {
		99  	return math.Float64frombits(F32to64(math.Float32bits(float32(f))))
	 100  }
	 101  
	 102  // float64 -hw-> int64 -hw-> float64
	 103  func hwint64(f float64) float64 {
	 104  	return float64(int64(f))
	 105  }
	 106  
	 107  // float64 -hw-> int32 -hw-> float64
	 108  func hwint32(f float64) float64 {
	 109  	return float64(int32(f))
	 110  }
	 111  
	 112  // float64 -sw-> int64 -hw-> float64
	 113  func toint64sw(f float64) float64 {
	 114  	i, ok := F64toint(math.Float64bits(f))
	 115  	if !ok {
	 116  		// There's no right answer for out of range.
	 117  		// Match the hardware to pass the test.
	 118  		i = int64(f)
	 119  	}
	 120  	return float64(i)
	 121  }
	 122  
	 123  // float64 -hw-> int64 -sw-> float64
	 124  func fromint64sw(f float64) float64 {
	 125  	return math.Float64frombits(Fintto64(int64(f)))
	 126  }
	 127  
	 128  var nerr int
	 129  
	 130  func err(t *testing.T, format string, args ...interface{}) {
	 131  	t.Errorf(format, args...)
	 132  
	 133  	// cut errors off after a while.
	 134  	// otherwise we spend all our time
	 135  	// allocating memory to hold the
	 136  	// formatted output.
	 137  	if nerr++; nerr >= 10 {
	 138  		t.Fatal("too many errors")
	 139  	}
	 140  }
	 141  
	 142  func test(t *testing.T, op string, hw, sw func(float64, float64) float64, all []float64) {
	 143  	for _, f := range all {
	 144  		for _, g := range all {
	 145  			h := hw(f, g)
	 146  			s := sw(f, g)
	 147  			if !same(h, s) {
	 148  				err(t, "%g %s %g = sw %g, hw %g\n", f, op, g, s, h)
	 149  			}
	 150  			testu(t, "to32", trunc32, to32sw, h)
	 151  			testu(t, "to64", trunc32, to64sw, h)
	 152  			testu(t, "toint64", hwint64, toint64sw, h)
	 153  			testu(t, "fromint64", hwint64, fromint64sw, h)
	 154  			testcmp(t, f, h)
	 155  			testcmp(t, h, f)
	 156  			testcmp(t, g, h)
	 157  			testcmp(t, h, g)
	 158  		}
	 159  	}
	 160  }
	 161  
	 162  func testu(t *testing.T, op string, hw, sw func(float64) float64, v float64) {
	 163  	h := hw(v)
	 164  	s := sw(v)
	 165  	if !same(h, s) {
	 166  		err(t, "%s %g = sw %g, hw %g\n", op, v, s, h)
	 167  	}
	 168  }
	 169  
	 170  func hwcmp(f, g float64) (cmp int, isnan bool) {
	 171  	switch {
	 172  	case f < g:
	 173  		return -1, false
	 174  	case f > g:
	 175  		return +1, false
	 176  	case f == g:
	 177  		return 0, false
	 178  	}
	 179  	return 0, true // must be NaN
	 180  }
	 181  
	 182  func testcmp(t *testing.T, f, g float64) {
	 183  	hcmp, hisnan := hwcmp(f, g)
	 184  	scmp, sisnan := Fcmp64(math.Float64bits(f), math.Float64bits(g))
	 185  	if int32(hcmp) != scmp || hisnan != sisnan {
	 186  		err(t, "cmp(%g, %g) = sw %v, %v, hw %v, %v\n", f, g, scmp, sisnan, hcmp, hisnan)
	 187  	}
	 188  }
	 189  
	 190  func same(f, g float64) bool {
	 191  	if math.IsNaN(f) && math.IsNaN(g) {
	 192  		return true
	 193  	}
	 194  	if math.Copysign(1, f) != math.Copysign(1, g) {
	 195  		return false
	 196  	}
	 197  	return f == g
	 198  }
	 199  

View as plain text