—# /=====================================================================\ #
# | LaTeXML::Common::Number | #
# | Representation of numbers | #
# |=====================================================================| #
# | Part of LaTeXML: | #
# | Public domain software, produced as part of work done by the | #
# | United States Government & not subject to copyright in the US. | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov> #_# | #
# | http://dlmf.nist.gov/LaTeXML/ (o o) | #
# \=========================================================ooo==U==ooo=/ #
package
LaTeXML::Common::Number;
use
LaTeXML::Global;
use
strict;
use
warnings;
use
LaTeXML::Core::Token;
our
@EXPORT
= (
qw(&Number)
);
#======================================================================
# Exported constructor.
sub
Number {
my
(
$number
) =
@_
;
return
LaTeXML::Common::Number->new(
$number
); }
#======================================================================
sub
new {
my
(
$class
,
$number
) =
@_
;
$number
= ToString(
$number
)
if
ref
$number
;
return
bless
[
$number
||
"0"
],
$class
; }
sub
valueOf {
my
(
$self
) =
@_
;
return
$$self
[0]; }
sub
toString {
my
(
$self
) =
@_
;
return
$$self
[0]; }
my
@SCALES
= (1, 10, 100, 1000, 10000, 100000);
# smallest number that makes a difference added to 1 in Perl's float format.
my
$EPSILON
= 1.0;
while
(1.0 +
$EPSILON
/ 2 != 1) {
$EPSILON
/= 2.0; }
# Round $number to $prec decimals (0...6)
# attempting to do so portably.
sub
roundto {
my
(
$number
,
$prec
) =
@_
;
$prec
= 2
unless
defined
$prec
;
$prec
= 0
if
$prec
< 0;
$prec
= 5
if
$prec
> 5;
my
$scale
=
$SCALES
[
$prec
];
# scale to integer, w/some slop in case arbitrarily close to an integer...
my
$n
=
$number
*
$scale
* (1 + 100 *
$EPSILON
);
return
int
(
$n
< -
$EPSILON
?
$n
- 0.5 : (
$n
>
$EPSILON
?
$n
+ 0.5 : 0.0)) /
$scale
; }
sub
ptValue {
my
(
$self
,
$prec
) =
@_
;
return
roundto(
$$self
[0] / 65536,
$prec
); }
sub
pxValue {
my
(
$self
,
$prec
) =
@_
;
return
roundto(
$$self
[0] / 65536 * (
$STATE
->lookupValue(
'DPI'
) || 100 / 72.27),
$prec
); }
sub
unlist {
my
(
$self
) =
@_
;
return
$self
; }
sub
revert {
my
(
$self
) =
@_
;
return
ExplodeText(
$self
->toString); }
sub
smaller {
my
(
$self
,
$other
) =
@_
;
return
(
$self
->valueOf <
$other
->valueOf) ?
$self
:
$other
; }
sub
larger {
my
(
$self
,
$other
) =
@_
;
return
(
$self
->valueOf >
$other
->valueOf) ?
$self
:
$other
; }
sub
absolute {
my
(
$self
,
$other
) =
@_
;
return
(
ref
$self
)->new(
abs
(
$self
->valueOf)); }
sub
sign {
my
(
$self
) =
@_
;
return
(
$self
->valueOf < 0) ? -1 : ((
$self
->valueOf > 0) ? 1 : 0); }
sub
negate {
my
(
$self
) =
@_
;
return
(
ref
$self
)->new(-
$self
->valueOf); }
sub
add {
my
(
$self
,
$other
) =
@_
;
return
(
ref
$self
)->new(
$self
->valueOf +
$other
->valueOf); }
sub
subtract {
my
(
$self
,
$other
) =
@_
;
return
(
ref
$self
)->new(
$self
->valueOf -
$other
->valueOf); }
# arg 2 is a number
sub
multiply {
my
(
$self
,
$other
) =
@_
;
return
(
ref
$self
)->new(
int
(
$self
->valueOf * (
ref
$other
?
$other
->valueOf :
$other
))); }
# Truncating division
sub
divide {
my
(
$self
,
$other
) =
@_
;
return
(
ref
$self
)->new(
int
(
$self
->valueOf / (
ref
$other
?
$other
->valueOf :
$other
))); }
# Rounding division
sub
divideround {
my
(
$self
,
$other
) =
@_
;
return
(
ref
$self
)->new(
int
(0.5 +
$self
->valueOf / (
ref
$other
?
$other
->valueOf :
$other
))); }
sub
stringify {
my
(
$self
) =
@_
;
return
"Number["
.
$$self
[0] .
"]"
; }
#======================================================================
1;
__END__
=pod
=head1 NAME
C<LaTeXML::Common::Number> - representation of numbers;
extends L<LaTeXML::Common::Object>.
=head2 Exported functions
=over 4
=item C<< $number = Number($num); >>
Creates a Number object representing C<$num>.
=back
=head2 Methods
=over 4
=item C<< @tokens = $object->unlist; >>
Return a list of the tokens making up this C<$object>.
=item C<< $string = $object->toString; >>
Return a string representing C<$object>.
=item C<< $string = $object->ptValue; >>
Return a value representing C<$object> without the measurement unit (pt)
with limited decimal places.
=item C<< $string = $object->pxValue; >>
Return an integer value representing C<$object> in pixels.
Uses the state variable C<DPI> (dots per inch).
=item C<< $n = $object->valueOf; >>
Return the value in scaled points (ignoring shrink and stretch, if any).
=item C<< $n = $object->smaller($other); >>
Return C<$object> or C<$other>, whichever is smaller
=item C<< $n = $object->larger($other); >>
Return C<$object> or C<$other>, whichever is larger
=item C<< $n = $object->absolute; >>
Return an object representing the absolute value of the C<$object>.
=item C<< $n = $object->sign; >>
Return an integer: -1 for negatives, 0 for 0 and 1 for positives
=item C<< $n = $object->negate; >>
Return an object representing the negative of the C<$object>.
=item C<< $n = $object->add($other); >>
Return an object representing the sum of C<$object> and C<$other>
=item C<< $n = $object->subtract($other); >>
Return an object representing the difference between C<$object> and C<$other>
=item C<< $n = $object->multiply($n); >>
Return an object representing the product of C<$object> and C<$n> (a regular number).
=item C<< $n = $object->divide($n); >>
Return an object representing the (truncating) division of C<$object> by C<$n> (a regular number).
=item C<< $n = $object->divideround($n); >>
Return an object representing the (rounding) division of C<$object> by C<$n> (a regular number).
=back
=head1 AUTHOR
Bruce Miller <bruce.miller@nist.gov>
=head1 COPYRIGHT
Public domain software, produced as part of work done by the
United States Government & not subject to copyright in the US.
=cut