package JE::Object::Math; our $VERSION = '0.042'; use strict; use warnings; use constant inf => 9**9**9; use constant nan => sin 9**9**9; use POSIX qw'floor ceil'; our @ISA = 'JE::Object'; require JE::Number; require JE::Object; require JE::Object::Function; =head1 NAME JE::Object::Math - JavaScript Math object =head1 SYNOPSIS use JE; use JE::Object::Math; $j = new JE; $math_obj = new JE::Object::Math $j; =head1 DESCRIPTION This class implements the JavaScript Math object. =head1 METHODS See L for descriptions of most of the methods. Only what is specific to JE::Object::Math is explained here. =over =item JE::Object::Math->new($global_obj) Creates a new Math object. =cut sub new { my($class, $global) = @_; my $self = $class->SUPER::new($global); $self->prop({ name => 'E', value => JE::Number->new($global, exp 1), dontenum => 1, dontdel => 1, readonly => 1, }); $self->prop({ name => 'LN10', value => JE::Number->new($global, log 10), dontenum => 1, dontdel => 1, readonly => 1, }); $self->prop({ name => 'LN2', value => JE::Number->new($global, log 2), dontenum => 1, dontdel => 1, readonly => 1, }); $self->prop({ name => 'LOG2E', value => JE::Number->new($global, 1/log 2), dontenum => 1, dontdel => 1, readonly => 1, }); $self->prop({ name => 'LOG10E', value => JE::Number->new($global, 1/log 10), dontenum => 1, dontdel => 1, readonly => 1, }); $self->prop({ name => 'PI', value => JE::Number->new($global, 4 * atan2 1,1), dontenum => 1, dontdel => 1, readonly => 1, }); $self->prop({ name => 'SQRT1_2', value => JE::Number->new($global, .5**.5), dontenum => 1, dontdel => 1, readonly => 1, }); $self->prop({ name => 'SQRT2', value => JE::Number->new($global, 2**.5), dontenum => 1, dontdel => 1, readonly => 1, }); $self->prop({ name => 'abs', value => JE::Object::Function->new({ scope => $global, name => 'abs', argnames => ['x'], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? abs $_[0]->to_number->value : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'acos', value => JE::Object::Function->new({ scope => $global, name => 'acos', argnames => ['x'], no_proto => 1, function_args => ['args'], function => sub { my $num; if(defined $_[0]) { $num = $_[0]->to_number->value; $num = atan2+ (1 - $num * $num)**.5, $num; } else { $num = 'nan'; } JE::Number->new($global, $num); }, }), dontenum => 1, }); $self->prop({ name => 'asin', value => JE::Object::Function->new({ scope => $global, name => 'asin', argnames => ['x'], no_proto => 1, function_args => ['args'], function => sub { my $num; if(defined $_[0]) { $num = $_[0]->to_number->value; $num = atan2+ $num, (1 - $num * $num)**.5; } else { $num = 'nan'; } JE::Number->new($global, $num); }, }), dontenum => 1, }); $self->prop({ name => 'atan', value => JE::Object::Function->new({ scope => $global, name => 'atan', argnames => ['x'], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? atan2($_[0]->to_number->value, 1) : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'atan2', value => JE::Object::Function->new({ scope => $global, name => 'atan2', argnames => [qw/y x/], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] && defined $_[1] ? atan2($_[0]->to_number->value, $_[1]->to_number->value) : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'ceil', value => JE::Object::Function->new({ scope => $global, name => 'ceil', argnames => [qw/x/], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? ceil($_[0]->to_number->value) : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'cos', value => JE::Object::Function->new({ scope => $global, name => 'cos', argnames => [qw/x/], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? cos($_[0]->to_number->value) : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'exp', value => JE::Object::Function->new({ scope => $global, name => 'exp', argnames => [qw/x/], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? exp($_[0]->to_number->value) : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'floor', value => JE::Object::Function->new({ scope => $global, name => 'floor', argnames => [qw/x/], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? floor($_[0]->to_number->value) : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'log', value => JE::Object::Function->new({ scope => $global, name => 'log', argnames => [qw/x/], no_proto => 1, function_args => ['args'], function => sub { my $num; if (defined $_[0]) { $num = $_[0]->to_number->value; $num = $num < 0 ? 'nan' : $num == 0 ? '-Infinity' : log $num; } else { $num = 'nan' } JE::Number->new($global, $num); }, }), dontenum => 1, }); $self->prop({ name => 'max', value => JE::Object::Function->new({ scope => $global, name => 'max', length => 2, no_proto => 1, function_args => ['args'], function => sub { @_ or return JE::Number->new($global, '-inf'); my $result; my $num; for (@_) { ($num = $_->to_number->value) == $num or return JE::Number->new($global, 'nan');; $result = $num if !defined $result or $result < $num; } JE::Number->new($global, $result); }, }), dontenum => 1, }); $self->prop({ name => 'min', value => JE::Object::Function->new({ scope => $global, name => 'min', length => 2, no_proto => 1, function_args => ['args'], function => sub { @_ or return JE::Number->new($global, 'inf'); my $result; my $num; for (@_) { ($num = $_->to_number->value) == $num or return JE::Number->new($global, 'nan');; $result = $num if !defined $result or $result > $num; } JE::Number->new($global, $result); }, }), dontenum => 1, }); $self->prop({ name => 'pow', value => JE::Object::Function->new({ scope => $global, name => 'pow', argnames => [qw/x y/], no_proto => 1, function_args => ['args'], function => sub { my $x = defined $_[0] ? $_[0]->to_number->value : nan; my $y = defined $_[1] ? $_[1]->to_number->value : nan; abs $x == 1 && abs $y == inf && return JE::Object::Number->new($global, 'nan'); return JE::Number->new($global, $x ** $y); }, }), dontenum => 1, }); $self->prop({ name => 'random', value => JE::Object::Function->new({ scope => $global, name => 'random', no_proto => 1, function_args => [], function => sub { JE::Number->new($global, rand); }, }), dontenum => 1, }); $self->prop({ name => 'round', value => JE::Object::Function->new({ scope => $global, name => 'round', argnames => ['x'], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? floor($_[0]->to_number->value+.5) : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'sin', value => JE::Object::Function->new({ scope => $global, name => 'sin', argnames => [qw/x/], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? sin($_[0]->to_number->value) : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'sqrt', value => JE::Object::Function->new({ scope => $global, name => 'sqrt', argnames => [qw/x/], no_proto => 1, function_args => ['args'], function => sub { JE::Number->new($global, defined $_[0] ? $_[0]->to_number->value ** .5 : 'nan'); }, }), dontenum => 1, }); $self->prop({ name => 'tan', value => JE::Object::Function->new({ scope => $global, name => 'tan', argnames => [qw/x/], no_proto => 1, function_args => ['args'], function => sub { my $num = shift; if(defined $num) { $num = $num->to_number->value; $num = sin($num) / cos $num; } else { $num = nan } JE::Number->new($global, $num); }, }), dontenum => 1, }); $self; } =item value Not particularly useful. Returns a hash ref that is completely empty, unless you've added your own properties to the object. This may change in a future release. =item class Returns the string 'Math' =cut sub class { 'Math' } return "a true value"; =back =head1 SEE ALSO =over 4 =item JE =item JE::Types =item JE::Object =item JE::Number =cut