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   1007644 use 5.010;
  4         36  
6 4     4   29 use strict;
  4         8  
  4         87  
7 4     4   18 use warnings;
  4         9  
  4         144  
8              
9             our $VERSION = '0.0004'; # VERSION
10              
11 4     4   1829 use PDL::Lite ();
  4         439849  
  4         116  
12 4     4   35 use PDL::Primitive qw(which);
  4         8  
  4         25  
13 4     4   335 use PDL::Types;
  4         15  
  4         452  
14              
15 4     4   918 use Safe::Isa;
  4         967  
  4         397  
16 4     4   28 use Scalar::Util qw(blessed);
  4         9  
  4         202  
17 4     4   31 use Test2::API qw(context);
  4         8  
  4         199  
18 4     4   30 use Test2::Compare qw(compare strict_convert);
  4         9  
  4         183  
19 4     4   25 use Test2::Util::Table qw(table);
  4         10  
  4         47  
20 4     4   255 use Test2::Util::Ref qw(render_ref);
  4         8  
  4         206  
21              
22 4     4   1951 use parent qw/Exporter/;
  4         1280  
  4         23  
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 3     3 1 10429 my ( $thing, $name ) = @_;
31 3         10 my $ctx = context();
32              
33 3 100       248 unless ( $thing->$_isa('PDL') ) {
34 2         30 my $thingname = render_ref($thing);
35 2         56 $ctx->ok( 0, $name, ["'$thingname' is not a piddle."] );
36 2         1191 $ctx->release;
37 2         52 return 0;
38             }
39              
40 1         53 $ctx->ok( 1, $name );
41 1         168 $ctx->release;
42 1         47 return 1;
43             }
44              
45              
46             sub pdl_is {
47 13     13 1 23162 my ( $got, $exp, $name, @diag ) = @_;
48 13         37 my $ctx = context();
49              
50 13         1065 my $gotname = render_ref($got);
51 13 100       426 unless ( $got->$_isa('PDL') ) {
52 2         28 $ctx->ok( 0, $name, ["First argument '$gotname' is not a piddle."] );
53 2         1040 $ctx->release;
54 2         52 return 0;
55             }
56 11 50       176 unless ( $exp->$_isa('PDL') ) {
57 0         0 my $expname = render_ref($exp);
58 0         0 $ctx->ok( 0, $name, ["Second argument '$expname' is not a piddle."] );
59 0         0 $ctx->release;
60 0         0 return 0;
61             }
62              
63 11         124 my $exp_class = ref($exp);
64 11 50       33 if ( ref($got) ne $exp_class ) {
65 0         0 $ctx->ok( 0, $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 11         43 my @exp_dims = $exp->dims;
73 11         309 my @got_dims = $got->dims;
74 11         209 my $delta_dims = compare( \@got_dims, \@exp_dims, \&strict_convert );
75              
76 11 100       4086 if ($delta_dims) {
77 2         10 $ctx->ok( 0, $name,
78             [ $delta_dims->table, 'Dimensions do not match', @diag ] );
79 2         12109 $ctx->release;
80 2         70 return 0;
81             }
82              
83             # compare isbad
84 9         15 my $both_bad;
85 9 100 66     71 if ( $got->badflag or $exp->badflag ) {
86 3         80 my $delta_isbad =
87             compare( $got->isbad->unpdl, $exp->isbad->unpdl, \&strict_convert );
88              
89 3 100       3391 if ($delta_isbad) {
90 1         7 $ctx->ok(
91             0, $name,
92             [
93             $delta_isbad->table, 'Bad value patterns do not match',
94             @diag
95             ]
96             );
97 1         4745 $ctx->release;
98 1         32 return 0;
99             }
100              
101 2         79 $both_bad = ( $got->isbad & $exp->isbad );
102             }
103              
104             # Compare data values.
105 8         29 my $diff;
106             my $is_numeric = !(
107 24     24   247 List::Util::any { $exp->$_isa($_) }
108 8   33     48 qw(PDL::SV PDL::Factor PDL::DateTime) or $exp->type eq 'byte'
109             );
110 8         612 eval {
111 8 50 33     31 if ( $is_numeric
      33        
112             and ( $exp->type >= PDL::float or $got->type >= PDL::float ) )
113             {
114 8         877 $diff = ( ( $got - $exp )->abs >
115             $TOLERANCE + ( $TOLERANCE_REL * $exp )->abs );
116             }
117             else {
118 0         0 $diff = ( $got != $exp );
119             }
120 8 100       108 if ( $exp->badflag ) {
121 2         43 $diff->where( $exp->isbad ) .= 0;
122             }
123             };
124 8 50       246 if ($@) {
125 0         0 my $gotname = render_ref($got);
126 0         0 $ctx->ok( 0, $name, [ "Error occurred during values comparison.", $@ ],
127             @diag );
128 0         0 $ctx->release;
129 0         0 return 0;
130             }
131 8         44 my $diff_which = which($diff);
132 8 100       388 unless ( $diff_which->isempty ) {
133             state $at = sub {
134 10     10   343 my ( $p, @position ) = @_;
135 10 50       42 if ( $p->isa('PDL::DateTime') ) {
136 0         0 return $p->dt_at(@position);
137             }
138             else {
139 10         24 return $p->at(@position);
140             }
141 2         24 };
142              
143 2         7 my $gotname = render_ref($got);
144             my @table = table(
145             sanitize => 1,
146             max_width => 80,
147             collapse => 1,
148             header => [qw(POSITION GOT CHECK)],
149             rows => [
150             map {
151 5         179 my @position = $exp->one2nd($_);
152             [
153 5         934 join( ',', @position ),
154             $at->( $got, @position ),
155             $at->( $exp, @position )
156             ]
157 2         83 } @{ $diff_which->unpdl }
  2         13  
158             ]
159             );
160 2         8393 $ctx->ok( 0, $name, [ "Values do not match.", @table ], @diag );
161 2         3176 $ctx->release;
162 2         90 return 0;
163             }
164              
165 6         60 $ctx->ok( 1, $name );
166 6         490 $ctx->release;
167 6         185 return 1;
168             }
169              
170             1;
171              
172             __END__