File Coverage

blib/lib/Test2/Tools/PDL.pm
Criterion Covered Total %
statement 99 112 88.3
branch 19 24 79.1
condition 5 12 41.6
subroutine 17 17 100.0
pod 2 2 100.0
total 142 167 85.0


line stmt bran cond sub pod time code
1             package Test2::Tools::PDL;
2              
3             # ABSTRACT: Test2 tools for verifying Perl Data Language piddles
4              
5 4     4   1046774 use 5.010;
  4         37  
6 4     4   26 use strict;
  4         5  
  4         78  
7 4     4   22 use warnings;
  4         8  
  4         162  
8              
9             our $VERSION = '0.0005'; # VERSION
10              
11 4     4   1877 use PDL::Lite ();
  4         447263  
  4         134  
12 4     4   35 use PDL::Primitive qw(which);
  4         11  
  4         28  
13 4     4   373 use PDL::Types;
  4         10  
  4         490  
14              
15 4     4   1906 use Safe::Isa;
  4         2066  
  4         426  
16 4     4   31 use Scalar::Util qw(blessed);
  4         9  
  4         229  
17 4     4   40 use Test2::API 1.302175 qw(context);
  4         99  
  4         242  
18 4     4   33 use Test2::Compare 0.000130 qw(compare strict_convert);
  4         85  
  4         263  
19 4     4   33 use Test2::Util::Table qw(table);
  4         8  
  4         54  
20 4     4   261 use Test2::Util::Ref qw(render_ref);
  4         11  
  4         284  
21              
22 4     4   1940 use parent qw/Exporter/;
  4         1259  
  4         30  
23             our @EXPORT = qw(pdl_ok pdl_is);
24              
25             our $TOLERANCE = $Test2::Compare::Float::DEFAULT_TOLERANCE;
26             our $TOLERANCE_REL = 0;
27              
28              
29             sub pdl_ok {
30 4     4 1 6924 my ( $thing, $name ) = @_;
31 4         11 my $ctx = context();
32              
33 4 100       358 unless ( $thing->$_isa('PDL') ) {
34 2         24 my $thingname = render_ref($thing);
35 2         60 $ctx->fail( $name, "'$thingname' is not a piddle." );
36 2         556 $ctx->release;
37 2         56 return 0;
38             }
39              
40 2         50 $ctx->ok( 1, $name );
41 2         215 $ctx->release;
42 2         67 return 1;
43             }
44              
45              
46             sub pdl_is {
47 14     14 1 41409 my ( $got, $exp, $name, @diag ) = @_;
48 14         40 my $ctx = context();
49              
50 14         1302 my $gotname = render_ref($got);
51 14 100       426 unless ( $got->$_isa('PDL') ) {
52 2         29 $ctx->fail( $name, "First argument '$gotname' is not a piddle." );
53 2         372 $ctx->release;
54 2         52 return 0;
55             }
56 12 50       186 unless ( $exp->$_isa('PDL') ) {
57 0         0 my $expname = render_ref($exp);
58 0         0 $ctx->fail( $name, "Second argument '$expname' is not a piddle." );
59 0         0 $ctx->release;
60 0         0 return 0;
61             }
62              
63 12         139 my $exp_class = ref($exp);
64 12 50       35 if ( ref($got) ne $exp_class ) {
65 0         0 $ctx->fail( $name,
66             "'$gotname' does not match the expected type '$exp_class'." );
67 0         0 $ctx->release;
68 0         0 return 0;
69             }
70              
71             # compare dimensions
72 12         37 my @exp_dims = $exp->dims;
73 12         330 my @got_dims = $got->dims;
74 12         228 my $delta_dims = compare( \@got_dims, \@exp_dims, \&strict_convert );
75              
76 12 100       4371 if ($delta_dims) {
77 2         9 $ctx->fail( $name, 'Dimensions do not match', $delta_dims->diag,
78             @diag );
79 2         10991 $ctx->release;
80 2         73 return 0;
81             }
82              
83             # compare isbad
84 10         18 my $both_bad;
85 10 100 66     72 if ( $got->badflag or $exp->badflag ) {
86 3         62 my $delta_isbad =
87             compare( $got->isbad->unpdl, $exp->isbad->unpdl, \&strict_convert );
88              
89 3 100       3472 if ($delta_isbad) {
90 1         6 $ctx->fail( $name, 'Bad value patterns do not match',
91             $delta_isbad->diag, @diag );
92 1         4395 $ctx->release;
93 1         37 return 0;
94             }
95              
96 2         49 $both_bad = ( $got->isbad & $exp->isbad );
97             }
98              
99             # Compare data values.
100 9         24 my $diff;
101             my $is_numeric = !(
102 27     27   270 List::Util::any { $exp->$_isa($_) }
103 9   33     57 qw(PDL::SV PDL::Factor PDL::DateTime) or $exp->type eq 'byte'
104             );
105 9         686 eval {
106 9 50 33     42 if ( $is_numeric
      33        
107             and ( $exp->type >= PDL::float or $got->type >= PDL::float ) )
108             {
109 9         952 $diff = ( ( $got - $exp )->abs >
110             $TOLERANCE + ( $TOLERANCE_REL * $exp )->abs );
111             }
112             else {
113 0         0 $diff = ( $got != $exp );
114             }
115 9 100       135 if ( $exp->badflag ) {
116 2         24 $diff->where( $exp->isbad ) .= 0;
117             }
118             };
119 9 50       241 if ($@) {
120 0         0 my $gotname = render_ref($got);
121 0         0 $ctx->fail( $name, "Error occurred during values comparison.",
122             $@, @diag );
123 0         0 $ctx->release;
124 0         0 return 0;
125             }
126 9         35 my $diff_which = which($diff);
127 9 100       390 unless ( $diff_which->isempty ) {
128             state $at = sub {
129 6     6   223 my ( $p, @position ) = @_;
130 6 50       29 if ( $p->isa('PDL::DateTime') ) {
131 0         0 return $p->dt_at(@position);
132             }
133             else {
134 6         15 return $p->at(@position);
135             }
136 2         25 };
137              
138 2         18 my $gotname = render_ref($got);
139             my @table = table(
140             sanitize => 1,
141             max_width => 80,
142             collapse => 1,
143             header => [qw(POSITION GOT CHECK)],
144             rows => [
145             map {
146 3         108 my @position = $exp->one2nd($_);
147             [
148 3         671 join( ',', @position ),
149             $at->( $got, @position ),
150             $at->( $exp, @position )
151             ]
152 2         104 } @{ $diff_which->unpdl }
  2         11  
153             ]
154             );
155 2         6383 $ctx->fail( $name, "Values do not match.", join( "\n", @table ),
156             @diag );
157 2         476 $ctx->release;
158 2         67 return 0;
159             }
160              
161 7         75 $ctx->ok( 1, $name );
162 7         572 $ctx->release;
163 7         228 return 1;
164             }
165              
166             1;
167              
168             __END__