Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion demo/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2142,8 +2142,71 @@ static int test_s_mp_sqr_toom(void)
mp_clear_multi(&a, &b, &c, NULL);
return EXIT_FAILURE;
}
#if (MP_DIGIT_BIT > 16)
static int test_s_mp_mul_ntt(void)
{
mp_int a, b, c, d;
int size;

#if (MP_DIGIT_BIT == 60)
int tc_cutoff;
#endif

DOR(mp_init_multi(&a, &b, &c, &d, NULL));
/* This number construction is limb-size specific */
#if (MP_DIGIT_BIT == 60)
DO(mp_rand(&a, 1196));
DO(mp_mul_2d(&a,71787 - mp_count_bits(&a), &a));

DO(mp_rand(&b, 1338));
DO(mp_mul_2d(&b, 80318 - mp_count_bits(&b), &b));
DO(mp_mul_2d(&b, 6310, &b));
DO(mp_2expt(&c, 99000 - 1000));
DO(mp_add(&b, &c, &b));

tc_cutoff = MP_MUL_NTT_CUTOFF;
MP_MUL_NTT_CUTOFF = INT_MAX;
DO(mp_mul(&a, &b, &c));
MP_MUL_NTT_CUTOFF = tc_cutoff;
DO(mp_mul(&a, &b, &d));
EXPECT(mp_cmp(&c, &d) == MP_EQ);
#endif

for (size = MP_MUL_NTT_CUTOFF; size < (MP_MUL_NTT_CUTOFF + 20); size++) {
DO(mp_rand(&a, size));
DO(mp_rand(&b, size));
DO(s_mp_mul_ntt(&a, &b, &c));
DO(s_mp_mul_full(&a,&b,&d));
EXPECT(mp_cmp(&c, &d) == MP_EQ);
}

mp_clear_multi(&a, &b, &c, &d, NULL);
return EXIT_SUCCESS;
LBL_ERR:
mp_clear_multi(&a, &b, &c, &d, NULL);
return EXIT_FAILURE;
}

