Skip to content

Commit 5a88847

Browse files
authored
Merge pull request #1885 from albinahlback/mpn_mullow
Generic `mpn_mullow` and hardcoded ones for x86
2 parents 31bf7d3 + 4d1b7a7 commit 5a88847

File tree

9 files changed

+1495
-3
lines changed

9 files changed

+1495
-3
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,5 @@ flint.pc
6464
autom4te.cache/
6565
config.m4
6666
src/flint-mparam.h
67+
.gdb_history
68+
vgcore.*

Makefile.in

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ RM_F:=rm -f
5656
RM_RF:=rm -rf
5757
CP:=cp
5858
CP_A:=cp -a
59+
GDB:=gdb
5960

6061
STATIC:=@STATIC@
6162
SHARED:=@SHARED@
@@ -498,6 +499,16 @@ else
498499
-include $(BUILD_DIR)/test/*.d
499500
-include $(BUILD_DIR)/*/test/*.d
500501
endif
502+
else ifeq ($(MAKECMDGOALS), debug)
503+
ifdef MOD
504+
$(warning Dependency tracking only set to cover the test executables of $(MOD).)
505+
-include $(foreach dir, $(MOD), $(BUILD_DIR)/$(dir)/test/*.d)
506+
else
507+
-include $(BUILD_DIR)/*/*.o.d
508+
-include $(BUILD_DIR)/*/*.lo.d
509+
-include $(BUILD_DIR)/test/*.d
510+
-include $(BUILD_DIR)/*/test/*.d
511+
endif
501512
else ifeq ($(MAKECMDGOALS), tune)
502513
-include $(BUILD_DIR)/*/*.o.d
503514
-include $(BUILD_DIR)/*/*.lo.d
@@ -798,6 +809,25 @@ check: library $(TESTS:%=%_TEST_RUN)
798809
@echo 'All tests passed.'
799810
endif
800811

812+
################################################################################
813+
# debugging
814+
################################################################################
815+
816+
%_TEST_DBG_RUN_ARGS: %
817+
@$(GDB) --args $< $(ARGS)
818+
819+
ifdef MOD
820+
ifdef ARGS
821+
DEBUG:=1
822+
debug: library $(patsubst %,%_TEST_DBG_RUN_ARGS, $($(sort $(MOD))_TESTS))
823+
endif
824+
endif
825+
826+
ifneq ($(DEBUG),1)
827+
debug:
828+
$(error Can only run debugger with one module and one argument at a time)
829+
endif
830+
801831
################################################################################
802832
# tuning
803833
################################################################################
@@ -952,11 +982,11 @@ dist:
952982
dev/make_dist.sh $(FLINT_VERSION)
953983

954984
################################################################################
955-
# debugging
985+
# makefile debugging
956986
################################################################################
957987

958988
print-%:
959989
@echo "$*=$($*)"
960990

961-
.PHONY: all library shared static examples checkexamples profile tests check tune valgrind clean distclean install uninstall dist %_TEST_RUN %_VALGRIND_RUN print-% coverage coverage_html
962-
.SILENT: $(mpn_extras_S_SOURCES)
991+
.PHONY: all library shared static examples checkexamples profile tests check tune valgrind clean distclean install uninstall dist %_TEST_RUN %_TEST_RUN_% %_TEST_DGB_RUN_ARGS %_VALGRIND_RUN print-% coverage coverage_html debug
992+
.PRECIOUS: $(mpn_extras_PIC_S_SOURCES) $(mpn_extras_S_SOURCES)

src/mpn_extras.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,36 @@ flint_mpn_sqr(mp_ptr r, mp_srcptr x, mp_size_t n)
370370
flint_mpn_mul((_z), (_y), (_yn), (_x), (_xn)); \
371371
}
372372

373+
/* Low multiplication ********************************************************/
374+
375+
#define FLINT_HAVE_MULLOW_FUNC(n) ((n) <= FLINT_MPN_MULLOW_FUNC_TAB_WIDTH)
376+
377+
FLINT_DLL extern const flint_mpn_mul_func_t flint_mpn_mullow_func_tab[];
378+
379+
mp_limb_t flint_mpn_mullow_basecase(mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
380+
381+
#if FLINT_HAVE_ASSEMBLY_x86_64_adx
382+
# define FLINT_MPN_MULLOW_FUNC_TAB_WIDTH 8
383+
# define FLINT_HAVE_NATIVE_mpn_mullow_basecase 1
384+
#else
385+
# define FLINT_MPN_MULLOW_FUNC_TAB_WIDTH 0
386+
#endif
387+
388+
/* TODO: Fix higher stuff */
389+
MPN_EXTRAS_INLINE
390+
mp_limb_t flint_mpn_mullow_n(mp_ptr rp, mp_srcptr xp, mp_srcptr yp, mp_size_t n)
391+
{
392+
FLINT_ASSERT(n >= 1);
393+
394+
if (FLINT_HAVE_MULLOW_FUNC(n))
395+
{
396+
FLINT_ASSERT(rp != xp);
397+
return flint_mpn_mullow_func_tab[n](rp, xp, yp);
398+
}
399+
else
400+
return flint_mpn_mullow_basecase(rp, xp, yp, n);
401+
}
402+
373403
/* High multiplication *******************************************************/
374404

375405
#define FLINT_HAVE_MULHIGH_FUNC(n) ((n) <= FLINT_MPN_MULHIGH_FUNC_TAB_WIDTH)

src/mpn_extras/mullow.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright (C) 2024 Albin Ahlbäck
3+
4+
This file is part of FLINT.
5+
6+
FLINT is free software: you can redistribute it and/or modify it under
7+
the terms of the GNU Lesser General Public License (LGPL) as published
8+
by the Free Software Foundation; either version 3 of the License, or
9+
(at your option) any later version. See <https://www.gnu.org/licenses/>.
10+
*/
11+
12+
#include "mpn_extras.h"
13+
14+
#if FLINT_HAVE_ASSEMBLY_x86_64_adx
15+
mp_limb_t flint_mpn_mullow_1(mp_ptr, mp_srcptr, mp_srcptr);
16+
mp_limb_t flint_mpn_mullow_2(mp_ptr, mp_srcptr, mp_srcptr);
17+
mp_limb_t flint_mpn_mullow_3(mp_ptr, mp_srcptr, mp_srcptr);
18+
mp_limb_t flint_mpn_mullow_4(mp_ptr, mp_srcptr, mp_srcptr);
19+
mp_limb_t flint_mpn_mullow_5(mp_ptr, mp_srcptr, mp_srcptr);
20+
mp_limb_t flint_mpn_mullow_6(mp_ptr, mp_srcptr, mp_srcptr);
21+
mp_limb_t flint_mpn_mullow_7(mp_ptr, mp_srcptr, mp_srcptr);
22+
mp_limb_t flint_mpn_mullow_8(mp_ptr, mp_srcptr, mp_srcptr);
23+
24+
const flint_mpn_mul_func_t flint_mpn_mullow_func_tab[] =
25+
{
26+
NULL,
27+
flint_mpn_mullow_1,
28+
flint_mpn_mullow_2,
29+
flint_mpn_mullow_3,
30+
flint_mpn_mullow_4,
31+
flint_mpn_mullow_5,
32+
flint_mpn_mullow_6,
33+
flint_mpn_mullow_7,
34+
flint_mpn_mullow_8
35+
};
36+
#else
37+
const flint_mpn_mul_func_t flint_mpn_mullow_func_tab[] = { NULL };
38+
#endif
39+
40+
#if !FLINT_HAVE_NATIVE_mpn_mullow_basecase
41+
mp_limb_t
42+
flint_mpn_mullow_basecase(mp_ptr rp, mp_srcptr xp, mp_srcptr yp, mp_size_t n)
43+
{
44+
mp_limb_t ret;
45+
mp_size_t ix;
46+
47+
ret = mpn_mul_1(rp, xp, n, yp[0]);
48+
49+
for (ix = 1; ix < n; ix++)
50+
{
51+
ret += mpn_addmul_1(rp + ix, xp, n - ix, yp[ix]);
52+
ret += xp[n - ix] * yp[ix];
53+
}
54+
55+
return ret;
56+
}
57+
#endif

src/mpn_extras/profile/p-mullow.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
Copyright (C) 2024 Albin Ahlbäck
3+
4+
This file is part of FLINT.
5+
6+
FLINT is free software: you can redistribute it and/or modify it under
7+
the terms of the GNU Lesser General Public License (LGPL) as published
8+
by the Free Software Foundation; either version 3 of the License, or
9+
(at your option) any later version. See <https://www.gnu.org/licenses/>.
10+
*/
11+
12+
#include "mpn_extras.h"
13+
#include "profiler.h"
14+
15+
#define mpn_mullo_basecase __gmpn_mullo_basecase
16+
void mpn_mullo_basecase(mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
17+
18+
#define N_MIN 1
19+
#define N_MAX 30
20+
21+
#if N_MAX < 9
22+
# define P 1
23+
#elif N_MAX < 99
24+
# define P 2
25+
#elif N_MAX < 999
26+
# define P 3
27+
#elif N_MAX < 9999
28+
# define P 4
29+
#else
30+
# define P 5
31+
#endif
32+
33+
#define _STR(x) #x
34+
#define STR(x) _STR(x)
35+
36+
int
37+
main(void)
38+
{
39+
mp_limb_t rp[2 * N_MAX];
40+
mp_limb_t xp[N_MAX];
41+
mp_limb_t yp[N_MAX];
42+
mp_size_t n;
43+
44+
flint_printf("%.*s mullo_basecase / FLINT || mul / mullow\n", P, " ");
45+
for (n = N_MIN; n <= N_MAX; n++)
46+
{
47+
double t1, t2, t3, FLINT_SET_BUT_UNUSED(__);
48+
flint_printf("n = %" STR(P) "wd:", n);
49+
50+
mpn_random2(xp, n);
51+
mpn_random2(yp, n);
52+
53+
TIMEIT_START
54+
mpn_mullo_basecase(rp, xp, yp, n);
55+
TIMEIT_STOP_VALUES(__, t1)
56+
57+
TIMEIT_START
58+
flint_mpn_mul_n(rp, xp, yp, n);
59+
TIMEIT_STOP_VALUES(__, t2)
60+
61+
TIMEIT_START
62+
flint_mpn_mullow_n(rp, xp, yp, n);
63+
TIMEIT_STOP_VALUES(__, t3)
64+
65+
flint_printf(" %7.2fx || %7.2f\n", t1 / t3, t2 / t3);
66+
}
67+
68+
flint_cleanup_master();
69+
70+
return 0;
71+
}
72+
73+
#undef N_MIN
74+
#undef N_MAX

src/mpn_extras/test/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "t-mul.c"
2525
#include "t-mul_n.c"
2626
#include "t-mul_toom22.c"
27+
#include "t-mullow_n.c"
2728
#include "t-mulhigh.c"
2829
#include "t-mulhigh_normalised.c"
2930
#include "t-mulmod_2expp1.c"
@@ -48,6 +49,7 @@ test_struct tests[] =
4849
TEST_FUNCTION(flint_mpn_mul),
4950
TEST_FUNCTION(flint_mpn_mul_n),
5051
TEST_FUNCTION(flint_mpn_mul_toom22),
52+
TEST_FUNCTION(flint_mpn_mullow_n),
5153
TEST_FUNCTION(flint_mpn_mulhigh),
5254
TEST_FUNCTION(flint_mpn_mulhigh_normalised),
5355
TEST_FUNCTION(flint_mpn_mulmod_2expp1),

src/mpn_extras/test/t-mullow_n.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
Copyright (C) 2024 Albin Ahlbäck
3+
4+
This file is part of FLINT.
5+
6+
FLINT is free software: you can redistribute it and/or modify it under
7+
the terms of the GNU Lesser General Public License (LGPL) as published
8+
by the Free Software Foundation; either version 3 of the License, or
9+
(at your option) any later version. See <https://www.gnu.org/licenses/>.
10+
*/
11+
12+
#include "test_helpers.h"
13+
#include "mpn_extras.h"
14+
15+
#define N_MIN 1
16+
#define N_MAX 30
17+
18+
TEST_FUNCTION_START(flint_mpn_mullow_n, state)
19+
{
20+
slong ix;
21+
int result;
22+
23+
mp_ptr rp, rpf, xp, yp;
24+
25+
for (ix = 0; ix < 100000 * flint_test_multiplier(); ix++)
26+
{
27+
mp_limb_t ret;
28+
mp_size_t n;
29+
30+
n = N_MIN + n_randint(state, N_MAX - N_MIN + 1);
31+
32+
rp = flint_malloc(sizeof(mp_limb_t) * n);
33+
rpf = flint_malloc(2 * sizeof(mp_limb_t) * n);
34+
xp = flint_malloc(sizeof(mp_limb_t) * n);
35+
yp = flint_malloc(sizeof(mp_limb_t) * n);
36+
37+
mpn_random2(xp, n);
38+
mpn_random2(yp, n);
39+
40+
if (ix < 1)
41+
continue;
42+
43+
ret = flint_mpn_mullow_n(rp, xp, yp, n);
44+
flint_mpn_mul_n(rpf, xp, yp, n);
45+
46+
result = (mpn_cmp(rp, rpf, n) == 0 && ret == rpf[n]);
47+
if (!result)
48+
TEST_FUNCTION_FAIL(
49+
"ix = %wd\n"
50+
"n = %wd\n"
51+
"xp = %{ulong*}\n"
52+
"yp = %{ulong*}\n"
53+
"Exp ret: %{ulong}\n"
54+
"Got ret: %{ulong}\n"
55+
"Expected: %{ulong*}\n"
56+
"Got: %{ulong*}\n",
57+
ix, n, xp, n, yp, n, rpf[n], ret, rpf, n, rp, n);
58+
59+
flint_free(rp);
60+
flint_free(rpf);
61+
flint_free(xp);
62+
flint_free(yp);
63+
}
64+
65+
TEST_FUNCTION_END(state);
66+
}
67+
68+
#undef N_MIN
69+
#undef N_MAX

0 commit comments

Comments
 (0)