Scalar::Vec::Util - Utility routines for vec strings.
VERSION
- Version 0.02
+ Version 0.03
SYNOPSIS
use Scalar::Vec::Util qw/vfill vcopy veq/;
The constants "SVU_PP" and "SVU_SIZE" are also only exported on request.
They are all exported by the tags ':consts' and ':all'.
+BENCHMARKS
+ The following timings were obtained by running the "samples/bench.pl"
+ script with perl 5.8.8 on a Core 2 Duo 2.66GHz machine. The "_pp"
+ entries are the pure Perl versions, while "_bv" are Bit::Vector
+ versions.
+
+ Filling bits at a given position :
+ Rate vfill_pp vfill_bv vfill
+ vfill_pp 80.3/s -- -100% -100%
+ vfill_bv 1053399/s 1312401% -- -11%
+ vfill 1180792/s 1471129% 12% --
+
+ Copying bits from a bit vector to a different one :
+ Rate vcopy_pp vcopy_bv vcopy
+ vcopy_pp 112/s -- -100% -100%
+ vcopy_bv 62599/s 55622% -- -89%
+ vcopy 558491/s 497036% 792% --
+
+ Moving bits in the same bit vector from a given position to a different
+ one :
+ Rate vmove_pp vmove_bv vmove
+ vmove_pp 64.8/s -- -100% -100%
+ vmove_bv 64742/s 99751% -- -88%
+ vmove 547980/s 845043% 746% --
+
+ Testing bit equality from different positions of different bit vectors :
+ Rate veq_pp veq_bv veq
+ veq_pp 92.7/s -- -100% -100%
+ veq_bv 32777/s 35241% -- -94%
+ veq 505828/s 545300% 1443% --
+
CAVEATS
Please report architectures where we can't use the alignment as the move
unit. I'll add exceptions for them.
=head1 VERSION
-Version 0.02
+Version 0.03
=cut
our $VERSION;
BEGIN {
- $VERSION = '0.02';
+ $VERSION = '0.03';
eval {
require XSLoader;
XSLoader::load(__PACKAGE__, $VERSION);
our @EXPORT_OK = map { @$_ } values %EXPORT_TAGS;
$EXPORT_TAGS{'all'} = [ @EXPORT_OK ];
+=head1 BENCHMARKS
+
+The following timings were obtained by running the C<samples/bench.pl> script with perl 5.8.8 on a Core 2 Duo 2.66GHz machine. The C<_pp> entries are the pure Perl versions, while C<_bv> are L<Bit::Vector> versions.
+
+=over 4
+
+=item Filling bits at a given position :
+
+ Rate vfill_pp vfill_bv vfill
+ vfill_pp 80.3/s -- -100% -100%
+ vfill_bv 1053399/s 1312401% -- -11%
+ vfill 1180792/s 1471129% 12% --
+
+=item Copying bits from a bit vector to a different one :
+
+ Rate vcopy_pp vcopy_bv vcopy
+ vcopy_pp 112/s -- -100% -100%
+ vcopy_bv 62599/s 55622% -- -89%
+ vcopy 558491/s 497036% 792% --
+
+=item Moving bits in the same bit vector from a given position to a different one :
+
+ Rate vmove_pp vmove_bv vmove
+ vmove_pp 64.8/s -- -100% -100%
+ vmove_bv 64742/s 99751% -- -88%
+ vmove 547980/s 845043% 746% --
+
+=item Testing bit equality from different positions of different bit vectors :
+
+ Rate veq_pp veq_bv veq
+ veq_pp 92.7/s -- -100% -100%
+ veq_bv 32777/s 35241% -- -94%
+ veq 505828/s 545300% 1443% --
+
+=back
+
=head1 CAVEATS
Please report architectures where we can't use the alignment as the move unit. I'll add exceptions for them.
use lib qw{blib/arch blib/lib};
use Scalar::Vec::Util qw/vfill vcopy veq/;
+my $has_bv = eval "use Bit::Vector; 1" || 0;
+print 'We ' . ('don\'t ' x !$has_bv) . "have Bit::Vector.\n";
my $n = 100_000;
my $i = 0;
return $_[0];
}
+sub len {
+ return $n - ($_[0] > $_[1] ? $_[0] : $_[1])
+}
+
+my ($bv1, $bv2, $bv3, $bv4);
+if ($has_bv) {
+ ($bv1, $bv2, $bv3, $bv4) = Bit::Vector->new($n, 4);
+}
+
print "fill:\n";
cmpthese -3, {
- vfill => sub { vfill $x, inc($i), $n - $i, 1; },
- vfill_pp => sub { Scalar::Vec::Util::vfill_pp($x, inc($i), $n - $i, 1); }
+ vfill => sub { vfill $x, inc($i), $n - $i, 1 },
+ vfill_pp => sub { Scalar::Vec::Util::vfill_pp($x, inc($i), $n - $i, 1) },
+ (vfill_bv => sub { $bv1->Interval_Fill(inc($i), $n - 1) }) x $has_bv
};
$i = 0;
my $y = '';
print "\ncopy:\n";
cmpthese -3, {
- vcopy => sub { vcopy $x, inc($i), $y, inc($j), $n - ($i > $j ? $i : $j); },
- vcopy_pp => sub { Scalar::Vec::Util::vcopy_pp($x, inc($i), $y, inc($j), $n - ($i > $j ? $i : $j)); }
+ vcopy => sub { vcopy $x, inc($i), $y, inc($j), len($i, $j) },
+ vcopy_pp => sub { Scalar::Vec::Util::vcopy_pp($x, inc($i), $y, inc($j), len($i, $j)) },
+ (vcopy_bv => sub { $bv2->Interval_Copy($bv1, inc($j), inc($i), len($i, $j)) }) x $has_bv
};
$i = 0;
$j = int $n / 2;
print "\nmove:\n";
cmpthese -3, {
- vcopy => sub { vcopy $x, inc($i), $x, inc($j), $n - ($i > $j ? $i : $j); },
- vcopy_pp => sub { Scalar::Vec::Util::vcopy_pp($x, inc($i), $x, inc($j), $n - ($i > $j ? $i : $j)); }
+ vmove => sub { vcopy $x, inc($i), $x, inc($j), len($i, $j) },
+ vmove_pp => sub { Scalar::Vec::Util::vcopy_pp($x, inc($i), $x, inc($j), len($i, $j)) },
+ (vmove_bv => sub { $bv1->Interval_Copy($bv1, inc($j), inc($i), len($i, $j)) }) x $has_bv
};
$i = 0;
$j = int $n / 2;
vfill $x, 0, $n, 1;
vfill $y, 0, $n, 1;
+if ($has_bv) {
+ $bv1->Fill();
+ $bv2->Fill();
+}
print "\neq:\n";
cmpthese -3, {
- veq => sub { veq $x, inc($i), $y, inc($j), $n - ($i > $j ? $i : $j); },
- veq_pp => sub { Scalar::Vec::Util::veq_pp($x, inc($i), $y, inc($j), $n - ($i > $j ? $i : $j)); }
+ veq => sub { veq $x, inc($i), $y, inc($j), len($i, $j) },
+ veq_pp => sub { Scalar::Vec::Util::veq_pp($x, inc($i), $y, inc($j), len($i, $j)) },
+ (veq_bv => sub {
+ inc($i);
+ inc($j);
+ my $l = len($i, $j);
+ $bv3->Resize($l);
+ $bv3->Interval_Copy($bv1, 0, $i, $l);
+ $bv4->Resize($l);
+ $bv4->Interval_Copy($bv2, 0, $j, $l);
+ $bv3->equal($bv4);
+ }) x $has_bv
};