go issue9604b 源码

  • 2022-07-15
  • 浏览 (822)

golang issue9604b 代码

文件路径:/test/fixedbugs/issue9604b.go

// runoutput

// Copyright 2015 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.

// terribly slow on wasm
// +build !wasm

package main

import (
	"fmt"
	"math/big"
	"unsafe"
)

var one = big.NewInt(1)

type _type struct {
	name   string
	bits   uint
	signed bool
}

// testvalues returns a list of all test values for this type.
func (t *_type) testvalues() []*big.Int {
	var a []*big.Int

	a = append(a, big.NewInt(0))
	a = append(a, big.NewInt(1))
	a = append(a, big.NewInt(2))
	if t.signed {
		a = append(a, big.NewInt(-1))
		a = append(a, big.NewInt(-2))
		r := big.NewInt(1)
		a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(1)))
		r = big.NewInt(1)
		a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(2)))
		r = big.NewInt(1)
		a = append(a, r.Lsh(r, t.bits-1).Neg(r))
		r = big.NewInt(1)
		a = append(a, r.Lsh(r, t.bits-1).Neg(r).Add(r, big.NewInt(1)))
	} else {
		r := big.NewInt(1)
		a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(1)))
		r = big.NewInt(1)
		a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(2)))
	}
	return a
}

// trunc truncates a value to the range of the given type.
func (t *_type) trunc(x *big.Int) *big.Int {
	r := new(big.Int)
	m := new(big.Int)
	m.Lsh(one, t.bits)
	m.Sub(m, one)
	r.And(x, m)
	if t.signed && r.Bit(int(t.bits)-1) == 1 {
		m.Neg(one)
		m.Lsh(m, t.bits)
		r.Or(r, m)
	}
	return r
}

var types = []_type{
	_type{"byte", 8, false},
	_type{"int8", 8, true},
	_type{"uint8", 8, false},
	_type{"rune", 32, true},
	_type{"int16", 16, true},
	_type{"uint16", 16, false},
	_type{"int32", 32, true},
	_type{"uint32", 32, false},
	_type{"int64", 64, true},
	_type{"uint64", 64, false},
	_type{"int", 8 * uint(unsafe.Sizeof(int(0))), true},
	_type{"uint", 8 * uint(unsafe.Sizeof(uint(0))), false},
	_type{"uintptr", 8 * uint(unsafe.Sizeof((*byte)(nil))), false},
}

type binop struct {
	name string
	eval func(x, y *big.Int) *big.Int
}

var binops = []binop{
	binop{"+", func(x, y *big.Int) *big.Int { return new(big.Int).Add(x, y) }},
	binop{"-", func(x, y *big.Int) *big.Int { return new(big.Int).Sub(x, y) }},
	binop{"*", func(x, y *big.Int) *big.Int { return new(big.Int).Mul(x, y) }},
	binop{"/", func(x, y *big.Int) *big.Int { return new(big.Int).Quo(x, y) }},
	binop{"%", func(x, y *big.Int) *big.Int { return new(big.Int).Rem(x, y) }},
	binop{"&", func(x, y *big.Int) *big.Int { return new(big.Int).And(x, y) }},
	binop{"|", func(x, y *big.Int) *big.Int { return new(big.Int).Or(x, y) }},
	binop{"^", func(x, y *big.Int) *big.Int { return new(big.Int).Xor(x, y) }},
	binop{"&^", func(x, y *big.Int) *big.Int { return new(big.Int).AndNot(x, y) }},
}

type unop struct {
	name string
	eval func(x *big.Int) *big.Int
}

var unops = []unop{
	unop{"+", func(x *big.Int) *big.Int { return new(big.Int).Set(x) }},
	unop{"-", func(x *big.Int) *big.Int { return new(big.Int).Neg(x) }},
	unop{"^", func(x *big.Int) *big.Int { return new(big.Int).Not(x) }},
}

type shiftop struct {
	name string
	eval func(x *big.Int, i uint) *big.Int
}

var shiftops = []shiftop{
	shiftop{"<<", func(x *big.Int, i uint) *big.Int { return new(big.Int).Lsh(x, i) }},
	shiftop{">>", func(x *big.Int, i uint) *big.Int { return new(big.Int).Rsh(x, i) }},
}

// valname returns the name of n as can be used as part of a variable name.
func valname(n *big.Int) string {
	s := fmt.Sprintf("%d", n)
	if s[0] == '-' {
		s = "neg" + s[1:]
	}
	return s
}

func main() {
	fmt.Println("package main")

	// We make variables to hold all the different values we'd like to use.
	// We use global variables to prevent any constant folding.
	for _, t := range types {
		for _, n := range t.testvalues() {
			fmt.Printf("var %s_%s %s = %d\n", t.name, valname(n), t.name, n)
		}
	}

	fmt.Println("func main() {")

	for _, t := range types {
		// test binary ops
		for _, op := range binops {
			for _, x := range t.testvalues() {
				for _, y := range t.testvalues() {
					if (op.name == "/" || op.name == "%") && y.Sign() == 0 {
						continue
					}
					r := t.trunc(op.eval(x, y))
					eqn := fmt.Sprintf("%s_%s %s %s_%s != %d", t.name, valname(x), op.name, t.name, valname(y), r)
					fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
				}
			}
		}
		// test unary ops
		for _, op := range unops {
			for _, x := range t.testvalues() {
				r := t.trunc(op.eval(x))
				eqn := fmt.Sprintf("%s %s_%s != %d", op.name, t.name, valname(x), r)
				fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
			}
		}
		// test shifts
		for _, op := range shiftops {
			for _, x := range t.testvalues() {

				for _, i := range []uint{0, 1, t.bits - 2, t.bits - 1, t.bits, t.bits + 1} {
					r := t.trunc(op.eval(x, i))
					eqn := fmt.Sprintf("%s_%s %s %d != %d", t.name, valname(x), op.name, i, r)
					fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
				}
			}
		}
	}

	fmt.Println("}")
}

相关信息

go 源码目录

相关文章

go bug000 源码

go bug002 源码

go bug003 源码

go bug004 源码

go bug005 源码

go bug006 源码

go bug007 源码

go bug008 源码

go bug009 源码

go bug010 源码

0  赞