File Coverage

blib/lib/List/Vectorize/lib/List.pl
Criterion Covered Total %
statement 301 311 96.7
branch 78 94 82.9
condition 23 29 79.3
subroutine 53 54 98.1
pod 34 34 100.0
total 489 522 93.6


line stmt bran cond sub pod time code
1            
2            
3             sub initial_array {
4            
5 18     18 1 80 check_prototype(@_, '$(\&|$|\@)?');
6            
7 18         30 my $size = shift;
8 18   100     75 my $value = shift || undef;
9 18 100       148 if(is_code_ref($value)) {
10 2         25 return sapply([1..$size], $value);
11             }
12             else {
13 16         44 return repeat($value, $size);
14             }
15             }
16            
17            
18             sub initial_matrix {
19            
20 6     6 1 42 check_prototype(@_, '$$(\&|$)?');
21            
22 6         11 my $n_row = shift;
23 6         10 my $n_col = shift;
24 6   100     20 my $value = shift || undef;
25            
26 6         15 my $mat = initial_array($n_row);
27 6 100       16 if(is_code_ref($value)) {
28 2     7   26 return sapply($mat, sub {sapply([1..$n_col], $value)});
  7         30  
29             }
30             else {
31 4     14   24 return sapply($mat, sub {repeat($value, $n_col)});
  14         28  
32             }
33             }
34            
35            
36             sub order {
37            
38 22     22 1 3229 check_prototype(@_, '\@(\&)?');
39            
40 22         35 my $array = shift;
41 22   100 154   374 my $function = shift || sub {$_[0] <=> $_[1]};
  154         282  
42            
43 22         44 my $order = [];
44 22         135 @$order = sort { $function->($array->[$a], $array->[$b]) } 0..$#$array;
  204         392  
45 22         133 return $order;
46             }
47            
48             sub rank {
49            
50 13     13 1 3250 check_prototype(@_, '\@(\&)?');
51            
52 13         39 my $order = order(@_);
53 13         23 my $array = shift(@_);
54 13         21 my $rank = [];
55 13         20 my $same = [];
56 13         20 my $index = [];
57 13         36 for($i = 0; $i < len($order); $i ++) {
58            
59 82 100 100     363 if($i != 0 and ($array->[$order->[$i]] != $array->[$order->[$i - 1]])) {
60 63         102 foreach (@$index) {
61 69         162 $rank->[$_] = mean($same);
62             }
63 63         110 $same = [];
64 63         109 $index = [];
65             }
66            
67 82         162 push(@$same, $i+1);
68 82         213 push(@$index, $order->[$i]);
69            
70             }
71            
72 13         34 foreach (@$index) {
73 13         39 $rank->[$_] = mean($same);
74             }
75 13         69 return $rank;
76             }
77            
78            
79             sub sort_array {
80            
81 36     36 1 146 check_prototype(@_, '\@(\&)?');
82            
83 36         65 my $array = shift;
84 36   100 612   220 my $function = shift || sub {$_[0] <=> $_[1]};
  612         1124  
85            
86 36         150 return [sort {$function->($a, $b)} @$array];
  649         841  
87             }
88            
89            
90             sub reverse_array {
91            
92 2     2 1 412 check_prototype(@_, '\@');
93            
94 2         5 my $array = shift;
95            
96 2         60 return [reverse(@$array)];
97             }
98            
99            
100             sub repeat {
101            
102 58     58 1 2327 check_prototype(@_, '($|\$|\@|\%)$$?');
103            
104 58         168 my $value = shift;
105 58         80 my $size = shift;
106 58         82 my $need_copy = shift;
107 58 100       132 $need_copy = defined($need_copy) ? $need_copy : 1;
108            
109 58         95 my $array = [];
110 58 100       210 if(is_ref_ref(\$value)) {
111 14         52 for(my $i = 0; $i < $size; $i ++) {
112 85 100       149 if($need_copy) {
113 77         159 push(@$array, copy($value));
114             }
115             else {
116 8         21 push(@$array, $value);
117             }
118             }
119             }
120             else {
121 44         133 for(my $i = 0; $i < $size; $i ++) {
122 259         586 push(@$array, $value);
123             }
124             }
125 58         409 return $array;
126             }
127            
128             sub rep {
129            
130 9     9 1 1462 check_prototype(@_, '($|\$|\@|\%)$$?');
131            
132 9         31 return repeat(@_);
133             }
134            
135            
136             sub copy {
137            
138 82     82 1 2781 check_prototype(@_, '(\$|\@|\%)');
139            
140 82         125 my $value = shift;
141 82         88 my $copy;
142 82 50       215 if(is_ref_ref(\$value)) {
143 82         222 my $s = Dumper($value);
144 82         5993 $s =~s/^\$\w+/\$copy/ms;
145 82         9331 eval($s);
146 82 50       337 if($@) {
147 0         0 croak "ERROR: $@\n";
148             }
149             }
150             else {
151 0         0 croak "ERROR: must copy a reference\n";
152             }
153 82         451 return $copy;
154             }
155            
156            
157             sub paste {
158            
159 19     19 1 110 check_prototype(@_, '(\@|$)+');
160            
161 19         74 my $sep;
162 19 100       101 if(is_scalar_ref(\$_[$#_])) {
163 16         33 $sep = pop;
164             }
165             else {
166 3         9 $sep = "|";
167             }
168 19         48 my @args = @_;
169            
170 19     128   150 return mapply(@args, sub{join $sep, @_});
  128         2669  
171             }
172            
173            
174             sub seq {
175            
176 8     8 1 53 check_prototype(@_, '$$$?');
177            
178 8         14 my $from = shift;
179 8         17 my $to = shift;
180 8   100     48 my $by = shift || 1;
181            
182 8         17 my $seq = [];
183 8 100       21 if($from < $to) {
184 6         24 for(my $i = $from; $i <= $to; $i += $by) {
185 49         116 push(@$seq, $i);
186             }
187             }
188             else {
189 2         10 for(my $i = $from; $i >= $to; $i -= $by) {
190 12         26 push(@$seq, $i);
191             }
192             }
193 8         105 return $seq;
194             }
195            
196            
197             sub c {
198            
199 8     8 1 924 check_prototype(@_, '(\@|$|\$)+');
200            
201 8         23 my @array_refs = @_;
202 8         17 my $c = [];
203 8         20 foreach (@array_refs) {
204 19 100       58 if(is_array_ref($_)) {
205 8         24 push(@$c, @$_);
206             }
207             else {
208 11         32 push(@$c, $_);
209             }
210             }
211 8         66 return $c;
212             }
213            
214            
215             sub test {
216            
217 109     109 1 292 check_prototype(@_, '\@\&');
218            
219 109         188 my $array = shift;
220 109         127 my $function = shift;
221            
222 109 100   454   4248 return sapply($array, sub {$function->($_[0]) ? 1: 0});
  454         860  
223             }
224            
225            
226             sub unique {
227            
228 41     41 1 1193 check_prototype(@_, '\@');
229            
230 41         69 my $array = shift;
231 41         94 my $hash = {};
232 41         82 return [grep {not $hash->{$_} ++} @$array];
  170         730  
233             }
234            
235            
236             sub subset {
237            
238 44     44 1 170 check_prototype(@_, '\@(\@|\&)');
239            
240 44         89 my $array = shift;
241 44         59 my $index = shift;
242            
243 44 100       153 if(is_code_ref($index)) {
244 2         3 my $function = $index;
245 2         9 return subset($array, which(test($array, $function)));
246             }
247             else {
248 42         81 my $subset = [];
249            
250 42         145 my $max_index = max($index);
251 42         137 my $min_index = min($index);
252 42 50       170 if($max_index * $min_index < 0) {
253 0         0 croak "ERROR: index should be in the same sign\n";
254             }
255 42 100       97 if($min_index >= 0) {
    50          
256 41         132 for(my $i = 0; $i < len($index); $i ++) {
257 209         564 push(@$subset, $array->[$index->[$i]]);
258             }
259             }
260             elsif($max_index < 0) {
261 1     3   6 return subset($array, setdiff(seq(0, $#$array), sapply($index, sub {-$_[0]-1})));
  3         9  
262             }
263 41         213 return $subset;
264             }
265             }
266            
267            
268             sub subset_value {
269            
270 10     10 1 2124 check_prototype(@_, '\@(\@|\&)(\@|$)');
271            
272 10         20 my $array = shift;
273 10         17 my $index = shift;
274 10         15 my $value = shift;
275            
276 10 100       33 if(is_code_ref($index)) {
277 3         6 my $function = $index;
278 3         10 return subset_value($array, which(test($array, $function)), $value);
279             }
280             else {
281 7 100       60 if(is_scalar_ref(\$value)) {
282 4         15 $value = repeat($value, len($index));
283             }
284 7 50       20 if(len($value) != len($index)) {
285 0         0 croak "ERROR: length of values must be equal to that of subset!\n";
286             }
287            
288 7         25 my $max_index = max($index);
289 7         25 my $min_index = min($index);
290 7 50       24 if($max_index * $min_index < 0) {
291 0         0 croak "ERROR: index should be in the same sign\n";
292             }
293 7 50       20 if($min_index >= 0) {
    0          
294 7         21 for(my $i = 0; $i < len($index); $i ++) {
295 31         85 $array->[$index->[$i]] = $value->[$i];
296             }
297 7         74 return $array;
298             }
299             elsif($max_index < 0) {
300 0     0   0 return subset($array, complement(sapply($index, sub {-$_[0]-1}), seq(0, $#$index)), $value);
  0         0  
301             }
302             }
303             }
304            
305            
306             # usage: del_array_item( [ARRAY REF])
307             # return: ARRAY REF
308             sub del_array_item {
309            
310 40     40 1 2881 check_prototype(@_, '\@($|\@)');
311            
312 40         65 my $array = shift;
313 40         56 my $del_i = shift;
314            
315 40 100       109 if(is_array_ref($del_i)) {
316 3         31 my $remain = setdiff([0..$#$array], $del_i);
317 3         18 @$array = @$array[@$remain];
318             }
319             else {
320 37         217 @$array = (@$array[0..($del_i-1)], @$array[($del_i+1)..$#$array]);
321             }
322 40         162 return $array;
323             }
324            
325            
326             sub which {
327            
328 25     25 1 80 check_prototype(@_, '\@');
329            
330 25         38 my $logical = shift;
331            
332 25         35 my $which = [];
333 25         71 @$which = grep {$logical->[$_]} 0..$#$logical;
  244         328  
334 25         91 return $which;
335             }
336            
337             sub all {
338            
339 81     81 1 1316 check_prototype(@_, '\@');
340            
341 81         255 my $l = shift;
342 81 100       377 if(len($l)) {
343 80 100   187   344 return sum(test($l, sub {$_[0]})) == len($l) ? 1 : 0;
  187         577  
344             } else {
345 1         5 return 0;
346             }
347             }
348            
349             sub any {
350            
351 4     4 1 17 check_prototype(@_, '\@');
352            
353 4         7 my $l = shift;
354 4 100   14   21 return sum(test($l, sub {$_[0]})) ? 1 : 0;
  14         41  
355             }
356            
357            
358             sub dim {
359            
360 39     39 1 1435 check_prototype(@_, '\@');
361            
362 39         71 my $mat = shift;
363 39 100   88   220 if(all(sapply($mat, sub {is_array_ref($_[0])}))) {
  88         264  
364            
365 38         96 my $nc = len($mat->[0]);
366 38 100   85   196 if(all(sapply($mat, sub {len($_[0]) == $nc}))) {
  85         154  
367 37         88 return (len($mat), $nc);
368             }
369             }
370            
371 2         27 return undef;
372            
373             }
374            
375            
376             sub t {
377            
378 2     2 1 25 check_prototype(@_, '\@');
379            
380 2         3 my $matrix = shift;
381            
382 2         10 my ($n_row, $n_col) = dim($matrix);
383            
384 2         28 my $t = [[]];
385 2         11 for(my $i = 0; $i < $n_row; $i ++) {
386 4         20 for(my $j = 0; $j < $n_col; $j ++) {
387 10         38 $t->[$j]->[$i] = $matrix->[$i]->[$j];
388             }
389             }
390 2         13 return $t;
391             }
392            
393             sub matrix_prod {
394            
395 10     10 1 2453 check_prototype(@_, '(\@)+');
396            
397 10 100       35 if(scalar(@_) > 2) {
398 2         5 my $first = shift(@_);
399 2         4 my $second = shift(@_);
400 2         15 return matrix_prod(matrix_prod($first, $second), @_);
401             }
402            
403 8         11 my $mat1 = shift;
404 8         12 my $mat2 = shift;
405            
406 8         20 my ($I, $J1) = dim($mat1);
407 8         88 my ($J2, $K) = dim($mat2);
408            
409 8 50       85 if($J1 == $J2) {
410 8         14 my $J = $J1;
411 8         10 my $product;
412 8         27 for(my $i = 0; $i < $I; $i ++) {
413 17         39 for(my $k = 0; $k < $K; $k ++) {
414 37         41 my $sum = 0;
415 37         111 for(my $j = 0; $j < $J; $j ++) {
416 78         190 $sum += $mat1->[$i]->[$j]*$mat2->[$j]->[$k];
417             }
418 37         117 $product->[$i]->[$k] = $sum;
419             }
420             }
421 8         49 return $product;
422             }
423             else {
424 0         0 croak "ERROR: columns in the first matrix must be equal to the rows in the second matrix";
425             }
426             }
427            
428            
429             sub is_array_identical {
430            
431 7     7 1 43 check_prototype(@_, '\@\@');
432            
433 7         15 my $array1 = shift;
434 7         10 my $array2 = shift;
435            
436 7 100       23 if(len($array1) != len($array2)) {
437 1         4 return 0;
438             }
439             else {
440 6 50   13   62 if(sum(mapply($array1, $array2, sub{abs($_[0]-$_[1]) < EPS})) == len($array1)) {
  13         55  
441 6         6247 return 1;
442             }
443             else {
444 0         0 return 0;
445             }
446             }
447             }
448            
449            
450             sub is_matrix_identical {
451            
452 4     4 1 676 check_prototype(@_, '\@\@');
453            
454 4         8 my $matrix1 = shift;
455 4         5 my $matrix2 = shift;
456            
457 4         13 my ($d1, $d2) = dim($matrix1);
458 4         53 my ($d3, $d4) = dim($matrix2);
459            
460 4 100 33     85 if(!defined($d1) or !defined($d2) or !defined($d3) or !defined($d4)) {
      33        
      66        
461 1         4 return 0;
462             }
463            
464 3 100 66     22 unless($d1 == $d3 and $d2 == $d4) {
465 1         5 return 0;
466             }
467            
468 2     4   18 my $v = mapply($matrix1, $matrix2, sub {is_array_identical($_[0], $_[1])});
  4         14  
469 2 50       12 if(sum($v) == len($matrix1)) {
470 2         18 return 1;
471             }
472             else {
473 0         0 return 0;
474             }
475             }
476            
477            
478             sub outer {
479            
480 4     4 1 521 check_prototype(@_, '\@\@(\&)?');
481            
482 4         8 my $vector1 = shift;
483 4         8 my $vector2 = shift;
484 4   100 20   27 my $function = shift || sub {$_[0]*$_[1]};
  20         102  
485            
486 4         7 my $outer = [];
487 4         15 for(my $i = 0; $i < len($vector1); $i ++) {
488 12         30 for(my $j = 0; $j < len($vector2); $j ++) {
489 40         87 $outer->[$i]->[$j] = $function->($vector1->[$i], $vector2->[$j]);
490             }
491             }
492            
493 4         30 return $outer;
494             }
495            
496             sub inner {
497            
498 5     5 1 2898 check_prototype(@_, '\@\@(\&)?');
499            
500 5         6 my $vector1 = shift;
501 5         46 my $vector2 = shift;
502 5   100 8   31 my $function = shift || sub {$_[0]*$_[1]};
  8         21  
503            
504 5         8 my $inner = [];
505 5         24 $inner = sum(mapply($vector1, $vector2, $function));
506            
507 5         29 return $inner;
508             }
509            
510            
511             sub len {
512            
513 4578     4578 1 7011 my $array = shift;
514 4578 100       13846 if(is_array_ref($array)) {
    100          
    100          
515 4571         15458 return scalar(@$array);
516             }
517             elsif(is_hash_ref($array)) {
518 3         17 return scalar(keys %$array);
519             }
520             elsif(!defined($array)) {
521 2         13 return 0;
522             }
523             else {
524 2         11 return 1;
525             }
526             }
527            
528             sub match {
529            
530 2     2 1 44 check_prototype(@_, '\@\@');
531            
532 2         3 my $array1 = shift;
533 2         4 my $array2 = shift;
534            
535 2         5 my $h = {};
536 2         6 foreach (@$array2) {
537 12         28 $h->{$_} = 1;
538             }
539            
540 2         6 my $index = [];
541 2         7 for(my $i = 0; $i < len($array1); $i ++) {
542 14 100       52 push(@$index, $i) if($h->{$array1->[$i]});
543             }
544 2         12 return $index;
545             }
546            
547             sub is_empty {
548 21     21 1 71 !len($_[0]) + 0;
549             }
550            
551             sub plus {
552            
553 7     7 1 45 check_prototype(@_, '(\@|$)+');
554            
555 7 50       29 croak "ERROR: at least two array lists is required" if scalar(@_) < 2;
556            
557 7         12 my $array1 = shift;
558 7         10 my $array2 = shift;
559 7         16 my @arrays = @_;
560            
561 7     70   45 my $res = mapply($array1, $array2, sub {$_[0] + $_[1]});
  70         161  
562 7 100       46 if(scalar(@arrays) == 0) {
563 5         29 return $res;
564             }
565             else {
566 2         15 return plus($res, @arrays);
567             }
568             }
569            
570             sub minus {
571            
572 7     7 1 45 check_prototype(@_, '(\@|$)+');
573            
574 7 50       30 croak "ERROR: at least two array lists is required" if scalar(@_) < 2;
575            
576 7         12 my $array1 = shift;
577 7         12 my $array2 = shift;
578 7         17 my @arrays = @_;
579            
580 7     70   41 my $res = mapply($array1, $array2, sub {$_[0] - $_[1]});
  70         182  
581 7 100       33 if(scalar(@arrays) == 0) {
582 5         26 return $res;
583             }
584             else {
585 2         15 return minus($res, @arrays);
586             }
587             }
588            
589             sub divide {
590            
591 4     4 1 15 check_prototype(@_, '(\@|$)+');
592            
593 4 50       17 croak "ERROR: at least two array lists is required" if scalar(@_) < 2;
594            
595 4         8 my $array1 = shift;
596 4         5 my $array2 = shift;
597 4         11 my @arrays = @_;
598            
599 4     40   24 my $res = mapply($array1, $array2, sub {$_[0] / $_[1]});
  40         103  
600 4 100       17 if(scalar(@arrays) == 0) {
601 3         22 return $res;
602             }
603             else {
604 1         7 return divide($res, @arrays);
605             }
606             }
607            
608             sub multiply {
609            
610 7     7 1 43 check_prototype(@_, '(\@|$)+');
611            
612 7 50       28 croak "ERROR: at least two array lists is required" if scalar(@_) < 2;
613            
614 7         13 my $array1 = shift;
615 7         12 my $array2 = shift;
616 7         12 my @arrays = @_;
617            
618 7     70   43 my $res = mapply($array1, $array2, sub {$_[0] * $_[1]});
  70         170  
619 7 100       33 if(scalar(@arrays) == 0) {
620 5         29 return $res;
621             }
622             else {
623 2         18 return multiply($res, @arrays);
624             }
625             }
626            
627            
628            
629             1;