[system] / trunk / pg / lib / Units.pm Repository: Repository Listing bbplugincoursesdistsnplrochestersystemwww

# View of /trunk/pg/lib/Units.pm

Mon Nov 26 17:58:28 2007 UTC (12 years, 2 months ago) by glarose
File size: 18411 byte(s)
```Add mg as a mass unit.  Hopefully the fact that this wasn't here before
is an oddity rather than indicating that I'm screwing something up.
```

```    1
2
3 # This is the "exported" subroutine.  Use this to evaluate the units given in an answer.
4
5 sub evaluate_units {
6   &Units::evaluate_units;
7 }
8
9 # Methods for evaluating units in answers
10 package Units;
11
12 #require Exporter;
13 #@ISA = qw(Exporter);
14 #@EXPORT = qw(evaluate_units);
15
16
17 # compound units are entered such as m/sec^2 or kg*m/sec^2
18 # the format is unit[^power]*unit^[*power].../  unit^power*unit^power....
19 # there can be only one / in a unit.
20 # powers can be negative integers as well as positive integers.
21
22     # These subroutines return a unit hash.
23     # A unit hash has the entries
24     #      factor => number   number can be any real number
25     #      m      => power    power is a signed integer
26     #      kg     => power
27     #      s      => power
29     #      degC   => power
30     #      degF   => power
31     #      degK   => power
32     #      perhaps other fundamental units will added later as well.
33
34 # Unfortunately there will be no automatic conversion between the different
35 # temperature scales since we haven't allowed for affine conversions.
36
37 our %fundamental_units = ('factor' => 1,
38                      'm'      => 0,
39                      'kg'     => 0,
40                      's'      => 0,
42                      'degC'   => 0,
43                      'degF'   => 0,
44                      'degK'   => 0,
45                      'mol'    => 0,  # moles, treated as a fundamental unit?
46                      'amp'    => 0,
47 );
48
49
50 # This hash contains all of the units which will be accepted.  These must
51 #be defined in terms of the
52 # fundamental units given above.  If the power of the fundamental unit is
53 #not included it is assumed to
54 # be zero.
55
56 our \$PI = 4*atan2(1,1);
57 #         9.80665 m/s^2  -- standard accelearationof gravity
58
59 our %known_units = ('m'  => {
60                            'factor'    => 1,
61                            'm'         => 1
62                           },
63                  'kg'  => {
64                            'factor'    => 1,
65                            'kg'        => 1
66                           },
67                  's'  => {
68                            'factor'    => 1,
69                            's'         => 1
70                           },
72                            'factor'    => 1,
74                           },
75                'degC' => {
76                            'factor'    => 1,
77                            'degC'      => 1
78                           },
79                'degF' => {
80                            'factor'    => 1,
81                            'degF'      => 1
82                           },
83                'degK' => {
84                            'factor'    => 1,
85                            'degK'      => 1
86                           },
87                'mol'  => {
88                            'factor'    =>1,
89                            'mol'       =>1
90                          },
91                 'amp'  => {
92                            'factor'    => 1,
93                            'amp'       => 1,
94                          },
95 # ANGLES
96 # deg  -- degrees
97 #
98                 'deg'  => {
99                            'factor'    => 0.0174532925,
101                           },
102 # TIME
103 # s     -- seconds
104 # ms    -- miliseconds
105 # min   -- minutes
106 # hr    -- hours
107 # day   -- days
108 # yr    -- years  -- 365 days in a year
109 #
110                   'ms'  => {
111                            'factor'    => 0.001,
112                            's'         => 1
113                           },
114                   'min'  => {
115                            'factor'    => 60,
116                            's'         => 1
117                           },
118                   'hr'  => {
119                            'factor'    => 3600,
120                            's'         => 1
121                           },
122                   'day'  => {
123                            'factor'    => 86400,
124                            's'         => 1
125                           },
126                   'yr'  => {
127                            'factor'    => 31557600,
128                            's'         => 1
129                           },
130
131 # LENGTHS
132 # m    -- meters
133 # cm   -- centimeters
134 # km   -- kilometers
135 # mm   -- millimeters
136 # micron -- micrometer
137 # um   -- micrometer
138 # nm   -- nanometer
139 # A    -- Angstrom
140 #
141                  'km'  => {
142                            'factor'    => 1000,
143                            'm'         => 1
144                           },
145                  'cm'  => {
146                            'factor'    => 0.01,
147                            'm'         => 1
148                           },
149                  'mm'  => {
150                            'factor'    => 0.001,
151                            'm'         => 1
152                           },
153              'micron'  => {
154                            'factor'    => 10**(-6),
155                            'm'         => 1
156                           },
157                  'um'  => {
158                            'factor'    => 10**(-6),
159                            'm'         => 1
160                           },
161                  'nm'  => {
162                            'factor'    => 10**(-9),
163                            'm'         => 1
164                           },
165                   'A'  => {
166                            'factor'    => 10**(-10),
167                            'm'         => 1
168                           },
169 # ENGLISH LENGTHS
170 # in    -- inch
171 # ft    -- feet
172 # mi    -- mile
173 # light-year
174 #
175                  'in'  => {
176                            'factor'    => 0.0254,
177                            'm'         => 1
178                           },
179                  'ft'  => {
180                            'factor'    => 0.3048,
181                            'm'         => 1
182                           },
183                  'mi'  => {
184                            'factor'    => 1609.344,
185                            'm'         => 1
186                           },
187          'light-year'  => {
188                            'factor'    => 9.46E15,
189                            'm'         => 1
190                           },
191 # VOLUME
192 # L   -- liter
193 # ml -- milliliters
194 # cc -- cubic centermeters
195 #
196                   'L'  => {
197                            'factor'    => 0.001,
198                            'm'         => 3
199                           },
200                  'cc'  => {
201                            'factor'    => 10**(-6),
202                            'm'         => 3,
203                           },
204                  'ml'  => {
205                            'factor'    => 10**(-6),
206                            'm'         => 3,
207                           },
208 # VELOCITY
209 # knots -- nautical miles per hour
210 #
211               'knots'  => {
212                            'factor'    =>  0.5144444444,
213                            'm'         => 1,
214                            's'         => -1
215                           },
216 # MASS
217 # mg   -- miligrams
218 # g    -- grams
219 # kg   -- kilograms
220 #
221                   'mg'  => {
222                            'factor'    => 0.000001,
223                            'kg'        => 1
224                           },
225                   'g'  => {
226                            'factor'    => 0.001,
227                            'kg'        => 1
228                           },
229 # ENGLISH MASS
230 # slug -- slug
231 #
232                'slug'  => {
233                            'factor'    => 14.6,
234                            'kg'         => 1
235                           },
236 # FREQUENCY
237 # Hz    -- Hertz
238 # kHz   -- kilo Hertz
239 # MHz   -- mega Herta
240 #
241                  'Hz'  => {
242                            'factor'    => 2*\$PI,  #2pi
243                            's'         => -1,
245                           },
246                 'kHz'  => {
247                            'factor'    => 1000*2*\$PI,  #1000*2pi,
248                            's'         => -1,
250                           },
251                 'MHz'  => {
252                            'factor'    => (10**6)*2*\$PI,  #10^6 * 2pi,
253                            's'         => -1,
255                           },
256                 'rev'  => {
257                       'factor'   => 2*\$PI,
259                       },
260                 'cycles'  => {
261                       'factor'   => 2*\$PI,
263                       },
264
265 # COMPOUND UNITS
266 #
267 # FORCE
268 # N      -- Newton
269 # microN -- micro Newton
270 # uN     -- micro Newton
271 # dyne   -- dyne
272 # lb     -- pound
273 # ton    -- ton
274 #
275                  'N'  => {
276                            'factor'    => 1,
277                            'm'         => 1,
278                            'kg'        => 1,
279                            's'         => -2
280                           },
281             'microN'  => {
282                            'factor'    => 10**(-6),
283                            'm'         => 1,
284                            'kg'        => 1,
285                            's'         => -2
286                           },
287                  'uN'  => {
288                            'factor'    => 10**(-6),
289                            'm'         => 1,
290                            'kg'        => 1,
291                            's'         => -2
292                           },
293                'dyne'  => {
294                            'factor'    => 10**(-5),
295                            'm'         => 1,
296                            'kg'        => 1,
297                            's'         => -2
298                           },
299                  'lb'  => {
300                            'factor'    => 4.4482216152605,
301                            'm'         => 1,
302                            'kg'        => 1,
303                            's'         => -2
304                           },
305                 'ton'  => {
306                            'factor'    => 8900,
307                            'm'         => 1,
308                            'kg'        => 1,
309                            's'         => -2
310                           },
311 # ENERGY
312 # J      -- Joule
313 # kJ     -- kilo Joule
314 # erg    -- erg
315 # lbf    -- foot pound
316 # cal    -- calorie
317 # kcal   -- kilocalorie
318 # eV     -- electron volt
319 # kWh    -- kilo Watt hour
320 #
321                     'J'  => {
322                            'factor'    => 1,
323                            'm'         => 2,
324                            'kg'        => 1,
325                            's'         => -2
326                           },
327                  'kJ'  => {
328                            'factor'    => 1000,
329                            'm'         => 2,
330                            'kg'        => 1,
331                            's'         => -2
332                           },
333                 'erg'  => {
334                            'factor'    => 10**(-7),
335                            'm'         => 2,
336                            'kg'        => 1,
337                            's'         => -2
338                           },
339                 'lbf'  => {
340                            'factor'    => 1.35582,
341                            'm'         => 2,
342                            'kg'        => 1,
343                            's'         => -2
344                           },
345                 'cal'  => {
346                            'factor'    => 4.19,
347                            'm'         => 2,
348                            'kg'        => 1,
349                            's'         => -2
350                           },
351                'kcal'  => {
352                            'factor'    => 4190,
353                            'm'         => 2,
354                            'kg'        => 1,
355                            's'         => -2
356                           },
357                 'eV'  => {
358                            'factor'    => 1.60E-9,
359                            'm'         => 2,
360                            'kg'        => 1,
361                            's'         => -2
362                           },
363                 'kWh'  => {
364                            'factor'    => 3.6E6,
365                            'm'         => 2,
366                            'kg'        => 1,
367                            's'         => -2
368                           },
369 # POWER
370 # W      -- Watt
371 # kW     -- kilo Watt
372 # hp     -- horse power  746 W
373 #
374                  'W'  => {
375                            'factor'    => 1,
376                            'm'         => 2,
377                            'kg'        => 1,
378                            's'         => -3
379                           },
380                  'kW'  => {
381                            'factor'    => 1000,
382                            'm'         => 2,
383                            'kg'        => 1,
384                            's'         => -3
385                           },
386                 'hp'   => {
387                            'factor'    => 746,
388                            'm'         => 2,
389                            'kg'        => 1,
390                            's'         => -3
391                           },
392 # PRESSURE
393 # Pa     -- Pascal
394 # kPa    -- kilo Pascal
395 # atm    -- atmosphere
396                  'Pa'  => {
397                            'factor'    => 1,
398                            'm'         => -1,
399                            'kg'        => 1,
400                            's'         => -2
401                           },
402                 'kPa'  => {
403                            'factor'    => 1000,
404                            'm'         => -1,
405                            'kg'        => 1,
406                            's'         => -2
407                           },
408                 'atm'  => {
409                            'factor'    => 1.01E5,
410                            'm'         => -1,
411                            'kg'        => 1,
412                            's'         => -2
413                           },
414 # ELECTRICAL UNITS (incomplete)
415 # C      -- Coulomb
416 # V      -- volt
417 # mV     -- milivolt
418 # kV     -- kilovolt
419 # MV     -- megavolt
423 # ohm    -- ohm
424 # kohm   -- kilo-ohm
425                 'C'    => {
426                            'factor'    => 1,
427                            'amp'       => 1,
428                            's'         => 1,
429                          },
430                 'V'    => {
431                            'factor'    => 1,
432                            'J'         => 1,
433                            'C'         => -1,
434                          },
435                 'mV'   => {
436                            'factor'    => 0.001,
437                            'V'         => 1,
438                          },
439                 'kV'   => {
440                            'factor'    => 1000,
441                            'V'         => 1,
442                          },
443                 'MV'   => {
444                            'factor'    => 10**(6),
445                            'V'         => 1,
446                          },
447                 'F'    => {
448                            'factor'    => 1,
449                            'C'         => 1,
450                            'V'         => -1,
451                          },
452                 'mF'   => {
453                            'factor'    => 0.001,
454                            'F'         => 1,
455                          },
456                 'uF'   => {
457                            'factor'    => 10**(-6),
458                            'F'         => 1,
459                          },
460                 'ohm'  => {
461                            'factor'    => 1,
462                            'V'         => 1,
463                            'amp'       => -1,
464                          },
465                 'kohm' => {
466                            'factor'    => 1000,
467                            'ohm'       => 1,
468                          },
469 );
470
471
472
473 sub process_unit {
474
475   my \$string = shift;
476     die ("UNIT ERROR: No units were defined.") unless defined(\$string);  #
477   #split the string into numerator and denominator --- the separator is /
478     my (\$numerator,\$denominator) = split( m{/}, \$string );
479
480
481
482   \$denominator = "" unless defined(\$denominator);
483   my %numerator_hash = process_term(\$numerator);
484   my %denominator_hash =  process_term(\$denominator);
485
486
487     my %unit_hash = %fundamental_units;
488   my \$u;
489   foreach \$u (keys %unit_hash) {
490     if ( \$u eq 'factor' ) {
491       \$unit_hash{\$u} = \$numerator_hash{\$u}/\$denominator_hash{\$u};  # calculate the correction factor for the unit
492     } else {
493
494       \$unit_hash{\$u} = \$numerator_hash{\$u} - \$denominator_hash{\$u}; # calculate the power of the fundamental unit in the unit
495     }
496   }
497   # return a unit hash.
498   return(%unit_hash);
499 }
500
501 sub process_term {
502   my \$string = shift;
503   my %unit_hash = %fundamental_units;
504   if (\$string) {
505
506     #split the numerator or denominator into factors -- the separators are *
507
508       my @factors = split(/\*/, \$string);
509
510     my \$f;
511     foreach \$f (@factors) {
512       my %factor_hash = process_factor(\$f);
513
514       my \$u;
515       foreach \$u (keys %unit_hash) {
516         if ( \$u eq 'factor' ) {
517           \$unit_hash{\$u} = \$unit_hash{\$u} * \$factor_hash{\$u};  # calculate the correction factor for the unit
518         } else {
519
520           \$unit_hash{\$u} = \$unit_hash{\$u} + \$factor_hash{\$u}; # calculate the power of the fundamental unit in the unit
521         }
522       }
523     }
524   }
525   #returns a unit hash.
526   #print "process_term returns", %unit_hash, "\n";
527   return(%unit_hash);
528 }
529
530
531 sub process_factor {
532   my \$string = shift;
533   #split the factor into unit and powers
534
535     my (\$unit_name,\$power) = split(/\^/, \$string);
536   \$power = 1 unless defined(\$power);
537   my %unit_hash = %fundamental_units;
538
539   if ( defined( \$known_units{\$unit_name} )  ) {
540     my %unit_name_hash = %{\$known_units{\$unit_name}};   # \$reference_units contains all of the known units.
541     my \$u;
542     foreach \$u (keys %unit_hash) {
543       if ( \$u eq 'factor' ) {
544         \$unit_hash{\$u} = \$unit_name_hash{\$u}**\$power;  # calculate the correction factor for the unit
545       } else {
546         my \$fundamental_unit = \$unit_name_hash{\$u};
547         \$fundamental_unit = 0 unless defined(\$fundamental_unit); # a fundamental unit which doesn't appear in the unit need not be defined explicitly
548         \$unit_hash{\$u} = \$fundamental_unit*\$power; # calculate the power of the fundamental unit in the unit
549       }
550     }
551   } else {
552     die "UNIT ERROR Unrecognizable unit: |\$unit_name|";
553   }
554   %unit_hash;
555 }
556
557 # This is the "exported" subroutine.  Use this to evaluate the units given in an answer.
558 sub evaluate_units {
559   my \$unit = shift;
560   my %output =  eval(q{process_unit( \$unit)});
561   %output = %fundamental_units if \$@;  # this is what you get if there is an error.
562   \$output{'ERROR'}=\$@ if \$@;
563   %output;
564 }
565 #################
566
567 1;
```