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   846121 use 5.010;
  4         32  
6 4     4   20 use strict;
  4         6  
  4         93  
7 4     4   18 use warnings;
  4         7  
  4         154  
8              
9             our $VERSION = '0.0003'; # VERSION
10              
11 4     4   1509 use PDL::Lite ();
  4         393178  
  4         106  
12 4     4   32 use PDL::Primitive qw(which);
  4         7  
  4         24  
13 4     4   309 use PDL::Types;
  4         8  
  4         402  
14              
15 4     4   804 use Safe::Isa;
  4         927  
  4         365  
16 4     4   28 use Scalar::Util qw(blessed);
  4         8  
  4         173  
17 4     4   24 use Test2::API qw(context);
  4         8  
  4         150  
18 4     4   24 use Test2::Compare qw(compare strict_convert);
  4         7  
  4         165  
19 4     4   54 use Test2::Util::Table qw(table);
  4         10  
  4         38  
20 4     4   236 use Test2::Util::Ref qw(render_ref);
  4         8  
  4         191  
21              
22 4     4   1559 use parent qw/Exporter/;
  4         1103  
  4         21  
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 6752 my ( $thing, $name ) = @_;
31 3         8 my $ctx = context();
32              
33 3 100       195 unless ( $thing->$_isa('PDL') ) {
34 2         19 my $thingname = render_ref($thing);
35 2         36 $ctx->ok( 0, $name, ["'$thingname' is not a piddle."] );
36 2         915 $ctx->release;
37 2         42 return 0;
38             }
39              
40 1         25 $ctx->ok( 1, $name );
41 1         93 $ctx->release;
42 1         30 return 1;
43             }
44              
45              
46             sub pdl_is {
47 12     12 1 17550 my ( $got, $exp, $name, @diag ) = @_;
48 12         29 my $ctx = context();
49              
50 12         776 my $gotname = render_ref($got);
51 12 100       286 unless ( $got->$_isa('PDL') ) {
52 2         21 $ctx->ok( 0, $name, ["First argument '$gotname' is not a piddle."] );
53 2         821 $ctx->release;
54 2         41 return 0;
55             }
56 10 50       119 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 10         98 my $exp_class = ref($exp);
64 10 50       21 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 10         23 my @exp_dims = $exp->dims;
73 10         213 my @got_dims = $got->dims;
74 10         150 my $delta_dims = compare( \@got_dims, \@exp_dims, \&strict_convert );
75              
76 10 100       2927 if ($delta_dims) {
77 2         15 $ctx->ok( 0, $name,
78             [ $delta_dims->table, 'Dimensions do not match', @diag ] );
79 2         10609 $ctx->release;
80 2         57 return 0;
81             }
82              
83             # compare isbad
84 8         10 my $both_bad;
85 8 100 66     45 if ( $got->badflag or $exp->badflag ) {
86 3         32 my $delta_isbad =
87             compare( $got->isbad->unpdl, $exp->isbad->unpdl, \&strict_convert );
88              
89 3 100       2733 if ($delta_isbad) {
90 1         5 $ctx->ok(
91             0, $name,
92             [
93             $delta_isbad->table, 'Bad value patterns do not match',
94             @diag
95             ]
96             );
97 1         4335 $ctx->release;
98 1         27 return 0;
99             }
100              
101 2         48 $both_bad = ( $got->isbad & $exp->isbad );
102             }
103              
104             # Compare data values.
105 7         15 my $diff;
106             my $is_numeric = !(
107 21     21   176 List::Util::any { $exp->$_isa($_) }
108 7   33     43 qw(PDL::SV PDL::Factor PDL::DateTime) or $exp->type eq 'byte'
109             );
110 7         407 eval {
111 7 50 33     23 if ( $is_numeric
      33        
112             and ( $exp->type >= PDL::float or $got->type >= PDL::float ) )
113             {
114 7         547 $diff = (($got - $exp)->abs > $TOLERANCE + $TOLERANCE_REL * $exp);
115             }
116             else {
117 0         0 $diff = ( $got != $exp );
118             }
119 7 100       74 if ( $exp->badflag ) {
120 2         17 $diff->where( $exp->isbad ) .= 0;
121             }
122             };
123 7 50       171 if ($@) {
124 0         0 my $gotname = render_ref($got);
125 0         0 $ctx->ok( 0, $name, [ "Error occurred during values comparison.", $@ ],
126             @diag );
127 0         0 $ctx->release;
128 0         0 return 0;
129             }
130 7         21 my $diff_which = which($diff);
131 7 100       237 unless ( $diff_which->isempty ) {
132             state $at = sub {
133 10     10   258 my ( $p, @position ) = @_;
134 10 50       37 if ( $p->isa('PDL::DateTime') ) {
135 0         0 return $p->dt_at(@position);
136             }
137             else {
138 10         18 return $p->at(@position);
139             }
140 2         14 };
141              
142 2         7 my $gotname = render_ref($got);
143             my @table = table(
144             sanitize => 1,
145             max_width => 80,
146             collapse => 1,
147             header => [qw(POSITION GOT CHECK)],
148             rows => [
149             map {
150 5         133 my @position = $exp->one2nd($_);
151             [
152 5         659 join( ',', @position ),
153             $at->( $got, @position ),
154             $at->( $exp, @position )
155             ]
156 2         53 } @{ $diff_which->unpdl }
  2         6  
157             ]
158             );
159 2         6805 $ctx->ok( 0, $name, [ "Values do not match.", @table ], @diag );
160 2         2656 $ctx->release;
161 2         54 return 0;
162             }
163              
164 5         40 $ctx->ok( 1, $name );
165 5         319 $ctx->release;
166 5         122 return 1;
167             }
168              
169             1;
170              
171             __END__