File Coverage

blib/lib/Rstats/Array.pm
Criterion Covered Total %
statement 696 754 92.3
branch 339 418 81.1
condition 37 53 69.8
subroutine 74 76 97.3
pod 0 47 0.0
total 1146 1348 85.0


line stmt bran cond sub pod time code
1             package Rstats::Array;
2 8     8   42 use Object::Simple -base;
  8         13  
  8         40  
3              
4 8     8   692 use Carp 'croak', 'carp';
  8         10  
  8         286  
5 8     8   32 use List::Util;
  8         14  
  8         282  
6 8     8   30 use Rstats;
  8         10  
  8         247  
7 8     8   202 use B;
  8         33  
  8         266  
8 8     8   33 use Rstats::Util;
  8         24  
  8         2313  
9              
10             our @CARP_NOT = ('Rstats');
11              
12             my %types_h = map { $_ => 1 } qw/character complex numeric double integer logical/;
13              
14             use overload
15             bool => \&bool,
16 7     7   35 '+' => sub { shift->_operation('add', @_) },
17 5     5   27 '-' => sub { shift->_operation('subtract', @_) },
18 3     3   14 '*' => sub { shift->_operation('multiply', @_) },
19 4     4   21 '/' => sub { shift->_operation('divide', @_) },
20 3     3   16 '%' => sub { shift->_operation('remainder', @_) },
21             'neg' => \&negation,
22 4     4   18 '**' => sub { shift->_operation('raise', @_) },
23 4     4   31 '<' => sub { shift->_operation('less_than', @_) },
24 4     4   21 '<=' => sub { shift->_operation('less_than_or_equal', @_) },
25 4     4   20 '>' => sub { shift->_operation('more_than', @_) },
26 4     4   22 '>=' => sub { shift->_operation('more_than_or_equal', @_) },
27 4     4   20 '==' => sub { shift->_operation('equal', @_) },
28 4     4   20 '!=' => sub { shift->_operation('not_equal', @_) },
29 8         266 '""' => \&to_string,
30 8     8   44 fallback => 1;
  8         10  
