File Coverage

blib/lib/Data/Dimensions/Map.pm
Criterion Covered Total %
statement 36 37 97.3
branch 5 6 83.3
condition n/a
subroutine 5 5 100.0
pod 0 3 0.0
total 46 51 90.2


line stmt bran cond sub pod time code
1             package Data::Dimensions::Map;
2             # hold information about units provided by the module
3              
4 5     5   145 use strict;
  5         13  
  5         362  
5 5     5   46 use vars qw(%SI_base %SI_units %units %basic %prefixes);
  5         11  
  5         14418  
6              
7             # basic SI units only need prefix scaling...
8             %SI_base = (
9             m => {m =>1 },
10             kg => {kg =>1},
11             s => {s =>1 },
12             A => {A =>1 },
13             K => {K =>1 },
14             cd => {cd =>1},
15             mol=> {mol=>1},
16              
17             rad=> {rad=>1},
18             sr => {sr =>1},
19            
20             Hz => {s => -1},
21             N => {kg => 1, m => 1, s => -2},
22             Pa => {kg => 1, m => -1,s => -2},
23             J => {kg => 1, m => 2, s => -2},
24             W => {kg => 1, m => 2, s => -3},
25              
26             coul => {A => 1, s=> 1},
27             V => {kg =>1, m=> 2, s=> -3, A => -1},
28             ohm => {kg =>1, m=> 2, s=> -3, A => -2},
29             S => {kg =>-1,m=>-2, s=> 3, A => 2},
30             F => {kg =>-1,m=>-2, s=> 4, A => 2},
31            
32             Wb => {kg =>1, m=> 2, s=> -2, A => -1},
33             H => {kg =>1, m=> 2, s=> -2, A => -2},
34             T => {kg =>1, m=> 1, s=> -2, A => -1},
35            
36             lm => {cd =>1, m=>-2},
37            
38             Bq => {s => -1},
39             Gy => {m => 2, s => -2},
40             );
41             %SI_units = (
42             %SI_base,
43             meter=> $SI_base{m},
44             kilo=> $SI_base{kg},
45             kilogram=> $SI_base{kg},
46             kilogramme=> $SI_base{kg},
47             sec=> $SI_base{s},
48             second=> $SI_base{s},
49             amp=> $SI_base{A},
50             ampere=> $SI_base{A},
51             kelvin=> $SI_base{K},
52             candela=> $SI_base{cd},
53             mole=> $SI_base{mol},
54             radian => $SI_base{rad},
55             steradian=> $SI_base{sr},
56             sterad=> $SI_base{sr},
57             hertz=> $SI_base{Hz},
58             newton=> $SI_base{N},
59             pascal=> $SI_base{Pa},
60             joule=> $SI_base{J},
61             watt=> $SI_base{W},
62             coulomb=> $SI_base{coul},
63             volt=> $SI_base{V},
64             seimens=> $SI_base{S},
65             farad=> $SI_base{F},
66             weber=> $SI_base{Wb},
67             henry=> $SI_base{H},
68             tesla=> $SI_base{T},
69             lumen=> $SI_base{lm},
70             becquerel=> $SI_base{Bq},
71             gray=> $SI_base{Gy},
72             );
73              
74             # This should be invoked last... We know that SI units cannot change
75             # the scaling of the base value, so we can ignore that here
76             sub parse_SI {
77 29     29 0 45 my ($hr, $scale) = @_;
78 29         37 my %temp;
79              
80 29         102 foreach my $unit (keys %$hr) {
81 32 50       78 if (exists $SI_units{$unit}) {
82 32         33 foreach (keys %{$SI_units{$unit}}) {
  32         88  
83 38         176 $temp{$_} += $SI_units{$unit}->{$_} * $hr->{$unit};
84             }
85             }
86             else {
87 0         0 $temp{$unit} += $hr->{$unit};
88             }
89             }
90 29         227 return (\%temp, $scale);
91             }
92              
93             %prefixes = (
94             semi=> 0.5,
95             demi=> 0.5,
96             yotta=> 1e24,
97             zetta=> 1e21,
98             exa=> 1e18,
99             peta=> 1e15,
100             tera=> 1e12,
101             giga=> 1e9,
102             mega=> 1e6,
103             kilo=> 1e3,
104             hecto=> 1e2,
105             deka=> 1e1,
106             deci=> 1e-1,
107             centi=> 1e-2,
108             milli=> 1e-3,
109             micro=> 1e-6,
110             nano=> 1e-9,
111             pico=> 1e-12,
112             femto=> 1e-15,
113             atto=> 1e-18,
114             zopto=> 1e-21,
115             yocto=> 1e-24,
116             Y=> 1e24,
117             Z=> 1e21,
118             E=> 1e18,
119             P=> 1e15,
120             T=> 1e12,
121             G=> 1e9,
122             M=> 1e6,
123             k=> 1e3,
124             h=> 1e2,
125             da=> 1e1,
126             d=> 1e-1,
127             c=> 1e-2,
128             m=> 1e-3,
129             u=> 1e-6,
130             n=> 1e-9,
131             p=> 1e-12,
132             f=> 1e-15,
133             a=> 1e-18,
134             z=> 1e-21,
135             y=> 1e-24,
136             );
137              
138             sub parse_prefix {
139 29     29 0 44 my ($hr, $scale) = @_;
140 29         106 my %temp;
141 29         640 my $rg = join('|', keys %prefixes);
142 29         1329 my $rx = qr/^($rg)\-(\w+)$/;
143            
144 29         194 foreach (keys %$hr) {
145 31 100       155 if ($_ =~ $rx) {
146 1         6 $temp{$2} = $hr->{$_};
147 1         8 $scale *= $prefixes{$1}**($hr->{$_});
148             }
149             else {
150 30         99 $temp{$_} = $hr->{$_};
151             }
152             }
153 29         162 return (\%temp, $scale);
154             }
155              
156             # $units{ unit } = [scale, {basic hash}];
157             %units = (
158             turn => [ 2 * 3.14159, {rad=>1}],
159             revolution => [ 2 * 3.14159, {rad=>1}],
160             degree => [ 2*3.14159 / 360, {rad=>1}],
161             deg => [ 2*3.14159 / 360, {rad=>1}],
162             arcdeg => [ 2*3.14159 / 360, {rad=>1}],
163             arcmin => [ 2*3.14159 / (360*60), {rad=>1}],
164             arcsec => [ 2*3.14159 / (360*60*60), {rad=>1}],
165             minute => [ 60, {s=>1}],
166             min => [ 60, {s=>1}],
167             hour=> [ 60*60, {s=>1}],
168             hr=> [ 60*60, {s=>1}],
169             day => [ 24*60*60, {s=>1}],
170             week=> [ 7*24*60*60, {s=>1}],
171             year=> [ 365*24*60*60, {s=>1}], # non-leap
172             yr=> [ 365*24*60*60, {s=>1}],
173             gram=> [ 1e-3, {kg=>1}],
174             gm=> [1e-3 , {kg=>1}],
175             tonne=> [1e3 , {kg=>1}],
176             # avoirdupois
177             lb=> [.45359237 , {kg=>1}],
178             pound=> [ .45359237, {kg=>1}],
179             ounce=> [ .45359237/16, {kg=>1}],
180             oz=> [ .45359237/16, {kg=>1}],
181              
182             micron => [ 1e-6, {m=>1}],
183             angstrom=> [ 1e-10, {m=>1}],
184             # Imperial
185             inch=> [2.54 / 100 , {m=>1}],
186             in => [ 2.54 / 100, {m=>1}],
187             foot=> [ 12*2.54 / 100, {m=>1}],
188             feet=> [12*2.54 / 100 , {m=>1}],
189             ft=> [ 12*2.54 / 100, {m=>1}],
190             yard=> [3*12*2.54 / 100, {m=>1}],
191             yd=> [ 3*12*2.54 / 100, {m=>1}],
192             mile=> [ 5280*12*2.54 / 100, {m=>1}],
193             nmile=> [ 1852, {m=>1}],
194             acre=> [4840 * (3*12*2.54 / 100)**2 , {m=>2}],
195             hectare => [100*100, {m => 2}],
196            
197             cc=> [(1/100)**3 , {m=>3}],
198             liter=> [ 1000*((1/100)**3), {m=>3}],
199             ml => [ (1/100)**3, {m=>3}],
200              
201             # US Liquid
202             gallon => [231 * (2.54 / 100)**3 , {m=>3}],
203             gal => [ 231 * (2.54 / 100)**3, {m=>3}],
204             quart => [ 231 * (2.54 / 100)**3 / 4, {m=>3}],
205             pint => [ 231 * (2.54 / 100)**3 / 8, {m=>3}],
206              
207             # UK Liquid
208             brgallon => [277.420 * (2.54 / 100)**3 , {m=>3}],
209             brquart=> [ 277.420 * (2.54 / 100)**3 / 4, {m=>3}],
210             brpint => [ 277.420 * (2.54 / 100)**3 / 8, {m=>3}],
211              
212             cal=> [ 4.1868, {joule=>1}],
213             mho=> [ 1, {ohm=>-1}],
214              
215             baud => [ 1, {bit=>1, s=>-1}],
216             byte => [ 8 ,{bit=>1}],
217             block=> [ 512*8, {bit=>1}],
218              
219             barn => [1e-28 , {m=>2}],
220             amu => [ 1.66044e-27, {kg=>1}],
221             electronvolt => [ 1.6021764e-19, {joule=>1}],
222             erg => [(1/100)**2 * (1/1000) , {m=>2, kg=>1, s=>-2}],
223             fermi=> [1e-15 , {m=>1}],
224             lightyear=> [ 365.25 * 299_792_458 * 60 * 60 * 24, {m=>1}],
225             parsec => [ 3.24 * 365.25 * 299_792_458 * 60 * 60 * 24, {m=>1}],
226              
227             point=> [(1/72) * 2.54 / 100 , {m=>1}],
228              
229             celsius => [1 , {K=>1}], # although no zero point changes
230             centrigrade=> [1 , {K=>1}],
231              
232             siderealyear=> [ 365.256360417* 24*60*60, {s=>1}],
233              
234             percent => [ 0.01, {}],
235              
236             # test me baby!
237             __HONK_IF_YOU_PERL => [10, {m=>1, s=>-1}],
238             );
239              
240             # This is the general scaling and convert to base monster
241             sub parse_other {
242 19     19 0 26 my ($hr, $scale) = @_;
243 19         25 my %temp;
244 19         71 foreach my $unit (keys %$hr) {
245 21 100       52 if (exists $units{$unit}) {
246 1         3 my $factor = $units{$unit}->[0];
247 1         2 my $exp = $hr->{$unit};
248 1         2 foreach (keys %{$units{$unit}->[1]}) {
  1         4  
249 2         5 $temp{$_} += $units{$unit}->[1]->{$_} * $exp;
250             }
251 1         3 $scale *= $factor ** $exp;
252             }
253             else {
254 20         63 $temp{$unit} = $hr->{$unit};
255             }
256             }
257 19         101 return (\%temp, $scale);
258             }
259              
260             1;
261              
262             __END__