mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			199 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
| // Copyright 2010 The Go Authors.  All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package runtime_test
 | |
| 
 | |
| import (
 | |
| 	"math"
 | |
| 	"math/rand"
 | |
| 	. "runtime"
 | |
| 	"testing"
 | |
| )
 | |
| 
 | |
| // turn uint64 op into float64 op
 | |
| func fop(f func(x, y uint64) uint64) func(x, y float64) float64 {
 | |
| 	return func(x, y float64) float64 {
 | |
| 		bx := math.Float64bits(x)
 | |
| 		by := math.Float64bits(y)
 | |
| 		return math.Float64frombits(f(bx, by))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func add(x, y float64) float64 { return x + y }
 | |
| func sub(x, y float64) float64 { return x - y }
 | |
| func mul(x, y float64) float64 { return x * y }
 | |
| func div(x, y float64) float64 { return x / y }
 | |
| 
 | |
| func TestFloat64(t *testing.T) {
 | |
| 	base := []float64{
 | |
| 		0,
 | |
| 		math.Copysign(0, -1),
 | |
| 		-1,
 | |
| 		1,
 | |
| 		math.NaN(),
 | |
| 		math.Inf(+1),
 | |
| 		math.Inf(-1),
 | |
| 		0.1,
 | |
| 		1.5,
 | |
| 		1.9999999999999998,     // all 1s mantissa
 | |
| 		1.3333333333333333,     // 1.010101010101...
 | |
| 		1.1428571428571428,     // 1.001001001001...
 | |
| 		1.112536929253601e-308, // first normal
 | |
| 		2,
 | |
| 		4,
 | |
| 		8,
 | |
| 		16,
 | |
| 		32,
 | |
| 		64,
 | |
| 		128,
 | |
| 		256,
 | |
| 		3,
 | |
| 		12,
 | |
| 		1234,
 | |
| 		123456,
 | |
| 		-0.1,
 | |
| 		-1.5,
 | |
| 		-1.9999999999999998,
 | |
| 		-1.3333333333333333,
 | |
| 		-1.1428571428571428,
 | |
| 		-2,
 | |
| 		-3,
 | |
| 		1e-200,
 | |
| 		1e-300,
 | |
| 		1e-310,
 | |
| 		5e-324,
 | |
| 		1e-105,
 | |
| 		1e-305,
 | |
| 		1e+200,
 | |
| 		1e+306,
 | |
| 		1e+307,
 | |
| 		1e+308,
 | |
| 	}
 | |
| 	all := make([]float64, 200)
 | |
| 	copy(all, base)
 | |
| 	for i := len(base); i < len(all); i++ {
 | |
| 		all[i] = rand.NormFloat64()
 | |
| 	}
 | |
| 
 | |
| 	test(t, "+", add, fop(Fadd64), all)
 | |
| 	test(t, "-", sub, fop(Fsub64), all)
 | |
| 	if GOARCH != "386" { // 386 is not precise!
 | |
| 		test(t, "*", mul, fop(Fmul64), all)
 | |
| 		test(t, "/", div, fop(Fdiv64), all)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // 64 -hw-> 32 -hw-> 64
 | |
| func trunc32(f float64) float64 {
 | |
| 	return float64(float32(f))
 | |
| }
 | |
| 
 | |
| // 64 -sw->32 -hw-> 64
 | |
| func to32sw(f float64) float64 {
 | |
| 	return float64(math.Float32frombits(F64to32(math.Float64bits(f))))
 | |
| }
 | |
| 
 | |
| // 64 -hw->32 -sw-> 64
 | |
| func to64sw(f float64) float64 {
 | |
| 	return math.Float64frombits(F32to64(math.Float32bits(float32(f))))
 | |
| }
 | |
| 
 | |
| // float64 -hw-> int64 -hw-> float64
 | |
| func hwint64(f float64) float64 {
 | |
| 	return float64(int64(f))
 | |
| }
 | |
| 
 | |
| // float64 -hw-> int32 -hw-> float64
 | |
| func hwint32(f float64) float64 {
 | |
| 	return float64(int32(f))
 | |
| }
 | |
| 
 | |
| // float64 -sw-> int64 -hw-> float64
 | |
| func toint64sw(f float64) float64 {
 | |
| 	i, ok := F64toint(math.Float64bits(f))
 | |
| 	if !ok {
 | |
| 		// There's no right answer for out of range.
 | |
| 		// Match the hardware to pass the test.
 | |
| 		i = int64(f)
 | |
| 	}
 | |
| 	return float64(i)
 | |
| }
 | |
| 
 | |
| // float64 -hw-> int64 -sw-> float64
 | |
| func fromint64sw(f float64) float64 {
 | |
| 	return math.Float64frombits(Fintto64(int64(f)))
 | |
| }
 | |
| 
 | |
| var nerr int
 | |
| 
 | |
| func err(t *testing.T, format string, args ...interface{}) {
 | |
| 	t.Errorf(format, args...)
 | |
| 
 | |
| 	// cut errors off after a while.
 | |
| 	// otherwise we spend all our time
 | |
| 	// allocating memory to hold the
 | |
| 	// formatted output.
 | |
| 	if nerr++; nerr >= 10 {
 | |
| 		t.Fatal("too many errors")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func test(t *testing.T, op string, hw, sw func(float64, float64) float64, all []float64) {
 | |
| 	for _, f := range all {
 | |
| 		for _, g := range all {
 | |
| 			h := hw(f, g)
 | |
| 			s := sw(f, g)
 | |
| 			if !same(h, s) {
 | |
| 				err(t, "%g %s %g = sw %g, hw %g\n", f, op, g, s, h)
 | |
| 			}
 | |
| 			testu(t, "to32", trunc32, to32sw, h)
 | |
| 			testu(t, "to64", trunc32, to64sw, h)
 | |
| 			testu(t, "toint64", hwint64, toint64sw, h)
 | |
| 			testu(t, "fromint64", hwint64, fromint64sw, h)
 | |
| 			testcmp(t, f, h)
 | |
| 			testcmp(t, h, f)
 | |
| 			testcmp(t, g, h)
 | |
| 			testcmp(t, h, g)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func testu(t *testing.T, op string, hw, sw func(float64) float64, v float64) {
 | |
| 	h := hw(v)
 | |
| 	s := sw(v)
 | |
| 	if !same(h, s) {
 | |
| 		err(t, "%s %g = sw %g, hw %g\n", op, v, s, h)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func hwcmp(f, g float64) (cmp int, isnan bool) {
 | |
| 	switch {
 | |
| 	case f < g:
 | |
| 		return -1, false
 | |
| 	case f > g:
 | |
| 		return +1, false
 | |
| 	case f == g:
 | |
| 		return 0, false
 | |
| 	}
 | |
| 	return 0, true // must be NaN
 | |
| }
 | |
| 
 | |
| func testcmp(t *testing.T, f, g float64) {
 | |
| 	hcmp, hisnan := hwcmp(f, g)
 | |
| 	scmp, sisnan := Fcmp64(math.Float64bits(f), math.Float64bits(g))
 | |
| 	if hcmp != scmp || hisnan != sisnan {
 | |
| 		err(t, "cmp(%g, %g) = sw %v, %v, hw %v, %v\n", f, g, scmp, sisnan, hcmp, hisnan)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func same(f, g float64) bool {
 | |
| 	if math.IsNaN(f) && math.IsNaN(g) {
 | |
| 		return true
 | |
| 	}
 | |
| 	if math.Copysign(1, f) != math.Copysign(1, g) {
 | |
| 		return false
 | |
| 	}
 | |
| 	return f == g
 | |
| }
 |