Dot products
#include <flint/gr_vec.h>int _gr_vec_dot(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx)sourceint _gr_vec_dot_rev(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, gr_srcptr vec2, slong len, gr_ctx_t ctx)sourceSet res to c + \sum_{i=0}^{n-1} a_i b_i, respectively c + \sum_{i=0}^{n-1} a_i b_{n-1-i}, or c - \sum if subtract is nonzero, where a = vec1, b = vec2, n = len and c = initial, which may be NULL for c = 0.
int _gr_vec_dot_strided(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, slong stride1, gr_srcptr vec2, slong stride2, slong len, gr_ctx_t ctx)sourceSets res to c \pm \sum_{i=0}^{n-1} a_{i s_1} b_{i s_2} with strides s_1 = stride1 and s_2 = stride2 (in elements), which may be negative or zero.
int _gr_vec_dot_si(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const slong * vec2, slong len, gr_ctx_t ctx)sourceint _gr_vec_dot_ui(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const ulong * vec2, slong len, gr_ctx_t ctx)sourceint _gr_vec_dot_fmpz(gr_ptr res, gr_srcptr initial, int subtract, gr_srcptr vec1, const fmpz * vec2, slong len, gr_ctx_t ctx)sourceAs _gr_vec_dot, with the second vector an array of slong, ulong or fmpz integers.
The dot product c \pm \sum_i a_i b_i is the central vector operation of the generic interface. Classical polynomial multiplication computes each coefficient of a product as a reversed dot product (_gr_vec_dot_rev), classical and blocked matrix multiplication compute each entry as a dot product of a row and a column (_gr_vec_dot_strided or a dot product with a transposed operand), and triangular solving, LU decomposition, power series inversion and Newton iteration are built from the same primitive. A ring that implements only GR_METHOD_VEC_DOT and GR_METHOD_VEC_DOT_REV efficiently therefore speeds up most generic algorithms (Three levels of operations).
Arguments#
All variants compute
where n = len, a = vec1, b = vec2, the second form is used when subtract is nonzero, and c = initial may be NULL, which means c = 0. The index map is \sigma(i) = i for _gr_vec_dot, \sigma(i) = n - 1 - i for _gr_vec_dot_rev, and for _gr_vec_dot_strided the entries used are a_{i s_1} and b_{i s_2} for strides s_1, s_2 counted in elements, which may be negative. The variants _gr_vec_dot_si, _gr_vec_dot_ui and _gr_vec_dot_fmpz take b as a C array of integers, which is how integer matrices and polynomials act on vectors over other rings without converting the integers first. For n = 0 the result is c (or zero).
The output res may alias initial but not an entry of vec1 or vec2. Implementations may evaluate the sum in any order and with delayed reductions, so in floating-point rings the rounding differs from that of a loop of gr_addmul calls; ball arithmetic rings return a correct enclosure in any case.
Implementations#
The default gr_generic_vec_dot multiplies and adds through the method table. The strided default, for rings that override VEC_DOT but not VEC_DOT_STRIDED, gathers the strided entries into temporary arrays by shallow copies and calls _gr_vec_dot. Specialised versions include:
- \mathbb{Z}/n\mathbb{Z} (
nmod,nmod8,nmod32,nmod_redc): accumulation of products in two or three words with a single reduction at the end, as in_nmod_vec_dot(Dot products modulo a word-size integer). - \mathbb{Z}/n\mathbb{Z} for 2 to 16 limbs (
mpn_mod): unreduced multi-limb accumulation with delayed reduction (Delayed reduction for multiword moduli). - \mathbb{Z} (
fmpz):_fmpz_vec_dot_general, which accumulates the products in limb arrays, separately for small terms and for large positive and negative terms, without intermediatefmpzvalues. - Real and complex balls (
arb,acb):arb_dotandacb_dot, which sum exactly in a fixed-point accumulator and add a single error bound [Joh2019dot]. - Floating point (
arf,acf,nfloat,dfloat) and finite fields (fq,fq_nmod,fq_zech): their own vector dot products.
Example#
Dot products modulo 7 with the four variants, for a = (1, 2, 3, 4), b = (5, 6, 0, 2), c = 3 and the integer weights w = (1, -2, 3, -4):
#include <flint/flint.h>
#include <flint/gr.h>
#include <flint/gr_vec.h>
int main(void)
{
gr_ctx_t ctx;
gr_ptr a, b, c, res;
slong n = 4, w[4] = {1, -2, 3, -4};
int status = GR_SUCCESS;
gr_ctx_init_nmod(ctx, 7);
a = gr_heap_init_vec(n, ctx);
b = gr_heap_init_vec(n, ctx);
c = gr_heap_init(ctx);
res = gr_heap_init(ctx);
status |= _gr_vec_set_str(a, "[1, 2, 3, 4]", n, ctx);
status |= _gr_vec_set_str(b, "[5, 6, 0, 2]", n, ctx);
status |= gr_set_ui(c, 3, ctx);
status |= _gr_vec_dot(res, NULL, 0, a, b, n, ctx);
flint_printf("a.b = %{gr}\n", res, ctx);
status |= _gr_vec_dot(res, c, 1, a, b, n, ctx);
flint_printf("3 - a.b = %{gr}\n", res, ctx);
status |= _gr_vec_dot_rev(res, NULL, 0, a, b, n, ctx);
flint_printf("a.rev(b) = %{gr}\n", res, ctx);
status |= _gr_vec_dot_strided(res, NULL, 0, a, 2, b, 2, 2, ctx);
flint_printf("a0b0 + a2b2 = %{gr}\n", res, ctx);
status |= _gr_vec_dot_si(res, c, 0, a, w, n, ctx);
flint_printf("3 + a.w = %{gr}\n", res, ctx);
gr_heap_clear_vec(a, n, ctx);
gr_heap_clear_vec(b, n, ctx);
gr_heap_clear(c, ctx);
gr_heap_clear(res, ctx);
gr_ctx_clear(ctx);
flint_printf("status %d\n", status);
return 0;
}a.b = 4 3 - a.b = 6 a.rev(b) = 5 a0b0 + a2b2 = 5 3 + a.w = 0 status 0
Here a \cdot b = 25 \equiv 4, the reversed product is 1 \cdot 2 + 2 \cdot 0 + 3 \cdot 6 + 4 \cdot 5 = 40 \equiv 5, and 3 + a \cdot w = 3 - 10 \equiv 0.
Guides#
- Performance of dfloat (
dfloat) - Getting started with generic rings (
gr)
References#
- [Joh2019dot] F. Johansson. Faster arbitrary-precision dot product and matrix multiplication. Proceedings of the 26th IEEE Symposium on Computer Arithmetic (ARITH-26), 2019, 15–22. https://arxiv.org/abs/1901.04289
The FLINT team, “Dot products (gr_vec.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/gr_vec/dot.html (generated 2026-10-20).
@misc{flint-doc-gr-vec-dot,
author = {{The FLINT team}},
title = {{Dot products (gr\_vec.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/gr_vec/dot.html},
note = {Generated 2026-10-20}
}