1 package File
::Rsync
::Mirror
::Recentfile
::FakeBigFloat
;
5 use Data
::Float
qw(nextup nextdown);
13 sub _bigfloatmax
($$);
14 sub _bigfloatmin
($$);
15 sub _increase_a_bit
($;$);
16 sub _increase_a_bit_tail
($$);
17 sub _my_sprintf_float
($);
23 File::Rsync::Mirror::Recentfile::FakeBigFloat - pseudo bigfloat support
27 use version
; our $VERSION = qv
('0.0.1');
30 use base
qw(Exporter);
42 $EXPORT_TAGS{all
} = \
@EXPORT_OK;
46 use File::Rsync::Mirror::Recentfile::FakeBigFloat qw(:all);
48 =head1 (ONLY) INTERNAL FUNCTIONS
50 These functions are not part of a public interface and can be
51 changed and go away any time without prior notice.
55 We treat strings that look like floating point numbers. If the native
56 floating point support is good enough we use it. If it isn't we make
57 sure no two unequal numbers are treated the same.
61 All functions are exported in the C<:all> tag.
63 =head2 _bigfloatcmp ( $l, $r )
65 Cmp function for floating point numbers that have a longer
66 mantissa than can be handled by native perl floats.
69 sub _bigfloatcmp
($$) {
71 if ($l =~ /\./ || $r =~ /\./) {
72 # if one is a float, both must be, otherwise perl gets it wrong (see test)
74 $_ .= ".0" unless /\./;
77 my $native = $l <=> $r;
78 return $native if $native;
79 $l =~ s/^/0/ while index($l,".") < index($r,".");
80 $r =~ s/^/0/ while index($r,".") < index($l,".");
84 =head2 _bigfloatge ( $l, $r )
89 sub _bigfloatge
($$) {
91 _bigfloatcmp
($l,$r) >= 0;
94 =head2 _bigfloatgt ( $l, $r )
99 sub _bigfloatgt
($$) {
101 _bigfloatcmp
($l,$r) > 0;
104 =head2 _bigfloatle ( $l, $r )
109 sub _bigfloatle
($$) {
111 _bigfloatcmp
($l,$r) <= 0;
114 =head2 _bigfloatlt ( $l, $r )
119 sub _bigfloatlt
($$) {
121 _bigfloatcmp
($l,$r) < 0;
124 =head2 _bigfloatmax ( $l, $r )
126 Same for max (of two arguments)
129 sub _bigfloatmax
($$) {
131 return _bigfloatcmp
($l,$r) >= 0 ?
$l : $r;
134 =head2 _bigfloatmin ( $l, $r )
136 Same for min (of two arguments)
139 sub _bigfloatmin
($$) {
141 return _bigfloatcmp
($l,$r) <= 0 ?
$l : $r;
144 =head2 _increase_a_bit ( $l, $r )
146 =head2 _increase_a_bit ( $n )
148 The first form calculates a string that is between the two numbers,
149 closer to $l to prevent rounding effects towards $r. The second form
150 calculates the second number itself based on the current architecture
151 and L<Data::Float::nextup()>.
153 Note: there is a %.128f hard coded that needs to be fixed
156 sub _my_sprintf_float
($) {
158 my $r = sprintf "%.128f", $x;
162 sub _increase_a_bit
($;$) {
164 unless (defined $l) {
165 die "Alert: _increase_a_bit called with undefined first argument";
169 die "Alert: _increase_a_bit called with identical arguments";
172 $r = _my_sprintf_float
(Data
::Float
::nextup
($l));
178 my $try = _my_sprintf_float
((3*$l+$r)/4);
179 if (_bigfloatlt
($l,$try) && _bigfloatlt
($try,$r) ) {
184 return _increase_a_bit_tail
($l,$r);
186 sub _increase_a_bit_tail
($$) {
190 $_ .= ".0" unless /\./;
192 $l =~ s/^/0/ while index($l,".") < index($r,".");
193 $r =~ s/^/0/ while index($r,".") < index($l,".");
194 $l .= "0" while length($l) < length($r);
195 $r .= "0" while length($r) < length($l);
197 DIG
: for (my $i = 0; $i < length($l); $i++) {
198 if (substr($l,$i,1) ne substr($r,$i,1)) {
203 $ret = substr($l,0,$diffdigit);
204 my $sl = substr($l,$diffdigit); # significant l
205 my $sr = substr($r,$diffdigit);
210 my $srlength = length $sr;
211 my $srmantissa = $srlength - index($sr,".");
212 # we want 1+$srlength because if l ends in 99999 and r in 00000,
213 # we need one digit more
214 my $fformat = sprintf "%%0%d.%df", 1+$srlength, $srmantissa;
215 my $appe = sprintf $fformat, (3*$sl+$sr)/4;
216 $appe =~ s/(\d)0+$/$1/;
222 my $try = substr($ret,0,length($ret)-1);
223 if (_bigfloatlt
($l,$try) && _bigfloatlt
($try,$r)) {
232 =head1 COPYRIGHT & LICENSE
234 Copyright 2008 Andreas König.
236 This program is free software; you can redistribute it and/or modify it
237 under the same terms as Perl itself.
241 1; # End of File::Rsync::Mirror::Recentfile
245 # cperl-indent-level: 4