File Coverage

blib/lib/Physics/Unit/Scalar.pm
Criterion Covered Total %
statement 127 141 90.0
branch 32 52 61.5
condition 8 21 38.1
subroutine 24 27 88.8
pod 13 18 72.2
total 204 259 78.7


line stmt bran cond sub pod time code
1             package Physics::Unit::Scalar;
2              
3 1     1   27638 use strict;
  1         2  
  1         34  
4 1     1   6 use Carp;
  1         2  
  1         90  
5 1     1   5 use base qw(Exporter);
  1         7  
  1         114  
6 1     1   5 use vars qw( $VERSION @EXPORT_OK %EXPORT_TAGS $debug);
  1         1  
  1         145  
7              
8             $VERSION = '0.53';
9             $VERSION = eval $VERSION;
10              
11             @EXPORT_OK = qw( ScalarFactory GetScalar );
12             %EXPORT_TAGS = ('ALL' => \@EXPORT_OK);
13              
14 1     1   765 use Physics::Unit ':ALL';
  1         3  
  1         1422  
15              
16              
17             InitSubtypes();
18              
19             sub new {
20 16     16 1 8792 my $proto = shift;
21 16 50       48 print "Scalar::new: proto is $proto.\n" if $debug;
22 16         25 my $class;
23 16         30 my $self = {};
24              
25 16 100       39 if (ref $proto) {
26             # Copy constructor
27 1         2 $class = ref $proto;
28 1         9 $self->{$_} = $$proto{$_} for keys %$proto;
29             }
30             else {
31             # Construct from a definition string
32             # Get the definition string, and remove whitespace
33 15         28 my $def = shift;
34 15 50       34 print "def is '$def'.\n" if $debug;
35 15 100       40 if (defined $def) {
36 14         177 $def =~ s/^\s*(.*?)\s*$/$1/;
37             }
38              
39 15         23 $class = $proto;
40              
41             # Convert the argument into a unit object
42 15 100       38 if ($class eq 'Physics::Unit::Scalar') {
43             # Build a generic Physics::Unit::Scalar object
44              
45 3         10 return ScalarFactory($def);
46              
47             #my $u = Physics::Unit->new($def);
48             #$self->{value} = $u->factor;
49             #$u->factor(1);
50             #$self->{MyUnit} = $self->{default_unit} = $u;
51             }
52             else {
53             # The user specified the type of Scalar explicitly
54 12         33 my $mu = $self->{MyUnit} = $self->{default_unit} =
55             GetMyUnit($class);
56              
57             # If no definition string was given, then set the value to
58             # one.
59              
60 12 100 66     210 if (!defined $def || $def eq '') {
    100          
61 1         4 $self->{value} = 1;
62             }
63              
64             # If the definition consists of just a number, then we'll use
65             # the default unit
66              
67             elsif ($def =~ /^$Physics::Unit::number_re$/io) {
68 2         7 $self->{value} = $def + 0; # convert to number
69             }
70              
71             else {
72 9         33 my $u = GetUnit($def);
73              
74 9 100       33 croak 'Unit definition string is of incorrect type'
75             if 'Physics::Unit::' . $u->type ne $class;
76              
77 8         33 $self->{value} = $u->convert($mu);
78             }
79             }
80             }
81              
82 12         56 bless $self, $class;
83             }
84              
85             sub ScalarFactory {
86 5     5 1 28 my $self = {
87             value => 1,
88             MyUnit => Physics::Unit->new(shift),
89             };
90              
91             # Call the mystery ScalarResolve() function.
92 5         16 return ScalarResolve($self);
93             }
94              
95             sub default_unit {
96 1     1 1 2 my $proto = shift;
97 1 50       5 if (ref $proto) {
98 1         5 return $proto->{default_unit};
99             }
100             else {
101 0         0 return GetDefaultUnit($proto);
102             }
103             }
104              
105             sub ToString {
106 11     11 1 2073 my $self = shift;
107 11 100       64 return $self->value .' '. $self->MyUnit->ToString unless @_;
108 1         5 my $u = GetUnit(shift);
109 1         4 my $v = $self->value * $self->MyUnit->convert($u);
110 1         10 return $v .' '. $u->ToString;
111             }
112              
113             sub convert {
114 1     1 1 796 my $self = shift;
115              
116 1         4 my $u = GetUnit(shift);
117              
118 1 50 33     7 croak 'convert called with invalid parameters'
119             if !ref $self || !ref $u;
120              
121 1         4 return $self->value * $self->MyUnit->convert($u);
122             }
123              
124             sub value {
125 13     13 1 604 my $self = shift;
126 13 50       29 $self->{value} = shift if @_;
127 13         140 return $self->{value};
128             }
129              
130             sub add {
131 1     1 1 647 my $self = shift;
132              
133 1         5 my $other = GetScalar(shift);
134              
135 1 50 33     10 croak 'Invalid arguments to Physics::Unit::Scalar::add'
136             if !ref $self || !ref $other;
137 1 50       5 carp "Scalar types don't match in add()"
138             if ref $self ne ref $other;
139              
140 1         3 $self->{value} += $other->{value};
141              
142 1         4 return $self;
143             }
144              
145             sub neg {
146 0     0 1 0 my $self = shift;
147 0 0       0 croak 'Invalid arguments to Physics::Unit::Scalar::neg'
148             if !ref $self;
149              
150 0         0 $self->{value} = - $self->{value};
151             }
152              
153             sub subtract {
154 0     0 1 0 my $self = shift;
155              
156 0         0 my $other = GetScalar(shift);
157              
158 0 0 0     0 croak 'Invalid arguments to Physics::Unit::Scalar::subtract'
159             if !(ref $self) || !(ref $other);
160 0 0       0 carp "Scalar types don't match in subtract()"
161             if ref $self ne ref $other;
162              
163 0         0 $self->{value} -= $other->{value};
164              
165 0         0 return $self;
166             }
167              
168             sub times {
169 2     2 1 3 my $self = shift;
170 2         6 my $other = GetScalar(shift);
171              
172 2 50 33     11 croak 'Invalid arguments to Physics::Unit::Scalar::times'
173             if !ref $self || !ref $other;
174              
175 2         14 my $value = $self->{value} * $other->{value};
176              
177 2         7 my $mu = $self->{MyUnit}->copy;
178              
179 2         9 $mu->times($other->{MyUnit});
180              
181 2         7 my $newscalar = {
182             value => $value,
183             MyUnit => $mu,
184             };
185              
186 2         6 return ScalarResolve($newscalar);
187             }
188              
189             sub recip {
190 2     2 1 5 my $self = shift;
191 2 50       8 croak 'Invalid argument to Physics::Unit::Scalar::recip'
192             unless ref $self;
193              
194 2 50       6 croak 'Attempt to take reciprocal of a zero Scalar'
195             unless $self->{value};
196              
197 2         10 my $mu = $self->{MyUnit}->copy;
198              
199 2         15 my $newscalar = {
200             value => 1 / $self->{value},
201             MyUnit => $mu->recip,
202             };
203              
204 2         7 return ScalarResolve($newscalar);
205             }
206              
207             sub divide {
208 2     2 1 6 my $self = shift;
209              
210 2         8 my $other = GetScalar(shift);
211              
212 2 50 33     14 croak 'Invalid arguments to Physics::Unit::Scalar::times'
213             if !ref $self || !ref $other;
214              
215 2         12 my $arg = $other->recip;
216              
217 2         14 return $self->times($arg);
218             }
219              
220             sub GetScalar {
221 5     5 1 10 my $n = shift;
222 5 100       16 if (ref $n) {
223 3         9 return $n;
224             }
225             else {
226 2         16 return ScalarFactory($n);
227             }
228             }
229              
230             sub InitSubtypes {
231 1     1 0 3 for my $type (ListTypes()) {
232 30 50       54 print "Creating class $type\n" if $debug;
233              
234 30         71 my $prototype = GetTypeUnit($type);
235 30   66     72 my $type_unit_name = $prototype->name || $prototype->def;
236             {
237 1     1   11 no strict 'refs';
  1         1  
  1         30  
  30         34  
238 1     1   5 no warnings 'once';
  1         3  
  1         146  
239 30         41 my $package = 'Physics::Unit::' . $type;
240 30         27 @{$package . '::ISA'} = qw(Physics::Unit::Scalar);
  30         533  
241 30         78 ${$package . '::DefaultUnit'} = ${$package . '::MyUnit'} =
  30         115  
  30         126  
242             GetUnit( $type_unit_name );
243             }
244             }
245             }
246              
247             sub MyUnit {
248 12     12 0 20 my $proto = shift;
249 12 50       27 if (ref ($proto)) {
250 12         55 return $proto->{MyUnit};
251             }
252             else {
253 0         0 return GetMyUnit($proto);
254             }
255             }
256              
257             sub GetMyUnit {
258 18     18 0 34 my $class = shift;
259 1     1   5 no strict 'refs';
  1         2  
  1         43  
260 18         22 return ${$class . '::MyUnit'};
  18         100  
261             }
262              
263             sub GetDefaultUnit {
264 0     0 0 0 my $class = shift;
265 1     1   5 no strict 'refs';
  1         1  
  1         183  
266 0         0 return ${$class . '::DefaultUnit'};
  0         0  
267             }
268              
269             sub ScalarResolve {
270 9     9 0 17 my $self = shift;
271              
272 9         16 my $mu = $self->{MyUnit};
273 9         28 my $type = $mu->type;
274              
275 9 100       23 if ($type) {
276 6 50       17 $type = 'dimensionless' if $type eq 'prefix';
277 6         27 $type = 'Physics::Unit::' . $type;
278              
279 6         18 my $newunit = GetMyUnit($type);
280 6         27 $self->{value} *= $mu->convert($newunit);
281 6         12 $self->{MyUnit} = $newunit;
282 6         12 $self->{default_unit} = $newunit;
283             }
284             else {
285 3         7 $type = "Physics::Unit::Scalar";
286              
287 3         14 $self->{value} *= $mu->factor;
288 3         11 $mu->factor(1);
289 3         6 $self->{default_unit} = $mu;
290             }
291              
292 9         74 bless $self, $type;
293             }
294              
295             1;
296              
297             __END__