/* tune-gcd-p
Tune the choice for splitting p in divide - and - conquer gcd .
Copyright 2008 , 2010 , 2011 Free Software Foundation , Inc .
This file is part of the GNU MP Library .
The GNU MP Library is free software ; you can redistribute it and / or modify
it under the terms of either :
* the GNU Lesser General Public License as published by the Free
Software Foundation ; either version 3 of the License , or ( at your
option ) any later version .
or
* the GNU General Public License as published by the Free Software
Foundation ; either version 2 of the License , or ( at your option ) any
later version .
or both in parallel , as here .
The GNU MP Library 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 copies of the GNU General Public License and the
GNU Lesser General Public License along with the GNU MP Library . If not ,
see https://www.gnu.org/licenses/. */
#define TUNE_GCD_P
1
#include "../mpn/gcd.c"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "speed.h"
/* Search for minimum over a range. FIXME: Implement golden-section /
fibonacci search*/
static int
search (
double *minp,
double (*f)(
void *,
int ),
void *ctx,
int start,
int end)
{
int x[
4 ];
double y[
4 ];
int best_i;
x[
0 ] = start;
x[
3 ] = end;
y[
0 ] = f(ctx, x[
0 ]);
y[
3 ] = f(ctx, x[
3 ]);
for (;;)
{
int i;
int length = x[
3 ] - x[
0 ];
x[
1 ] = x[
0 ] + length/
3 ;
x[
2 ] = x[
0 ] +
2 *length/
3 ;
y[
1 ] = f(ctx, x[
1 ]);
y[
2 ] = f(ctx, x[
2 ]);
#if 0
printf(
"%d: %f, %d: %f, %d:, %f %d: %f\n" ,
x[
0 ], y[
0 ], x[
1 ], y[
1 ], x[
2 ], y[
2 ], x[
3 ], y[
3 ]);
#endif
for (best_i =
0 , i =
1 ; i <
4 ; i++)
if (y[i] < y[best_i])
best_i = i;
if (length <=
4 )
break ;
if (best_i >=
2 )
{
x[
0 ] = x[
1 ];
y[
0 ] = y[
1 ];
}
else
{
x[
3 ] = x[
2 ];
y[
3 ] = y[
2 ];
}
}
*minp = y[best_i];
return x[best_i];
}
static int
compare_double(
const void *ap,
const void *bp)
{
double a = * (
const double *) ap;
double b = * (
const double *) bp;
if (a < b)
return -
1 ;
else if (a > b)
return 1 ;
else
return 0 ;
}
static double
median (
double *v, size_t n)
{
qsort(v, n,
sizeof (*v), compare_double);
return v[n/
2 ];
}
#define TIME(res, code)
do { \
double time_measurement[
5 ]; \
unsigned time_i; \
\
for (time_i =
0 ; time_i <
5 ; time_i++) \
{ \
speed_starttime(); \
code; \
time_measurement[time_i] = speed_endtime(); \
} \
res = median(time_measurement,
5 ); \
}
while (
0 )
struct bench_data
{
mp_size_t n;
mp_ptr ap;
mp_ptr bp;
mp_ptr up;
mp_ptr vp;
mp_ptr gp;
};
static double
bench_gcd (
void *ctx,
int p)
{
struct bench_data *data = (
struct bench_data *) ctx;
double t;
p_table[data->n] = p;
TIME(t, {
MPN_COPY (data->up, data->ap, data->n);
MPN_COPY (data->vp, data->bp, data->n);
mpn_gcd (data->gp, data->up, data->n, data->vp, data->n);
});
return t;
}
int
main(
int argc,
char **argv)
{
gmp_randstate_t rands;
struct bench_data data;
mp_size_t n;
TMP_DECL;
/* Unbuffered so if output is redirected to a file it isn't lost if the
program is killed part way through. */
setbuf (stdout, NULL);
setbuf (stderr, NULL);
gmp_randinit_default (rands);
TMP_MARK;
data.ap = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
data.bp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
data.up = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
data.vp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
data.gp = TMP_ALLOC_LIMBS (P_TABLE_SIZE);
mpn_random (data.ap, P_TABLE_SIZE);
mpn_random (data.bp, P_TABLE_SIZE);
memset (p_table,
0 ,
sizeof (p_table));
for (n =
100 ; n < P_TABLE_SIZE; n++)
{
mp_size_t p;
mp_size_t best_p;
double best_time;
double lehmer_time;
if (data.ap[n-
1 ] ==
0 )
data.ap[n-
1 ] =
1 ;
if (data.bp[n-
1 ] ==
0 )
data.bp[n-
1 ] =
1 ;
data.n = n;
lehmer_time = bench_gcd (&data,
0 );
best_p = search (&best_time, bench_gcd, &data, n/
5 ,
4 *n/
5 );
if (best_time > lehmer_time)
best_p =
0 ;
printf(
"%6zu %6zu %5.3g" , n, best_p, (
double ) best_p / n);
if (best_p >
0 )
{
double speedup =
100 * (lehmer_time - best_time) / lehmer_time;
printf(
" %5.3g%%" , speedup);
if (speedup <
1 .
0 )
{
printf(
" (ignored)" );
best_p =
0 ;
}
}
printf(
"\n" );
p_table[n] = best_p;
}
TMP_FREE;
gmp_randclear(rands);
return 0 ;
}
Messung V0.5 in Prozent C=89 H=99 G=94
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland