=pod
=encoding utf8
=head1 NAME
Math::GF - Galois Fields arithmetics
=head1 VERSION
This document describes Math::GF version 0.004.
=head1 SYNOPSIS
use Math::GF;
# prime orders leverage on Math::GF::Zn
my $GF5 = Math::GF->new(order => 5);
# prints "yes!" because 5 is prime
say 'yes!' if $GF5->order_is_prime;
# prints "order 5 = 5^1"
say 'order ', $GF5->order, ' = ', $GF5->p, '^', $GF5->n;
# generate some elements
my $zero_gf5 = $GF5->additive_neutral;
my $one_gf5 = $GF5->multiplicative_neutral;
my $four_gf5 = $GF5->e(4); # scalar context
my ($two_gf5, $three_gf5) = $GF5->(2, 3); # list context
# use some operations, both print "yes!"
say 'yes!' if $two_gf5 == $one_gf5 + $one_gf5;
say 'yes!' if $three_gf5 == $four_gf5 * $two_gf5;
# non-prime orders leverage on Math::GF::Extension
my $GF8 = Math::GF->new(order => 8);
# prints "order not prime!"
say 'order not prime!' unless $GF8->order_is_prime;
# prints "order 8 = 2^3"
say 'order ', $GF8->order, ' = ', $GF8->p, '^', $GF8->n;
# same operations as before anyway, no change in API
my $zero_gf8 = $GF8->additive_neutral;
my $one_gf8 = $GF8->multiplicative_neutral;
my ($three_gf8, $five_gf8) = $GF8->e(3, 5);
# use some operations... no more modulo operations in GF(2^3)
say 'yes!' if $three_gf8 * $five_gf8 == $GF8->e(4);
# import a factory function for building elements
Math::GF->import_builder(81, name => 'GF81'); # GF(3^4)
say 'yes!' if GF81(5) * GF81(8) == GF81(19);
# Need all elements? No problem
my @all_gf27 = Math::GF->new(order => 27)->all;
=head1 DESCRIPTION
This module allows you to generate and handle operations inside a Galois
Field (GF) of I<any> allowed order:
=over
=item *
orders that are too big are likely to explode
=item *
orders that aren't prime number powers do not have associated Galois
Fields.
=back
It's easy to generate a new GF of a given order:
my $GF5 = Math::GF->new(order => 5); # GF(5)
my $GF8 = Math::GF->new(order => 8); # GF(2^3)
Since a GF of order I<N> has exactly I<N> elements, it's easy to refer to
them with integers from I<0> to I<< N - 1 >>. If you want to actually
generate the associated element you can use the L</e> method:
my $e5_gf8 = $GF8->e(5);
If you're planning to work extensively with a specific GF, or just want
some syntactic sugar, you can import a factory function in your package
that will generate elements in the specific GF:
# by default, import a function named GF_p_n for GF(p^n)
Math::GF->import_builder(8);
my $e5 = GF_2_3(5);
# you can give your name though
Math::GF->import_builder(8, name => 'GF8');
my $e5_gf8 = GF8(5);
If you need all elements, look at the L</all> method. It's the same as
doing this:
my @all = map { $GF8->e($_) } 0 .. 8 - 1;
but easier to type and possibly a bit quicker.
Elements associated to I<0> and I<1> have the I<usual> meaning of the
additive and multiplicative neutral elements, respectively. You can also
get them with L</additive_neutral> and L</multiplicative_neutral>.
=head1 METHODS
In the following, C<$GF> is supposed to be a C<Math::GF> object.
=begin HIDE
=head2 B<< BUILDARGS >>
Pre-munge arguments before they reach the BUILD method. See documentation
for L<Moo>.
=end HIDE
=head2 B<< additive_neutral >>
my $zero = $GF->additive_neutral;
the neutral element of the Galois Field with respect to the addition
operation. Same as C<< $GF->e(0) >>.
=head2 B<< all >>
my @all_elements = $GF->all;
generate all elements of the Galois Field.
=head2 B<< e >>
my $e5 = $GF->e(5);
my @some = $GF->e(2, 3, 5, 7);
factory method to generate one or more elements in the field. When called
in scalar context it always operate on the first provided argument only.
=head2 B<< element_class >>
my $class_name = $GF->element_class;
the underlying class for generating elements. It defaults to
L<Math::GF::Zn> when the L</order> is a prime number and
L<Math::GF::Extension> when it is not; there is probably little
motivation for you to fiddle with this.
=head2 B<< import_builder >>
Math::GF->import_builder($order, %args);
import a factory function in the caller's package for easier generation of
elements in the GF of the specified C<$order>.
By default, the name of the imported function is C<GF_p> or C<GF_p_n>
where C<p> is a prime and C<n> is the power of the prime such that C<<
$order = p ** n >> (the C<n> part is omitted if it is equal to C<1>). For
example:
Math::GF->import_builder(5); # imports GF_5()
Math::GF->import_builder(8); # imports GF_2_3()
You can pass your own C<name> in the C<%args> though:
Math::GF->import_builder(8, name => 'GF8'); # imports GF8()
The imported function is a wrapper around L</e>:
my $one = GF_2_3(1);
my @some = GF_5(1, 3, 4);
Allowed keys in C<%args>:
=over
=item C<< level >>
by default the function is imported in the caller's package. This allows
you to alter which level in the call stack you want to peek for importing
the sub.
=item C<< name >>
the name of the method, see above for the default.
=back
=head2 B<< multiplicative_neutral >>
my $one = $GF->multiplicative_neutral;
the neutral element of the Galois Field with respect to the multiplication
operation. Same as C<< $GF>e(1) >>.
=head2 B<< n >>
my $power = $GF->n;
the L</order> of a Galois Field must be a power of a prime L</p>, this
method provides the value of the power. E.g. if the I<order> is C<8>, the
prime is C<2> and the power is C<3>.
=head2 B<< order >>
my $order = $GF->order;
the I<order> of the Galois Field. Only powers of a single prime are
allowed.
=head2 B<< order_is_prime >>
my $boolean = $GF->order_is_prime;
the L</order> of a Galois Field can only be a power of a prime, with the
special case in which this power is 1, i.e. the I<order> itself is a prime
number. This method provided a true value in this case, false otherwise.
=head2 B<< p >>
my $prime = $GF->p;
the L</order> of a Galois Field must be a power of a prime, this method
provides the value of the prime number. E.g. if the I<order> is C<8>, the
prime is C<2> and the power is C<3>. See also L</n>.
=head2 B<< prod_table >>
my $pt = $GF->prod_table;
a table that can be used to evaluate the product of two elements in the
field.
The table is provided as a reference to an Array of Arrays. The elements
in the field are associated to indexes from C<0> to C<< order - 1 >>;
table element C<< $pt->[$A][$B] >> represents the result of the product
between element associated to C<$A> and element associated to C<$B>.
You shouldn't in general need to fiddle with this table, as it is used
behind the scenes by C<Math::GF::Extension>, where all operations are
overloaded.
=head2 B<< sum_table >>
my $st = $GF->sum_table;
a table that can be used to evaluate the product of two elements in the
field.
The table is provided as a reference to an Array of Arrays. The elements
in the field are associated to indexes from C<0> to C<< order - 1 >>;
table element C<< $pt->[$A][$B] >> represents the result of the addition
between element associated to C<$A> and element associated to C<$B>.
You shouldn't in general need to fiddle with this table, as it is used
behind the scenes by C<Math::GF::Extension>, where all operations are
overloaded.
=head1 BUGS AND LIMITATIONS
Report bugs through GitHub (patches welcome).
=head1 SEE ALSO
L<Math::Polynomial> is used behind the scenes to generate the tables in
case the order is not a prime.
L<Math::GF::Zn> is used for generating elements in the field and handling
operations between them in an easy way in case of prime L</order>.
L<Math::GF::Extension> is used for elements in the field in case of
non-prime L</order>s.
=head1 AUTHOR
Flavio Poletti <polettix@cpan.org>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2017, 2018 by Flavio Poletti <polettix@cpan.org>
This module is free software. You can redistribute it and/or modify it
under the terms of the Artistic License 2.0.
This program is distributed in the hope that it will be useful, but
without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.
=cut