mirror of
https://github.com/golang/go.git
synced 2025-05-30 19:52:53 +00:00
cmd/yacc: replace units example with simpler expr example
The units example is nice but is covered by the Lucent license, which may be a concern for some people making a commercial source code distribution of Go. R=golang-dev, r CC=golang-dev https://golang.org/cl/13283045
This commit is contained in:
parent
ab38e2a498
commit
fdaf88ea5b
@ -2,9 +2,9 @@
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
units: yacc.go units.y
|
||||
go run yacc.go -p units_ units.y
|
||||
go build -o units y.go
|
||||
expr: yacc.go expr.y
|
||||
go run yacc.go -p expr expr.y
|
||||
go build -o expr y.go
|
||||
|
||||
clean:
|
||||
rm -f y.go y.output units
|
||||
rm -f y.go y.output expr
|
||||
|
@ -20,10 +20,8 @@ written in C and documented at
|
||||
Adepts of the original yacc will have no trouble adapting to this
|
||||
form of the tool.
|
||||
|
||||
The file units.y in this directory is a yacc grammar for a version of
|
||||
the Unix tool units, also written in Go and largely transliterated
|
||||
from the Plan 9 C version. It needs the flag "-p units_" (see
|
||||
below).
|
||||
The file expr.y in this directory is a yacc grammar for a very simple
|
||||
expression parser. It needs the flag "-p expr" (see below).
|
||||
|
||||
The generated parser is reentrant. Parse expects to be given an
|
||||
argument that conforms to the following interface:
|
||||
|
205
src/cmd/yacc/expr.y
Normal file
205
src/cmd/yacc/expr.y
Normal file
@ -0,0 +1,205 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// This is an example of a goyacc program.
|
||||
// To build it:
|
||||
// go tool yacc -p "expr" expr.y (produces y.go)
|
||||
// go build -o expr y.go
|
||||
// expr
|
||||
// > <type an expression>
|
||||
|
||||
%{
|
||||
|
||||
// This tag will be copied to the generated file to prevent that file
|
||||
// confusing a future build.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
num *big.Rat
|
||||
}
|
||||
|
||||
%type <num> expr expr1 expr2 expr3
|
||||
|
||||
%token <num> NUM
|
||||
|
||||
%%
|
||||
|
||||
top:
|
||||
expr
|
||||
{
|
||||
if $1.IsInt() {
|
||||
fmt.Println($1.Num().String())
|
||||
} else {
|
||||
fmt.Println($1.String())
|
||||
}
|
||||
}
|
||||
|
||||
expr:
|
||||
expr1
|
||||
| '+' expr
|
||||
{
|
||||
$$ = $2
|
||||
}
|
||||
| '-' expr
|
||||
{
|
||||
$$.Neg($2)
|
||||
}
|
||||
|
||||
expr1:
|
||||
expr2
|
||||
| expr1 '+' expr2
|
||||
{
|
||||
$$.Add($1, $3)
|
||||
}
|
||||
| expr1 '-' expr2
|
||||
{
|
||||
$$.Sub($1, $3)
|
||||
}
|
||||
|
||||
expr2:
|
||||
expr3
|
||||
| expr2 '*' expr3
|
||||
{
|
||||
$$.Mul($1, $3)
|
||||
}
|
||||
| expr2 '/' expr3
|
||||
{
|
||||
$$.Quo($1, $3)
|
||||
}
|
||||
|
||||
expr3:
|
||||
NUM
|
||||
| '(' expr ')'
|
||||
{
|
||||
$$ = $2
|
||||
}
|
||||
|
||||
|
||||
%%
|
||||
|
||||
// The parser expects the lexer to return 0 on EOF. Give it a name
|
||||
// for clarity.
|
||||
const eof = 0
|
||||
|
||||
// The parser uses the type <prefix>Lex as a lexer. It must provide
|
||||
// the methods Lex(*<prefix>SymType) int and Error(string).
|
||||
type exprLex struct {
|
||||
line []byte
|
||||
peek rune
|
||||
}
|
||||
|
||||
// The parser calls this method to get each new token. This
|
||||
// implementation returns operators and NUM.
|
||||
func (x *exprLex) Lex(yylval *exprSymType) int {
|
||||
for {
|
||||
c := x.next()
|
||||
switch c {
|
||||
case eof:
|
||||
return eof
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return x.num(c, yylval)
|
||||
case '+', '-', '*', '/', '(', ')':
|
||||
return int(c)
|
||||
|
||||
// Recognize Unicode multiplication and division
|
||||
// symbols, returning what the parser expects.
|
||||
case '×':
|
||||
return '*'
|
||||
case '÷':
|
||||
return '/'
|
||||
|
||||
case ' ', '\t', '\n':
|
||||
default:
|
||||
log.Printf("unrecognized character %q", c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lex a number.
|
||||
func (x *exprLex) num(c rune, yylval *exprSymType) int {
|
||||
add := func(b *bytes.Buffer, c rune) {
|
||||
if _, err := b.WriteRune(c); err != nil {
|
||||
log.Fatalf("WriteRune: %s", err)
|
||||
}
|
||||
}
|
||||
var b bytes.Buffer
|
||||
add(&b, c)
|
||||
L: for {
|
||||
c = x.next()
|
||||
switch c {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'e', 'E':
|
||||
add(&b, c)
|
||||
default:
|
||||
break L
|
||||
}
|
||||
}
|
||||
if c != eof {
|
||||
x.peek = c
|
||||
}
|
||||
yylval.num = &big.Rat{}
|
||||
_, ok := yylval.num.SetString(b.String())
|
||||
if !ok {
|
||||
log.Printf("bad number %q", b.String())
|
||||
return eof
|
||||
}
|
||||
return NUM
|
||||
}
|
||||
|
||||
// Return the next rune for the lexer.
|
||||
func (x *exprLex) next() rune {
|
||||
if x.peek != eof {
|
||||
r := x.peek
|
||||
x.peek = eof
|
||||
return r
|
||||
}
|
||||
if len(x.line) == 0 {
|
||||
return eof
|
||||
}
|
||||
c, size := utf8.DecodeRune(x.line)
|
||||
x.line = x.line[size:]
|
||||
if c == utf8.RuneError && size == 1 {
|
||||
log.Print("invalid utf8")
|
||||
return x.next()
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// The parser calls this method on a parse error.
|
||||
func (x *exprLex) Error(s string) {
|
||||
log.Printf("parse error: %s", s)
|
||||
}
|
||||
|
||||
func main() {
|
||||
in := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
if _, err := os.Stdout.WriteString("> "); err != nil {
|
||||
log.Fatalf("WriteString: %s", err)
|
||||
}
|
||||
line, err := in.ReadBytes('\n')
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("ReadBytes: %s", err)
|
||||
}
|
||||
|
||||
exprParse(&exprLex{line: line})
|
||||
}
|
||||
}
|
@ -1,576 +0,0 @@
|
||||
/ Plan 9's /lib/units
|
||||
/ http://plan9.bell-labs.com/sources/plan9/lib/units
|
||||
/
|
||||
/ Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
|
||||
/ Distributed under the terms of the Lucent Public License Version 1.02
|
||||
/ See http://plan9.bell-labs.com/plan9/license.html
|
||||
/
|
||||
/order of evaluation
|
||||
/ + -
|
||||
/ * /
|
||||
/ juxtaposition (meaning *)
|
||||
/ ¹ ² ³ ^
|
||||
/ | (meaning /)
|
||||
/ name number ()
|
||||
|
||||
/dimensions
|
||||
m #
|
||||
kg #
|
||||
sec #
|
||||
coul #
|
||||
candela #
|
||||
$ #
|
||||
radian #
|
||||
bit #
|
||||
erlang #
|
||||
°K #
|
||||
°C #
|
||||
°F #
|
||||
|
||||
/constants
|
||||
|
||||
π 3.14159265358979323846
|
||||
pi π
|
||||
c 2.997925e+8 m/sec
|
||||
g 9.80665 m/sec²
|
||||
au 1.49597871e+11 m
|
||||
mole 6.022169e+23
|
||||
e 1.6021917e-19 coul
|
||||
energy c²
|
||||
force g
|
||||
mercury 1.33322e+5 kg/m²sec²
|
||||
hg mercury
|
||||
h 6.62620e-34 m²kg/sec
|
||||
ℏ h/2 π
|
||||
hbar ℏ
|
||||
nonillion 1e30
|
||||
octillion 1e27
|
||||
septillion 1e24
|
||||
sextillion 1e21
|
||||
pentillion 1e18
|
||||
quadrillion 1e15
|
||||
trillion 1e12
|
||||
billion 1e9
|
||||
million 1e6
|
||||
thousand 1e3
|
||||
hundred 1e2
|
||||
|
||||
/dimensionless
|
||||
|
||||
° 1|180 π radian
|
||||
degree °
|
||||
circle 2 π radian
|
||||
turn 2 π radian
|
||||
grad .9 °
|
||||
arcdeg 1 °
|
||||
arcmin 1|60 °
|
||||
arcsec 1|3600 °
|
||||
ccs 1|36 erlang
|
||||
|
||||
steradian radian²
|
||||
sphere 4 π steradian
|
||||
sr steradian
|
||||
giga 1024 1024 1024
|
||||
|
||||
/Time
|
||||
|
||||
second sec
|
||||
s sec
|
||||
minute 60 sec
|
||||
min minute
|
||||
hour 60 min
|
||||
hr hour
|
||||
day 24 hr
|
||||
da day
|
||||
week 7 day
|
||||
year 365.24219879 day
|
||||
yr year
|
||||
month 1|12 year
|
||||
ms millisec
|
||||
us microsec
|
||||
|
||||
/Mass
|
||||
|
||||
gram millikg
|
||||
gm gram
|
||||
mg milligram
|
||||
metricton kilokg
|
||||
|
||||
/Avoirdupois
|
||||
|
||||
lb .45359237 kg
|
||||
lbf lb g
|
||||
pound lb
|
||||
ounce 1|16 lb
|
||||
oz ounce
|
||||
dram 1|16 oz
|
||||
dr dram
|
||||
grain 1|7000 lb
|
||||
gr grain
|
||||
shortton 2000 lb
|
||||
ton shortton
|
||||
longton 2240 lb
|
||||
|
||||
/Apothecary
|
||||
|
||||
scruple 20 grain
|
||||
apdram 60 grain
|
||||
apounce 480 grain
|
||||
troyounce apounce
|
||||
appound 5760 grain
|
||||
troypound appound
|
||||
|
||||
/Length
|
||||
|
||||
meter m
|
||||
cm centimeter
|
||||
mm millimeter
|
||||
km kilometer
|
||||
nm nanometer
|
||||
micron micrometer
|
||||
µ micrometer
|
||||
Å decinanometer
|
||||
angstrom Å
|
||||
|
||||
inch 2.54 cm
|
||||
" inch
|
||||
in inch
|
||||
inches inch
|
||||
' 12"
|
||||
foot 12 in
|
||||
feet foot
|
||||
ft foot
|
||||
yard 3 ft
|
||||
yd yard
|
||||
rod 5.5 yd
|
||||
rd rod
|
||||
mile 5280 ft
|
||||
mi mile
|
||||
|
||||
british 1200|3937 m/ft
|
||||
nmile 1852 m
|
||||
|
||||
acre 4840 yd²
|
||||
|
||||
cc cm³
|
||||
liter kilocc
|
||||
ml milliliter
|
||||
|
||||
/US Liquid
|
||||
|
||||
gallon 231 in³
|
||||
imperial 1.20095
|
||||
epa 0.8
|
||||
gal gallon
|
||||
quart 1|4 gal
|
||||
qt quart
|
||||
pint 1|2 qt
|
||||
pt pint
|
||||
|
||||
floz 1|16 pt
|
||||
fldr 1|8 floz
|
||||
|
||||
/US Dry
|
||||
|
||||
dry 268.8025 in³/gallon
|
||||
peck 8 dry quart
|
||||
pk peck
|
||||
bushel 4 peck
|
||||
bu bushel
|
||||
|
||||
/British
|
||||
|
||||
brgallon 277.420 in³
|
||||
brquart 1|4 brgallon
|
||||
brpint 1|2 brquart
|
||||
brfloz 1|20 brpint
|
||||
brpeck 554.84 in³
|
||||
brbushel 4 brpeck
|
||||
|
||||
/Energy Work
|
||||
|
||||
newton kg m/sec²
|
||||
nt newton
|
||||
joule nt m
|
||||
cal 4.1868 joule
|
||||
|
||||
/Electrical
|
||||
|
||||
coulomb coul
|
||||
ampere coul/sec
|
||||
amp ampere
|
||||
watt joule/sec
|
||||
volt watt/amp
|
||||
Ω volt/amp
|
||||
ohm Ω
|
||||
mho 1/Ω
|
||||
farad coul/volt
|
||||
henry sec²/farad
|
||||
weber volt sec
|
||||
|
||||
/Light
|
||||
|
||||
cd candela
|
||||
lumen cd sr
|
||||
lux cd sr/m²
|
||||
|
||||
/ MONEY DATE
|
||||
/ Wed Aug 29, 2012
|
||||
|
||||
argentinapeso $ 0.2160
|
||||
australiadollar $ 1.0372
|
||||
boliviaboliviano $ 0.1427
|
||||
brazilreal $ 0.4872
|
||||
britainpound $ 1.5843
|
||||
canadadollar $ 1.0117
|
||||
chilepeso $ 1 | 480.6
|
||||
chinayuan $ 0.1574
|
||||
colombiapeso $ 1 | 1834
|
||||
czechkoruna $ 0.0506
|
||||
denmarkkrone $ 0.1681
|
||||
dominicanpeso $ 0.0256
|
||||
egyptpound $ 0.1640
|
||||
elsalvadorcolon $ 1 | 8.75
|
||||
europeuro $ 1.2528
|
||||
guatemalaquetzal $ 0.1290
|
||||
honduraslempira $ 0.0511
|
||||
hongkongdollar $ 0.1289
|
||||
hungaryforint $ 1 | 226.5
|
||||
indiarupee $ 0.0180
|
||||
indonesiarupiah $ 1 | 9540
|
||||
israelshekel $ 0.2479
|
||||
japanyen $ 0.0127
|
||||
kenyashilling $ 0.0119
|
||||
kuwaitdinar $ 3.5456
|
||||
lebanonpound $ 1 | 1505.5
|
||||
malaysiaringgit $ 0.3204
|
||||
mexicopeso $ 0.0754
|
||||
newzealanddollar $ 0.8035
|
||||
nicaraguacordoba $ 0.0421
|
||||
norwaykrone $ 0.1717
|
||||
pakistanrupee $ 0.0106
|
||||
paraguayguarani $ 1 | 4415
|
||||
perunewsol $ 0.3832
|
||||
philippinespeso $ 0.0236
|
||||
polandzloty $ 0.3001
|
||||
russiaruble $ 0.0311
|
||||
saudiarabiariyal $ 1 | 3.75
|
||||
singaporedollar $ 0.7976
|
||||
slovakkoruna 1 | 30.126 europeuro
|
||||
southafricarand $ 0.1188
|
||||
southkoreawon $ 1 | 1135
|
||||
swedenkrona $ 0.1502
|
||||
switzerlandfranc $ 1.0431
|
||||
taiwandollar $ 0.0334
|
||||
thailandbaht $ 0.0319
|
||||
turkeynewlira $ 0.5504
|
||||
uaedirham $ 0.2723
|
||||
uruguaynewpeso $ 0.0465
|
||||
vietnamdong $ 1 | 20865
|
||||
|
||||
/ END MONEY
|
||||
|
||||
€ europeuro
|
||||
£ britainpound
|
||||
¥ japanyen
|
||||
dollar $
|
||||
|
||||
baht thailandbaht
|
||||
brpound britainpound
|
||||
dirham uaedirham
|
||||
euro europeuro
|
||||
forint hungaryforint
|
||||
krona swedenkrona
|
||||
peso mexicopeso
|
||||
rand southafricarand
|
||||
real brazilreal
|
||||
yuan chinayuan
|
||||
ringgit malaysiaringgit
|
||||
riyal saudiarabiariyal
|
||||
ruble russiaruble
|
||||
rupee indiarupee
|
||||
rupiah indonesiarupiah
|
||||
shekel israelshekel
|
||||
sol perunewsol
|
||||
won southkoreawon
|
||||
yen japanyen
|
||||
zloty polandzloty
|
||||
|
||||
usdollar dollar
|
||||
sterling britainpound | pound
|
||||
poundsterling britainpound
|
||||
|
||||
/bits
|
||||
|
||||
baud bit/sec
|
||||
byte 8 bit
|
||||
short 2 byte
|
||||
long 4 byte
|
||||
vlong 8 bytes
|
||||
frame 2352 byte
|
||||
|
||||
/Australian liquid measure
|
||||
|
||||
pony 7 brfloz
|
||||
midie 10 brfloz
|
||||
pot midie
|
||||
handle midie
|
||||
schooner 15 brfloz
|
||||
jug 40 brfloz
|
||||
resch midie
|
||||
alf midie
|
||||
tinny 13 brfloz
|
||||
stubby tinny
|
||||
twisty 250 ml
|
||||
longneck 2 tinny
|
||||
slab 24 tinny
|
||||
sixpack 6 tinny
|
||||
nip brfloz
|
||||
|
||||
/wine
|
||||
winebottle 750 ml
|
||||
balthazar 16 winebottle
|
||||
jeroboam 4 winebottle
|
||||
magnum 2 winebottle
|
||||
mathusalem 8 winebottle
|
||||
methuselah 8 winebottle
|
||||
nebuchadnezzar 20 winebottle
|
||||
rehoboam 6 winebottle
|
||||
salmanazar 12 winebottle
|
||||
split 0.25 winebottle
|
||||
jigger 1.5 floz
|
||||
|
||||
/Trivia
|
||||
|
||||
% 1|100
|
||||
admiraltyknot 6080 ft/hr
|
||||
ε₀ (1e-9/36π) farad/m
|
||||
α (1/4π ε₀) e²/ℏ c
|
||||
alpha α
|
||||
apostilb cd/π m²
|
||||
are 1e+2 m²
|
||||
arpentcan 27.52 mi
|
||||
arpentlin 191.835 ft
|
||||
astronomicalunit au
|
||||
atmosphere 1.01325e+5 nt/m²
|
||||
atm atmosphere
|
||||
atomicmassunit 1.66044e-27 kg
|
||||
amu atomicmassunit
|
||||
bag 94 lb
|
||||
bakersdozen 13
|
||||
bar 1e+5 nt/m²
|
||||
barie 1e-1 nt/m²
|
||||
barleycorn 1|3 in
|
||||
barn 1e-28 m²
|
||||
barrel 42 gal
|
||||
barye 1e-1 nt/m²
|
||||
bev 1e+9 e volt
|
||||
biot 10 amp
|
||||
blondel cd/π m²
|
||||
boardfoot 144 in³
|
||||
bolt 40 yd
|
||||
bottommeasure 1|40 in
|
||||
britishthermalunit 1.05506e+3 joule
|
||||
btu britishthermalunit
|
||||
quad 1.0e+15 btu
|
||||
refrigeration 12000 btu/ton hour
|
||||
buck dollar
|
||||
cable 720 ft
|
||||
caliber 1e-2 in
|
||||
calorie cal
|
||||
carat 205 mg
|
||||
cent centidollar
|
||||
cental 100 lb
|
||||
centesimalminute 1e-2 grad
|
||||
centesimalsecond 1e-4 grad
|
||||
century 100 year
|
||||
cfs ft³/sec
|
||||
chain 66 ft
|
||||
circularinch 1|4 π in²
|
||||
circularmil 1e-6|4 π in²
|
||||
clusec 1e-8 mm hg m³/s
|
||||
coomb 4 bu
|
||||
cord 128 ft³
|
||||
cordfoot cord
|
||||
crith 9.06e-2 gm
|
||||
cubit 18 in
|
||||
cup 1|2 pt
|
||||
curie 3.7e+10/sec
|
||||
cusec ft³/sec
|
||||
dalton amu
|
||||
decade 10 yr
|
||||
degK °K
|
||||
degC °C
|
||||
degF °F
|
||||
dipotre 1/m
|
||||
displacementton 35 ft³
|
||||
doppelzentner 100 kg
|
||||
dozen 12
|
||||
drop .03 cm³
|
||||
dyne cm gm/sec²
|
||||
electronvolt e volt
|
||||
ell 45 in
|
||||
engineerschain 100 ft
|
||||
engineerslink 100|100 ft
|
||||
equivalentfootcandle lumen/π ft²
|
||||
equivalentlux lumen/π m²
|
||||
equivalentphot cd/π cm²
|
||||
erg cm²gm/sec²
|
||||
ev e volt
|
||||
faraday 9.652e+4 coul
|
||||
fathom 6 ft
|
||||
fermi 1e-15 m
|
||||
fifth 4|5 qt
|
||||
fin 5 dollar
|
||||
finger 7|8 in
|
||||
firkin 9 gal
|
||||
footcandle lumen/ft²
|
||||
footlambert cd/π ft²
|
||||
fortnight 14 da
|
||||
franklin 3.33564e-10 coul
|
||||
frigorie kilocal
|
||||
furlong 220 yd
|
||||
galileo 1e-2 m/sec²
|
||||
gamma 1e-9 weber/m²
|
||||
gauss 1e-4 weber/m²
|
||||
geodeticfoot british ft
|
||||
geographicalmile 1852 m
|
||||
gilbert 7.95775e-1 amp
|
||||
gill 1|4 pt
|
||||
gross 144
|
||||
gunterschain 22 yd
|
||||
hand 4 in
|
||||
hectare 1e+4 m²
|
||||
hefnercandle .92 cd
|
||||
hertz 1/sec
|
||||
hogshead 2 barrel
|
||||
hd hogshead
|
||||
homestead 1|4 mi²
|
||||
horsepower 550 ft lb g/sec
|
||||
hp horsepower
|
||||
hyl gm force sec²/m
|
||||
hz 1/sec
|
||||
imaginarycubicfoot 1.4 ft³
|
||||
karat 1|24
|
||||
kcal kilocal
|
||||
kcalorie kilocal
|
||||
kev 1e+3 e volt
|
||||
key kg
|
||||
khz 1e+3/sec
|
||||
kilderkin 18 gal
|
||||
knot nmile/hr
|
||||
kwh kilowatt hour
|
||||
lambert cd/π cm²
|
||||
langley cal/cm²
|
||||
last 80 bu
|
||||
league 3 mi
|
||||
lightyear c yr
|
||||
ly lightyear
|
||||
lightsecond c sec
|
||||
line 1|12 in
|
||||
link 66|100 ft
|
||||
longhundredweight 112 lb
|
||||
longquarter 28 lb
|
||||
lusec 1e-6 mm hg m³/s
|
||||
mach 331.46 m/sec
|
||||
marineleague 3 nmile
|
||||
maxwell 1e-8 weber
|
||||
metriccarat 200 mg
|
||||
mev 1e+6 e volt
|
||||
mgd megagal/day
|
||||
mh millihenry
|
||||
mhz 1e+6/sec
|
||||
mil 1e-3 in
|
||||
millennium 1000 year
|
||||
minersinch 1.5 ft³/min
|
||||
minim 1|60 fldr
|
||||
mo month
|
||||
mpg mile/gal
|
||||
mph mile/hr
|
||||
nail 1|16 yd
|
||||
nauticalmile nmile
|
||||
nit cd/m²
|
||||
noggin 1|8 qt
|
||||
nox 1e-3 lux
|
||||
ns nanosec
|
||||
oersted 2.5e+2 amp/m π
|
||||
oe oersted
|
||||
pace 36 in
|
||||
palm 3 in
|
||||
parasang 3.5 mi
|
||||
parsec au radian/arcsec
|
||||
pascal nt/m²
|
||||
pc parsec
|
||||
pennyweight 1|20 oz
|
||||
percent %
|
||||
perch rd
|
||||
pf picofarad
|
||||
phot lumen/cm²
|
||||
pica 1|6 in
|
||||
pieze 1e+3 nt/m²
|
||||
pipe 4 barrel
|
||||
point 1|72 in
|
||||
poise gm/cm sec
|
||||
pole rd
|
||||
poundal ft lb/sec²
|
||||
pdl poundal
|
||||
proof 1/200
|
||||
psi lb g/in²
|
||||
quarter 9 in
|
||||
quartersection 1|4 mi²
|
||||
quintal 100 kg
|
||||
quire 25
|
||||
rad 100 erg/gm
|
||||
ream 500
|
||||
registerton 100 ft³
|
||||
rhe 10 m²/nt sec
|
||||
rontgen 2.58e-4 curie/kg
|
||||
rood 1.21e+3 yd
|
||||
rope 20 ft
|
||||
rutherford 1e+6/sec
|
||||
rydberg 1.36054e+1 ev
|
||||
sabin 1 ft²
|
||||
sack 3 bu
|
||||
seam 8 bu
|
||||
section mi²
|
||||
shippington 40 ft³
|
||||
shorthundredweight 100 lb
|
||||
shortquarter 25 lb
|
||||
siemens 1/Ω
|
||||
σ 5.66956e-5 erg/cm² °K^4 sec
|
||||
sigma σ
|
||||
skein 120 yd
|
||||
skot 1e-3 apostilb
|
||||
slug lb g sec²/ft
|
||||
span 9 in
|
||||
spat 4 π sr
|
||||
spindle 14400 yd
|
||||
square 100 ft²
|
||||
squidge 1|972 inch
|
||||
catsquidge 1|432 inch
|
||||
stere m³
|
||||
sthene 1e+3 nt
|
||||
stilb cd/cm²
|
||||
stoke 1e-4 m²/sec
|
||||
stone 14 lb
|
||||
strike 2 bu
|
||||
surveyfoot british ft
|
||||
surveyorschain 66 ft
|
||||
surveyorslink 66|100 ft
|
||||
tablespoon 4 fldr
|
||||
teaspoon 4|3 fldr
|
||||
tesla weber/m²
|
||||
therm 1e+5 btu
|
||||
thermie 1e+6 cal
|
||||
timberfoot ft³
|
||||
tnt 4.6e+6 m²/sec²
|
||||
tonne 1e+6 gm
|
||||
torr mm hg
|
||||
township 36 mi²
|
||||
tun 8 barrel
|
||||
water .22491|2.54 kg/m²sec²
|
||||
wey 40 bu
|
||||
weymass 252 lb
|
||||
Xunit 1.00202e-13 m
|
||||
k 1.38047e-16 erg/°K
|
||||
foal 9223372036854775807
|
@ -1,768 +0,0 @@
|
||||
// Derived from Plan 9's /sys/src/cmd/units.y
|
||||
// http://plan9.bell-labs.com/sources/plan9/sys/src/cmd/units.y
|
||||
//
|
||||
// Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
|
||||
// Portions Copyright 2009 The Go Authors. All Rights Reserved.
|
||||
// Distributed under the terms of the Lucent Public License Version 1.02
|
||||
// See http://plan9.bell-labs.com/plan9/license.html
|
||||
|
||||
// Generate parser with prefix "units_":
|
||||
// go tool yacc -p "units_"
|
||||
|
||||
%{
|
||||
|
||||
// This tag will end up in the generated y.go, so that forgetting
|
||||
// 'make clean' does not fail the next build.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// units.y
|
||||
// example of a Go yacc program
|
||||
// usage is
|
||||
// go tool yacc -p "units_" units.y (produces y.go)
|
||||
// go build -o units y.go
|
||||
// ./units $GOROOT/src/cmd/yacc/units.txt
|
||||
// you have: c
|
||||
// you want: furlongs/fortnight
|
||||
// * 1.8026178e+12
|
||||
// / 5.5474878e-13
|
||||
// you have:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"runtime"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
Ndim = 15 // number of dimensions
|
||||
Maxe = 695 // log of largest number
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
vval float64
|
||||
dim [Ndim]int8
|
||||
}
|
||||
|
||||
type Var struct {
|
||||
name string
|
||||
node Node
|
||||
}
|
||||
|
||||
var fi *bufio.Reader // input
|
||||
var fund [Ndim]*Var // names of fundamental units
|
||||
var line string // current input line
|
||||
var lineno int // current input line number
|
||||
var linep int // index to next rune in unput
|
||||
var nerrors int // error count
|
||||
var one Node // constant one
|
||||
var peekrune rune // backup runt from input
|
||||
var retnode1 Node
|
||||
var retnode2 Node
|
||||
var retnode Node
|
||||
var sym string
|
||||
var vflag bool
|
||||
%}
|
||||
|
||||
%union {
|
||||
node Node
|
||||
vvar *Var
|
||||
numb int
|
||||
vval float64
|
||||
}
|
||||
|
||||
%type <node> prog expr expr0 expr1 expr2 expr3 expr4
|
||||
|
||||
%token <vval> VÄL // dieresis to test UTF-8
|
||||
%token <vvar> VAR
|
||||
%token <numb> _SUP // tests leading underscore in token name
|
||||
%%
|
||||
prog:
|
||||
':' VAR expr
|
||||
{
|
||||
var f int
|
||||
f = int($2.node.dim[0])
|
||||
$2.node = $3
|
||||
$2.node.dim[0] = 1
|
||||
if f != 0 {
|
||||
Errorf("redefinition of %v", $2.name)
|
||||
} else if vflag {
|
||||
fmt.Printf("%v\t%v\n", $2.name, &$2.node)
|
||||
}
|
||||
}
|
||||
| ':' VAR '#'
|
||||
{
|
||||
var f, i int
|
||||
for i = 1; i < Ndim; i++ {
|
||||
if fund[i] == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i >= Ndim {
|
||||
Error("too many dimensions")
|
||||
i = Ndim - 1
|
||||
}
|
||||
fund[i] = $2
|
||||
f = int($2.node.dim[0])
|
||||
$2.node = one
|
||||
$2.node.dim[0] = 1
|
||||
$2.node.dim[i] = 1
|
||||
if f != 0 {
|
||||
Errorf("redefinition of %v", $2.name)
|
||||
} else if vflag {
|
||||
fmt.Printf("%v\t#\n", $2.name)
|
||||
}
|
||||
}
|
||||
| ':'
|
||||
{
|
||||
}
|
||||
| '?' expr
|
||||
{
|
||||
retnode1 = $2
|
||||
}
|
||||
| '?'
|
||||
{
|
||||
retnode1 = one
|
||||
}
|
||||
|
||||
expr:
|
||||
expr4
|
||||
| expr '+' expr4
|
||||
{
|
||||
add(&$$, &$1, &$3)
|
||||
}
|
||||
| expr '-' expr4
|
||||
{
|
||||
sub(&$$, &$1, &$3)
|
||||
}
|
||||
|
||||
expr4:
|
||||
expr3
|
||||
| expr4 '*' expr3
|
||||
{
|
||||
mul(&$$, &$1, &$3)
|
||||
}
|
||||
| expr4 '/' expr3
|
||||
{
|
||||
div(&$$, &$1, &$3)
|
||||
}
|
||||
|
||||
expr3:
|
||||
expr2
|
||||
| expr3 expr2
|
||||
{
|
||||
mul(&$$, &$1, &$2)
|
||||
}
|
||||
|
||||
expr2:
|
||||
expr1
|
||||
| expr2 _SUP
|
||||
{
|
||||
xpn(&$$, &$1, $2)
|
||||
}
|
||||
| expr2 '^' expr1
|
||||
{
|
||||
var i int
|
||||
for i = 1; i < Ndim; i++ {
|
||||
if $3.dim[i] != 0 {
|
||||
Error("exponent has units")
|
||||
$$ = $1
|
||||
break
|
||||
}
|
||||
}
|
||||
if i >= Ndim {
|
||||
i = int($3.vval)
|
||||
if float64(i) != $3.vval {
|
||||
Error("exponent not integral")
|
||||
}
|
||||
xpn(&$$, &$1, i)
|
||||
}
|
||||
}
|
||||
|
||||
expr1:
|
||||
expr0
|
||||
| expr1 '|' expr0
|
||||
{
|
||||
div(&$$, &$1, &$3)
|
||||
}
|
||||
|
||||
expr0:
|
||||
VAR
|
||||
{
|
||||
if $1.node.dim[0] == 0 {
|
||||
Errorf("undefined %v", $1.name)
|
||||
$$ = one
|
||||
} else {
|
||||
$$ = $1.node
|
||||
}
|
||||
}
|
||||
| VÄL
|
||||
{
|
||||
$$ = one
|
||||
$$.vval = $1
|
||||
}
|
||||
| '(' expr ')'
|
||||
{
|
||||
$$ = $2
|
||||
}
|
||||
%%
|
||||
|
||||
type UnitsLex int
|
||||
|
||||
func (UnitsLex) Lex(yylval *units_SymType) int {
|
||||
var c rune
|
||||
var i int
|
||||
|
||||
c = peekrune
|
||||
peekrune = ' '
|
||||
|
||||
loop:
|
||||
if (c >= '0' && c <= '9') || c == '.' {
|
||||
goto numb
|
||||
}
|
||||
if ralpha(c) {
|
||||
goto alpha
|
||||
}
|
||||
switch c {
|
||||
case ' ', '\t':
|
||||
c = getrune()
|
||||
goto loop
|
||||
case '×':
|
||||
return '*'
|
||||
case '÷':
|
||||
return '/'
|
||||
case '¹', 'ⁱ':
|
||||
yylval.numb = 1
|
||||
return _SUP
|
||||
case '²', '':
|
||||
yylval.numb = 2
|
||||
return _SUP
|
||||
case '³', '':
|
||||
yylval.numb = 3
|
||||
return _SUP
|
||||
}
|
||||
return int(c)
|
||||
|
||||
alpha:
|
||||
sym = ""
|
||||
for i = 0; ; i++ {
|
||||
sym += string(c)
|
||||
c = getrune()
|
||||
if !ralpha(c) {
|
||||
break
|
||||
}
|
||||
}
|
||||
peekrune = c
|
||||
yylval.vvar = lookup(0)
|
||||
return VAR
|
||||
|
||||
numb:
|
||||
sym = ""
|
||||
for i = 0; ; i++ {
|
||||
sym += string(c)
|
||||
c = getrune()
|
||||
if !rdigit(c) {
|
||||
break
|
||||
}
|
||||
}
|
||||
peekrune = c
|
||||
f, err := strconv.ParseFloat(sym, 64)
|
||||
if err != nil {
|
||||
fmt.Printf("error converting %v\n", sym)
|
||||
f = 0
|
||||
}
|
||||
yylval.vval = f
|
||||
return VÄL
|
||||
}
|
||||
|
||||
func (UnitsLex) Error(s string) {
|
||||
Errorf("syntax error, last name: %v", sym)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var file string
|
||||
|
||||
flag.BoolVar(&vflag, "v", false, "verbose")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
file = filepath.Join(runtime.GOROOT(), "src/cmd/yacc/units.txt")
|
||||
if flag.NArg() > 0 {
|
||||
file = flag.Arg(0)
|
||||
} else if file == "" {
|
||||
fmt.Fprintf(os.Stderr, "cannot find data file units.txt; provide it as argument or set $GOROOT\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error opening %v: %v\n", file, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fi = bufio.NewReader(f)
|
||||
|
||||
one.vval = 1
|
||||
|
||||
/*
|
||||
* read the 'units' file to
|
||||
* develop a database
|
||||
*/
|
||||
lineno = 0
|
||||
for {
|
||||
lineno++
|
||||
if readline() {
|
||||
break
|
||||
}
|
||||
if len(line) == 0 || line[0] == '/' {
|
||||
continue
|
||||
}
|
||||
peekrune = ':'
|
||||
units_Parse(UnitsLex(0))
|
||||
}
|
||||
|
||||
/*
|
||||
* read the console to
|
||||
* print ratio of pairs
|
||||
*/
|
||||
fi = bufio.NewReader(os.NewFile(0, "stdin"))
|
||||
|
||||
lineno = 0
|
||||
for {
|
||||
if (lineno & 1) != 0 {
|
||||
fmt.Printf("you want: ")
|
||||
} else {
|
||||
fmt.Printf("you have: ")
|
||||
}
|
||||
if readline() {
|
||||
break
|
||||
}
|
||||
peekrune = '?'
|
||||
nerrors = 0
|
||||
units_Parse(UnitsLex(0))
|
||||
if nerrors != 0 {
|
||||
continue
|
||||
}
|
||||
if (lineno & 1) != 0 {
|
||||
if specialcase(&retnode, &retnode2, &retnode1) {
|
||||
fmt.Printf("\tis %v\n", &retnode)
|
||||
} else {
|
||||
div(&retnode, &retnode2, &retnode1)
|
||||
fmt.Printf("\t* %v\n", &retnode)
|
||||
div(&retnode, &retnode1, &retnode2)
|
||||
fmt.Printf("\t/ %v\n", &retnode)
|
||||
}
|
||||
} else {
|
||||
retnode2 = retnode1
|
||||
}
|
||||
lineno++
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
/*
|
||||
* all characters that have some
|
||||
* meaning. rest are usable as names
|
||||
*/
|
||||
func ralpha(c rune) bool {
|
||||
switch c {
|
||||
case 0, '+', '-', '*', '/', '[', ']', '(', ')',
|
||||
'^', ':', '?', ' ', '\t', '.', '|', '#',
|
||||
'×', '÷', '¹', 'ⁱ', '²', '', '³', '':
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
* number forming character
|
||||
*/
|
||||
func rdigit(c rune) bool {
|
||||
switch c {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'.', 'e', '+', '-':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Errorf(s string, v ...interface{}) {
|
||||
fmt.Printf("%v: %v\n\t", lineno, line)
|
||||
fmt.Printf(s, v...)
|
||||
fmt.Printf("\n")
|
||||
|
||||
nerrors++
|
||||
if nerrors > 5 {
|
||||
fmt.Printf("too many errors\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func Error(s string) {
|
||||
Errorf("%s", s)
|
||||
}
|
||||
|
||||
func add(c, a, b *Node) {
|
||||
var i int
|
||||
var d int8
|
||||
|
||||
for i = 0; i < Ndim; i++ {
|
||||
d = a.dim[i]
|
||||
c.dim[i] = d
|
||||
if d != b.dim[i] {
|
||||
Error("add must be like units")
|
||||
}
|
||||
}
|
||||
c.vval = fadd(a.vval, b.vval)
|
||||
}
|
||||
|
||||
func sub(c, a, b *Node) {
|
||||
var i int
|
||||
var d int8
|
||||
|
||||
for i = 0; i < Ndim; i++ {
|
||||
d = a.dim[i]
|
||||
c.dim[i] = d
|
||||
if d != b.dim[i] {
|
||||
Error("sub must be like units")
|
||||
}
|
||||
}
|
||||
c.vval = fadd(a.vval, -b.vval)
|
||||
}
|
||||
|
||||
func mul(c, a, b *Node) {
|
||||
var i int
|
||||
|
||||
for i = 0; i < Ndim; i++ {
|
||||
c.dim[i] = a.dim[i] + b.dim[i]
|
||||
}
|
||||
c.vval = fmul(a.vval, b.vval)
|
||||
}
|
||||
|
||||
func div(c, a, b *Node) {
|
||||
var i int
|
||||
|
||||
for i = 0; i < Ndim; i++ {
|
||||
c.dim[i] = a.dim[i] - b.dim[i]
|
||||
}
|
||||
c.vval = fdiv(a.vval, b.vval)
|
||||
}
|
||||
|
||||
func xpn(c, a *Node, b int) {
|
||||
var i int
|
||||
|
||||
*c = one
|
||||
if b < 0 {
|
||||
b = -b
|
||||
for i = 0; i < b; i++ {
|
||||
div(c, c, a)
|
||||
}
|
||||
} else {
|
||||
for i = 0; i < b; i++ {
|
||||
mul(c, c, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func specialcase(c, a, b *Node) bool {
|
||||
var i int
|
||||
var d, d1, d2 int8
|
||||
|
||||
d1 = 0
|
||||
d2 = 0
|
||||
for i = 1; i < Ndim; i++ {
|
||||
d = a.dim[i]
|
||||
if d != 0 {
|
||||
if d != 1 || d1 != 0 {
|
||||
return false
|
||||
}
|
||||
d1 = int8(i)
|
||||
}
|
||||
d = b.dim[i]
|
||||
if d != 0 {
|
||||
if d != 1 || d2 != 0 {
|
||||
return false
|
||||
}
|
||||
d2 = int8(i)
|
||||
}
|
||||
}
|
||||
if d1 == 0 || d2 == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if fund[d1].name == "°C" && fund[d2].name == "°F" &&
|
||||
b.vval == 1 {
|
||||
for ll := 0; ll < len(c.dim); ll++ {
|
||||
c.dim[ll] = b.dim[ll]
|
||||
}
|
||||
c.vval = a.vval*9./5. + 32.
|
||||
return true
|
||||
}
|
||||
|
||||
if fund[d1].name == "°F" && fund[d2].name == "°C" &&
|
||||
b.vval == 1 {
|
||||
for ll := 0; ll < len(c.dim); ll++ {
|
||||
c.dim[ll] = b.dim[ll]
|
||||
}
|
||||
c.vval = (a.vval - 32.) * 5. / 9.
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func printdim(str string, d, n int) string {
|
||||
var v *Var
|
||||
|
||||
if n != 0 {
|
||||
v = fund[d]
|
||||
if v != nil {
|
||||
str += fmt.Sprintf("%v", v.name)
|
||||
} else {
|
||||
str += fmt.Sprintf("[%d]", d)
|
||||
}
|
||||
switch n {
|
||||
case 1:
|
||||
break
|
||||
case 2:
|
||||
str += "²"
|
||||
case 3:
|
||||
str += "³"
|
||||
default:
|
||||
str += fmt.Sprintf("^%d", n)
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func (n Node) String() string {
|
||||
var str string
|
||||
var f, i, d int
|
||||
|
||||
str = fmt.Sprintf("%.7e ", n.vval)
|
||||
|
||||
f = 0
|
||||
for i = 1; i < Ndim; i++ {
|
||||
d = int(n.dim[i])
|
||||
if d > 0 {
|
||||
str = printdim(str, i, d)
|
||||
} else if d < 0 {
|
||||
f = 1
|
||||
}
|
||||
}
|
||||
|
||||
if f != 0 {
|
||||
str += " /"
|
||||
for i = 1; i < Ndim; i++ {
|
||||
d = int(n.dim[i])
|
||||
if d < 0 {
|
||||
str = printdim(str, i, -d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
func (v *Var) String() string {
|
||||
var str string
|
||||
str = fmt.Sprintf("%v %v", v.name, v.node)
|
||||
return str
|
||||
}
|
||||
|
||||
func readline() bool {
|
||||
s, err := fi.ReadString('\n')
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
line = s
|
||||
linep = 0
|
||||
return false
|
||||
}
|
||||
|
||||
func getrune() rune {
|
||||
var c rune
|
||||
var n int
|
||||
|
||||
if linep >= len(line) {
|
||||
return 0
|
||||
}
|
||||
c, n = utf8.DecodeRuneInString(line[linep:len(line)])
|
||||
linep += n
|
||||
if c == '\n' {
|
||||
c = 0
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
var symmap = make(map[string]*Var) // symbol table
|
||||
|
||||
func lookup(f int) *Var {
|
||||
var p float64
|
||||
var w *Var
|
||||
|
||||
v, ok := symmap[sym]
|
||||
if ok {
|
||||
return v
|
||||
}
|
||||
if f != 0 {
|
||||
return nil
|
||||
}
|
||||
v = new(Var)
|
||||
v.name = sym
|
||||
symmap[sym] = v
|
||||
|
||||
p = 1
|
||||
for {
|
||||
p = fmul(p, pname())
|
||||
if p == 0 {
|
||||
break
|
||||
}
|
||||
w = lookup(1)
|
||||
if w != nil {
|
||||
v.node = w.node
|
||||
v.node.vval = fmul(v.node.vval, p)
|
||||
break
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
type Prefix struct {
|
||||
vval float64
|
||||
name string
|
||||
}
|
||||
|
||||
var prefix = []Prefix{ // prefix table
|
||||
{1e-24, "yocto"},
|
||||
{1e-21, "zepto"},
|
||||
{1e-18, "atto"},
|
||||
{1e-15, "femto"},
|
||||
{1e-12, "pico"},
|
||||
{1e-9, "nano"},
|
||||
{1e-6, "micro"},
|
||||
{1e-6, "μ"},
|
||||
{1e-3, "milli"},
|
||||
{1e-2, "centi"},
|
||||
{1e-1, "deci"},
|
||||
{1e1, "deka"},
|
||||
{1e2, "hecta"},
|
||||
{1e2, "hecto"},
|
||||
{1e3, "kilo"},
|
||||
{1e6, "mega"},
|
||||
{1e6, "meg"},
|
||||
{1e9, "giga"},
|
||||
{1e12, "tera"},
|
||||
{1e15, "peta"},
|
||||
{1e18, "exa"},
|
||||
{1e21, "zetta"},
|
||||
{1e24, "yotta"},
|
||||
}
|
||||
|
||||
func pname() float64 {
|
||||
var i, j, n int
|
||||
var s string
|
||||
|
||||
/*
|
||||
* rip off normal prefixs
|
||||
*/
|
||||
n = len(sym)
|
||||
for i = 0; i < len(prefix); i++ {
|
||||
s = prefix[i].name
|
||||
j = len(s)
|
||||
if j < n && sym[0:j] == s {
|
||||
sym = sym[j:n]
|
||||
return prefix[i].vval
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rip off 's' suffixes
|
||||
*/
|
||||
if n > 2 && sym[n-1] == 's' {
|
||||
sym = sym[0 : n-1]
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// careful multiplication
|
||||
// exponents (log) are checked before multiply
|
||||
func fmul(a, b float64) float64 {
|
||||
var l float64
|
||||
|
||||
if b <= 0 {
|
||||
if b == 0 {
|
||||
return 0
|
||||
}
|
||||
l = math.Log(-b)
|
||||
} else {
|
||||
l = math.Log(b)
|
||||
}
|
||||
|
||||
if a <= 0 {
|
||||
if a == 0 {
|
||||
return 0
|
||||
}
|
||||
l += math.Log(-a)
|
||||
} else {
|
||||
l += math.Log(a)
|
||||
}
|
||||
|
||||
if l > Maxe {
|
||||
Error("overflow in multiply")
|
||||
return 1
|
||||
}
|
||||
if l < -Maxe {
|
||||
Error("underflow in multiply")
|
||||
return 0
|
||||
}
|
||||
return a * b
|
||||
}
|
||||
|
||||
// careful division
|
||||
// exponents (log) are checked before divide
|
||||
func fdiv(a, b float64) float64 {
|
||||
var l float64
|
||||
|
||||
if b <= 0 {
|
||||
if b == 0 {
|
||||
Errorf("division by zero: %v %v", a, b)
|
||||
return 1
|
||||
}
|
||||
l = math.Log(-b)
|
||||
} else {
|
||||
l = math.Log(b)
|
||||
}
|
||||
|
||||
if a <= 0 {
|
||||
if a == 0 {
|
||||
return 0
|
||||
}
|
||||
l -= math.Log(-a)
|
||||
} else {
|
||||
l -= math.Log(a)
|
||||
}
|
||||
|
||||
if l < -Maxe {
|
||||
Error("overflow in divide")
|
||||
return 1
|
||||
}
|
||||
if l > Maxe {
|
||||
Error("underflow in divide")
|
||||
return 0
|
||||
}
|
||||
return a / b
|
||||
}
|
||||
|
||||
func fadd(a, b float64) float64 {
|
||||
return a + b
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user