File Coverage

blib/lib/JE/Object/Math.pm
Criterion Covered Total %
statement 46 105 43.8
branch 1 72 1.3
condition 0 30 0.0
subroutine 8 25 32.0
pod 2 2 100.0
total 57 234 24.3


line stmt bran cond sub pod time code
1             package JE::Object::Math;
2              
3             our $VERSION = '0.066';
4              
5              
6 2     2   1069 use strict;
  2         4  
  2         83  
7 2     2   11 use warnings;
  2         3  
  2         91  
8              
9 2     2   12 use constant inf => 9**9**9;
  2         3  
  2         163  
10 2     2   12 use constant nan => sin 9**9**9;
  2         426  
  2         166  
11              
12 2     2   13 use POSIX qw'floor ceil';
  2         4  
  2         18  
13              
14             our @ISA = 'JE::Object';
15              
16             require JE::Number;
17             require JE::Object;
18             require JE::Object::Function;
19              
20              
21              
22             =head1 NAME
23              
24             JE::Object::Math - JavaScript Math object
25              
26             =head1 SYNOPSIS
27              
28             use JE;
29             use JE::Object::Math;
30              
31             $j = new JE;
32              
33             $math_obj = new JE::Object::Math $j;
34              
35             =head1 DESCRIPTION
36              
37             This class implements the JavaScript Math object.
38              
39             =head1 METHODS
40              
41             See L for descriptions of most of the methods. Only what
42             is specific to JE::Object::Math is explained here.
43              
44             =over
45              
46             =item JE::Object::Math->new($global_obj)
47              
48             Creates a new Math object.
49              
50             =cut
51              
52             sub new {
53 2     2 1 5 my($class, $global) = @_;
54 2         19 my $self = $class->SUPER::new($global);
55              
56 2         14 $self->prop({
57             name => 'E',
58             value => JE::Number->new($global, exp 1),
59             dontenum => 1,
60             dontdel => 1,
61             readonly => 1,
62             });
63 2         12 $self->prop({
64             name => 'LN10',
65             value => JE::Number->new($global, log 10),
66             dontenum => 1,
67             dontdel => 1,
68             readonly => 1,
69             });
70 2         11 $self->prop({
71             name => 'LN2',
72             value => JE::Number->new($global, log 2),
73             dontenum => 1,
74             dontdel => 1,
75             readonly => 1,
76             });
77 2         8 $self->prop({
78             name => 'LOG2E',
79             value => JE::Number->new($global, 1/log 2),
80             dontenum => 1,
81             dontdel => 1,
82             readonly => 1,
83             });
84 2         9 $self->prop({
85             name => 'LOG10E',
86             value => JE::Number->new($global, 1/log 10),
87             dontenum => 1,
88             dontdel => 1,
89             readonly => 1,
90             });
91 2         9 $self->prop({
92             name => 'PI',
93             value => JE::Number->new($global, 4 * atan2 1,1),
94             dontenum => 1,
95             dontdel => 1,
96             readonly => 1,
97             });
98 2         11 $self->prop({
99             name => 'SQRT1_2',
100             value => JE::Number->new($global, .5**.5),
101             dontenum => 1,
102             dontdel => 1,
103             readonly => 1,
104             });
105 2         10 $self->prop({
106             name => 'SQRT2',
107             value => JE::Number->new($global, 2**.5),
108             dontenum => 1,
109             dontdel => 1,
110             readonly => 1,
111             });
112              
113             $self->prop({
114             name => 'abs',
115             value => JE::Object::Function->new({
116             scope => $global,
117             name => 'abs',
118             argnames => ['x'],
119             no_proto => 1,
120             function_args => ['args'],
121             function => sub {
122 2 50   2   17 JE::Number->new($global,
123             defined $_[0]
124             ? abs $_[0]->to_number->value
125             : 'nan');
126             },
127 2         41 }),
128             dontenum => 1,
129             });
130             $self->prop({
131             name => 'acos',
132             value => JE::Object::Function->new({
133             scope => $global,
134             name => 'acos',
135             argnames => ['x'],
136             no_proto => 1,
137             function_args => ['args'],
138             function => sub {
139 0     0   0 my $num;
140 0 0       0 if(defined $_[0]) {
141 0         0 $num = $_[0]->to_number->value;
142 0         0 $num = atan2+
143             (1 - $num * $num)**.5,
144             $num;
145             }
146             else {
147 0         0 $num = 'nan';
148             }
149 0         0 JE::Number->new($global, $num);
150             },
151 2         26 }),
152             dontenum => 1,
153             });
154             $self->prop({
155             name => 'asin',
156             value => JE::Object::Function->new({
157             scope => $global,
158             name => 'asin',
159             argnames => ['x'],
160             no_proto => 1,
161             function_args => ['args'],
162             function => sub {
163 0     0   0 my $num;
164 0 0       0 if(defined $_[0]) {
165 0         0 $num = $_[0]->to_number->value;
166 0         0 $num = atan2+
167             $num,
168             (1 - $num * $num)**.5;
169             }
170             else {
171 0         0 $num = 'nan';
172             }
173 0         0 JE::Number->new($global, $num);
174             },
175 2         24 }),
176             dontenum => 1,
177             });
178             $self->prop({
179             name => 'atan',
180             value => JE::Object::Function->new({
181             scope => $global,
182             name => 'atan',
183             argnames => ['x'],
184             no_proto => 1,
185             function_args => ['args'],
186             function => sub {
187 0 0   0   0 JE::Number->new($global,
188             defined $_[0]
189             ? atan2($_[0]->to_number->value, 1)
190             : 'nan');
191             },
192 2         26 }),
193             dontenum => 1,
194             });
195             $self->prop({
196             name => 'atan2',
197             value => JE::Object::Function->new({
198             scope => $global,
199             name => 'atan2',
200             argnames => [qw/y x/],
201             no_proto => 1,
202             function_args => ['args'],
203             function => sub {
204             JE::Number->new($global,
205             defined $_[0] && defined $_[1]
206 0 0 0 0   0 ? do {
207 0         0 my $a = $_[0]->to_number->value;
208 0         0 my $b = $_[1]->to_number->value;
209             # Windoze has trouble
210             # with two infs.
211 0 0 0     0 $a + 1 == $a && $b+1 == $b
    0          
    0          
212             ? ($b>0 ? 1 : 3) * atan2(1,1)
213             * ($a > 0 ? 1 : -1)
214             : atan2($a, $b)
215             }
216             : 'nan');
217             },
218 2         25 }),
219             dontenum => 1,
220             });
221             $self->prop({
222             name => 'ceil',
223             value => JE::Object::Function->new({
224             scope => $global,
225             name => 'ceil',
226             argnames => [qw/x/],
227             no_proto => 1,
228             function_args => ['args'],
229             function => sub {
230 0 0   0   0 JE::Number->new($global,
231             defined $_[0]
232             ? ceil($_[0]->to_number->value)
233             : 'nan');
234             },
235 2         25 }),
236             dontenum => 1,
237             });
238             $self->prop({
239             name => 'cos',
240             value => JE::Object::Function->new({
241             scope => $global,
242             name => 'cos',
243             argnames => [qw/x/],
244             no_proto => 1,
245             function_args => ['args'],
246             function => sub {
247 0 0   0   0 JE::Number->new($global,
248             defined $_[0]
249             ? cos($_[0]->to_number->value)
250             : 'nan');
251             },
252 2         31 }),
253             dontenum => 1,
254             });
255             $self->prop({
256             name => 'exp',
257             value => JE::Object::Function->new({
258             scope => $global,
259             name => 'exp',
260             argnames => [qw/x/],
261             no_proto => 1,
262             function_args => ['args'],
263             function => sub {
264 0 0   0   0 JE::Number->new($global,
    0          
    0          
265             defined $_[0]
266             ? $_[0] + 1 == $_[0] # inf
267             ? $_[0] < 0 ? 0 : 'inf'
268             : exp($_[0]->to_number->value)
269             : 'nan');
270             },
271 2         26 }),
272             dontenum => 1,
273             });
274             $self->prop({
275             name => 'floor',
276             value => JE::Object::Function->new({
277             scope => $global,
278             name => 'floor',
279             argnames => [qw/x/],
280             no_proto => 1,
281             function_args => ['args'],
282             function => sub {
283 0 0   0   0 JE::Number->new($global,
284             defined $_[0]
285             ? floor($_[0]->to_number->value)
286             : 'nan');
287             },
288 2         25 }),
289             dontenum => 1,
290             });
291             $self->prop({
292             name => 'log',
293             value => JE::Object::Function->new({
294             scope => $global,
295             name => 'log',
296             argnames => [qw/x/],
297             no_proto => 1,
298             function_args => ['args'],
299             function => sub {
300 0     0   0 my $num;
301 0 0       0 if (defined $_[0]) {
302 0         0 $num = $_[0]->to_number->value;
303 0 0       0 $num = $num < 0 ? 'nan' :
    0          
304             $num == 0 ? '-Infinity' :
305             log $num;
306             }
307 0         0 else { $num = 'nan' }
308 0         0 JE::Number->new($global, $num);
309             },
310 2         28 }),
311             dontenum => 1,
312             });
313             $self->prop({
314             name => 'max',
315             value => JE::Object::Function->new({
316             scope => $global,
317             name => 'max',
318             length => 2,
319             no_proto => 1,
320             function_args => ['args'],
321             function => sub {
322 0 0   0   0 @_ or return JE::Number->new($global, '-inf');
323 0         0 my $result; my $num;
324 0         0 for (@_) {
325 0 0       0 ($num = $_->to_number->value) == $num or
326             return JE::Number->new($global, 'nan');;
327 0 0 0     0 $result = $num if !defined $result or $result < $num;
328             }
329 0         0 JE::Number->new($global, $result);
330              
331             },
332 2         25 }),
333             dontenum => 1,
334             });
335             $self->prop({
336             name => 'min',
337             value => JE::Object::Function->new({
338             scope => $global,
339             name => 'min',
340             length => 2,
341             no_proto => 1,
342             function_args => ['args'],
343             function => sub {
344 0 0   0   0 @_ or return JE::Number->new($global, 'inf');
345 0         0 my $result; my $num;
346 0         0 for (@_) {
347 0 0       0 ($num = $_->to_number->value) == $num or
348             return JE::Number->new($global, 'nan');;
349 0 0 0     0 $result = $num if !defined $result or $result > $num;
350             }
351 0         0 JE::Number->new($global, $result);
352              
353             },
354 2         26 }),
355             dontenum => 1,
356             });
357              
358             $self->prop({
359             name => 'pow',
360             value => JE::Object::Function->new({
361             scope => $global,
362             name => 'pow',
363             argnames => [qw/x y/],
364             no_proto => 1,
365             function_args => ['args'],
366             function => sub {
367 0 0   0   0 my $x = defined $_[0] ? $_[0]->to_number->value : nan;
368 0 0       0 my $y = defined $_[1] ? $_[1]->to_number->value : nan;
369              
370 0 0 0     0 abs $x == 1 && abs $y == inf &&
371             return JE::Object::Number->new($global, 'nan');
372              
373 0 0       0 $y == 0 &&
374             return JE::Number->new($global, 1);
375              
376 0 0 0     0 $x == 0 && $y < 0 && return JE'Number->new($global, inf);
377              
378 0 0 0     0 $x == -+inf && $y < 0 &&
    0 0        
379             return JE'Number->new($global,
380             int $y != $y || !($y % 2) ? 0 : -0.0);
381              
382 0 0 0     0 $x == -+inf && $y > 0 && int $y != $y &&
      0        
383             return JE'Number->new($global, inf);
384              
385 0         0 return JE::Number->new($global, $x ** $y);
386              
387             },
388 2         28 }),
389             dontenum => 1,
390             });
391             $self->prop({
392             name => 'random',
393             value => JE::Object::Function->new({
394             scope => $global,
395             name => 'random',
396             no_proto => 1,
397             function_args => [],
398             function => sub {
399 0     0   0 JE::Number->new($global, rand);
400             },
401 2         22 }),
402             dontenum => 1,
403             });
404             $self->prop({
405             name => 'round',
406             value => JE::Object::Function->new({
407             scope => $global,
408             name => 'round',
409             argnames => ['x'],
410             no_proto => 1,
411             function_args => ['args'],
412             function => sub {
413 0 0   0   0 JE::Number->new($global,
414             defined $_[0]
415             ? floor($_[0]->to_number->value+.5)
416             : 'nan');
417             },
418 2         28 }),
419             dontenum => 1,
420             });
421             $self->prop({
422             name => 'sin',
423             value => JE::Object::Function->new({
424             scope => $global,
425             name => 'sin',
426             argnames => [qw/x/],
427             no_proto => 1,
428             function_args => ['args'],
429             function => sub {
430 0 0   0   0 JE::Number->new($global,
431             defined $_[0]
432             ? sin($_[0]->to_number->value)
433             : 'nan');
434             },
435 2         25 }),
436             dontenum => 1,
437             });
438             $self->prop({
439             name => 'sqrt',
440             value => JE::Object::Function->new({
441             scope => $global,
442             name => 'sqrt',
443             argnames => [qw/x/],
444             no_proto => 1,
445             function_args => ['args'],
446             function => sub {
447             JE::Number->new($global,
448             defined $_[0]
449 0 0   0   0 ? do {
450 0         0 my $num
451             = $_[0]->to_number->value;
452 0 0       0 $num == -+inf
453             ? 'nan'
454             : $num ** .5
455             }
456             : 'nan');
457             },
458 2         26 }),
459             dontenum => 1,
460             });
461             $self->prop({
462             name => 'tan',
463             value => JE::Object::Function->new({
464             scope => $global,
465             name => 'tan',
466             argnames => [qw/x/],
467             no_proto => 1,
468             function_args => ['args'],
469             function => sub {
470 0     0   0 my $num = shift;
471 0 0       0 if(defined $num) {
472 0         0 $num = $num->to_number->value;
473 0         0 $num = sin($num) / cos $num;
474             }
475 0         0 else { $num = nan }
476 0         0 JE::Number->new($global, $num);
477             },
478 2         26 }),
479             dontenum => 1,
480             });
481              
482 2         31 $self;
483             }
484              
485              
486              
487             =item value
488              
489             Not particularly useful. Returns a hash ref that is completely empty,
490             unless you've added
491             your own properties to the object. This may change in a future release.
492              
493             =item class
494              
495             Returns the string 'Math'
496              
497             =cut
498              
499 3     3 1 14 sub class { 'Math' }
500              
501              
502              
503              
504             return "a true value";
505              
506             =back
507              
508             =head1 SEE ALSO
509              
510             =over 4
511              
512             =item JE
513              
514             =item JE::Types
515              
516             =item JE::Object
517              
518             =item JE::Number
519              
520             =back
521              
522             =cut