File Coverage

lib/HTML/Object/DOM/Number.pm
Criterion Covered Total %
statement 29 45 64.4
branch 1 6 16.6
condition 0 3 0.0
subroutine 10 20 50.0
pod 8 8 100.0
total 48 82 58.5


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## HTML Object - ~/lib/HTML/Object/DOM/Number.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2021 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2021/12/13
7             ## Modified 2022/09/18
8             ## All rights reserved
9             ##
10             ##
11             ## This program is free software; you can redistribute it and/or modify it
12             ## under the same terms as Perl itself.
13             ##----------------------------------------------------------------------------
14             package HTML::Object::DOM::Number;
15             BEGIN
16             {
17 3     3   1011 use strict;
  3         7  
  3         159  
18 3     3   15 use warnings;
  3         7  
  3         83  
19 3     3   20 use parent qw( Module::Generic::Number );
  3         4  
  3         19  
20 3     3   197 use vars qw( $EPSILON $VERSION );
  3         8  
  3         129  
21 3     3   21 use Config;
  3         7  
  3         190  
22             # use Machine::Epsilon ();
23 3     3   21 use POSIX qw( Inf NaN );
  3         6  
  3         55  
24             use constant {
25             MAX_SAFE_INTEGER => (POSIX::pow(2,53) - 1),
26             # MAX_VALUE => (1.7976931348623157 * POSIX::pow(10,308)),
27 3 50       50 MAX_VALUE => (POSIX::pow(2, $Config::Config{use64bitint} eq 'define' ? 64 : 32)),
28             MIN_SAFE_INTEGER => (-(POSIX::pow(2,53) - 1)),
29             MIN_VALUE => POSIX::pow(2, -1074),
30             # <https://perldoc.perl.org/perldata#Special-floating-point:-infinity-(Inf)-and-not-a-number-(NaN)>
31             # NEGATIVE_INFINITY => -9**9**9,
32             NEGATIVE_INFINITY => -Inf,
33             POSITIVE_INFINITY => Inf,
34 3     3   572 };
  3         4  
35 3     3   1689 our $EPSILON;
36 3         64 our $VERSION = 'v0.2.0';
37             };
38              
39 3     3   20 use strict;
  3         6  
  3         60  
40 3     3   16 use warnings;
  3         12  
  3         1097  
