File Coverage

blib/lib/Rstats/Util.pm
Criterion Covered Total %
statement 92 94 97.8
branch 34 40 85.0
condition 18 21 85.7
subroutine 10 10 100.0
pod 0 2 0.0
total 154 167 92.2


line stmt bran cond sub pod time code
1             package Rstats::Util;
2 21     21   106 use strict;
  21         41  
  21         541  
3 21     21   100 use warnings;
  21         35  
  21         598  
4              
5             require Rstats;
6 21     21   106 use Scalar::Util ();
  21         36  
  21         346  
7 21     21   104 use B ();
  21         36  
  21         389  
8 21     21   98 use Carp 'croak';
  21         241  
  21         989  
9 21     21   21153 use Rstats::Func;
  21         78  
  21         2323  
10              
11             my $NAME
12             = eval { require Sub::Util; Sub::Util->can('set_subname') } || sub { $_[1] };
13              
14             sub monkey_patch {
15 329     329 0 964 my ($class, %patch) = @_;
16 21     21   119 no strict 'refs';
  21         45  
  21         885  
17 21     21   116 no warnings 'redefine';
  21         45  
  21         20498  
18 329         2990 *{"${class}::$_"} = $NAME->("${class}::$_", $patch{$_}) for keys %patch;
  329         2628  
19             }
20              
21             sub parse_index {
22 1048     1048 0 1600 my $r = shift;
23            
24 1048         1734 my ($x1, $drop, $_indexs) = @_;
25 1048         2314 my @_indexs = @$_indexs;
26            
27 1048         5229 my $x1_dim = $x1->dim_as_array->values;
28 1048         5302 my @indexs;
29             my @x2_dim;
30            
31 1048 100 100     4368 if (ref $_indexs[0] && Rstats::Func::is_array($r, $_indexs[0])
      66        
      66        
32             && Rstats::Func::is_logical($r, $_indexs[0]) && Rstats::Func::dim($r, $_indexs[0])->get_length > 1) {
33 1         2 my $x2 = $_indexs[0];
34 1         13 my $x2_dim_values = Rstats::Func::dim($r, $x2)->values;
35 1         9 my $x2_values = $x2->values;
36 1         3 my $poss = [];
37 1         5 for (my $i = 0; $i < @$x2_values; $i++) {
38 9 100       26 next unless $x2_values->[$i];
39 3         8 push @$poss, $i;
40             }
41            
42 1         7 return [$poss, []];
43             }
44             else {
45 1047         2826 for (my $i = 0; $i < @$x1_dim; $i++) {
46 3070         4361 my $_index = $_indexs[$i];
47              
48 3070 100       22079 my $index = defined $_index ? Rstats::Func::to_object($r, $_index) : Rstats::Func::NULL($r);
49 3070         16440 my $index_values = $index->values;
50 3070 100 100     30682 if (@$index_values && !Rstats::Func::is_character($r, $index) && !Rstats::Func::is_logical($r, $index)) {
      100        
51 3043         3902 my $minus_count = 0;
52 3043         5838 for my $index_value (@$index_values) {
53 3104 50       7250 if ($index_value == 0) {
54 0         0 croak "0 is invalid index";
55             }
56             else {
57 3104 100       8347 $minus_count++ if $index_value < 0;
58             }
59             }
60 3043 50 66     7497 croak "Can't min minus sign and plus sign"
61             if $minus_count > 0 && $minus_count != @$index_values;
62 3043 100       6713 $index->{_minus} = 1 if $minus_count > 0;
63             }
64            
65 3070 100       18400 if (!@{$index->values}) {
  3070 100       15569  
    100          
    100          
66 15         54 my $index_values_new = [1 .. $x1_dim->[$i]];
67 15         165 $index = Rstats::Func::c_integer($r, @$index_values_new);
68             }
69             elsif (Rstats::Func::is_character($r, $index)) {
70 2 50       22 if (Rstats::Func::is_vector($r, $x1)) {
    0          
71 2         6 my $index_new_values = [];
72 2         5 for my $name (@{$index->values}) {
  2         13  
73 4         7 my $i = 0;
74 4         8 my $value;
75 4         7 for my $x1_name (@{Rstats::Func::names($r, $x1)->values}) {
  4         51  
76 12 100       32 if ($name eq $x1_name) {
77 4         20 $value = $x1->values->[$i];
78 4         13 last;
79             }
80 8         13 $i++;
81             }
82 4 50       26 croak "Can't find name" unless defined $value;
83 4         12 push @$index_new_values, $value;
84             }
85 2         37 $indexs[$i] = Rstats::Func::c_integer($r, @$index_new_values);
86             }
87             elsif (Rstats::Func::is_matrix($r, $x1)) {
88            
89             }
90             else {
91 0         0 croak "Can't support name except vector and matrix";
92             }
93             }
94             elsif (Rstats::Func::is_logical($r, $index)) {
95 10         22 my $index_values_new = [];
96 10         20 for (my $i = 0; $i < @{$index->values}; $i++) {
  46         246  
97 36 100       146 push @$index_values_new, $i + 1 if $index_values->[$i];
98             }
99 10         128 $index = Rstats::Func::c_integer($r, @$index_values_new);
100             }
101             elsif ($index->{_minus}) {
102 10         20 my $index_value_new = [];
103            
104 10         35 for my $k (1 .. $x1_dim->[$i]) {
105 33 100       43 push @$index_value_new, $k unless grep { $_ == -$k } @{$index->values};
  62         261  
  33         162  
106             }
107 10         119 $index = Rstats::Func::c_integer($r, @$index_value_new);
108             }
109              
110 3070         21063 push @indexs, $index;
111              
112 3070         12692 my $count = Rstats::Func::get_length($r, $index);
113 3070 100 100     20472 push @x2_dim, $count unless $count == 1 && $drop;
114             }
115 1047 100       3287 @x2_dim = (1) unless @x2_dim;
116            
117 1047         1942 my $index_values = [map { $_->values } @indexs];
  3072         15841  
118 1047         9272 my $ords = cross_product($index_values);
119 1047         3162 my @poss = map { Rstats::Util::index_to_pos($_, $x1_dim) } @$ords;
  1198         6126  
120            
121 1047         7185 return [\@poss, \@x2_dim, \@indexs];
122             }
123             }
124              
125             =head1 NAME
126              
127             Rstats::Util - Utility class
128              
129             =head1 FUNCTION
130              
131             =head2 looks_like_na (xs)
132              
133             =head2 looks_like_logical (xs)
134              
135             =head2 looks_like_double (xs)
136              
137             =head2 looks_like_integer (xs)
138              
139             =head2 looks_like_complex (xs)
140              
141             =head2 index_to_pos (xs)
142              
143             =head2 pos_to_index (xs)
144              
145             =head2 cross_product (xs)
146              
147             1;