File Coverage

lib/Algorithm/Diff/XS.pm
Criterion Covered Total %
statement 365 416 87.7
branch 112 144 77.7
condition 86 107 80.3
subroutine 52 63 82.5
pod 0 10 0.0
total 615 740 83.1


line stmt bran cond sub pod time code
1             package Algorithm::Diff::XS;
2 2     2   4741 use 5.006;
  2         8  
  2         77  
3 2     2   12 use strict;
  2     2   2  
  2         55  
  2         15  
  2         5  
  2         66  
4 2     2   25 use warnings;
  2         8  
  2         65  
5 2     2   12 use vars '$VERSION';
  2     2   3  
  2         110  
  2         10  
  2         4  
  2         24  
6 2     2   2212 use Algorithm::Diff;
  2         13346  
  2         335  
7 2     2   98  
  2         3  
  2         6256  
8             BEGIN {
9 2     2   4     $VERSION = '0.04';
10 2         10     require XSLoader;
11 2         1248     XSLoader::load( __PACKAGE__, $VERSION );
12              
13 2         12     my $code = do {
14 2 50       170         open my $fh, '<', $INC{'Algorithm/Diff.pm'}
15                       or die "Cannot read $INC{'Algorithm/Diff.pm'}: $!";
16 2         10         local $/;
17 2         349         <$fh>;
18                 };
19              
20                 {
21 2     2   20         no warnings;
  2         4  
  2         251  
  2         4  
22 2         5         local $@;
23 2         201         $code =~ s/Algorithm::Diff/Algorithm::Diff::XS/g;
24 2         212         $code =~ s/sub LCSidx/sub LCSidx_old/g;
25 2         320         $code = "#line 1 " . __FILE__ . "\n$code";
26 2         246         eval $code;
27 2 50       643         die $@ if $@;
28                 }
29              
30 2     2   13     no warnings 'redefine';
  2         3  
  2         246  
31              
32                 sub LCSidx {
33 11     11 0 253         my $lcs = Algorithm::Diff::XS->_CREATE_;
34 11         25         my ( @l, @r );
35 11         57         for my $chunk ( $lcs->_LCS_(@_) ) {
36 22     25   37             push @l, $chunk->[0];
  25         37  
37 22         36             push @r, $chunk->[1];
  25         105  
38 25         27         }
39 11         92         return ( \@l, \@r );
  25         28  
40 25         28     }
41             }
42 25         132  
43             sub _line_map_ {
44 115     11   154     my $ctx = shift;
  11         21  
45 115         739     my %lines;
  11         20  
46 115 100       224     push @{ $lines{ $_[$_] } }, $_ for 0 .. $#_; # values MUST be SvIOK
  11         47  
  39         128  
47 11         42     \%lines;
48 1         3 }
  1         6  
49              
50             sub _LCS_ {
51 11     11   28     my ( $ctx, $a, $b ) = @_;
52 114         1106     my ( $amin, $amax, $bmin, $bmax ) = ( 0, $#$a, 0, $#$b );
  11         37  
53              
54 11   100     104     while ( $amin <= $amax and $bmin <= $bmax and $a->[$amin] eq $b->[$bmin] ) {
      100        
55 25 50       84         $amin++;
  6         9  
56 6         31         $bmin++;
57                 }
58 11   100     96     while ( $amin <= $amax and $bmin <= $bmax and $a->[$amax] eq $b->[$bmax] ) {
      100        
59 2         4         $amax--;
60 2         7         $bmax--;
61                 }
62              
63 11         62     my $h =
64                   $ctx->_line_map_( @$b[ $bmin .. $bmax ] ); # line numbers are off by $bmin
65              
66 11 50       34     return $amin + _core_loop_( $ctx, $a, $amin, $amax, $h ) + ( $#$a - $amax )
67                   unless wantarray;
68 41     41   55  
69 11   66     88     my @lcs = _core_loop_( $ctx, $a, $amin, $amax, $h );
  41         306  
70 11 100       37     if ( $bmin > 0 ) {
71 3         10         $_->[1] += $bmin for @lcs; # correct line numbers
72 41 50 66     378     }
73              
74 11         98     map( [ $_ => $_ ], 0 .. ( $amin - 1 ) ),
  41         144  
75 41         91       @lcs,
76                   map( [ $_ => ++$bmax ], ( $amax + 1 ) .. $#$a );
77             }
78              
79 0         0 1;
80 0         0  
81             __END__
82 0         0
83             =head1 NAME
84 0         0
85             Algorithm::Diff::XS - Algorithm::Diff with XS core loop
86            
87 0         0 =head1 SYNOPSIS
88            
89 0 0       0 # Drop-in replacement to Algorithm::Diff, but "compact_diff"
    0          
90             # and C<LCSidx> will run much faster for large data sets.
91 0         0 use Algorithm::Diff::XS qw( compact_diff LCSidx );
92            
93             =head1 DESCRIPTION
94            
95 0         0 This module is a simple re-packaging of Joe Schaefer's excellent
96             but not very well-known L<Algorithm::LCS> with a drop-in interface
97             that simply re-uses the installed version of the L<Algorithm::Diff>
98             module.
99 0         0
100             Note that only the C<LCSidx> function is optimized in XS at the
101             moment, which means only C<compact_diff> will get significantly
102             faster for large data sets, while C<diff> and C<sdiff> will run
103             in identical speed as C<Algorithm::Diff>.
104 0         0
105 0         0 =head1 BENCHMARK
106            
107             Rate Algorithm::Diff Algorithm::Diff::XS
108             Algorithm::Diff 14.7/s -- -98%
109             Algorithm::Diff::XS 806/s 5402% --
110            
111             The benchmarking script is as below:
112            
113             my @data = ([qw/a b d/ x 50], [qw/b a d c/ x 50]);
114             cmpthese( 500, {
115             'Algorithm::Diff' => sub {
116             Algorithm::Diff::compact_diff(@data)
117             },
118             'Algorithm::Diff::XS' => sub {
119             Algorithm::Diff::XS::compact_diff(@data)
120             },
121             });
122            
123             =head1 SEE ALSO
124            
125             L<Algorithm::Diff>, L<Algorithm::LCS>.
126            
127             =head1 AUTHORS
128 25     25   154
129 25         27 Audrey Tang E<lt>cpan@audreyt.orgE<gt>
130 25         100
131 25         30 =head1 COPYRIGHT
132 25         27
133             Copyright 2008 by Audrey Tang E<lt>cpan@audreyt.orgE<gt>.
134 25 50       70
135             Contains derived code copyrighted 2003 by Joe Schaefer,
136 0         0 E<lt>joe+cpan@sunstarsys.comE<gt>.
137 0         0
138 0         0 This library is free software; you can redistribute it and/or modify
139             it under the same terms as Perl itself.
140            
141             =cut
142 25 50 33     85