For basic functions, the function code_for_xxx()
does not take any
input. However, in order to give a way to choose between different
codes, a hash called $options
is passed as a first argument. It
is up to the field implementer to decide which options are
pertinent for the class of fields he considers. A very typical
option will be the word size (32 or 64).
In order for the function code_for_xxx()
to have
access to appropriate names, the special sequence @!
is available: it is verbatim translated to the appropriate prefix
mpfq_TAG_
during code creation. Hence, for instance, if
the code needs an intermediate field element for the computation,
it can be declared like that:
@!elt tmp_elt;
The output of code_for_xxx()
should be an array of two elements:
the first follows the prototype given by the API, and give names to
the parameters of the function xxx
to be used in the
implementation. The second element returned by
code_for_xxx()
is a
string giving the C function implementation. For example, for
the field GF(7), the addition will be implemented by the following
Perl code:
sub code_for_add
{
return [ 'inline(K!, z, x, y)', "z = (x+y)%7;" ];
}
If the implementation of code_for_xxx()
requires
auxiliary functions that are not listed in api.pl (for instance
code_for_mul
might rely on
code_for_karatsuba
), then they must be returned as
one or several additional members at the end of the returned array.
Each such member must be a hash reference of the following form:
{ kind => 'inline(K!, z, x, y)', code => 'z = x+y', name => 'unreduced_add', requirements => 'dst_elt src_elt src_elt' }
where kind
and requirements
describe the
prototype, code
is the body of the function, and
name
is its name as called by
code_for_xxx()
. Beware that it will be created with a
mpfq_TAG
prefix, so that inside
code_for_xxx()
you must add @!
in front
of the name you give in the name
key.
There is a small example in src/gf7/code_for_7.pm
,
that is a (very partial!) implementation of GF(7).