[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 3576 - (download) (as text) (annotate)
Thu Aug 25 20:01:25 2005 UTC (14 years, 5 months ago) by glarose
File size: 18010 byte(s)
Add some electrical units.  Take two, hopefully in the correct branch
this time.

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9