github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/unit/constant/generate_constants.go (about) 1 // Copyright ©2014 The Gonum 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 // +build ignore 6 7 package main 8 9 import ( 10 "bytes" 11 "go/format" 12 "log" 13 "math" 14 "os" 15 "strings" 16 "text/template" 17 18 "github.com/jingcheng-WU/gonum/unit" 19 ) 20 21 const ( 22 elementaryCharge = 1.602176634e-19 23 fineStructure = 7.2973525693e-3 24 lightSpeed = 2.99792458e8 25 planck = 6.62607015e-34 26 ) 27 28 var constants = []Constant{ 29 { 30 Name: "AtomicMass", Value: 1.66053906660e-27, 31 Dimensions: []Dimension{{massName, 1}}, 32 Comment: "AtomicMass is the atomic mass constant (mᵤ), one twelfth of the mass of an unbound atom of carbon-12 at rest and in its ground state.", 33 Uncertainty: 0.00000000050e-27, 34 }, 35 { 36 Name: "Avogadro", Value: 6.02214076e23, 37 Dimensions: []Dimension{{moleName, -1}}, 38 Comment: "Avogadro is the Avogadro constant (A), the number of constituent particles contained in one mole of a substance.", 39 }, 40 { 41 Name: "Boltzmann", Value: 1.380649e-23, 42 Dimensions: []Dimension{{massName, 1}, {lengthName, 2}, {timeName, -2}, {temperatureName, -1}}, 43 Comment: "Boltzmann is the Boltzmann constant (k), it relates the average relative kinetic energy of particles in a gas with the temperature of the gas.", 44 }, 45 { 46 Name: "ElectricConstant", Value: 1 / (4 * math.Pi * 1e-7 * lightSpeed * lightSpeed), 47 Dimensions: []Dimension{{currentName, 2}, {timeName, 4}, {massName, -1}, {lengthName, -3}}, 48 Comment: "ElectricConstant is the electric constant (ε₀), the value of the absolute dielectric permittivity of classical vacuum.", 49 Uncertainty: 0.0000000013e-12, 50 }, 51 { 52 Name: "ElementaryCharge", Value: elementaryCharge, 53 Dimensions: []Dimension{{currentName, 1}, {timeName, 1}}, 54 Comment: "ElementaryCharge, is the elementary charge constant (e), the magnitude of electric charge carried by a single proton or electron.", 55 }, 56 { 57 Name: "Faraday", Value: 96485.33212, 58 Dimensions: []Dimension{{currentName, 1}, {timeName, 1}, {moleName, -1}}, 59 Comment: "Faraday is the Faraday constant, the magnitude of electric charge per mole of electrons.", 60 }, 61 { 62 Name: "FineStructure", Value: fineStructure, 63 Comment: "FineStructure is the fine structure constant (α), it describes the strength of the electromagnetic interaction between elementary charged particles.", 64 Uncertainty: 0.0000000011e-3, 65 }, 66 { 67 Name: "Gravitational", Value: 6.67430e-11, 68 Dimensions: []Dimension{{massName, -1}, {lengthName, 3}, {timeName, -2}}, 69 Comment: "Gravitational is the universal gravitational constant (G), the proportionality constant connecting the gravitational force between two bodies.", 70 Uncertainty: 0.00015e-11, 71 }, 72 { 73 Name: "LightSpeedInVacuum", Value: lightSpeed, 74 Dimensions: []Dimension{{lengthName, 1}, {timeName, -1}}, 75 Comment: "LightSpeedInVacuum is the c constant, the speed of light in a vacuum.", 76 }, 77 { 78 Name: "MagneticConstant", Value: 2 * fineStructure * planck / (elementaryCharge * elementaryCharge * lightSpeed), 79 Dimensions: []Dimension{{currentName, 2}, {timeName, 4}, {massName, -1}, {lengthName, -3}}, 80 Comment: "MagneticConstant is the magnetic constant (μ₀), the magnetic permeability in a classical vacuum.", 81 Uncertainty: 0.00000000019e-6, 82 }, 83 { 84 Name: "Planck", Value: planck, 85 Dimensions: []Dimension{{massName, 1}, {lengthName, 2}, {timeName, -1}}, 86 Comment: "Planck is the Planck constant (h), it relates the energy carried by a photon to its frequency.", 87 }, 88 { 89 Name: "StandardGravity", Value: 9.80665, 90 Dimensions: []Dimension{{lengthName, 1}, {timeName, -2}}, 91 Comment: "StandardGravity is the standard gravity constant (g₀), the nominal gravitational acceleration of an object in a vacuum near the surface of the Earth", 92 }, 93 } 94 95 const ( 96 angleName = "AngleDim" 97 currentName = "CurrentDim" 98 lengthName = "LengthDim" 99 luminousIntensityName = "LuminousIntensityDim" 100 massName = "MassDim" 101 moleName = "MoleDim" 102 temperatureName = "TemperatureDim" 103 timeName = "TimeDim" 104 ) 105 106 var dimOf = map[string]unit.Dimension{ 107 "AngleDim": unit.AngleDim, 108 "CurrentDim": unit.CurrentDim, 109 "LengthDim": unit.LengthDim, 110 "LuminousIntensityDim": unit.LuminousIntensityDim, 111 "MassDim": unit.MassDim, 112 "MoleDim": unit.MoleDim, 113 "TemperatureDim": unit.TemperatureDim, 114 "TimeDim": unit.TimeDim, 115 } 116 117 type Constant struct { 118 Name string 119 Value float64 120 Dimensions []Dimension 121 Comment string 122 Uncertainty float64 123 } 124 125 type Dimension struct { 126 Name string 127 Power int 128 } 129 130 func (c Constant) IsDefined() bool { 131 return definedEquivalentOf(unit.New(1, c.dimensions())) != "" 132 } 133 134 func (c Constant) Type() string { 135 typ := definedEquivalentOf(unit.New(1, c.dimensions())) 136 if typ == "" { 137 return strings.ToLower(c.Name[:1]) + c.Name[1:] + "Units" 138 } 139 return typ 140 } 141 142 func (c Constant) Units() string { 143 return c.dimensions().String() 144 } 145 146 func (c Constant) dimensions() unit.Dimensions { 147 dims := make(unit.Dimensions) 148 for _, d := range c.Dimensions { 149 dims[dimOf[d.Name]] = d.Power 150 } 151 return dims 152 } 153 154 // Generate a file for each of the constants. 155 func main() { 156 for _, c := range constants { 157 generate(c) 158 generateTest(c) 159 } 160 } 161 162 const baseUnitTemplate = `// Code generated by "go generate github.com/jingcheng-WU/gonum/unit/constant”; DO NOT EDIT. 163 164 // Copyright ©2019 The Gonum Authors. All rights reserved. 165 // Use of this source code is governed by a BSD-style 166 // license that can be found in the LICENSE file. 167 168 package constant 169 170 import "github.com/jingcheng-WU/gonum/unit" 171 172 // {{.Comment}}{{if .Dimensions}} 173 // {{$n := len .Dimensions}}The dimension{{if gt $n 1}}s{{end}} of {{.Name}} {{if eq $n 1}}is{{else}}are{{end}} {{.Units}}.{{end}} {{if not .Uncertainty}}The constant is exact.{{else}}The standard uncertainty of the constant is {{.Uncertainty}} {{.Units}}.{{end}} 174 const {{.Name}} = {{.Type}}({{.Value}}) 175 ` 176 177 var baseUnit = template.Must(template.New("base").Parse(baseUnitTemplate)) 178 179 const methodTemplate = `// Code generated by "go generate github.com/jingcheng-WU/gonum/unit/constant”; DO NOT EDIT. 180 181 // Copyright ©2019 The Gonum Authors. All rights reserved. 182 // Use of this source code is governed by a BSD-style 183 // license that can be found in the LICENSE file. 184 185 package constant 186 187 import ( 188 "fmt" 189 190 "github.com/jingcheng-WU/gonum/unit" 191 ) 192 193 // {{.Comment}} 194 // {{$n := len .Dimensions}}The dimension{{if gt $n 1}}s{{end}} of {{.Name}} {{if eq $n 1}}is{{else}}are{{end}} {{.Units}}. {{if not .Uncertainty}}The constant is exact.{{else}}The standard uncertainty of the constant is {{.Uncertainty}} {{.Units}}.{{end}} 195 const {{.Name}} = {{.Type}}({{.Value}}) 196 197 type {{.Type}} float64 198 199 // Unit converts the {{.Type}} to a *unit.Unit 200 func (cnst {{.Type}}) Unit() *unit.Unit { 201 return unit.New(float64(cnst), unit.Dimensions{ 202 {{range .Dimensions}} unit.{{.Name}}: {{.Power}}, 203 {{end}} 204 }) 205 } 206 207 func (cnst {{.Type}}) Format(fs fmt.State, c rune) { 208 switch c { 209 case 'v': 210 if fs.Flag('#') { 211 fmt.Fprintf(fs, "%T(%v)", cnst, float64(cnst)) 212 return 213 } 214 fallthrough 215 case 'e', 'E', 'f', 'F', 'g', 'G': 216 p, pOk := fs.Precision() 217 w, wOk := fs.Width() 218 switch { 219 case pOk && wOk: 220 fmt.Fprintf(fs, "%*.*"+string(c), w, p, cnst.Unit()) 221 case pOk: 222 fmt.Fprintf(fs, "%.*"+string(c), p, cnst.Unit()) 223 case wOk: 224 fmt.Fprintf(fs, "%*"+string(c), w, cnst.Unit()) 225 default: 226 fmt.Fprintf(fs, "%"+string(c), cnst.Unit()) 227 } 228 default: 229 fmt.Fprintf(fs, "%%!"+string(c)+"(constant.{{.Type}}=%v {{.Units}})", float64(cnst)) 230 } 231 } 232 ` 233 234 var methods = template.Must(template.New("methods").Parse(methodTemplate)) 235 236 func generate(c Constant) { 237 lowerName := strings.ToLower(c.Name) 238 filename := lowerName + ".go" 239 f, err := os.Create(filename) 240 if err != nil { 241 log.Fatal(err) 242 } 243 defer f.Close() 244 245 var buf bytes.Buffer 246 247 if c.IsDefined() { 248 err = baseUnit.Execute(&buf, c) 249 if err != nil { 250 log.Fatal(err) 251 } 252 } else { 253 err = methods.Execute(&buf, c) 254 if err != nil { 255 log.Fatal(err) 256 } 257 } 258 259 b, err := format.Source(buf.Bytes()) 260 if err != nil { 261 f.Write(buf.Bytes()) // This is here to debug bad format. 262 log.Fatalf("error formatting %q: %s", c.Name, err) 263 } 264 265 f.Write(b) 266 } 267 268 const testTemplate = `// Code generated by "go generate github.com/jingcheng-WU/gonum/unit/constant”; DO NOT EDIT. 269 270 // Copyright ©2019 The Gonum Authors. All rights reserved. 271 // Use of this source code is governed by a BSD-style 272 // license that can be found in the LICENSE file. 273 274 package constant 275 276 import ( 277 "fmt" 278 "testing" 279 ) 280 281 func Test{{.Name}}Format(t *testing.T) { 282 t.Parallel() 283 for _, test := range []struct{ 284 format string 285 want string 286 }{ 287 {"%v", "{{.Value}} {{.Units}}"}, 288 {"%.1v", "{{printf "%.1v" .Value}} {{.Units}}"}, 289 {"%50.1v", "{{$s := printf "%.1v %s" .Value .Units}}{{printf "%50s" $s}}"}, 290 {"%50v", "{{$s := printf "%v %s" .Value .Units}}{{printf "%50s" $s}}"}, 291 {"%1v", "{{.Value}} {{.Units}}"}, 292 {"%#v", "constant.{{.Type}}({{.Value}})"}, 293 {"%s", "%!s(constant.{{.Type}}={{.Value}} {{.Units}})"}, 294 } { 295 got := fmt.Sprintf(test.format, {{.Name}}) 296 if got != test.want { 297 t.Errorf("Format %q: got: %q want: %q", test.format, got, test.want) 298 } 299 } 300 } 301 ` 302 303 var tests = template.Must(template.New("test").Parse(testTemplate)) 304 305 func generateTest(c Constant) { 306 if c.IsDefined() { 307 return 308 } 309 310 lowerName := strings.ToLower(c.Name) 311 filename := lowerName + "_test.go" 312 f, err := os.Create(filename) 313 if err != nil { 314 log.Fatal(err) 315 } 316 defer f.Close() 317 318 var buf bytes.Buffer 319 320 err = tests.Execute(&buf, c) 321 if err != nil { 322 log.Fatal(err) 323 } 324 325 b, err := format.Source(buf.Bytes()) 326 if err != nil { 327 f.Write(buf.Bytes()) // This is here to debug bad format. 328 log.Fatalf("error formatting test for %q: %s", c.Name, err) 329 } 330 331 f.Write(b) 332 }