File Coverage

blib/lib/Algorithm/Bitonic/Sort.pm
Criterion Covered Total %
statement 68 72 94.4
branch 15 18 83.3
condition 7 10 70.0
subroutine 9 9 100.0
pod 1 1 100.0
total 100 110 90.9


line stmt bran cond sub pod time code
1             package Algorithm::Bitonic::Sort;
2              
3 2     2   23785 use utf8;
  2         11  
  2         9  
4 2     2   53 use feature 'say';
  2         3  
  2         145  
5 2     2   428 use common::sense;
  2         12  
  2         7  
6 2     2   89 use constant DEBUG => $ENV{ALGORITHM_BITONIC_SORT_DEBUG};
  2         3  
  2         293  
7              
8             if (DEBUG) {
9             require Data::Dumper::Simple;
10             }
11              
12             our (@ISA, @EXPORT);
13             BEGIN {
14 2     2   7 require Exporter;
15 2         12 @ISA = qw(Exporter);
16 2         1427 @EXPORT = qw(bitonic_sort); # symbols to export on request
17             }
18              
19             # "A supercomputer is a device for turning compute-bound problems into I/O-bound problems."
20              
21             =encoding utf8
22              
23             =head1 NAME
24              
25             Algorithm::Bitonic::Sort - Sorting numbers with Bitonic Sort
26              
27             =head1 VERSION
28              
29             Version 0.04
30              
31             =cut
32              
33             our $VERSION = '0.04';
34              
35              
36             =head1 SYNOPSIS
37              
38             Use L with the following style.
39              
40             use Algorithm::Bitonic::Sort;
41            
42             my @sample = (1,4,8,4,4365,67,33,345);
43             my @result_up = bitonic_sort( 1 ,@sample); # incremental
44             my @result_down = bitonic_sort( 0 ,@sample); # decremental
45              
46             =head1 DESCRIPTION
47              
48             This is an Perl 5 implementation of Ken Batcher's Bitonic mergesort.
49              
50              
51             =head1 Limitation
52              
53             The original Bitonic can only sort N numbers, which N is a power of 2.
54              
55             Which means that you can sort a set of numbers (an array or list) which
56             contains 2 (2**1) or 4 (2**2) or 8 (2**3) or any 2**M amount of members.
57              
58              
59             =head1 EXPORT
60              
61             bitonic_sort
62              
63              
64             =head1 SUBROUTINES
65              
66             =head2 bitonic_sort
67              
68             Accepts the first param as the ascending/decreasing selector.
69             True (1 or any true value) means ascending (incremental),
70             False (0 or any false value) means decreasing.
71              
72             All the rest params will treat as members/items to be sorted.
73              
74             WARNING:
75             Giving any amount of members not equal to 2**N will have unexpected result and fail.
76              
77             =cut
78              
79             sub bitonic_sort {
80 30     30 1 353 my $up = shift;
81 30         17 say '#### Sort: '.Dumper(@_) if DEBUG;
82            
83 30 100       41 return @_ if int @_ <= 1;
84            
85 14 100       19 my $single_bit = shift @_ if @_ % 2;
86 14   100     21 $single_bit //= 'NA';
87            
88 14         7 say Dumper $single_bit if DEBUG;
89            
90 14         14 my @num = @_;
91 14         29 my @first = bitonic_sort( 1, @num[0..(@num /2 -1)] );
92 14         22 my @second = bitonic_sort( 0, @num[(@num /2)..(@num -1)] );
93            
94             #~ return _bitonic_merge( $up, @first, @second );
95 14         17 return _bitonic_merge( $up, $single_bit, @first, @second );
96             #~ return _bitonic_merge( $up, $single_bit, \@first, \@second );
97             }
98              
99             sub _bitonic_merge {
100 82     82   62 my $up = shift;
101 82         30 say '#### Merge: '.Dumper(@_) if DEBUG;
102            
103 82         63 my $single_bit = shift;
104 82         38 say Dumper $single_bit if DEBUG;
105             #~ my $first = shift; # ARRAY ref
106             #~ my $second = shift; # ARRAY ref
107            
108             # assume input @num is bitonic, and sorted list is returned
109 82 100       117 return @_ if int @_ == 1;
110            
111 34 50       38 my $single_bit_2 = shift @_ if @_ % 2;
112 34   100     39 $single_bit_2 //= 'NA';
113            
114 34         28 my @num = @_;
115 34         30 @num = _bitonic_compare( $up, @num );
116             #~ @num = _bitonic_compare( $up, $first, $second );
117            
118             #~ my @first = _bitonic_merge( $up, @num[0..(@num /2 -1)] );
119             #~ my @second = _bitonic_merge( $up, @num[(@num /2)..(@num -1)] );
120             #~ my @first = _bitonic_merge( $up, $single_bit, @num[0..(@num /2 -1)] );
121             #~ my @second = _bitonic_merge( $up, $single_bit, @num[(@num /2)..(@num -1)] );
122 34         50 my @first = _bitonic_merge( $up, 'NA', @num[0..(@num /2 -1)] );
123 34         48 my @second = _bitonic_merge( $up, 'NA', @num[(@num /2)..(@num -1)] );
124            
125 34         34 @num = (@first, @second);
126 34 100       45 @num = _some_sorting_algorithm( $up, $single_bit, @first, @second ) if $single_bit ne 'NA';
127 34 50       37 @num = _some_sorting_algorithm( $up, $single_bit_2, @first, @second ) if $single_bit_2 ne 'NA';
128            
129 34         18 say "#####\n# Merge Result\n#####\n".Dumper(@num) if DEBUG;
130            
131 34         48 return (@num);
132             }
133              
134             sub _bitonic_compare {
135 34     34   24 my $up = shift;
136 34         16 say '#### Compare: '.Dumper(@_) if DEBUG;
137 34         36 my @num = @_;
138             #~ my $first = shift; # ARRAY ref
139             #~ my $second = shift; # ARRAY ref
140             #~ say Dumper $first;
141            
142 34         36 my $dist = int @num /2;
143             #~
144 34         36 for my $i (0..$dist-1) {
145 48         21 say "i=$i, dist=$dist, $num[$i] > $num[$i+$dist]) == $up" if DEBUG;
146 48 100       69 if ( ($num[$i] > $num[$i+$dist]) == $up ) {
147 26         15 say "Swapping....." if DEBUG;
148 26         35 ($num[$i], $num[$i+$dist]) = ($num[$i+$dist], $num[$i]); #swap
149             }
150             }
151             #~ for my $i (0..(int @$first)) {
152             #~ if ( ($first->[$i] > $second->[$i]) == $up ) {
153             #~ ($first->[$i], $second->[$i]) = ($second->[$i], $first->[$i]); #swap
154             #~ }
155             #~ }
156            
157 34         19 say 'Compared result:'.Dumper(@num) if DEBUG;
158 34         43 return @num;
159             #~ return ($first, $second);
160             }
161              
162              
163             sub _some_sorting_algorithm {
164 2     2   1 my $up = shift;
165 2         3 my $single_bit = shift;
166 2         14 my @num = @_;
167 2         2 my @num_new;
168            
169 2         2 say "_SOME_SORTING_ALGORITHM: INPUT: ".Dumper(@num) if DEBUG;
170            
171 2         4 while (my $curr = shift @num) {
172 9         7 say "_SOME_SORTING_ALGORITHM: for: ".Dumper($curr, $single_bit, @num) if DEBUG;
173 9 100 66     24 if ($up and $single_bit < $curr) {
    50 33        
174 1         2 push @num_new, $single_bit;
175 1         2 push @num_new, $curr;
176 1         1 say "Return earlier, up is ".($up or '0').':'.Dumper(@num_new, @num) if DEBUG;
177 1         4 return (@num_new, @num);
178             } elsif ($single_bit > $curr and not $up) {
179 0         0 push @num_new, $single_bit;
180 0         0 push @num_new, $curr;
181 0         0 say "Return earlier, up is ".($up or '0').':'.Dumper(@num_new, @num) if DEBUG;
182 0         0 return (@num_new, @num)
183             } else {
184 8         13 push @num_new, $curr;
185             }
186             }
187            
188 1         1 push @num_new, $single_bit;
189 1         2 say "Return normal, ".Dumper(@num_new, @num) if DEBUG;
190 1         2 return @num_new;
191             }
192              
193             =head1 AUTHOR
194              
195             BlueT - Matthew Lien - 練喆明, C<< >>
196              
197             =head1 BUGS
198              
199             Please report any bugs or feature requests to C, or through
200             the web interface at L. I will be notified, and then you'll
201             automatically be notified of progress on your bug as I make changes.
202              
203              
204              
205              
206             =head1 SUPPORT
207              
208             You can find documentation for this module with the perldoc command.
209              
210             perldoc Algorithm::Bitonic::Sort
211              
212              
213             You can also look for information at:
214              
215             =over 4
216              
217             =item * RT: CPAN's request tracker (report bugs here)
218              
219             L
220              
221             =item * AnnoCPAN: Annotated CPAN documentation
222              
223             L
224              
225             =item * CPAN Ratings
226              
227             L
228              
229             =item * Search CPAN
230              
231             L
232              
233             =item * Launchpad
234              
235             L
236              
237             =item * GitHub
238              
239             L
240              
241             =back
242              
243              
244             =head1 ACKNOWLEDGEMENTS
245              
246             =head1 SEE ALSO
247              
248             =over 4
249              
250             =item * Batcher's web page at Kent State University
251              
252             L
253              
254             =item * Bitonic sorter on Wikipedia
255              
256             L
257              
258             =back
259              
260             =head1 LICENSE AND COPYRIGHT
261              
262             Copyright 2012 BlueT - Matthew Lien - 練喆明.
263              
264             This program is free software; you can redistribute it and/or modify it
265             under the terms of either: the GNU General Public License as published
266             by the Free Software Foundation; or the Artistic License.
267              
268             See http://dev.perl.org/licenses/ for more information.
269              
270              
271             =cut
272              
273             1; # End of Algorithm::Bitonic::Sort