General API of an MPFQ field

All finite fields in MPFQ follow the same API that is defined in the file 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 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_MPN, MPFQ_PRIME_MPZ or MPFQ_POLYNOMIAL. The last argument identifies the finite field your want. For MPFQ_PRIME_MPN, one must pass an mp_limb_t * value of the proper width to be used by the implementation. For MPFQ_PRIME_MPZ, you must pass an mpz value. In the case of MPFQ_POLYNOMIAL, this will depend on the underlying field, which is admittedly somewhat messy. Whether MPFQ_PRIME_MPN or MPFQ_PRIME_MPZ is recognized, or both, is presently not specified. At the moment MPFQ_PRIME_MPZ is always recognized, this might also be the case of MPFQ_PRIME_MPN later on.

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_t);
    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_t, 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);

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.

    /* 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);