Algebraic structures are represented in the field_t data type, which mostly contains pointers to functions written to perform operations such as addition and multiplication on elements of that particular group, ring or field:
struct field_s {
...
void (*init)(element_ptr);
void (*clear)(element_ptr);
...
void (*add)(element_ptr, element_ptr, element_ptr);
void (*sub)(element_ptr, element_ptr, element_ptr);
void (*mul)(element_ptr, element_ptr, element_ptr);
...
};
typedef struct field_s *field_ptr;
typedef struct field_s field_t[1];
The name algebraic_structure_t is arguably more accurate, but far too cumbersome. If my naming choice causes discomfort, it may help if groups and rings are simply viewed as fields where certain things don't work!
The last two lines of the above code excerpt show how GMP, and PBC, define data types: they are actually arrays of length one so that when a variable is declared, space is automatically allocated for it. Yet when used as a argument to a function, a pointer is passed, thus there is no need to explicitly allocate and deallocate memory, nor reference and dereference variables.
Each element_t contains a field
named field to such a
field_t variable. The only other
field is data, which
stores any data needed for the implementation of the particular
algebraic structure the element resides in.
struct element_s {
struct field_s *field;
void *data;
};
When an element_t variable is
initialized, field is
set appropriately, and then the initialization specific to that
field is called to complete the initialization. Here, a line of
code is worth a thousand words:
void element_init(element_t e, field_ptr f)
{
e->field = f;
f->init(e);
}
Thus when a call to one of the element_ functions, the
field pointer is
followed to see which version of the function should be called,
so that for example modular addition is performed if the input
element is an element of a finite field, while polynomial
addition is performed for elements of a polynomial ring and so
on.
void element_add(element_t n, element_t a, element_t b)
{
n->field->add(n, a, b);
}