| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Algorithm::Bitonic::Sort; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 2 |  |  | 2 |  | 24154 | use utf8; | 
|  | 2 |  |  |  |  | 9 |  | 
|  | 2 |  |  |  |  | 8 |  | 
| 4 | 2 |  |  | 2 |  | 50 | use feature 'say'; | 
|  | 2 |  |  |  |  | 1 |  | 
|  | 2 |  |  |  |  | 137 |  | 
| 5 | 2 |  |  | 2 |  | 453 | use common::sense; | 
|  | 2 |  |  |  |  | 11 |  | 
|  | 2 |  |  |  |  | 7 |  | 
| 6 | 2 |  |  | 2 |  | 86 | use constant DEBUG => $ENV{ALGORITHM_BITONIC_SORT_DEBUG}; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 280 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | if (DEBUG) { | 
| 9 |  |  |  |  |  |  | require Data::Dumper::Simple; | 
| 10 |  |  |  |  |  |  | } | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | our (@ISA, @EXPORT); | 
| 13 |  |  |  |  |  |  | BEGIN { | 
| 14 | 2 |  |  | 2 |  | 6 | require Exporter; | 
| 15 | 2 |  |  |  |  | 12 | @ISA = qw(Exporter); | 
| 16 | 2 |  |  |  |  | 1437 | @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.05 | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | =cut | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | our $VERSION = '0.05'; | 
| 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,2,67,33,345); | 
| 43 |  |  |  |  |  |  | my @result_inc = bitonic_sort( 1 ,@sample);	# incremental | 
| 44 |  |  |  |  |  |  | my @result_dec = bitonic_sort( 0 ,@sample);	# decremental | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | Bitonic mergesort is a parallel algorithm for sorting. It is also used as a construction method for building a sorting network. | 
| 49 |  |  |  |  |  |  | This is an Perl 5 implementation of Ken Batcher's Bitonic mergesort. | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | =head1 Limitation | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | This is a enhanced version of Bitonic Sort which removed the limitation of original version. | 
| 54 |  |  |  |  |  |  | This module supports any amount of numbers. | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | The original Bitonic can only sort N numbers, which N is a power of 2. | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | =head1 EXPORT | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | bitonic_sort | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | =head1 SUBROUTINES | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | =head2 bitonic_sort | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | The First Parameter works 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 other params will be treated as members/items to be sorted. | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | =cut | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | sub bitonic_sort { | 
| 78 | 30 |  |  | 30 | 1 | 624 | my $up = shift; | 
| 79 | 30 |  |  |  |  | 18 | say '#### Sort: '.Dumper(@_) if DEBUG; | 
| 80 |  |  |  |  |  |  |  | 
| 81 | 30 | 100 |  |  |  | 43 | return @_ if int @_ <= 1; | 
| 82 |  |  |  |  |  |  |  | 
| 83 | 14 | 100 |  |  |  | 19 | my $single_bit = shift @_ if @_ % 2; | 
| 84 | 14 |  | 100 |  |  | 20 | $single_bit //= 'NA'; | 
| 85 |  |  |  |  |  |  |  | 
| 86 | 14 |  |  |  |  | 10 | say Dumper $single_bit if DEBUG; | 
| 87 |  |  |  |  |  |  |  | 
| 88 | 14 |  |  |  |  | 12 | my @num = @_; | 
| 89 | 14 |  |  |  |  | 25 | my @first = bitonic_sort( 1, @num[0..(@num /2 -1)] ); | 
| 90 | 14 |  |  |  |  | 21 | my @second = bitonic_sort( 0, @num[(@num /2)..(@num -1)] ); | 
| 91 |  |  |  |  |  |  |  | 
| 92 | 14 |  |  |  |  | 17 | return _bitonic_merge( $up, $single_bit, @first, @second ); | 
| 93 |  |  |  |  |  |  | } | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | sub _bitonic_merge { | 
| 96 | 82 |  |  | 82 |  | 48 | my $up = shift; | 
| 97 | 82 |  |  |  |  | 43 | say '#### Merge: '.Dumper(@_) if DEBUG; | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 82 |  |  |  |  | 49 | my $single_bit = shift; | 
| 100 | 82 |  |  |  |  | 38 | say Dumper $single_bit if DEBUG; | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | # assume input @num is bitonic, and sorted list is returned | 
| 103 | 82 | 100 |  |  |  | 133 | return @_ if int @_ == 1; | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 34 | 50 |  |  |  | 38 | my $single_bit_2 = shift @_ if @_ % 2; | 
| 106 | 34 |  | 100 |  |  | 39 | $single_bit_2 //= 'NA'; | 
| 107 |  |  |  |  |  |  |  | 
| 108 | 34 |  |  |  |  | 28 | my @num = @_; | 
| 109 | 34 |  |  |  |  | 33 | @num = _bitonic_compare( $up, @num ); | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 34 |  |  |  |  | 55 | my @first = _bitonic_merge( $up, 'NA', @num[0..(@num /2 -1)] ); | 
| 112 | 34 |  |  |  |  | 51 | my @second = _bitonic_merge( $up, 'NA', @num[(@num /2)..(@num -1)] ); | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 34 |  |  |  |  | 31 | @num = (@first, @second); | 
| 115 | 34 | 100 |  |  |  | 50 | @num = _some_sorting_algorithm( $up, $single_bit, @first, @second ) if $single_bit ne 'NA'; | 
| 116 | 34 | 50 |  |  |  | 39 | @num = _some_sorting_algorithm( $up, $single_bit_2, @first, @second ) if $single_bit_2 ne 'NA'; | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 34 |  |  |  |  | 15 | say "#####\n# Merge Result\n#####\n".Dumper(@num)  if DEBUG; | 
| 119 |  |  |  |  |  |  |  | 
| 120 | 34 |  |  |  |  | 50 | return (@num); | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | sub _bitonic_compare { | 
| 124 | 34 |  |  | 34 |  | 24 | my $up = shift; | 
| 125 | 34 |  |  |  |  | 14 | say '#### Compare: '.Dumper(@_) if DEBUG; | 
| 126 | 34 |  |  |  |  | 30 | my @num = @_; | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 34 |  |  |  |  | 31 | my $dist = int @num /2; | 
| 129 |  |  |  |  |  |  | #~ | 
| 130 | 34 |  |  |  |  | 33 | for my $i (0..$dist-1) { | 
| 131 | 48 |  |  |  |  | 24 | say "i=$i, dist=$dist, $num[$i] > $num[$i+$dist]) == $up" if DEBUG; | 
| 132 | 48 | 100 |  |  |  | 69 | if ( ($num[$i] > $num[$i+$dist]) == $up ) { | 
| 133 | 26 |  |  |  |  | 14 | say "Swapping....." if DEBUG; | 
| 134 | 26 |  |  |  |  | 32 | ($num[$i], $num[$i+$dist]) = ($num[$i+$dist], $num[$i]);	#swap | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  | } | 
| 137 |  |  |  |  |  |  | #~ for my $i (0..(int @$first)) { | 
| 138 |  |  |  |  |  |  | #~ if ( ($first->[$i] > $second->[$i]) == $up ) { | 
| 139 |  |  |  |  |  |  | #~ ($first->[$i], $second->[$i]) = ($second->[$i], $first->[$i]);	#swap | 
| 140 |  |  |  |  |  |  | #~ } | 
| 141 |  |  |  |  |  |  | #~ } | 
| 142 |  |  |  |  |  |  |  | 
| 143 | 34 |  |  |  |  | 14 | say 'Compared result:'.Dumper(@num) if DEBUG; | 
| 144 | 34 |  |  |  |  | 43 | return @num; | 
| 145 |  |  |  |  |  |  | #~ return ($first, $second); | 
| 146 |  |  |  |  |  |  | } | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | sub _some_sorting_algorithm { | 
| 150 | 2 |  |  | 2 |  | 1 | my $up = shift; | 
| 151 | 2 |  |  |  |  | 2 | my $single_bit = shift; | 
| 152 | 2 |  |  |  |  | 14 | my @num = @_; | 
| 153 | 2 |  |  |  |  | 1 | my @num_new; | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 2 |  |  |  |  | 2 | say "_SOME_SORTING_ALGORITHM: INPUT: ".Dumper(@num) if DEBUG; | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 2 |  |  |  |  | 5 | while (my $curr = shift @num) { | 
| 158 | 9 |  |  |  |  | 8 | say "_SOME_SORTING_ALGORITHM: for: ".Dumper($curr, $single_bit, @num) if DEBUG; | 
| 159 | 9 | 100 | 66 |  |  | 23 | if ($up and $single_bit < $curr) { | 
|  |  | 50 | 33 |  |  |  |  | 
| 160 | 1 |  |  |  |  | 2 | push @num_new, $single_bit; | 
| 161 | 1 |  |  |  |  | 1 | push @num_new, $curr; | 
| 162 | 1 |  |  |  |  | 1 | say "Return earlier, up is ".($up or '0').':'.Dumper(@num_new, @num) if DEBUG; | 
| 163 | 1 |  |  |  |  | 4 | return (@num_new, @num); | 
| 164 |  |  |  |  |  |  | } elsif ($single_bit > $curr and not $up) { | 
| 165 | 0 |  |  |  |  | 0 | push @num_new, $single_bit; | 
| 166 | 0 |  |  |  |  | 0 | push @num_new, $curr; | 
| 167 | 0 |  |  |  |  | 0 | say "Return earlier, up is ".($up or '0').':'.Dumper(@num_new, @num) if DEBUG; | 
| 168 | 0 |  |  |  |  | 0 | return (@num_new, @num) | 
| 169 |  |  |  |  |  |  | } else { | 
| 170 | 8 |  |  |  |  | 11 | push @num_new, $curr; | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 | 1 |  |  |  |  | 2 | push @num_new, $single_bit; | 
| 175 | 1 |  |  |  |  | 1 | say "Return normal, ".Dumper(@num_new, @num) if DEBUG; | 
| 176 | 1 |  |  |  |  | 3 | return @num_new; | 
| 177 |  |  |  |  |  |  | } | 
| 178 |  |  |  |  |  |  |  | 
| 179 |  |  |  |  |  |  | =head1 AUTHOR | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | BlueT - Matthew Lien - 練喆明, C<<  >> | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | =head1 INSTALLATION | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | To install this module, run the following commands: | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | perl Makefile.PL | 
| 189 |  |  |  |  |  |  | make | 
| 190 |  |  |  |  |  |  | make test | 
| 191 |  |  |  |  |  |  | make install | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | Or install with cpanm | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | cpanm Algorithm::Bitonic::Sort | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | =head1 BUGS | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | Please report any bugs or feature requests to CPAN ( C, L ) or GitHub (L). | 
| 201 |  |  |  |  |  |  | I will be notified, and then you'll 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-2017 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 |