File Coverage

blib/lib/Test/PDL.pm
Criterion Covered Total %
statement 93 150 62.0
branch 41 48 85.4
condition 17 17 100.0
subroutine 30 31 96.7
pod 5 5 100.0
total 186 251 74.1


line stmt bran cond sub pod time code
1             package Test::PDL;
2             $Test::PDL::VERSION = '0.13';
3             # ABSTRACT: Test Perl Data Language arrays (a.k.a. piddles) for equality
4              
5              
6 6     6   807045 use strict;
  6     1   12  
  6     1   1480  
  0     1      
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
7 6     6   25 use warnings;
  6     1   10  
  6     1   158  
  0     1      
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
8 6     6   2417 use PDL::Lite;
  6     1   246429  
  6     1   148  
  0     0      
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
9 6     6   34 use PDL::Types ();
  6     1   7  
  6     1   111  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
10              
11 6     6   21 use base qw( Exporter );
  6     1   7  
  6     1   5836  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
12             our @EXPORT = qw( is_pdl );
13             our @EXPORT_OK = qw( eq_pdl eq_pdl_diag is_pdl test_pdl );
14             our %EXPORT_TAGS = ( deep => [ qw( test_pdl ) ] );
15              
16              
17             our %OPTIONS = (
18             TOLERANCE => 1e-6,
19             EQUAL_TYPES => 1,
20             );
21              
22              
23             sub import
24             {
25 6     6   1887 my $i = 0;
26 6         23 while( $i < @_ ) {
27 12 50       49 if( $_[ $i ] =~ /^-/ ) {
28 1         3 my( $key, $val ) = splice @_, $i, 2;
29 1         1 $key =~ s/^-(.*)/\U$1/;
30 1         20 set_options( $key, $val );
31             }
32 12         32 else { $i++ }
33             }
34 6         785 __PACKAGE__->export_to_level( 1, @_ );
35             }
36              
37              
38             sub _approx
39             {
40 65     65   91 my( $a, $b ) = @_;
41 65         1279 return abs( $a - $b ) < $OPTIONS{ TOLERANCE };
42             }
43              
44              
45             sub _comparison_fails
46             {
47 161     161   181 my ( $got, $expected ) = @_;
48 161 100       184 if( not eval { $got->isa('PDL') } ) {
  161         670  
49 11         44 return 'received value is not a piddle';
50             }
51 151 100       1048 if( not eval { $expected->isa('PDL') } ) {
  151         438  
52 6         19 return 'expected value is not a piddle';
53             }
54 146 100 100     709 if( $OPTIONS{ EQUAL_TYPES } && $got->type != $expected->type ) {
55 7         1950 return 'types do not match (EQUAL_TYPES is true)';
56             }
57 140 100       3465 if( $got->ndims != $expected->ndims ) {
58 7         38 return 'dimensions do not match in number';
59             }
60 134 100       359 if( not _dimensions_match( [$got->dims], [$expected->dims] ) ) {
61 4         26 return 'dimensions do not match in extent';
62             }
63             # evaluating these only makes sense for piddles that conform in shape
64 131 100 100     891 if( ( $got->badflag == 1 || $expected->badflag == 1 ) &&
      100        
65 79         1894 not eval { PDL::all( PDL::isbad($got) == PDL::isbad($expected) ) } ) {
66 4         162 return 'bad value patterns do not match';
67             }
68             # if we get here, bad value patterns are sure to match
69 128 100 100     3716 if( $got->type < PDL::float && $expected->type < PDL::float ) {
70 64 100       2870 if( not eval { PDL::all( $got == $expected ) } ) {
  64         672  
71 4         143 return 'values do not match';
72             }
73             }
74             else {
75             # floating-point comparison must be approximate
76 65 100       1939 if( not eval { PDL::all( _approx $got, $expected ) } ) {
  65         115  
77 25         4132 return 'values do not match';
78             }
79             }
80             # if we get here, we didn't fail
81 101         5009 return 0;
82             }
83              
84              
85             sub _dimensions_match
86             {
87 134     134   3709 my @A = @{ +shift };
  134         410  
88 134         1865 my @B = @{ +shift };
  134         170  
89 134   100     621 while( my $a = shift @A and my $b = shift @B ) {
90 101 100       368 if( $a != $b ) { return 0 }
  4         14  
91             }
92 131         317 return 1;
93             }
94              
95              
96             sub is_pdl
97             {
98 27     27 1 14432 require Test::Builder;
99 27         38 my ( $got, $expected, $name ) = @_;
100 27         76 my $tb = Test::Builder->new;
101 27 100       111 if( eval { $name->isa('PDL') } ) {
  27 0       216  
102 2         32 $tb->croak( 'error in arguments: test name is a piddle' );
103             }
104 26   100     106 $name ||= "piddles are equal";
105 26 100       42 if( my $reason = _comparison_fails $got, $expected ) {
106 16         984 my $rc = $tb->ok( 0, $name );
107 16         5515 my $fmt = '%-8T %-12D (%-5S) ';
108             $tb->diag( " $reason\n",
109 16 100       344 " got: ", eval { $got->isa('PDL') && !$got->isnull } ? $got->info( $fmt ) : '', $got, "\n",
    0          
110 16 100       29 " expected: ", eval { $expected->isa('PDL') && !$expected->isnull } ? $expected->info( $fmt ) : '', $expected );
  16 100       3415  
    100          
    0          
111 16         4260 return $rc;
112             }
113             else {
114 11         48 return $tb->ok( 1, $name );
115             }
116             }
117              
118              
119             sub eq_pdl
120             {
121 31     31 1 7271 my ( $got, $expected ) = @_;
122 31         55 return !_comparison_fails( $got, $expected );
123             }
124              
125              
126             sub eq_pdl_diag
127             {
128 106     106 1 61753 my ( $got, $expected ) = @_;
129 106         196 my $reason = _comparison_fails( $got, $expected );
130 106 100       329 if( $reason ) { return 0, $reason }
  25         110  
131 82         223 else { return 1 }
132             }
133              
134              
135             sub test_pdl
136             {
137 29     29 1 19328 require Test::Deep::PDL;
138 29         121 my $expected = pdl( @_ );
139 29         1653 return Test::Deep::PDL->new( $expected );
140             }
141              
142              
143             for my $type ( PDL::Types::types ) {
144             my $sub = sub {
145 33     33   46694 require Test::Deep::PDL;
146 33 100       1074 my $expected = PDL::convert(
147             PDL::Core::alltopdl( 'PDL', scalar(@_) > 1 ? [@_] : shift ),
148             $type->numval
149             );
150 33         2176 return Test::Deep::PDL->new( $expected );
151             };
152             my $sub_name = 'test_' . $type->convertfunc;
153             {
154 6     6   44 no strict 'refs';
  6     1   12  
  6     1   1056  
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
  0            
155             *$sub_name = $sub;
156             }
157             push @EXPORT_OK, $sub_name;
158             push @{ $EXPORT_TAGS{deep} }, $sub_name;
159             }
160              
161              
162             sub set_options
163             {
164 34     34 1 21346 while( my( $key, $value ) = splice @_, 0, 2 ) {
165 35 100       273 barf( "invalid option $key" ) unless grep { $key eq $_ } keys %OPTIONS;
  68         177  
166 33 100       79 barf( "undefined value for $key" ) unless defined $value;
167 32         163 $OPTIONS{ $key } = $value;
168             }
169             }
170              
171              
172             1;
173              
174             __END__