gr.h (continued) – implementing rings¶
Defining a ring requires putting appropriate data into a
gr_ctx_t
parent object, most importantly the method table
and the size of elements.
Example¶
This is an extract from the fmpz
wrapper in gr/fmpz.c
:
/* Some methods */
...
int
_gr_fmpz_add(fmpz_t res, const fmpz_t x, const fmpz_t y, const gr_ctx_t ctx)
{
fmpz_add(res, x, y);
return GR_SUCCESS;
}
...
/* The method table */
int _fmpz_methods_initialized = 0;
gr_static_method_table _fmpz_methods;
gr_method_tab_input _fmpz_methods_input[] =
{
{GR_METHOD_CTX_IS_RING, (gr_funcptr) gr_generic_ctx_predicate_true},
...
{GR_METHOD_INIT, (gr_funcptr) _gr_fmpz_init},
{GR_METHOD_CLEAR, (gr_funcptr) _gr_fmpz_clear},
...
{GR_METHOD_ADD_FMPZ, (gr_funcptr) _gr_fmpz_add},
...
{0, (gr_funcptr) NULL},
};
/* Context object initializer */
void
gr_ctx_init_fmpz(gr_ctx_t ctx)
{
ctx->which_ring = GR_CTX_FMPZ;
ctx->sizeof_elem = sizeof(fmpz);
ctx->size_limit = WORD_MAX;
ctx->methods = _fmpz_methods;
if (!_fmpz_methods_initialized)
{
gr_method_tab_init(_fmpz_methods, _fmpz_methods_input);
_fmpz_methods_initialized = 1;
}
}
Note that the method table only has to be constructed once, allowing new context objects for the same domain to be initialized cheaply.
Method table¶
-
type gr_funcptr¶
Typedef for a pointer to a function with signature
int func(void)
, used to represent method table entries.
-
type gr_method¶
Enumeration type for indexing method tables. Enum values named
GR_METHOD_INIT
,GR_METHOD_ADD_UI
, etc. correspond to methodsgr_init
,gr_add_ui
, etc. The number of methods is given byGR_METHOD_TAB_SIZE
, which can be used to declare static method tables.
-
type gr_static_method_table¶
Typedef for an array of length
GR_METHOD_TAB_SIZE
withgr_funcptr
entries.
-
type gr_method_tab_input¶
Typedef representing a (index, function pointer) pair.
-
void gr_method_tab_init(gr_funcptr *methods, gr_method_tab_input *tab)¶
Initializes the method table methods. This first inserts default and generic methods in all slots, and then overwrites with the specialized methods listed in tab.
Placeholder and trivial methods¶
-
int gr_not_implemented(void)¶
This function does nothing and returns
GR_UNABLE
. It is used as a generic fallback method when no implementation is available.
-
int gr_not_in_domain(void)¶
This function does nothing and returns
GR_DOMAIN
. It can be used for an operation that never makes sense in the present domain, e.g.for the constant \(\pi\) in the rational numbers.
-
truth_t gr_generic_ctx_predicate(gr_ctx_t ctx)¶
Does nothing and returns
T_UNKNOWN
, used as a generic fallback for predicate methods.
Required methods¶
A context object must at minimum define the following methods for a ring:
init
clear
swap
randtest
write
zero
one
equal
set
set_si
set_ui
set_fmpz
neg
add
sub
mul
Other methods have generic defaults which may be overridden for performance or completeness.
Implementing context predicates (ctx_is_integral_domain
, ctx_is_field
, etc.)
is strongly recommended so that the most appropriate algorithms
can be used in generic implementations.
Rings with cheap operations on single elements should also provide non-generic versions of performance-critical vector operations to minimize overhead. The most important vector operations include:
vec_init
vec_clear
vec_swap
vec_zero
vec_neg
vec_add
vec_sub
vec_mul_scalar_ui
/si
vec_addmul_scalar_ui
/si
vec_dot
vec_dot_rev
Dot products, for example, are the main building block for classical polynomial multiplication and matrix multiplication. The methods
poly_mullow
matrix_mul
should be overridden for rings where faster-than-classical polynomial and matrix multiplication is possible. Other higher-complexity generic algorithms will try to reduce to polynomial and matrix multiplication automatically, but may in turn need to be overridden to select accurate cutoffs between different algorithms.