41              
42             sub init
43             {
44 0     0 1   my $self = shift( @_ );
45 0           $self->{_init_strict_use_sub} = 1;
46 0 0         $self->SUPER::init( @_ ) || return( $self->pass_error );
47             # $EPSILON = Machine::Epsilon::machine_epsilon() if( !defined( $EPSILON ) );
48 0 0         $EPSILON = POSIX::pow(2,-52) if( !defined( $EPSILON ) );
49 0           return( $self );
50             }
51              
52             # Note: property EPSILON
53             sub EPSILON : lvalue { return( shift->_lvalue({
54             get => sub
55             {
56 0     0     my $self = shift( @_ );
57 0           return( $EPSILON );
58             },
59             set => sub
60             {
61 0     0     my( $self, $ref ) = @_;
62 0           $EPSILON = shift( @$ref );
63             }
64 0     0 1   }, @_ ) ); }
65              
66             # Note: property MAX_SAFE_INTEGER is a constant
67              
68             # Note: property MAX_VALUE is a constant
69              
70             # Note: property MIN_SAFE_INTEGER is a constant
71              
72             # Note: property MIN_VALUE is a constant
73              
74             # Note: property NEGATIVE_INFINITY is a constant
75              
76             # Note: property POSITIVE_INFINITY is a constant
77              
78 0     0 1   sub isFinite { return( $_[1] != Inf ); }
79              
80 0     0 1   sub isInteger { return( shift->_is_integer( $_[0] ) ); }
81              
82 0     0 1   sub isNaN { return( POSIX::isnan( $_[1] ) ); }
83              
84 0   0 0 1   sub isSafeInteger { return( $_[0]->_is_integer( $_[1] ) && abs( $_[1] ) < MAX_SAFE_INTEGER ); }
85              
86 0     0 1   sub parseFloat { return( shift->new( shift( @_ ) ) ); }
87              
88 0     0 1   sub parseInt { return( shift->new( shift( @_ ) ) ); }
89              
90             1;
91             # NOTE: POD
92             __END__
93              
94             =encoding utf-8
95              
96             =head1 NAME
97              
98             HTML::Object::DOM::Number - HTML Object DOM Number
99              
100             =head1 SYNOPSIS
101              
102             use HTML::Object::DOM::Number;
103             my $this = HTML::Object::DOM::Number->new ||
104             die( HTML::Object::DOM::Number->error, "\n" );
105              
106             =head1 VERSION
107              
108             v0.2.0
109              
110             =head1 DESCRIPTION
111              
112             This interface represents and manipulates numbers like 37 or -9.25.
113              
114             It inherits from L<Module::Generic::Number>
115              
116             =head1 PROPERTIES
117              
118             =head2 EPSILON
119              
120             The smallest interval between two representable numbers.
121              
122             The EPSILON property has a value of approximately 2.22044604925031e-16, or 2^-52
123              
124             You do not have to create a HTML::Object::DOM::Number object to access this static property (use HTML::Object::DOM::Number->EPSILON).
125              
126             Example:
127              
128             my $result = abs(0.2 - 0.3 + 0.1);
129              
130             say $result;
131             # expected output: 2.77555756156289e-17
132              
133             say $result < HTML::Object::DOM::Number->EPSILON;
134             # expected output: 1 (i.e. true)
135              
136             if( !defined( HTML::Object::DOM::Number->EPSILON ) )
137             {
138             HTML::Object::DOM::Number->EPSILON = POSIX::pow(2, -52);
139             }
140              
141             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON>
142              
143             =head2 MAX_SAFE_INTEGER
144              
145             This represents the maximum safe integer in JavaScript i.e. (2^53 - 1).
146              
147             However, under perl, it does not work the same way.
148              
149             Example:
150              
151             Under JavaScript
152              
153             const x = Number.MAX_SAFE_INTEGER + 1;
154             const y = Number.MAX_SAFE_INTEGER + 2;
155              
156             console.log(Number.MAX_SAFE_INTEGER);
157             // expected output: 9007199254740991
158              
159             console.log(x);
160             // expected output: 9007199254740992
161              
162             console.log(x === y);
163             // expected output: true
164              
165             However, under perl, C<$x == $y> would be false of course.
166              
167             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER>
168              
169             =head2 MAX_VALUE
170              
171             This represents the maximum numeric value representable in JavaScript.
172              
173             The C<MAX_VALUE> property has a value of approximately 1.79E+308, or 2^64. Values larger than MAX_VALUE are represented as Infinity.
174              
175             Because MAX_VALUE is a static property of HTML::Object::DOM::Number, you always use it as C<HTML::Object::DOM::Number->MAX_VALUE>, rather than as a property of a C<HTML::Object::DOM::Number> object you created.
176              
177             Example:
178              
179             if( $num1 * $num2 <= HTML::Object::DOM::Number->MAX_VALUE )
180             {
181             func1();
182             }
183             else
184             {
185             func2();
186             }
187              
188             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_VALUE>
189              
190             =head2 MIN_SAFE_INTEGER
191              
192             This represents the minimum safe integer in JavaScript (-(2^53 - 1)).
193              
194             Because C<MIN_SAFE_INTEGER> is a static property of HTML::Object::DOM::Number, you can use it as C<HTML::Object::DOM::Number->MIN_SAFE_INTEGER>, rather than as a property of a C<HTML::Object::DOM::Number> object you created.
195              
196             Example:
197              
198             HTML::Object::DOM::Number->MIN_SAFE_INTEGER # -9007199254740991
199             -(POSIX::pow(2, 53) - 1) # -9007199254740991
200              
201             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER>
202              
203             =head2 MIN_VALUE
204              
205             The smallest positive representable number—that is, the positive number closest to zero (without actually being zero).
206              
207             Example:
208              
209             if( $num1 / $num2 >= HTML::Object::DOM::Number->MIN_VALUE )
210             {
211             func1();
212             }
213             else
214             {
215             func2();
216             }
217              
218             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_VALUE>
219              
220             =head2 NEGATIVE_INFINITY
221              
222             Special value representing negative infinity. Returned on overflow.
223              
224             Example:
225              
226             my $smallNumber = (-HTML::Object::DOM::Number->MAX_VALUE) * 2;
227              
228             if( $smallNumber == HTML::Object::DOM::Number->NEGATIVE_INFINITY )
229             {
230             $smallNumber = returnFinite();
231             }
232              
233             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/NEGATIVE_INFINITY>
234              
235             =head2 NaN
236              
237             Special "Not a Number" value.
238              
239             This is actually a value exported by L<POSIX>
240              
241             Example:
242              
243             sub sanitise
244             {
245             my $x = shift( @_ );
246             if( isNaN($x) )
247             {
248             return( HTML::Object::DOM::Number->NaN );
249             }
250             return($x);
251             }
252              
253             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/NaN>
254              
255             =head2 POSITIVE_INFINITY
256              
257             Special value representing infinity. Returned on overflow.
258              
259             Example:
260              
261             my $bigNumber = HTML::Object::DOM::Number->MAX_VALUE * 2;
262              
263             if( $bigNumber == HTML::Object::DOM::Number->POSITIVE_INFINITY )
264             {
265             $bigNumber = returnFinite();
266             }
267              
268             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/POSITIVE_INFINITY>
269              
270             =head1 METHODS
271              
272             Inherits methods from its parent L<Module::Generic::Number>
273              
274             =head2 isFinite
275              
276             Determine whether the passed value is a finite number.
277              
278             Example:
279              
280             HTML::Object::DOM::Number->isFinite($value)
281              
282             HTML::Object::DOM::Number->isFinite(Infinity); # false
283             HTML::Object::DOM::Number->isFinite(NaN); # false
284             HTML::Object::DOM::Number->isFinite(-Infinity); # false
285              
286             HTML::Object::DOM::Number->isFinite(0); # true
287             HTML::Object::DOM::Number->isFinite(2e64); # true
288              
289             HTML::Object::DOM::Number->isFinite('0'); # false, would've been true with
290             # global isFinite('0')
291             HTML::Object::DOM::Number->isFinite(undef); # false, would've been true with
292             # global isFinite(undef)
293              
294             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite>
295              
296             =head2 isInteger
297              
298             Determine whether the passed value is an integer.
299              
300             Example:
301              
302             HTML::Object::DOM::Number->isInteger(value)
303              
304             HTML::Object::DOM::Number->isInteger(0); # true
305             HTML::Object::DOM::Number->isInteger(1); # true
306             HTML::Object::DOM::Number->isInteger(-100000); # true
307             HTML::Object::DOM::Number->isInteger(99999999999999999999999); # true
308              
309             HTML::Object::DOM::Number->isInteger(0.1); # false
310             HTML::Object::DOM::Number->isInteger(Math->PI); # false
311              
312             HTML::Object::DOM::Number->isInteger(NaN); # false
313             HTML::Object::DOM::Number->isInteger(Infinity); # false
314             HTML::Object::DOM::Number->isInteger(-Infinity); # false
315             HTML::Object::DOM::Number->isInteger('10'); # false
316             HTML::Object::DOM::Number->isInteger(true); # false
317             HTML::Object::DOM::Number->isInteger(false); # false
318             HTML::Object::DOM::Number->isInteger([1]); # false
319              
320             HTML::Object::DOM::Number->isInteger(5.0); # true
321             HTML::Object::DOM::Number->isInteger(5.000000000000001); # false
322             HTML::Object::DOM::Number->isInteger(5.0000000000000001); # true
323              
324             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger>
325              
326             =head2 isNaN
327              
328             Determine whether the passed value is C<NaN>.
329              
330             Example:
331              
332             HTML::Object::DOM::Number->isNaN(value)
333              
334             HTML::Object::DOM::Number->isNaN(NaN); # true
335             HTML::Object::DOM::Number->isNaN(HTML::Object::DOM::Number->NaN); # true
336             HTML::Object::DOM::Number->isNaN(0 / 0); # true
337              
338             # e->g. these would have been true with global isNaN()
339             HTML::Object::DOM::Number->isNaN('NaN'); # false
340             HTML::Object::DOM::Number->isNaN(undefined); # false
341             HTML::Object::DOM::Number->isNaN({}); # false
342             HTML::Object::DOM::Number->isNaN('blabla'); # false
343              
344             # These all return false
345             HTML::Object::DOM::Number->isNaN(true);
346             HTML::Object::DOM::Number->isNaN(undef);
347             HTML::Object::DOM::Number->isNaN(37);
348             HTML::Object::DOM::Number->isNaN('37');
349             HTML::Object::DOM::Number->isNaN('37.37');
350             HTML::Object::DOM::Number->isNaN('');
351             HTML::Object::DOM::Number->isNaN(' ');
352              
353             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN>
354              
355             =head2 isSafeInteger
356              
357             Determine whether the passed value is a safe integer (number between -(2^53 - 1) and 2^53 - 1).
358              
359             Example:
360              
361             HTML::Object::DOM::Number->isSafeInteger(3); # true
362             HTML::Object::DOM::Number->isSafeInteger(POSIX::pow(2, 53)); # false
363             HTML::Object::DOM::Number->isSafeInteger(POSIX::pow(2, 53) - 1); # true
364             HTML::Object::DOM::Number->isSafeInteger(NaN); # false
365             HTML::Object::DOM::Number->isSafeInteger(Infinity); # false
366             HTML::Object::DOM::Number->isSafeInteger('3'); # false
367             HTML::Object::DOM::Number->isSafeInteger(3.1); # false
368             HTML::Object::DOM::Number->isSafeInteger(3.0); # true
369              
370             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger>
371              
372             =head2 parseFloat
373              
374             Provided with a value and this will return a new L<HTML::Object::DOM::Number> object.
375              
376             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseFloat>
377              
378             =head2 parseInt
379              
380             Provided with a value and this will return a new L<HTML::Object::DOM::Number> object.
381              
382             See also L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/parseInt>
383              
384             =head1 AUTHOR
385              
386             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
387              
388             =head1 SEE ALSO
389              
390             L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number>, L<Machine::Epsilon>
391              
392             =head1 COPYRIGHT & LICENSE
393              
394             Copyright(c) 2021 DEGUEST Pte. Ltd.
395              
396             All rights reserved
397              
398             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
399              
400             =cut