line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Physics::Unit; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
22336
|
use strict; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
81
|
|
4
|
2
|
|
|
2
|
|
13
|
use Carp; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
183
|
|
5
|
2
|
|
|
2
|
|
10
|
use base qw(Exporter); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
233
|
|
6
|
2
|
|
|
|
|
18291
|
use vars qw( |
7
|
|
|
|
|
|
|
$VERSION |
8
|
|
|
|
|
|
|
@EXPORT_OK |
9
|
|
|
|
|
|
|
%EXPORT_TAGS |
10
|
|
|
|
|
|
|
$debug |
11
|
|
|
|
|
|
|
$number_re |
12
|
2
|
|
|
2
|
|
12
|
); |
|
2
|
|
|
|
|
5
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
$VERSION = '0.53'; |
15
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
@EXPORT_OK = qw( |
18
|
|
|
|
|
|
|
$number_re |
19
|
|
|
|
|
|
|
GetTypeUnit |
20
|
|
|
|
|
|
|
GetUnit |
21
|
|
|
|
|
|
|
InitBaseUnit |
22
|
|
|
|
|
|
|
InitPrefix |
23
|
|
|
|
|
|
|
InitTypes |
24
|
|
|
|
|
|
|
InitUnit |
25
|
|
|
|
|
|
|
ListTypes |
26
|
|
|
|
|
|
|
ListUnits |
27
|
|
|
|
|
|
|
NumBases |
28
|
|
|
|
|
|
|
DeleteNames |
29
|
|
|
|
|
|
|
); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
%EXPORT_TAGS = ('ALL' => \@EXPORT_OK); |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# This is the regular expression used to parse out a number. It |
34
|
|
|
|
|
|
|
# is here so that other modules can use it for convenience. |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
$number_re = '([-+]?((\d+\.?\d*)|(\.\d+))([eE][-+]?((\d+\.?\d*)|(\.\d+)))?)'; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# The value of this hash is a string representing the token returned |
39
|
|
|
|
|
|
|
# when this word is seen |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my %reserved_word = ( |
42
|
|
|
|
|
|
|
per => 'divide', |
43
|
|
|
|
|
|
|
square => 'square', |
44
|
|
|
|
|
|
|
sq => 'square', |
45
|
|
|
|
|
|
|
cubic => 'cubic', |
46
|
|
|
|
|
|
|
squared => 'squared', |
47
|
|
|
|
|
|
|
cubed => 'cubed', |
48
|
|
|
|
|
|
|
); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Pre-defined units |
51
|
|
|
|
|
|
|
my %unit_by_name; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# Values are references to units representing the prefix |
54
|
|
|
|
|
|
|
my %prefix; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Known quantity types. The values of this hash are references to |
57
|
|
|
|
|
|
|
# unit objects that exemplify these types |
58
|
|
|
|
|
|
|
my %prototype; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# The number of base units |
61
|
|
|
|
|
|
|
my $NumBases = 0; |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# The names of the base units |
64
|
|
|
|
|
|
|
my @BaseName; |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
InitBaseUnit ( |
67
|
|
|
|
|
|
|
'Distance' => ['meter', 'm', 'meters', 'metre', 'metres'], |
68
|
|
|
|
|
|
|
'Mass' => ['gram', 'gm', 'grams'], |
69
|
|
|
|
|
|
|
'Time' => ['second', 's', 'sec', 'secs', 'seconds'], |
70
|
|
|
|
|
|
|
'Temperature' => ['kelvin', 'k', 'kelvins', |
71
|
|
|
|
|
|
|
'degree-kelvin', 'degrees-kelvin', 'degree-kelvins'], |
72
|
|
|
|
|
|
|
'Current' => ['ampere', 'amp', 'amps', 'amperes'], |
73
|
|
|
|
|
|
|
'Substance' => ['mole', 'mol', 'moles'], |
74
|
|
|
|
|
|
|
'Luminosity' => ['candela', 'cd', 'candelas', 'candle', 'candles'], |
75
|
|
|
|
|
|
|
'Money' => ['us-dollar', 'dollar', 'dollars', 'us-dollars', '$'], |
76
|
|
|
|
|
|
|
'Data' => ['bit', 'bits'], |
77
|
|
|
|
|
|
|
); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
InitPrefix ( |
80
|
|
|
|
|
|
|
'deka', 1e1, |
81
|
|
|
|
|
|
|
'deca', 1e1, |
82
|
|
|
|
|
|
|
'hecto', 1e2, |
83
|
|
|
|
|
|
|
'kilo', 1e3, |
84
|
|
|
|
|
|
|
'mega', 1e6, |
85
|
|
|
|
|
|
|
'giga', 1e9, |
86
|
|
|
|
|
|
|
'tera', 1e12, |
87
|
|
|
|
|
|
|
'peta', 1e15, |
88
|
|
|
|
|
|
|
'exa', 1e18, |
89
|
|
|
|
|
|
|
'zetta', 1e21, |
90
|
|
|
|
|
|
|
'yotta', 1e24, |
91
|
|
|
|
|
|
|
'deci', 1e-1, |
92
|
|
|
|
|
|
|
'centi', 1e-2, |
93
|
|
|
|
|
|
|
'milli', 1e-3, |
94
|
|
|
|
|
|
|
'micro', 1e-6, |
95
|
|
|
|
|
|
|
'nano', 1e-9, |
96
|
|
|
|
|
|
|
'pico', 1e-12, |
97
|
|
|
|
|
|
|
'femto', 1e-15, |
98
|
|
|
|
|
|
|
'atto', 1e-18, |
99
|
|
|
|
|
|
|
'zepto', 1e-21, |
100
|
|
|
|
|
|
|
'yocto', 1e-24, |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# binary prefixes |
103
|
|
|
|
|
|
|
'kibi', 2^10, |
104
|
|
|
|
|
|
|
'mebi', 2^20, |
105
|
|
|
|
|
|
|
'gibi', 2^30, |
106
|
|
|
|
|
|
|
'tebi', 2^40, |
107
|
|
|
|
|
|
|
'pebi', 2^50, |
108
|
|
|
|
|
|
|
'exbi', 2^60, |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# others |
111
|
|
|
|
|
|
|
'semi', 0.5, |
112
|
|
|
|
|
|
|
'demi', 0.5, |
113
|
|
|
|
|
|
|
); |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
InitUnit ( |
117
|
|
|
|
|
|
|
# Dimensionless |
118
|
|
|
|
|
|
|
['pi',], '3.1415926535897932385', |
119
|
|
|
|
|
|
|
['e',], '2.7182818284590452354', |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
['unity', 'one', 'ones',], '1', |
122
|
|
|
|
|
|
|
['two', 'twos',], '2', |
123
|
|
|
|
|
|
|
['three', 'threes',], '3', |
124
|
|
|
|
|
|
|
['four', 'fours',], '4', |
125
|
|
|
|
|
|
|
['five', 'fives',], '5', |
126
|
|
|
|
|
|
|
['six', 'sixes',], '6', |
127
|
|
|
|
|
|
|
['seven', 'sevens',], '7', |
128
|
|
|
|
|
|
|
['eight', 'eights',], '8', |
129
|
|
|
|
|
|
|
['nine', 'nines'], '9', |
130
|
|
|
|
|
|
|
['ten', 'tens',], '10', |
131
|
|
|
|
|
|
|
['eleven', 'elevens',], '11', |
132
|
|
|
|
|
|
|
['twelve', 'twelves',], '12', |
133
|
|
|
|
|
|
|
['thirteen', 'thirteens',], '13', |
134
|
|
|
|
|
|
|
['fourteen', 'fourteens',], '14', |
135
|
|
|
|
|
|
|
['fifteen', 'fifteens',], '15', |
136
|
|
|
|
|
|
|
['sixteen', 'sixteens',], '16', |
137
|
|
|
|
|
|
|
['seventeen', 'seventeens',], '17', |
138
|
|
|
|
|
|
|
['eighteen', 'eighteens',], '18', |
139
|
|
|
|
|
|
|
['nineteen', 'nineteens',], '19', |
140
|
|
|
|
|
|
|
['twenty', 'twenties',], '20', |
141
|
|
|
|
|
|
|
['thirty', 'thirties',], '30', |
142
|
|
|
|
|
|
|
['forty', 'forties',], '40', |
143
|
|
|
|
|
|
|
['fifty', 'fifties',], '50', |
144
|
|
|
|
|
|
|
['sixty', 'sixties',], '60', |
145
|
|
|
|
|
|
|
['seventy', 'seventies',], '70', |
146
|
|
|
|
|
|
|
['eighty', 'eighties',], '80', |
147
|
|
|
|
|
|
|
['ninety', 'nineties',], '90', |
148
|
|
|
|
|
|
|
['hundred', 'hundreds'], '100', |
149
|
|
|
|
|
|
|
['thousand', 'thousands'], '1000', |
150
|
|
|
|
|
|
|
['million', 'millions',], '1e6', |
151
|
|
|
|
|
|
|
['billion', 'billions',], '1e9', |
152
|
|
|
|
|
|
|
['trillion', 'trillions',], '1e12', |
153
|
|
|
|
|
|
|
['quadrillion', 'quadrillions',], '1e15', |
154
|
|
|
|
|
|
|
['quintillion', 'quintillions',], '1e18', |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
['half', 'halves',], '0.5', |
157
|
|
|
|
|
|
|
['third', 'thirds',], '1/3', |
158
|
|
|
|
|
|
|
['fourth', 'fourths',], '0.25', |
159
|
|
|
|
|
|
|
['tenth',], '0.1', |
160
|
|
|
|
|
|
|
['hundredth',], '0.01', |
161
|
|
|
|
|
|
|
['thousandth',], '0.001', |
162
|
|
|
|
|
|
|
['millionth',], '1e-6', |
163
|
|
|
|
|
|
|
['billionth',], '1e-9', |
164
|
|
|
|
|
|
|
['trillionth',], '1e-12', |
165
|
|
|
|
|
|
|
['quadrillionth',], '1e-15', |
166
|
|
|
|
|
|
|
['quintillionth',], '1e-18', |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
['percent', '%',], '0.01', |
169
|
|
|
|
|
|
|
['dozen', 'doz',], '12', |
170
|
|
|
|
|
|
|
['gross',], '144', |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# Angular |
173
|
|
|
|
|
|
|
['radian', 'radians',], '1', |
174
|
|
|
|
|
|
|
['steradian', 'sr', 'steradians',], '1', |
175
|
|
|
|
|
|
|
['degree', 'deg', 'degrees',], 'pi radians / 180', |
176
|
|
|
|
|
|
|
['arcminute', 'arcmin', 'arcminutes',], 'deg / 60', |
177
|
|
|
|
|
|
|
['arcsecond', 'arcsec', 'arcseconds',], 'arcmin / 60', |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# Distance |
180
|
|
|
|
|
|
|
['foot', 'ft', 'feet',], '.3048 m', # exact |
181
|
|
|
|
|
|
|
['inch', 'in', 'inches',], 'ft/12', # exact |
182
|
|
|
|
|
|
|
['mil', 'mils',], 'in/1000', # exact |
183
|
|
|
|
|
|
|
['yard', 'yards',], '3 ft', # exact |
184
|
|
|
|
|
|
|
['fathom', 'fathoms',], '2 yards', # exact |
185
|
|
|
|
|
|
|
['rod', 'rods',], '5.5 yards', # exact |
186
|
|
|
|
|
|
|
['pole', 'poles',], '1 rod', # exact |
187
|
|
|
|
|
|
|
['perch', 'perches',], '1 rod', # exact |
188
|
|
|
|
|
|
|
['furlong', 'furlongs',], '40 rods', # exact |
189
|
|
|
|
|
|
|
['mile', 'mi', 'miles',], '5280 ft', # exact |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
['micron', 'microns', 'um',], '1e-6 m', # exact |
192
|
|
|
|
|
|
|
['angstrom', 'a', 'angstroms',], '1e-10 m', # exact |
193
|
|
|
|
|
|
|
['cm',], 'centimeter', # exact |
194
|
|
|
|
|
|
|
['km',], 'kilometer', # exact |
195
|
|
|
|
|
|
|
['nm',], 'nanometer', # exact |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
['pica',], 'in/6', # exact, but see below |
198
|
|
|
|
|
|
|
['point',], 'pica/12', # exact |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
['nautical-mile', 'nmi', 'nauticalmiles', |
201
|
|
|
|
|
|
|
'nauticalmile', 'nautical-miles',], '1852 m', # exact |
202
|
|
|
|
|
|
|
['astronomical-unit', 'au',], '1.49598e11 m', |
203
|
|
|
|
|
|
|
['light-year', 'ly', 'light-years', |
204
|
|
|
|
|
|
|
'lightyear', 'lightyears'], '9.46e15 m', |
205
|
|
|
|
|
|
|
['parsec', 'parsecs',], '3.083e16 m', |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# equatorial radius of the reference geoid: |
208
|
|
|
|
|
|
|
['re'], '6378388 m', # exact |
209
|
|
|
|
|
|
|
# polar radius of the reference geoid: |
210
|
|
|
|
|
|
|
['rp'], '6356912 m', # exact |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# Acceleration |
213
|
|
|
|
|
|
|
['g0', 'earth-gravity'], '9.80665 m/s^2', # exact |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# Mass |
216
|
|
|
|
|
|
|
['kg',], 'kilogram', # exact |
217
|
|
|
|
|
|
|
['metric-ton', 'metric-tons', 'tonne', |
218
|
|
|
|
|
|
|
'tonnes'], '1000 kg', # exact |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
['grain', 'grains'], '.0648 gm', |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
['pound-mass', 'lbm', 'lbms', |
223
|
|
|
|
|
|
|
'pounds-mass'], '0.45359237 kg', # exact |
224
|
|
|
|
|
|
|
['ounce', 'oz', 'ounces'], 'lbm/16', # exact |
225
|
|
|
|
|
|
|
['stone', 'stones'], '14 lbm', # exact |
226
|
|
|
|
|
|
|
['hundredweight', 'hundredweights'], '100 lbms', # exact |
227
|
|
|
|
|
|
|
['ton', 'tons', 'short-ton', 'short-tons'], '2000 lbms', # exact |
228
|
|
|
|
|
|
|
['long-ton', 'long-tons'], '2240 lbms', # exact |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
['slug', 'slugs'], 'lbm g0 s^2/ft', # exact |
231
|
|
|
|
|
|
|
['mg',], 'milligram', # exact |
232
|
|
|
|
|
|
|
['ug',], 'microgram', # exact |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
['dram', 'drams'], 'ounce / 16', # exact |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
['troy-pound', 'troy-pounds'], '0.373 kg', |
237
|
|
|
|
|
|
|
['troy-ounce', 'troy-ounces', |
238
|
|
|
|
|
|
|
'ounce-troy', 'ounces-troy'], '31.103 gm', |
239
|
|
|
|
|
|
|
['pennyweight', 'pennyweights'], '1.555 gm', |
240
|
|
|
|
|
|
|
['scruple', 'scruples'], '1.296 gm', |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
['hg',], 'hectogram', # exact |
243
|
|
|
|
|
|
|
['dag',], 'decagram', # exact |
244
|
|
|
|
|
|
|
['dg',], 'decigram', # exact |
245
|
|
|
|
|
|
|
['cg',], 'centigram', # exact |
246
|
|
|
|
|
|
|
['carat', 'carats', 'karat', 'karats',], '200 milligrams', # exact |
247
|
|
|
|
|
|
|
['j-point',], '2 carats', # exact |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
['atomic-mass-unit', 'amu', 'u', |
250
|
|
|
|
|
|
|
'atomic-mass-units'], '1.6605402e-27 kg', |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# Time |
254
|
|
|
|
|
|
|
['minute', 'min', 'mins', 'minutes'], '60 s', |
255
|
|
|
|
|
|
|
['hour', 'hr', 'hrs', 'hours'], '60 min', |
256
|
|
|
|
|
|
|
['day', 'days'], '24 hr', |
257
|
|
|
|
|
|
|
['week', 'wk', 'weeks'], '7 days', |
258
|
|
|
|
|
|
|
['fortnight', 'fortnights'], '2 week', |
259
|
|
|
|
|
|
|
['year', 'yr', 'yrs', 'years'], '365.25 days', |
260
|
|
|
|
|
|
|
['month', 'mon', 'mons', 'months'], 'year / 12', # an average month |
261
|
|
|
|
|
|
|
['score', 'scores'], '20 yr', |
262
|
|
|
|
|
|
|
['century', 'centuries'], '100 yr', |
263
|
|
|
|
|
|
|
['millenium', 'millenia',], '1000 yr', |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
['ms', 'msec', 'msecs'], 'millisecond', |
266
|
|
|
|
|
|
|
['us', 'usec', 'usecs'], 'microsecond', |
267
|
|
|
|
|
|
|
['ns', 'nsec', 'nsecs'], 'nanosecond', |
268
|
|
|
|
|
|
|
['ps', 'psec', 'psecs'], 'picosecond', |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# Data |
271
|
|
|
|
|
|
|
['byte', 'bytes'], '8 bits', |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# Frequency |
274
|
|
|
|
|
|
|
['hertz', 'hz'], '1/sec', |
275
|
|
|
|
|
|
|
['becquerel', 'bq'], '1 hz', |
276
|
|
|
|
|
|
|
['revolution', 'revolutions',], '1', |
277
|
|
|
|
|
|
|
['rpm',], 'revolutions per minute', |
278
|
|
|
|
|
|
|
['cycle', 'cycles',], '1', |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# Current |
281
|
|
|
|
|
|
|
['abampere', 'abamp', 'abamps', 'abamperes'], '10 amps', |
282
|
|
|
|
|
|
|
['statampere', 'statamp', 'statamps', 'statamperes'], '3.336e-10 amps', |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
['ma',], 'milliamp', |
285
|
|
|
|
|
|
|
['ua',], 'microamp', |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
# Electric_potential |
288
|
|
|
|
|
|
|
['volt', 'v', 'volts'], 'kg m^2 / amp s^3', |
289
|
|
|
|
|
|
|
['mv',], 'millivolt', |
290
|
|
|
|
|
|
|
['uv',], 'microvolt', |
291
|
|
|
|
|
|
|
['abvolt', 'abvolts'], '1e-8 volt', |
292
|
|
|
|
|
|
|
['statvolt', 'statvolts'], '299.8 volt', |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# Resistance |
295
|
|
|
|
|
|
|
['ohm', 'ohms'], 'kg m^2 / amp^2 s^3', |
296
|
|
|
|
|
|
|
['abohm', 'abohms'], 'nano ohm', |
297
|
|
|
|
|
|
|
['statohm', 'statohms'], '8.987e11 ohm', |
298
|
|
|
|
|
|
|
['kilohm', 'kilohms',], 'kilo ohm', |
299
|
|
|
|
|
|
|
['megohm', 'megohms'], 'mega ohm', |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# Conductance |
302
|
|
|
|
|
|
|
['siemens',], 'amp^2 s^3 / kg m^2', |
303
|
|
|
|
|
|
|
['mho', 'mhos'], '1/ohm', |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
# Capacitance |
306
|
|
|
|
|
|
|
['farad', 'f', 'farads'], 'amp^2 s^4 / kg m^2', |
307
|
|
|
|
|
|
|
['abfarad', 'abfarads'], 'giga farad', |
308
|
|
|
|
|
|
|
['statfarad', 'statfarads'], '1.113e-12 farad', |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
['uf',], 'microfarad', |
311
|
|
|
|
|
|
|
['pf',], 'picofarads', |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# Inductance |
314
|
|
|
|
|
|
|
['henry', 'henrys'], 'kg m^2 / amp^2 s^2', |
315
|
|
|
|
|
|
|
['abhenry', 'abhenrys'], 'nano henry', |
316
|
|
|
|
|
|
|
['stathenry', 'stathenrys'], '8.987e11 henry', |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
['uh',], 'microhenry', |
319
|
|
|
|
|
|
|
['mh',], 'millihenry', |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# Magnetic_flux |
322
|
|
|
|
|
|
|
['weber', 'wb', 'webers'], 'kg m^2 / amp s^2', |
323
|
|
|
|
|
|
|
['maxwell', 'maxwells'], '1e-8 weber', |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# Magnetic_field |
326
|
|
|
|
|
|
|
['tesla', 'teslas'], 'kg / amp sec^2', |
327
|
|
|
|
|
|
|
['gauss',], '1e-4 tesla', |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
# Temperature |
330
|
|
|
|
|
|
|
['degree-rankine', 'degrees-rankine'], '5/9 * kelvin', # exact |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# Force |
333
|
|
|
|
|
|
|
['pound', 'lb', 'lbs', 'pounds', |
334
|
|
|
|
|
|
|
'pound-force', 'lbf', |
335
|
|
|
|
|
|
|
'pounds-force', 'pound-weight'], 'slug foot / s^2', # exact |
336
|
|
|
|
|
|
|
['ounce-force', 'ozf'], 'pound-force / 16', # exact |
337
|
|
|
|
|
|
|
['newton', 'nt', 'newtons'], 'kg m / s^2', # exact |
338
|
|
|
|
|
|
|
['dyne', 'dynes'], 'gm cm / s^2', # exact |
339
|
|
|
|
|
|
|
['gram-weight', 'gram-force'], 'gm g0', # exact |
340
|
|
|
|
|
|
|
['kgf',], 'kilo gram-force', # exact |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
# Area |
343
|
|
|
|
|
|
|
['are', 'ares'], '100 square meters', |
344
|
|
|
|
|
|
|
['hectare', 'hectares',], '100 ares', |
345
|
|
|
|
|
|
|
['acre', 'acres'], '43560 square feet', |
346
|
|
|
|
|
|
|
['barn', 'barns'], '1e-28 square meters', |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# Volume |
349
|
|
|
|
|
|
|
['liter', 'l', 'liters'], 'm^3/1000', # exact |
350
|
|
|
|
|
|
|
['cl',], 'centiliter', # exact |
351
|
|
|
|
|
|
|
['dl',], 'deciliter', # exact |
352
|
|
|
|
|
|
|
['cc', 'ml',], 'cubic centimeter', # exact |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
['gallon', 'gal', 'gallons'], '3.785411784 liter', |
355
|
|
|
|
|
|
|
['quart', 'qt', 'quarts'], 'gallon/4', |
356
|
|
|
|
|
|
|
['peck', 'pecks'], '8 quarts', |
357
|
|
|
|
|
|
|
['bushel', 'bushels'], '4 pecks', |
358
|
|
|
|
|
|
|
['fifth', 'fifths'], 'gallon/5', |
359
|
|
|
|
|
|
|
['pint', 'pt', 'pints'], 'quart/2', |
360
|
|
|
|
|
|
|
['cup', 'cups'], 'pint/2', |
361
|
|
|
|
|
|
|
['fluid-ounce', 'floz', 'fluidounce', |
362
|
|
|
|
|
|
|
'fluidounces', 'fluid-ounces'], 'cup/8', |
363
|
|
|
|
|
|
|
['gill', 'gills'], '4 fluid-ounces', |
364
|
|
|
|
|
|
|
['fluidram', 'fluidrams'], '3.5516 cc', |
365
|
|
|
|
|
|
|
['minim', 'minims'], '0.059194 cc', |
366
|
|
|
|
|
|
|
['tablespoon', 'tbsp', 'tablespoons'], 'fluid-ounce / 2', |
367
|
|
|
|
|
|
|
['teaspoon', 'tsp', 'teaspoons'], 'tablespoon / 3', |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
# Power |
370
|
|
|
|
|
|
|
['watt', 'w', 'watts'], 'kg m^2 / s^3', |
371
|
|
|
|
|
|
|
['horsepower', 'hp'], '550 foot pound-force / s', |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
# Energy |
374
|
|
|
|
|
|
|
['joule', 'j', 'joules'], 'kg m^2 / s^2', # exact |
375
|
|
|
|
|
|
|
['electron-volt', 'ev', 'electronvolt', |
376
|
|
|
|
|
|
|
'electronvolts', 'electron-volts'], '1.60217733e-19 joule', |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
['mev',], 'mega electron-volt', |
379
|
|
|
|
|
|
|
['gev',], 'giga electron-volt', |
380
|
|
|
|
|
|
|
['tev',], 'tera electron-volt', |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
['calorie', 'cal', 'calories'], '4.184 joules', # exact |
383
|
|
|
|
|
|
|
['kcal',], 'kilocalorie', # exact |
384
|
|
|
|
|
|
|
['british-thermal-unit', 'btu', 'btus', |
385
|
|
|
|
|
|
|
'britishthermalunit', 'britishthermalunits', |
386
|
|
|
|
|
|
|
'british-thermal-units'], '1055.056 joule', |
387
|
|
|
|
|
|
|
['erg', 'ergs'], '1.0e-7 joule', # exact |
388
|
|
|
|
|
|
|
['kwh',], 'kilowatt hour', # exact |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
# Torque |
391
|
|
|
|
|
|
|
['foot-pound', 'ftlb', 'ft-lb', |
392
|
|
|
|
|
|
|
'footpound', 'footpounds', 'foot-pounds'], 'foot pound-force', |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
# Charge |
395
|
|
|
|
|
|
|
['coulomb', 'coul', 'coulombs'], 'ampere second', |
396
|
|
|
|
|
|
|
['abcoulomb', 'abcoul', 'abcoulombs'], '10 coulomb', |
397
|
|
|
|
|
|
|
['statcoulomb', 'statcoul', 'statcoulombs'], '3.336e-10 coulomb', |
398
|
|
|
|
|
|
|
['elementary-charge', 'eq'], '1.6021892e-19 coulomb', |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
# Pressure |
401
|
|
|
|
|
|
|
['pascal', 'pa'], 'newton / m^2', |
402
|
|
|
|
|
|
|
['bar', 'bars'], '1e5 pascal', |
403
|
|
|
|
|
|
|
['torr',], '(101325 / 760) pascal', |
404
|
|
|
|
|
|
|
['psi',], 'pounds per inch^2', |
405
|
|
|
|
|
|
|
['atmosphere', 'atm'], '101325 pascal', # exact |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
# Speed |
408
|
|
|
|
|
|
|
['mph',], 'mi/hr', |
409
|
|
|
|
|
|
|
['kph',], 'km/hr', |
410
|
|
|
|
|
|
|
['kps',], 'km/s', |
411
|
|
|
|
|
|
|
['fps',], 'ft/s', |
412
|
|
|
|
|
|
|
['knot', 'knots'], 'nm/hr', |
413
|
|
|
|
|
|
|
['mps',], 'meter/s', |
414
|
|
|
|
|
|
|
['speed-of-light', 'c'], '2.99792458e8 m/sec', |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
# Dose of radiation |
417
|
|
|
|
|
|
|
['gray', 'gy'], 'joule / kg', |
418
|
|
|
|
|
|
|
['sievert', 'sv'], 'joule / kg', |
419
|
|
|
|
|
|
|
['rad',], 'gray / 100', |
420
|
|
|
|
|
|
|
['rem',], 'sievert / 100', |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
# Other |
423
|
|
|
|
|
|
|
['gravitational-constant', 'g'], '6.6720e-11 m^3 / kg s^2', |
424
|
|
|
|
|
|
|
# Planck constant: |
425
|
|
|
|
|
|
|
['h'], '6.626196e-34 J/s', |
426
|
|
|
|
|
|
|
# Avogadro constant: |
427
|
|
|
|
|
|
|
['na'], '6.022169/mol', |
428
|
|
|
|
|
|
|
); |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
InitTypes ( |
432
|
|
|
|
|
|
|
'Dimensionless' => 'unity', |
433
|
|
|
|
|
|
|
'Frequency' => 'hertz', |
434
|
|
|
|
|
|
|
'Electric_potential' => 'volt', |
435
|
|
|
|
|
|
|
'Resistance' => 'ohm', |
436
|
|
|
|
|
|
|
'Conductance' => 'siemens', |
437
|
|
|
|
|
|
|
'Capacitance' => 'farad', |
438
|
|
|
|
|
|
|
'Inductance' => 'henry', |
439
|
|
|
|
|
|
|
'Magnetic_flux' => 'weber', |
440
|
|
|
|
|
|
|
'Magnetic_field' => 'tesla', |
441
|
|
|
|
|
|
|
'Momentum' => 'kg m/s', |
442
|
|
|
|
|
|
|
'Force' => 'newton', |
443
|
|
|
|
|
|
|
'Area' => 'are', |
444
|
|
|
|
|
|
|
'Volume' => 'liter', |
445
|
|
|
|
|
|
|
'Power' => 'watt', |
446
|
|
|
|
|
|
|
'Energy' => 'joule', |
447
|
|
|
|
|
|
|
'Torque' => 'kg m^2/s^2', |
448
|
|
|
|
|
|
|
'Charge' => 'coulomb', |
449
|
|
|
|
|
|
|
'Pressure' => 'pascal', |
450
|
|
|
|
|
|
|
'Speed' => 'mps', |
451
|
|
|
|
|
|
|
'Dose' => 'gray', # of radiation |
452
|
|
|
|
|
|
|
'Acceleration' => 'm/s^2', |
453
|
|
|
|
|
|
|
); |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
GetUnit('joule')->type('Energy'); |
457
|
|
|
|
|
|
|
GetUnit('ev')->type('Energy'); |
458
|
|
|
|
|
|
|
GetUnit('mev')->type('Energy'); |
459
|
|
|
|
|
|
|
GetUnit('gev')->type('Energy'); |
460
|
|
|
|
|
|
|
GetUnit('tev')->type('Energy'); |
461
|
|
|
|
|
|
|
GetUnit('cal')->type('Energy'); |
462
|
|
|
|
|
|
|
GetUnit('kcal')->type('Energy'); |
463
|
|
|
|
|
|
|
GetUnit('btu')->type('Energy'); |
464
|
|
|
|
|
|
|
GetUnit('erg')->type('Energy'); |
465
|
|
|
|
|
|
|
GetUnit('kwh')->type('Energy'); |
466
|
|
|
|
|
|
|
GetUnit('ftlb')->type('Torque'); |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
sub InitBaseUnit { |
470
|
3
|
|
|
3
|
1
|
17
|
while (@_) { |
471
|
19
|
|
|
|
|
33
|
my ($t, $names) = (shift, shift); |
472
|
19
|
50
|
33
|
|
|
103
|
croak 'Invalid arguments to InitBaseUnit' |
473
|
|
|
|
|
|
|
if ref $t || (ref $names ne "ARRAY"); |
474
|
|
|
|
|
|
|
|
475
|
19
|
50
|
|
|
|
49
|
print "Initializing Base Unit $$names[0]\n" if $debug; |
476
|
|
|
|
|
|
|
|
477
|
19
|
|
|
|
|
42
|
my $unit = NewOne(); |
478
|
19
|
|
|
|
|
47
|
$unit->AddNames(@$names); |
479
|
19
|
|
|
|
|
39
|
$unit->{def} = $unit->name(); # def same as name |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
# The dimension vector for this Unit has zeros in every place |
482
|
|
|
|
|
|
|
# except the last |
483
|
19
|
|
|
|
|
35
|
$unit->{dim}->[$NumBases] = 1; |
484
|
19
|
|
|
|
|
35
|
$BaseName[$NumBases] = $unit->abbr(); |
485
|
19
|
|
|
|
|
22
|
$NumBases++; |
486
|
|
|
|
|
|
|
|
487
|
19
|
|
|
|
|
42
|
$unit->NewType($t); |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
sub InitPrefix { |
492
|
3
|
|
|
3
|
1
|
13
|
while (@_) { |
493
|
60
|
|
|
|
|
93
|
my ($name, $factor) = (shift, shift); |
494
|
60
|
50
|
33
|
|
|
451
|
croak 'Invalid arguments to InitPrefix' |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
495
|
|
|
|
|
|
|
if !$name || !$factor || ref $name || ref $factor; |
496
|
|
|
|
|
|
|
|
497
|
60
|
50
|
|
|
|
108
|
print "Initializing Prefix $name\n" if $debug; |
498
|
|
|
|
|
|
|
|
499
|
60
|
|
|
|
|
97
|
my $u = NewOne(); |
500
|
60
|
|
|
|
|
127
|
$u->AddNames($name); |
501
|
60
|
|
|
|
|
91
|
$u->{factor} = $factor; |
502
|
60
|
|
|
|
|
79
|
$u->{type} = 'prefix'; |
503
|
60
|
|
|
|
|
117
|
$prefix{$name} = $u; |
504
|
|
|
|
|
|
|
|
505
|
60
|
|
|
|
|
295
|
$u->{def} = $factor; |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
sub InitUnit { |
510
|
6
|
|
|
6
|
1
|
23
|
while (@_) { |
511
|
438
|
|
|
|
|
796
|
my ($names, $def) = (shift, shift); |
512
|
|
|
|
|
|
|
|
513
|
438
|
50
|
33
|
|
|
2037
|
if (ref $names ne "ARRAY" || !$def) { |
514
|
0
|
|
|
|
|
0
|
print "InitUnit, second argument is '$def'\n"; |
515
|
0
|
|
|
|
|
0
|
croak 'Invalid arguments to InitUnit'; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
438
|
50
|
|
|
|
740
|
print "Initializing Unit $$names[0]\n" if $debug; |
519
|
438
|
|
|
|
|
1777
|
my $u = CreateUnit($def); |
520
|
438
|
|
|
|
|
1102
|
$u->AddNames(@$names); |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
sub InitTypes { |
525
|
3
|
|
|
3
|
1
|
15
|
while (@_) { |
526
|
43
|
|
|
|
|
60
|
my ($t, $u) = (shift, shift); |
527
|
43
|
50
|
33
|
|
|
233
|
croak 'Invalid arguments to InitTypes' |
|
|
|
33
|
|
|
|
|
528
|
|
|
|
|
|
|
if !$t || ref $t || !$u; |
529
|
|
|
|
|
|
|
|
530
|
43
|
|
|
|
|
64
|
my $unit = GetUnit($u); |
531
|
43
|
|
|
|
|
80
|
$unit->NewType($t); |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
} |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
sub GetUnit { |
536
|
1376
|
|
|
1376
|
1
|
3686
|
my $u = shift; |
537
|
1376
|
50
|
|
|
|
2797
|
croak 'GetUnit: expected an argument' unless $u; |
538
|
1376
|
100
|
|
|
|
3342
|
return $u if ref $u; |
539
|
|
|
|
|
|
|
|
540
|
744
|
100
|
|
|
|
1770
|
if ($unit_by_name{$u}) { |
541
|
|
|
|
|
|
|
#print "GetUnit, $u yields ", $unit_by_name{$u}->name, "\n"; |
542
|
717
|
|
|
|
|
1980
|
return $unit_by_name{$u}; |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
# Try it as an expression |
546
|
27
|
|
|
|
|
66
|
return CreateUnit($u); |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
sub ListUnits { |
550
|
5
|
|
|
5
|
1
|
2838
|
return sort keys %unit_by_name; |
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
sub ListTypes { |
554
|
1
|
|
|
1
|
1
|
22
|
return sort keys %prototype; |
555
|
|
|
|
|
|
|
} |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
sub NumBases { |
558
|
0
|
|
|
0
|
1
|
0
|
return $NumBases; |
559
|
|
|
|
|
|
|
} |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
sub GetTypeUnit { |
562
|
30
|
|
|
30
|
1
|
33
|
my $t = shift; |
563
|
30
|
|
|
|
|
68
|
return $prototype{$t}; |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
# DeleteNames - argument can be either an array ref, a list of name strings, or |
567
|
|
|
|
|
|
|
# a unit object |
568
|
|
|
|
|
|
|
sub DeleteNames { |
569
|
4
|
|
|
4
|
1
|
24
|
my $arg0 = $_[0]; |
570
|
4
|
|
100
|
|
|
27
|
my $argIsUnit = ref $arg0 && ref $arg0 ne 'ARRAY'; |
571
|
|
|
|
|
|
|
# Get the list of names to delete |
572
|
4
|
100
|
|
|
|
16
|
my $names = |
|
|
100
|
|
|
|
|
|
573
|
|
|
|
|
|
|
!ref $arg0 |
574
|
|
|
|
|
|
|
? \@_ # list of names |
575
|
|
|
|
|
|
|
: ref $arg0 eq 'ARRAY' |
576
|
|
|
|
|
|
|
? $arg0 # array ref |
577
|
|
|
|
|
|
|
: $arg0->{names}; # unit object |
578
|
|
|
|
|
|
|
|
579
|
4
|
|
|
|
|
5
|
my $u; |
580
|
4
|
100
|
|
|
|
10
|
if ($argIsUnit) { $u = $arg0; } |
|
1
|
|
|
|
|
3
|
|
581
|
4
|
|
|
|
|
8
|
for my $n (@$names) { |
582
|
8
|
50
|
|
|
|
13
|
if (LookName($n) != 2) { |
583
|
0
|
|
|
|
|
0
|
croak "'$n' is not a unit name."; |
584
|
|
|
|
|
|
|
} |
585
|
8
|
50
|
|
|
|
17
|
print "deleting '$n'\n" if $debug; |
586
|
8
|
|
|
|
|
10
|
delete $prefix{$n}; |
587
|
8
|
100
|
|
|
|
23
|
if (!$argIsUnit) { $u = $unit_by_name{$n}; } |
|
5
|
|
|
|
|
8
|
|
588
|
8
|
|
|
|
|
12
|
delete $unit_by_name{$n}; |
589
|
|
|
|
|
|
|
# Delete the array element matching $n from @{$u->{names}} |
590
|
8
|
100
|
|
|
|
18
|
if (!$argIsUnit) { |
591
|
5
|
|
|
|
|
4
|
$u->{names} = [ grep { $_ ne $n } @{$u->{names}} ]; |
|
15
|
|
|
|
|
42
|
|
|
5
|
|
|
|
|
11
|
|
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
} |
594
|
4
|
100
|
|
|
|
14
|
if ($argIsUnit) { $u->{names} = []; } |
|
1
|
|
|
|
|
5
|
|
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
sub new { |
599
|
20
|
|
|
20
|
1
|
1172
|
my $proto = shift; |
600
|
20
|
|
|
|
|
23
|
my $class; |
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
my $self; |
603
|
20
|
100
|
|
|
|
47
|
if (ref $proto) { # object method |
604
|
2
|
|
|
|
|
6
|
$self = $proto->copy; |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
else { # class method |
607
|
18
|
|
|
|
|
24
|
my $r = shift; |
608
|
18
|
|
|
|
|
39
|
$self = CreateUnit($r); |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
|
611
|
20
|
|
|
|
|
58
|
$self->AddNames(@_); |
612
|
20
|
|
|
|
|
64
|
return $self; |
613
|
|
|
|
|
|
|
} |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
sub type { |
616
|
49
|
|
|
49
|
1
|
1110
|
my $self = shift; |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# See if the user is setting the type |
619
|
49
|
|
|
|
|
61
|
my $t; |
620
|
49
|
100
|
|
|
|
108
|
if ($t = shift) { |
621
|
|
|
|
|
|
|
# XXX Maybe we should check that $t is a valid type name, and |
622
|
|
|
|
|
|
|
# XXX that it's type really does match. |
623
|
23
|
|
|
|
|
52
|
return $self->{type} = $t; |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
# If the type is known already, return it |
627
|
26
|
100
|
|
|
|
76
|
return $self->{type} if $self->{type}; |
628
|
|
|
|
|
|
|
|
629
|
|
|
|
|
|
|
# See if it is a prefix |
630
|
22
|
|
|
|
|
49
|
my $name = $self->name(); |
631
|
|
|
|
|
|
|
|
632
|
22
|
50
|
66
|
|
|
74
|
return $self->{type} = 'prefix' |
633
|
|
|
|
|
|
|
if defined $name && defined $prefix{$name}; |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
# Collect all matching types |
636
|
22
|
|
|
|
|
31
|
my @t; |
637
|
22
|
|
|
|
|
158
|
for (keys %prototype) { |
638
|
667
|
100
|
|
|
|
1258
|
push @t, $_ |
639
|
|
|
|
|
|
|
unless CompareDim($self, $prototype{$_}); |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
# Return value depends on whether we got zero, one, or multiple types |
643
|
22
|
100
|
|
|
|
277
|
return undef unless @t; |
644
|
18
|
100
|
|
|
|
519
|
return $self->{type} = $t[0] if @t == 1; |
645
|
1
|
|
|
|
|
5
|
return \@t; |
646
|
|
|
|
|
|
|
} |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
sub name { |
649
|
90
|
|
|
90
|
1
|
128
|
my $self = shift; |
650
|
90
|
|
|
|
|
129
|
my $n = $self->{names}; |
651
|
90
|
|
|
|
|
306
|
return $$n[0]; |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
sub abbr { |
655
|
19
|
|
|
19
|
1
|
33
|
my $self = shift; |
656
|
19
|
|
|
|
|
21
|
my $n = ${$self->{names}}[0]; |
|
19
|
|
|
|
|
35
|
|
657
|
19
|
50
|
|
|
|
54
|
return undef unless defined $n; |
658
|
|
|
|
|
|
|
|
659
|
19
|
|
|
|
|
41
|
for ($self->names()) { |
660
|
79
|
100
|
|
|
|
297
|
$n = $_ if length $_ < length $n; |
661
|
|
|
|
|
|
|
} |
662
|
19
|
|
|
|
|
59
|
return $n; |
663
|
|
|
|
|
|
|
} |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
sub names { |
666
|
22
|
|
|
22
|
1
|
1511
|
my $self = shift; |
667
|
22
|
|
|
|
|
24
|
return @{$self->{names}}; |
|
22
|
|
|
|
|
89
|
|
668
|
|
|
|
|
|
|
} |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
sub def { |
671
|
4
|
|
|
4
|
1
|
8
|
my $self = shift; |
672
|
4
|
|
|
|
|
23
|
return $self->{def}; |
673
|
|
|
|
|
|
|
} |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
sub expanded { |
676
|
11
|
|
|
11
|
1
|
46
|
my $self = shift; |
677
|
11
|
|
|
|
|
17
|
my $s = $self->{factor}; |
678
|
11
|
100
|
|
|
|
31
|
$s = '' if $s == 1; |
679
|
|
|
|
|
|
|
|
680
|
11
|
|
|
|
|
14
|
my $i = 0; |
681
|
11
|
|
|
|
|
12
|
for my $d (@{$self->{dim}}) { |
|
11
|
|
|
|
|
25
|
|
682
|
118
|
100
|
|
|
|
183
|
if ($d) { |
683
|
|
|
|
|
|
|
#print "Dimension index $i is $d\n"; |
684
|
22
|
100
|
|
|
|
46
|
if ($s) { $s .= " "; } |
|
20
|
|
|
|
|
60
|
|
685
|
22
|
|
|
|
|
28
|
$s .= $BaseName[$i]; |
686
|
22
|
100
|
|
|
|
58
|
$s .= "^$d" unless $d == 1; |
687
|
|
|
|
|
|
|
} |
688
|
118
|
|
|
|
|
125
|
$i++; |
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
|
691
|
11
|
50
|
|
|
|
32
|
$s = 1 if $s eq ''; |
692
|
11
|
|
|
|
|
58
|
return $s; |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
sub ToString { |
696
|
11
|
|
|
11
|
1
|
16
|
my $self = shift; |
697
|
11
|
|
66
|
|
|
26
|
return $self->name || $self->def || $self->expanded; |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
sub factor { |
701
|
9
|
|
|
9
|
1
|
14
|
my $self = shift; |
702
|
9
|
100
|
|
|
|
29
|
if (@_) { |
703
|
3
|
|
|
|
|
10
|
$self->CheckChange; |
704
|
3
|
|
|
|
|
4
|
$self->{factor} = shift; |
705
|
|
|
|
|
|
|
} |
706
|
9
|
|
|
|
|
33
|
return $self->{factor}; |
707
|
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
sub convert { |
710
|
19
|
|
|
19
|
1
|
38
|
my ($self, $other) = @_; |
711
|
19
|
|
|
|
|
41
|
my $u = GetUnit($other); |
712
|
19
|
50
|
|
|
|
52
|
carp "Can't convert ". $self->name() .' to '. $u->name() |
713
|
|
|
|
|
|
|
if CompareDim($self, $u); |
714
|
19
|
|
|
|
|
111
|
return $self->{factor} / $u->{factor}; |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
sub times { |
718
|
470
|
|
|
470
|
1
|
965
|
my $self = shift; |
719
|
470
|
|
|
|
|
782
|
$self->CheckChange; |
720
|
470
|
|
|
|
|
768
|
my $u = GetUnit(shift); |
721
|
470
|
|
|
|
|
951
|
$self->{factor} *= $u->{factor}; |
722
|
|
|
|
|
|
|
|
723
|
470
|
|
|
|
|
940
|
for (0 .. $NumBases) { |
724
|
4736
|
100
|
|
|
|
8534
|
my $u_val = defined $u->{dim}[$_] ? $u->{dim}[$_] : 0; |
725
|
4736
|
100
|
|
|
|
7550
|
if (defined $self->{dim}[$_]) { |
726
|
4718
|
|
|
|
|
7823
|
$self->{dim}[$_] += $u_val; |
727
|
|
|
|
|
|
|
} |
728
|
|
|
|
|
|
|
else { |
729
|
18
|
|
|
|
|
54
|
$self->{dim}[$_] = $u_val; |
730
|
|
|
|
|
|
|
} |
731
|
|
|
|
|
|
|
} |
732
|
|
|
|
|
|
|
|
733
|
470
|
|
|
|
|
779
|
$self->{type} = ''; |
734
|
470
|
|
|
|
|
1736
|
return $self; |
735
|
|
|
|
|
|
|
} |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
sub recip { |
738
|
141
|
|
|
141
|
1
|
191
|
my $self = shift; |
739
|
141
|
|
|
|
|
264
|
$self->CheckChange; |
740
|
141
|
|
|
|
|
288
|
$self->{factor} = 1 / $self->{factor}; |
741
|
|
|
|
|
|
|
|
742
|
141
|
|
|
|
|
251
|
for (0 .. $NumBases) { |
743
|
1424
|
100
|
|
|
|
2263
|
if (defined $self->{dim}[$_]) { |
744
|
1416
|
|
|
|
|
2606
|
$self->{dim}->[$_] = -$self->{dim}->[$_]; |
745
|
|
|
|
|
|
|
} |
746
|
|
|
|
|
|
|
else { |
747
|
8
|
|
|
|
|
26
|
$self->{dim}[$_] = 0; |
748
|
|
|
|
|
|
|
} |
749
|
|
|
|
|
|
|
} |
750
|
|
|
|
|
|
|
|
751
|
141
|
|
|
|
|
397
|
return $self; |
752
|
|
|
|
|
|
|
} |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
sub divide { |
755
|
139
|
|
|
139
|
1
|
202
|
my ($self, $other) = @_; |
756
|
139
|
|
|
|
|
239
|
my $u = GetUnit($other)->copy; |
757
|
139
|
|
|
|
|
326
|
$self->times($u->recip); |
758
|
|
|
|
|
|
|
} |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
sub power { |
761
|
88
|
|
|
88
|
1
|
151
|
my $self = shift; |
762
|
88
|
|
|
|
|
147
|
$self->CheckChange; |
763
|
88
|
|
|
|
|
121
|
my $p = shift; |
764
|
88
|
50
|
|
|
|
180
|
die 'Exponentiation to integer values only, please' |
765
|
|
|
|
|
|
|
unless $p == int $p; |
766
|
88
|
|
|
|
|
184
|
$self->{factor} **= $p; |
767
|
|
|
|
|
|
|
|
768
|
88
|
|
|
|
|
201
|
for (0 .. $NumBases) { |
769
|
885
|
100
|
|
|
|
1569
|
$self->{dim}[$_] = 0 unless defined $self->{dim}[$_]; |
770
|
885
|
|
|
|
|
1208
|
$self->{dim}[$_] *= $p; |
771
|
|
|
|
|
|
|
} |
772
|
|
|
|
|
|
|
|
773
|
88
|
|
|
|
|
148
|
$self->{type} = ''; |
774
|
88
|
|
|
|
|
125
|
return $self; |
775
|
|
|
|
|
|
|
} |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
sub add { |
778
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
779
|
0
|
|
|
|
|
0
|
$self->CheckChange; |
780
|
|
|
|
|
|
|
|
781
|
0
|
|
|
|
|
0
|
my $other = shift; |
782
|
0
|
|
|
|
|
0
|
my $u = GetUnit($other); |
783
|
|
|
|
|
|
|
|
784
|
0
|
0
|
|
|
|
0
|
croak "Can't add ". $u->type .' to a '. $self->type |
785
|
|
|
|
|
|
|
if CompareDim($self, $u); |
786
|
0
|
|
|
|
|
0
|
$self->{factor} += $u->{factor}; |
787
|
0
|
|
|
|
|
0
|
return $self; |
788
|
|
|
|
|
|
|
} |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
sub neg { |
791
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
792
|
0
|
|
|
|
|
0
|
$self->CheckChange; |
793
|
0
|
|
|
|
|
0
|
$self->{factor} = -$self->{factor}; |
794
|
0
|
|
|
|
|
0
|
return $self; |
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
sub subtract { |
798
|
0
|
|
|
0
|
1
|
0
|
my ($self, $other) = @_; |
799
|
0
|
|
|
|
|
0
|
my $u = GetUnit($other)->copy; |
800
|
0
|
|
|
|
|
0
|
$self->add( $u->neg ); |
801
|
|
|
|
|
|
|
} |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
sub copy { |
804
|
754
|
|
|
754
|
1
|
899
|
my $self = shift; |
805
|
754
|
|
|
|
|
5915
|
my $n = { |
806
|
|
|
|
|
|
|
'factor' => $self->{factor}, |
807
|
754
|
|
|
|
|
1155
|
'dim' => [@{$self->{dim}}], |
808
|
|
|
|
|
|
|
'type' => $self->{type}, |
809
|
|
|
|
|
|
|
'names' => [], |
810
|
|
|
|
|
|
|
'def' => $self->{def}, |
811
|
|
|
|
|
|
|
}; |
812
|
|
|
|
|
|
|
|
813
|
754
|
|
|
|
|
1553
|
bless $n, 'Physics::Unit'; |
814
|
754
|
|
|
|
|
1367
|
return $n; |
815
|
|
|
|
|
|
|
} |
816
|
|
|
|
|
|
|
|
817
|
|
|
|
|
|
|
sub equal { |
818
|
6
|
|
|
6
|
1
|
13
|
my $obj1 = shift; |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
# If it was called as a class method, throw away the first |
821
|
|
|
|
|
|
|
# argument (the class name) |
822
|
6
|
100
|
|
|
|
16
|
$obj1 = shift unless ref $obj1; |
823
|
6
|
|
|
|
|
13
|
$obj1 = GetUnit($obj1); |
824
|
6
|
|
|
|
|
14
|
my $obj2 = GetUnit(shift); |
825
|
|
|
|
|
|
|
|
826
|
6
|
50
|
|
|
|
14
|
return 0 if CompareDim($obj1, $obj2); |
827
|
6
|
50
|
|
|
|
20
|
return 0 unless $obj1->{factor} == $obj2->{factor}; |
828
|
6
|
|
|
|
|
35
|
return 1; |
829
|
|
|
|
|
|
|
} |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
sub NewOne { |
832
|
417
|
|
|
417
|
0
|
2594
|
my $u = { |
833
|
|
|
|
|
|
|
'factor' => 1, |
834
|
|
|
|
|
|
|
'dim' => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], |
835
|
|
|
|
|
|
|
'type' => undef, |
836
|
|
|
|
|
|
|
'names' => [], |
837
|
|
|
|
|
|
|
'def' => undef, |
838
|
|
|
|
|
|
|
}; |
839
|
417
|
|
|
|
|
1137
|
bless $u, 'Physics::Unit'; |
840
|
|
|
|
|
|
|
} |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
sub AddNames { |
843
|
537
|
|
|
537
|
0
|
639
|
my $self = shift; |
844
|
537
|
|
|
|
|
538
|
my $n; |
845
|
537
|
|
|
|
|
1234
|
while ($n = shift) { |
846
|
1070
|
50
|
|
|
|
1993
|
croak "Can't use a reference as a name!" if ref $n; |
847
|
1070
|
50
|
|
|
|
1897
|
carp "Name $n is already defined" if LookName($n); |
848
|
1070
|
|
|
|
|
1180
|
push @{$self->{names}}, "\L$n"; |
|
1070
|
|
|
|
|
4112
|
|
849
|
1070
|
|
|
|
|
8638
|
$unit_by_name{$n} = $self; |
850
|
|
|
|
|
|
|
} |
851
|
|
|
|
|
|
|
} |
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
sub NewType { |
854
|
62
|
|
|
62
|
0
|
85
|
my ($self, $t) = @_; |
855
|
|
|
|
|
|
|
# my $oldtype = $self->type; |
856
|
|
|
|
|
|
|
# croak "NewType: the type $t is already defined as $oldtype" |
857
|
|
|
|
|
|
|
# if $oldtype ne 'unknown'; |
858
|
62
|
|
|
|
|
98
|
$self->{type} = $t; |
859
|
62
|
|
|
|
|
236
|
$prototype{$t} = $self; |
860
|
|
|
|
|
|
|
} |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
sub CreateUnit { |
863
|
483
|
|
|
483
|
0
|
641
|
my $def = shift; |
864
|
|
|
|
|
|
|
# argument was a Unit object |
865
|
483
|
100
|
|
|
|
824
|
return $def->new() if ref $def; |
866
|
|
|
|
|
|
|
# argument was either a simple name or an expression - doesn't matter |
867
|
482
|
|
|
|
|
674
|
$def = lc $def; |
868
|
|
|
|
|
|
|
|
869
|
482
|
|
|
|
|
718
|
my $u = expr($def); |
870
|
482
|
|
|
|
|
918
|
$u->{def} = $def; |
871
|
482
|
|
|
|
|
811
|
return $u; |
872
|
|
|
|
|
|
|
} |
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
sub CompareDim { |
875
|
692
|
|
|
692
|
0
|
1119
|
my ($u1, $u2) = @_; |
876
|
692
|
|
|
|
|
4641
|
my $d1 = $u1->{dim}; |
877
|
692
|
|
|
|
|
1020
|
my $d2 = $u2->{dim}; |
878
|
|
|
|
|
|
|
|
879
|
692
|
|
|
|
|
1176
|
for (0 .. $NumBases) { |
880
|
1370
|
100
|
|
|
|
3082
|
$$d1[$_] = 0 unless defined $$d1[$_]; |
881
|
1370
|
100
|
|
|
|
2792
|
$$d2[$_] = 0 unless defined $$d2[$_]; |
882
|
1370
|
|
|
|
|
1868
|
my $c = ($$d1[$_] <=> $$d2[$_]); |
883
|
1370
|
100
|
|
|
|
4457
|
return $c if $c; |
884
|
|
|
|
|
|
|
} |
885
|
44
|
|
|
|
|
152
|
return 0; |
886
|
|
|
|
|
|
|
} |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
sub LookName { |
889
|
1709
|
|
|
1709
|
0
|
3399
|
my $name = shift; |
890
|
1709
|
50
|
|
|
|
3631
|
return 3 if defined $prototype{$name}; |
891
|
1709
|
100
|
|
|
|
4373
|
return 2 if defined $unit_by_name{$name}; |
892
|
1154
|
100
|
|
|
|
2164
|
return 1 if defined $reserved_word{$name}; |
893
|
1134
|
|
|
|
|
3174
|
return 0; |
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
sub DebugString { |
897
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
898
|
0
|
|
|
|
|
0
|
my $s = $self->{factor}; |
899
|
0
|
|
|
|
|
0
|
$s .= '['. join (', ', @{$self->{dim}}) .']'; |
|
0
|
|
|
|
|
0
|
|
900
|
0
|
|
|
|
|
0
|
return $s; |
901
|
|
|
|
|
|
|
} |
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
sub CheckChange { |
904
|
702
|
|
|
702
|
0
|
855
|
my $self = shift; |
905
|
702
|
50
|
|
|
|
1611
|
carp "You're not allowed to change named units!" if $self->{names}[0]; |
906
|
702
|
|
|
|
|
1196
|
$self->{names} = []; |
907
|
702
|
|
|
|
|
1665
|
$self->{type} = $self->{def} = undef; |
908
|
|
|
|
|
|
|
} |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
# global variables used for parsing. |
911
|
|
|
|
|
|
|
my $def; # string being parsed |
912
|
|
|
|
|
|
|
my $tok; # the token type |
913
|
|
|
|
|
|
|
my $numval; # the value when the token is a number |
914
|
|
|
|
|
|
|
my $tokname; # when it is a name |
915
|
|
|
|
|
|
|
my $indent; # used to indent debug messages |
916
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
# parser |
918
|
|
|
|
|
|
|
sub expr { |
919
|
484
|
100
|
|
484
|
0
|
1028
|
if (@_) { |
920
|
482
|
|
|
|
|
687
|
$def = shift; |
921
|
482
|
|
|
|
|
732
|
get_token(); |
922
|
|
|
|
|
|
|
} |
923
|
|
|
|
|
|
|
|
924
|
484
|
50
|
|
|
|
1013
|
print ' ' x $indent, "inside expr\n" if $debug; |
925
|
484
|
|
|
|
|
1008
|
$indent++; |
926
|
484
|
|
|
|
|
776
|
my $u = term(); |
927
|
|
|
|
|
|
|
|
928
|
484
|
|
|
|
|
564
|
for (;;) { |
929
|
623
|
100
|
|
|
|
1421
|
if ($tok eq 'times') { |
|
|
100
|
|
|
|
|
|
930
|
3
|
|
|
|
|
41
|
get_token(); |
931
|
3
|
|
|
|
|
49
|
$u->times(term()); |
932
|
|
|
|
|
|
|
} |
933
|
|
|
|
|
|
|
elsif ($tok eq 'divide') { |
934
|
136
|
|
|
|
|
222
|
get_token(); |
935
|
136
|
|
|
|
|
249
|
$u->divide(term()); |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
else { |
938
|
484
|
50
|
|
|
|
884
|
print ' ' x $indent, "expr: returning ", $u->DebugString, "\n" |
939
|
|
|
|
|
|
|
if $debug; |
940
|
484
|
|
|
|
|
476
|
$indent--; |
941
|
484
|
|
|
|
|
892
|
return $u; |
942
|
|
|
|
|
|
|
} |
943
|
|
|
|
|
|
|
} |
944
|
|
|
|
|
|
|
} |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
sub term { |
947
|
623
|
50
|
|
623
|
0
|
1067
|
print ' ' x $indent, "inside term\n" if $debug; |
948
|
623
|
|
|
|
|
621
|
$indent++; |
949
|
623
|
|
|
|
|
934
|
my $u = Factor(); |
950
|
|
|
|
|
|
|
|
951
|
623
|
|
|
|
|
698
|
for (;;) { |
952
|
887
|
50
|
|
|
|
1490
|
print ' ' x $indent, "inside term loop\n" if $debug; |
953
|
887
|
100
|
66
|
|
|
7502
|
if ($tok eq 'number' || |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
954
|
|
|
|
|
|
|
$tok eq 'name' || |
955
|
|
|
|
|
|
|
$tok eq 'prefix' || |
956
|
|
|
|
|
|
|
$tok eq 'square' || |
957
|
|
|
|
|
|
|
$tok eq 'cubic') |
958
|
|
|
|
|
|
|
{ |
959
|
264
|
|
|
|
|
1380
|
$u->times(Factor()); |
960
|
|
|
|
|
|
|
} |
961
|
|
|
|
|
|
|
else { |
962
|
623
|
50
|
|
|
|
1092
|
print ' ' x $indent, "term: returning ", $u->DebugString, "\n" |
963
|
|
|
|
|
|
|
if $debug; |
964
|
623
|
|
|
|
|
847
|
$indent--; |
965
|
623
|
|
|
|
|
1393
|
return $u; |
966
|
|
|
|
|
|
|
} |
967
|
|
|
|
|
|
|
} |
968
|
|
|
|
|
|
|
} |
969
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
sub Factor { |
971
|
887
|
50
|
|
887
|
0
|
4636
|
print ' ' x $indent, "inside factor\n" if $debug; |
972
|
887
|
|
|
|
|
870
|
$indent++; |
973
|
|
|
|
|
|
|
|
974
|
887
|
|
|
|
|
1255
|
my $u = prim(); |
975
|
|
|
|
|
|
|
|
976
|
887
|
|
|
|
|
984
|
for (;;) { |
977
|
964
|
50
|
|
|
|
1762
|
print ' ' x $indent, "inside factor loop\n" if $debug; |
978
|
964
|
100
|
|
|
|
1486
|
if ($tok eq 'exponent') { |
979
|
77
|
|
|
|
|
139
|
get_token(); |
980
|
77
|
50
|
|
|
|
264
|
die 'Exponent must be an integer' |
981
|
|
|
|
|
|
|
unless $tok eq 'number'; |
982
|
77
|
|
|
|
|
175
|
$u->power($numval); |
983
|
77
|
|
|
|
|
127
|
get_token(); |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
else { |
986
|
887
|
50
|
|
|
|
1723
|
print ' ' x $indent, "factor: returning ", |
987
|
|
|
|
|
|
|
$u->DebugString, "\n" if $debug; |
988
|
887
|
|
|
|
|
937
|
$indent--; |
989
|
887
|
|
|
|
|
1821
|
return $u; |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
} |
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
sub prim { |
995
|
959
|
50
|
|
959
|
0
|
4476
|
print ' ' x $indent, "inside prim\n" if $debug; |
996
|
959
|
|
|
|
|
967
|
$indent++; |
997
|
|
|
|
|
|
|
|
998
|
959
|
|
|
|
|
921
|
my $u; |
999
|
|
|
|
|
|
|
|
1000
|
959
|
100
|
|
|
|
2482
|
if ($tok eq 'number') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1001
|
338
|
50
|
|
|
|
596
|
print ' ' x $indent, "got number $numval\n" if $debug; |
1002
|
|
|
|
|
|
|
# Create a new Unit object to represent this number |
1003
|
338
|
|
|
|
|
613
|
$u = NewOne(); |
1004
|
338
|
|
|
|
|
636
|
$u->{factor} = $numval; |
1005
|
338
|
|
|
|
|
505
|
get_token(); |
1006
|
|
|
|
|
|
|
} |
1007
|
|
|
|
|
|
|
elsif ($tok eq 'prefix') { |
1008
|
62
|
50
|
|
|
|
119
|
print ' ' x $indent, "got a prefix: ", "$tokname\n" if $debug; |
1009
|
62
|
|
|
|
|
113
|
$u = GetUnit($tokname)->copy(); |
1010
|
62
|
|
|
|
|
108
|
get_token(); |
1011
|
62
|
|
|
|
|
156
|
$u->times(prim()); |
1012
|
|
|
|
|
|
|
} |
1013
|
|
|
|
|
|
|
elsif ($tok eq 'name') { |
1014
|
547
|
50
|
|
|
|
1079
|
print ' ' x $indent, "got a name: ", "$tokname\n" if $debug; |
1015
|
547
|
|
|
|
|
872
|
$u = GetUnit($tokname)->copy(); |
1016
|
547
|
|
|
|
|
1007
|
get_token(); |
1017
|
|
|
|
|
|
|
} |
1018
|
|
|
|
|
|
|
elsif ($tok eq 'lparen') { |
1019
|
2
|
50
|
|
|
|
8
|
print ' ' x $indent, "got a left paren\n" if $debug; |
1020
|
2
|
|
|
|
|
5
|
get_token(); |
1021
|
2
|
|
|
|
|
11
|
$u = expr(); |
1022
|
2
|
50
|
|
|
|
9
|
die 'Missing right parenthesis' |
1023
|
|
|
|
|
|
|
unless $tok eq 'rparen'; |
1024
|
2
|
|
|
|
|
5
|
get_token(); |
1025
|
|
|
|
|
|
|
} |
1026
|
|
|
|
|
|
|
elsif ($tok eq 'end') { |
1027
|
0
|
0
|
|
|
|
0
|
print ' ' x $indent, "got end\n" if $debug; |
1028
|
0
|
|
|
|
|
0
|
$u = NewOne(); |
1029
|
|
|
|
|
|
|
} |
1030
|
|
|
|
|
|
|
elsif ($tok eq 'square') { |
1031
|
8
|
|
|
|
|
21
|
get_token(); |
1032
|
8
|
|
|
|
|
16
|
$u = prim()->power(2); |
1033
|
|
|
|
|
|
|
} |
1034
|
|
|
|
|
|
|
elsif ($tok eq 'cubic') { |
1035
|
2
|
|
|
|
|
7
|
get_token(); |
1036
|
2
|
|
|
|
|
9
|
$u = prim()->power(3); |
1037
|
|
|
|
|
|
|
} |
1038
|
|
|
|
|
|
|
else { |
1039
|
0
|
|
|
|
|
0
|
die 'Primary expected'; |
1040
|
|
|
|
|
|
|
} |
1041
|
|
|
|
|
|
|
|
1042
|
959
|
50
|
|
|
|
1907
|
print ' ' x $indent, "prim: returning ", $u->DebugString, "\n" |
1043
|
|
|
|
|
|
|
if $debug; |
1044
|
959
|
|
|
|
|
934
|
$indent--; |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
# Before returning, see if the *next* token is 'squared' or 'cubed' |
1047
|
959
|
|
|
|
|
945
|
for(;;) { |
1048
|
960
|
100
|
|
|
|
2240
|
if ($tok eq 'squared') { |
|
|
50
|
|
|
|
|
|
1049
|
1
|
|
|
|
|
3
|
get_token(); |
1050
|
1
|
|
|
|
|
3
|
$u->power(2); |
1051
|
|
|
|
|
|
|
} |
1052
|
|
|
|
|
|
|
elsif ($tok eq 'cubed') { |
1053
|
0
|
|
|
|
|
0
|
get_token(); |
1054
|
0
|
|
|
|
|
0
|
$u->power(3); |
1055
|
|
|
|
|
|
|
} |
1056
|
|
|
|
|
|
|
else { |
1057
|
959
|
|
|
|
|
1149
|
last; |
1058
|
|
|
|
|
|
|
} |
1059
|
|
|
|
|
|
|
} |
1060
|
|
|
|
|
|
|
|
1061
|
959
|
|
|
|
|
1612
|
return $u; |
1062
|
|
|
|
|
|
|
} |
1063
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
sub get_token { |
1065
|
1737
|
50
|
|
1737
|
0
|
3586
|
print ' ' x $indent, "get_token, looking at '$def'\n" if $debug; |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
# First remove whitespace at the begining |
1068
|
1737
|
|
|
|
|
5316
|
$def =~ s/^\s+//; |
1069
|
|
|
|
|
|
|
|
1070
|
1737
|
100
|
|
|
|
8585
|
if ($def eq '') { |
1071
|
482
|
|
|
|
|
588
|
$tok = 'end'; |
1072
|
482
|
|
|
|
|
799
|
return; |
1073
|
|
|
|
|
|
|
} |
1074
|
|
|
|
|
|
|
|
1075
|
1255
|
100
|
100
|
|
|
12466
|
if ($def =~ s/^\(//) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1076
|
2
|
|
|
|
|
5
|
$tok = 'lparen'; |
1077
|
|
|
|
|
|
|
} |
1078
|
|
|
|
|
|
|
elsif ($def =~ s/^\)//) { |
1079
|
2
|
|
|
|
|
5
|
$tok = 'rparen'; |
1080
|
|
|
|
|
|
|
} |
1081
|
|
|
|
|
|
|
elsif ($def =~ s/^\*\*// || $def =~ s/^\^//) { |
1082
|
77
|
|
|
|
|
148
|
$tok = 'exponent'; |
1083
|
|
|
|
|
|
|
} |
1084
|
|
|
|
|
|
|
elsif ($def =~ s/^\*//) { |
1085
|
3
|
|
|
|
|
7
|
$tok = 'times'; |
1086
|
|
|
|
|
|
|
} |
1087
|
|
|
|
|
|
|
elsif ($def =~ s/^\///) { |
1088
|
127
|
|
|
|
|
239
|
$tok = 'divide'; |
1089
|
|
|
|
|
|
|
} |
1090
|
|
|
|
|
|
|
elsif ($def =~ s/^$number_re//io) { |
1091
|
415
|
|
|
|
|
968
|
$numval = $1 + 0; # convert to a number |
1092
|
415
|
|
|
|
|
867
|
$tok = 'number'; |
1093
|
|
|
|
|
|
|
} |
1094
|
|
|
|
|
|
|
elsif ($def =~ /^([^\ \n\r\t\f\(\)\/\^\*]+)/) { |
1095
|
629
|
|
|
|
|
1110
|
my $t = $1; |
1096
|
629
|
|
|
|
|
1129
|
my $l = LookName($t); |
1097
|
|
|
|
|
|
|
|
1098
|
629
|
100
|
|
|
|
1632
|
if ($l == 1) { |
|
|
100
|
|
|
|
|
|
1099
|
20
|
|
|
|
|
37
|
$tok = $reserved_word{$t}; |
1100
|
20
|
|
|
|
|
26
|
$tokname = $t; |
1101
|
20
|
|
|
|
|
37
|
$def = substr $def, length($t); |
1102
|
20
|
|
|
|
|
29
|
return; |
1103
|
|
|
|
|
|
|
} |
1104
|
|
|
|
|
|
|
elsif ($l == 2) { |
1105
|
547
|
|
|
|
|
802
|
$tok = 'name'; |
1106
|
547
|
|
|
|
|
615
|
$tokname = $t; |
1107
|
547
|
|
|
|
|
1083
|
$def = substr $def, length($t); |
1108
|
547
|
|
|
|
|
847
|
return; |
1109
|
|
|
|
|
|
|
} |
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
# Couldn't find the name on the first try, look for prefix |
1112
|
62
|
|
|
|
|
481
|
for my $p (keys %prefix) { |
1113
|
971
|
100
|
|
|
|
9660
|
if ($t =~ /^$p/i) { |
1114
|
62
|
|
|
|
|
137
|
$tok = 'prefix'; |
1115
|
62
|
|
|
|
|
85
|
$tokname = $p; |
1116
|
62
|
|
|
|
|
130
|
$def = substr $def, length($p); |
1117
|
62
|
|
|
|
|
152
|
return; |
1118
|
|
|
|
|
|
|
} |
1119
|
|
|
|
|
|
|
} |
1120
|
0
|
|
|
|
|
|
die "Unknown unit: $t\n"; |
1121
|
|
|
|
|
|
|
} |
1122
|
|
|
|
|
|
|
else { |
1123
|
0
|
|
|
|
|
|
die "Illegal token in $def"; |
1124
|
|
|
|
|
|
|
} |
1125
|
|
|
|
|
|
|
} |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
1; |
1128
|
|
|
|
|
|
|
__END__ |