Chess-Plisco
view release on metacpan or search on metacpan
lib/Chess/Plisco/Macro.pod view on Meta::CPAN
=head1 NAME
Chess::Plisco::Macro - Macros/inline functions for Chess::Plisco
=head1 SYNOPSIS
use integer;
use Chess::Plisco qw(:all);
use Chess::Plisco::Macro;
my $white_pieces = cp_pos_white_pieces(Chess::Plisco->new);
my $bitboard = '0x8080808080808080';
my $popcount;
cp_bitboard_popcount $bitboard, $popcount;
cp_bitboard_popcount($bitboard, $popcount); # You can also use parentheses ...
print "There are $popcount bits set in $bitboard.\n";
=head1 DESCRIPTION
The module L<Chess::Plisco::Macro> is a source filter. It makes a number
of macros respectively inline functions available that can be invoked without
any subroutine call overhead. In fact, all invocations of these macros are
translated into constant expressions at compile-time.
All the functionality available in the module is also available as instance
or class methods of L<Chess::Plisco>. You should only use the macros
defined here if you have to squeeze out the last bit of performance from
your code, for example, when writing a chess engine. Otherwise, using the
macros has only disadvantages:
=over 4
=item It increases the compile-time of your code significantly.
=item Syntax checks on your code may fail.
=item Seemingly correct syntax may lead to syntax errors.
=item Your code becomes less readable; although sometimes it may not.
=back
If performance outweighs these problems in your use case, read on!
The source filter is probably not perfect but is able to translate at least
the source code of L<Chess::Plisco>. If you have trouble like unexpected
syntax errors in your own code, you can use the function C<preprocess()> (see
below), to get a translation of your source file, and find the problem.
Please note that not all translation errors are considered a bug of the
source filter. If the problem can be avoided by re-formulating your code,
a fix will probably be refused.
=head1 MOTIVATION
Chess programming should be really fast, and in this context the unavoidable
overhead of method or subroutine calls contributes enormously to the execution
time of the software.
In the C programming language, you can use preprocessor macros or inline
functions in order to avoid the calling overhead. In Perl, this can only
be done for constants with the L<constant> pragma:
use constant CP_FILE_A => 0;
use constant CP_SQUARE_E1 => 0x0808080808080808 | 0x00000000000000ff;
These are actually subroutines but Perl inlines them into your code, even
with constant folding (see the second example), so that you pay no price for
the use of these constants.
But L<Chess::Plisco> needs parametrized macros. For example, if you want
to extract the start square of a move, you have to do this:
$from = ((($move) >> 6) & 0x3f);
But it is awkward to remember. Other computations are even more complicated.
For example to get the number of bits set in a bitboard C<$bb>, you have to
do the following:
my $_b = $bb;
for ($popcount = 0; $_b; ++$popcount) {
$_b &= $_b - 1;
}
This is a well-known algorithm but you either have to implement it in a function
or method and pay the price of subroutine calls, or you have to repeat it over
and over in your code.
This module tries to mitigate that dilemma. If you just "use" it, all
invocations of the macros defined here, are translated into a regular statements
so that you can do these computations without subroutine call overhead.
Depending on the exact implementation of the macro, you can sometimes even use
them as l-vales (the left-hand side of an assignment) but you should generally
avoid this because the resulting code will become hard to understand.
=head1 PITFALLS
There are a number of caveats, when using this module. You had been warned
before, do not use it! If you cannot help, then ...
=head2 Import Constants from L<Chess::Plisco>
Remember that the macro calls defined in your code will be replaced by other
code at compile-time and that other code makes use of constants defined in
L<Chess::Plisco>. Therefore, you should always import these constants
with C<use Chess::Plisco ':all'>.
=head2 Use C<integer>
( run in 0.633 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )