File Coverage

blib/lib/MooX/PDL2.pm
Criterion Covered Total %
statement 25 25 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 34 34 100.0


line stmt bran cond sub pod time code
1             package MooX::PDL2;
2              
3             # ABSTRACT: A Moo based PDL 2.X object
4              
5 5     5   551349 use strict;
  5         14  
  5         121  
6 5     5   22 use warnings;
  5         10  
  5         169  
7              
8             our $VERSION = '0.01';
9              
10 5     5   22 use Scalar::Util qw[ blessed weaken ];
  5         9  
  5         198  
11 5     5   1365 use PDL::Lite;
  5         429980  
  5         39  
12 5     5   541 use Carp;
  5         21  
  5         210  
13              
14 5     5   1808 use Moo;
  5         32329  
  5         29  
15 5     5   7013 use MooX::ProtectedAttributes;
  5         2573  
  5         27  
16              
17 5     5   2119 use namespace::clean;
  5         43647  
  5         34  
18              
19             # do not simply extend PDL on its own.
20              
21             # We want a standard Moo constructor, but everything else from
22             # PDL. PDLx::DetachedObject gives us
23             #
24             # * PDL inheritance;
25             # * a generic initializer() class method; and
26             # * a constructor.
27             #
28             # The constructor is ignored by Moo as Moo::Object is the first
29             # in the inheritance chain and it ignores upstream constructors.
30              
31             extends 'Moo::Object', 'PDLx::DetachedObject';
32              
33             #pod =attr _PDL
34             #pod
35             #pod The actual piddle associated with an object. B<PDL> routines
36             #pod will transparently uses this when passed an object.
37             #pod
38             #pod This attribute is
39             #pod
40             #pod =over
41             #pod
42             #pod =item *
43             #pod
44             #pod lazy
45             #pod
46             #pod =item *
47             #pod
48             #pod has a builder which returns C<< PDL->null >>
49             #pod
50             #pod =item *
51             #pod
52             #pod will coerce its argument to be a piddle
53             #pod
54             #pod =item *
55             #pod
56             #pod has a clearer
57             #pod
58             #pod =back
59             #pod
60             #pod See L</EXAMPLES> for fun ways of combining it with Moo's facilities.
61             #pod
62             #pod =cut
63              
64             protected_has _PDL => (
65             is => 'lazy',
66             isa => sub {
67             blessed $_[0] && blessed $_[0] eq 'PDL'
68             or croak( "_PDL attribute must be of class 'PDL'" );
69             },
70             coerce => sub { PDL->topdl( $_[0] ) },
71 6     6   326 builder => sub { PDL->null },
72             clearer => 1,
73             );
74              
75             protected_has PDL => (
76             is => 'ro',
77             init_arg => undef,
78             default => sub {
79             my $self = shift;
80             weaken $self;
81             sub { $self->_PDL };
82             },
83             );
84              
85             namespace::clean->clean_subroutines( __PACKAGE__, 'PDL' );
86              
87             #pod =method new
88             #pod
89             #pod # null value
90             #pod $pdl = MooX::PDL2->new;
91             #pod
92             #pod
93             #pod =cut
94              
95             1;
96              
97             #
98             # This file is part of MooX-PDL2
99             #
100             # This software is Copyright (c) 2017 by Smithsonian Astrophysical Observatory.
101             #
102             # This is free software, licensed under:
103             #
104             # The GNU General Public License, Version 3, June 2007
105             #
106              
107             =pod
108              
109             =head1 NAME
110              
111             MooX::PDL2 - A Moo based PDL 2.X object
112              
113             =head1 VERSION
114              
115             version 0.01
116              
117             =head1 SYNOPSIS
118              
119             use Moo;
120             extends 'MooX::PDL2';
121              
122             =head1 DESCRIPTION
123              
124             This class provides the thinnest possible layer required to create a
125             L<Moo> object which is recognized by L<PDL>.
126              
127             L<PDL> will treat a non-L<PDL> blessed hash as a L<PDL> object if it
128             has a hash element with a key of C<PDL>. That element may be a
129             C<PDL> piddle or a I<subroutine> which returns a piddle.
130              
131             This class provides a C<PDL> method (which must not be overridden!) which
132             returns the contents of the C<_PDL> attribute. That attribute is yours
133             to manipulate.
134              
135             =head2 Classes without required constructor parameters
136              
137             B<PDL> does not pass any parameters to a class' B<initialize> method
138             when constructing a new object. Because of this, the default
139             implementation of B<MooX::PDL2::initialize()> returns a bare piddle,
140             not an instance of B<MooX::PDL2>, as it cannot know whether your class
141             requires parameters during construction.
142              
143             If your class does I<not> require parameters be passed to the constructor,
144             it is safe to overload the C<initialize> method to return a fully fledged
145             instance of your class:
146              
147             sub initialize { shift->new() }
148              
149             =head2 Overloaded operators
150              
151             L<PDL> overloads a number of the standard Perl operators. For the most part it
152             does this using subroutines rather than methods, which makes it difficult to
153             manipulate them. Consider using L<overload::reify> to wrap the overloads in
154             methods, e.g.:
155              
156             package MyPDL;
157             use Moo;
158             extends 'MooX::PDL2';
159             use overload::reify;
160              
161             =head1 ATTRIBUTES
162              
163             =head2 _PDL
164              
165             The actual piddle associated with an object. B<PDL> routines
166             will transparently uses this when passed an object.
167              
168             This attribute is
169              
170             =over
171              
172             =item *
173              
174             lazy
175              
176             =item *
177              
178             has a builder which returns C<< PDL->null >>
179              
180             =item *
181              
182             will coerce its argument to be a piddle
183              
184             =item *
185              
186             has a clearer
187              
188             =back
189              
190             See L</EXAMPLES> for fun ways of combining it with Moo's facilities.
191              
192             =head1 METHODS
193              
194             =head2 new
195              
196             # null value
197             $pdl = MooX::PDL2->new;
198              
199             =head1 EXAMPLES
200              
201             =head2 A class representing an evaluated polynomial
202              
203             This class represents an evaluated polynomial. The polynomial coefficients and
204             the values at which it is evaluated are attributes of the class. When they are
205             changed they trigger a change in the underlying piddle.
206              
207             Here's the definition:
208              
209             package PolyNomial;
210            
211             use PDL::Lite;
212            
213             use Moo;
214             extends 'MooX::PDL2';
215            
216             has x => (
217             is => 'rw',
218             required => 1,
219             trigger => sub { $_[0]->_clear_PDL },
220             );
221            
222             has coeffs => (
223             is => 'rw',
224             required => 1,
225             trigger => sub { $_[0]->_clear_PDL },
226             );
227            
228             sub _build__PDL {
229            
230             my $self = shift;
231            
232             my $x = $self->x;
233             my $coeff = $self->coeffs;
234            
235             # this calculation is not robust at all
236             my $pdl = $x->ones;
237             $pdl *= $coeff->[0];
238            
239             for ( my $exp = 1 ; $exp < @$coeff + 1 ; ++$exp ) {
240             $pdl += $coeff->[$exp] * $x**$exp;
241             }
242             $pdl;
243             }
244            
245             1;
246              
247             Note that the attributes use triggers to clear C<_PDL> so that it will
248             be recalculated when it is next accessed through the C<_PDL> attribute
249             accessor.
250              
251             And here's how to use it
252              
253             use PDL::Lite;
254             use PolyNomial;
255            
256             my $m = PolyNomial->new( coeffs => [ 3, 4 ], x => PDL->sequence(10) );
257             print $m, "\n";
258            
259             $m *= 2;
260             print $m, "\n";
261            
262             $m->x( PDL->sequence( 5 ) );
263             print $m, "\n";
264              
265             With sample output:
266              
267             [3 7 11 15 19 23 27 31 35 39]
268             [6 14 22 30 38 46 54 62 70 78]
269             [3 7 11 15 19]
270              
271              
272             =head1 BUGS AND LIMITATIONS
273              
274             You can make new bug reports, and view existing ones, through the
275             web interface at L<https://rt.cpan.org/Public/Dist/Display.html?Name=MooX-PDL2>.
276              
277             =head1 SEE ALSO
278              
279             Please see those modules/websites for more information related to this module.
280              
281             =over 4
282              
283             =item *
284              
285             L<PDLx::DetachedObject>
286              
287             =back
288              
289             =head1 AUTHOR
290              
291             Diab Jerius <djerius@cpan.org>
292              
293             =head1 COPYRIGHT AND LICENSE
294              
295             This software is Copyright (c) 2017 by Smithsonian Astrophysical Observatory.
296              
297             This is free software, licensed under:
298              
299             The GNU General Public License, Version 3, June 2007
300              
301             =cut
302              
303             __END__
304              
305              
306             #pod =head1 SYNOPSIS
307             #pod
308             #pod use Moo;
309             #pod extends 'MooX::PDL2';
310             #pod
311             #pod =head1 DESCRIPTION
312             #pod
313             #pod This class provides the thinnest possible layer required to create a
314             #pod L<Moo> object which is recognized by L<PDL>.
315             #pod
316             #pod L<PDL> will treat a non-L<PDL> blessed hash as a L<PDL> object if it
317             #pod has a hash element with a key of C<PDL>. That element may be a
318             #pod C<PDL> piddle or a I<subroutine> which returns a piddle.
319             #pod
320             #pod This class provides a C<PDL> method (which must not be overridden!) which
321             #pod returns the contents of the C<_PDL> attribute. That attribute is yours
322             #pod to manipulate.
323             #pod
324             #pod
325             #pod =head2 Classes without required constructor parameters
326             #pod
327             #pod B<PDL> does not pass any parameters to a class' B<initialize> method
328             #pod when constructing a new object. Because of this, the default
329             #pod implementation of B<MooX::PDL2::initialize()> returns a bare piddle,
330             #pod not an instance of B<MooX::PDL2>, as it cannot know whether your class
331             #pod requires parameters during construction.
332             #pod
333             #pod If your class does I<not> require parameters be passed to the constructor,
334             #pod it is safe to overload the C<initialize> method to return a fully fledged
335             #pod instance of your class:
336             #pod
337             #pod sub initialize { shift->new() }
338             #pod
339             #pod =head2 Overloaded operators
340             #pod
341             #pod L<PDL> overloads a number of the standard Perl operators. For the most part it
342             #pod does this using subroutines rather than methods, which makes it difficult to
343             #pod manipulate them. Consider using L<overload::reify> to wrap the overloads in
344             #pod methods, e.g.:
345             #pod
346             #pod package MyPDL;
347             #pod use Moo;
348             #pod extends 'MooX::PDL2';
349             #pod use overload::reify;
350             #pod
351             #pod
352             #pod =head1 EXAMPLES
353             #pod
354             #pod =head2 A class representing an evaluated polynomial
355             #pod
356             #pod This class represents an evaluated polynomial. The polynomial coefficients and
357             #pod the values at which it is evaluated are attributes of the class. When they are
358             #pod changed they trigger a change in the underlying piddle.
359             #pod
360             #pod Here's the definition:
361             #pod
362             #pod # EXAMPLE: examples/PolyNomial.pm
363             #pod
364             #pod Note that the attributes use triggers to clear C<_PDL> so that it will
365             #pod be recalculated when it is next accessed through the C<_PDL> attribute
366             #pod accessor.
367             #pod
368             #pod And here's how to use it
369             #pod
370             #pod # EXAMPLE: examples/poly.pl
371             #pod
372             #pod With sample output:
373             #pod
374             #pod # COMMAND: perl -Ilib -Iexamples examples/poly.pl
375             #pod
376             #pod =head1 SEE ALSO
377             #pod
378             #pod L<PDLx::DetachedObject>