[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 1079 - (download) (as text) (annotate)
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
   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 );
   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                           },
   66                 'rad' => {
   67                            'factor'    => 1,
   68                            'rad'       => 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,
   91                            'rad'       => 1
   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,
  230                            'rad'       => 1
  231                           },
  232                 'kHz'  => {
  233                            'factor'    => 1000*2*$PI,  #1000*2pi,
  234                            's'         => -1,
  235                            'rad'       => 1
  236                           },
  237                 'MHz'  => {
  238                            'factor'    => (10**6)*2*$PI,  #10^6 * 2pi,
  239                            's'         => -1,
  240                            'rad'       => 1
  241                           },
  242                 'rev'  => {
  243                       'factor'   => 2*$PI,
  244                       'rad'      => 1
  245                       },
  246                 'cycles'  => {
  247                       'factor'   => 2*$PI,
  248                       'rad'      => 1
  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 #################

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9