31              
32             has 'elements';
33              
34             sub values {
35 8853     8853 0 12714 my $self = shift;
36            
37 8853 100       11715 if (@_) {
38 1         2 my @elements = map { Rstats::Util::element($_) } @{$_[0]};
  24         132  
  1         3  
39 1         8 $self->{elements} = \@elements;
40             }
41             else {
42 8852         8776 my @values = map { Rstats::Util::value($_) } @{$self->elements};
  8659         35854  
  8852         117720  
43            
44 8852         45711 return \@values;
45             }
46             }
47              
48 82     82 0 1003 sub value { Rstats::Util::value(shift->element(@_)) }
49              
50             sub typeof {
51 5     5 0 895 my $self = shift;
52            
53 5         8 my $type = $self->{type};
54 5 50       9 my $a1_elements = defined $type ? $type : "NULL";
55 5         12 my $a1 = Rstats::Array->c([$a1_elements]);
56            
57 5         12 return $a1;
58             }
59              
60             sub mode {
61 4501     4501 0 5179 my $self = shift;
62            
63 4501 100       5888 if (@_) {
64 4491         4918 my $type = $_[0];
65             croak qq/Error in eval(expr, envir, enclos) : could not find function "as_$type"/
66 4491 50       6811 unless $types_h{$type};
67            
68 4491 100       5857 if ($type eq 'numeric') {
69 1         1 $self->{type} = 'double';
70             }
71             else {
72 4490         6675 $self->{type} = $type;
73             }
74            
75 4491         6315 return $self;
76             }
77             else {
78 10         15 my $type = $self->{type};
79 10         10 my $mode;
80 10 50       25 if (defined $type) {
81 10 100 100     35 if ($type eq 'integer' || $type eq 'double') {
82 6         7 $mode = 'numeric';
83             }
84             else {
85 4         5 $mode = $type;
86             }
87             }
88             else {
89 0         0 croak qq/could not find function "as_$type"/;
90             }
91              
92 10         22 return Rstats::Array->c([$mode]);
93             }
94             }
95              
96             sub bool {
97 4143     4143 0 20849 my $self = shift;
98            
99 4143         5054 my $length = @{$self->elements};
  4143         52088  
100 4143 100       20879 if ($length == 0) {
    100          
101 1         86 croak 'Error in if (a) { : argument is of length zero';
102             }
103             elsif ($length > 1) {
104 3         398 carp 'In if (a) { : the condition has length > 1 and only the first element will be used';
105             }
106            
107 4142         6812 my $element = $self->element;
108            
109 4142         21446 return Rstats::Util::bool($element);
110             }
111              
112             sub clone_without_elements {
113 157     157 0 234 my ($self, %opt) = @_;
114            
115 157         289 my $array = Rstats::Array->new;
116 157         723 $array->{type} = $self->{type};
117 157 100       170 $array->{names} = [@{$self->{names} || []}];
  157         493  
118 157 100       201 $array->{rownames} = [@{$self->{rownames} || []}];
  157         391  
119 157 100       178 $array->{colnames} = [@{$self->{colnames} || []}];
  157         371  
120 157 100       174 $array->{dim} = [@{$self->{dim} || []}];
  157         357  
121 157 50       276 $array->{elements} = $opt{elements} ? $opt{elements} : [];
122            
123 157         266 return $array;
124             }
125              
126             sub row {
127 1     1 0 2 my $self = shift;
128            
129 1         4 my $nrow = $self->nrow->value;
130 1         10 my $ncol = $self->ncol->value;
131            
132 1         10 my @values = (1 .. $nrow) x $ncol;
133            
134 1         5 return Rstats::Array->array(\@values, [$nrow, $ncol]);
135             }
136              
137             sub col {
138 1     1 0 2 my $self = shift;
139            
140 1         2 my $nrow = $self->nrow->value;
141 1         9 my $ncol = $self->ncol->value;
142            
143 1         7 my @values;
144 1         4 for my $col (1 .. $ncol) {
145 4         19 push @values, ($col) x $nrow;
146             }
147            
148 1         4 return Rstats::Array->array(\@values, [$nrow, $ncol]);
149             }
150              
151             sub nrow {
152 3     3 0 4 my $self = shift;
153            
154 3         7 return Rstats::Array->array($self->dim->values->[0]);
155             }
156              
157             sub ncol {
158 3     3 0 6 my $self = shift;
159            
160 3         6 return Rstats::Array->array($self->dim->values->[1]);
161             }
162              
163             sub names {
164 17     17 0 34 my $self = shift;
165            
166 17 100       38 if (@_) {
167 4         7 my $_names = shift;
168 4         5 my $names;
169 4 50       36 if (!defined $_names) {
    100          
    50          
170 0         0 $names = [];
171             }
172             elsif (ref $_names eq 'ARRAY') {
173 2         6 $names = $_names;
174             }
175             elsif (ref $_names eq 'Rstats::Array') {
176 2         43 $names = $_names->elements;
177             }
178             else {
179 0         0 $names = [$_names];
180             }
181            
182 4         22 my $duplication = {};
183 4         41 for my $name (@$names) {
184             croak "Don't use same name in names arguments"
185 14 50       45 if $duplication->{$name};
186 14         41 $duplication->{$name}++;
187             }
188 4         19 $self->{names} = $names;
189             }
190             else {
191 13 100       33 $self->{names} = [] unless exists $self->{names};
192 13         30 return Rstats::Array->array($self->{names});
193             }
194             }
195              
196             sub colnames {
197 11     11 0 18 my $self = shift;
198            
199 11 100       22 if (@_) {
200 3         3 my $_colnames = shift;
201 3         6 my $colnames;
202 3 50       10 if (!defined $_colnames) {
    50          
    0          
203 0         0 $colnames = [];
204             }
205             elsif (ref $_colnames eq 'ARRAY') {
206 3         5 $colnames = $_colnames;
207             }
208             elsif (ref $_colnames eq 'Rstats::Array') {
209 0         0 $colnames = $_colnames->elements;
210             }
211             else {
212 0         0 $colnames = [$_colnames];
213             }
214            
215 3         5 my $duplication = {};
216 3         6 for my $name (@$colnames) {
217             croak "Don't use same name in colnames arguments"
218 8 50       16 if $duplication->{$name};
219 8         13 $duplication->{$name}++;
220             }
221 3         10 $self->{colnames} = $colnames;
222             }
223             else {
224 8 100       23 $self->{colnames} = [] unless exists $self->{colnames};
225 8         20 return Rstats::Array->array($self->{colnames});
226             }
227             }
228              
229             sub rownames {
230 11     11 0 26 my $self = shift;
231            
232 11 100       23 if (@_) {
233 3         6 my $_rownames = shift;
234 3         6 my $rownames;
235 3 50       13 if (!defined $_rownames) {
    50          
    0          
236 0         0 $rownames = [];
237             }
238             elsif (ref $_rownames eq 'ARRAY') {
239 3         6 $rownames = $_rownames;
240             }
241             elsif (ref $_rownames eq 'Rstats::Array') {
242 0         0 $rownames = $_rownames->elements;
243             }
244             else {
245 0         0 $rownames = [$_rownames];
246             }
247            
248 3         7 my $duplication = {};
249 3         6 for my $name (@$rownames) {
250             croak "Don't use same name in rownames arguments"
251 9 50       19 if $duplication->{$name};
252 9         17 $duplication->{$name}++;
253             }
254 3         12 $self->{rownames} = $rownames;
255             }
256             else {
257 8 100       22 $self->{rownames} = [] unless exists $self->{rownames};
258 8         46 return Rstats::Array->array($self->{rownames});
259             }
260             }
261              
262             sub dim {
263 5919     5919 0 6093 my $self = shift;
264            
265 5919 100       8115 if (@_) {
266 554         584 my $a1 = $_[0];
267 554 50       1053 if (ref $a1 eq 'Rstats::Array') {
    50          
    0          
268 0         0 $self->{dim} = $a1->elements;
269             }
270             elsif (ref $a1 eq 'ARRAY') {
271 554         967 $self->{dim} = $a1;
272             }
273             elsif(!ref $a1) {
274 0         0 $self->{dim} = [$a1];
275             }
276             else {
277 0         0 croak "Invalid elements is passed to dim argument";
278             }
279             }
280             else {
281 5365 100       9126 $self->{dim} = [] unless exists $self->{dim};
282 5365         10260 return Rstats::Array->new(elements => $self->{dim});
283             }
284             }
285              
286             sub length {
287 195     195 0 210 my $self = shift;
288            
289 195         184 my $length = @{$self->elements};
  195         2311  
290            
291 195         1000 return $length;
292             }
293              
294             sub seq {
295 97     97 0 161 my $self = shift;
296            
297             # Option
298 97 100       287 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
299            
300             # Along
301 97         186 my $along = $opt->{along};
302            
303 97 100       172 if ($along) {
304 1         8 my $length = $along->length;
305 1         6 return $self->seq([1,$length]);
306             }
307             else {
308 96         123 my $from_to = shift;
309 96         142 my $from;
310             my $to;
311 96 100       245 if (ref $from_to eq 'ARRAY') {
    100          
312 7         9 $from = $from_to->[0];
313 7         7 $to = $from_to->[1];
314             }
315             elsif (defined $from_to) {
316 4         4 $from = 1;
317 4         5 $to = $from_to;
318             }
319            
320             # From
321 96 100       237 $from = $opt->{from} unless defined $from;
322 96 50       185 croak "seq function need from option" unless defined $from;
323            
324             # To
325 96 100       195 $to = $opt->{to} unless defined $to;
326              
327             # Length
328 96         166 my $length = $opt->{length};
329            
330             # By
331 96         124 my $by = $opt->{by};
332            
333 96 50 66     247 if (defined $length && defined $by) {
334 0         0 croak "Can't use by option and length option as same time";
335             }
336            
337 96 100       189 unless (defined $by) {
338 93 100       232 if ($to >= $from) {
339 92         131 $by = 1;
340             }
341             else {
342 1         2 $by = -1;
343             }
344             }
345 96 50       199 croak "by option should be except for 0" if $by == 0;
346            
347 96 50       163 $to = $from unless defined $to;
348            
349 96 100 66     225 if (defined $length && $from ne $to) {
350 1         4 $by = ($to - $from) / ($length - 1);
351             }
352            
353 96         147 my $elements = [];
354 96 100       266 if ($to == $from) {
    100          
355 2         41 $elements->[0] = $to;
356             }
357             elsif ($to > $from) {
358 92 50       168 if ($by < 0) {
359 0         0 croak "by option is invalid number(seq function)";
360             }
361            
362 92         135 my $element = $from;
363 92         159 while ($element <= $to) {
364 1757         2097 push @$elements, $element;
365 1757         2328 $element += $by;
366             }
367             }
368             else {
369 2 50       6 if ($by > 0) {
370 0         0 croak "by option is invalid number(seq function)";
371             }
372            
373 2         3 my $element = $from;
374 2         4 while ($element >= $to) {
375 8         9 push @$elements, $element;
376 8         12 $element += $by;
377             }
378             }
379            
380 96         223 return $self->c($elements);
381             }
382             }
383              
384             sub C {
385 84     84 0 206 my ($self, $seq_str) = @_;
386              
387 84         139 my $by;
388             my $mode;
389 84 100       288 if ($seq_str =~ s/^(.+)\*//) {
390 1         3 $by = $1;
391             }
392            
393 84         138 my $from;
394             my $to;
395 84 50       468 if ($seq_str =~ /([^\:]+)(?:\:(.+))?/) {
396 84         205 $from = $1;
397 84         158 $to = $2;
398 84 50       187 $to = $from unless defined $to;
399             }
400            
401 84         386 my $vector = $self->seq({from => $from, to => $to, by => $by});
402            
403 84         446 return $vector;
404             }
405              
406             sub c {
407 4435     4435 0 6451 my ($self, $a1) = @_;
408            
409             # Array
410 4435         7796 my $array = Rstats::Array->new;
411            
412             # Value
413 4435         18806 my $elements = [];
414 4435 50       6248 if (defined $a1) {
415 4435 100       6915 if (ref $a1 eq 'ARRAY') {
    100          
416 3654         5180 for my $a (@$a1) {
417 7669 100       12474 if (ref $a eq 'ARRAY') {
    100          
418 10         22 push @$elements, @$a;
419             }
420             elsif (ref $a eq 'Rstats::Array') {
421 21         30 push @$elements, @{$a->elements};
  21         275  
422             }
423             else {
424 7638         11460 push @$elements, $a;
425             }
426             }
427             }
428             elsif (ref $a1 eq 'Rstats::Array') {
429 59         905 $elements = $a1->elements;
430             }
431             else {
432 722         1257 $elements = [$a1];
433             }
434             }
435             else {
436 0         0 croak "Invalid first argument";
437             }
438            
439             # Check elements
440 4435         5625 my $mode_h = {};
441 4435         5869 for my $element (@$elements) {
442 9824 100       15463 next if Rstats::Util::is_na($element);
443            
444 9817 50       19947 if (!defined $element) {
    100          
    100          
    100          
    100          
    100          
    100          
445 0         0 croak "undef is invalid element";
446             }
447             elsif (Rstats::Util::is_character($element)) {
448 16         25 $mode_h->{character}++;
449             }
450             elsif (Rstats::Util::is_complex($element)) {
451 31         61 $mode_h->{complex}++;
452             }
453             elsif (Rstats::Util::is_double($element)) {
454 3162         5110 $mode_h->{double}++;
455             }
456             elsif (Rstats::Util::is_integer($element)) {
457 2         27 $element = Rstats::Util::double($element->value);
458 2         11 $mode_h->{double}++;
459             }
460             elsif (Rstats::Util::is_logical($element)) {
461 2876         6046 $mode_h->{logical}++;
462             }
463             elsif (Rstats::Util::is_perl_number($element)) {
464 3618         6072 $element = Rstats::Util::double($element);
465 3618         21221 $mode_h->{double}++;
466             }
467             else {
468 112         278 $element = Rstats::Util::character("$element");
469 112         687 $mode_h->{character}++;
470             }
471             }
472              
473             # Upgrade elements and type
474 4435         10490 my @modes = keys %$mode_h;
475 4435 100       6880 if (@modes > 1) {
476 1 50       5 if ($mode_h->{character}) {
    50          
    0          
    0          
477 0         0 my $a1 = Rstats::Array->new(elements => $elements)->as_character;
478 0         0 $elements = $a1->elements;
479 0         0 $array->mode('character');
480             }
481             elsif ($mode_h->{complex}) {
482 1         4 my $a1 = Rstats::Array->new(elements => $elements)->as_complex;
483 1         15 $elements = $a1->elements;
484 1         6 $array->mode('complex');
485             }
486             elsif ($mode_h->{double}) {
487 0         0 my $a1 = Rstats::Array->new(elements => $elements)->as_double;
488 0         0 $elements = $a1->elements;
489 0         0 $array->mode('double');
490             }
491             elsif ($mode_h->{logical}) {
492 0         0 my $a1 = Rstats::Array->new(elements => $elements)->as_logical;
493 0         0 $elements = $a1->elements;
494 0         0 $array->mode('logical');
495             }
496             }
497             else {
498 4434   100     8742 $array->mode($modes[0] || 'logical');
499             }
500            
501 4435         70801 $array->elements($elements);
502            
503 4435         30086 return $array;
504             }
505              
506             sub array {
507 554     554 0 725 my $self = shift;
508            
509             # Arguments
510 554 100       1188 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
511 554         878 my ($a1, $_dim) = @_;
512 554 100       1001 $_dim = $opt->{dim} unless defined $_dim;
513            
514 554         880 my $array = Rstats::Array->c($a1);
515              
516             # Dimention
517 554         7062 my $elements = $array->elements;
518 554         2320 my $dim;
519 554 100       864 if (defined $_dim) {
520 286 50       707 if (ref $_dim eq 'Rstats::Array') {
    100          
    50          
521 0         0 $dim = $_dim->elements;
522             }
523             elsif (ref $_dim eq 'ARRAY') {
524 285         352 $dim = $_dim;
525             }
526             elsif(!ref $_dim) {
527 1         2 $dim = [$_dim];
528             }
529             }
530             else {
531 268         416 $dim = [scalar @$elements]
532             }
533 554         1148 $array->dim($dim);
534            
535             # Fix elements
536 554         630 my $max_length = 1;
537 554 50       594 $max_length *= $_ for @{$array->_real_dim_values || [scalar @$elements]};
  554         813  
538 554 100       1472 if (@$elements > $max_length) {
    100          
539 7         24 @$elements = splice @$elements, 0, $max_length;
540             }
541             elsif (@$elements < $max_length) {
542 10         36 my $repeat_count = int($max_length / @$elements) + 1;
543 10         50 @$elements = (@$elements) x $repeat_count;
544 10         27 @$elements = splice @$elements, 0, $max_length;
545             }
546 554         8152 $array->elements($elements);
547            
548 554         5105 return $array;
549             }
550              
551             sub _real_dim_values {
552 5271     5271   5446 my $self = shift;
553            
554 5271         7659 my $dim = $self->dim;
555 5271 100       25588 if (@{$dim->values}) {
  5271         7418  
556 1077         1608 return $dim->values;
557             }
558             else {
559 4194 50       52360 if (defined $self->elements) {
560 4194         28492 my $length = @{$self->elements};
  4194         50090  
561 4194         21379 return [$length];
562             }
563             else {
564 0         0 return;
565             }
566             }
567             }
568              
569             sub at {
570 249     249 0 309 my $self = shift;
571            
572 249 100       434 if (@_) {
573 210         459 $self->{at} = [@_];
574            
575 210         313 return $self;
576             }
577            
578 39         66 return $self->{at};
579             }
580              
581             sub element {
582 4469     4469 0 5061 my $self = shift;
583            
584 4469         6344 my $dim_values = $self->_real_dim_values;
585            
586 4469 100       6861 if (@_) {
587 296 100       563 if (@$dim_values == 1) {
    100          
588 2         27 return $self->elements->[$_[0] - 1];
589             }
590             elsif (@$dim_values == 2) {
591 149         2137 return $self->elements->[($_[0] + $dim_values->[0] * ($_[1] - 1)) - 1];
592             }
593             else {
594 145         276 return $self->get(@_)->elements->[0];
595             }
596             }
597             else {
598 4173         50546 return $self->elements->[0];
599             }
600             }
601              
602             sub is_numeric {
603 16     16 0 43 my $self = shift;
604            
605 16 50 33     62 my $is = ($self->{type} || '') eq 'double' || ($self->{type} || '') eq 'integer' ? Rstats::Util::TRUE : Rstats::Util::FALSE;
606            
607 16         32 return $self->c([$is]);
608             }
609              
610             sub is_double {
611 0     0 0 0 my $self = shift;
612            
613 0 0 0     0 my $is = ($self->{type} || '') eq 'double' ? Rstats::Util::TRUE : Rstats::Util::FALSE;
614            
615 0         0 return $self->c([$is]);
616             }
617              
618             sub is_integer {
619 14     14 0 39 my $self = shift;
620            
621 14 50 50     47 my $is = ($self->{type} || '') eq 'integer' ? Rstats::Util::TRUE : Rstats::Util::FALSE;
622            
623 14         29 return $self->c([$is]);
624             }
625              
626             sub is_complex {
627 24     24 0 72 my $self = shift;
628            
629 24 50 50     81 my $is = ($self->{type} || '') eq 'complex' ? Rstats::Util::TRUE : Rstats::Util::FALSE;
630            
631 24         47 return $self->c([$is]);
632             }
633              
634             sub is_character {
635 1349     1349 0 1594 my $self = shift;
636            
637 1349 100 50     3526 my $is = ($self->{type} || '') eq 'character' ? Rstats::Util::TRUE : Rstats::Util::FALSE;
638            
639 1349         2454 return $self->c([$is]);
640             }
641              
642             sub is_logical {
643 1347     1347 0 8465 my $self = shift;
644            
645 1347 100 50     3487 my $is = ($self->{type} || '') eq 'logical' ? Rstats::Util::TRUE : Rstats::Util::FALSE;
646            
647 1347         2532 return $self->c([$is]);
648             }
649              
650             sub _as {
651 18     18   25 my ($self, $mode) = @_;
652            
653 18 100       34 if ($mode eq 'character') {
    100          
    100          
    50          
    50          
    0          
654 12         18 return $self->as_character;
655             }
656             elsif ($mode eq 'complex') {
657 2         4 return $self->as_complex;
658             }
659             elsif ($mode eq 'double') {
660 2         4 return $self->as_double;
661             }
662             elsif ($mode eq 'numeric') {
663 0         0 return $self->as_numeric;
664             }
665             elsif ($mode eq 'integer') {
666 2         4 return $self->as_integer;
667             }
668             elsif ($mode eq 'logical') {
669 0         0 return $self->as_logical;
670             }
671             else {
672 0         0 croak "Invalid mode is passed";
673             }
674             }
675              
676             sub as_complex {
677 26     26 0 454 my $self = shift;
678            
679 26         30 my $a1 = $self;
680 26         355 my $a1_elements = $a1->elements;
681 26         132 my $a2 = $self->clone_without_elements;
682             my @a2_elements = map {
683 26 100       43 if (Rstats::Util::is_na($_)) {
  36 100       99  
    100          
    100          
    50          
    50          
684 1         3 $_;
685             }
686             elsif (Rstats::Util::is_character($_)) {
687 13         175 my $z = Rstats::Util::looks_like_complex($_->value);
688 13 100       23 if (defined $z) {
689 11         26 Rstats::Util::complex($z->{re}, $z->{im});
690             }
691             else {
692 2         168 carp 'NAs introduced by coercion';
693 2         96 Rstats::Util::NA;
694             }
695             }
696             elsif (Rstats::Util::is_complex($_)) {
697 4         10 $_;
698             }
699             elsif (Rstats::Util::is_double($_)) {
700 16 100       68 if (Rstats::Util::is_nan($_)) {
701 1         2 Rstats::Util::NA;
702             }
703             else {
704 15         51 Rstats::Util::complex_double($_, Rstats::Util::double(0));
705             }
706             }
707             elsif (Rstats::Util::is_integer($_)) {
708 0         0 Rstats::Util::complex($_->value, 0);
709             }
710             elsif (Rstats::Util::is_logical($_)) {
711 2 100       56 Rstats::Util::complex($_->value ? 1 : 0, 0);
712             }
713             else {
714 0         0 croak "unexpected type";
715             }
716             } @$a1_elements;
717 26         514 $a2->elements(\@a2_elements);
718 26         150 $a2->{type} = 'complex';
719              
720 26         61 return $a2;
721             }
722              
723 17     17 0 28 sub as_numeric { as_double(@_) }
724              
725             sub as_double {
726 19     19 0 25 my $self = shift;
727            
728 19         17 my $a1 = $self;
729 19         266 my $a1_elements = $a1->elements;
730 19         92 my $a2 = $self->clone_without_elements;
731             my @a2_elements = map {
732 19 100       34 if (Rstats::Util::is_na($_)) {
  30 100       74  
    100          
    100          
    100          
    50          
733 1         3 $_;
734             }
735             elsif (Rstats::Util::is_character($_)) {
736 5 100       68 if (my $num = Rstats::Util::looks_like_number($_->value)) {
737 4         10 Rstats::Util::double($num + 0);
738             }
739             else {
740 1         95 carp 'NAs introduced by coercion';
741 1         56 Rstats::Util::NA;
742             }
743             }
744             elsif (Rstats::Util::is_complex($_)) {
745 3         350 carp "imaginary parts discarded in coercion";
746 3         237 Rstats::Util::double($_->re->value);
747             }
748             elsif (Rstats::Util::is_double($_)) {
749 12         25 $_;
750             }
751             elsif (Rstats::Util::is_integer($_)) {
752 5         70 Rstats::Util::double($_->value);
753             }
754             elsif (Rstats::Util::is_logical($_)) {
755 4 100       57 Rstats::Util::double($_->value ? 1 : 0);
756             }
757             else {
758 0         0 croak "unexpected type";
759             }
760             } @$a1_elements;
761 19         325 $a2->elements(\@a2_elements);
762 19         98 $a2->{type} = 'double';
763              
764 19         41 return $a2;
765             }
766              
767             sub as_integer {
768 20     20 0 481 my $self = shift;
769            
770 20         22 my $a1 = $self;
771 20         304 my $a1_elements = $a1->elements;
772 20         95 my $a2 = $self->clone_without_elements;
773             my @a2_elements = map {
774 20 100       31 if (Rstats::Util::is_na($_)) {
  33 100       125  
    100          
    100          
    100          
    50          
775 1         3 $_;
776             }
777             elsif (Rstats::Util::is_character($_)) {
778 5 100       68 if (my $num = Rstats::Util::looks_like_number($_->value)) {
779 4         9 Rstats::Util::integer(int $num);
780             }
781             else {
782 1         78 carp 'NAs introduced by coercion';
783 1         53 Rstats::Util::NA;
784             }
785             }
786             elsif (Rstats::Util::is_complex($_)) {
787 1         77 carp "imaginary parts discarded in coercion";
788 1         71 Rstats::Util::integer(int($_->re->value));
789             }
790             elsif (Rstats::Util::is_double($_)) {
791 20 100 100     39 if (Rstats::Util::is_nan($_) || Rstats::Util::is_infinite($_)) {
792 2         4 Rstats::Util::NA;
793             }
794             else {
795 18         251 Rstats::Util::integer($_->value);
796             }
797             }
798             elsif (Rstats::Util::is_integer($_)) {
799 2         34 $_;
800             }
801             elsif (Rstats::Util::is_logical($_)) {
802 4 100       89 Rstats::Util::integer($_->value ? 1 : 0);
803             }
804             else {
805 0         0 croak "unexpected type";
806             }
807             } @$a1_elements;
808 20         406 $a2->elements(\@a2_elements);
809 20         107 $a2->{type} = 'integer';
810              
811 20         45 return $a2;
812             }
813              
814             sub as_logical {
815 11     11 0 13 my $self = shift;
816            
817 11         13 my $a1 = $self;
818 11         129 my $a1_elements = $a1->elements;
819 11         53 my $a2 = $self->clone_without_elements;
820             my @a2_elements = map {
821 11 100       15 if (Rstats::Util::is_na($_)) {
  15 100       25  
    100          
    100          
    50          
    50          
822 1         4 $_;
823             }
824             elsif (Rstats::Util::is_character($_)) {
825 3         5 Rstats::Util::NA;
826             }
827             elsif (Rstats::Util::is_complex($_)) {
828 2         241 carp "imaginary parts discarded in coercion";
829 2         170 my $re = $_->re->value;
830 2         61 my $im = $_->im->value;
831 2 100 66     48 if (defined $re && $re == 0 && defined $im && $im == 0) {
      66        
      66        
832 1         3 Rstats::Util::FALSE;
833             }
834             else {
835 1         3 Rstats::Util::TRUE;
836             }
837             }
838             elsif (Rstats::Util::is_double($_)) {
839 7 100       11 if (Rstats::Util::is_nan($_)) {
    100          
840 1         2 Rstats::Util::NA;
841             }
842             elsif (Rstats::Util::is_infinite($_)) {
843 1         2 Rstats::Util::TRUE;
844             }
845             else {
846 5 100       70 $_->value == 0 ? Rstats::Util::FALSE : Rstats::Util::TRUE;
847             }
848             }
849             elsif (Rstats::Util::is_integer($_)) {
850 0 0       0 $_->value == 0 ? Rstats::Util::FALSE : Rstats::Util::TRUE;
851             }
852             elsif (Rstats::Util::is_logical($_)) {
853 2 100       28 $_->value == 0 ? Rstats::Util::FALSE : Rstats::Util::TRUE;
854             }
855             else {
856 0         0 croak "unexpected type";
857             }
858             } @$a1_elements;
859 11         171 $a2->elements(\@a2_elements);
860 11         62 $a2->{type} = 'logical';
861              
862 11         20 return $a2;
863             }
864              
865             sub as_character {
866 25     25 0 446 my $self = shift;
867              
868 25         349 my $a1_elements = $self->elements;
869 25         130 my $a2 = $self->clone_without_elements;
870             my @a2_elements = map {
871 25         41 Rstats::Util::character(Rstats::Util::to_string($_))
  59         230  
872             } @$a1_elements;
873 25         488 $a2->elements(\@a2_elements);
874 25         131 $a2->{type} = 'character';
875              
876 25         61 return $a2;
877             }
878              
879             sub get {
880 171     171 0 288 my $self = shift;
881              
882 171 100       300 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
883 171         221 my $drop = $opt->{drop};
884 171 100       298 $drop = 1 unless defined $drop;
885            
886 171         323 my @_indexs = @_;
887              
888 171         170 my $_indexs;
889 171 50       246 if (@_indexs) {
890 171         219 $_indexs = \@_indexs;
891             }
892             else {
893 0         0 my $at = $self->at;
894 0 0       0 $_indexs = ref $at eq 'ARRAY' ? $at : [$at];
895             }
896 171         330 $self->at($_indexs);
897            
898 171 100       308 if (ref $_indexs->[0] eq 'CODE') {
899 1         2 my @elements2 = grep { $_indexs->[0]->() } @{$self->values};
  5         13  
  1         2  
900 1         5 return Rstats::Array->c(\@elements2);
901             }
902              
903 170         310 my ($positions, $a2_dim) = $self->_parse_index($drop, @$_indexs);
904            
905 170         259 my @a2_elements = map { $self->elements->[$_ - 1] } @$positions;
  266         3995  
906            
907 170         1188 return Rstats::Array->array(\@a2_elements, $a2_dim);
908             }
909              
910             sub NULL {
911 10     10 0 16 my $self = shift;
912            
913 10         24 return Rstats::Array->numeric(0);
914             }
915              
916             sub numeric {
917 11     11 0 21 my ($self, $num) = @_;
918            
919 11         29 return Rstats::Array->c([(0) x $num]);
920             }
921              
922             sub _to_a {
923 878     878   1333 my ($self, $data) = @_;
924            
925 878 100       1363 return $self->NULL unless defined $data;
926 871         871 my $v;
927 871 100       1360 if (ref $data eq 'Rstats::Array') {
928 77         110 $v = $data;
929             }
930             else {
931 794         1317 $v = Rstats::Array->c($data);
932             }
933            
934 871         1291 return $v;
935             }
936              
937             sub set {
938 39     39 0 66 my ($self, $_array) = @_;
939              
940 39         62 my $at = $self->at;
941 39 50       91 my $_indexs = ref $at eq 'ARRAY' ? $at : [$at];
942              
943 39         55 my $code;
944             my $array;
945 39 100       97 if (ref $_array eq 'CODE') {
946 1         3 $code = $_array;
947             }
948             else {
949 38         74 $array = Rstats::Array->_to_a($_array);
950             }
951            
952 39         106 my ($positions, $a2_dim) = $self->_parse_index(0, @$_indexs);
953            
954 39         695 my $self_elements = $self->elements;
955 39 100       251 if ($code) {
956 1         4 for (my $i = 0; $i < @$positions; $i++) {
957 3         18 my $pos = $positions->[$i];
958 3         9 local $_ = Rstats::Util::value($self_elements->[$pos - 1]);
959 3         22 $self_elements->[$pos - 1] = Rstats::Util::element($code->());
960             }
961             }
962             else {
963 38         516 my $array_elements = $array->elements;
964 38         220 for (my $i = 0; $i < @$positions; $i++) {
965 42         64 my $pos = $positions->[$i];
966 42         134 $self_elements->[$pos - 1] = $array_elements->[(($i + 1) % @$positions) - 1];
967             }
968             }
969            
970 39         129 return $self;
971             }
972              
973              
974             sub _parse_index {
975 209     209   424 my ($self, $drop, @_indexs) = @_;
976            
977 209         323 my $a1_dim = $self->_real_dim_values;
978 209         315 my @indexs;
979             my @a2_dim;
980            
981 209         412 for (my $i = 0; $i < @$a1_dim; $i++) {
982 683         922 my $_index = $_indexs[$i];
983            
984 683         1174 my $index = Rstats::Array->_to_a($_index);
985 683         1210 my $index_values = $index->values;
986 683 100 100     1698 if (@$index_values && !$index->is_character && !$index->is_logical) {
      66        
987 667         4184 my $minus_count = 0;
988 667         990 for my $index_value (@$index_values) {
989 687 50       1027 if ($index_value == 0) {
990 0         0 croak "0 is invalid index";
991             }
992             else {
993 687 100       1073 $minus_count++ if $index_value < 0;
994             }
995             }
996 667 50 66     1047 croak "Can't min minus sign and plus sign"
997             if $minus_count > 0 && $minus_count != @$index_values;
998 667 100       902 $index->{_minus} = 1 if $minus_count > 0;
999             }
1000            
1001 683 100       1658 if (!@{$index->values}) {
  683 100       1120  
    50          
    100          
1002 14         53 my $index_values_new = [1 .. $a1_dim->[$i]];
1003 14         41 $index = Rstats::Array->array($index_values_new);
1004             }
1005             elsif ($index->is_character) {
1006 2 50       17 if ($self->is_vector) {
    0          
1007 2         13 my $index_new_values = [];
1008 2         3 for my $name (@{$index->values}) {
  2         13  
1009 4         7 my $i = 0;
1010 4         4 my $value;
1011 4         6 for my $self_name (@{$self->names->values}) {
  4         7  
1012 12 100       20 if ($name eq $self_name) {
1013 4         32 $value = $self->values->[$i];
1014 4         7 last;
1015             }
1016 8         11 $i++;
1017             }
1018 4 50       16 croak "Can't find name" unless defined $value;
1019 4         10 push @$index_new_values, $value;
1020             }
1021 2         7 $indexs[$i] = Rstats::Array->array($index_new_values);
1022             }
1023             elsif ($self->is_matrix) {
1024            
1025             }
1026             else {
1027 0         0 croak "Can't support name except vector and matrix";
1028             }
1029             }
1030             elsif ($index->is_logical) {
1031 0         0 my $index_values_new = [];
1032 0         0 for (my $i = 0; $i < @{$index->values}; $i++) {
  0         0  
1033 0 0       0 push @$index_values_new, $i + 1 if Rstats::Util::bool($index->elements->[$i]);
1034             }
1035 0         0 $index = Rstats::Array->array($index_values_new);
1036             }
1037             elsif ($index->{_minus}) {
1038 4         25 my $index_value_new = [];
1039            
1040 4         11 for my $k (1 .. $a1_dim->[$i]) {
1041 15 100       16 push @$index_value_new, $k unless grep { $_ == -$k } @{$index->values};
  26         61  
  15         26  
1042             }
1043 4         11 $index = Rstats::Array->array($index_value_new);
1044             }
1045              
1046 683         5051 push @indexs, $index;
1047              
1048 683         757 my $count = @{$index->elements};
  683         8598  
1049 683 100 100     4758 push @a2_dim, $count unless $count == 1 && $drop;
1050             }
1051 209 100       458 @a2_dim = (1) unless @a2_dim;
1052            
1053 209         378 my $index_values = [map { $_->values } @indexs];
  685         1012  
1054 209         453 my $ords = $self->_cross_product($index_values);
1055 209         308 my @positions = map { $self->_pos($_, $a1_dim) } @$ords;
  311         521  
1056            
1057 209         1256 return (\@positions, \@a2_dim);
1058             }
1059              
1060             sub _cross_product {
1061 210     210   321 my ($self, $values) = @_;
1062              
1063 210         412 my @idxs = (0) x @$values;
1064 210         356 my @idx_idx = 0..(@idxs - 1);
1065 210         330 my @array = map { $_->[0] } @$values;
  688         958  
1066 210         312 my $result = [];
1067            
1068 210         449 push @$result, [@array];
1069 210         249 my $end_loop;
1070 210         251 while (1) {
1071 319         424 foreach my $i (@idx_idx) {
1072 843 100       852 if( $idxs[$i] < @{$values->[$i]} - 1 ) {
  843         1231  
1073 109         124 $array[$i] = $values->[$i][++$idxs[$i]];
1074 109         171 push @$result, [@array];
1075 109         133 last;
1076             }
1077            
1078 734 100       1006 if ($i == $idx_idx[-1]) {
1079 210         250 $end_loop = 1;
1080 210         249 last;
1081             }
1082            
1083 524         515 $idxs[$i] = 0;
1084 524         621 $array[$i] = $values->[$i][0];
1085             }
1086 319 100       441 last if $end_loop;
1087             }
1088            
1089 210         389 return $result;
1090             }
1091              
1092             sub _pos {
1093 313     313   906 my ($self, $ord, $dim) = @_;
1094            
1095 313         336 my $pos = 0;
1096 313         555 for (my $d = 0; $d < @$dim; $d++) {
1097 973 100       1206 if ($d > 0) {
1098 660         645 my $tmp = 1;
1099 660         1267 $tmp *= $dim->[$_] for (0 .. $d - 1);
1100 660         1062 $pos += $tmp * ($ord->[$d] - 1);
1101             }
1102             else {
1103 313         525 $pos += $ord->[$d];
1104             }
1105             }
1106            
1107 313         574 return $pos;
1108             }
1109              
1110             sub to_string {
1111 17     17 0 72 my $self = shift;
1112              
1113 17         271 my $elements = $self->elements;
1114            
1115 17         86 my $dim_values = $self->_real_dim_values;
1116            
1117 17         26 my $dim_length = @$dim_values;
1118 17         26 my $dim_num = $dim_length - 1;
1119 17         22 my $positions = [];
1120            
1121 17         27 my $str;
1122 17 100       37 if (@$elements) {
1123 16 100       37 if ($dim_length == 1) {
    100          
1124 8         22 my $names = $self->names->values;
1125 8 100       26 if (@$names) {
1126 1         4 $str .= join(' ', @$names) . "\n";
1127             }
1128 8         13 my @parts = map { Rstats::Util::to_string($_) } @$elements;
  53         260  
1129 8         76 $str .= '[1] ' . join(' ', @parts) . "\n";
1130             }
1131             elsif ($dim_length == 2) {
1132 6         11 $str .= ' ';
1133            
1134 6         15 my $colnames = $self->colnames->values;
1135 6 100       19 if (@$colnames) {
1136 1         4 $str .= join(' ', @$colnames) . "\n";
1137             }
1138             else {
1139 5         12 for my $d2 (1 .. $dim_values->[1]) {
1140 11 100       28 $str .= $d2 == $dim_values->[1] ? "[,$d2]\n" : "[,$d2] ";
1141             }
1142             }
1143            
1144 6         16 my $rownames = $self->rownames->values;
1145 6 100       18 my $use_rownames = @$rownames ? 1 : 0;
1146 6         16 for my $d1 (1 .. $dim_values->[0]) {
1147 42 100       63 if ($use_rownames) {
1148 2         4 my $rowname = $rownames->[$d1 - 1];
1149 2         4 $str .= "$rowname ";
1150             }
1151             else {
1152 40         57 $str .= "[$d1,] ";
1153             }
1154            
1155 42         45 my @parts;
1156 42         52 for my $d2 (1 .. $dim_values->[1]) {
1157 70         247 push @parts, Rstats::Util::to_string($self->element($d1, $d2));
1158             }
1159            
1160 42         282 $str .= join(' ', @parts) . "\n";
1161             }
1162             }
1163             else {
1164 2         3 my $code;
1165             $code = sub {
1166 4     4   9 my (@dim_values) = @_;
1167 4         6 my $dim_value = pop @dim_values;
1168            
1169 4         9 for (my $i = 1; $i <= $dim_value; $i++) {
1170 10         39 $str .= (',' x $dim_num) . "$i" . "\n";
1171 10         17 unshift @$positions, $i;
1172 10 100       32 if (@dim_values > 2) {
1173 2         12 $dim_num--;
1174 2         9 $code->(@dim_values);
1175 2         5 $dim_num++;
1176             }
1177             else {
1178 8         17 $str .= ' ';
1179 8         25 for my $d2 (1 .. $dim_values[1]) {
1180 30 100       76 $str .= $d2 == $dim_values[1] ? "[,$d2]\n" : "[,$d2] ";
1181             }
1182 8         18 for my $d1 (1 .. $dim_values[0]) {
1183 38         92 $str .= "[$d1,] ";
1184            
1185 38         57 my @parts;
1186 38         56 for my $d2 (1 .. $dim_values[1]) {
1187 144         834 push @parts, Rstats::Util::to_string($self->element($d1, $d2, @$positions));
1188             }
1189            
1190 38         351 $str .= join(' ', @parts) . "\n";
1191             }
1192             }
1193 10         48 shift @$positions;
1194             }
1195 2         12 };
1196 2         6 $code->(@$dim_values);
1197             }
1198             }
1199             else {
1200 1         2 $str = 'NULL';
1201             }
1202            
1203 17         77 return $str;
1204             }
1205              
1206             sub negation {
1207 1     1 0 4 my $self = shift;
1208            
1209 1         2 my $a1_elements = [map { Rstats::Util::negation($_) } @{$self->elements}];
  3         20  
  1         14  
1210 1         9 my $a1 = $self->clone_without_elements;
1211 1         15 $a1->elements($a1_elements);
1212            
1213 1         6 return $a1;
1214             }
1215              
1216             sub _operation {
1217 50     50   101 my ($self, $op, $data, $reverse) = @_;
1218            
1219 50         62 my $a1;
1220             my $a2;
1221 50 100       128 if (ref $data eq 'Rstats::Array') {
1222 39         45 $a1 = $self;
1223 39         39 $a2 = $data;
1224             }
1225             else {
1226 11 100       19 if ($reverse) {
1227 4         9 $a1 = Rstats::Array->array([$data]);
1228 4         6 $a2 = $self;
1229             }
1230             else {
1231 7         16 $a1 = $self;
1232 7         16 $a2 = Rstats::Array->array([$data]);
1233             }
1234             }
1235            
1236             # Upgrade mode if mode is different
1237             ($a1, $a2) = $self->_upgrade_mode($a1, $a2)
1238 50 100       102 if $a1->{type} ne $a2->{type};
1239            
1240             # Calculate
1241 50         50 my $a1_length = @{$a1->elements};
  50         636  
1242 50         207 my $a2_length = @{$a2->elements};
  50         613  
1243 50 100       221 my $longer_length = $a1_length > $a2_length ? $a1_length : $a2_length;
1244            
1245 8     8   46750 no strict 'refs';
  8         15  
  8         6891  
1246 50         82 my $operation = "Rstats::Util::$op";
1247             my @a3_elements = map {
1248 50         132 &$operation($a1->elements->[$_ % $a1_length], $a2->elements->[$_ % $a2_length])
  132         1858  
1249             } (0 .. $longer_length - 1);
1250            
1251 44         200 my $a3 = Rstats::Array->array(\@a3_elements);
1252 44 50       84 if ($op eq '/') {
1253 0         0 $a3->{type} = 'double';
1254             }
1255             else {
1256 44         71 $a3->{type} = $a1->{type};
1257             }
1258            
1259 44         184 return $a3;
1260             }
1261              
1262             sub _upgrade_mode {
1263 9     9   16 my ($self, @arrays) = @_;
1264            
1265             # Check elements
1266 9         10 my $mode_h = {};
1267 9         14 for my $array (@arrays) {
1268 18   50     31 my $type = $array->{type} || '';
1269 18 100       36 if ($type eq 'character') {
    100          
    100          
    100          
    50          
1270 6         11 $mode_h->{character}++;
1271             }
1272             elsif ($type eq 'complex') {
1273 1         2 $mode_h->{complex}++;
1274             }
1275             elsif ($type eq 'double') {
1276 8         12 $mode_h->{double}++;
1277             }
1278             elsif ($type eq 'integer') {
1279 2         4 $mode_h->{integer}++;
1280             }
1281             elsif ($type eq 'logical') {
1282 1         2 $mode_h->{logical}++;
1283             }
1284             else {
1285 0         0 croak "Invalid mode";
1286             }
1287             }
1288              
1289             # Upgrade elements and type if mode is different
1290 9         21 my @modes = keys %$mode_h;
1291 9 50       15 if (@modes > 1) {
1292 9         9 my $to_mode;
1293 9 100       20 if ($mode_h->{character}) {
    100          
    100          
    50          
    0          
1294 6         7 $to_mode = 'character';
1295             }
1296             elsif ($mode_h->{complex}) {
1297 1         2 $to_mode = 'complex';
1298             }
1299             elsif ($mode_h->{double}) {
1300 1         2 $to_mode = 'double';
1301             }
1302             elsif ($mode_h->{integer}) {
1303 1         1 $to_mode = 'integer';
1304             }
1305             elsif ($mode_h->{logical}) {
1306 0         0 $to_mode = 'logical';
1307             }
1308 9         19 $_ = $_->_as($to_mode) for @arrays;
1309             }
1310            
1311 9         26 return @arrays;
1312             }
1313              
1314              
1315             sub matrix {
1316 74     74 0 107 my $self = shift;
1317            
1318 74 100       191 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
1319              
1320 74         159 my ($_a1, $nrow, $ncol, $byrow, $dirnames) = @_;
1321              
1322 74 50       154 croak "matrix method need data as frist argument"
1323             unless defined $_a1;
1324            
1325 74         149 my $a1 = Rstats::Array->_to_a($_a1);
1326            
1327             # Row count
1328 74 100       164 $nrow = $opt->{nrow} unless defined $nrow;
1329            
1330             # Column count
1331 74 100       135 $ncol = $opt->{ncol} unless defined $ncol;
1332            
1333             # By row
1334 74 50       138 $byrow = $opt->{byrow} unless defined $byrow;
1335            
1336 74         1156 my $a1_elements = $a1->elements;
1337 74         386 my $a1_length = @$a1_elements;
1338 74 100 100     283 if (!defined $nrow && !defined $ncol) {
    100          
    100          
1339 26         31 $nrow = $a1_length;
1340 26         38 $ncol = 1;
1341             }
1342             elsif (!defined $nrow) {
1343 1         3 $nrow = int($a1_length / $ncol);
1344             }
1345             elsif (!defined $ncol) {
1346 1         3 $ncol = int($a1_length / $nrow);
1347             }
1348 74         104 my $length = $nrow * $ncol;
1349            
1350 74         141 my $dim = [$nrow, $ncol];
1351 74         97 my $matrix;
1352 74 100       116 if ($byrow) {
1353 1         4 $matrix = $self->array(
1354             $a1_elements,
1355             [$dim->[1], $dim->[0]],
1356             );
1357            
1358 1         4 $matrix = $self->t($matrix);
1359             }
1360             else {
1361 73         150 $matrix = $self->array($a1_elements, $dim);
1362             }
1363            
1364 74         313 return $matrix;
1365             }
1366              
1367             sub t {
1368 3     3 0 8 my ($self, $m1) = @_;
1369            
1370 3         8 my $m1_row = $m1->dim->elements->[0];
1371 3         87 my $m1_col = $m1->dim->elements->[1];
1372            
1373 3         98 my $m2 = $self->matrix(0, $m1_col, $m1_row);
1374            
1375 3         9 for my $row (1 .. $m1_row) {
1376 11         22 for my $col (1 .. $m1_col) {
1377 30         69 my $element = $m1->element($row, $col);
1378 30         245 $m2->at($col, $row);
1379 30         57 $m2->set($element);
1380             }
1381             }
1382            
1383 3         16 return $m2;
1384             }
1385              
1386             sub is_array {
1387 5     5 0 253 my $self = shift;
1388            
1389 5         12 return $self->c([Rstats::Util::TRUE()]);
1390             }
1391              
1392             sub is_vector {
1393 12     12 0 67 my $self = shift;
1394            
1395 12 100       19 my $is = @{$self->dim->elements} == 0 ? Rstats::Util::TRUE() : Rstats::Util::FALSE();
  12         31  
1396            
1397 12         47 return $self->c([$is]);
1398             }
1399              
1400             sub is_matrix {
1401 21     21 0 293 my $self = shift;
1402              
1403 21 100       34 my $is = @{$self->dim->elements} == 2 ? Rstats::Util::TRUE() : Rstats::Util::FALSE();
  21         75  
1404            
1405 21         89 return $self->c([$is]);
1406             }
1407              
1408             sub as_matrix {
1409 16     16 0 62 my $self = shift;
1410            
1411 16         39 my $a1_dim_elements = $self->_real_dim_values;
1412 16         31 my $a1_dim_count = @$a1_dim_elements;
1413 16         32 my $a2_dim_elements = [];
1414 16         31 my $row;
1415             my $col;
1416 16 100       38 if ($a1_dim_count == 2) {
1417 6         14 $row = $a1_dim_elements->[0];
1418 6         13 $col = $a1_dim_elements->[1];
1419             }
1420             else {
1421 10         18 $row = 1;
1422 10         53 $row *= $_ for @$a1_dim_elements;
1423 10         18 $col = 1;
1424             }
1425            
1426 16         25 my $a2_elements = [@{$self->elements}];
  16         323  
1427            
1428 16         180 return $self->matrix($a2_elements, $row, $col);
1429             }
1430              
1431             sub as_array {
1432 0     0 0 0 my $self = shift;
1433            
1434 0         0 my $a1_elements = [@{$self->elements}];
  0         0  
1435 0         0 my $a1_dim_elements = [@{$self->_real_dim_values}];
  0         0  
1436            
1437 0         0 return $self->array($a1_elements, $a1_dim_elements);
1438             }
1439              
1440             sub as_vector {
1441 10     10 0 42 my $self = shift;
1442            
1443 10         18 my $a1_elements = [@{$self->elements}];
  10         170  
1444            
1445 10         86 return $self->c($a1_elements);
1446             }
1447              
1448             1;
1449