"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "Basic/Pod/PP.pod" between
PDL-2.082.tar.gz and PDL-2.083.tar.gz

About: PDL (Perl Data Language) aims to turn perl into an efficient numerical language for scientific computing (similar to IDL and MatLab).

PP.pod  (PDL-2.082):PP.pod  (PDL-2.083)
skipping to change at line 74 skipping to change at line 74
C<pp_addhdr> so far will be included. Therefore, if you add C functions, C<pp_addhdr> so far will be included. Therefore, if you add C functions,
make sure to make them C<static> to avoid clashes with later F<.c> files. make sure to make them C<static> to avoid clashes with later F<.c> files.
But a better practice is make them be separate C files, with any necessary But a better practice is make them be separate C files, with any necessary
F<.h> to be included by them and the F<.pd> file. You can then add them F<.h> to be included by them and the F<.pd> file. You can then add them
to your F<Makefile.PL> (note this is the C<_int> version, see separate to your F<Makefile.PL> (note this is the C<_int> version, see separate
notes on how to "opt-in" for your own modules): notes on how to "opt-in" for your own modules):
my @pack = (["pnm.pd", qw(Pnm PDL::IO::Pnm)]); my @pack = (["pnm.pd", qw(Pnm PDL::IO::Pnm)]);
my %hash = pdlpp_stdargs_int(@pack); my %hash = pdlpp_stdargs_int(@pack);
$hash{OBJECT} .= ' get$(OBJ_EXT)'; $hash{OBJECT} .= ' get$(OBJ_EXT)';
sub MY::postamble { pdlpp_postamble_int(@pack); }; sub MY::postamble { pdlpp_postamble_int(@pack); }
WriteMakefile(%hash); WriteMakefile(%hash);
=head2 pp_addpm =head2 pp_addpm
=for ref =for ref
Add code to the generated .pm file Add code to the generated .pm file
=head2 pp_addxs =head2 pp_addxs
skipping to change at line 109 skipping to change at line 109
=for example =for example
pp_add_macros(SUCC => sub { "($_[0] + 1)" }); pp_add_macros(SUCC => sub { "($_[0] + 1)" });
# ... # ...
Code => '$a() = $SUCC($b());', Code => '$a() = $SUCC($b());',
=head2 pp_add_typemaps =head2 pp_add_typemaps
=for ref =for ref
Available from 2.082. Add an XS typemap for use as C<OtherPars>. Takes Available from 2.082. Add an XS typemap for use as C<OtherPars> or from
manually-added XS. Takes
one named argument, either C<typemap> (an L<ExtUtils::Typemaps> object), one named argument, either C<typemap> (an L<ExtUtils::Typemaps> object),
C<string>, or C<file>. C<string>, or C<file>.
=for example =for example
pp_add_typemaps(string=><<'EOT'); pp_add_typemaps(string=><<'EOT');
TYPEMAP: <<END_OF_TYPEMAP TYPEMAP: <<END_OF_TYPEMAP
TYPEMAP TYPEMAP
NV_ADD1 T_NV_ADD1 NV_ADD1 T_NV_ADD1
skipping to change at line 144 skipping to change at line 145
=for ref =for ref
Add BEGIN-block wrapping to code for the generated .pm file Add BEGIN-block wrapping to code for the generated .pm file
=head2 pp_bless =head2 pp_bless
=for ref =for ref
Sets the package to which the XS code is added (default is PDL) Sets the package to which the XS code is added (default is PDL)
=head2 pp_boundscheck
=for ref
Control state of PDL bounds checking activity
=head2 pp_core_importList =head2 pp_core_importList
=for ref =for ref
Specify what is imported from PDL::Core Specify what is imported from PDL::Core
=head2 pp_def =head2 pp_def
=for ref =for ref
skipping to change at line 1348 skipping to change at line 1343
$CROAK("Diagonal: must have at least 1 dimension"); $CROAK("Diagonal: must have at least 1 dimension");
$DOCOMPALLOC(); /* malloc()s the whichdims */ $DOCOMPALLOC(); /* malloc()s the whichdims */
for(i=0; i<$COMP(whichdims_count); i++) for(i=0; i<$COMP(whichdims_count); i++)
$COMP(whichdims)[i] = tmp[i]; $COMP(whichdims)[i] = tmp[i];
free(tmp); free(tmp);
/* ... */ /* ... */
', ',
# ... # ...
); );
The C<MakeComp> code is placed in the C<pdl_(funcname)_run>, so access The C<MakeComp> code is placed in the C<pdl_run_(funcname)>, so access
to C<Pars> (which will just be C<pdl *>s)/C<OtherPars> values is just to C<Pars> (which will just be C<pdl *>s)/C<OtherPars> values is just
via their names, not a macro. via their names, not a macro. The default code (which also applies
to C<OtherPars>) makes a copy of values where it knows how to do so,
including C<SV*> and C<char*>.
You can also provide a C<CompFreeCodeComp> key, in case your C<MakeComp>
needs tidying up after it.
As of 2.058, you can instead give a C99 "incomplete As of 2.058, you can instead give a C99 "incomplete
array" type parameter as an C<OtherPars> entry: array" type parameter as an C<OtherPars> entry:
pp_def( pp_def(
'diagonal', 'diagonal',
OtherPars => 'PDL_Indx whichdims[]', OtherPars => 'PDL_Indx whichdims[]',
MakeComp => ' MakeComp => '
if ($COMP(whichdims_count) < 1) if ($COMP(whichdims_count) < 1)
$CROAK("Diagonal: must have at least 1 dimension"); $CROAK("Diagonal: must have at least 1 dimension");
/* ... */ /* ... */
', ',
# ... # ...
); );
There is an XS F<typemap> entry (only for C<PDL_Indx> array types for There is an XS F<typemap> entry (for C<PDL_Indx> and C<pdl*> array types for
now) that adds a C<(varname)_count> variable having extracted the index now) that relies on a C<(varname)_count> variable being declared in the
XS C<INPUT> section (PP does this for you), to extract the index
numbers from an array-ref parameter, and sets the count variable to the numbers from an array-ref parameter, and sets the count variable to the
right value. PP then makes a copy of the data available. The C function right value. PP then makes a copy of the data available. The C function
(here, C<pdl_diagonal_run>)'s caller (here, the generated XS function) (here, C<pdl_run_diagonal>)'s caller (here, the generated XS function)
is responsible for freeing the array passed in (here, PDL's C<smalloc> is responsible for freeing the array passed in (here, PDL's C<smalloc>
function is used, so the user need do nothing different). function is used, so the user need do nothing different).
=head4 XS-only OtherPars
As of 2.083, you can prefix the names of C<OtherPars> with C<$>, e.g.
pp_def('minus',
OtherPars => 'int $swap',
# ...
);
This will mean they are available in C<HdrCode> and C<FtrCode>, but not
elsewhere in the generated code (e.g. C<MakeComp>, C<Code>).
=head2 Other functions in the Code section =head2 Other functions in the Code section
The only PP function that we have used in the examples so far is C<loop>. The only PP function that we have used in the examples so far is C<loop>.
Additionally, there are currently two other functions which are recognised Additionally, there are currently two other functions which are recognised
in the C<Code> section: in the C<Code> section:
=head3 broadcastloop =head3 broadcastloop
As we heard above the signature of a PP defined function defines the As we heard above the signature of a PP defined function defines the
dimensions of all the pdl arguments involved in a I<primitive> operation. dimensions of all the pdl arguments involved in a I<primitive> operation.
skipping to change at line 1530 skipping to change at line 1543
Pars => ' p(m); x(n); [o] y(); [t] work(wn); ', Pars => ' p(m); x(n); [o] y(); [t] work(wn); ',
RedoDimsCode => '$SIZE(wn) = $SIZE(n) + $SIZE(m) * $SIZE(m);', RedoDimsCode => '$SIZE(wn) = $SIZE(n) + $SIZE(m) * $SIZE(m);',
Code => ' Code => '
externalfunc( $P(p), $P(x), $SIZE(m), $SIZE(n), $P(work) ); externalfunc( $P(p), $P(x), $SIZE(m), $SIZE(n), $P(work) );
' '
); );
As of 2.075, you can use the dimensions of passed-in ndarrays as they As of 2.075, you can use the dimensions of passed-in ndarrays as they
are available when the C<RedoDimsCode> is run. are available when the C<RedoDimsCode> is run.
Before the code in the Code section is executed PP Before the code in the Code section is executed PP
will create the proper storage for C<work> if it does not will create the proper storage for C<work> (one area per POSIX thread,
exist. Note that you only took the first dimension of C<p> in case of broadcasting that multi-threads - the user cannot supply this).
Note that you only took the first dimension of C<p>
and C<x> because the user may have sent ndarrays with extra and C<x> because the user may have sent ndarrays with extra
broadcasting dimensions. Of course, the temporary ndarray C<work> (note the broadcasting dimensions.
[t] flag) should not be given any broadcast dimensions anyway.
You can also use C<RedoDimsCode> to set the dimension of a You can also use C<RedoDimsCode> to set the dimension of a
ndarray flagged with [o]. In this case you set the dimensions ndarray flagged with [o]. In this case you set the dimensions
for the named dimension in the signature using $SIZE() as in for the named dimension in the signature using $SIZE() as in
the preceding example. However, because the ndarray is the preceding example. However, because the ndarray is
flagged with [o] instead of [t], broadcasting dimensions will flagged with [o] instead of [t], broadcasting dimensions will
be added if required just as if the size of the dimension be added if required just as if the size of the dimension
were computed from the signature according to the usual were computed from the signature according to the usual
rules. Here is an example from PDL::Math rules. Here is an example from PDL::Math
skipping to change at line 1645 skipping to change at line 1658
pp_def('init_meat', pp_def('init_meat',
Pars => 'double x(n); double y(n);', Pars => 'double x(n); double y(n);',
OtherPars => 'gsl_spline *spl', OtherPars => 'gsl_spline *spl',
Code =>'gsl_spline_init,($COMP(spl),$P(x),$P(y),$SIZE(n)));' Code =>'gsl_spline_init,($COMP(spl),$P(x),$P(y),$SIZE(n)));'
); );
where I have removed a macro wrapper call, but that would obscure the where I have removed a macro wrapper call, but that would obscure the
discussion. discussion.
You can also have C<OtherPars> entries that are "incomplete arrays"
of C<pdl*>, both for input and output:
OtherPars => 'pdl *ins[]', # $COMP(ins_count) will be available
# OR
OtherPars => '[o] pdl *outs[]', # update $COMP(outs_count) in your code
Note that the output F<typemap> entry does a C<free> on the array of
C<pdl*> pointers, so ensure that you C<malloc> it in your code, without
leaking.
=head3 OtherPars as outputs =head3 OtherPars as outputs
As of 2.081, you can specify an C<OtherPar> as an output. This looks like: As of 2.081, you can specify an C<OtherPar> as an output. This looks like:
pp_def('output_op', pp_def('output_op',
Pars => 'in(n=2)', Pars => 'in(n=2)',
OtherPars => '[o] PDL_Anyval v0; [o] PDL_Anyval v1', OtherPars => '[o] PDL_Anyval v0; [o] PDL_Anyval v1',
Code => ' Code => '
pdl_datatypes dt = $PDL(in)->datatype; pdl_datatypes dt = $PDL(in)->datatype;
ANYVAL_FROM_CTYPE($COMP(v0), dt, $in(n=>0)); ANYVAL_FROM_CTYPE($COMP(v0), dt, $in(n=>0));
ANYVAL_FROM_CTYPE($COMP(v1), dt, $in(n=>1)); ANYVAL_FROM_CTYPE($COMP(v1), dt, $in(n=>1));
', ',
); );
The passed-in stack SV will be mutated in place, so this code will then work: The passed-in stack SV will be mutated in place, so this code will then work:
output_op([5,7], my $v0, my $v1); output_op([5,7], my $v0, my $v1);
is_deeply [$v0,$v1], [5,7], 'output OtherPars work'; is_deeply [$v0,$v1], [5,7], 'output OtherPars work';
($v0, $v1) = output_op([5,7]); # you can omit them, then they get returned
is_deeply [$v0,$v1], [5,7], 'output OtherPars work 1a';
An operation with output C<OtherPars> cannot broadcast, since that would An operation with output C<OtherPars> cannot broadcast, since that would
cause undefined results. A runtime check is generated that throws an cause undefined results. A runtime check is generated that throws an
exception if any C<Par> would cause broadcasting. exception if any C<Par> would cause broadcasting.
Note the syntax for C<OtherPars> has C<[o]> go I<before> the type, while Note the syntax for C<OtherPars> has C<[o]> go I<before> the type, while
it goes I<after> the type in C<Pars>. It was felt this was the best way it goes I<after> the type in C<Pars>. It was felt this was the best way
to avoid ambiguity given C types can have C<[]> in them. to avoid ambiguity given C types can have C<[]> in them.
This relies on the relevant C<OtherPar> having an C<OUTPUT> entry in an This relies on the relevant C<OtherPar> having an C<OUTPUT> entry in an
XS typemap. XS typemap.
As of 2.083, it is also possible to specify C<OtherPars> as C<[io]>,
which means they I<must> be supplied (rather than being optional, like
an C<[o]> one), but will still be updated after the operation has
finished.
=head2 Other useful PP keys in data operation definitions =head2 Other useful PP keys in data operation definitions
You have already heard about the C<OtherPars> key. Currently, there are not You have already heard about the C<OtherPars> key. Currently, there are not
many other keys for a data operation that will be useful in normal (whatever many other keys for a data operation that will be useful in normal (whatever
that is) PP programming. In fact, it would be interesting to hear about that is) PP programming. In fact, it would be interesting to hear about
a case where you think you need more than what is provided at the moment. a case where you think you need more than what is provided at the moment.
Please speak up on one of the PDL mailing lists. Most other keys recognised Please speak up on one of the PDL mailing lists. Most other keys recognised
by C<pp_def> are only really useful for what we call I<slice operations> by C<pp_def> are only really useful for what we call I<slice operations>
(see also above). (see also above).
skipping to change at line 1753 skipping to change at line 1784
=head3 OtherParsDefaults =head3 OtherParsDefaults
OtherPars => 'int a; int b', OtherPars => 'int a; int b',
OtherParsDefaults => { b => 0 }, OtherParsDefaults => { b => 0 },
Allows specifying default values for C<OtherPars>. It is an error to Allows specifying default values for C<OtherPars>. It is an error to
specify a default for one that is before another that does not have specify a default for one that is before another that does not have
a default. a default.
=head3 ArgOrder
Pars => 'x(); y(); [o]z()'
OtherPars => 'int a; int b',
ArgOrder => [qw(x y a b z)],
# or, a non-reference true value to enable flexible arg-handling and
# move defaultable to the end, followed by output ndarrays then OtherPars
Pars => 'x(); y(); [o]z()'
OtherPars => 'int a; int b',
ArgOrder => 1,
Allows specifying a different order for providing the operation's
arguments. This affects only the generated XS (not C C<pdl_run_(name)>)
parameter list; the internal ordering of C<pdl*> in various C arrays
is unaffected.
Providing a non-reference true value enables flexible argument-handling
and moves defaultable to the end, followed by output ndarrays then
output C<OtherPars>. Also, all outputs (ndarray and C<OtherPars>) will
be returned on the stack, even if supplied as arguments.
It is an error to specify arguments that are not provided, or to give
a false value, or to have "optional" arguments after mandatory ones.
=head4 XS argument-handling change
This also changes PP's XS argument handling; normally you can specify:
=over
=item *
just the input/io arguments
=item *
(if the operation has default values provided) those plus values for all argumen
ts with defaults
=item *
all of those plus output arguments, in other words all non-C<[t]> arguments
=back
With C<ArgOrder> given, "optional" arguments (outputs and ones with
defaults) will be filled in from the leftmost missing one.
=head3 HdrCode
This is C code that is inserted in the XS function before the call to
the generated C<pdl_run_(funcname)>. It will have access to all the Pars
and OtherPars as C values.
=head3 FtrCode
As of 2.083.
This is C code that is inserted in the XS function after the call to
the generated C<pdl_run_(funcname)>. It will have access to all the Pars
and OtherPars as C values.
=head2 Other PDL::PP functions to support concise package definition =head2 Other PDL::PP functions to support concise package definition
So far, we have described the C<pp_def> and C<pp_done> functions. PDL::PP So far, we have described the C<pp_def> and C<pp_done> functions. PDL::PP
exports a few other functions to aid you in writing concise PDL extension exports a few other functions to aid you in writing concise PDL extension
package definitions. package definitions.
=head3 pp_addhdr =head3 pp_addhdr
Often when you interface library functions as in the above example Often when you interface library functions as in the above example
you have to include additional C include files. Since the XS file is you have to include additional C include files. Since the XS file is
skipping to change at line 1867 skipping to change at line 1959
pp_add_isa(' Some::Other::Class '); pp_add_isa(' Some::Other::Class ');
=head3 pp_bless =head3 pp_bless
If your pp_def routines are to be used as object methods use If your pp_def routines are to be used as object methods use
C<pp_bless> to specify the package (i.e. class) to which C<pp_bless> to specify the package (i.e. class) to which
your I<pp_def>ed methods will be added. For example, your I<pp_def>ed methods will be added. For example,
C<pp_bless('PDL::MyClass')>. The default is C<PDL> if this is C<pp_bless('PDL::MyClass')>. The default is C<PDL> if this is
omitted. omitted.
The value given here (or the default, C<PDL>), anywhere in the F<.pd>
file, will be the package into which all PP operations get added, even
for operations whose C<pp_def> was called I<before> the C<pp_bless>.
This is because that package is inserted at the start of the generated
XS code by C<pp_done>. The only way this changes is if C<pp_addxs> is
called, which will add the given code (or none if an empty string is
given) to the C<$::PDLPACK> package,
I<and then changes the package to the pp_bless value>. For historical
reasons, this cannot be changed. So, to have several different packages
in one F<.pd> file, do something like this:
# any pp_def up till now will get put in PDL::Pack2
pp_bless('PDL::Pack1');
pp_addxs('');
pp_def('func1', ...);
pp_bless('PDL::Pack2');
pp_addxs('');
pp_def('otherfunc', ...);
=head3 pp_addxs =head3 pp_addxs
Sometimes you want to add extra XS code of your own Sometimes you want to add extra XS code of your own
(that is generally not involved with any broadcasting/indexing issues (that is generally not involved with any broadcasting/indexing issues
but supplies some other functionality you want to access from the Perl but supplies some other functionality you want to access from the Perl
side) to the generated XS file, for example side) to the generated XS file, for example
pp_addxs('',' pp_addxs('','
# Determine endianness of machine # Determine endianness of machine
skipping to change at line 2350 skipping to change at line 2461
=head3 P2Child =head3 P2Child
Forces C<Pars> to be C<PARENT> and C<CHILD>, the function's Forces C<Pars> to be C<PARENT> and C<CHILD>, the function's
C<GenericTypes> to be all of them, no C<HaveBroadcasting> or C<CallCopy>, C<GenericTypes> to be all of them, no C<HaveBroadcasting> or C<CallCopy>,
and turns on C<DefaultFlow> (so do not supply any of those args). and turns on C<DefaultFlow> (so do not supply any of those args).
Intended for affine transformations with dataflow. Intended for affine transformations with dataflow.
=head3 DefaultFlow =head3 DefaultFlow
If true, sets in the C<pdl_transvtable> (see L<PDL::Internals>) the If I<set>, sets in the C<pdl_transvtable> (see L<PDL::Internals>) the
C<iflags> such that the trans will start with dataflow both forwards C<iflags> such that the trans will start with dataflow both forwards
and backwards. and backwards. Note that setting this to any value (including 0) will
trigger the behaviour.
=head3 HaveBroadcasting =head3 HaveBroadcasting
Default true. If so, generate code implementing broadcasting (see Default true. If so, generate code implementing broadcasting (see
L<PDL::Indexing>). L<PDL::Indexing>).
=head3 CallCopy =head3 CallCopy
For parameters that get created, normally the C<< PDL->initialize >> For parameters that get created, normally the C<< PDL->initialize >>
will be used (or on a subclass). If this is true (which is the default will be used (or on a subclass). If this is true (which is the default
skipping to change at line 2577 skipping to change at line 2689
section is C code that gets called by Perl when your module is loaded and is section is C code that gets called by Perl when your module is loaded and is
useful for automatic initialization. You can learn more about XS and the BOOT useful for automatic initialization. You can learn more about XS and the BOOT
section at L<perlxs>. section at L<perlxs>.
=head3 pp_addhdr =head3 pp_addhdr
Adds pure-C code to your XS file. XS files are structured such that pure C Adds pure-C code to your XS file. XS files are structured such that pure C
code must come before XS specifications. This allows you to specify such code must come before XS specifications. This allows you to specify such
C code. C code.
=head3 pp_boundscheck
PDL normally checks the bounds of your accesses before making them. You can
turn that on or off at runtime by setting MyPackage::set_boundscheck. This
function allows you to remove that runtime flexibility and B<never> do bounds
checking. It also returns the current boundschecking status if called
without any argumens.
NOTE: I have not found anything about bounds checking in other documentation.
That needs to be addressed.
=head2 Generating Perl Code =head2 Generating Perl Code
Many functions imported when you use PDL::PP allow you to modify the Many functions imported when you use PDL::PP allow you to modify the
contents of the generated .pm file. In addition to pp_def and pp_done, contents of the generated .pm file. In addition to pp_def and pp_done,
the role of these functions is primarily to add code to various parts of the role of these functions is primarily to add code to various parts of
your generated .pm file. your generated .pm file.
=head3 pp_addpm =head3 pp_addpm
Adds Perl code to the generated .pm file. PDL::PP actually keeps track of Adds Perl code to the generated .pm file. PDL::PP actually keeps track of
 End of changes. 18 change blocks. 
30 lines changed or deleted 132 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)