diff options
Diffstat (limited to 'tools/mbench/mpfr-gfx.c')
-rw-r--r-- | tools/mbench/mpfr-gfx.c | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/tools/mbench/mpfr-gfx.c b/tools/mbench/mpfr-gfx.c new file mode 100644 index 000000000..aa66adc85 --- /dev/null +++ b/tools/mbench/mpfr-gfx.c @@ -0,0 +1,447 @@ +/* +Copyright 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +Contributed by Patrick Pelissier and Paul Zimmermann, INRIA. + +This file is part of the MPFR Library. + +The MPFR Library is free software; you can redistribute it and/or modify +it under the terms of 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. + +The MPFR 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 Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the MPFR Library; see the file COPYING.LESSER. If not, see +http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <string.h> +#include <limits.h> +#include <sys/time.h> +#include <sys/resource.h> + +#include "timp.h" + +/* To avoid __gmpf_cmp to be declared as pure */ +#define __GMP_NO_ATTRIBUTE_CONST_PURE +#include "gmp.h" +#include "mpfr.h" + +#ifdef SCS_SUPPORT +# define SCS(x) x +# include "scs.h" +# define EXTRA_TEST_LIST \ + BENCH("SCSLIB( Compiled var ):::::::::::", ; ); \ + BENCH("scs_add", scs_add(sc1,sc2,sc3)); \ + BENCH("scs_sub", scs_sub(sc1,sc2,sc3)); \ + BENCH("scs_mul", scs_mul(sc1,sc2,sc3)); \ + BENCH("scs_div", scs_div(sc1,sc2,sc3)); \ + BENCH("scs_set", scs_set(sc1,sc2)); \ + BENCH("scs_set0", scs_set_si(sc1,0)); \ + BENCH("scs_set1", scs_set_si(sc1,1)); +#else +# define SCS(x) ((void) 0) +# define EXTRA_TEST_LIST ((void)0); +#endif + +#undef EXTRA_TEST_LIST +# define EXTRA_TEST_LIST \ + BENCH("mpfr_exp", mpfr_exp(a,b,GMP_RNDN)); \ + BENCH("mpfr_log", mpfr_log(a,b,GMP_RNDN)); \ + BENCH("mpfr_sin", mpfr_sin(a,b,GMP_RNDN)); \ + BENCH("mpfr_cos", mpfr_cos(a,b,GMP_RNDN)); \ + BENCH("mpfr_tan", mpfr_tan(a,b,GMP_RNDN)); \ + BENCH("mpfr_asin", mpfr_asin(a,b,GMP_RNDN)); \ + BENCH("mpfr_acos", mpfr_acos(a,b,GMP_RNDN)); \ + BENCH("mpfr_atan", mpfr_atan(a,b,GMP_RNDN)); \ + BENCH("mpfr_agm", mpfr_agm(a,b,c,GMP_RNDN)); \ + BENCH("mpfr_const_log2", (mpfr_const_log2) (a, GMP_RNDN)); \ + BENCH("mpfr_const_pi", (mpfr_const_pi)(a, GMP_RNDN)); \ + BENCH("mpfr_sinh", mpfr_sinh(a,b,GMP_RNDN)); \ + BENCH("mpfr_cosh", mpfr_cosh(a,b,GMP_RNDN)); \ + BENCH("mpfr_tanh", mpfr_tanh(a,b,GMP_RNDN)); \ + BENCH("mpfr_asinh", mpfr_asinh(a,b,GMP_RNDN)); \ + BENCH("mpfr_acosh", mpfr_acosh(a,b,GMP_RNDN)); \ + BENCH("mpfr_atanh", mpfr_atanh(a,b,GMP_RNDN)); + + + +/* Theses macros help the compiler to determine if a test is likely*/ +/* or unlikely. */ +#if __GNUC__ >= 3 +# define LIKELY(x) (__builtin_expect(!!(x),1)) +# define UNLIKELY(x) (__builtin_expect((x),0)) +#else +# define LIKELY(x) (x) +# define UNLIKELY(x) (x) +#endif + +/* + * List of all the tests to do. + * Macro "BENCH" is defined below. + */ +#define TEST_LIST \ + BENCH("MPFR::::::::::", ; ); \ + BENCH("mpfr_add", mpfr_add(a,b,c,GMP_RNDN)); \ + BENCH("mpfr_sub", mpfr_sub(a,b,c,GMP_RNDN)); \ + BENCH("mpfr_mul", mpfr_mul(a,b,c,GMP_RNDN)); \ + BENCH("mpfr_div", mpfr_div(a,b,c,GMP_RNDN)); \ + BENCH("mpfr_sqrt", mpfr_sqrt(a,b,GMP_RNDN)); \ + BENCH("mpfr_cmp", mpfr_cmp(b,c)); \ + BENCH("mpfr_sgn", mpfr_sgn(b)); \ + BENCH("mpfr_set", mpfr_set(a,b, GMP_RNDN)); \ + BENCH("mpfr_set0", mpfr_set_si(a,0,GMP_RNDN)); \ + BENCH("mpfr_set1", mpfr_set_si(a,1,GMP_RNDN)); \ + BENCH("mpfr_swap", mpfr_swap(b,c)); \ + BENCH("MPF:::::::::::", ; ); \ + BENCH("mpf_add", mpf_add(x,y,z)); \ + BENCH("mpf_sub", mpf_sub(x,y,z)); \ + BENCH("mpf_mul", mpf_mul(x,y,z)); \ + BENCH("mpf_div", mpf_div(x,y,z)); \ + BENCH("mpf_sqrt", mpf_sqrt(x,y)); \ + BENCH("mpf_cmp", mpf_cmp(y,z)); \ + BENCH("mpf_set", mpf_set(x,y)); \ + BENCH("mpf_set0", mpf_set_si(x,0)); \ + BENCH("mpf_set1", mpf_set_si(x,1)); \ + BENCH("mpf_swap", mpf_swap(y,z)); \ + EXTRA_TEST_LIST + +#define USAGE \ + "Get the graph of the low-level functions of Mpfr (gnuplot).\n" \ + __FILE__" " __DATE__" " __TIME__" GCC "__VERSION__ "\n" \ + "Usage: mpfr-gfx [-bPREC_BEGIN] [-ePREC_END] [-sPREC_STEP] [-rPREC_RATIO]\n" \ + " [-mSTAT_SIZE] [-oFILENAME] [-xFUNCTION_NUM] [-yFUNCTION_NUM] [-c]\n" \ + " [-fSMOOTH] [-p]\n" + +unsigned long num; +mpf_t *xt, *yt, *zt; +int smooth = 3; /* (default) minimal number of routine calls for each number */ + +void lets_start(unsigned long n, mpfr_prec_t p) +{ + unsigned long i; + gmp_randstate_t state; + + num = n; + xt = malloc(sizeof(mpf_t) * num); + yt = malloc(sizeof(mpf_t) * num); + zt = malloc(sizeof(mpf_t) * num); + if (xt==NULL || yt==NULL || zt==NULL) + { + fprintf(stderr, "Can't allocate tables!\n"); + abort(); + } + + gmp_randinit_lc_2exp_size (state, 128); + gmp_randseed_ui (state, 1452369); + for(i = 0 ; i < num ; i++) + { + mpf_init2(xt[i], p); + mpf_init2(yt[i], p); + mpf_init2(zt[i], p); + mpf_urandomb(yt[i], state, p); + mpf_urandomb(zt[i], state, p); + } + gmp_randclear(state); +} + +void lets_end(void) +{ + unsigned long i; + + for(i = 0 ; i < num ; i++) + { + mpf_clear(xt[i]); + mpf_clear(yt[i]); + mpf_clear(zt[i]); + } + free (xt); + free (yt); + free (zt); +} + +double get_speed(mpfr_prec_t p, int select) +{ + unsigned long long mc[num], m; + mpfr_t a,b,c; + mpf_t x,y,z; + unsigned long long moy; + int i,j=0, op, cont, print_done = 0; + const char *str = "void"; + SCS(( scs_t sc1, sc2, sc3 )); + + mpf_init2(x, p); mpf_init2(y, p); mpf_init2(z, p); + mpfr_init2(a, p); mpfr_init2(b, p); mpfr_init2(c, p); + + for(i = 0 ; i < num ; i++) + { + // yt[i][0]._mp_exp = (rand() % p) / GMP_NUMB_BITS; + //zt[i][0]._mp_exp = (rand() % p) / GMP_NUMB_BITS; + mc[i] = 0xFFFFFFFFFFFFFFFLL; + } + + TIMP_OVERHEAD (); + + /* we perform at least smooth loops */ + for(j = 0, cont = smooth ; cont ; j++, cont--) + { + /* we loop over each of the num random numbers */ + for(i = 0 ; i < num ; i++) + { + /* Set var for tests */ + mpf_set(y, yt[i]); + mpf_set(z, zt[i]); + mpfr_set_f(b, yt[i], GMP_RNDN); + mpfr_set_f(c, zt[i], GMP_RNDN); + SCS(( scs_set_mpfr(sc2, b), scs_set_mpfr(sc3, c) )); + /* if the measured time m is smaller than the smallest one + observed so far mc[i] for the i-th random number, we start + again the smooth loops */ +#undef BENCH +#define BENCH(TEST_STR, TEST) \ + if (op++ == select) { \ + m = TIMP_MEASURE(TEST); \ + str = TEST_STR; \ + if (m < mc[i]) {mc[i] = m; cont = smooth;}\ + } + op = 0; + TEST_LIST; + if (print_done == 0 && strcmp (str, "void") != 0 ) + { + printf("Prec=%4.4lu Func=%20.20s", p, str); + fflush (stdout); + print_done = 1; + } + } + } + mpfr_clear(a); mpfr_clear(b); mpfr_clear(c); + mpf_clear(x); mpf_clear(y); mpf_clear(z); + /* End */ + /* Save result */ + moy = mc[0]; + for(i = 1 ; i < num ; i++) moy += mc[i]; + printf(" Pass=%4.4d..................%Lu.%Lu\n", + j+1, moy/num, (moy*100LL/num)%100LL); + return (double) (moy) / (double) num; +} + +/* compares two functions given by indices select1 and select2 + (by default select1 refers to mpfr and select2 to mpf). + + If postscript=0, output is plain gnuplot; + If postscript=1, output is postscript. +*/ +int +write_data (const char *filename, + unsigned long num, + mpfr_prec_t p1, mpfr_prec_t p2, mpfr_prec_t ps, float pr, + int select1, int select2, int postscript) +{ + char strf[256], strg[256]; + FILE *f, *g; + mpfr_prec_t p, step; + int op = 0; + + lets_start (num, p2); + strcpy (strf, filename); + strcat (strf, ".data"); + f = fopen (strf, "w"); + if (f == NULL) + { + fprintf (stderr, "Can't open %s!\n", strf); + lets_end (); + abort (); + } + strcpy (strg, filename); + strcat (strg, ".gnuplot"); + g = fopen (strg, "w"); + if (g == NULL) + { + fprintf (stderr, "Can't open %s!\n", strg); + lets_end (); + abort (); + } + fprintf (g, "set data style lines\n"); + if (postscript) + fprintf (g, "set terminal postscript\n"); +#undef BENCH +#define BENCH(TEST_STR, TEST) \ + if (++op == select1) \ + fprintf (g, "plot \"%s\" using 1:2 title \"%s\", \\\n", strf, \ + TEST_STR); \ + else if (op == select2) \ + fprintf (g, " \"%s\" using 1:3 title \"%s\"\n", strf, TEST_STR); + op = -1; + TEST_LIST; + + step = ps; + for (p = p1 ; p < p2 ; p+=step) + { + fprintf(f, "%lu\t%1.20e\t%1.20e\n", p, + get_speed(p, select1), + get_speed(p, select2)); + if (pr != 0.0) + { + step = (mpfr_prec_t) (p * pr - p); + if (step < 1) + step = 1; + } + } + + fclose (f); + fclose (g); + lets_end (); + if (postscript == 0) + fprintf (stderr, "Now type: gnuplot -persist %s.gnuplot\n", filename); + else + fprintf (stderr, "Now type: gnuplot %s.gnuplot > %s.ps\n", filename, + filename); + return 0; +} + +/* this function considers all functions from s_begin to s_end */ +int +write_data2 (const char *filename, + unsigned long num, + mpfr_prec_t p_begin, mpfr_prec_t p_end, mpfr_prec_t p_step, float p_r, + int s_begin, int s_end) +{ + FILE *f; + mpfr_prec_t p, step; + int s; + + lets_start (num, p_end); + f = fopen (filename, "w"); + if (f == NULL) + { + fprintf (stderr, "Can't open %s!\n", filename); + lets_end (); + exit (1); + } + + step = p_step; + for (p = p_begin ; p < p_end ; p += step) + { + fprintf (f, "%lu", p); + for (s = s_begin ; s <= s_end ; s++) + fprintf (f, "\t%1.20e", get_speed (p, s)); + fprintf (f, "\n"); + if (p_r != 0.0) + { + step = (mpfr_prec_t) (p * p_r - p); + if (step < 1) + step = 1; + } + } + fclose (f); + lets_end (); + return 0; +} + +int op_num (void) +{ + int op; +#undef BENCH +#define BENCH(TEST_STR, TEST) op++; + op = 0; + TEST_LIST; + return op; +} + +int main(int argc, const char *argv[]) +{ + mpfr_prec_t p1, p2, ps; + float pr; + int i; + unsigned long stat; + const char *filename = "plot"; + int select1, select2, max_op, conti; + int postscript = 0; + + printf (USAGE); + + max_op = op_num (); + select1 = 1; select2 = 13; + p1 = 2; p2 = 500; ps = 4; pr = 0.0; + stat = 500; /* number of different random numbers */ + conti = 0; + + for(i = 1 ; i < argc ; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'b': + p1 = atol(argv[i]+2); + break; + case 'e': + p2 = atol(argv[i]+2); + break; + case 's': + ps = atol(argv[i]+2); + break; + case 'r': + pr = atof (argv[i]+2); + if (pr <= 1.0) + { + fprintf (stderr, "-rPREC_RATIO must be > 1.0\n"); + exit (1); + } + break; + case 'm': + stat = atol(argv[i]+2); + break; + case 'x': + select1 = atoi (argv[i]+2); + select2 = select1 + 12; + break; + case 'y': + select2 = atoi (argv[i]+2); + break; + case 'o': + filename = argv[i]+2; + break; + case 'c': + conti = 1; + break; + case 'p': + postscript = 1; + break; + case 'f': + smooth = atoi (argv[i]+2); + break; + default: + fprintf(stderr, "Unkwown option: %s\n", argv[i]); + abort (); + } + } + } + /* Set low priority */ + setpriority(PRIO_PROCESS,0,14); + if (pr == 0.0) + printf("GMP:%s MPFR:%s From p=%lu to %lu by %lu Output: %s N=%ld\n", + gmp_version, mpfr_get_version(), p1,p2,ps, filename, stat); + else + printf("GMP:%s MPFR:%s From p=%lu to %lu by %f Output: %s N=%ld\n", + gmp_version, mpfr_get_version(), p1, p2, pr, filename, stat); + + if (select2 >= max_op) + select2 = max_op-1; + if (select1 >= max_op) + select1 = max_op-1; + + if (conti == 0) + write_data (filename, stat, p1, p2, ps, pr, select1, select2, postscript); + else + write_data2 (filename, stat, p1, p2, ps, pr, select1, select2); + + return 0; +} |