File Coverage

blib/lib/Rstats.pm
Criterion Covered Total %
statement 573 626 91.5
branch 76 102 74.5
condition 9 14 64.2
subroutine 95 104 91.3
pod 0 96 0.0
total 753 942 79.9


line stmt bran cond sub pod time code
1             package Rstats;
2              
3             our $VERSION = '0.0150';
4              
5 8     8   448046 use Object::Simple -base;
  8         8667  
  8         51  
6              
7 8     8   809 use List::Util;
  8         14  
  8         538  
8 8     8   3630 use Math::Trig ();
  8         108000  
  8         224  
9 8     8   53 use Carp 'croak';
  8         12  
  8         417  
10 8     8   4769 use POSIX ();;
  8         39820  
  8         176  
11 8     8   2918 use Math::Round ();
  8         7228  
  8         45490  
12             require Rstats::Util;
13             require Rstats::Array;
14              
15             # TODO
16             # logp1x
17             # gamma
18             # lgamma
19             # complete_cases
20              
21 0     0 0 0 sub Inf { shift->c(Rstats::Util::Inf()) }
22 1     1 0 80 sub NA { shift->c(Rstats::Util::NA()) }
23 0     0 0 0 sub NaN { shift->c(Rstats::Util::NaN()) }
24 3     3 0 817 sub TRUE { shift->c(Rstats::Util::TRUE()) }
25 3     3 0 9 sub FALSE { shift->c(Rstats::Util::FALSE()) }
26              
27             sub is_null {
28 0     0 0 0 my ($self, $_a1) = @_;
29            
30 0         0 my $a1 = $self->_to_a($_a1);
31            
32 0 0       0 my @a2_elements = [!@$a1->elements ? Rstats::Util::TRUE() : Rstats::Util::FALSE()];
33 0         0 my $a2 = Rstats::Array->array(\@a2_elements);
34 0         0 $a2->mode('logical');
35            
36 0         0 return $a2;
37             }
38              
39             sub is_na {
40 0     0 0 0 my ($self, $_a1) = @_;
41            
42 0         0 my $a1 = $self->_to_a($_a1);
43            
44             my @a2_elements = map {
45 0 0       0 ref $_ eq 'Rstats::Type::NA' ? Rstats::Util::TRUE() : Rstats::Util::FALSE()
46 0         0 } @{$a1->elements};
  0         0  
47 0         0 my $a2 = Rstats::Array->array(\@a2_elements);
48 0         0 $a2->mode('logical');
49            
50 0         0 return $a2;
51             }
52              
53             sub is_nan {
54 0     0 0 0 my ($self, $_a1) = @_;
55            
56 0         0 my $a1 = $self->_to_a($_a1);
57            
58             my @a2_elements = map {
59 0 0       0 ref $_ eq 'Rstats::NaN' ? Rstats::Util::TRUE() : Rstats::Util::FALSE()
60 0         0 } @{$a1->elements};
  0         0  
61 0         0 my $a2 = Rstats::Array->array(\@a2_elements);
62 0         0 $a2->mode('logical');
63            
64 0         0 return $a2;
65             }
66              
67             sub is_finite {
68 0     0 0 0 my ($self, $_a1) = @_;
69              
70 0         0 my $a1 = $self->_to_a($_a1);
71            
72             my @a2_elements = map {
73 0 0 0     0 !ref $_ || ref $_ eq 'Rstats::Type::Complex' || ref $_ eq 'Rstats::Logical'
74             ? Rstats::Util::TRUE()
75             : Rstats::Util::FALSE()
76 0         0 } @{$a1->elements};
  0         0  
77 0         0 my $a2 = Rstats::Array->array(\@a2_elements);
78 0         0 $a2->mode('logical');
79            
80 0         0 return $a2;
81             }
82              
83             sub is_infinite {
84 0     0 0 0 my ($self, $_a1) = @_;
85            
86 0         0 my $a1 = $self->_to_a($_a1);
87            
88             my @a2_elements = map {
89 0 0       0 ref $_ eq 'Rstats::Inf' ? Rstats::Util::TRUE() : Rstats::Util::FALSE()
90 0         0 } @{$a1->elements};
  0         0  
91 0         0 my $a2 = Rstats::Array->array(\@a2_elements);
92 0         0 $a2->mode('logical');
93              
94 0         0 return $a1->clone_without_elements(elements => \@a2_elements);
95             }
96              
97             sub complex {
98 15     15 0 4470 my ($self, $re, $im) = @_;
99            
100 15         40 return $self->c([Rstats::Util::complex($re, $im)]);
101             }
102              
103              
104             sub as_complex {
105 20     20 0 76 my ($self, $a1) = @_;
106            
107 20         38 return $a1->as_complex;
108             }
109              
110             sub as_numeric {
111 17     17 0 57 my ($self, $a1) = @_;
112            
113 17         35 return $a1->as_numeric;
114             }
115              
116             sub as_integer {
117 12     12 0 44 my ($self, $a1) = @_;
118            
119 12         21 return $a1->as_integer;
120             }
121              
122             sub as_character {
123 8     8 0 32 my ($self, $a1) = @_;
124            
125 8         20 return $a1->as_character;
126             }
127              
128             sub as_logical {
129 11     11 0 43 my ($self, $a1) = @_;
130            
131 11         21 return $a1->as_logical;
132             }
133              
134             sub as_matrix {
135 6     6 0 23 my ($self, $a1) = @_;
136            
137 6         14 return $a1->as_matrix;
138             }
139              
140             sub as_vector {
141 2     2 0 9 my ($self, $a1) = @_;
142            
143 2         7 return $a1->as_vector;
144             }
145              
146             sub as_array {
147 0     0 0 0 my ($self, $a1) = @_;
148            
149 0         0 return $a1->as_array;
150             }
151              
152             sub is_matrix {
153 1     1 0 17 my ($self, $a1) = @_;
154            
155 1         5 return $a1->is_matrix;
156             }
157              
158             sub is_vector {
159 1     1 0 7 my ($self, $a1) = @_;
160            
161 1         4 return $a1->is_vector;
162             }
163              
164             sub is_array {
165 1     1 0 11 my ($self, $a1) = @_;
166            
167 1         5 return $a1->is_array;
168             }
169              
170             sub rbind {
171 1     1 0 725 my ($self, @arrays) = @_;
172            
173 1         83 my $matrix = $self->cbind(@arrays);
174            
175 1         5 return $self->t($matrix);
176             }
177              
178             sub cbind {
179 2     2 0 596 my ($self, @arrays) = @_;
180            
181 2         6 my $row_count_needed;
182             my $col_count_total;
183 2         5 my $a2_elements = [];
184 2         7 for my $_a (@arrays) {
185            
186 6         58 my $a = $self->_to_a($_a);
187            
188 6         11 my $row_count;
189 6 50       19 if ($a->is_matrix) {
    50          
190 0         0 $row_count = $a->dim->elements->[0];
191 0         0 $col_count_total += $a->dim->elements->[1];
192             }
193             elsif ($a->is_vector) {
194 6         49 $row_count = $a->_real_dim_values->[0];
195 6         14 $col_count_total += 1;
196             }
197             else {
198 0         0 croak "cbind or rbind can only receive matrix and vector";
199             }
200            
201 6 100       25 $row_count_needed = $row_count unless defined $row_count_needed;
202 6 50       37 croak "Row count is different" if $row_count_needed ne $row_count;
203            
204 6         152 push @$a2_elements, $a->elements;
205             }
206 2         20 my $matrix = $self->matrix($a2_elements, $row_count_needed, $col_count_total);
207            
208 2         9 return $matrix;
209             }
210              
211             sub rowSums {
212 1     1 0 7 my ($self, $m1) = @_;
213            
214 1         3 my $dim_values = $m1->dim->values;
215 1 50       5 if (@$dim_values == 2) {
216 1         1 my $v1_values = [];
217 1         4 for my $col (1 .. $dim_values->[1]) {
218 3         5 my $v1_value = 0;
219 3         9 $v1_value += $m1->value($_, $col) for (1 .. $dim_values->[0]);
220 3         17 push @$v1_values, $v1_value;
221             }
222 1         12 return $self->c($v1_values);
223             }
224             else {
225 0         0 croak "Can't culculate rowSums";
226             }
227             }
228              
229             sub colSums {
230 1     1 0 9 my ($self, $m1) = @_;
231            
232 1         3 my $dim_values = $m1->dim->values;
233 1 50       7 if (@$dim_values == 2) {
234 1         2 my $v1_values = [];
235 1         3 for my $row (1 .. $dim_values->[0]) {
236 4         4 my $v1_value = 0;
237 4         11 $v1_value += $m1->value($row, $_) for (1 .. $dim_values->[1]);
238 4         23 push @$v1_values, $v1_value;
239             }
240 1         3 return $self->c($v1_values);
241             }
242             else {
243 0         0 croak "Can't culculate colSums";
244             }
245             }
246              
247             sub rowMeans {
248 1     1 0 7 my ($self, $m1) = @_;
249            
250 1         3 my $dim_values = $m1->dim->values;
251 1 50       4 if (@$dim_values == 2) {
252 1         2 my $v1_values = [];
253 1         3 for my $col (1 .. $dim_values->[1]) {
254 3         4 my $v1_value = 0;
255 3         8 $v1_value += $m1->value($_, $col) for (1 .. $dim_values->[0]);
256 3         20 push @$v1_values, $v1_value / $dim_values->[0];
257             }
258 1         3 return $self->c($v1_values);
259             }
260             else {
261 0         0 croak "Can't culculate rowSums";
262             }
263             }
264              
265             sub colMeans {
266 1     1 0 6 my ($self, $m1) = @_;
267            
268 1         4 my $dim_values = $m1->dim->values;
269 1 50       32 if (@$dim_values == 2) {
270 1         6 my $v1_values = [];
271 1         15 for my $row (1 .. $dim_values->[0]) {
272 4         7 my $v1_value = 0;
273 4         21 $v1_value += $m1->value($row, $_) for (1 .. $dim_values->[1]);
274 4         25 push @$v1_values, $v1_value / $dim_values->[1];
275             }
276 1         5 return $self->c($v1_values);
277             }
278             else {
279 0         0 croak "Can't culculate colSums";
280             }
281             }
282              
283             sub row {
284 1     1 0 6 my ($self, $m) = @_;
285            
286 1         4 return $m->row;
287             }
288              
289             sub col {
290 1     1 0 6 my ($self, $m) = @_;
291            
292 1         4 return $m->col;
293             }
294              
295             sub nrow {
296 1     1 0 6 my ($self, $m) = @_;
297            
298 1         3 return $m->nrow;
299             }
300              
301             sub ncol {
302 1     1 0 4 my ($self, $m) = @_;
303            
304 1         5 return $m->ncol;
305             }
306              
307             sub t {
308 2     2 0 7 my $self = shift;
309            
310 2         9 return Rstats::Array->t(@_);
311             }
312              
313             sub cumsum {
314 1     1 0 5 my ($self, $_v1) = @_;
315            
316 1         3 my $v1 = $self->_to_a($_v1);
317 1         2 my @v2_values;
318 1         1 my $total = 0;
319 1         2 push @v2_values, $total = $total + $_ for @{$v1->values};
  1         2  
320            
321 1         2 return $self->c(\@v2_values);
322             }
323              
324             sub rnorm {
325 1     1 0 443 my $self = shift;
326            
327             # Option
328 1 50       4 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
329            
330             # Count
331 1         2 my ($count, $mean, $sd) = @_;
332 1 50       3 croak "rnorm count should be bigger than 0"
333             if $count < 1;
334            
335             # Mean
336 1 50       2 $mean = 0 unless defined $mean;
337            
338             # Standard deviation
339 1 50       2 $sd = 1 unless defined $sd;
340            
341             # Random numbers(standard deviation)
342 1         2 my @v1_elements;
343 1         3 for (1 .. $count) {
344 100         128 my ($rand1, $rand2) = (rand, rand);
345 100         136 while ($rand1 == 0) { $rand1 = rand(); }
  0         0  
346            
347 100         182 my $rnorm = ($sd * sqrt(-2 * log($rand1))
348             * sin(2 * Math::Trig::pi * $rand2))
349             + $mean;
350            
351 100         138 push @v1_elements, $rnorm;
352             }
353            
354 1         39 return $self->c(\@v1_elements);
355             }
356              
357             sub sequence {
358 1     1 0 5 my ($self, $_v1) = @_;
359            
360 1         3 my $v1 = $self->_to_a($_v1);
361 1         2 my $v1_values = $v1->values;
362            
363 1         2 my @v2_values;
364 1         3 for my $v1_value (@$v1_values) {
365 3         8 push @v2_values, $self->seq($v1_value)->values;
366             }
367            
368 1         3 return $self->c(\@v2_values);
369             }
370              
371             # TODO: prob option
372             sub sample {
373 4     4 0 22 my $self = shift;
374 4 100       12 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
375            
376 4         7 my ($_v1, $length) = @_;
377 4         9 my $v1 = $self->_to_a($_v1);
378            
379             # Replace
380 4         7 my $replace = $opt->{replace};
381            
382 4         9 my $v1_length = $self->length($v1);
383 4 50       10 $length = $v1_length unless defined $length;
384            
385 4 50 66     13 croak "second argument element must be bigger than first argument elements count when you specify 'replace' option"
386             if $length > $v1_length && !$replace;
387            
388 4         4 my @v2_elements;
389 4         11 for my $i (0 .. $length - 1) {
390 155         383 my $rand_num = int(rand $self->length($v1));
391 155         165 my $rand_element = splice @{$v1->elements}, $rand_num, 1;
  155         1868  
392 155         683 push @v2_elements, $rand_element;
393 155 100       245 push @{$v1->elements}, $rand_element if $replace;
  55         646  
394             }
395            
396 4         16 return $self->c(\@v2_elements);
397             }
398              
399             sub NULL {
400 3     3 0 1081 my $self = shift;
401            
402 3         13 return Rstats::Array->NULL;
403             }
404              
405             sub _to_a {
406 83     83   112 my $self = shift;
407            
408 83         192 return Rstats::Array->_to_a(@_);
409             }
410              
411 1     1 0 8 sub order { shift->_order(1, @_) }
412 1     1 0 6 sub rev { shift->_order(0, @_) }
413              
414             sub _order {
415 2     2   4 my ($self, $asc, $_v1) = @_;
416            
417 2         5 my $v1 = $self->_to_a($_v1);
418 2         5 my $v1_values = $v1->values;
419            
420 2         3 my @pos_vals;
421 2         14 push @pos_vals, {pos => $_ + 1, val => $v1_values->[$_]} for (0 .. @$v1_values - 1);
422             my @sorted_pos_values = $asc
423 5         8 ? sort { $a->{val} <=> $b->{val} } @pos_vals
424 2 100       9 : sort { $b->{val} <=> $a->{val} } @pos_vals;
  5         9  
425 2         4 my @orders = map { $_->{pos} } @sorted_pos_values;
  8         11  
426            
427 2         4 return $self->c(\@orders);
428             }
429              
430             sub which {
431 1     1 0 11 my ($self, $_v1, $cond_cb) = @_;
432            
433 1         3 my $v1 = $self->_to_a($_v1);
434 1         3 my $v1_values = $v1->values;
435 1         3 my @v2_values;
436 1         4 for (my $i = 0; $i < @$v1_values; $i++) {
437 3         7 local $_ = $v1_values->[$i];
438 3 100       6 if ($cond_cb->($v1_values->[$i])) {
439 2         9 push @v2_values, $i + 1;
440             }
441             }
442            
443 1         3 return $self->c(\@v2_values);
444             }
445              
446             sub ifelse {
447 1     1 0 7 my ($self, $_v1, $value1, $value2) = @_;
448            
449 1         3 my $v1 = $self->_to_a($_v1);
450 1         4 my $v1_values = $v1->values;
451 1         2 my @v2_values;
452 1         3 for my $v1_value (@$v1_values) {
453 3         4 local $_ = $v1_value;
454 3 100       6 if ($v1_value) {
455 2         4 push @v2_values, $value1;
456             }
457             else {
458 1         1 push @v2_values, $value2;
459             }
460             }
461            
462 1         4 return $self->array(\@v2_values);
463             }
464              
465             sub replace {
466 3     3 0 16 my ($self, $_v1, $_v2, $_v3) = @_;
467            
468 3         5 my $v1 = $self->_to_a($_v1);
469 3         5 my $v2 = $self->_to_a($_v2);
470 3         5 my $v3 = $self->_to_a($_v3);
471            
472 3         7 my $v1_values = $v1->values;
473 3         6 my $v2_values = $v2->values;
474 3         4 my $v2_values_h = {};
475 3         6 for my $v2_value (@$v2_values) {
476 9         23 $v2_values_h->{$v2_value - 1}++;
477             croak "replace second argument can't have duplicate number"
478 9 50       17 if $v2_values_h->{$v2_value - 1} > 1;
479             }
480 3         7 my $v3_values = $v3->values;
481 3         5 my $v3_length = @{$v3_values};
  3         5  
482            
483 3         4 my $v4_values = [];
484 3         3 my $replace_count = 0;
485 3         20 for (my $i = 0; $i < @$v1_values; $i++) {
486 30 100       64 if ($v2_values_h->{$i}) {
487 9         13 push @$v4_values, $v3_values->[$replace_count % $v3_length];
488 9         14 $replace_count++;
489             }
490             else {
491 21         34 push @$v4_values, $v1_values->[$i];
492             }
493             }
494            
495 3         7 return $self->array($v4_values);
496             }
497              
498             sub dim {
499 24     24 0 643 my $self = shift;
500 24         36 my $v1 = shift;
501            
502 24         83 return $v1->dim(@_);
503             }
504              
505             sub append {
506 4     4 0 16 my $self = shift;
507              
508 4 100       10 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
509 4         5 my $v1 = shift;
510 4         4 my $element = shift;
511            
512 4         5 my $after = $opt->{after};
513 4 100       10 $after = $self->length($v1) unless defined $after;
514            
515 4 100       21 if (ref $element eq 'ARRAY') {
    100          
516 1         2 splice @{$v1->elements}, $after, 0, @$element;
  1         14  
517             }
518             elsif (ref $element eq 'Rstats::Array') {
519 1         2 splice @{$v1->elements}, $after, 0, @{$element->elements};
  1         13  
  1         16  
520             }
521             else {
522 2         3 splice @{$v1->elements}, $after, 0, $element;
  2         51  
523             }
524            
525 4         24 return $v1
526             }
527              
528             sub names {
529 3     3 0 12 my $self = shift;
530 3         5 my $v1 = shift;
531            
532 3         13 return $v1->names(@_);
533             }
534              
535             sub rownames {
536 3     3 0 16 my $self = shift;
537 3         6 my $m1 = shift;
538            
539 3         11 return $m1->rownames(@_);
540             }
541              
542             sub colnames {
543 3     3 0 16 my $self = shift;
544 3         3 my $m1 = shift;
545            
546 3         8 return $m1->colnames(@_);
547             }
548              
549             sub numeric {
550 1     1 0 452 my $self = shift;
551            
552 1         4 return Rstats::Array->numeric(@_);
553             }
554              
555             sub matrix {
556 55     55 0 15149 my $self = shift;
557            
558 55         165 return Rstats::Array->matrix(@_);
559             }
560              
561             sub array {
562 198     198 0 39116 my $self = shift;
563            
564 198         488 return Rstats::Array->array(@_);
565             }
566              
567             sub paste {
568 2     2 0 3 my $self = shift;
569              
570 2 100       7 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
571            
572 2         4 my $sep = $opt->{sep};
573 2 100       11 $sep = ' ' unless defined $sep;
574            
575 2         3 my $str = shift;
576 2         3 my $v1 = shift;
577            
578 2         5 my $v1_values = $v1->values;
579 2         4 my $v2_values = [];
580 2         9 push @$v2_values, "$str$sep$_" for @$v1_values;
581            
582 2         7 return Rstats::Array->c($v2_values);
583             }
584              
585             sub c {
586 164     164 0 36224 my $self = shift;
587            
588 164         408 return Rstats::Array->c(@_);
589             }
590              
591             sub C {
592 84     84 0 45085 my $self = shift;
593            
594 84         332 return Rstats::Array->C(@_);
595             }
596              
597             sub set_seed {
598 2     2 0 1072 my ($self, $seed) = @_;
599            
600 2         9 $self->{seed} = $seed;
601             }
602              
603             sub runif {
604 6     6 0 17 my ($self, $count, $min, $max) = @_;
605            
606 6 100       12 $min = 0 unless defined $min;
607 6 100       10 $max = 1 unless defined $max;
608 6 50       12 croak "runif third argument must be bigger than second argument"
609             if $min > $max;
610            
611 6         6 my $diff = $max - $min;
612 6         6 my @v1_elements;
613 6 100       11 if (defined $self->{seed}) {
614 2         3 srand $self->{seed};
615 2         3 $self->{seed} = undef;
616             }
617 6         23 for (1 .. $count) {
618 220         215 my $rand = rand($diff) + $min;
619 220         236 push @v1_elements, $rand;
620             }
621            
622 6         11 return $self->c(\@v1_elements);
623             }
624              
625             sub seq {
626 12     12 0 3285 my $self = shift;
627            
628 12         28 return Rstats::Array->seq(@_);
629             }
630              
631             sub rep {
632 1     1 0 7 my $self = shift;
633              
634 1 50       5 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
635            
636 1         2 my $v1 = shift;
637 1   50     4 my $times = $opt->{times} || 1;
638            
639 1         2 my $elements = [];
640 1         3 push @$elements, @{$v1->elements} for 1 .. $times;
  3         57  
641 1         6 my $v2 = $self->c($elements);
642            
643 1         3 return $v2;
644             }
645              
646             sub max {
647 3     3 0 12 my ($self, @vs) = @_;
648            
649 3         6 my @all_values = map { @{$_->values} } @vs;
  4         3  
  4         8  
650 3         9 my $max = List::Util::max(@all_values);
651 3         6 return $max;
652             }
653              
654             sub min {
655 3     3 0 12 my ($self, @vs) = @_;
656            
657 3         6 my @all_values = map { @{$_->values} } @vs;
  4         4  
  4         8  
658 3         8 my $min = List::Util::min(@all_values);
659 3         7 return $min;
660             }
661              
662             sub pmax {
663 1     1 0 6 my ($self, @vs) = @_;
664            
665 1         1 my @maxs;
666 1         3 for my $v (@vs) {
667 2         6 my $values = $v->values;
668 2         7 for (my $i = 0; $i <@$values; $i++) {
669 8 100 100     25 $maxs[$i] = $values->[$i]
670             if !defined $maxs[$i] || $values->[$i] > $maxs[$i]
671             }
672             }
673            
674 1         4 my $v_max = $self->c(\@maxs);
675            
676 1         3 return $v_max;
677             }
678              
679             sub pmin {
680 1     1 0 6 my ($self, @vs) = @_;
681            
682 1         2 my @mins;
683 1         3 for my $v (@vs) {
684 2         6 my $values = $v->values;
685 2         7 for (my $i = 0; $i <@$values; $i++) {
686 8 100 100     24 $mins[$i] = $values->[$i]
687             if !defined $mins[$i] || $values->[$i] < $mins[$i]
688             }
689             }
690            
691 1         3 my $v_min = $self->c(\@mins);
692            
693 1         3 return $v_min;
694             }
695              
696             sub expm1 {
697 2     2 0 422 my ($self, $_a1) = @_;
698            
699 2         5 my $a1 = $self->_to_a($_a1);
700            
701             my @a2_elements
702             = map {
703 4 100       67 Rstats::Util::double(
704             abs($_->value) < 1e-5
705             ? $_->value + 0.5 * $_->value * $_->value
706             : exp($_->value) - 1.0
707             )
708 2         4 } @{$a1->elements};
  2         26  
709            
710 2         16 my $a2 = $a1->clone_without_elements;
711 2         29 $a2->elements(\@a2_elements);
712 2         13 $a2->mode('double');
713            
714 2         5 return $a2;
715             }
716              
717             sub abs {
718 2     2 0 462 my ($self, $_a1) = @_;
719            
720 2         6 my $a1 = $self->_to_a($_a1);
721            
722 2         3 my @a2_elements = map { Rstats::Util::double(abs $_->value) } @{$a1->elements};
  4         65  
  2         27  
723            
724 2         14 my $a2 = $a1->clone_without_elements;
725 2         30 $a2->elements(\@a2_elements);
726 2         12 $a2->mode('double');
727            
728 2         4 return $a2;
729             }
730              
731             sub sum {
732 4     4 0 11 my ($self, $_v1) = @_;
733            
734 4         10 my $v1 = $self->_to_a($_v1);
735 4         10 my $v1_values = $v1->values;
736 4         15 my $sum = List::Util::sum(@$v1_values);
737 4         7 return $self->c($sum);
738             }
739              
740             sub prod {
741 1     1 0 7 my ($self, $v1) = @_;
742            
743 1         3 my $v1_values = $v1->values;
744 1         4 my $prod = List::Util::product(@$v1_values);
745 1         3 return $self->c($prod);
746             }
747              
748             sub mean {
749 2     2 0 7 my ($self, $data) = @_;
750            
751 2         3 my $v = $data;
752 2         5 my $mean = $self->sum($v)->value / $self->length($v);
753            
754 2         9 return $self->c($mean);
755             }
756              
757             sub var {
758 1     1 0 8 my ($self, $v1) = @_;
759              
760 1         4 my $var = $self->sum(($v1 - $self->mean($v1)) ** 2)->value
761             / ($self->length($v1) - 1);
762            
763 1         8 return $self->c($var);
764             }
765              
766             sub head {
767 3     3 0 15 my $self = shift;
768              
769 3 100       8 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
770 3         4 my $v1 = shift;
771            
772 3         5 my $n = $opt->{n};
773 3 100       6 $n = 6 unless defined $n;
774            
775 3         5 my $elements1 = $v1->{elements};
776 3 100       7 my $max = $self->length($v1) < $n ? $self->length($v1) : $n;
777 3         4 my @elements2;
778 3         8 for (my $i = 0; $i < $max; $i++) {
779 12         19 push @elements2, $elements1->[$i];
780             }
781            
782 3         8 return $v1->new(elements => \@elements2);
783             }
784              
785             sub tail {
786 3     3 0 12 my $self = shift;
787              
788 3 100       10 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
789 3         5 my $v1 = shift;
790            
791 3         4 my $n = $opt->{n};
792 3 100       7 $n = 6 unless defined $n;
793            
794 3         3 my $elements1 = $v1->{elements};
795 3 100       7 my $max = $self->length($v1) < $n ? $self->length($v1) : $n;
796 3         4 my @elements2;
797 3         8 for (my $i = 0; $i < $max; $i++) {
798 12         19 unshift @elements2, $elements1->[$self->length($v1) - ($i + 1)];
799             }
800            
801 3         8 return $v1->new(elements => \@elements2);
802             }
803              
804             sub trunc {
805 2     2 0 464 my ($self, $_a1) = @_;
806            
807 2         4 my $a1 = $self->_to_a($_a1);
808            
809 2         3 my @a2_elements = map { Rstats::Util::double(int $_->value) } @{$a1->elements};
  8         145  
  2         26  
810              
811 2         15 my $a2 = $a1->clone_without_elements;
812 2         30 $a2->elements(\@a2_elements);
813 2         13 $a2->mode('double');
814            
815 2         6 return $a2;
816             }
817              
818             sub floor {
819 2     2 0 448 my ($self, $_a1) = @_;
820            
821 2         4 my $a1 = $self->_to_a($_a1);
822            
823 2         3 my @a2_elements = map { Rstats::Util::double(POSIX::floor $_->value) } @{$a1->elements};
  8         134  
  2         29  
824              
825 2         15 my $a2 = $a1->clone_without_elements;
826 2         30 $a2->elements(\@a2_elements);
827 2         14 $a2->mode('double');
828            
829 2         6 return $a2;
830             }
831              
832             sub round {
833 7     7 0 2064 my $self = shift;
834              
835 7 100       18 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
836 7         10 my ($_a1, $digits) = @_;
837 7 100       15 $digits = $opt->{digits} unless defined $digits;
838 7 100       12 $digits = 0 unless defined $digits;
839            
840 7         13 my $a1 = $self->_to_a($_a1);
841              
842 7         17 my $r = 10 ** $digits;
843 7         9 my @a2_elements = map { Rstats::Util::double(Math::Round::round_even($_->value * $r) / $r) } @{$a1->elements};
  35         640  
  7         95  
844 7         51 my $a2 = $a1->clone_without_elements;
845 7         109 $a2->elements(\@a2_elements);
846 7         44 $a2->mode('double');
847            
848 7         37 return $a2;
849             }
850              
851             sub ceiling {
852 2     2 0 440 my ($self, $_a1) = @_;
853            
854 2         5 my $a1 = $self->_to_a($_a1);
855 2         3 my @a2_elements = map { Rstats::Util::double(POSIX::ceil $_->value) } @{$a1->elements};
  8         131  
  2         26  
856            
857 2         15 my $a2 = $a1->clone_without_elements;
858 2         32 $a2->elements(\@a2_elements);
859 2         14 $a2->mode('double');
860            
861 2         6 return $a2;
862             }
863              
864             sub log {
865 4     4 0 411 my ($self, $_a1) = @_;
866            
867 4         8 my $a1 = $self->_to_a($_a1);
868            
869 4         7 my @a2_elements = map { Rstats::Util::double(log $_->value) } @{$a1->elements};
  8         131  
  4         52  
870              
871 4         36 my $a2 = $a1->clone_without_elements;
872 4         58 $a2->elements(\@a2_elements);
873 4         25 $a2->mode('double');
874            
875 4         10 return $a2;
876             }
877              
878 2     2 0 442 sub logb { shift->log(@_) }
879              
880             sub log10 {
881 2     2 0 445 my ($self, $_a1) = @_;
882            
883 2         5 my $a1 = $self->_to_a($_a1);
884            
885 2         4 my @a2_elements = map { Rstats::Util::double(CORE::log $_->value / CORE::log 10) } @{$a1->elements};
  4         68  
  2         27  
886              
887 2         15 my $a2 = $a1->clone_without_elements;
888 2         29 $a2->elements(\@a2_elements);
889 2         12 $a2->mode('double');
890             }
891              
892             sub log2 {
893 2     2 0 443 my ($self, $_a1) = @_;
894            
895 2         29 my $a1 = $self->_to_a($_a1);
896            
897 2         4 my @a2_elements = map { Rstats::Util::double(CORE::log $_->value / CORE::log 2) } @{$a1->elements};
  4         66  
  2         27  
898              
899 2         13 my $a2 = $a1->clone_without_elements;
900 2         29 $a2->elements(\@a2_elements);
901 2         13 $a2->mode('double');
902            
903 2         5 return $a2;
904             }
905              
906             sub exp {
907 1     1 0 5 my ($self, $_a1) = @_;
908            
909 1         3 my $a1 = $self->_to_a($_a1);
910            
911 1         2 my @a2_elements = map { Rstats::Util::double(exp $_->value) } @{$a1->elements};
  3         57  
  1         14  
912              
913 1         15 my $a2 = $a1->clone_without_elements;
914 1         16 $a2->elements(\@a2_elements);
915 1         6 $a2->mode('double');
916            
917 1         2 return $a2;
918             }
919              
920             sub sin {
921 2     2 0 420 my ($self, $_a1) = @_;
922            
923 2         5 my $a1 = $self->_to_a($_a1);
924            
925 2         4 my @a2_elements = map { Rstats::Util::double(sin $_->value) } @{$a1->elements};
  4         68  
  2         27  
926              
927 2         15 my $a2 = $a1->clone_without_elements;
928 2         29 $a2->elements(\@a2_elements);
929 2         14 $a2->mode('double');
930            
931 2         5 return $a2;
932             }
933              
934             sub cos {
935 2     2 0 489 my ($self, $_a1) = @_;
936            
937 2         5 my $a1 = $self->_to_a($_a1);
938            
939 2         3 my @a2_elements = map { Rstats::Util::double(cos $_->value) } @{$a1->elements};
  4         66  
  2         27  
940              
941 2         34 my $a2 = $a1->clone_without_elements;
942 2         34 $a2->elements(\@a2_elements);
943 2         12 $a2->mode('double');
944            
945 2         6 return $a2;
946             }
947              
948             sub tan {
949 2     2 0 1169 my ($self, $_a1) = @_;
950            
951 2         5 my $a1 = $self->_to_a($_a1);
952            
953 2         4 my @a2_elements = map { Rstats::Util::double(Math::Trig::tan $_->value) } @{$a1->elements};
  4         73  
  2         27  
954              
955 2         15 my $a2 = $a1->clone_without_elements;
956 2         31 $a2->elements(\@a2_elements);
957 2         13 $a2->mode('double');
958            
959 2         5 return $a2;
960             }
961              
962             sub asinh {
963 2     2 0 496 my ($self, $_a1) = @_;
964            
965 2         5 my $a1 = $self->_to_a($_a1);
966            
967 2         3 my @a2_elements = map { Rstats::Util::double(Math::Trig::asinh $_->value) } @{$a1->elements};
  4         119  
  2         40  
968              
969 2         16 my $a2 = $a1->clone_without_elements;
970 2         30 $a2->elements(\@a2_elements);
971 2         13 $a2->mode('double');
972            
973 2         5 return $a2;
974             }
975              
976             sub acosh {
977 2     2 0 2179 my ($self, $_a1) = @_;
978            
979 2         6 my $a1 = $self->_to_a($_a1);
980            
981 2         3 my @a2_elements = map { Rstats::Util::double(Math::Trig::acosh $_->value) } @{$a1->elements};
  4         71  
  2         26  
982              
983 2         16 my $a2 = $a1->clone_without_elements;
984 2         32 $a2->elements(\@a2_elements);
985 2         13 $a2->mode('double');
986            
987 2         5 return $a2;
988             }
989              
990             sub atanh {
991 2     2 0 424 my ($self, $_a1) = @_;
992            
993 2         5 my $a1 = $self->_to_a($_a1);
994            
995 2         3 my @a2_elements = map { Rstats::Util::double(Math::Trig::atanh $_->value) } @{$a1->elements};
  4         82  
  2         27  
996              
997 2         21 my $a2 = $a1->clone_without_elements;
998 2         34 $a2->elements(\@a2_elements);
999 2         14 $a2->mode('double');
1000            
1001 2         5 return $a2;
1002             }
1003              
1004             sub asin {
1005 2     2 0 1140 my ($self, $_a1) = @_;
1006            
1007 2         4 my $a1 = $self->_to_a($_a1);
1008            
1009 2         3 my @a2_elements = map { Rstats::Util::double(Math::Trig::asin $_->value) } @{$a1->elements};
  4         74  
  2         27  
1010              
1011 2         24 my $a2 = $a1->clone_without_elements;
1012 2         38 $a2->elements(\@a2_elements);
1013 2         14 $a2->mode('double');
1014            
1015 2         5 return $a2;
1016             }
1017              
1018             sub acos {
1019 2     2 0 421 my ($self, $_a1) = @_;
1020            
1021 2         4 my $a1 = $self->_to_a($_a1);
1022            
1023 2         3 my @a2_elements = map { Rstats::Util::double(Math::Trig::acos $_->value) } @{$a1->elements};
  4         75  
  2         35  
1024              
1025 2         16 my $a2 = $a1->clone_without_elements;
1026 2         33 $a2->elements(\@a2_elements);
1027 2         13 $a2->mode('double');
1028            
1029 2         5 return $a2;
1030             }
1031              
1032             sub atan {
1033 2     2 0 488 my ($self, $_a1) = @_;
1034            
1035 2         6 my $a1 = $self->_to_a($_a1);
1036            
1037 2         5 my @a2_elements = map { Rstats::Util::double(Math::Trig::atan $_->value) } @{$a1->elements};
  4         69  
  2         27  
1038              
1039 2         15 my $a2 = $a1->clone_without_elements;
1040 2         31 $a2->elements(\@a2_elements);
1041 2         12 $a2->mode('double');
1042            
1043 2         5 return $a2;
1044             }
1045              
1046             sub sinh {
1047 2     2 0 428 my ($self, $_a1) = @_;
1048            
1049 2         5 my $a1 = $self->_to_a($_a1);
1050            
1051 2         3 my @a2_elements = map { Rstats::Util::double(Math::Trig::sinh $_->value) } @{$a1->elements};
  4         71  
  2         35  
1052              
1053 2         15 my $a2 = $a1->clone_without_elements;
1054 2         31 $a2->elements(\@a2_elements);
1055 2         13 $a2->mode('double');
1056            
1057 2         5 return $a2;
1058             }
1059              
1060             sub cosh {
1061 2     2 0 502 my ($self, $_a1) = @_;
1062            
1063 2         5 my $a1 = $self->_to_a($_a1);
1064            
1065 2         4 my @a2_elements = map { Rstats::Util::double(Math::Trig::cosh $_->value) } @{$a1->elements};
  4         69  
  2         27  
1066              
1067 2         13 my $a2 = $a1->clone_without_elements;
1068 2         31 $a2->elements(\@a2_elements);
1069 2         13 $a2->mode('double');
1070            
1071 2         6 return $a2;
1072             }
1073              
1074             sub tanh {
1075 2     2 0 438 my ($self, $_a1) = @_;
1076            
1077 2         6 my $a1 = $self->_to_a($_a1);
1078            
1079 2         3 my @a2_elements = map { Rstats::Util::double(Math::Trig::tanh $_->value) } @{$a1->elements};
  4         69  
  2         26  
1080              
1081 2         14 my $a2 = $a1->clone_without_elements;
1082 2         31 $a2->elements(\@a2_elements);
1083 2         12 $a2->mode('double');
1084            
1085 2         6 return $a2;
1086             }
1087              
1088             sub sqrt {
1089 2     2 0 408 my ($self, $_a1) = @_;
1090            
1091 2         5 my $a1 = $self->_to_a($_a1);
1092            
1093 2         4 my @a2_elements = map { Rstats::Util::double(sqrt $_->value) } @{$a1->elements};
  6         100  
  2         27  
1094            
1095 2         15 my $a2 = $a1->clone_without_elements;
1096 2         31 $a2->elements(\@a2_elements);
1097 2         11 $a2->mode('double');
1098            
1099 2         5 return $a2;
1100             }
1101              
1102             sub range {
1103 1     1 0 6 my ($self, $array) = @_;
1104            
1105 1         3 my $min = $self->min($array);
1106 1         3 my $max = $self->max($array);
1107            
1108 1         17 return $self->c([$min, $max]);
1109             }
1110              
1111             sub i {
1112 0     0 0 0 my $self = shift;
1113            
1114 0         0 my $i = Rstats::Type::Complex->new(re => 0, im => 1);
1115            
1116 0         0 return $i;
1117             }
1118              
1119             sub length {
1120 194     194 0 261 my $self = shift;
1121 194         180 my $v1 = shift;
1122            
1123 194         269 return $v1->length;
1124             }
1125              
1126             sub sort {
1127 2     2 0 11 my $self = shift;
1128              
1129 2 100       8 my $opt = ref $_[-1] eq 'HASH' ? pop @_ : {};
1130 2         3 my $decreasing = $opt->{decreasing};
1131 2         3 my $_v1 = shift;
1132            
1133 2         5 my $v1 = $self->_to_a($_v1);
1134 2         5 my $v1_values = $v1->values;
1135 2 100       10 my $v2_values = $decreasing ? [reverse sort(@$v1_values)] : [sort(@$v1_values)];
1136 2         5 return $self->c($v2_values);
1137             }
1138              
1139             1;
1140              
1141             =head1 NAME
1142              
1143             Rstats - R language build on Perl
1144              
1145             =head1 SYNOPSYS
1146            
1147             use Rstats;
1148             my $r = Rstats->new;
1149            
1150             # Array
1151             my $v1 = $r->c([1, 2, 3]);
1152             my $v2 = $r->c([2, 3, 4]);
1153             my $v3 = $v1 + v2;
1154             print $v3;