[system] / trunk / pg / lib / Units.pm Repository:
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5591 - (download) (as text) (annotate)
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
   28     #      rad    => 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,
   41                      'rad'    => 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                           },
   71                 'rad' => {
   72                            'factor'    => 1,
   73                            'rad'       => 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,
  100                            'rad'       => 1
  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,
  244                            'rad'       => 1
  245                           },
  246                 'kHz'  => {
  247                            'factor'    => 1000*2*$PI,  #1000*2pi,
  248                            's'         => -1,
  249                            'rad'       => 1
  250                           },
  251                 'MHz'  => {
  252                            'factor'    => (10**6)*2*$PI,  #10^6 * 2pi,
  253                            's'         => -1,
  254                            'rad'       => 1
  255                           },
  256                 'rev'  => {
  257                       'factor'   => 2*$PI,
  258                       'rad'      => 1
  259                       },
  260                 'cycles'  => {
  261                       'factor'   => 2*$PI,
  262                       'rad'      => 1
  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
  420 # F      -- Farad
  421 # mF     -- miliFarad
  422 # uF     -- microFarad
  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;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9