Add default Smack manifest for mpfr.spec
[toolchains/mpfr.git] / speed.c
1 /* Tune various threshold of MPFR
2
3 Copyright 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
5
6 This file is part of the GNU MPFR Library.
7
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23 #include <stdlib.h>
24 #include <time.h>
25
26 #define MPFR_NEED_LONGLONG_H
27 #include "mpfr-impl.h"
28
29 /* extracted from mulders.c */
30 #ifdef MPFR_MULHIGH_TAB_SIZE
31 static short mulhigh_ktab[MPFR_MULHIGH_TAB_SIZE];
32 #else
33 static short mulhigh_ktab[] = {MPFR_MULHIGH_TAB};
34 #define MPFR_MULHIGH_TAB_SIZE \
35   ((mp_size_t) (sizeof(mulhigh_ktab) / sizeof(mulhigh_ktab[0])))
36 #endif
37
38 #undef _PROTO
39 #define _PROTO __GMP_PROTO
40 #include "speed.h"
41
42 int verbose;
43
44 /* s->size: precision of both input and output
45    s->xp  : Mantissa of first input
46    s->yp  : mantissa of second input                    */
47
48 #define SPEED_MPFR_FUNC(mean_fun) do {               \
49   unsigned  i;                                       \
50   mp_ptr    wp;                                      \
51   double    t;                                       \
52   mpfr_t    w, x;                                    \
53   mp_size_t size;                                    \
54   MPFR_TMP_DECL (marker);                            \
55                                                      \
56   SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN);    \
57   SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX);    \
58   MPFR_TMP_MARK (marker);                            \
59                                                      \
60   size = (s->size-1)/GMP_NUMB_BITS+1;             \
61   s->xp[size-1] |= MPFR_LIMB_HIGHBIT;                \
62   MPFR_TMP_INIT1 (s->xp, x, s->size);                \
63   MPFR_SET_EXP (x, 0);                               \
64                                                      \
65   MPFR_TMP_INIT (wp, w, s->size, size);              \
66                                                      \
67   speed_operand_src (s, s->xp, size);                \
68   speed_operand_dst (s, wp, size);                   \
69   speed_cache_fill (s);                              \
70                                                      \
71   speed_starttime ();                                \
72   i = s->reps;                                       \
73   do                                                 \
74     mean_fun (w, x, MPFR_RNDN);                       \
75   while (--i != 0);                                  \
76   t = speed_endtime ();                              \
77                                                      \
78   MPFR_TMP_FREE (marker);                            \
79   return t;                                          \
80 } while (0)
81
82 #define SPEED_MPFR_OP(mean_fun) do {                 \
83   unsigned  i;                                       \
84   mp_ptr    wp;                                      \
85   double    t;                                       \
86   mpfr_t    w, x, y;                                 \
87   mp_size_t size;                                    \
88   MPFR_TMP_DECL (marker);                            \
89                                                      \
90   SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN);    \
91   SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX);    \
92   MPFR_TMP_MARK (marker);                            \
93                                                      \
94   size = (s->size-1)/GMP_NUMB_BITS+1;             \
95   s->xp[size-1] |= MPFR_LIMB_HIGHBIT;                \
96   MPFR_TMP_INIT1 (s->xp, x, s->size);                \
97   MPFR_SET_EXP (x, 0);                               \
98   s->yp[size-1] |= MPFR_LIMB_HIGHBIT;                \
99   MPFR_TMP_INIT1 (s->yp, y, s->size);                \
100   MPFR_SET_EXP (y, 0);                               \
101                                                      \
102   MPFR_TMP_INIT (wp, w, s->size, size);              \
103                                                      \
104   speed_operand_src (s, s->xp, size);                \
105   speed_operand_src (s, s->yp, size);                \
106   speed_operand_dst (s, wp, size);                   \
107   speed_cache_fill (s);                              \
108                                                      \
109   speed_starttime ();                                \
110   i = s->reps;                                       \
111   do                                                 \
112     mean_fun (w, x, y, MPFR_RNDN);                    \
113   while (--i != 0);                                  \
114   t = speed_endtime ();                              \
115                                                      \
116   MPFR_TMP_FREE (marker);                            \
117   return t;                                          \
118 } while (0)
119
120
121 /* First we include all the functions we want to tune inside this program.
122    We can't use GNU MPFR library since the THRESHOLD can't vary */
123
124 /* Setup mpfr_mul */
125 mpfr_prec_t mpfr_mul_threshold = MPFR_MUL_THRESHOLD;
126 static double speed_mpfr_mul (struct speed_params *s) {
127   SPEED_MPFR_OP (mpfr_mul);
128 }
129
130
131
132 /************************************************
133  * Common functions (inspired by GMP function)  *
134  ************************************************/
135 #define THRESHOLD_WINDOW 16
136 #define THRESHOLD_FINAL_WINDOW 128
137 static double domeasure (mpfr_prec_t *threshold,
138                          double (*func) (struct speed_params *),
139                          mpfr_prec_t p)
140 {
141   struct speed_params s;
142   mp_size_t size;
143   double t;
144
145   s.align_xp = s.align_yp = s.align_wp = 64;
146   s.size = p;
147   size = (p - 1)/GMP_NUMB_BITS+1;
148   s.xp = malloc (2*size*sizeof (mp_limb_t));
149   if (s.xp == NULL)
150     {
151       fprintf (stderr, "Can't allocate memory.\n");
152       abort ();
153     }
154   mpn_random (s.xp, size);
155   s.yp = s.xp + size;
156   mpn_random (s.yp, size);
157   t = speed_measure (func, &s);
158   if (t == -1.0)
159     {
160       fprintf (stderr, "Failed to measure function!\n");
161       abort ();
162     }
163   free (s.xp);
164   return t;
165 }
166
167 /* Tune a function with a simple THRESHOLD
168    The function doesn't depend on another threshold.
169    It assumes that it uses algo1 if p < THRESHOLD
170    and algo2 otherwise.
171    if algo2 is better for low prec, and algo1 better for high prec,
172    the behaviour of this function is undefined. */
173 static void
174 tune_simple_func (mpfr_prec_t *threshold,
175                   double (*func) (struct speed_params *),
176                   mpfr_prec_t pstart, mpfr_prec_t pend)
177 {
178   double measure;
179   mpfr_prec_t p = pstart;
180   mp_size_t k, n;
181
182   while (p <= pend)
183     {
184       measure = domeasure (threshold, func, p);
185       printf ("prec=%lu mpfr_mul=%e ", p, measure);
186       n = 1 + (p - 1) / GMP_NUMB_BITS;
187       if (n <= MPFR_MUL_THRESHOLD)
188         k = MUL_FFT_THRESHOLD + 1;
189       else if (n < MPFR_MULHIGH_TAB_SIZE)
190         k = mulhigh_ktab[n];
191       else
192         k = 2*n/3;
193       if (k < 0)
194         printf ("[mpn_mul_basecase]\n");
195       else if (k == 0)
196         printf ("[mpfr_mulhigh_n_basecase]\n");
197       else if (k > MUL_FFT_THRESHOLD)
198         printf ("[mpn_mul_n]\n");
199       else
200         printf ("[mpfr_mulhigh_n]\n");
201       p = p + p / 10;
202     }
203 }
204
205 /*******************************************************
206  *            Tune all the threshold of MPFR           *
207  * Warning: tune the function in their dependent order!*
208  *******************************************************/
209 static void
210 all (void)
211 {
212   FILE *f = stdout;
213   time_t  start_time, end_time;
214   struct tm  *tp;
215
216   speed_time_init ();
217   if (verbose) {
218     printf ("Using: %s\n", speed_time_string);
219     printf ("speed_precision %d", speed_precision);
220     if (speed_unittime == 1.0)
221       printf (", speed_unittime 1 cycle");
222     else
223       printf (", speed_unittime %.2e secs", speed_unittime);
224     if (speed_cycletime == 1.0 || speed_cycletime == 0.0)
225       printf (", CPU freq unknown\n");
226     else
227       printf (", CPU freq %.2f MHz\n\n", 1e-6/speed_cycletime);
228   }
229
230   time (&start_time);
231   tp = localtime (&start_time);
232   fprintf (f, "/* Generated by MPFR's tuneup.c, %d-%02d-%02d, ",
233           tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday);
234
235 #ifdef __ICC
236   fprintf (f, "icc %d.%d.%d */\n", __ICC / 100, __ICC / 10 % 10, __ICC % 10);
237 #elif defined(__GNUC__)
238   fprintf (f, "gcc %d.%d */\n", __GNUC__, __GNUC_MINOR__);
239 #elif defined (__SUNPRO_C)
240   fprintf (f, "Sun C %d.%d */\n", __SUNPRO_C / 0x100, __SUNPRO_C % 0x100);
241 #elif defined (__sgi) && defined (_COMPILER_VERSION)
242   fprintf (f, "MIPSpro C %d.%d.%d */\n",
243            _COMPILER_VERSION / 100,
244            _COMPILER_VERSION / 10 % 10,
245            _COMPILER_VERSION % 10);
246 #elif defined (__DECC) && defined (__DECC_VER)
247   fprintf (f, "DEC C %d */\n", __DECC_VER);
248 #else
249   fprintf (f, "system compiler */\n");
250 #endif
251   fprintf (f, "\n");
252
253   /* Tune mpfr_mul (threshold is in limbs, but it doesn't matter too much) */
254   if (verbose)
255     printf ("Measuring mpfr_mul with mpfr_mul_threshold=%lu...\n",
256             mpfr_mul_threshold);
257   tune_simple_func (&mpfr_mul_threshold, speed_mpfr_mul,
258                     2*GMP_NUMB_BITS+1, 1000);
259
260   /* End of tuning */
261   time (&end_time);
262   if (verbose)
263     printf ("Complete (took %ld seconds).\n", end_time - start_time);
264 }
265
266
267 /* Main function */
268 int main (int argc, char *argv[])
269 {
270   /* Unbuffered so if output is redirected to a file it isn't lost if the
271      program is killed part way through.  */
272   setbuf (stdout, NULL);
273   setbuf (stderr, NULL);
274
275   verbose = argc > 1;
276
277   if (verbose)
278     printf ("Tuning MPFR (Coffee time?)...\n");
279
280   all ();
281
282   return 0;
283 }