All finite fields in MPFQ follow the same API that is defined in
the file api.pl
shipped with the MPFQ distribution.
We reproduce it here, but if you have doubts about a possible
mistake in this doc, please refer to the api.pl
file
within the source tree. This file is responsible for the
enforcement of the calling parameters in the generated code and
therefore closest to what is actually implemented.
In what follows, we assume that the FieldFamily
is
TAG
.
Exported types:
typedef mpfq_TAG_field; typedef mpfq_TAG_dst_field; typedef mpfq_TAG_elt; typedef mpfq_TAG_dst_elt; typedef mpfq_TAG_src_elt; typedef mpfq_TAG_elt_ur; typedef mpfq_TAG_dst_elt_ur; typedef mpfq_TAG_src_elt_ur; typedef mpfq_TAG_vec; typedef mpfq_TAG_dst_vec; typedef mpfq_TAG_src_vec; typedef mpfq_TAG_vec_ur; typedef mpfq_TAG_dst_vec_ur; typedef mpfq_TAG_src_vec_ur;
The field
and dst_field
types are for
storing the current finite field. In some cases, the
TAG
already defines a unique finite field, however,
even in that case, it is mandatory to have such a type, for
consistency of the interface. An element of the finite field can be declared using
the elt
type. The elt
type comes with two friends which give
the types for passing elements as arguments of functions. The
src
variant translates into the const
keyword.
An unreduced element can be stored in a variable of type
elt_ur
. An unreduced element is a sum of products of two elements, for which the simplification has not been performed: reduction modulo p
for prime fields in classical representation, montgomery reduction for prime fields in montgomery representation, and polynomial division for extension field like 2_n
or TAG_e
.
Only a few functions are available for manipulating unreduced elements.
The following functions are available. All of them take a pointer to the finite field as first element. In all cases, the same element can be given in input and ouput. In general, the name is explicit enough, so that for most of them no explanation is really needed.
/* Functions related to the field structure */ void mpfq_TAG_field_init(mpfq_TAG_dst_field); void mpfq_TAG_field_clear(mpfq_TAG_dst_field); void mpfq_TAG_field_specify(mpfq_TAG_dst_field, unsigned long, void *); void mpfq_TAG_field_setopt(mpfq_TAG_dst_field, unsigned long, void *); int mpfq_TAG_field_degree(mpfq_TAG_dst_field); void field_characteristic(mpfq_TAG_dst_field, mpz_t);
Calling the field_init
function is mandatory before
doing anything with the field. In the case where TAG
identifies a unique field, there is nothing more to do, but if
TAG
covers several finite fields, it is necessary to
specify the particular finite field you really want to work in. The
field_specify
is meant for that purpose. The
unsigned long
argument describes the kind of
specification. It can be MPFQ_PRIME_MPZ
or MPFQ_POLYNOMIAL
. The last
argument identifies the finite field your want. For
MPFQ_PRIME_MPZ
, you must pass an mpz
value.
The field_setopt
has the same behaviour: the
unsigned long
argument gives the kind of optimization
you want, and the last argument allows you to pass some information
to describe the optimization. Note that this mechanism is intended to allow
some optimization or precomputation made at runtime, and is usually
not used for a TAG
that describes a single field or a
small family of fields for which the optimizations and
precomputations can be made at compile-time.
/* Element allocation functions */ void mpfq_TAG_init(mpfq_TAG_dst_field, mpfq_TAG_elt *); void mpfq_TAG_clear(mpfq_TAG_dst_field, mpfq_TAG_elt *); /* Element assignment functions */ void mpfq_TAG_set(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt); void mpfq_TAG_set_ui(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, unsigned long); void mpfq_TAG_set_zero(mpfq_TAG_dst_field, mpfq_TAG_dst_elt); unsigned long mpfq_TAG_get_ui(mpfq_TAG_dst_field, mpfq_TAG_src_elt); void mpfq_TAG_set_mpn(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mp_limb_t *, size_t); void mpfq_TAG_set_mpz(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpz_srcptr); void mpfq_TAG_get_mpn(mpfq_TAG_dst_field, mp_limb_t *, mpfq_TAG_src_elt); void mpfq_TAG_get_mpz(mpfq_TAG_dst_field, mpz_ptr, mpfq_TAG_src_elt); void mpfq_TAG_random(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, gmp_randstate_t); void mpfq_TAG_random2(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, gmp_randstate_t);
Note that the randomness is taken from the GMP random functions.
We refer to the GMP documentation for initializing and seeding the
gmp_randstate_t
.
/* Arithmetic operations on elements */ void mpfq_TAG_add(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt, mpfq_TAG_src_elt); void mpfq_TAG_sub(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt, mpfq_TAG_src_elt); void mpfq_TAG_neg(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt); void mpfq_TAG_mul(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt, mpfq_TAG_src_elt); void mpfq_TAG_sqr(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt); void mpfq_TAG_pow(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt, unsigned long *, size_t); int mpfq_TAG_is_sqr(mpfq_TAG_dst_field, mpfq_TAG_src_elt); int mpfq_TAG_sqrt(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt); void mpfq_TAG_frobenius(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt); void mpfq_TAG_add_ui(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt, unsigned long); void mpfq_TAG_sub_ui(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt, unsigned long); void mpfq_TAG_mul_ui(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt, unsigned long); int mpfq_TAG_inv(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_elt); void mpfq_TAG_hadamard(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_dst_elt, mpfq_TAG_dst_elt, mpfq_TAG_dst_elt);
This last function hadamard
is marked as optional in the API, so before using it, one should verify whether it is implemented in the FieldFamilly
he wants to use; for all optional calls in the API, a preprocessor macro is defined if the function is provided. This symbol is HAVE_TAG_FunctionName
, i.e. in this case HAVE_mpfq_p_1_hadamard
.
/* Operations involving unreduced elements */ void mpfq_TAG_elt_ur_init(mpfq_TAG_dst_field, mpfq_TAG_elt_ur *); void mpfq_TAG_elt_ur_clear(mpfq_TAG_dst_field, mpfq_TAG_elt_ur *); void mpfq_TAG_elt_ur_set(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, mpfq_TAG_src_elt_ur); void mpfq_TAG_elt_ur_set_elt(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, mpfq_TAG_src_elt); void mpfq_TAG_elt_ur_set_zero(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur); void mpfq_TAG_elt_ur_set_ui(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, unsigned long); void mpfq_TAG_mul_ur(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, mpfq_TAG_src_elt, mpfq_TAG_src_elt); void mpfq_TAG_sqr_ur(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, mpfq_TAG_src_elt); void mpfq_TAG_elt_ur_add(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, mpfq_TAG_src_elt, mpfq_TAG_src_elt); void mpfq_TAG_elt_ur_sub(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, mpfq_TAG_src_elt, mpfq_TAG_src_elt); void mpfq_TAG_elt_ur_neg(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, mpfq_TAG_src_elt); void mpfq_TAG_reduce(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_dst_elt_ur); /* Comparison functions */ int mpfq_TAG_cmp(mpfq_TAG_dst_field, mpfq_TAG_src_elt, mpfq_TAG_src_elt); int mpfq_TAG_cmp_ui(mpfq_TAG_dst_field, mpfq_TAG_src_elt, unsigned long); int mpfq_TAG_is_zero(mpfq_TAG_dst_field, mpfq_TAG_src_elt);
The comparison functions return 0 if the elements are equal and 1 or -1 otherwise, depending on some arbitrary order (this order allows sorting).
/* Input/output functions */ void mpfq_TAG_asprint(mpfq_TAG_dst_field, char**, mpfq_TAG_src_elt); void mpfq_TAG_fprint(mpfq_TAG_dst_field, FILE*, mpfq_TAG_src_elt); void mpfq_TAG_print(mpfq_TAG_dst_field, mpfq_TAG_src_elt); int mpfq_TAG_sscan(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, const char*); int mpfq_TAG_fscan(mpfq_TAG_dst_field, FILE*, mpfq_TAG_dst_elt); int mpfq_TAG_scan(mpfq_TAG_dst_field, mpfq_TAG_dst_elt); std::istream& mpfq_TAG_cxx_in(mpfq_TAG_dst_field, std::istream&, mpfq_TAG_dst_elt); std::ostream& mpfq_TAG_cxx_out(mpfq_TAG_dst_field, std::ostream&, mpfq_TAG_src_elt);
The function asprint
prints the element in the given
string, ending with \0
char. The functions
sscan
, fscan
and scan
return
1 if the parsing was succesful and 0 otherwise.
The functions cxx_in
and cxx_out
are only exposed if __cplusplus
is defined.
/* Vector allocation functions */ void mpfq_TAG_vec_init(mpfq_TAG_dst_field, mpfq_TAG_vec *, unsigned int); void mpfq_TAG_vec_reinit(mpfq_TAG_dst_field, mpfq_TAG_vec *, unsigned int, unsigned int); void mpfq_TAG_vec_clear(mpfq_TAG_dst_field, mpfq_TAG_vec *, unsigned int); /* Vector assignment functions */ void mpfq_TAG_vec_set(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_set_zero(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, unsigned int); void mpfq_TAG_vec_setcoef(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_src_elt, unsigned int); void mpfq_TAG_vec_setcoef_ui(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, unsigned long, unsigned int); void mpfq_TAG_vec_getcoef(mpfq_TAG_dst_field, mpfq_TAG_dst_elt, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_random(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, unsigned int, gmp_randstate_t); void mpfq_TAG_vec_random2(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, unsigned int, gmp_randstate_t); /* Arithmetic operations on vectors */ void mpfq_TAG_vec_add(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_src_vec, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_neg(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_rev(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_sub(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_src_vec, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_scal_mul(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_src_vec, mpfq_TAG_src_elt, unsigned int); void mpfq_TAG_vec_conv(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_src_vec, unsigned int, mpfq_TAG_src_vec, unsigned int); /* Comparison functions */ int mpfq_TAG_vec_cmp(mpfq_TAG_dst_field, mpfq_TAG_src_vec, mpfq_TAG_src_vec, unsigned int); int mpfq_TAG_vec_is_zero(mpfq_TAG_dst_field, mpfq_TAG_src_vec, unsigned int); /* Input/output functions */ void mpfq_TAG_vec_asprint(mpfq_TAG_dst_field, char**, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_fprint(mpfq_TAG_dst_field, FILE*, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_print(mpfq_TAG_dst_field, mpfq_TAG_src_vec, unsigned int); int mpfq_TAG_vec_sscan(mpfq_TAG_dst_field, mpfq_TAG_vec *, unsigned int *, const char*); int mpfq_TAG_vec_fscan(mpfq_TAG_dst_field, FILE*, mpfq_TAG_vec *, unsigned int *); int mpfq_TAG_vec_scan(mpfq_TAG_dst_field, mpfq_TAG_vec *, unsigned int *); /* Operations involving unreduced elements */ void mpfq_TAG_vec_ur_init(mpfq_TAG_dst_field, mpfq_TAG_vec_ur *, unsigned int); void mpfq_TAG_vec_ur_reinit(mpfq_TAG_dst_field, mpfq_TAG_vec_ur *, unsigned int, unsigned int); void mpfq_TAG_vec_ur_clear(mpfq_TAG_dst_field, mpfq_TAG_vec_ur *, unsigned int); void mpfq_TAG_vec_ur_set_zero(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, unsigned int); void mpfq_TAG_vec_ur_set_vec(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_ur_set(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_vec_ur, unsigned int); void mpfq_TAG_vec_ur_setcoef(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_elt_ur, unsigned int); void mpfq_TAG_vec_ur_getcoef(mpfq_TAG_dst_field, mpfq_TAG_dst_elt_ur, mpfq_TAG_src_vec_ur, unsigned int); void mpfq_TAG_vec_ur_add(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_vec_ur, mpfq_TAG_src_vec_ur, unsigned int); void mpfq_TAG_vec_ur_neg(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_vec_ur, unsigned int); void mpfq_TAG_vec_ur_rev(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_vec_ur, unsigned int); void mpfq_TAG_vec_ur_sub(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_vec_ur, mpfq_TAG_src_vec_ur, unsigned int); void mpfq_TAG_vec_scal_mul_ur(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_vec, mpfq_TAG_src_elt, unsigned int); void mpfq_TAG_vec_conv_ur(mpfq_TAG_dst_field, mpfq_TAG_dst_vec_ur, mpfq_TAG_src_vec, unsigned int, mpfq_TAG_src_vec, unsigned int); void mpfq_TAG_vec_reduce(mpfq_TAG_dst_field, mpfq_TAG_dst_vec, mpfq_TAG_dst_vec_ur, unsigned int);