tuneup.c revision 1.1.1.1.8.2 1 1.1.1.1.8.2 tls /* Tune various threshold of MPFR
2 1.1.1.1.8.2 tls
3 1.1.1.1.8.2 tls Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4 1.1.1.1.8.2 tls Contributed by the AriC and Caramel projects, INRIA.
5 1.1.1.1.8.2 tls
6 1.1.1.1.8.2 tls This file is part of the GNU MPFR Library.
7 1.1.1.1.8.2 tls
8 1.1.1.1.8.2 tls The GNU MPFR Library is free software; you can redistribute it and/or modify
9 1.1.1.1.8.2 tls it under the terms of the GNU Lesser General Public License as published by
10 1.1.1.1.8.2 tls the Free Software Foundation; either version 3 of the License, or (at your
11 1.1.1.1.8.2 tls option) any later version.
12 1.1.1.1.8.2 tls
13 1.1.1.1.8.2 tls The GNU MPFR Library is distributed in the hope that it will be useful, but
14 1.1.1.1.8.2 tls WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 1.1.1.1.8.2 tls or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 1.1.1.1.8.2 tls License for more details.
17 1.1.1.1.8.2 tls
18 1.1.1.1.8.2 tls You should have received a copy of the GNU Lesser General Public License
19 1.1.1.1.8.2 tls along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
20 1.1.1.1.8.2 tls http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 1.1.1.1.8.2 tls 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22 1.1.1.1.8.2 tls
23 1.1.1.1.8.2 tls #include <stdlib.h>
24 1.1.1.1.8.2 tls #include <time.h>
25 1.1.1.1.8.2 tls
26 1.1.1.1.8.2 tls #define MPFR_NEED_LONGLONG_H
27 1.1.1.1.8.2 tls #include "mpfr-impl.h"
28 1.1.1.1.8.2 tls
29 1.1.1.1.8.2 tls #undef _PROTO
30 1.1.1.1.8.2 tls #define _PROTO __GMP_PROTO
31 1.1.1.1.8.2 tls #include "speed.h"
32 1.1.1.1.8.2 tls
33 1.1.1.1.8.2 tls int verbose;
34 1.1.1.1.8.2 tls
35 1.1.1.1.8.2 tls /* template for an unary function */
36 1.1.1.1.8.2 tls /* s->size: precision of both input and output
37 1.1.1.1.8.2 tls s->xp : Mantissa of first input
38 1.1.1.1.8.2 tls s->yp : mantissa of second input */
39 1.1.1.1.8.2 tls #define SPEED_MPFR_FUNC(mean_fun) \
40 1.1.1.1.8.2 tls do \
41 1.1.1.1.8.2 tls { \
42 1.1.1.1.8.2 tls unsigned i; \
43 1.1.1.1.8.2 tls mpfr_limb_ptr wp; \
44 1.1.1.1.8.2 tls double t; \
45 1.1.1.1.8.2 tls mpfr_t w, x; \
46 1.1.1.1.8.2 tls mp_size_t size; \
47 1.1.1.1.8.2 tls MPFR_TMP_DECL (marker); \
48 1.1.1.1.8.2 tls \
49 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \
50 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \
51 1.1.1.1.8.2 tls MPFR_TMP_MARK (marker); \
52 1.1.1.1.8.2 tls \
53 1.1.1.1.8.2 tls size = (s->size-1)/GMP_NUMB_BITS+1; \
54 1.1.1.1.8.2 tls s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \
55 1.1.1.1.8.2 tls MPFR_TMP_INIT1 (s->xp, x, s->size); \
56 1.1.1.1.8.2 tls MPFR_SET_EXP (x, 0); \
57 1.1.1.1.8.2 tls \
58 1.1.1.1.8.2 tls MPFR_TMP_INIT (wp, w, s->size, size); \
59 1.1.1.1.8.2 tls \
60 1.1.1.1.8.2 tls speed_operand_src (s, s->xp, size); \
61 1.1.1.1.8.2 tls speed_operand_dst (s, wp, size); \
62 1.1.1.1.8.2 tls speed_cache_fill (s); \
63 1.1.1.1.8.2 tls \
64 1.1.1.1.8.2 tls speed_starttime (); \
65 1.1.1.1.8.2 tls i = s->reps; \
66 1.1.1.1.8.2 tls do \
67 1.1.1.1.8.2 tls mean_fun (w, x, MPFR_RNDN); \
68 1.1.1.1.8.2 tls while (--i != 0); \
69 1.1.1.1.8.2 tls t = speed_endtime (); \
70 1.1.1.1.8.2 tls \
71 1.1.1.1.8.2 tls MPFR_TMP_FREE (marker); \
72 1.1.1.1.8.2 tls return t; \
73 1.1.1.1.8.2 tls } \
74 1.1.1.1.8.2 tls while (0)
75 1.1.1.1.8.2 tls
76 1.1.1.1.8.2 tls /* same as SPEED_MPFR_FUNC, but for say mpfr_sin_cos (y, z, x, r) */
77 1.1.1.1.8.2 tls #define SPEED_MPFR_FUNC2(mean_fun) \
78 1.1.1.1.8.2 tls do \
79 1.1.1.1.8.2 tls { \
80 1.1.1.1.8.2 tls unsigned i; \
81 1.1.1.1.8.2 tls mpfr_limb_ptr vp, wp; \
82 1.1.1.1.8.2 tls double t; \
83 1.1.1.1.8.2 tls mpfr_t v, w, x; \
84 1.1.1.1.8.2 tls mp_size_t size; \
85 1.1.1.1.8.2 tls MPFR_TMP_DECL (marker); \
86 1.1.1.1.8.2 tls \
87 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \
88 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \
89 1.1.1.1.8.2 tls MPFR_TMP_MARK (marker); \
90 1.1.1.1.8.2 tls \
91 1.1.1.1.8.2 tls size = (s->size-1)/GMP_NUMB_BITS+1; \
92 1.1.1.1.8.2 tls s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \
93 1.1.1.1.8.2 tls MPFR_TMP_INIT1 (s->xp, x, s->size); \
94 1.1.1.1.8.2 tls MPFR_SET_EXP (x, 0); \
95 1.1.1.1.8.2 tls \
96 1.1.1.1.8.2 tls MPFR_TMP_INIT (vp, v, s->size, size); \
97 1.1.1.1.8.2 tls MPFR_TMP_INIT (wp, w, s->size, size); \
98 1.1.1.1.8.2 tls \
99 1.1.1.1.8.2 tls speed_operand_src (s, s->xp, size); \
100 1.1.1.1.8.2 tls speed_operand_dst (s, vp, size); \
101 1.1.1.1.8.2 tls speed_operand_dst (s, wp, size); \
102 1.1.1.1.8.2 tls speed_cache_fill (s); \
103 1.1.1.1.8.2 tls \
104 1.1.1.1.8.2 tls speed_starttime (); \
105 1.1.1.1.8.2 tls i = s->reps; \
106 1.1.1.1.8.2 tls do \
107 1.1.1.1.8.2 tls mean_fun (v, w, x, MPFR_RNDN); \
108 1.1.1.1.8.2 tls while (--i != 0); \
109 1.1.1.1.8.2 tls t = speed_endtime (); \
110 1.1.1.1.8.2 tls \
111 1.1.1.1.8.2 tls MPFR_TMP_FREE (marker); \
112 1.1.1.1.8.2 tls return t; \
113 1.1.1.1.8.2 tls } \
114 1.1.1.1.8.2 tls while (0)
115 1.1.1.1.8.2 tls
116 1.1.1.1.8.2 tls /* template for a function like mpfr_mul */
117 1.1.1.1.8.2 tls #define SPEED_MPFR_OP(mean_fun) \
118 1.1.1.1.8.2 tls do \
119 1.1.1.1.8.2 tls { \
120 1.1.1.1.8.2 tls unsigned i; \
121 1.1.1.1.8.2 tls mpfr_limb_ptr wp; \
122 1.1.1.1.8.2 tls double t; \
123 1.1.1.1.8.2 tls mpfr_t w, x, y; \
124 1.1.1.1.8.2 tls mp_size_t size; \
125 1.1.1.1.8.2 tls MPFR_TMP_DECL (marker); \
126 1.1.1.1.8.2 tls \
127 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \
128 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \
129 1.1.1.1.8.2 tls MPFR_TMP_MARK (marker); \
130 1.1.1.1.8.2 tls \
131 1.1.1.1.8.2 tls size = (s->size-1)/GMP_NUMB_BITS+1; \
132 1.1.1.1.8.2 tls s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \
133 1.1.1.1.8.2 tls MPFR_TMP_INIT1 (s->xp, x, s->size); \
134 1.1.1.1.8.2 tls MPFR_SET_EXP (x, 0); \
135 1.1.1.1.8.2 tls s->yp[size-1] |= MPFR_LIMB_HIGHBIT; \
136 1.1.1.1.8.2 tls MPFR_TMP_INIT1 (s->yp, y, s->size); \
137 1.1.1.1.8.2 tls MPFR_SET_EXP (y, 0); \
138 1.1.1.1.8.2 tls \
139 1.1.1.1.8.2 tls MPFR_TMP_INIT (wp, w, s->size, size); \
140 1.1.1.1.8.2 tls \
141 1.1.1.1.8.2 tls speed_operand_src (s, s->xp, size); \
142 1.1.1.1.8.2 tls speed_operand_src (s, s->yp, size); \
143 1.1.1.1.8.2 tls speed_operand_dst (s, wp, size); \
144 1.1.1.1.8.2 tls speed_cache_fill (s); \
145 1.1.1.1.8.2 tls \
146 1.1.1.1.8.2 tls speed_starttime (); \
147 1.1.1.1.8.2 tls i = s->reps; \
148 1.1.1.1.8.2 tls do \
149 1.1.1.1.8.2 tls mean_fun (w, x, y, MPFR_RNDN); \
150 1.1.1.1.8.2 tls while (--i != 0); \
151 1.1.1.1.8.2 tls t = speed_endtime (); \
152 1.1.1.1.8.2 tls \
153 1.1.1.1.8.2 tls MPFR_TMP_FREE (marker); \
154 1.1.1.1.8.2 tls return t; \
155 1.1.1.1.8.2 tls } \
156 1.1.1.1.8.2 tls while (0)
157 1.1.1.1.8.2 tls
158 1.1.1.1.8.2 tls /* special template for mpfr_mul(a,b,b) */
159 1.1.1.1.8.2 tls #define SPEED_MPFR_SQR(mean_fun) \
160 1.1.1.1.8.2 tls do \
161 1.1.1.1.8.2 tls { \
162 1.1.1.1.8.2 tls unsigned i; \
163 1.1.1.1.8.2 tls mpfr_limb_ptr wp; \
164 1.1.1.1.8.2 tls double t; \
165 1.1.1.1.8.2 tls mpfr_t w, x; \
166 1.1.1.1.8.2 tls mp_size_t size; \
167 1.1.1.1.8.2 tls MPFR_TMP_DECL (marker); \
168 1.1.1.1.8.2 tls \
169 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \
170 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \
171 1.1.1.1.8.2 tls MPFR_TMP_MARK (marker); \
172 1.1.1.1.8.2 tls \
173 1.1.1.1.8.2 tls size = (s->size-1)/GMP_NUMB_BITS+1; \
174 1.1.1.1.8.2 tls s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \
175 1.1.1.1.8.2 tls MPFR_TMP_INIT1 (s->xp, x, s->size); \
176 1.1.1.1.8.2 tls MPFR_SET_EXP (x, 0); \
177 1.1.1.1.8.2 tls \
178 1.1.1.1.8.2 tls MPFR_TMP_INIT (wp, w, s->size, size); \
179 1.1.1.1.8.2 tls \
180 1.1.1.1.8.2 tls speed_operand_src (s, s->xp, size); \
181 1.1.1.1.8.2 tls speed_operand_dst (s, wp, size); \
182 1.1.1.1.8.2 tls speed_cache_fill (s); \
183 1.1.1.1.8.2 tls \
184 1.1.1.1.8.2 tls speed_starttime (); \
185 1.1.1.1.8.2 tls i = s->reps; \
186 1.1.1.1.8.2 tls do \
187 1.1.1.1.8.2 tls mean_fun (w, x, x, MPFR_RNDN); \
188 1.1.1.1.8.2 tls while (--i != 0); \
189 1.1.1.1.8.2 tls t = speed_endtime (); \
190 1.1.1.1.8.2 tls \
191 1.1.1.1.8.2 tls MPFR_TMP_FREE (marker); \
192 1.1.1.1.8.2 tls return t; \
193 1.1.1.1.8.2 tls } \
194 1.1.1.1.8.2 tls while (0)
195 1.1.1.1.8.2 tls
196 1.1.1.1.8.2 tls /* s->size: precision of both input and output
197 1.1.1.1.8.2 tls s->xp : Mantissa of first input
198 1.1.1.1.8.2 tls s->r : exponent
199 1.1.1.1.8.2 tls s->align_xp : sign (1 means positive, 2 means negative)
200 1.1.1.1.8.2 tls */
201 1.1.1.1.8.2 tls #define SPEED_MPFR_FUNC_WITH_EXPONENT(mean_fun) \
202 1.1.1.1.8.2 tls do \
203 1.1.1.1.8.2 tls { \
204 1.1.1.1.8.2 tls unsigned i; \
205 1.1.1.1.8.2 tls mpfr_limb_ptr wp; \
206 1.1.1.1.8.2 tls double t; \
207 1.1.1.1.8.2 tls mpfr_t w, x; \
208 1.1.1.1.8.2 tls mp_size_t size; \
209 1.1.1.1.8.2 tls MPFR_TMP_DECL (marker); \
210 1.1.1.1.8.2 tls \
211 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size >= MPFR_PREC_MIN); \
212 1.1.1.1.8.2 tls SPEED_RESTRICT_COND (s->size <= MPFR_PREC_MAX); \
213 1.1.1.1.8.2 tls MPFR_TMP_MARK (marker); \
214 1.1.1.1.8.2 tls \
215 1.1.1.1.8.2 tls size = (s->size-1)/GMP_NUMB_BITS+1; \
216 1.1.1.1.8.2 tls s->xp[size-1] |= MPFR_LIMB_HIGHBIT; \
217 1.1.1.1.8.2 tls MPFR_TMP_INIT1 (s->xp, x, s->size); \
218 1.1.1.1.8.2 tls MPFR_SET_EXP (x, s->r); \
219 1.1.1.1.8.2 tls if (s->align_xp == 2) MPFR_SET_NEG (x); \
220 1.1.1.1.8.2 tls \
221 1.1.1.1.8.2 tls MPFR_TMP_INIT (wp, w, s->size, size); \
222 1.1.1.1.8.2 tls \
223 1.1.1.1.8.2 tls speed_operand_src (s, s->xp, size); \
224 1.1.1.1.8.2 tls speed_operand_dst (s, wp, size); \
225 1.1.1.1.8.2 tls speed_cache_fill (s); \
226 1.1.1.1.8.2 tls \
227 1.1.1.1.8.2 tls speed_starttime (); \
228 1.1.1.1.8.2 tls i = s->reps; \
229 1.1.1.1.8.2 tls do \
230 1.1.1.1.8.2 tls mean_fun (w, x, MPFR_RNDN); \
231 1.1.1.1.8.2 tls while (--i != 0); \
232 1.1.1.1.8.2 tls t = speed_endtime (); \
233 1.1.1.1.8.2 tls \
234 1.1.1.1.8.2 tls MPFR_TMP_FREE (marker); \
235 1.1.1.1.8.2 tls return t; \
236 1.1.1.1.8.2 tls } \
237 1.1.1.1.8.2 tls while (0)
238 1.1.1.1.8.2 tls
239 1.1.1.1.8.2 tls /* First we include all the functions we want to tune inside this program.
240 1.1.1.1.8.2 tls We can't use the GNU MPFR library since the thresholds are fixed macros. */
241 1.1.1.1.8.2 tls
242 1.1.1.1.8.2 tls /* Setup mpfr_exp_2 */
243 1.1.1.1.8.2 tls mpfr_prec_t mpfr_exp_2_threshold;
244 1.1.1.1.8.2 tls #undef MPFR_EXP_2_THRESHOLD
245 1.1.1.1.8.2 tls #define MPFR_EXP_2_THRESHOLD mpfr_exp_2_threshold
246 1.1.1.1.8.2 tls #include "exp_2.c"
247 1.1.1.1.8.2 tls static double
248 1.1.1.1.8.2 tls speed_mpfr_exp_2 (struct speed_params *s)
249 1.1.1.1.8.2 tls {
250 1.1.1.1.8.2 tls SPEED_MPFR_FUNC (mpfr_exp_2);
251 1.1.1.1.8.2 tls }
252 1.1.1.1.8.2 tls
253 1.1.1.1.8.2 tls /* Setup mpfr_exp */
254 1.1.1.1.8.2 tls mpfr_prec_t mpfr_exp_threshold;
255 1.1.1.1.8.2 tls #undef MPFR_EXP_THRESHOLD
256 1.1.1.1.8.2 tls #define MPFR_EXP_THRESHOLD mpfr_exp_threshold
257 1.1.1.1.8.2 tls #include "exp.c"
258 1.1.1.1.8.2 tls static double
259 1.1.1.1.8.2 tls speed_mpfr_exp (struct speed_params *s)
260 1.1.1.1.8.2 tls {
261 1.1.1.1.8.2 tls SPEED_MPFR_FUNC (mpfr_exp);
262 1.1.1.1.8.2 tls }
263 1.1.1.1.8.2 tls
264 1.1.1.1.8.2 tls /* Setup mpfr_sin_cos */
265 1.1.1.1.8.2 tls mpfr_prec_t mpfr_sincos_threshold;
266 1.1.1.1.8.2 tls #undef MPFR_SINCOS_THRESHOLD
267 1.1.1.1.8.2 tls #define MPFR_SINCOS_THRESHOLD mpfr_sincos_threshold
268 1.1.1.1.8.2 tls #include "sin_cos.c"
269 1.1.1.1.8.2 tls #include "cos.c"
270 1.1.1.1.8.2 tls static double
271 1.1.1.1.8.2 tls speed_mpfr_sincos (struct speed_params *s)
272 1.1.1.1.8.2 tls {
273 1.1.1.1.8.2 tls SPEED_MPFR_FUNC2 (mpfr_sin_cos);
274 1.1.1.1.8.2 tls }
275 1.1.1.1.8.2 tls
276 1.1.1.1.8.2 tls /* Setup mpfr_mul, mpfr_sqr and mpfr_div */
277 1.1.1.1.8.2 tls mpfr_prec_t mpfr_mul_threshold;
278 1.1.1.1.8.2 tls mpfr_prec_t mpfr_sqr_threshold;
279 1.1.1.1.8.2 tls mpfr_prec_t mpfr_div_threshold;
280 1.1.1.1.8.2 tls #undef MPFR_MUL_THRESHOLD
281 1.1.1.1.8.2 tls #define MPFR_MUL_THRESHOLD mpfr_mul_threshold
282 1.1.1.1.8.2 tls #undef MPFR_SQR_THRESHOLD
283 1.1.1.1.8.2 tls #define MPFR_SQR_THRESHOLD mpfr_sqr_threshold
284 1.1.1.1.8.2 tls #undef MPFR_DIV_THRESHOLD
285 1.1.1.1.8.2 tls #define MPFR_DIV_THRESHOLD mpfr_div_threshold
286 1.1.1.1.8.2 tls #include "mul.c"
287 1.1.1.1.8.2 tls #include "div.c"
288 1.1.1.1.8.2 tls static double
289 1.1.1.1.8.2 tls speed_mpfr_mul (struct speed_params *s)
290 1.1.1.1.8.2 tls {
291 1.1.1.1.8.2 tls SPEED_MPFR_OP (mpfr_mul);
292 1.1.1.1.8.2 tls }
293 1.1.1.1.8.2 tls static double
294 1.1.1.1.8.2 tls speed_mpfr_sqr (struct speed_params *s)
295 1.1.1.1.8.2 tls {
296 1.1.1.1.8.2 tls SPEED_MPFR_SQR (mpfr_mul);
297 1.1.1.1.8.2 tls }
298 1.1.1.1.8.2 tls static double
299 1.1.1.1.8.2 tls speed_mpfr_div (struct speed_params *s)
300 1.1.1.1.8.2 tls {
301 1.1.1.1.8.2 tls SPEED_MPFR_OP (mpfr_div);
302 1.1.1.1.8.2 tls }
303 1.1.1.1.8.2 tls
304 1.1.1.1.8.2 tls /************************************************
305 1.1.1.1.8.2 tls * Common functions (inspired by GMP function) *
306 1.1.1.1.8.2 tls ************************************************/
307 1.1.1.1.8.2 tls static int
308 1.1.1.1.8.2 tls analyze_data (double *dat, int ndat)
309 1.1.1.1.8.2 tls {
310 1.1.1.1.8.2 tls double x, min_x;
311 1.1.1.1.8.2 tls int j, min_j;
312 1.1.1.1.8.2 tls
313 1.1.1.1.8.2 tls x = 0.0;
314 1.1.1.1.8.2 tls for (j = 0; j < ndat; j++)
315 1.1.1.1.8.2 tls if (dat[j] > 0.0)
316 1.1.1.1.8.2 tls x += dat[j];
317 1.1.1.1.8.2 tls
318 1.1.1.1.8.2 tls min_x = x;
319 1.1.1.1.8.2 tls min_j = 0;
320 1.1.1.1.8.2 tls
321 1.1.1.1.8.2 tls for (j = 0; j < ndat; x -= dat[j], j++)
322 1.1.1.1.8.2 tls {
323 1.1.1.1.8.2 tls if (x < min_x)
324 1.1.1.1.8.2 tls {
325 1.1.1.1.8.2 tls min_x = x;
326 1.1.1.1.8.2 tls min_j = j;
327 1.1.1.1.8.2 tls }
328 1.1.1.1.8.2 tls }
329 1.1.1.1.8.2 tls return min_j;
330 1.1.1.1.8.2 tls }
331 1.1.1.1.8.2 tls
332 1.1.1.1.8.2 tls static double
333 1.1.1.1.8.2 tls mpfr_speed_measure (speed_function_t fun, struct speed_params *s, char *m)
334 1.1.1.1.8.2 tls {
335 1.1.1.1.8.2 tls double t = -1.0;
336 1.1.1.1.8.2 tls int i;
337 1.1.1.1.8.2 tls int number_of_iterations = 30;
338 1.1.1.1.8.2 tls for (i = 1; i <= number_of_iterations && t == -1.0; i++)
339 1.1.1.1.8.2 tls {
340 1.1.1.1.8.2 tls t = speed_measure (fun, s);
341 1.1.1.1.8.2 tls if ( (t == -1.0) && (i+1 <= number_of_iterations) )
342 1.1.1.1.8.2 tls printf("speed_measure failed for size %lu. Trying again... (%d/%d)\n",
343 1.1.1.1.8.2 tls s->size, i+1, number_of_iterations);
344 1.1.1.1.8.2 tls }
345 1.1.1.1.8.2 tls if (t == -1.0)
346 1.1.1.1.8.2 tls {
347 1.1.1.1.8.2 tls fprintf (stderr, "Failed to measure %s!\n", m);
348 1.1.1.1.8.2 tls fprintf (stderr, "If CPU frequency scaling is enabled, please disable it:\n");
349 1.1.1.1.8.2 tls fprintf (stderr, " under Linux: cpufreq-selector -g performance\n");
350 1.1.1.1.8.2 tls fprintf (stderr, "On a multi-core processor, you might also try to load all the cores\n");
351 1.1.1.1.8.2 tls abort ();
352 1.1.1.1.8.2 tls }
353 1.1.1.1.8.2 tls return t;
354 1.1.1.1.8.2 tls }
355 1.1.1.1.8.2 tls
356 1.1.1.1.8.2 tls #define THRESHOLD_WINDOW 16
357 1.1.1.1.8.2 tls #define THRESHOLD_FINAL_WINDOW 128
358 1.1.1.1.8.2 tls static double
359 1.1.1.1.8.2 tls domeasure (mpfr_prec_t *threshold,
360 1.1.1.1.8.2 tls double (*func) (struct speed_params *),
361 1.1.1.1.8.2 tls mpfr_prec_t p)
362 1.1.1.1.8.2 tls {
363 1.1.1.1.8.2 tls struct speed_params s;
364 1.1.1.1.8.2 tls mp_size_t size;
365 1.1.1.1.8.2 tls double t1, t2, d;
366 1.1.1.1.8.2 tls
367 1.1.1.1.8.2 tls s.align_xp = s.align_yp = s.align_wp = 64;
368 1.1.1.1.8.2 tls s.size = p;
369 1.1.1.1.8.2 tls size = (p - 1)/GMP_NUMB_BITS+1;
370 1.1.1.1.8.2 tls s.xp = malloc (2*size*sizeof (mp_limb_t));
371 1.1.1.1.8.2 tls if (s.xp == NULL)
372 1.1.1.1.8.2 tls {
373 1.1.1.1.8.2 tls fprintf (stderr, "Can't allocate memory.\n");
374 1.1.1.1.8.2 tls abort ();
375 1.1.1.1.8.2 tls }
376 1.1.1.1.8.2 tls mpn_random (s.xp, size);
377 1.1.1.1.8.2 tls s.yp = s.xp + size;
378 1.1.1.1.8.2 tls mpn_random (s.yp, size);
379 1.1.1.1.8.2 tls *threshold = MPFR_PREC_MAX;
380 1.1.1.1.8.2 tls t1 = mpfr_speed_measure (func, &s, "function 1");
381 1.1.1.1.8.2 tls *threshold = 1;
382 1.1.1.1.8.2 tls t2 = mpfr_speed_measure (func, &s, "function 2");
383 1.1.1.1.8.2 tls free (s.xp);
384 1.1.1.1.8.2 tls /* t1 is the time of the first algo (used for low prec) */
385 1.1.1.1.8.2 tls if (t2 >= t1)
386 1.1.1.1.8.2 tls d = (t2 - t1) / t2;
387 1.1.1.1.8.2 tls else
388 1.1.1.1.8.2 tls d = (t2 - t1) / t1;
389 1.1.1.1.8.2 tls /* d > 0 if we have to use algo 1.
390 1.1.1.1.8.2 tls d < 0 if we have to use algo 2 */
391 1.1.1.1.8.2 tls return d;
392 1.1.1.1.8.2 tls }
393 1.1.1.1.8.2 tls
394 1.1.1.1.8.2 tls /* Performs measures when both the precision and the point of evaluation
395 1.1.1.1.8.2 tls shall vary. s.yp is ignored and not initialized.
396 1.1.1.1.8.2 tls It assumes that func depends on three thresholds with a boundary of the
397 1.1.1.1.8.2 tls form threshold1*x + threshold2*p = some scaling factor, if x<0,
398 1.1.1.1.8.2 tls and threshold3*x + threshold2*p = some scaling factor, if x>=0.
399 1.1.1.1.8.2 tls */
400 1.1.1.1.8.2 tls static double
401 1.1.1.1.8.2 tls domeasure2 (long int *threshold1, long int *threshold2, long int *threshold3,
402 1.1.1.1.8.2 tls double (*func) (struct speed_params *),
403 1.1.1.1.8.2 tls mpfr_prec_t p,
404 1.1.1.1.8.2 tls mpfr_t x)
405 1.1.1.1.8.2 tls {
406 1.1.1.1.8.2 tls struct speed_params s;
407 1.1.1.1.8.2 tls mp_size_t size;
408 1.1.1.1.8.2 tls double t1, t2, d;
409 1.1.1.1.8.2 tls mpfr_t xtmp;
410 1.1.1.1.8.2 tls
411 1.1.1.1.8.2 tls if (MPFR_IS_SINGULAR (x))
412 1.1.1.1.8.2 tls {
413 1.1.1.1.8.2 tls mpfr_fprintf (stderr, "x=%RNf is not a regular number.\n");
414 1.1.1.1.8.2 tls abort ();
415 1.1.1.1.8.2 tls }
416 1.1.1.1.8.2 tls if (MPFR_IS_NEG (x))
417 1.1.1.1.8.2 tls s.align_xp = 2;
418 1.1.1.1.8.2 tls else
419 1.1.1.1.8.2 tls s.align_xp = 1;
420 1.1.1.1.8.2 tls
421 1.1.1.1.8.2 tls s.align_yp = s.align_wp = 64;
422 1.1.1.1.8.2 tls s.size = p;
423 1.1.1.1.8.2 tls size = (p - 1)/GMP_NUMB_BITS+1;
424 1.1.1.1.8.2 tls
425 1.1.1.1.8.2 tls mpfr_init2 (xtmp, p);
426 1.1.1.1.8.2 tls mpn_random (xtmp->_mpfr_d, size);
427 1.1.1.1.8.2 tls xtmp->_mpfr_d[size-1] |= MPFR_LIMB_HIGHBIT;
428 1.1.1.1.8.2 tls MPFR_SET_EXP (xtmp, -53);
429 1.1.1.1.8.2 tls mpfr_add_ui (xtmp, xtmp, 1, MPFR_RNDN);
430 1.1.1.1.8.2 tls mpfr_mul (xtmp, xtmp, x, MPFR_RNDN); /* xtmp = x*(1+perturb) */
431 1.1.1.1.8.2 tls /* where perturb ~ 2^(-53) is */
432 1.1.1.1.8.2 tls /* randomly chosen. */
433 1.1.1.1.8.2 tls s.xp = xtmp->_mpfr_d;
434 1.1.1.1.8.2 tls s.r = MPFR_GET_EXP (xtmp);
435 1.1.1.1.8.2 tls
436 1.1.1.1.8.2 tls *threshold1 = 0;
437 1.1.1.1.8.2 tls *threshold2 = 0;
438 1.1.1.1.8.2 tls *threshold3 = 0;
439 1.1.1.1.8.2 tls t1 = mpfr_speed_measure (func, &s, "function 1");
440 1.1.1.1.8.2 tls
441 1.1.1.1.8.2 tls if (MPFR_IS_NEG (x))
442 1.1.1.1.8.2 tls *threshold1 = INT_MIN;
443 1.1.1.1.8.2 tls else
444 1.1.1.1.8.2 tls *threshold3 = INT_MAX;
445 1.1.1.1.8.2 tls *threshold2 = INT_MAX;
446 1.1.1.1.8.2 tls t2 = mpfr_speed_measure (func, &s, "function 2");
447 1.1.1.1.8.2 tls
448 1.1.1.1.8.2 tls /* t1 is the time of the first algo (used for low prec) */
449 1.1.1.1.8.2 tls if (t2 >= t1)
450 1.1.1.1.8.2 tls d = (t2 - t1) / t2;
451 1.1.1.1.8.2 tls else
452 1.1.1.1.8.2 tls d = (t2 - t1) / t1;
453 1.1.1.1.8.2 tls /* d > 0 if we have to use algo 1.
454 1.1.1.1.8.2 tls d < 0 if we have to use algo 2 */
455 1.1.1.1.8.2 tls mpfr_clear (xtmp);
456 1.1.1.1.8.2 tls return d;
457 1.1.1.1.8.2 tls }
458 1.1.1.1.8.2 tls
459 1.1.1.1.8.2 tls /* Tune a function with a simple THRESHOLD
460 1.1.1.1.8.2 tls The function doesn't depend on another threshold.
461 1.1.1.1.8.2 tls It assumes that it uses algo1 if p < THRESHOLD
462 1.1.1.1.8.2 tls and algo2 otherwise.
463 1.1.1.1.8.2 tls if algo2 is better for low prec, and algo1 better for high prec,
464 1.1.1.1.8.2 tls the behaviour of this function is undefined. */
465 1.1.1.1.8.2 tls static void
466 1.1.1.1.8.2 tls tune_simple_func (mpfr_prec_t *threshold,
467 1.1.1.1.8.2 tls double (*func) (struct speed_params *),
468 1.1.1.1.8.2 tls mpfr_prec_t pstart)
469 1.1.1.1.8.2 tls {
470 1.1.1.1.8.2 tls double measure[THRESHOLD_FINAL_WINDOW+1];
471 1.1.1.1.8.2 tls double d;
472 1.1.1.1.8.2 tls mpfr_prec_t pstep;
473 1.1.1.1.8.2 tls int i, numpos, numneg, try;
474 1.1.1.1.8.2 tls mpfr_prec_t pmin, pmax, p;
475 1.1.1.1.8.2 tls
476 1.1.1.1.8.2 tls /* first look for a lower bound within 10% */
477 1.1.1.1.8.2 tls pmin = p = pstart;
478 1.1.1.1.8.2 tls d = domeasure (threshold, func, pmin);
479 1.1.1.1.8.2 tls if (d < 0.0)
480 1.1.1.1.8.2 tls {
481 1.1.1.1.8.2 tls if (verbose)
482 1.1.1.1.8.2 tls printf ("Oops: even for %lu, algo 2 seems to be faster!\n",
483 1.1.1.1.8.2 tls (unsigned long) pmin);
484 1.1.1.1.8.2 tls *threshold = MPFR_PREC_MIN;
485 1.1.1.1.8.2 tls return;
486 1.1.1.1.8.2 tls }
487 1.1.1.1.8.2 tls if (d >= 1.00)
488 1.1.1.1.8.2 tls for (;;)
489 1.1.1.1.8.2 tls {
490 1.1.1.1.8.2 tls d = domeasure (threshold, func, pmin);
491 1.1.1.1.8.2 tls if (d < 1.00)
492 1.1.1.1.8.2 tls break;
493 1.1.1.1.8.2 tls p = pmin;
494 1.1.1.1.8.2 tls pmin += pmin/2;
495 1.1.1.1.8.2 tls }
496 1.1.1.1.8.2 tls pmin = p;
497 1.1.1.1.8.2 tls for (;;)
498 1.1.1.1.8.2 tls {
499 1.1.1.1.8.2 tls d = domeasure (threshold, func, pmin);
500 1.1.1.1.8.2 tls if (d < 0.10)
501 1.1.1.1.8.2 tls break;
502 1.1.1.1.8.2 tls pmin += GMP_NUMB_BITS;
503 1.1.1.1.8.2 tls }
504 1.1.1.1.8.2 tls
505 1.1.1.1.8.2 tls /* then look for an upper bound within 20% */
506 1.1.1.1.8.2 tls pmax = pmin * 2;
507 1.1.1.1.8.2 tls for (;;)
508 1.1.1.1.8.2 tls {
509 1.1.1.1.8.2 tls d = domeasure (threshold, func, pmax);
510 1.1.1.1.8.2 tls if (d < -0.20)
511 1.1.1.1.8.2 tls break;
512 1.1.1.1.8.2 tls pmax += pmin / 2; /* don't increase too rapidly */
513 1.1.1.1.8.2 tls }
514 1.1.1.1.8.2 tls
515 1.1.1.1.8.2 tls /* The threshold is between pmin and pmax. Affine them */
516 1.1.1.1.8.2 tls try = 0;
517 1.1.1.1.8.2 tls while ((pmax-pmin) >= THRESHOLD_FINAL_WINDOW)
518 1.1.1.1.8.2 tls {
519 1.1.1.1.8.2 tls pstep = MAX(MIN(GMP_NUMB_BITS/2,(pmax-pmin)/(2*THRESHOLD_WINDOW)),1);
520 1.1.1.1.8.2 tls if (verbose)
521 1.1.1.1.8.2 tls printf ("Pmin = %8lu Pmax = %8lu Pstep=%lu\n", pmin, pmax, pstep);
522 1.1.1.1.8.2 tls p = (pmin + pmax) / 2;
523 1.1.1.1.8.2 tls for (i = numpos = numneg = 0 ; i < THRESHOLD_WINDOW + 1 ; i++)
524 1.1.1.1.8.2 tls {
525 1.1.1.1.8.2 tls measure[i] = domeasure (threshold, func,
526 1.1.1.1.8.2 tls p+(i-THRESHOLD_WINDOW/2)*pstep);
527 1.1.1.1.8.2 tls if (measure[i] > 0)
528 1.1.1.1.8.2 tls numpos ++;
529 1.1.1.1.8.2 tls else if (measure[i] < 0)
530 1.1.1.1.8.2 tls numneg ++;
531 1.1.1.1.8.2 tls }
532 1.1.1.1.8.2 tls if (numpos > numneg)
533 1.1.1.1.8.2 tls /* We use more often algo 1 than algo 2 */
534 1.1.1.1.8.2 tls pmin = p - THRESHOLD_WINDOW/2*pstep;
535 1.1.1.1.8.2 tls else if (numpos < numneg)
536 1.1.1.1.8.2 tls pmax = p + THRESHOLD_WINDOW/2*pstep;
537 1.1.1.1.8.2 tls else
538 1.1.1.1.8.2 tls /* numpos == numneg ... */
539 1.1.1.1.8.2 tls if (++ try > 2)
540 1.1.1.1.8.2 tls {
541 1.1.1.1.8.2 tls *threshold = p;
542 1.1.1.1.8.2 tls if (verbose)
543 1.1.1.1.8.2 tls printf ("Quick find: %lu\n", *threshold);
544 1.1.1.1.8.2 tls return ;
545 1.1.1.1.8.2 tls }
546 1.1.1.1.8.2 tls }
547 1.1.1.1.8.2 tls
548 1.1.1.1.8.2 tls /* Final tune... */
549 1.1.1.1.8.2 tls if (verbose)
550 1.1.1.1.8.2 tls printf ("Finalizing in [%lu, %lu]... ", pmin, pmax);
551 1.1.1.1.8.2 tls for (i = 0 ; i < THRESHOLD_FINAL_WINDOW+1 ; i++)
552 1.1.1.1.8.2 tls measure[i] = domeasure (threshold, func, pmin+i);
553 1.1.1.1.8.2 tls i = analyze_data (measure, THRESHOLD_FINAL_WINDOW+1);
554 1.1.1.1.8.2 tls *threshold = pmin + i;
555 1.1.1.1.8.2 tls if (verbose)
556 1.1.1.1.8.2 tls printf ("%lu\n", *threshold);
557 1.1.1.1.8.2 tls return;
558 1.1.1.1.8.2 tls }
559 1.1.1.1.8.2 tls
560 1.1.1.1.8.2 tls /* Tune a function which behavior depends on both p and x,
561 1.1.1.1.8.2 tls in a given direction.
562 1.1.1.1.8.2 tls It assumes that for (x,p) close to zero, algo1 is used
563 1.1.1.1.8.2 tls and algo2 is used when (x,p) is far from zero.
564 1.1.1.1.8.2 tls If algo2 is better for low prec, and algo1 better for high prec,
565 1.1.1.1.8.2 tls the behaviour of this function is undefined.
566 1.1.1.1.8.2 tls This tuning function tries couples (x,p) of the form (ell*dirx, ell*dirp)
567 1.1.1.1.8.2 tls until it finds a point on the boundary. It returns ell.
568 1.1.1.1.8.2 tls */
569 1.1.1.1.8.2 tls static void
570 1.1.1.1.8.2 tls tune_simple_func_in_some_direction (long int *threshold1,
571 1.1.1.1.8.2 tls long int *threshold2,
572 1.1.1.1.8.2 tls long int *threshold3,
573 1.1.1.1.8.2 tls double (*func) (struct speed_params *),
574 1.1.1.1.8.2 tls mpfr_prec_t pstart,
575 1.1.1.1.8.2 tls int dirx, int dirp,
576 1.1.1.1.8.2 tls mpfr_t xres, mpfr_prec_t *pres)
577 1.1.1.1.8.2 tls {
578 1.1.1.1.8.2 tls double measure[THRESHOLD_FINAL_WINDOW+1];
579 1.1.1.1.8.2 tls double d;
580 1.1.1.1.8.2 tls mpfr_prec_t pstep;
581 1.1.1.1.8.2 tls int i, numpos, numneg, try;
582 1.1.1.1.8.2 tls mpfr_prec_t pmin, pmax, p;
583 1.1.1.1.8.2 tls mpfr_t xmin, xmax, x;
584 1.1.1.1.8.2 tls mpfr_t ratio;
585 1.1.1.1.8.2 tls
586 1.1.1.1.8.2 tls mpfr_init2 (ratio, MPFR_SMALL_PRECISION);
587 1.1.1.1.8.2 tls mpfr_set_si (ratio, dirx, MPFR_RNDN);
588 1.1.1.1.8.2 tls mpfr_div_si (ratio, ratio, dirp, MPFR_RNDN);
589 1.1.1.1.8.2 tls
590 1.1.1.1.8.2 tls mpfr_init2 (xmin, MPFR_SMALL_PRECISION);
591 1.1.1.1.8.2 tls mpfr_init2 (xmax, MPFR_SMALL_PRECISION);
592 1.1.1.1.8.2 tls mpfr_init2 (x, MPFR_SMALL_PRECISION);
593 1.1.1.1.8.2 tls
594 1.1.1.1.8.2 tls /* first look for a lower bound within 10% */
595 1.1.1.1.8.2 tls pmin = p = pstart;
596 1.1.1.1.8.2 tls mpfr_mul_ui (xmin, ratio, (unsigned int)pmin, MPFR_RNDN);
597 1.1.1.1.8.2 tls mpfr_set (x, xmin, MPFR_RNDN);
598 1.1.1.1.8.2 tls
599 1.1.1.1.8.2 tls d = domeasure2 (threshold1, threshold2, threshold3, func, pmin, xmin);
600 1.1.1.1.8.2 tls if (d < 0.0)
601 1.1.1.1.8.2 tls {
602 1.1.1.1.8.2 tls if (verbose)
603 1.1.1.1.8.2 tls printf ("Oops: even for %lu, algo 2 seems to be faster!\n",
604 1.1.1.1.8.2 tls (unsigned long) pmin);
605 1.1.1.1.8.2 tls *pres = MPFR_PREC_MIN;
606 1.1.1.1.8.2 tls mpfr_mul_ui (xres, ratio, (unsigned int)*pres, MPFR_RNDN);
607 1.1.1.1.8.2 tls mpfr_clear (ratio); mpfr_clear (x); mpfr_clear (xmin); mpfr_clear (xmax);
608 1.1.1.1.8.2 tls return;
609 1.1.1.1.8.2 tls }
610 1.1.1.1.8.2 tls if (d >= 1.00)
611 1.1.1.1.8.2 tls for (;;)
612 1.1.1.1.8.2 tls {
613 1.1.1.1.8.2 tls d = domeasure2 (threshold1, threshold2, threshold3, func, pmin, xmin);
614 1.1.1.1.8.2 tls if (d < 1.00)
615 1.1.1.1.8.2 tls break;
616 1.1.1.1.8.2 tls p = pmin;
617 1.1.1.1.8.2 tls mpfr_set (x, xmin, MPFR_RNDN);
618 1.1.1.1.8.2 tls pmin += pmin/2;
619 1.1.1.1.8.2 tls mpfr_mul_ui (xmin, ratio, (unsigned int)pmin, MPFR_RNDN);
620 1.1.1.1.8.2 tls }
621 1.1.1.1.8.2 tls pmin = p;
622 1.1.1.1.8.2 tls mpfr_set (xmin, x, MPFR_RNDN);
623 1.1.1.1.8.2 tls for (;;)
624 1.1.1.1.8.2 tls {
625 1.1.1.1.8.2 tls d = domeasure2 (threshold1, threshold2, threshold3, func, pmin, xmin);
626 1.1.1.1.8.2 tls if (d < 0.10)
627 1.1.1.1.8.2 tls break;
628 1.1.1.1.8.2 tls pmin += GMP_NUMB_BITS;
629 1.1.1.1.8.2 tls mpfr_mul_ui (xmin, ratio, (unsigned int)pmin, MPFR_RNDN);
630 1.1.1.1.8.2 tls }
631 1.1.1.1.8.2 tls
632 1.1.1.1.8.2 tls /* then look for an upper bound within 20% */
633 1.1.1.1.8.2 tls pmax = pmin * 2;
634 1.1.1.1.8.2 tls mpfr_mul_ui (xmax, ratio, (unsigned int)pmax, MPFR_RNDN);
635 1.1.1.1.8.2 tls for (;;)
636 1.1.1.1.8.2 tls {
637 1.1.1.1.8.2 tls d = domeasure2 (threshold1, threshold2, threshold3, func, pmax, xmax);
638 1.1.1.1.8.2 tls if (d < -0.20)
639 1.1.1.1.8.2 tls break;
640 1.1.1.1.8.2 tls pmax += pmin / 2; /* don't increase too rapidly */
641 1.1.1.1.8.2 tls mpfr_mul_ui (xmax, ratio, (unsigned int)pmax, MPFR_RNDN);
642 1.1.1.1.8.2 tls }
643 1.1.1.1.8.2 tls
644 1.1.1.1.8.2 tls /* The threshold is between pmin and pmax. Affine them */
645 1.1.1.1.8.2 tls try = 0;
646 1.1.1.1.8.2 tls while ((pmax-pmin) >= THRESHOLD_FINAL_WINDOW)
647 1.1.1.1.8.2 tls {
648 1.1.1.1.8.2 tls pstep = MAX(MIN(GMP_NUMB_BITS/2,(pmax-pmin)/(2*THRESHOLD_WINDOW)),1);
649 1.1.1.1.8.2 tls if (verbose)
650 1.1.1.1.8.2 tls printf ("Pmin = %8lu Pmax = %8lu Pstep=%lu\n", pmin, pmax, pstep);
651 1.1.1.1.8.2 tls p = (pmin + pmax) / 2;
652 1.1.1.1.8.2 tls mpfr_mul_ui (x, ratio, (unsigned int)p, MPFR_RNDN);
653 1.1.1.1.8.2 tls for (i = numpos = numneg = 0 ; i < THRESHOLD_WINDOW + 1 ; i++)
654 1.1.1.1.8.2 tls {
655 1.1.1.1.8.2 tls *pres = p+(i-THRESHOLD_WINDOW/2)*pstep;
656 1.1.1.1.8.2 tls mpfr_mul_ui (xres, ratio, (unsigned int)*pres, MPFR_RNDN);
657 1.1.1.1.8.2 tls measure[i] = domeasure2 (threshold1, threshold2, threshold3,
658 1.1.1.1.8.2 tls func, *pres, xres);
659 1.1.1.1.8.2 tls if (measure[i] > 0)
660 1.1.1.1.8.2 tls numpos ++;
661 1.1.1.1.8.2 tls else if (measure[i] < 0)
662 1.1.1.1.8.2 tls numneg ++;
663 1.1.1.1.8.2 tls }
664 1.1.1.1.8.2 tls if (numpos > numneg)
665 1.1.1.1.8.2 tls {
666 1.1.1.1.8.2 tls /* We use more often algo 1 than algo 2 */
667 1.1.1.1.8.2 tls pmin = p - THRESHOLD_WINDOW/2*pstep;
668 1.1.1.1.8.2 tls mpfr_mul_ui (xmin, ratio, (unsigned int)pmin, MPFR_RNDN);
669 1.1.1.1.8.2 tls }
670 1.1.1.1.8.2 tls else if (numpos < numneg)
671 1.1.1.1.8.2 tls {
672 1.1.1.1.8.2 tls pmax = p + THRESHOLD_WINDOW/2*pstep;
673 1.1.1.1.8.2 tls mpfr_mul_ui (xmax, ratio, (unsigned int)pmax, MPFR_RNDN);
674 1.1.1.1.8.2 tls }
675 1.1.1.1.8.2 tls else
676 1.1.1.1.8.2 tls /* numpos == numneg ... */
677 1.1.1.1.8.2 tls if (++ try > 2)
678 1.1.1.1.8.2 tls {
679 1.1.1.1.8.2 tls *pres = p;
680 1.1.1.1.8.2 tls mpfr_mul_ui (xres, ratio, (unsigned int)*pres, MPFR_RNDN);
681 1.1.1.1.8.2 tls if (verbose)
682 1.1.1.1.8.2 tls printf ("Quick find: %lu\n", *pres);
683 1.1.1.1.8.2 tls mpfr_clear (ratio);
684 1.1.1.1.8.2 tls mpfr_clear (x); mpfr_clear (xmin); mpfr_clear (xmax);
685 1.1.1.1.8.2 tls return ;
686 1.1.1.1.8.2 tls }
687 1.1.1.1.8.2 tls }
688 1.1.1.1.8.2 tls
689 1.1.1.1.8.2 tls /* Final tune... */
690 1.1.1.1.8.2 tls if (verbose)
691 1.1.1.1.8.2 tls printf ("Finalizing in [%lu, %lu]... ", pmin, pmax);
692 1.1.1.1.8.2 tls for (i = 0 ; i < THRESHOLD_FINAL_WINDOW+1 ; i++)
693 1.1.1.1.8.2 tls {
694 1.1.1.1.8.2 tls *pres = pmin+i;
695 1.1.1.1.8.2 tls mpfr_mul_ui (xres, ratio, (unsigned int)*pres, MPFR_RNDN);
696 1.1.1.1.8.2 tls measure[i] = domeasure2 (threshold1, threshold2, threshold3,
697 1.1.1.1.8.2 tls func, *pres, xres);
698 1.1.1.1.8.2 tls }
699 1.1.1.1.8.2 tls i = analyze_data (measure, THRESHOLD_FINAL_WINDOW+1);
700 1.1.1.1.8.2 tls *pres = pmin + i;
701 1.1.1.1.8.2 tls mpfr_mul_ui (xres, ratio, (unsigned int)*pres, MPFR_RNDN);
702 1.1.1.1.8.2 tls if (verbose)
703 1.1.1.1.8.2 tls printf ("%lu\n", *pres);
704 1.1.1.1.8.2 tls mpfr_clear (ratio); mpfr_clear (x); mpfr_clear (xmin); mpfr_clear (xmax);
705 1.1.1.1.8.2 tls return;
706 1.1.1.1.8.2 tls }
707 1.1.1.1.8.2 tls
708 1.1.1.1.8.2 tls /************************************
709 1.1.1.1.8.2 tls * Tune Mulders' mulhigh function *
710 1.1.1.1.8.2 tls ************************************/
711 1.1.1.1.8.2 tls #define TOLERANCE 1.00
712 1.1.1.1.8.2 tls #define MULDERS_TABLE_SIZE 1024
713 1.1.1.1.8.2 tls #ifndef MPFR_MULHIGH_SIZE
714 1.1.1.1.8.2 tls # define MPFR_MULHIGH_SIZE MULDERS_TABLE_SIZE
715 1.1.1.1.8.2 tls #endif
716 1.1.1.1.8.2 tls #ifndef MPFR_SQRHIGH_SIZE
717 1.1.1.1.8.2 tls # define MPFR_SQRHIGH_SIZE MULDERS_TABLE_SIZE
718 1.1.1.1.8.2 tls #endif
719 1.1.1.1.8.2 tls #ifndef MPFR_DIVHIGH_SIZE
720 1.1.1.1.8.2 tls # define MPFR_DIVHIGH_SIZE MULDERS_TABLE_SIZE
721 1.1.1.1.8.2 tls #endif
722 1.1.1.1.8.2 tls #define MPFR_MULHIGH_TAB_SIZE MPFR_MULHIGH_SIZE
723 1.1.1.1.8.2 tls #define MPFR_SQRHIGH_TAB_SIZE MPFR_SQRHIGH_SIZE
724 1.1.1.1.8.2 tls #define MPFR_DIVHIGH_TAB_SIZE MPFR_DIVHIGH_SIZE
725 1.1.1.1.8.2 tls #include "mulders.c"
726 1.1.1.1.8.2 tls
727 1.1.1.1.8.2 tls static double
728 1.1.1.1.8.2 tls speed_mpfr_mulhigh (struct speed_params *s)
729 1.1.1.1.8.2 tls {
730 1.1.1.1.8.2 tls SPEED_ROUTINE_MPN_MUL_N (mpfr_mulhigh_n);
731 1.1.1.1.8.2 tls }
732 1.1.1.1.8.2 tls
733 1.1.1.1.8.2 tls static double
734 1.1.1.1.8.2 tls speed_mpfr_sqrhigh (struct speed_params *s)
735 1.1.1.1.8.2 tls {
736 1.1.1.1.8.2 tls SPEED_ROUTINE_MPN_SQR (mpfr_sqrhigh_n);
737 1.1.1.1.8.2 tls }
738 1.1.1.1.8.2 tls
739 1.1.1.1.8.2 tls static double
740 1.1.1.1.8.2 tls speed_mpfr_divhigh (struct speed_params *s)
741 1.1.1.1.8.2 tls {
742 1.1.1.1.8.2 tls SPEED_ROUTINE_MPN_DC_DIVREM_CALL (mpfr_divhigh_n (q, a, d, s->size));
743 1.1.1.1.8.2 tls }
744 1.1.1.1.8.2 tls
745 1.1.1.1.8.2 tls #define MAX_STEPS 513 /* maximum number of values of k tried for a given n */
746 1.1.1.1.8.2 tls
747 1.1.1.1.8.2 tls /* Tune mpfr_mulhigh_n for size n */
748 1.1.1.1.8.2 tls static mp_size_t
749 1.1.1.1.8.2 tls tune_mul_mulders_upto (mp_size_t n)
750 1.1.1.1.8.2 tls {
751 1.1.1.1.8.2 tls struct speed_params s;
752 1.1.1.1.8.2 tls mp_size_t k, kbest, step;
753 1.1.1.1.8.2 tls double t, tbest;
754 1.1.1.1.8.2 tls MPFR_TMP_DECL (marker);
755 1.1.1.1.8.2 tls
756 1.1.1.1.8.2 tls if (n == 0)
757 1.1.1.1.8.2 tls return -1;
758 1.1.1.1.8.2 tls
759 1.1.1.1.8.2 tls MPFR_TMP_MARK (marker);
760 1.1.1.1.8.2 tls s.align_xp = s.align_yp = s.align_wp = 64;
761 1.1.1.1.8.2 tls s.size = n;
762 1.1.1.1.8.2 tls s.xp = MPFR_TMP_ALLOC (n * sizeof (mp_limb_t));
763 1.1.1.1.8.2 tls s.yp = MPFR_TMP_ALLOC (n * sizeof (mp_limb_t));
764 1.1.1.1.8.2 tls mpn_random (s.xp, n);
765 1.1.1.1.8.2 tls mpn_random (s.yp, n);
766 1.1.1.1.8.2 tls
767 1.1.1.1.8.2 tls /* Check k == -1, mpn_mul_basecase */
768 1.1.1.1.8.2 tls mulhigh_ktab[n] = -1;
769 1.1.1.1.8.2 tls kbest = -1;
770 1.1.1.1.8.2 tls tbest = mpfr_speed_measure (speed_mpfr_mulhigh, &s, "mpfr_mulhigh");
771 1.1.1.1.8.2 tls
772 1.1.1.1.8.2 tls /* Check k == 0, mpn_mulhigh_n_basecase */
773 1.1.1.1.8.2 tls mulhigh_ktab[n] = 0;
774 1.1.1.1.8.2 tls t = mpfr_speed_measure (speed_mpfr_mulhigh, &s, "mpfr_mulhigh");
775 1.1.1.1.8.2 tls if (t * TOLERANCE < tbest)
776 1.1.1.1.8.2 tls kbest = 0, tbest = t;
777 1.1.1.1.8.2 tls
778 1.1.1.1.8.2 tls /* Check Mulders with cutoff point k */
779 1.1.1.1.8.2 tls step = 1 + n / (2 * MAX_STEPS);
780 1.1.1.1.8.2 tls /* we need k >= (n+3)/2, which translates into k >= (n+4)/2 in C */
781 1.1.1.1.8.2 tls for (k = (n + 4) / 2 ; k < n ; k += step)
782 1.1.1.1.8.2 tls {
783 1.1.1.1.8.2 tls mulhigh_ktab[n] = k;
784 1.1.1.1.8.2 tls t = mpfr_speed_measure (speed_mpfr_mulhigh, &s, "mpfr_mulhigh");
785 1.1.1.1.8.2 tls if (t * TOLERANCE < tbest)
786 1.1.1.1.8.2 tls kbest = k, tbest = t;
787 1.1.1.1.8.2 tls }
788 1.1.1.1.8.2 tls
789 1.1.1.1.8.2 tls mulhigh_ktab[n] = kbest;
790 1.1.1.1.8.2 tls
791 1.1.1.1.8.2 tls MPFR_TMP_FREE (marker);
792 1.1.1.1.8.2 tls return kbest;
793 1.1.1.1.8.2 tls }
794 1.1.1.1.8.2 tls
795 1.1.1.1.8.2 tls /* Tune mpfr_sqrhigh_n for size n */
796 1.1.1.1.8.2 tls static mp_size_t
797 1.1.1.1.8.2 tls tune_sqr_mulders_upto (mp_size_t n)
798 1.1.1.1.8.2 tls {
799 1.1.1.1.8.2 tls struct speed_params s;
800 1.1.1.1.8.2 tls mp_size_t k, kbest, step;
801 1.1.1.1.8.2 tls double t, tbest;
802 1.1.1.1.8.2 tls MPFR_TMP_DECL (marker);
803 1.1.1.1.8.2 tls
804 1.1.1.1.8.2 tls if (n == 0)
805 1.1.1.1.8.2 tls return -1;
806 1.1.1.1.8.2 tls
807 1.1.1.1.8.2 tls MPFR_TMP_MARK (marker);
808 1.1.1.1.8.2 tls s.align_xp = s.align_wp = 64;
809 1.1.1.1.8.2 tls s.size = n;
810 1.1.1.1.8.2 tls s.xp = MPFR_TMP_ALLOC (n * sizeof (mp_limb_t));
811 1.1.1.1.8.2 tls mpn_random (s.xp, n);
812 1.1.1.1.8.2 tls
813 1.1.1.1.8.2 tls /* Check k == -1, mpn_sqr_basecase */
814 1.1.1.1.8.2 tls sqrhigh_ktab[n] = -1;
815 1.1.1.1.8.2 tls kbest = -1;
816 1.1.1.1.8.2 tls tbest = mpfr_speed_measure (speed_mpfr_sqrhigh, &s, "mpfr_sqrhigh");
817 1.1.1.1.8.2 tls
818 1.1.1.1.8.2 tls /* Check k == 0, mpfr_mulhigh_n_basecase */
819 1.1.1.1.8.2 tls sqrhigh_ktab[n] = 0;
820 1.1.1.1.8.2 tls t = mpfr_speed_measure (speed_mpfr_sqrhigh, &s, "mpfr_sqrhigh");
821 1.1.1.1.8.2 tls if (t * TOLERANCE < tbest)
822 1.1.1.1.8.2 tls kbest = 0, tbest = t;
823 1.1.1.1.8.2 tls
824 1.1.1.1.8.2 tls /* Check Mulders */
825 1.1.1.1.8.2 tls step = 1 + n / (2 * MAX_STEPS);
826 1.1.1.1.8.2 tls /* we need k >= (n+3)/2, which translates into k >= (n+4)/2 in C */
827 1.1.1.1.8.2 tls for (k = (n + 4) / 2 ; k < n ; k += step)
828 1.1.1.1.8.2 tls {
829 1.1.1.1.8.2 tls sqrhigh_ktab[n] = k;
830 1.1.1.1.8.2 tls t = mpfr_speed_measure (speed_mpfr_sqrhigh, &s, "mpfr_sqrhigh");
831 1.1.1.1.8.2 tls if (t * TOLERANCE < tbest)
832 1.1.1.1.8.2 tls kbest = k, tbest = t;
833 1.1.1.1.8.2 tls }
834 1.1.1.1.8.2 tls
835 1.1.1.1.8.2 tls sqrhigh_ktab[n] = kbest;
836 1.1.1.1.8.2 tls
837 1.1.1.1.8.2 tls MPFR_TMP_FREE (marker);
838 1.1.1.1.8.2 tls return kbest;
839 1.1.1.1.8.2 tls }
840 1.1.1.1.8.2 tls
841 1.1.1.1.8.2 tls /* Tune mpfr_divhigh_n for size n */
842 1.1.1.1.8.2 tls static mp_size_t
843 1.1.1.1.8.2 tls tune_div_mulders_upto (mp_size_t n)
844 1.1.1.1.8.2 tls {
845 1.1.1.1.8.2 tls struct speed_params s;
846 1.1.1.1.8.2 tls mp_size_t k, kbest, step;
847 1.1.1.1.8.2 tls double t, tbest;
848 1.1.1.1.8.2 tls MPFR_TMP_DECL (marker);
849 1.1.1.1.8.2 tls
850 1.1.1.1.8.2 tls if (n == 0)
851 1.1.1.1.8.2 tls return 0;
852 1.1.1.1.8.2 tls
853 1.1.1.1.8.2 tls MPFR_TMP_MARK (marker);
854 1.1.1.1.8.2 tls s.align_xp = s.align_yp = s.align_wp = s.align_wp2 = 64;
855 1.1.1.1.8.2 tls s.size = n;
856 1.1.1.1.8.2 tls s.xp = MPFR_TMP_ALLOC (n * sizeof (mp_limb_t));
857 1.1.1.1.8.2 tls s.yp = MPFR_TMP_ALLOC (n * sizeof (mp_limb_t));
858 1.1.1.1.8.2 tls mpn_random (s.xp, n);
859 1.1.1.1.8.2 tls mpn_random (s.yp, n);
860 1.1.1.1.8.2 tls
861 1.1.1.1.8.2 tls /* Check k == n, i.e., mpn_divrem */
862 1.1.1.1.8.2 tls divhigh_ktab[n] = n;
863 1.1.1.1.8.2 tls kbest = n;
864 1.1.1.1.8.2 tls tbest = mpfr_speed_measure (speed_mpfr_divhigh, &s, "mpfr_divhigh");
865 1.1.1.1.8.2 tls
866 1.1.1.1.8.2 tls /* Check k == 0, i.e., mpfr_divhigh_n_basecase */
867 1.1.1.1.8.2 tls #if defined(WANT_GMP_INTERNALS) && defined(HAVE___GMPN_SBPI1_DIVAPPR_Q)
868 1.1.1.1.8.2 tls if (n > 2) /* mpn_sbpi1_divappr_q requires dn > 2 */
869 1.1.1.1.8.2 tls #endif
870 1.1.1.1.8.2 tls {
871 1.1.1.1.8.2 tls divhigh_ktab[n] = 0;
872 1.1.1.1.8.2 tls t = mpfr_speed_measure (speed_mpfr_divhigh, &s, "mpfr_divhigh");
873 1.1.1.1.8.2 tls if (t * TOLERANCE < tbest)
874 1.1.1.1.8.2 tls kbest = 0, tbest = t;
875 1.1.1.1.8.2 tls }
876 1.1.1.1.8.2 tls
877 1.1.1.1.8.2 tls /* Check Mulders */
878 1.1.1.1.8.2 tls step = 1 + n / (2 * MAX_STEPS);
879 1.1.1.1.8.2 tls /* we should have (n+3)/2 <= k < n, which translates into
880 1.1.1.1.8.2 tls (n+4)/2 <= k < n in C */
881 1.1.1.1.8.2 tls for (k = (n + 4) / 2 ; k < n ; k += step)
882 1.1.1.1.8.2 tls {
883 1.1.1.1.8.2 tls divhigh_ktab[n] = k;
884 1.1.1.1.8.2 tls t = mpfr_speed_measure (speed_mpfr_divhigh, &s, "mpfr_divhigh");
885 1.1.1.1.8.2 tls if (t * TOLERANCE < tbest)
886 1.1.1.1.8.2 tls kbest = k, tbest = t;
887 1.1.1.1.8.2 tls }
888 1.1.1.1.8.2 tls
889 1.1.1.1.8.2 tls divhigh_ktab[n] = kbest;
890 1.1.1.1.8.2 tls
891 1.1.1.1.8.2 tls MPFR_TMP_FREE (marker);
892 1.1.1.1.8.2 tls
893 1.1.1.1.8.2 tls return kbest;
894 1.1.1.1.8.2 tls }
895 1.1.1.1.8.2 tls
896 1.1.1.1.8.2 tls static void
897 1.1.1.1.8.2 tls tune_mul_mulders (FILE *f)
898 1.1.1.1.8.2 tls {
899 1.1.1.1.8.2 tls mp_size_t k;
900 1.1.1.1.8.2 tls
901 1.1.1.1.8.2 tls if (verbose)
902 1.1.1.1.8.2 tls printf ("Tuning mpfr_mulhigh_n[%d]", (int) MPFR_MULHIGH_TAB_SIZE);
903 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_MULHIGH_TAB \\\n ");
904 1.1.1.1.8.2 tls for (k = 0 ; k < MPFR_MULHIGH_TAB_SIZE ; k++)
905 1.1.1.1.8.2 tls {
906 1.1.1.1.8.2 tls fprintf (f, "%d", (int) tune_mul_mulders_upto (k));
907 1.1.1.1.8.2 tls if (k != MPFR_MULHIGH_TAB_SIZE-1)
908 1.1.1.1.8.2 tls fputc (',', f);
909 1.1.1.1.8.2 tls if ((k+1) % 16 == 0)
910 1.1.1.1.8.2 tls fprintf (f, " \\\n ");
911 1.1.1.1.8.2 tls if (verbose)
912 1.1.1.1.8.2 tls putchar ('.');
913 1.1.1.1.8.2 tls }
914 1.1.1.1.8.2 tls fprintf (f, " \n");
915 1.1.1.1.8.2 tls if (verbose)
916 1.1.1.1.8.2 tls putchar ('\n');
917 1.1.1.1.8.2 tls }
918 1.1.1.1.8.2 tls
919 1.1.1.1.8.2 tls static void
920 1.1.1.1.8.2 tls tune_sqr_mulders (FILE *f)
921 1.1.1.1.8.2 tls {
922 1.1.1.1.8.2 tls mp_size_t k;
923 1.1.1.1.8.2 tls
924 1.1.1.1.8.2 tls if (verbose)
925 1.1.1.1.8.2 tls printf ("Tuning mpfr_sqrhigh_n[%d]", (int) MPFR_SQRHIGH_TAB_SIZE);
926 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_SQRHIGH_TAB \\\n ");
927 1.1.1.1.8.2 tls for (k = 0 ; k < MPFR_SQRHIGH_TAB_SIZE ; k++)
928 1.1.1.1.8.2 tls {
929 1.1.1.1.8.2 tls fprintf (f, "%d", (int) tune_sqr_mulders_upto (k));
930 1.1.1.1.8.2 tls if (k != MPFR_SQRHIGH_TAB_SIZE-1)
931 1.1.1.1.8.2 tls fputc (',', f);
932 1.1.1.1.8.2 tls if ((k+1) % 16 == 0)
933 1.1.1.1.8.2 tls fprintf (f, " \\\n ");
934 1.1.1.1.8.2 tls if (verbose)
935 1.1.1.1.8.2 tls putchar ('.');
936 1.1.1.1.8.2 tls }
937 1.1.1.1.8.2 tls fprintf (f, " \n");
938 1.1.1.1.8.2 tls if (verbose)
939 1.1.1.1.8.2 tls putchar ('\n');
940 1.1.1.1.8.2 tls }
941 1.1.1.1.8.2 tls
942 1.1.1.1.8.2 tls static void
943 1.1.1.1.8.2 tls tune_div_mulders (FILE *f)
944 1.1.1.1.8.2 tls {
945 1.1.1.1.8.2 tls mp_size_t k;
946 1.1.1.1.8.2 tls
947 1.1.1.1.8.2 tls if (verbose)
948 1.1.1.1.8.2 tls printf ("Tuning mpfr_divhigh_n[%d]", (int) MPFR_DIVHIGH_TAB_SIZE);
949 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_DIVHIGH_TAB \\\n ");
950 1.1.1.1.8.2 tls for (k = 0 ; k < MPFR_DIVHIGH_TAB_SIZE ; k++)
951 1.1.1.1.8.2 tls {
952 1.1.1.1.8.2 tls fprintf (f, "%d", (int) tune_div_mulders_upto (k));
953 1.1.1.1.8.2 tls if (k != MPFR_DIVHIGH_TAB_SIZE - 1)
954 1.1.1.1.8.2 tls fputc (',', f);
955 1.1.1.1.8.2 tls if ((k+1) % 16 == 0)
956 1.1.1.1.8.2 tls fprintf (f, " /*%zu-%zu*/ \\\n ", k - 15, k);
957 1.1.1.1.8.2 tls if (verbose)
958 1.1.1.1.8.2 tls putchar ('.');
959 1.1.1.1.8.2 tls }
960 1.1.1.1.8.2 tls fprintf (f, " \n");
961 1.1.1.1.8.2 tls if (verbose)
962 1.1.1.1.8.2 tls putchar ('\n');
963 1.1.1.1.8.2 tls }
964 1.1.1.1.8.2 tls
965 1.1.1.1.8.2 tls /*******************************************************
966 1.1.1.1.8.2 tls * Tuning functions for mpfr_ai *
967 1.1.1.1.8.2 tls *******************************************************/
968 1.1.1.1.8.2 tls
969 1.1.1.1.8.2 tls long int mpfr_ai_threshold1;
970 1.1.1.1.8.2 tls long int mpfr_ai_threshold2;
971 1.1.1.1.8.2 tls long int mpfr_ai_threshold3;
972 1.1.1.1.8.2 tls #undef MPFR_AI_THRESHOLD1
973 1.1.1.1.8.2 tls #define MPFR_AI_THRESHOLD1 mpfr_ai_threshold1
974 1.1.1.1.8.2 tls #undef MPFR_AI_THRESHOLD2
975 1.1.1.1.8.2 tls #define MPFR_AI_THRESHOLD2 mpfr_ai_threshold2
976 1.1.1.1.8.2 tls #undef MPFR_AI_THRESHOLD3
977 1.1.1.1.8.2 tls #define MPFR_AI_THRESHOLD3 mpfr_ai_threshold3
978 1.1.1.1.8.2 tls
979 1.1.1.1.8.2 tls #include "ai.c"
980 1.1.1.1.8.2 tls
981 1.1.1.1.8.2 tls static double
982 1.1.1.1.8.2 tls speed_mpfr_ai (struct speed_params *s)
983 1.1.1.1.8.2 tls {
984 1.1.1.1.8.2 tls SPEED_MPFR_FUNC_WITH_EXPONENT (mpfr_ai);
985 1.1.1.1.8.2 tls }
986 1.1.1.1.8.2 tls
987 1.1.1.1.8.2 tls
988 1.1.1.1.8.2 tls /*******************************************************
989 1.1.1.1.8.2 tls * Tune all the threshold of MPFR *
990 1.1.1.1.8.2 tls * Warning: tune the function in their dependent order!*
991 1.1.1.1.8.2 tls *******************************************************/
992 1.1.1.1.8.2 tls static void
993 1.1.1.1.8.2 tls all (const char *filename)
994 1.1.1.1.8.2 tls {
995 1.1.1.1.8.2 tls FILE *f;
996 1.1.1.1.8.2 tls time_t start_time, end_time;
997 1.1.1.1.8.2 tls struct tm *tp;
998 1.1.1.1.8.2 tls mpfr_t x1, x2, x3, tmp1, tmp2;
999 1.1.1.1.8.2 tls mpfr_prec_t p1, p2, p3;
1000 1.1.1.1.8.2 tls
1001 1.1.1.1.8.2 tls f = fopen (filename, "w");
1002 1.1.1.1.8.2 tls if (f == NULL)
1003 1.1.1.1.8.2 tls {
1004 1.1.1.1.8.2 tls fprintf (stderr, "Can't open file '%s' for writing.\n", filename);
1005 1.1.1.1.8.2 tls abort ();
1006 1.1.1.1.8.2 tls }
1007 1.1.1.1.8.2 tls
1008 1.1.1.1.8.2 tls speed_time_init ();
1009 1.1.1.1.8.2 tls if (verbose)
1010 1.1.1.1.8.2 tls {
1011 1.1.1.1.8.2 tls printf ("Using: %s\n", speed_time_string);
1012 1.1.1.1.8.2 tls printf ("speed_precision %d", speed_precision);
1013 1.1.1.1.8.2 tls if (speed_unittime == 1.0)
1014 1.1.1.1.8.2 tls printf (", speed_unittime 1 cycle");
1015 1.1.1.1.8.2 tls else
1016 1.1.1.1.8.2 tls printf (", speed_unittime %.2e secs", speed_unittime);
1017 1.1.1.1.8.2 tls if (speed_cycletime == 1.0 || speed_cycletime == 0.0)
1018 1.1.1.1.8.2 tls printf (", CPU freq unknown\n");
1019 1.1.1.1.8.2 tls else
1020 1.1.1.1.8.2 tls printf (", CPU freq %.2f MHz\n\n", 1e-6/speed_cycletime);
1021 1.1.1.1.8.2 tls }
1022 1.1.1.1.8.2 tls
1023 1.1.1.1.8.2 tls time (&start_time);
1024 1.1.1.1.8.2 tls tp = localtime (&start_time);
1025 1.1.1.1.8.2 tls fprintf (f, "/* Generated by MPFR's tuneup.c, %d-%02d-%02d, ",
1026 1.1.1.1.8.2 tls tp->tm_year+1900, tp->tm_mon+1, tp->tm_mday);
1027 1.1.1.1.8.2 tls
1028 1.1.1.1.8.2 tls #ifdef __ICC
1029 1.1.1.1.8.2 tls fprintf (f, "icc %d.%d.%d */\n", __ICC / 100, __ICC / 10 % 10, __ICC % 10);
1030 1.1.1.1.8.2 tls #elif defined(__GNUC__)
1031 1.1.1.1.8.2 tls #ifdef __GNUC_PATCHLEVEL__
1032 1.1.1.1.8.2 tls fprintf (f, "gcc %d.%d.%d */\n", __GNUC__, __GNUC_MINOR__,
1033 1.1.1.1.8.2 tls __GNUC_PATCHLEVEL__);
1034 1.1.1.1.8.2 tls #else
1035 1.1.1.1.8.2 tls fprintf (f, "gcc %d.%d */\n", __GNUC__, __GNUC_MINOR__);
1036 1.1.1.1.8.2 tls #endif
1037 1.1.1.1.8.2 tls #elif defined (__SUNPRO_C)
1038 1.1.1.1.8.2 tls fprintf (f, "Sun C %d.%d */\n", __SUNPRO_C / 0x100, __SUNPRO_C % 0x100);
1039 1.1.1.1.8.2 tls #elif defined (__sgi) && defined (_COMPILER_VERSION)
1040 1.1.1.1.8.2 tls fprintf (f, "MIPSpro C %d.%d.%d */\n",
1041 1.1.1.1.8.2 tls _COMPILER_VERSION / 100,
1042 1.1.1.1.8.2 tls _COMPILER_VERSION / 10 % 10,
1043 1.1.1.1.8.2 tls _COMPILER_VERSION % 10);
1044 1.1.1.1.8.2 tls #elif defined (__DECC) && defined (__DECC_VER)
1045 1.1.1.1.8.2 tls fprintf (f, "DEC C %d */\n", __DECC_VER);
1046 1.1.1.1.8.2 tls #else
1047 1.1.1.1.8.2 tls fprintf (f, "system compiler */\n");
1048 1.1.1.1.8.2 tls #endif
1049 1.1.1.1.8.2 tls fprintf (f, "\n\n");
1050 1.1.1.1.8.2 tls fprintf (f, "#ifndef MPFR_TUNE_CASE\n");
1051 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_TUNE_CASE \"src/mparam.h\"\n");
1052 1.1.1.1.8.2 tls fprintf (f, "#endif\n\n");
1053 1.1.1.1.8.2 tls
1054 1.1.1.1.8.2 tls /* Tune mulhigh */
1055 1.1.1.1.8.2 tls tune_mul_mulders (f);
1056 1.1.1.1.8.2 tls
1057 1.1.1.1.8.2 tls /* Tune sqrhigh */
1058 1.1.1.1.8.2 tls tune_sqr_mulders (f);
1059 1.1.1.1.8.2 tls
1060 1.1.1.1.8.2 tls /* Tune divhigh */
1061 1.1.1.1.8.2 tls tune_div_mulders (f);
1062 1.1.1.1.8.2 tls fflush (f);
1063 1.1.1.1.8.2 tls
1064 1.1.1.1.8.2 tls /* Tune mpfr_mul (threshold is in limbs, but it doesn't matter too much) */
1065 1.1.1.1.8.2 tls if (verbose)
1066 1.1.1.1.8.2 tls printf ("Tuning mpfr_mul...\n");
1067 1.1.1.1.8.2 tls tune_simple_func (&mpfr_mul_threshold, speed_mpfr_mul,
1068 1.1.1.1.8.2 tls 2*GMP_NUMB_BITS+1);
1069 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_MUL_THRESHOLD %lu /* limbs */\n",
1070 1.1.1.1.8.2 tls (unsigned long) (mpfr_mul_threshold - 1) / GMP_NUMB_BITS + 1);
1071 1.1.1.1.8.2 tls
1072 1.1.1.1.8.2 tls /* Tune mpfr_sqr (threshold is in limbs, but it doesn't matter too much) */
1073 1.1.1.1.8.2 tls if (verbose)
1074 1.1.1.1.8.2 tls printf ("Tuning mpfr_sqr...\n");
1075 1.1.1.1.8.2 tls tune_simple_func (&mpfr_sqr_threshold, speed_mpfr_sqr,
1076 1.1.1.1.8.2 tls 2*GMP_NUMB_BITS+1);
1077 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_SQR_THRESHOLD %lu /* limbs */\n",
1078 1.1.1.1.8.2 tls (unsigned long) (mpfr_sqr_threshold - 1) / GMP_NUMB_BITS + 1);
1079 1.1.1.1.8.2 tls
1080 1.1.1.1.8.2 tls /* Tune mpfr_div (threshold is in limbs, but it doesn't matter too much) */
1081 1.1.1.1.8.2 tls if (verbose)
1082 1.1.1.1.8.2 tls printf ("Tuning mpfr_div...\n");
1083 1.1.1.1.8.2 tls tune_simple_func (&mpfr_div_threshold, speed_mpfr_div,
1084 1.1.1.1.8.2 tls 2*GMP_NUMB_BITS+1);
1085 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_DIV_THRESHOLD %lu /* limbs */\n",
1086 1.1.1.1.8.2 tls (unsigned long) (mpfr_div_threshold - 1) / GMP_NUMB_BITS + 1);
1087 1.1.1.1.8.2 tls
1088 1.1.1.1.8.2 tls /* Tune mpfr_exp_2 */
1089 1.1.1.1.8.2 tls if (verbose)
1090 1.1.1.1.8.2 tls printf ("Tuning mpfr_exp_2...\n");
1091 1.1.1.1.8.2 tls tune_simple_func (&mpfr_exp_2_threshold, speed_mpfr_exp_2, GMP_NUMB_BITS);
1092 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_EXP_2_THRESHOLD %lu /* bits */\n",
1093 1.1.1.1.8.2 tls (unsigned long) mpfr_exp_2_threshold);
1094 1.1.1.1.8.2 tls
1095 1.1.1.1.8.2 tls /* Tune mpfr_exp */
1096 1.1.1.1.8.2 tls if (verbose)
1097 1.1.1.1.8.2 tls printf ("Tuning mpfr_exp...\n");
1098 1.1.1.1.8.2 tls tune_simple_func (&mpfr_exp_threshold, speed_mpfr_exp,
1099 1.1.1.1.8.2 tls MPFR_PREC_MIN+3*GMP_NUMB_BITS);
1100 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_EXP_THRESHOLD %lu /* bits */\n",
1101 1.1.1.1.8.2 tls (unsigned long) mpfr_exp_threshold);
1102 1.1.1.1.8.2 tls
1103 1.1.1.1.8.2 tls /* Tune mpfr_sin_cos */
1104 1.1.1.1.8.2 tls if (verbose)
1105 1.1.1.1.8.2 tls printf ("Tuning mpfr_sin_cos...\n");
1106 1.1.1.1.8.2 tls tune_simple_func (&mpfr_sincos_threshold, speed_mpfr_sincos,
1107 1.1.1.1.8.2 tls MPFR_PREC_MIN+3*GMP_NUMB_BITS);
1108 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_SINCOS_THRESHOLD %lu /* bits */\n",
1109 1.1.1.1.8.2 tls (unsigned long) mpfr_sincos_threshold);
1110 1.1.1.1.8.2 tls
1111 1.1.1.1.8.2 tls /* Tune mpfr_ai */
1112 1.1.1.1.8.2 tls if (verbose)
1113 1.1.1.1.8.2 tls printf ("Tuning mpfr_ai...\n");
1114 1.1.1.1.8.2 tls mpfr_init2 (x1, MPFR_SMALL_PRECISION);
1115 1.1.1.1.8.2 tls mpfr_init2 (x2, MPFR_SMALL_PRECISION);
1116 1.1.1.1.8.2 tls mpfr_init2 (x3, MPFR_SMALL_PRECISION);
1117 1.1.1.1.8.2 tls mpfr_init2 (tmp1, MPFR_SMALL_PRECISION);
1118 1.1.1.1.8.2 tls mpfr_init2 (tmp2, MPFR_SMALL_PRECISION);
1119 1.1.1.1.8.2 tls
1120 1.1.1.1.8.2 tls tune_simple_func_in_some_direction (&mpfr_ai_threshold1, &mpfr_ai_threshold2,
1121 1.1.1.1.8.2 tls &mpfr_ai_threshold3, speed_mpfr_ai,
1122 1.1.1.1.8.2 tls MPFR_PREC_MIN+GMP_NUMB_BITS,
1123 1.1.1.1.8.2 tls -60, 200, x1, &p1);
1124 1.1.1.1.8.2 tls tune_simple_func_in_some_direction (&mpfr_ai_threshold1, &mpfr_ai_threshold2,
1125 1.1.1.1.8.2 tls &mpfr_ai_threshold3, speed_mpfr_ai,
1126 1.1.1.1.8.2 tls MPFR_PREC_MIN+GMP_NUMB_BITS,
1127 1.1.1.1.8.2 tls -20, 500, x2, &p2);
1128 1.1.1.1.8.2 tls tune_simple_func_in_some_direction (&mpfr_ai_threshold1, &mpfr_ai_threshold2,
1129 1.1.1.1.8.2 tls &mpfr_ai_threshold3, speed_mpfr_ai,
1130 1.1.1.1.8.2 tls MPFR_PREC_MIN+GMP_NUMB_BITS,
1131 1.1.1.1.8.2 tls 40, 200, x3, &p3);
1132 1.1.1.1.8.2 tls
1133 1.1.1.1.8.2 tls mpfr_mul_ui (tmp1, x2, (unsigned long)p1, MPFR_RNDN);
1134 1.1.1.1.8.2 tls mpfr_mul_ui (tmp2, x1, (unsigned long)p2, MPFR_RNDN);
1135 1.1.1.1.8.2 tls mpfr_sub (tmp1, tmp1, tmp2, MPFR_RNDN);
1136 1.1.1.1.8.2 tls mpfr_div_ui (tmp1, tmp1, MPFR_AI_SCALE, MPFR_RNDN);
1137 1.1.1.1.8.2 tls
1138 1.1.1.1.8.2 tls mpfr_set_ui (tmp2, (unsigned long)p1, MPFR_RNDN);
1139 1.1.1.1.8.2 tls mpfr_sub_ui (tmp2, tmp2, (unsigned long)p2, MPFR_RNDN);
1140 1.1.1.1.8.2 tls mpfr_div (tmp2, tmp2, tmp1, MPFR_RNDN);
1141 1.1.1.1.8.2 tls mpfr_ai_threshold1 = mpfr_get_si (tmp2, MPFR_RNDN);
1142 1.1.1.1.8.2 tls
1143 1.1.1.1.8.2 tls mpfr_sub (tmp2, x2, x1, MPFR_RNDN);
1144 1.1.1.1.8.2 tls mpfr_div (tmp2, tmp2, tmp1, MPFR_RNDN);
1145 1.1.1.1.8.2 tls mpfr_ai_threshold2 = mpfr_get_si (tmp2, MPFR_RNDN);
1146 1.1.1.1.8.2 tls
1147 1.1.1.1.8.2 tls mpfr_set_ui (tmp1, (unsigned long)p3, MPFR_RNDN);
1148 1.1.1.1.8.2 tls mpfr_mul_si (tmp1, tmp1, mpfr_ai_threshold2, MPFR_RNDN);
1149 1.1.1.1.8.2 tls mpfr_ui_sub (tmp1, MPFR_AI_SCALE, tmp1, MPFR_RNDN);
1150 1.1.1.1.8.2 tls mpfr_div (tmp1, tmp1, x3, MPFR_RNDN);
1151 1.1.1.1.8.2 tls mpfr_ai_threshold3 = mpfr_get_si (tmp1, MPFR_RNDN);
1152 1.1.1.1.8.2 tls
1153 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_AI_THRESHOLD1 %ld /* threshold for negative input of mpfr_ai */\n", mpfr_ai_threshold1);
1154 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_AI_THRESHOLD2 %ld\n", mpfr_ai_threshold2);
1155 1.1.1.1.8.2 tls fprintf (f, "#define MPFR_AI_THRESHOLD3 %ld\n", mpfr_ai_threshold3);
1156 1.1.1.1.8.2 tls
1157 1.1.1.1.8.2 tls mpfr_clear (x1); mpfr_clear (x2); mpfr_clear (x3);
1158 1.1.1.1.8.2 tls mpfr_clear (tmp1); mpfr_clear (tmp2);
1159 1.1.1.1.8.2 tls
1160 1.1.1.1.8.2 tls /* End of tuning */
1161 1.1.1.1.8.2 tls time (&end_time);
1162 1.1.1.1.8.2 tls fprintf (f, "/* Tuneup completed successfully, took %ld seconds */\n",
1163 1.1.1.1.8.2 tls (long) (end_time - start_time));
1164 1.1.1.1.8.2 tls if (verbose)
1165 1.1.1.1.8.2 tls printf ("Complete (took %ld seconds).\n", (long) (end_time - start_time));
1166 1.1.1.1.8.2 tls
1167 1.1.1.1.8.2 tls fclose (f);
1168 1.1.1.1.8.2 tls }
1169 1.1.1.1.8.2 tls
1170 1.1.1.1.8.2 tls
1171 1.1.1.1.8.2 tls /* Main function */
1172 1.1.1.1.8.2 tls int main (int argc, char *argv[])
1173 1.1.1.1.8.2 tls {
1174 1.1.1.1.8.2 tls /* Unbuffered so if output is redirected to a file it isn't lost if the
1175 1.1.1.1.8.2 tls program is killed part way through. */
1176 1.1.1.1.8.2 tls setbuf (stdout, NULL);
1177 1.1.1.1.8.2 tls setbuf (stderr, NULL);
1178 1.1.1.1.8.2 tls
1179 1.1.1.1.8.2 tls verbose = argc > 1;
1180 1.1.1.1.8.2 tls
1181 1.1.1.1.8.2 tls if (verbose)
1182 1.1.1.1.8.2 tls printf ("Tuning MPFR (Coffee time?)...\n");
1183 1.1.1.1.8.2 tls
1184 1.1.1.1.8.2 tls all ("mparam.h");
1185 1.1.1.1.8.2 tls
1186 1.1.1.1.8.2 tls return 0;
1187 1.1.1.1.8.2 tls }
1188