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

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

Mon Jun 9 17:36:12 2003 UTC (16 years, 7 months ago) by apizer
File size: 15898 byte(s)
removed unneccesary shebang lines

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
35 my %fundamental_units = ('factor' => 1,
36                      'm'      => 0,
37                      'kg'     => 0,
38                      's'      => 0,
40                      'degC'   => 0,
41                      'degF'   => 0,
42                      'degK'   => 0,
43                      'mol'    => 0,  # moles, treated as a fundamental unit?
44 );
45
46 # This hash contains all of the units which will be accepted.  These must
47 #be defined in terms of the
48 # fundamental units given above.  If the power of the fundamental unit is
49 #not included it is assumed to
50 # be zero.
51
52 my \$PI = 4*atan2(1,1);
53
54 my %known_units = ('m'  => {
55                            'factor'    => 1,
56                            'm'         => 1
57                           },
58                  'kg'  => {
59                            'factor'    => 1,
60                            'kg'        => 1
61                           },
62                  's'  => {
63                            'factor'    => 1,
64                            's'         => 1
65                           },
67                            'factor'    => 1,
69                           },
70                'degC' => {
71                            'factor'    => 1,
72                            'degC'      => 1
73                           },
74                'degF' => {
75                            'factor'    => 1,
76                            'degF'      => 1
77                           },
78                'degK' => {
79                            'factor'    => 1,
80                            'degK'      => 1
81                           },
82                'mol'  => {
83                       'factor'  =>1,
84                       'mol'   =>1
85                       },
86 # ANGLES
87 # deg  -- degrees
88 #
89                 'deg'  => {
90                            'factor'    => 0.0174532925,
92                           },
93 # TIME
94 # s     -- seconds
95 # ms    -- miliseconds
96 # min   -- minutes
97 # hr    -- hours
98 # day   -- days
99 # yr    -- years  -- 365 days in a year
100 #
101                   'ms'  => {
102                            'factor'    => 0.001,
103                            's'         => 1
104                           },
105                   'min'  => {
106                            'factor'    => 60,
107                            's'         => 1
108                           },
109                   'hr'  => {
110                            'factor'    => 3600,
111                            's'         => 1
112                           },
113                   'day'  => {
114                            'factor'    => 86400,
115                            's'         => 1
116                           },
117                   'yr'  => {
118                            'factor'    => 31557600,
119                            's'         => 1
120                           },
121
122 # LENGTHS
123 # m    -- meters
124 # cm   -- centimeters
125 # km   -- kilometers
126 # mm   -- millimeters
127 # micron -- micrometer
128 # um   -- micrometer
129 # nm   -- nanometer
130 # A    -- Angstrom
131 #
132                  'km'  => {
133                            'factor'    => 1000,
134                            'm'         => 1
135                           },
136                  'cm'  => {
137                            'factor'    => 0.01,
138                            'm'         => 1
139                           },
140                  'mm'  => {
141                            'factor'    => 0.001,
142                            'm'         => 1
143                           },
144              'micron'  => {
145                            'factor'    => 10**(-6),
146                            'm'         => 1
147                           },
148                  'um'  => {
149                            'factor'    => 10**(-6),
150                            'm'         => 1
151                           },
152                  'nm'  => {
153                            'factor'    => 10**(-9),
154                            'm'         => 1
155                           },
156                   'A'  => {
157                            'factor'    => 10**(-10),
158                            'm'         => 1
159                           },
160 # ENGLISH LENGTHS
161 # in    -- inch
162 # ft    -- feet
163 # mi    -- mile
164 # light-year
165 #
166                  'in'  => {
167                            'factor'    => 0.0254,
168                            'm'         => 1
169                           },
170                  'ft'  => {
171                            'factor'    => 0.3048,
172                            'm'         => 1
173                           },
174                  'mi'  => {
175                            'factor'    => 1609.344,
176                            'm'         => 1
177                           },
178          'light-year'  => {
179                            'factor'    => 9.46E15,
180                            'm'         => 1
181                           },
182 # VOLUME
183 # L   -- liter
184 # ml -- milliliters
185 # cc -- cubic centermeters
186 #
187                   'L'  => {
188                            'factor'    => 0.001,
189                            'm'         => 3
190                           },
191                  'cc'  => {
192                            'factor'    => 10**(-6),
193                            'm'         => 3,
194                           },
195                  'ml'  => {
196                            'factor'    => 10**(-6),
197                            'm'         => 3,
198                           },
199 # VELOCITY
200 # knots -- nautical miles per hour
201 #
202               'knots'  => {
203                            'factor'    =>  0.5144444444,
204                            'm'         => 1,
205                            's'         => -1
206                           },
207 # MASS
208 # g    -- grams
209 # kg   -- kilograms
210 #
211                   'g'  => {
212                            'factor'    => 0.001,
213                            'kg'         => 1
214                           },
215 # ENGLISH MASS
216 # slug -- slug
217 #
218                'slug'  => {
219                            'factor'    => 14.6,
220                            'kg'         => 1
221                           },
222 # FREQUENCY
223 # Hz    -- Hertz
224 # kHz   -- kilo Hertz
225 # MHz   -- mega Herta
226 #
227                  'Hz'  => {
228                            'factor'    => 2*\$PI,  #2pi
229                            's'         => -1,
231                           },
232                 'kHz'  => {
233                            'factor'    => 1000*2*\$PI,  #1000*2pi,
234                            's'         => -1,
236                           },
237                 'MHz'  => {
238                            'factor'    => (10**6)*2*\$PI,  #10^6 * 2pi,
239                            's'         => -1,
241                           },
242                 'rev'  => {
243                       'factor'   => 2*\$PI,
245                       },
246                 'cycles'  => {
247                       'factor'   => 2*\$PI,
249                       },
250
251 # COMPOUND UNITS
252 #
253 # FORCE
254 # N      -- Newton
255 # microN -- micro Newton
256 # uN     -- micro Newton
257 # dyne   -- dyne
258 # lb     -- pound
259 # ton    -- ton
260 #
261                  'N'  => {
262                            'factor'    => 1,
263                            'm'         => 1,
264                            'kg'        => 1,
265                            's'         => -2
266                           },
267             'microN'  => {
268                            'factor'    => 10**(-6),
269                            'm'         => 1,
270                            'kg'        => 1,
271                            's'         => -2
272                           },
273                  'uN'  => {
274                            'factor'    => 10**(-6),
275                            'm'         => 1,
276                            'kg'        => 1,
277                            's'         => -2
278                           },
279                'dyne'  => {
280                            'factor'    => 10**(-5),
281                            'm'         => 1,
282                            'kg'        => 1,
283                            's'         => -2
284                           },
285                  'lb'  => {
286                            'factor'    => 4.45,
287                            'm'         => 1,
288                            'kg'        => 1,
289                            's'         => -2
290                           },
291                 'ton'  => {
292                            'factor'    => 8900,
293                            'm'         => 1,
294                            'kg'        => 1,
295                            's'         => -2
296                           },
297 # ENERGY
298 # J      -- Joule
299 # kJ     -- kilo Joule
300 # erg    -- erg
301 # lbf    -- foot pound
302 # cal    -- calorie
303 # kcal   -- kilocalorie
304 # eV     -- electron volt
305 # kWh    -- kilo Watt hour
306 #
307                     'J'  => {
308                            'factor'    => 1,
309                            'm'         => 2,
310                            'kg'        => 1,
311                            's'         => -2
312                           },
313                  'kJ'  => {
314                            'factor'    => 1000,
315                            'm'         => 2,
316                            'kg'        => 1,
317                            's'         => -2
318                           },
319                 'erg'  => {
320                            'factor'    => 10**(-7),
321                            'm'         => 2,
322                            'kg'        => 1,
323                            's'         => -2
324                           },
325                 'lbf'  => {
326                            'factor'    => 1.355,
327                            'm'         => 2,
328                            'kg'        => 1,
329                            's'         => -2
330                           },
331                 'cal'  => {
332                            'factor'    => 4.19,
333                            'm'         => 2,
334                            'kg'        => 1,
335                            's'         => -2
336                           },
337                'kcal'  => {
338                            'factor'    => 4190,
339                            'm'         => 2,
340                            'kg'        => 1,
341                            's'         => -2
342                           },
343                 'eV'  => {
344                            'factor'    => 1.60E-9,
345                            'm'         => 2,
346                            'kg'        => 1,
347                            's'         => -2
348                           },
349                 'kWh'  => {
350                            'factor'    => 3.6E6,
351                            'm'         => 2,
352                            'kg'        => 1,
353                            's'         => -2
354                           },
355 # POWER
356 # W      -- Watt
357 # kW     -- kilo Watt
358 # hp     -- horse power  746 W
359 #
360                  'W'  => {
361                            'factor'    => 1,
362                            'm'         => 2,
363                            'kg'        => 1,
364                            's'         => -3
365                           },
366                  'kW'  => {
367                            'factor'    => 1000,
368                            'm'         => 2,
369                            'kg'        => 1,
370                            's'         => -3
371                           },
372                 'hp'   => {
373                            'factor'    => 746,
374                            'm'         => 2,
375                            'kg'        => 1,
376                            's'         => -3
377                           },
378 # PRESSURE
379 # Pa     -- Pascal
380 # kPa    -- kilo Pascal
381 # atm    -- atmosphere
382                  'Pa'  => {
383                            'factor'    => 1,
384                            'm'         => -1,
385                            'kg'        => 1,
386                            's'         => -2
387                           },
388                 'kPa'  => {
389                            'factor'    => 1000,
390                            'm'         => -1,
391                            'kg'        => 1,
392                            's'         => -2
393                           },
394                 'atm'  => {
395                            'factor'    => 1.01E5,
396                            'm'         => -1,
397                            'kg'        => 1,
398                            's'         => -2
399                           },
400
401 );
402
403
404
405 sub process_unit {
406
407   my \$string = shift;
408     die ("UNIT ERROR: No units were defined.") unless defined(\$string);  #
409   #split the string into numerator and denominator --- the separator is /
410     my (\$numerator,\$denominator) = split( m{/}, \$string );
411
412
413
414   \$denominator = "" unless defined(\$denominator);
415   my %numerator_hash = process_term(\$numerator);
416   my %denominator_hash =  process_term(\$denominator);
417
418
419     my %unit_hash = %fundamental_units;
420   my \$u;
421   foreach \$u (keys %unit_hash) {
422     if ( \$u eq 'factor' ) {
423       \$unit_hash{\$u} = \$numerator_hash{\$u}/\$denominator_hash{\$u};  # calculate the correction factor for the unit
424     } else {
425
426       \$unit_hash{\$u} = \$numerator_hash{\$u} - \$denominator_hash{\$u}; # calculate the power of the fundamental unit in the unit
427     }
428   }
429   # return a unit hash.
430   return(%unit_hash);
431 }
432
433 sub process_term {
434   my \$string = shift;
435   my %unit_hash = %fundamental_units;
436   if (\$string) {
437
438     #split the numerator or denominator into factors -- the separators are *
439
440       my @factors = split(/\*/, \$string);
441
442     my \$f;
443     foreach \$f (@factors) {
444       my %factor_hash = process_factor(\$f);
445
446       my \$u;
447       foreach \$u (keys %unit_hash) {
448         if ( \$u eq 'factor' ) {
449           \$unit_hash{\$u} = \$unit_hash{\$u} * \$factor_hash{\$u};  # calculate the correction factor for the unit
450         } else {
451
452           \$unit_hash{\$u} = \$unit_hash{\$u} + \$factor_hash{\$u}; # calculate the power of the fundamental unit in the unit
453         }
454       }
455     }
456   }
457   #returns a unit hash.
458   #print "process_term returns", %unit_hash, "\n";
459   return(%unit_hash);
460 }
461
462
463 sub process_factor {
464   my \$string = shift;
465   #split the factor into unit and powers
466
467     my (\$unit_name,\$power) = split(/\^/, \$string);
468   \$power = 1 unless defined(\$power);
469   my %unit_hash = %fundamental_units;
470
471   if ( defined( \$known_units{\$unit_name} )  ) {
472     my %unit_name_hash = %{\$known_units{\$unit_name}};   # \$reference_units contains all of the known units.
473     my \$u;
474     foreach \$u (keys %unit_hash) {
475       if ( \$u eq 'factor' ) {
476         \$unit_hash{\$u} = \$unit_name_hash{\$u}**\$power;  # calculate the correction factor for the unit
477       } else {
478         my \$fundamental_unit = \$unit_name_hash{\$u};
479         \$fundamental_unit = 0 unless defined(\$fundamental_unit); # a fundamental unit which doesn't appear in the unit need not be defined explicitly
480         \$unit_hash{\$u} = \$fundamental_unit*\$power; # calculate the power of the fundamental unit in the unit
481       }
482     }
483   } else {
484     die "UNIT ERROR Unrecognizable unit: |\$unit_name|";
485   }
486   %unit_hash;
487 }
488
489 # This is the "exported" subroutine.  Use this to evaluate the units given in an answer.
490 sub evaluate_units {
491   my \$unit = shift;
492   my %output =  eval(q{process_unit( \$unit)});
493   %output = %fundamental_units if \$@;  # this is what you get if there is an error.
494   \$output{'ERROR'}=\$@ if \$@;
495   %output;
496 }
497 #################