/*
mul-profile-main.c: program for profiling multiplication (various zn_poly
algorithms, and optionally NTL)
Copyright (C) 2007, 2008, David Harvey
This file is part of the zn_poly library (version 0.8).
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*
Note: if this file is compiled with the constant PROFILE_NTL defined, then
it will include support for NTL profiling, and needs to be compiled as C++.
Otherwise it can be compiled as a C program.
*/
#include
#include
#include "support.h"
#include "profiler.h"
#include "zn_poly_internal.h"
#include "zn_poly.h"
/*
Performs and prints one line of profiling output, for the given number
of bits and polynomial length.
active[i] is a flag indicating whether the algorithm indexed by i
should be profiled (see ALGO_MUL_xyz constants).
*/
void do_line(int* active, unsigned bits, size_t len, int squaring)
{
char* names[] = {"best",
"ks1", "ks1_redc", "ks2", "ks2_redc",
"ks3", "ks3_redc", "ks4", "ks4_redc",
"fft", "ntl"};
profile_mul_info_t info;
info->len = len;
// choose an odd modulus exactly _bits_ bits long
info->n = (1UL << (bits - 1))
+ 2 * random_ulong(1UL << (bits - 2)) + 1;
info->squaring = squaring;
printf("len = %5lu, bits = %2u", len, bits);
fflush(stdout);
int algo;
for (algo = 0; algo < 11; algo++)
{
if (active[algo])
{
info->algo = algo;
double spread;
double result = profile(&spread, NULL, profile_mul, &info, 1.0);
printf(", %s = %.3le (%.1lf%%)", names[algo], result, 100 * spread);
fflush(stdout);
}
}
printf("\n");
}
#if __cplusplus
extern "C"
#endif
void prof_main(int argc, char* argv[])
{
// read command line arguments
// can include the strings "best", "ks1", "ks1_redc", "ks2", "ks2_redc",
// "ks3", "ks3_redc", "ks4", "ks4_redc", "fft", "ntl"
// to select various algorithms
// can also include "sqr" anywhere, which means to profile squaring
// if you do "bits " then only that number of bits will be profiled
// otherwise it ranges over various bitsizes
// if you do "length " then only that length will be profiled
// otherwise it ranges over various lengths
int active[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int any_active = 0;
int squaring = 0;
int do_one_bits = 0;
int chosen_bits = 0;
int do_one_length = 0;
ulong chosen_length = 0;
int i;
for (i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "best"))
active[ALGO_MUL_BEST] = any_active = 1;
else if (!strcmp(argv[i], "ks1"))
active[ALGO_MUL_KS1] = any_active = 1;
else if (!strcmp(argv[i], "ks1_redc"))
active[ALGO_MUL_KS1_REDC] = any_active = 1;
else if (!strcmp(argv[i], "ks2"))
active[ALGO_MUL_KS2] = any_active = 1;
else if (!strcmp(argv[i], "ks2_redc"))
active[ALGO_MUL_KS2_REDC] = any_active = 1;
else if (!strcmp(argv[i], "ks3"))
active[ALGO_MUL_KS3] = any_active = 1;
else if (!strcmp(argv[i], "ks3_redc"))
active[ALGO_MUL_KS3_REDC] = any_active = 1;
else if (!strcmp(argv[i], "ks4"))
active[ALGO_MUL_KS4] = any_active = 1;
else if (!strcmp(argv[i], "ks4_redc"))
active[ALGO_MUL_KS4_REDC] = any_active = 1;
else if (!strcmp(argv[i], "fft"))
active[ALGO_MUL_FFT] = any_active = 1;
else if (!strcmp(argv[i], "ntl"))
active[ALGO_MUL_NTL] = any_active = 1;
else if (!strcmp(argv[i], "bits"))
{
do_one_bits = 1;
chosen_bits = atoi(argv[++i]);
}
else if (!strcmp(argv[i], "length"))
{
do_one_length = 1;
chosen_length = atol(argv[++i]);
}
else if (!strcmp(argv[i], "sqr"))
{
squaring = 1;
}
else
{
printf("unknown option %s\n", argv[i]);
exit(1);
}
}
if (!any_active)
active[0] = 1; // profile plain multiplication if nothing selected
// bitsizes to use by default if none are selected
unsigned bitsizes[9] = {4, 8, 16, 24, 32, 40, 48, 56, 64};
int j;
size_t len;
unsigned bits;
if (do_one_bits && do_one_length)
{
do_line(active, chosen_bits, chosen_length, squaring);
}
else if (do_one_bits && !do_one_length)
{
// loop over lengths, spaced out logarithmically
for (j = 0; j < 120; j++)
{
size_t new_len = (size_t) floor(pow(1.1, (double) j));
if (new_len == len)
continue;
len = new_len;
do_line(active, chosen_bits, len, squaring);
}
}
else if (!do_one_bits && do_one_length)
{
// loop over bitsizes in above table
for (i = 0; i < sizeof(bitsizes) / sizeof(bitsizes[0]); i++)
do_line(active, bitsizes[i], chosen_length, squaring);
}
else // neither bits nor length is fixed
{
// loop over bitsizes in above table
for (i = 0; i < sizeof(bitsizes) / sizeof(bitsizes[0]); i++)
{
// loop over lengths, spaced out logarithmically
for (j = 0; j < 120; j++)
{
size_t new_len = (size_t) floor(pow(1.1, (double) j));
if (new_len == len)
continue;
len = new_len;
do_line(active, bitsizes[i], len, squaring);
}
printf("-------------------------------------------\n");
}
}
}
// end of file ****************************************************************