File Coverage

blib/lib/Math/Calc/Units/Convert.pm
Criterion Covered Total %
statement 33 33 100.0
branch 6 8 75.0
condition n/a
subroutine 10 10 100.0
pod 0 5 0.0
total 49 56 87.5


line stmt bran cond sub pod time code
1             package Math::Calc::Units::Convert;
2 1     1   4 use base 'Exporter';
  1         2  
  1         71  
3 1     1   5 use strict;
  1         2  
  1         32  
4 1     1   4 use vars qw(@EXPORT_OK);
  1         2  
  1         46  
5 1     1   32 BEGIN { @EXPORT_OK = qw(convert reduce canonical find_top construct); };
6              
7 1     1   659 use Math::Calc::Units::Convert::Multi qw(to_canonical);
  1         4  
  1         383  
8              
9             # convert : value x unit -> value
10             #
11             # The lower-level conversion routines really only know how to convert
12             # things to canonical units. But this routine may be called with eg
13             # 120 minutes -> hours. So we convert both the current and target to
14             # canonical units, and divide the first by the second. (Doesn't work
15             # for adding units that aren't multiples of each other, but that's not
16             # what this tool is for anyway.)
17             sub convert {
18 172     172 0 294 my ($from, $unit) = @_;
19              
20 172         338 my $to = [ 1, $unit ];
21              
22 172         374 my $canon_from = canonical($from);
23 172         339 my $canon_to = canonical($to);
24              
25 172 100       411 die "conversion between incompatible units"
26             if not same_units($canon_from->[1], $canon_to->[1]);
27              
28 170         1146 return [ $canon_from->[0] / $canon_to->[0], $unit ];
29             }
30              
31             # Are the (canonical) units compatible? (They must have exactly the
32             # same base units, and each must be raised to exactly the same power.)
33             sub same_units {
34 172     172 0 230 my ($u1, $u2) = @_;
35 172 50       606 return if keys %$u1 != keys %$u2;
36 172         509 while (my ($bu1, $bp1) = each %$u1) {
37 191 100       490 return if ! exists $u2->{$bu1};
38 189 50       742 return if $bp1 != $u2->{$bu1};
39             }
40 170         465 return 1;
41             }
42              
43             sub canonical {
44 481     481 0 623 my ($v) = @_;
45 481         1240 my $c = to_canonical($v->[1]);
46 481         1288 my $w = [ $v->[0] * $c->[0], $c->[1] ];
47 481         5668 return $w;
48             }
49              
50             sub reduce {
51 125     125 0 174 my ($v) = @_;
52 125         231 return canonical($v, 'reduce, please');
53             }
54              
55             sub construct {
56 7     7 0 11 my ($constructor, $args) = @_;
57 7         22 return Math::Calc::Units::Convert::Multi::construct($constructor, $args);
58             }
59              
60             1;