static int test_s_mp_sqr_ntt(void)
{
mp_int a, b, c;
int size;

DOR(mp_init_multi(&a, &b, &c, NULL));
for (size = MP_SQR_NTT_CUTOFF; size < (MP_SQR_NTT_CUTOFF + 20); size++) {
DO(mp_rand(&a, size));
DO(s_mp_sqr_ntt(&a, &b));
DO(s_mp_sqr(&a, &c));
EXPECT(mp_cmp(&b, &c) == MP_EQ);
}

mp_clear_multi(&a, &b, &c, NULL);
return EXIT_SUCCESS;
LBL_ERR:
mp_clear_multi(&a, &b, &c, NULL);
return EXIT_FAILURE;
}
#endif
static int test_mp_radix_size(void)
{
mp_int a;
Expand Down Expand Up @@ -2606,7 +2669,11 @@ static int unit_tests(int argc, char **argv)
T2(s_mp_mul_karatsuba, ONLY_PUBLIC_API, S_MP_MUL_KARATSUBA),
T2(s_mp_sqr_karatsuba, ONLY_PUBLIC_API, S_MP_SQR_KARATSUBA),
T2(s_mp_mul_toom, ONLY_PUBLIC_API, S_MP_MUL_TOOM),
T2(s_mp_sqr_toom, ONLY_PUBLIC_API, S_MP_SQR_TOOM)
T2(s_mp_sqr_toom, ONLY_PUBLIC_API, S_MP_SQR_TOOM),
#if (MP_DIGIT_BIT > 16)
T2(s_mp_mul_ntt, ONLY_PUBLIC_API, S_MP_MUL_NTT),
T2(s_mp_sqr_ntt, ONLY_PUBLIC_API, S_MP_SQR_NTT)
#endif
#undef T3
#undef T2
#undef T1
Expand Down
86 changes: 58 additions & 28 deletions etc/tune.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
static uint64_t s_timer_function(void);
static void s_timer_start(void);
static uint64_t s_timer_stop(void);
static uint64_t s_time_mul(int size);
static uint64_t s_time_sqr(int size);
static uint64_t s_time_mul(int size, int increment);
static uint64_t s_time_sqr(int size, int increment);
static void s_usage(char *s);

static uint64_t s_timer_function(void)
Expand Down Expand Up @@ -61,7 +61,7 @@ static int s_stabilization_extra;
static int s_offset = 1;

#define s_mp_mul_full(a, b, c) s_mp_mul(a, b, c, (a)->used + (b)->used + 1)
static uint64_t s_time_mul(int size)
static uint64_t s_time_mul(int size, int increment)
{
int x;
mp_err e;
Expand All @@ -83,7 +83,7 @@ static uint64_t s_time_mul(int size)
}

s_timer_start();
for (x = 0; x < s_number_of_test_loops; x++) {
for (x = 0; x < s_number_of_test_loops; x += increment) {
if ((e = mp_mul(&a,&b,&c)) != MP_OKAY) {
t1 = UINT64_MAX;
goto LBL_ERR;
Expand All @@ -107,7 +107,7 @@ static uint64_t s_time_mul(int size)
return t1;
}

static uint64_t s_time_sqr(int size)
static uint64_t s_time_sqr(int size, int increment)
{
int x;
mp_err e;
Expand All @@ -125,7 +125,7 @@ static uint64_t s_time_sqr(int size)
}

s_timer_start();
for (x = 0; x < s_number_of_test_loops; x++) {
for (x = 0; x < s_number_of_test_loops; x+=increment) {
if ((e = mp_sqr(&a,&b)) != MP_OKAY) {
t1 = UINT64_MAX;
goto LBL_ERR;
Expand Down Expand Up @@ -158,7 +158,7 @@ struct tune_args {
int increment_print;
} args;

static void s_run(const char *name, uint64_t (*op)(int size), int *cutoff)
static void s_run(const char *name, uint64_t (*op)(int size, int increment), int *cutoff, int increment)
{
int x, count = 0;
uint64_t t1, t2;
Expand All @@ -167,14 +167,14 @@ static void s_run(const char *name, uint64_t (*op)(int size), int *cutoff)
}
for (x = 8; x < args.upper_limit_print; x += args.increment_print) {
*cutoff = INT_MAX;
t1 = op(x);
t1 = op(x, increment);
if ((t1 == 0u) || (t1 == UINT64_MAX)) {
fprintf(stderr,"%s failed at x = INT_MAX (%s)\n", name,
(t1 == 0u)?"wrong result":"internal error");
exit(EXIT_FAILURE);
}
*cutoff = x;
t2 = op(x);
t2 = op(x, increment);
if ((t2 == 0u) || (t2 == UINT64_MAX)) {
fprintf(stderr,"%s failed (%s)\n", name,
(t2 == 0u)?"wrong result":"internal error");
Expand Down Expand Up @@ -243,6 +243,8 @@ static void s_usage(char *s)
fprintf(stderr," kss = karatsuba squaring\n");
fprintf(stderr," tc3m = Toom-Cook 3-way multiplication\n");
fprintf(stderr," tc3s = Toom-Cook 3-way squaring\n");
fprintf(stderr," nttm = NTT multiplication\n");
fprintf(stderr," ntts = NTT squaring\n");
fprintf(stderr," Implies '-p'\n");
fprintf(stderr," -h this message\n");
exit(s_exit_code);
Expand All @@ -251,17 +253,20 @@ static void s_usage(char *s)
struct cutoffs {
int MUL_KARATSUBA, SQR_KARATSUBA;
int MUL_TOOM, SQR_TOOM;
int MUL_NTT, SQR_NTT;
};

const struct cutoffs max_cutoffs =
{ INT_MAX, INT_MAX, INT_MAX, INT_MAX };
{ INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX};

static void set_cutoffs(const struct cutoffs *c)
{
MP_MUL_KARATSUBA_CUTOFF = c->MUL_KARATSUBA;
MP_SQR_KARATSUBA_CUTOFF = c->SQR_KARATSUBA;
MP_MUL_TOOM_CUTOFF = c->MUL_TOOM;
MP_SQR_TOOM_CUTOFF = c->SQR_TOOM;
MP_MUL_NTT_CUTOFF = c->MUL_NTT;
MP_SQR_NTT_CUTOFF = c->SQR_NTT;
}

static void get_cutoffs(struct cutoffs *c)
Expand All @@ -270,7 +275,8 @@ static void get_cutoffs(struct cutoffs *c)
c->SQR_KARATSUBA = MP_SQR_KARATSUBA_CUTOFF;
c->MUL_TOOM = MP_MUL_TOOM_CUTOFF;
c->SQR_TOOM = MP_SQR_TOOM_CUTOFF;

c->MUL_NTT = MP_MUL_NTT_CUTOFF;
c->SQR_NTT = MP_SQR_NTT_CUTOFF;
}

int main(int argc, char **argv)
Expand Down Expand Up @@ -302,7 +308,7 @@ int main(int argc, char **argv)
args.bncore = 0;
args.terse = 0;

args.upper_limit_print = 3000;
args.upper_limit_print = 20000;
args.increment_print = 1;

/* Very simple option parser, please treat it nicely. */
Expand Down Expand Up @@ -423,6 +429,10 @@ int main(int argc, char **argv)
MP_MUL_TOOM_CUTOFF = (int)s_strtol(str, &endptr, "[3/4] No value for MP_MUL_TOOM_CUTOFF given");
str = endptr + 1;
MP_SQR_TOOM_CUTOFF = (int)s_strtol(str, &endptr, "[4/4] No value for MP_SQR_TOOM_CUTOFF given");
str = endptr + 1;
MP_MUL_NTT_CUTOFF = (int)s_strtol(str, &endptr, "[3/4] No value for MP_MUL_NTT_CUTOFF given");
str = endptr + 1;
MP_SQR_NTT_CUTOFF = (int)s_strtol(str, &endptr, "[4/4] No value for MP_SQR_NTT_CUTOFF given");
break;
case 'h':
s_exit_code = EXIT_SUCCESS;
Expand All @@ -448,7 +458,7 @@ int main(int argc, char **argv)
struct {
const char *name;
int *cutoff, *update;
uint64_t (*fn)(int size);
uint64_t (*fn)(int size, int increment);
} test[] = {
#define T_MUL_SQR(n, o, f) { #n, &MP_##o##_CUTOFF, &(updated.o), MP_HAS(S_MP_##o) ? f : NULL }
/*
Expand All @@ -457,33 +467,49 @@ int main(int argc, char **argv)
of the macro MP_WPARRAY in tommath.h which needs to
be changed manually (to 0 (zero)).
*/
T_MUL_SQR("Karatsuba multiplication", MUL_KARATSUBA, s_time_mul),
T_MUL_SQR("Karatsuba squaring", SQR_KARATSUBA, s_time_sqr),
T_MUL_SQR("Toom-Cook 3-way multiplying", MUL_TOOM, s_time_mul),
T_MUL_SQR("Toom-Cook 3-way squaring", SQR_TOOM, s_time_sqr),
T_MUL_SQR("Karatsuba multiplication", MUL_KARATSUBA, s_time_mul), /* 0 */
T_MUL_SQR("Karatsuba squaring", SQR_KARATSUBA, s_time_sqr), /* 1 */
T_MUL_SQR("Toom-Cook 3-way multiplying", MUL_TOOM, s_time_mul), /* 2 */
T_MUL_SQR("Toom-Cook 3-way squaring", SQR_TOOM, s_time_sqr), /* 3 */
T_MUL_SQR("NTT multiplying", MUL_NTT, s_time_mul), /* 4 */
T_MUL_SQR("NTT squaring", SQR_NTT, s_time_sqr), /* 5 */
#undef T_MUL_SQR
};
/* Turn all limits from bncore.c to the max */
set_cutoffs(&max_cutoffs);
for (n = 0; n < sizeof(test)/sizeof(test[0]); ++n) {
for (n = 0; n < 4; ++n) {
if (test[n].fn != NULL) {
s_run(test[n].name, test[n].fn, test[n].cutoff, 1);
*test[n].update = *test[n].cutoff;
/* *test[n].cutoff = INT_MAX; */
}
}
for (n = 4; n < 6; ++n) {
if (test[n].fn != NULL) {
s_run(test[n].name, test[n].fn, test[n].cutoff);
s_run(test[n].name, test[n].fn, test[n].cutoff, 53);
*test[n].update = *test[n].cutoff;
*test[n].cutoff = INT_MAX;
/* Only test Karatsuba against school,
test the rest against the cutoff one lower */
/* *test[n].cutoff = INT_MAX; */
}
}
}
if (args.terse == 1) {
printf("%d %d %d %d\n",
printf("%d %d %d %d %d %d\n",
updated.MUL_KARATSUBA,
updated.SQR_KARATSUBA,
updated.MUL_TOOM,
updated.SQR_TOOM);
updated.SQR_TOOM,
updated.MUL_NTT,
updated.SQR_NTT);

} else {
printf("MUL_KARATSUBA_CUTOFF = %d\n", updated.MUL_KARATSUBA);
printf("SQR_KARATSUBA_CUTOFF = %d\n", updated.SQR_KARATSUBA);
printf("MUL_TOOM_CUTOFF = %d\n", updated.MUL_TOOM);
printf("SQR_TOOM_CUTOFF = %d\n", updated.SQR_TOOM);
printf("MUL_NTT_CUTOFF = %d\n", updated.MUL_NTT);
printf("SQR_NTT_CUTOFF = %d\n", updated.SQR_NTT);
}

if (args.print == 1) {
Expand All @@ -503,19 +529,19 @@ int main(int argc, char **argv)

for (x = 8; x < args.upper_limit_print; x += args.increment_print) {
set_cutoffs(&max_cutoffs);
t1 = s_time_mul(x);
t1 = s_time_mul(x,1);
set_cutoffs(&orig);
t2 = s_time_mul(x);
t2 = s_time_mul(x,1);
fprintf(multiplying, "%d: %9" PRIu64 " %9" PRIu64 ", %9" PRIi64 "\n", x, t1, t2, (int64_t)t2 - (int64_t)t1);
fflush(multiplying);
if (args.verbose == 1) {
printf("MUL %d: %9" PRIu64 " %9" PRIu64 ", %9" PRIi64 "\n", x, t1, t2, (int64_t)t2 - (int64_t)t1);
fflush(stdout);
}
set_cutoffs(&max_cutoffs);
t1 = s_time_sqr(x);
t1 = s_time_sqr(x,1);
set_cutoffs(&orig);
t2 = s_time_sqr(x);
t2 = s_time_sqr(x,1);
fprintf(squaring,"%d: %9" PRIu64 " %9" PRIu64 ", %9" PRIi64 "\n", x, t1, t2, (int64_t)t2 - (int64_t)t1);
fflush(squaring);
if (args.verbose == 1) {
Expand All @@ -527,16 +553,20 @@ int main(int argc, char **argv)
if (args.verbose == 1) {
set_cutoffs(&orig);
if (args.terse == 1) {
printf("%d %d %d %d\n",
printf("%d %d %d %d %d %d\n",
MP_MUL_KARATSUBA_CUTOFF,
MP_SQR_KARATSUBA_CUTOFF,
MP_MUL_TOOM_CUTOFF,
MP_SQR_TOOM_CUTOFF);
MP_SQR_TOOM_CUTOFF,
MP_MUL_NTT_CUTOFF,
MP_SQR_NTT_CUTOFF);
} else {
printf("MUL_KARATSUBA_CUTOFF = %d\n", MP_MUL_KARATSUBA_CUTOFF);
printf("SQR_KARATSUBA_CUTOFF = %d\n", MP_SQR_KARATSUBA_CUTOFF);
printf("MUL_TOOM_CUTOFF = %d\n", MP_MUL_TOOM_CUTOFF);
printf("SQR_TOOM_CUTOFF = %d\n", MP_SQR_TOOM_CUTOFF);
printf("MUL_NTT_CUTOFF = %d\n", MP_MUL_NTT_CUTOFF);
printf("SQR_NTT_CUTOFF = %d\n", MP_SQR_NTT_CUTOFF);
}
}
}
Expand Down
26 changes: 22 additions & 4 deletions etc/tune_it.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ RNUM=0
# test are running if you do not have enough memory to avoid page faults. #
#############################################################################

# TODO: Because of NTT the defaults of LIMIT is down from 100, RLOOPS down from 10
# and LAG is up from 3
# Number of rounds overall.
LIMIT=100
LIMIT=10
# Number of loops for each input.
RLOOPS=10
RLOOPS=3
# Offset ( > 0 ) . Runs tests with asymmetric input of the form 1:OFFSET
# Please use another destination for TOMMATH_CUTOFFS_H if you change OFFSET, because the numbers
# with an offset different from 1 (one) are not usable as the general cut-off values
Expand All @@ -45,7 +47,7 @@ OFFSET=1
# Number ( >= 3 ) of positive results (TC-is-faster) accumulated until it is accepted.
# Due to the algorithm used to compute the median in this Posix compliant shell script
# the value needs to be 3 (three), not less, to keep the variation small.
LAG=3
LAG=100
# Keep the temporary file $FILE_NAME. Set to 0 (zero) to remove it at the end.
# The file is in a format fit to feed into R directly. If you do it and find the median
# of this program to be off by more than a couple: please contact the authors and report
Expand All @@ -56,7 +58,7 @@ KEEP_TEMP=1
echo "You might like to watch the numbers go up to $LIMIT but it will take a long time!"

# Might not have sufficient rights or disc full.
echo "km ks tc3m tc3s" > $FILE_NAME || die "Writing header to $FILE_NAME" $?
echo "km ks tc3m tc3s nttm ntts" > $FILE_NAME || die "Writing header to $FILE_NAME" $?
i=1
while [ $i -le $LIMIT ]; do
RNUM=$(LCG)
Expand Down Expand Up @@ -104,3 +106,19 @@ echo "#define MP_DEFAULT_MUL_TOOM_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die
TMP=$(median $FILE_NAME 4 $i)
echo "#define MP_DEFAULT_SQR_TOOM_CUTOFF $TMP"
echo "#define MP_DEFAULT_SQR_TOOM_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(tc3s) Appending to $TOMMATH_CUTOFFS_H" $?
TMP=$(median $FILE_NAME 5 $i)
echo "#define MP_DEFAULT_MUL_NTT_CUTOFF $TMP"
echo "#define MP_DEFAULT_MUL_NTT_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(nttm) Appending to $TOMMATH_CUTOFFS_H" $?
TMP=$(median $FILE_NAME 6 $i)
echo "#define MP_DEFAULT_SQR_NTT_CUTOFF $TMP"
echo "#define MP_DEFAULT_SQR_NTT_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(ntts) Appending to $TOMMATH_CUTOFFS_H" $?










2 changes: 2 additions & 0 deletions helper.pl
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,8 @@ sub generate_def {
MP_SQR_KARATSUBA_CUTOFF
MP_MUL_TOOM_CUTOFF
MP_SQR_TOOM_CUTOFF
MP_MUL_NTT_CUTOFF
MP_SQR_NTT_CUTOFF
";
return 0;
}
Expand Down
Loading
Loading