Пример #1
0
// checkIsBestApprox32 checks that f is the best possible float32
// approximation of r.
// Returns true on success.
func checkIsBestApprox32(t *testing.T, f float32, r *Rat) bool {
	if math.Abs(float64(f)) >= math.MaxFloat32 {
		// Cannot check +Inf, -Inf, nor the float next to them (MaxFloat32).
		// But we have tests for these special cases.
		return true
	}

	// r must be strictly between f0 and f1, the floats bracketing f.
	f0 := math.Nextafter32(f, float32(math.Inf(-1)))
	f1 := math.Nextafter32(f, float32(math.Inf(+1)))

	// For f to be correct, r must be closer to f than to f0 or f1.
	df := delta(r, float64(f))
	df0 := delta(r, float64(f0))
	df1 := delta(r, float64(f1))
	if df.Cmp(df0) > 0 {
		t.Errorf("Rat(%v).Float32() = %g (%b), but previous float32 %g (%b) is closer", r, f, f, f0, f0)
		return false
	}
	if df.Cmp(df1) > 0 {
		t.Errorf("Rat(%v).Float32() = %g (%b), but next float32 %g (%b) is closer", r, f, f, f1, f1)
		return false
	}
	if df.Cmp(df0) == 0 && !isEven32(f) {
		t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0)
		return false
	}
	if df.Cmp(df1) == 0 && !isEven32(f) {
		t.Errorf("Rat(%v).Float32() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1)
		return false
	}
	return true
}
Пример #2
0
func TestRound(t *testing.T) {
	ival := []float32{0}
	x := float32(1)
	for !math.IsInf(float64(x), 1) {
		ival = append(ival, x)
		x *= 2
	}
	fval := []float32{}
	x = 0.5
	for x != 0 {
		fval = append(fval, x, math.Nextafter32(x, 1), math.Nextafter32(x, -1))
		x /= 2
	}
	for _, i := range ival {
		for _, f := range fval {
			x := i + f
			y := Round(x)
			d := Abs(y - x)
			assert(d <= 0.5, "Round/Abs", t)
			assert(d < 0.5 || int(y)&1 == 0, "Round/Abs", t)
			assert(Round(-x) == -Round(x), "Round", t)
			assert(Signbit(Round(-x)) == !Signbit(y), "Signbit/Round", t)
		}
	}
}
Пример #3
0
func TestRasterizeAlmostAxisAligned(t *testing.T) {
	z := NewRasterizer(8, 8)
	z.MoveTo(2, 2)
	z.LineTo(6, math.Nextafter32(2, 0))
	z.LineTo(6, 6)
	z.LineTo(math.Nextafter32(2, 0), 6)
	z.ClosePath()

	dst := image.NewAlpha(z.Bounds())
	z.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})

	if err := checkCornersCenter(dst); err != nil {
		t.Error(err)
	}
}
Пример #4
0
func TestTrunc(t *testing.T) {
	ival := []float32{}
	x := float32(1)
	for !math.IsInf(float64(x), 1) {
		ival = append(ival, x)
		x *= 2
	}
	fval := []float32{}
	x = math.Nextafter32(1, -1)
	for x != 0 {
		fval = append(fval, x)
		x = 1 - (1-x)*2
	}
	for _, i := range ival {
		for _, f := range fval {
			x := i + f
			y := Trunc(x)
			assert(y == i || x-i == 1, "Trunc", t)
			z := Trunc(-x)
			assert(z == -y, "Trunc", t)
			assert(Signbit(Trunc(-x)) == !Signbit(y), "Signbit/Trunc", t)
		}
	}
}
Пример #5
0
func init() {
	epsilon32 = math.Nextafter32(1, 2) - 1
}
Пример #6
0
func TestMarshalFloat(t *testing.T) {
	t.Parallel()
	nfail := 0
	test := func(f float64, bits int) {
		vf := interface{}(f)
		if bits == 32 {
			f = float64(float32(f)) // round
			vf = float32(f)
		}
		bout, err := Marshal(vf)
		if err != nil {
			t.Errorf("Marshal(%T(%g)): %v", vf, vf, err)
			nfail++
			return
		}
		out := string(bout)

		// result must convert back to the same float
		g, err := strconv.ParseFloat(out, bits)
		if err != nil {
			t.Errorf("Marshal(%T(%g)) = %q, cannot parse back: %v", vf, vf, out, err)
			nfail++
			return
		}
		if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±0
			t.Errorf("Marshal(%T(%g)) = %q (is %g, not %g)", vf, vf, out, float32(g), vf)
			nfail++
			return
		}

		bad := badFloatREs
		if bits == 64 {
			bad = bad[:len(bad)-2]
		}
		for _, re := range bad {
			if re.MatchString(out) {
				t.Errorf("Marshal(%T(%g)) = %q, must not match /%s/", vf, vf, out, re)
				nfail++
				return
			}
		}
	}

	var (
		bigger  = math.Inf(+1)
		smaller = math.Inf(-1)
	)

	var digits = "1.2345678901234567890123"
	for i := len(digits); i >= 2; i-- {
		for exp := -30; exp <= 30; exp++ {
			for _, sign := range "+-" {
				for bits := 32; bits <= 64; bits += 32 {
					s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)
					f, err := strconv.ParseFloat(s, bits)
					if err != nil {
						log.Fatal(err)
					}
					next := math.Nextafter
					if bits == 32 {
						next = func(g, h float64) float64 {
							return float64(math.Nextafter32(float32(g), float32(h)))
						}
					}
					test(f, bits)
					test(next(f, bigger), bits)
					test(next(f, smaller), bits)
					if nfail > 50 {
						t.Fatalf("stopping test early")
					}
				}
			}
		}
	}
	test(0, 64)
	test(math.Copysign(0, -1), 64)
	test(0, 32)
	test(math.Copysign(0, -1), 32)
}
Пример #7
0
func Nextafter32(x, y float32) float32 { return math.Nextafter32(x, y) }