blob: 6be0d912a15e01846883adc21454b4ffa4d394a2 [file] [log] [blame]
// Copyright 2021 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 generator
import (
"bytes"
"fmt"
"math"
)
// numparm describes a numeric parameter type; it implements the
// "parm" interface.
type numparm struct {
tag string
widthInBits uint32
ctl bool
isBlank
addrTakenHow
isGenValFunc
skipCompare
}
var f32parm *numparm = &numparm{
tag: "float",
widthInBits: uint32(32),
ctl: false,
}
var f64parm *numparm = &numparm{
tag: "float",
widthInBits: uint32(64),
ctl: false,
}
func (p numparm) TypeName() string {
if p.tag == "byte" {
return "byte"
}
return fmt.Sprintf("%s%d", p.tag, p.widthInBits)
}
func (p numparm) QualName() string {
return p.TypeName()
}
func (p numparm) String() string {
if p.tag == "byte" {
return "byte"
}
ctl := ""
if p.ctl {
ctl = " [ctl=yes]"
}
return fmt.Sprintf("%s%s", p.TypeName(), ctl)
}
func (p numparm) NumElements() int {
return 1
}
func (p numparm) IsControl() bool {
return p.ctl
}
func (p numparm) GenElemRef(elidx int, path string) (string, parm) {
return path, &p
}
func (p numparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) {
t := fmt.Sprintf("%s%d%s", p.tag, p.widthInBits, suffix)
if p.tag == "byte" {
t = fmt.Sprintf("%s%s", p.tag, suffix)
}
b.WriteString(prefix + " " + t)
}
func (p numparm) genRandNum(s *genstate, value int) (string, int) {
which := uint8(s.wr.Intn(int64(100)))
if p.tag == "int" {
var v int64
if which < 3 {
// max
v = (1 << (p.widthInBits - 1)) - 1
} else if which < 5 {
// min
v = (-1 << (p.widthInBits - 1))
} else {
nrange := int64(1 << (p.widthInBits - 2))
v = s.wr.Intn(nrange)
if value%2 != 0 {
v = -v
}
}
return fmt.Sprintf("%s%d(%d)", p.tag, p.widthInBits, v), value + 1
}
if p.tag == "uint" || p.tag == "byte" {
nrange := int64(1 << (p.widthInBits - 2))
v := s.wr.Intn(nrange)
if p.tag == "byte" {
return fmt.Sprintf("%s(%d)", p.tag, v), value + 1
}
return fmt.Sprintf("%s%d(0x%x)", p.tag, p.widthInBits, v), value + 1
}
if p.tag == "float" {
if p.widthInBits == 32 {
rf := s.wr.Float32() * (math.MaxFloat32 / 4)
if value%2 != 0 {
rf = -rf
}
return fmt.Sprintf("%s%d(%v)", p.tag, p.widthInBits, rf), value + 1
}
if p.widthInBits == 64 {
return fmt.Sprintf("%s%d(%v)", p.tag, p.widthInBits,
s.wr.NormFloat64()), value + 1
}
panic("unknown float type")
}
if p.tag == "complex" {
if p.widthInBits == 64 {
f1, v2 := f32parm.genRandNum(s, value)
f2, v3 := f32parm.genRandNum(s, v2)
return fmt.Sprintf("complex(%s,%s)", f1, f2), v3
}
if p.widthInBits == 128 {
f1, v2 := f64parm.genRandNum(s, value)
f2, v3 := f64parm.genRandNum(s, v2)
return fmt.Sprintf("complex(%v,%v)", f1, f2), v3
}
panic("unknown complex type")
}
panic("unknown numeric type")
}
func (p numparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) {
r, nv := p.genRandNum(s, value)
verb(5, "numparm.GenValue(%d) = %s", value, r)
return r, nv
}
func (p numparm) HasPointer() bool {
return false
}