File Coverage

blib/lib/JE/Object/Math.pm
Criterion Covered Total %
statement 46 103 44.6
branch 1 66 1.5
condition 0 18 0.0
subroutine 8 25 32.0
pod 2 2 100.0
total 57 214 26.6


line stmt bran cond sub pod time code
1             package JE::Object::Math;
2              
3             our $VERSION = '0.064';
4              
5              
6 2     2   864 use strict;
  2         4  
  2         84  
7 2     2   10 use warnings;
  2         2  
  2         70  
8              
9 2     2   9 use constant inf => 9**9**9;
  2         3  
  2         142  
10 2     2   8 use constant nan => sin 9**9**9;
  2         3  
  2         92  
11              
12 2     2   10 use POSIX qw'floor ceil';
  2         319  
  2         19  
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 4 my($class, $global) = @_;
54 2         13 my $self = $class->SUPER::new($global);
55              
56 2         10 $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         9 $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         7 $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         7 $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         7 $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         7 $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   9 JE::Number->new($global,
123             defined $_[0]
124             ? abs $_[0]->to_number->value
125             : 'nan');
126             },
127 2         29 }),
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         18 }),
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         16 }),
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         21 }),
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         23 }),
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         16 }),
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         16 }),
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         29 }),
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         22 }),
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         22 }),
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         23 }),
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         18 }),
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 return JE::Number->new($global, $x ** $y);
379              
380             },
381 2         21 }),
382             dontenum => 1,
383             });
384             $self->prop({
385             name => 'random',
386             value => JE::Object::Function->new({
387             scope => $global,
388             name => 'random',
389             no_proto => 1,
390             function_args => [],
391             function => sub {
392 0     0   0 JE::Number->new($global, rand);
393             },
394 2         46 }),
395             dontenum => 1,
396             });
397             $self->prop({
398             name => 'round',
399             value => JE::Object::Function->new({
400             scope => $global,
401             name => 'round',
402             argnames => ['x'],
403             no_proto => 1,
404             function_args => ['args'],
405             function => sub {
406 0 0   0   0 JE::Number->new($global,
407             defined $_[0]
408             ? floor($_[0]->to_number->value+.5)
409             : 'nan');
410             },
411 2         17 }),
412             dontenum => 1,
413             });
414             $self->prop({
415             name => 'sin',
416             value => JE::Object::Function->new({
417             scope => $global,
418             name => 'sin',
419             argnames => [qw/x/],
420             no_proto => 1,
421             function_args => ['args'],
422             function => sub {
423 0 0   0   0 JE::Number->new($global,
424             defined $_[0]
425             ? sin($_[0]->to_number->value)
426             : 'nan');
427             },
428 2         16 }),
429             dontenum => 1,
430             });
431             $self->prop({
432             name => 'sqrt',
433             value => JE::Object::Function->new({
434             scope => $global,
435             name => 'sqrt',
436             argnames => [qw/x/],
437             no_proto => 1,
438             function_args => ['args'],
439             function => sub {
440             JE::Number->new($global,
441             defined $_[0]
442 0 0   0   0 ? do {
443 0         0 my $num
444             = $_[0]->to_number->value;
445 0 0       0 $num == -+inf
446             ? 'nan'
447             : $num ** .5
448             }
449             : 'nan');
450             },
451 2         16 }),
452             dontenum => 1,
453             });
454             $self->prop({
455             name => 'tan',
456             value => JE::Object::Function->new({
457             scope => $global,
458             name => 'tan',
459             argnames => [qw/x/],
460             no_proto => 1,
461             function_args => ['args'],
462             function => sub {
463 0     0   0 my $num = shift;
464 0 0       0 if(defined $num) {
465 0         0 $num = $num->to_number->value;
466 0         0 $num = sin($num) / cos $num;
467             }
468 0         0 else { $num = nan }
469 0         0 JE::Number->new($global, $num);
470             },
471 2         40 }),
472             dontenum => 1,
473             });
474              
475 2         22 $self;
476             }
477              
478              
479              
480             =item value
481              
482             Not particularly useful. Returns a hash ref that is completely empty,
483             unless you've added
484             your own properties to the object. This may change in a future release.
485              
486             =item class
487              
488             Returns the string 'Math'
489              
490             =cut
491              
492 3     3 1 11 sub class { 'Math' }
493              
494              
495              
496              
497             return "a true value";
498              
499             =back
500              
501             =head1 SEE ALSO
502              
503             =over 4
504              
505             =item JE
506              
507             =item JE::Types
508              
509             =item JE::Object
510              
511             =item JE::Number
512              
513             =back
514              
515             =cut