github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/cmd/signature-fuzzer/internal/fuzz-generator/numparm.go (about) 1 // Copyright 2021 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 generator 6 7 import ( 8 "bytes" 9 "fmt" 10 "math" 11 ) 12 13 // numparm describes a numeric parameter type; it implements the 14 // "parm" interface. 15 type numparm struct { 16 tag string 17 widthInBits uint32 18 ctl bool 19 isBlank 20 addrTakenHow 21 isGenValFunc 22 skipCompare 23 } 24 25 var f32parm *numparm = &numparm{ 26 tag: "float", 27 widthInBits: uint32(32), 28 ctl: false, 29 } 30 var f64parm *numparm = &numparm{ 31 tag: "float", 32 widthInBits: uint32(64), 33 ctl: false, 34 } 35 36 func (p numparm) TypeName() string { 37 if p.tag == "byte" { 38 return "byte" 39 } 40 return fmt.Sprintf("%s%d", p.tag, p.widthInBits) 41 } 42 43 func (p numparm) QualName() string { 44 return p.TypeName() 45 } 46 47 func (p numparm) String() string { 48 if p.tag == "byte" { 49 return "byte" 50 } 51 ctl := "" 52 if p.ctl { 53 ctl = " [ctl=yes]" 54 } 55 return fmt.Sprintf("%s%s", p.TypeName(), ctl) 56 } 57 58 func (p numparm) NumElements() int { 59 return 1 60 } 61 62 func (p numparm) IsControl() bool { 63 return p.ctl 64 } 65 66 func (p numparm) GenElemRef(elidx int, path string) (string, parm) { 67 return path, &p 68 } 69 70 func (p numparm) Declare(b *bytes.Buffer, prefix string, suffix string, caller bool) { 71 t := fmt.Sprintf("%s%d%s", p.tag, p.widthInBits, suffix) 72 if p.tag == "byte" { 73 t = fmt.Sprintf("%s%s", p.tag, suffix) 74 } 75 b.WriteString(prefix + " " + t) 76 } 77 78 func (p numparm) genRandNum(s *genstate, value int) (string, int) { 79 which := uint8(s.wr.Intn(int64(100))) 80 if p.tag == "int" { 81 var v int64 82 if which < 3 { 83 // max 84 v = (1 << (p.widthInBits - 1)) - 1 85 86 } else if which < 5 { 87 // min 88 v = (-1 << (p.widthInBits - 1)) 89 } else { 90 nrange := int64(1 << (p.widthInBits - 2)) 91 v = s.wr.Intn(nrange) 92 if value%2 != 0 { 93 v = -v 94 } 95 } 96 return fmt.Sprintf("%s%d(%d)", p.tag, p.widthInBits, v), value + 1 97 } 98 if p.tag == "uint" || p.tag == "byte" { 99 nrange := int64(1 << (p.widthInBits - 2)) 100 v := s.wr.Intn(nrange) 101 if p.tag == "byte" { 102 return fmt.Sprintf("%s(%d)", p.tag, v), value + 1 103 } 104 return fmt.Sprintf("%s%d(0x%x)", p.tag, p.widthInBits, v), value + 1 105 } 106 if p.tag == "float" { 107 if p.widthInBits == 32 { 108 rf := s.wr.Float32() * (math.MaxFloat32 / 4) 109 if value%2 != 0 { 110 rf = -rf 111 } 112 return fmt.Sprintf("%s%d(%v)", p.tag, p.widthInBits, rf), value + 1 113 } 114 if p.widthInBits == 64 { 115 return fmt.Sprintf("%s%d(%v)", p.tag, p.widthInBits, 116 s.wr.NormFloat64()), value + 1 117 } 118 panic("unknown float type") 119 } 120 if p.tag == "complex" { 121 if p.widthInBits == 64 { 122 f1, v2 := f32parm.genRandNum(s, value) 123 f2, v3 := f32parm.genRandNum(s, v2) 124 return fmt.Sprintf("complex(%s,%s)", f1, f2), v3 125 } 126 if p.widthInBits == 128 { 127 f1, v2 := f64parm.genRandNum(s, value) 128 f2, v3 := f64parm.genRandNum(s, v2) 129 return fmt.Sprintf("complex(%v,%v)", f1, f2), v3 130 } 131 panic("unknown complex type") 132 } 133 panic("unknown numeric type") 134 } 135 136 func (p numparm) GenValue(s *genstate, f *funcdef, value int, caller bool) (string, int) { 137 r, nv := p.genRandNum(s, value) 138 verb(5, "numparm.GenValue(%d) = %s", value, r) 139 return r, nv 140 } 141 142 func (p numparm) HasPointer() bool { 143 return false 144 }