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