File Coverage

blib/lib/Sort/Packed.pm
Criterion Covered Total %
statement 44 53 83.0
branch 15 26 57.6
condition 7 15 46.6
subroutine 8 10 80.0
pod 5 5 100.0
total 79 109 72.4


line stmt bran cond sub pod time code
1             package Sort::Packed;
2              
3             our $VERSION = '0.08';
4              
5 1     1   128785 use strict;
  1         3  
  1         44  
6 1     1   5 use warnings;
  1         3  
  1         32  
7 1     1   6 use Carp;
  1         1  
  1         697  
8              
9             require Exporter;
10              
11             our @ISA = qw(Exporter);
12             our @EXPORT_OK = qw( sort_packed
13             radixsort_packed
14             mergesort_packed
15             sort_packed_custom
16             mergesort_packed_custom
17             reverse_packed
18             shuffle_packed );
19              
20             # byte_order:
21             # 0 - big endian
22             # 1 - little endian
23              
24             # type
25             # 0 - unsigned
26             # 1 - signed
27             # 2 - float
28             # 3 - float x86
29              
30             my %nv_format = ( '5839b4c876bebf3f' => 'LE',
31             '3fbfbe76c8b43958' => 'BE',
32             '83c0caa145b6f3fdfb3f0000' => 'LE_x86',
33             '3ffbfbe76c8b4395810624dd2f1a9fbe' => 'BE',
34             'be9f1a2fdd24068195438b6ce7fbfb3f' => 'LE',
35             '83c0caa145b6f3fdfb3f000000000000' => 'LE_x86');
36              
37             my $double_format = $nv_format{unpack 'H*' => pack d => 0.124} || 'LE';
38             my $double_byte_order = ($double_format =~ /^BE/ ? 0 : 1);
39             my $double_type = ($double_format =~ /x86/ ? 2 : 3);
40              
41             require XSLoader;
42             XSLoader::load('Sort::Packed', $VERSION);
43              
44             my %cache;
45             sub _template_props {
46 39 50   39   283 my ($dir, $pattern, $rep) = $_[0] =~ /^([+\-]?)(\w!?)(\d*)$/
47             or croak "invalid template '$_[0]'";
48              
49 39 100       89 $dir = ($dir eq '-' ? -1 : 1);
50 39   50     147 $rep ||= 1;
51              
52 39 50       99 $pattern =~ /^[bBhHuUwxX]/
53             and croak "unsupported pack format '$pattern'";
54              
55 39         37 my ($test1, $test2, $test3);
56 39         52 eval {
57 1     1   7 no warnings;
  1         2  
  1         1615  
58 39         67 $test1 = pack $pattern => 0x1;
59 39         78 $test2 = unpack $pattern => pack $pattern => -1;
60             };
61 39 50       82 $@ and croak "invalid pack pattern '$pattern': $@";
62              
63 39         57 my $vsize = length $test1;
64 39         60 my $ix = index $test1, chr 0x1;
65 39 100       140 my $vtype = ($test2 eq '-1' ? 1 : 0);
66 39         40 my $byte_order;
67 39 100       89 if ($pattern =~ /^[fdFD]/) {
68 9         11 $vtype = $double_type;
69 9         12 $byte_order = $double_byte_order;
70             }
71             else {
72 30 100 66     155 if ($vsize == 1 or $ix == $vsize - 1) {
    50          
73 6         9 $byte_order = 0;
74             }
75             elsif ($ix == 0) {
76 24         32 $byte_order = 1;
77             }
78             else {
79 0         0 croak "unsupported pack format '$pattern'"
80             }
81             }
82              
83 39         236 $dir, $vsize, $vtype, $byte_order, $rep
84             }
85              
86             sub radixsort_packed {
87 390 50   390 1 1293273 @_ == 2 or croak 'Usage: sort_packed($format, $vector)';
88 390   100     2037 my ($dir, $vsize, $vtype, $byte_order, $rep) = @{$cache{$_[0]} ||= [_template_props($_[0])]};
  390         8580  
89 390         28167 _radixsort_packed($_[1], $dir, $vsize, $vtype, $byte_order, $rep);
90             }
91              
92             sub mergesort_packed {
93 390 50   390 1 976875 @_ == 2 or croak 'Usage: radixsort_packed($format, $vector)';
94 390   50     680 my ($dir, $vsize, $vtype, $byte_order, $rep) = @{$cache{$_[0]} ||= [_template_props($_[0])]};
  390         2387  
95 390         16296 _mergesort_packed($_[1], undef, $dir, $vsize, $vtype, $byte_order, $rep);
96             }
97              
98             *sort_packed = \&radixsort_packed;
99              
100             sub mergesort_packed_custom (&@) {
101 390 50   390 1 1307693 @_ == 3 or croak 'Usage: mergesort_packed_custom { cmp($a, $b) } $format, $vector';
102 390   50     637 my ($dir, $vsize, $vtype, $byte_order, $rep) = @{$cache{$_[1]} ||= [_template_props($_[1])]};
  390         2156  
103 390         3536 _mergesort_packed($_[2], $_[0], $dir, $vsize, $vtype, $byte_order, $rep);
104             }
105              
106             *sort_packed_custom = \&radixsort_packed_custom;
107              
108             sub reverse_packed {
109 0 0   0 1   @_ == 2 or croak 'Usage: reverse_packed($format, $vector)';
110 0   0       my (undef, $vsize, undef, undef, $rep) = @{$cache{$_[0]} ||= [_template_props($_[0])]};
  0            
111 0           _reverse_packed($_[1], $vsize * $rep);
112             }
113              
114             sub shuffle_packed {
115 0 0   0 1   @_ == 2 or croak 'Usage: shuffle_packed($format, $vector)';
116 0   0       my (undef, $vsize, undef, undef, $rep) = @{$cache{$_[0]} ||= [_template_props($_[0])]};
  0            
117 0           _shuffle_packed($_[1], $vsize * $rep);
118             }
119              
120             1;
121             __END__