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   102 use strict;
  21         36  
  21         555  
3 21     21   102 use warnings;
  21         34  
  21         601  
4              
5             require Rstats;
6 21     21   105 use Scalar::Util ();
  21         35  
  21         314  
7 21     21   101 use B ();
  21         33  
  21         391  
8 21     21   97 use Carp 'croak';
  21         234  
  21         918  
9 21     21   20671 use Rstats::Func;
  21         89  
  21         2239  
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 909 my ($class, %patch) = @_;
16 21     21   114 no strict 'refs';
  21         39  
  21         866  
17 21     21   109 no warnings 'redefine';
  21         43  
  21         20661  
18 329         2950 *{"${class}::$_"} = $NAME->("${class}::$_", $patch{$_}) for keys %patch;
  329         2550  
19             }
20              
21             sub parse_index {
22 1048     1048 0 1506 my $r = shift;
23            
24 1048         1736 my ($x1, $drop, $_indexs) = @_;
25 1048         2317 my @_indexs = @$_indexs;
26            
27 1048         4974 my $x1_dim = $x1->dim_as_array->values;
28 1048         4979 my @indexs;
29             my @x2_dim;
30            
31 1048 100 100     4307 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         3 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         6 for (my $i = 0; $i < @$x2_values; $i++) {
38 9 100       25 next unless $x2_values->[$i];
39 3         7 push @$poss, $i;
40             }
41            
42 1         6 return [$poss, []];
43             }
44             else {
45 1047         2867 for (my $i = 0; $i < @$x1_dim; $i++) {
46 3070         4665 my $_index = $_indexs[$i];
47              
48 3070 100       21637 my $index = defined $_index ? Rstats::Func::to_object($r, $_index) : Rstats::Func::NULL($r);
49 3070         15600 my $index_values = $index->values;
50 3070 100 100     30143 if (@$index_values && !Rstats::Func::is_character($r, $index) && !Rstats::Func::is_logical($r, $index)) {
      100        
51 3043         3603 my $minus_count = 0;
52 3043         6397 for my $index_value (@$index_values) {
53 3104 50       6954 if ($index_value == 0) {
54 0         0 croak "0 is invalid index";
55             }
56             else {
57 3104 100       8548 $minus_count++ if $index_value < 0;
58             }
59             }
60 3043 50 66     8158 croak "Can't min minus sign and plus sign"
61             if $minus_count > 0 && $minus_count != @$index_values;
62 3043 100       7051 $index->{_minus} = 1 if $minus_count > 0;
63             }
64            
65 3070 100       18977 if (!@{$index->values}) {
  3070 100       15532  
    100          
    100          
66 15         50 my $index_values_new = [1 .. $x1_dim->[$i]];
67 15         164 $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         7 my $index_new_values = [];
72 2         4 for my $name (@{$index->values}) {
  2         11  
73 4         8 my $i = 0;
74 4         6 my $value;
75 4         6 for my $x1_name (@{Rstats::Func::names($r, $x1)->values}) {
  4         51  
76 12 100       29 if ($name eq $x1_name) {
77 4         22 $value = $x1->values->[$i];
78 4         13 last;
79             }
80 8         13 $i++;
81             }
82 4 50       27 croak "Can't find name" unless defined $value;
83 4         10 push @$index_new_values, $value;
84             }
85 2         39 $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         21 my $index_values_new = [];
96 10         19 for (my $i = 0; $i < @{$index->values}; $i++) {
  46         206  
97 36 100       132 push @$index_values_new, $i + 1 if $index_values->[$i];
98             }
99 10         121 $index = Rstats::Func::c_integer($r, @$index_values_new);
100             }
101             elsif ($index->{_minus}) {
102 10         17 my $index_value_new = [];
103            
104 10         33 for my $k (1 .. $x1_dim->[$i]) {
105 33 100       37 push @$index_value_new, $k unless grep { $_ == -$k } @{$index->values};
  62         244  
  33         175  
106             }
107 10         109 $index = Rstats::Func::c_integer($r, @$index_value_new);
108             }
109              
110 3070         21073 push @indexs, $index;
111              
112 3070         12744 my $count = Rstats::Func::get_length($r, $index);
113 3070 100 100     20892 push @x2_dim, $count unless $count == 1 && $drop;
114             }
115 1047 100       3385 @x2_dim = (1) unless @x2_dim;
116            
117 1047         1994 my $index_values = [map { $_->values } @indexs];
  3072         15070  
118 1047         9151 my $ords = cross_product($index_values);
119 1047         3139 my @poss = map { Rstats::Util::index_to_pos($_, $x1_dim) } @$ords;
  1198         5851  
120            
121 1047         7063 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;