1# /=====================================================================\ # 2# | LaTeXML::Common::Number | # 3# | Representation of numbers | # 4# |=====================================================================| # 5# | Part of LaTeXML: | # 6# | Public domain software, produced as part of work done by the | # 7# | United States Government & not subject to copyright in the US. | # 8# |---------------------------------------------------------------------| # 9# | Bruce Miller <bruce.miller@nist.gov> #_# | # 10# | http://dlmf.nist.gov/LaTeXML/ (o o) | # 11# \=========================================================ooo==U==ooo=/ # 12package LaTeXML::Common::Number; 13use LaTeXML::Global; 14use strict; 15use warnings; 16use LaTeXML::Common::Object; 17use LaTeXML::Core::Token; 18use base qw(LaTeXML::Common::Object); 19use base qw(Exporter); 20our @EXPORT = (qw(&Number &roundto)); 21 22#====================================================================== 23# Exported constructor. 24 25sub Number { 26 my ($number) = @_; 27 return LaTeXML::Common::Number->new($number); } 28 29#====================================================================== 30 31sub new { 32 my ($class, $number) = @_; 33 $number = ToString($number) if ref $number; 34 return bless [$number || "0"], $class; } 35 36sub valueOf { 37 my ($self) = @_; 38 return $$self[0]; } 39 40sub toString { 41 my ($self) = @_; 42 return $$self[0]; } 43 44my @SCALES = (1, 10, 100, 1000, 10000, 100000); 45 46# smallest number that makes a difference added to 1 in Perl's float format. 47my $EPSILON = 1.0; 48while (1.0 + $EPSILON / 2 != 1) { 49 $EPSILON /= 2.0; } 50 51# Round $number to $prec decimals (0...6) 52# attempting to do so portably. 53sub roundto { 54 my ($number, $prec) = @_; 55 $prec = 2 unless defined $prec; 56 $prec = 0 if $prec < 0; 57 $prec = 5 if $prec > 5; 58 my $scale = $SCALES[$prec]; 59 # scale to integer, w/some slop in case arbitrarily close to an integer... 60 my $n = $number * $scale * (1 + 100 * $EPSILON); 61 return int($n < -$EPSILON ? $n - 0.5 : ($n > $EPSILON ? $n + 0.5 : 0.0)) / $scale; } 62 63sub ptValue { 64 my ($self, $prec) = @_; 65 return roundto($$self[0] / 65536, $prec); } 66 67sub pxValue { 68 my ($self, $prec) = @_; 69 return roundto($$self[0] / 65536 * ($STATE->lookupValue('DPI') || 100 / 72.27), $prec); } 70 71sub unlist { 72 my ($self) = @_; 73 return $self; } 74 75sub revert { 76 my ($self) = @_; 77 return ExplodeText($self->toString); } 78 79sub smaller { 80 my ($self, $other) = @_; 81 return ($self->valueOf < $other->valueOf) ? $self : $other; } 82 83sub larger { 84 my ($self, $other) = @_; 85 return ($self->valueOf > $other->valueOf) ? $self : $other; } 86 87sub absolute { 88 my ($self, $other) = @_; 89 return (ref $self)->new(abs($self->valueOf)); } 90 91sub sign { 92 my ($self) = @_; 93 return ($self->valueOf < 0) ? -1 : (($self->valueOf > 0) ? 1 : 0); } 94 95sub negate { 96 my ($self) = @_; 97 return (ref $self)->new(-$self->valueOf); } 98 99sub add { 100 my ($self, $other) = @_; 101 return (ref $self)->new($self->valueOf + $other->valueOf); } 102 103sub subtract { 104 my ($self, $other) = @_; 105 return (ref $self)->new($self->valueOf - $other->valueOf); } 106 107# arg 2 is a number 108sub multiply { 109 my ($self, $other) = @_; 110 return (ref $self)->new(int($self->valueOf * (ref $other ? $other->valueOf : $other))); } 111 112# Truncating division 113sub divide { 114 my ($self, $other) = @_; 115 return (ref $self)->new(int($self->valueOf / (ref $other ? $other->valueOf : $other))); } 116 117# Rounding division 118sub divideround { 119 my ($self, $other) = @_; 120 return (ref $self)->new(int(0.5 + $self->valueOf / (ref $other ? $other->valueOf : $other))); } 121 122sub stringify { 123 my ($self) = @_; 124 return "Number[" . $$self[0] . "]"; } 125 126#====================================================================== 1271; 128 129__END__ 130 131=pod 132 133=head1 NAME 134 135C<LaTeXML::Common::Number> - representation of numbers; 136extends L<LaTeXML::Common::Object>. 137 138=head2 Exported functions 139 140=over 4 141 142=item C<< $number = Number($num); >> 143 144Creates a Number object representing C<$num>. 145 146=back 147 148=head2 Methods 149 150=over 4 151 152=item C<< @tokens = $object->unlist; >> 153 154Return a list of the tokens making up this C<$object>. 155 156=item C<< $string = $object->toString; >> 157 158Return a string representing C<$object>. 159 160=item C<< $string = $object->ptValue; >> 161 162Return a value representing C<$object> without the measurement unit (pt) 163with limited decimal places. 164 165=item C<< $string = $object->pxValue; >> 166 167Return an integer value representing C<$object> in pixels. 168Uses the state variable C<DPI> (dots per inch). 169 170=item C<< $n = $object->valueOf; >> 171 172Return the value in scaled points (ignoring shrink and stretch, if any). 173 174=item C<< $n = $object->smaller($other); >> 175 176Return C<$object> or C<$other>, whichever is smaller 177 178=item C<< $n = $object->larger($other); >> 179 180Return C<$object> or C<$other>, whichever is larger 181 182=item C<< $n = $object->absolute; >> 183 184Return an object representing the absolute value of the C<$object>. 185 186=item C<< $n = $object->sign; >> 187 188Return an integer: -1 for negatives, 0 for 0 and 1 for positives 189 190=item C<< $n = $object->negate; >> 191 192Return an object representing the negative of the C<$object>. 193 194=item C<< $n = $object->add($other); >> 195 196Return an object representing the sum of C<$object> and C<$other> 197 198=item C<< $n = $object->subtract($other); >> 199 200Return an object representing the difference between C<$object> and C<$other> 201 202=item C<< $n = $object->multiply($n); >> 203 204Return an object representing the product of C<$object> and C<$n> (a regular number). 205 206=item C<< $n = $object->divide($n); >> 207 208Return an object representing the (truncating) division of C<$object> by C<$n> (a regular number). 209 210=item C<< $n = $object->divideround($n); >> 211 212Return an object representing the (rounding) division of C<$object> by C<$n> (a regular number). 213 214=back 215 216=head1 AUTHOR 217 218Bruce Miller <bruce.miller@nist.gov> 219 220=head1 COPYRIGHT 221 222Public domain software, produced as part of work done by the 223United States Government & not subject to copyright in the US. 224 225=cut 226 227