File Coverage

blib/lib/Math/Calc/Units/Convert/Multi.pm
Criterion Covered Total %
statement 63 71 88.7
branch 18 22 81.8
condition 2 2 100.0
subroutine 15 17 88.2
pod 0 11 0.0
total 98 123 79.6


line stmt bran cond sub pod time code
1             package Math::Calc::Units::Convert::Multi;
2 1     1   5 use base 'Exporter';
  1         2  
  1         69  
3 1     1   5 use vars qw(@EXPORT_OK);
  1         1  
  1         55  
4             BEGIN {
5 1     1   75 @EXPORT_OK = qw(to_canonical simple_convert singular
6             variants major_variants
7             major_pref range_score pref_score
8             get_class construct);
9             };
10             require Math::Calc::Units::Convert::Time;
11             require Math::Calc::Units::Convert::Byte;
12             require Math::Calc::Units::Convert::Date;
13             require Math::Calc::Units::Convert::Distance;
14             require Math::Calc::Units::Convert::Combo;
15 1     1   5 use strict;
  1         2  
  1         33  
16 1     1   5 use vars qw(@UnitClasses);
  1         1  
  1         895  
17              
18             @UnitClasses = qw(Math::Calc::Units::Convert::Time
19             Math::Calc::Units::Convert::Byte
20             Math::Calc::Units::Convert::Date
21             Math::Calc::Units::Convert::Distance
22             Math::Calc::Units::Convert::Combo);
23              
24             # to_canonical : unit -> value
25             #
26             sub to_canonical {
27 488     488 0 748 my ($unit) = @_;
28              
29 488         621 my $val = 1;
30 488         488 my %newUnit;
31              
32 488         1505 while (my ($unitName, $power) = each %$unit) {
33 555         843 my ($mult, $canon) = name_to_canonical($unitName);
34 555         1106 $val *= $mult ** $power;
35              
36 555 100       931 if (ref $canon) {
37             # Uh oh, it was a combination of basic types
38 7         21 my $c = to_canonical($canon);
39 7         14 $val *= $c->[0] ** $power;
40 7         10 while (my ($name, $subPower) = each %{ $c->[1] }) {
  21         102  
41 14 100       44 if (($newUnit{$name} += $subPower * $power) == 0) {
42 1         4 delete $newUnit{$name};
43             }
44             }
45             } else {
46 548 100       2820 if (($newUnit{$canon} += $power) == 0) {
47 3         13 delete $newUnit{$canon};
48             }
49             }
50             }
51              
52 488         1651 return [ $val, \%newUnit ];
53             }
54              
55             # name_to_canonical : unitName -> value x baseUnit
56             #
57             # Memoizing this doubles the speed of the test suite.
58             #
59             my %CANON_CACHE;
60             sub name_to_canonical {
61 1260     1260 0 1513 my $unitName = shift;
62 1260   100     3133 $CANON_CACHE{$unitName} ||= [ _name_to_canonical($unitName) ];
63 1260         1261 return @{ $CANON_CACHE{$unitName} };
  1260         3507  
64             }
65              
66             sub _name_to_canonical {
67 76     76   92 my ($unitName) = @_;
68              
69             # First, check for compound units
70 76 100       287 if (my $v = Math::Calc::Units::Convert::Combo->lookup_compound($unitName)) {
71 2         7 return @$v;
72             }
73              
74 74         136 foreach my $uclass (@UnitClasses) {
75 201 100       665 if (my ($val, $base) = $uclass->to_canonical($unitName)) {
76 63         488 return ($val, $base);
77             }
78             }
79 11         40 return Math::Calc::Units::Convert::Base->to_canonical($unitName);
80             }
81              
82             sub get_class {
83 705     705 0 834 my ($unitName) = @_;
84 705         1198 my (undef, $canon) = name_to_canonical($unitName);
85 705         1654 foreach my $uclass (@UnitClasses) {
86 1524         5348 my $canon_unit = $uclass->canonical_unit();
87 1524 100       3213 next if ! defined $canon_unit;
88 1500 100       5618 return $uclass if $canon_unit eq $canon;
89             }
90 24         102 return 'Math::Calc::Units::Convert::Base';
91             }
92              
93             sub simple_convert {
94 0     0 0 0 my ($u, $v) = @_;
95 0         0 foreach my $uclass (@UnitClasses) {
96 0         0 my $c;
97 0 0       0 return $c if $c = $uclass->simple_convert($u, $v);
98             }
99 0         0 return;
100             }
101              
102             sub singular {
103 0     0 0 0 my ($unitName) = @_;
104 0         0 return get_class($unitName)->singular($unitName);
105             }
106              
107             sub variants {
108 22     22 0 37 my ($base) = @_;
109 22         44 return get_class($base)->variants($base);
110             }
111              
112             sub major_variants {
113 4     4 0 6 my ($base) = @_;
114 4         11 return get_class($base)->major_variants($base);
115             }
116              
117             sub major_pref {
118 9     9 0 14 my ($base) = @_;
119 9         60 return get_class($base)->major_pref($base);
120             }
121              
122             sub range_score {
123 282     282 0 361 my ($val, $unitName) = @_;
124 282 50       655 die if ref $unitName;
125 282         428 return get_class($unitName)->range_score($val, $unitName);
126             }
127              
128             sub pref_score {
129 296     296 0 377 my ($unitName) = @_;
130 296 50       565 die if ref $unitName;
131 296         490 return get_class($unitName)->pref_score($unitName);
132             }
133              
134             sub construct {
135 7     7 0 9 my ($constructor, $args) = @_;
136 7         14 foreach my $uclass (@UnitClasses) {
137 21         19 my $c;
138 21 100       116 return $c if $c = $uclass->construct($constructor, $args);
139             }
140 0           return;
141             }
142              
143             1;