Annotation of OpenXM_contrib/gmp/tune/speed.h, Revision 1.1.1.1
1.1 maekawa 1: /* Header for speed and threshold things. */
2:
3: /*
4: Copyright (C) 1999, 2000 Free Software Foundation, Inc.
5:
6: This file is part of the GNU MP Library.
7:
8: The GNU MP Library is free software; you can redistribute it and/or modify
9: it under the terms of the GNU Lesser General Public License as published by
10: the Free Software Foundation; either version 2.1 of the License, or (at your
11: option) any later version.
12:
13: The GNU MP Library is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16: License for more details.
17:
18: You should have received a copy of the GNU Lesser General Public License
19: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21: MA 02111-1307, USA.
22: */
23:
24: #ifndef __SPEED_H__
25: #define __SPEED_H__
26:
27:
28: /* sizes of temporary space required */
29: #define MPN_KARA_MUL_N_TSIZE(n) (2*((n)+BITS_PER_MP_LIMB))
30: #define MPN_KARA_SQR_N_TSIZE(n) (2*((n)+BITS_PER_MP_LIMB))
31: #define MPN_TOOM3_MUL_N_TSIZE(n) (2*(n) + 3*BITS_PER_MP_LIMB)
32: #define MPN_TOOM3_SQR_N_TSIZE(n) (2*((n) + BITS_PER_MP_LIMB))
33:
34:
35: /* Pad ptr,oldsize with zero limbs (at the most significant end) to make it
36: newsize long. */
37: #define MPN_ZERO_EXTEND(ptr, oldsize, newsize) \
38: do { \
39: ASSERT ((newsize) >= (oldsize)); \
40: MPN_ZERO ((ptr)+(oldsize), (newsize)-(oldsize)); \
41: } while (0)
42:
43: /* A mask of the least significant n bits. Note 1<<32 doesn't give zero on
44: x86 family CPUs, hence the separate case for BITS_PER_MP_LIMB. */
45: #define MP_LIMB_T_LOWBITMASK(n) \
46: ((n) == BITS_PER_MP_LIMB ? MP_LIMB_T_MAX : ((mp_limb_t) 1 << (n)) - 1)
47:
48:
49: /* align must be a power of 2 here, usually CACHE_LINE_SIZE is a good choice */
50:
51: #define TMP_ALLOC_ALIGNED(bytes, align) \
52: align_pointer (TMP_ALLOC ((bytes) + (align)-1), (align))
53: #define TMP_ALLOC_LIMBS_ALIGNED(limbs, align) \
54: ((mp_ptr) TMP_ALLOC_ALIGNED ((limbs)*sizeof(mp_limb_t), align))
55:
56: /* 32 for pentium, 64 for athlon, might want to configure this for other
57: CPUs. In truth though nothing has yet shown up that cares about cache
58: line boundaries. The only practical effect of this is to restrict the
59: range that s->align_xp can take. Perhaps this could be a variable
60: instead. */
61: #define CACHE_LINE_SIZE 64 /* bytes */
62:
63: #define SPEED_TMP_ALLOC_ADJUST_MASK (CACHE_LINE_SIZE/BYTES_PER_MP_LIMB - 1)
64:
65: #define SPEED_TMP_ALLOC_LIMBS(limbs, align) \
66: (speed_tmp_alloc_adjust \
67: (TMP_ALLOC_LIMBS((limbs) + SPEED_TMP_ALLOC_ADJUST_MASK), (align)))
68:
69:
70: /* This is the size for s->xp_block and s->yp_block, used in certain
71: routines that want to run across many different data values and use
72: s->size for a different purpose, eg. SPEED_ROUTINE_MPN_GCD_1.
73:
74: 512 means 2kbytes of data for each of xp_block and yp_block, making 4k
75: total, which should fit easily in any L1 data cache. */
76:
77: #define SPEED_BLOCK_SIZE 512 /* limbs */
78:
79:
80: extern double speed_unittime;
81: extern double speed_cycletime;
82: extern int speed_precision;
83: extern const char *speed_time_string;
84: void speed_time_init _PROTO ((void));
85: void speed_starttime _PROTO ((void));
86: double speed_endtime _PROTO ((void));
87:
88: struct speed_params {
89: unsigned reps; /* how many times to run the routine */
90: mp_ptr xp; /* first argument */
91: mp_ptr yp; /* second argument */
92: mp_size_t size; /* size of both arguments */
93: long r; /* user supplied parameter */
94: mp_size_t align_xp; /* alignment of xp */
95: mp_size_t align_yp; /* alignment of yp */
96: mp_size_t align_wp; /* intended alignment of wp */
97: mp_size_t align_wp2; /* intended alignment of wp2 */
98: mp_ptr xp_block; /* first special SPEED_BLOCK_SIZE block */
99: mp_ptr yp_block; /* second special SPEED_BLOCK_SIZE block */
100:
101: double time_divisor; /* optionally set by the speed routine */
102:
103: /* used by the cache priming things */
104: int cache;
105: unsigned src_num, dst_num;
106: struct {
107: mp_ptr ptr;
108: mp_size_t size;
109: } src[2], dst[3];
110: };
111:
112: typedef double (*speed_function_t) _PROTO ((struct speed_params *s));
113:
114: double speed_measure _PROTO ((speed_function_t fun, struct speed_params *s));
115:
116: /* Prototypes for speed measuring routines */
117:
118: double speed_malloc_free _PROTO ((struct speed_params *s));
119: double speed_malloc_realloc_free _PROTO ((struct speed_params *s));
120: double speed_memcpy _PROTO ((struct speed_params *s));
121: double speed_modlimb_invert _PROTO ((struct speed_params *s));
122: double speed_mp_allocate_free _PROTO ((struct speed_params *s));
123: double speed_mp_allocate_reallocate_free _PROTO ((struct speed_params *s));
124:
125: double speed_mpf_init_clear _PROTO ((struct speed_params *s));
126:
127: double speed_mpn_add_n _PROTO ((struct speed_params *s));
128: double speed_mpn_add_n_self _PROTO ((struct speed_params *s));
129: double speed_mpn_add_n_inplace _PROTO ((struct speed_params *s));
130: double speed_mpn_and_n _PROTO ((struct speed_params *s));
131: double speed_mpn_andn_n _PROTO ((struct speed_params *s));
132: double speed_mpn_addmul_1 _PROTO ((struct speed_params *s));
133: double speed_mpn_bz_divrem_n _PROTO ((struct speed_params *s));
134: double speed_mpn_bz_divrem_sb _PROTO ((struct speed_params *s));
135: double speed_mpn_bz_tdiv_qr _PROTO ((struct speed_params *s));
136: double speed_MPN_COPY _PROTO ((struct speed_params *s));
137: double speed_MPN_COPY_DECR _PROTO ((struct speed_params *s));
138: double speed_MPN_COPY_INCR _PROTO ((struct speed_params *s));
139: double speed_mpn_divexact_by3 _PROTO ((struct speed_params *s));
140: double speed_mpn_divmod_1 _PROTO ((struct speed_params *s));
141: double speed_mpn_divrem_1 _PROTO ((struct speed_params *s));
142: double speed_mpn_divrem_1f _PROTO ((struct speed_params *s));
143: double speed_mpn_divrem_1c _PROTO ((struct speed_params *s));
144: double speed_mpn_divrem_1cf _PROTO ((struct speed_params *s));
145: double speed_mpn_divrem_2 _PROTO ((struct speed_params *s));
146: double speed_mpn_gcd _PROTO ((struct speed_params *s));
147: double speed_mpn_gcd_1 _PROTO ((struct speed_params *s));
148: double speed_mpn_gcdext _PROTO ((struct speed_params *s));
149: double speed_mpn_hamdist _PROTO ((struct speed_params *s));
150: double speed_mpn_ior_n _PROTO ((struct speed_params *s));
151: double speed_mpn_iorn_n _PROTO ((struct speed_params *s));
152: double speed_mpn_jacobi_base _PROTO ((struct speed_params *s));
153: double speed_mpn_kara_mul_n _PROTO ((struct speed_params *s));
154: double speed_mpn_kara_sqr_n _PROTO ((struct speed_params *s));
155: double speed_mpn_lshift _PROTO ((struct speed_params *s));
156: double speed_mpn_mod_1 _PROTO ((struct speed_params *s));
157: double speed_mpn_mod_1c _PROTO ((struct speed_params *s));
158: double speed_mpn_mul_1 _PROTO ((struct speed_params *s));
159: double speed_mpn_mul_basecase _PROTO ((struct speed_params *s));
160: double speed_mpn_mul_fft _PROTO ((struct speed_params *s));
161: double speed_mpn_mul_fft_sqr _PROTO ((struct speed_params *s));
162: double speed_mpn_mul_fft_full _PROTO ((struct speed_params *s));
163: double speed_mpn_mul_fft_full_sqr _PROTO ((struct speed_params *s));
164: double speed_mpn_mul_n _PROTO ((struct speed_params *s));
165: double speed_mpn_mul_n_sqr _PROTO ((struct speed_params *s));
166: double speed_mpn_mul_n_toom3 _PROTO ((struct speed_params *s));
167: double speed_mpn_nand_n _PROTO ((struct speed_params *s));
168: double speed_mpn_nior_n _PROTO ((struct speed_params *s));
169: double speed_mpn_popcount _PROTO ((struct speed_params *s));
170: double speed_mpn_rshift _PROTO ((struct speed_params *s));
171: double speed_mpn_sqr_basecase _PROTO ((struct speed_params *s));
172: double speed_mpn_sqr_n _PROTO ((struct speed_params *s));
173: double speed_mpn_sqr_toom3 _PROTO ((struct speed_params *s));
174: double speed_mpn_sub_n _PROTO ((struct speed_params *s));
175: double speed_mpn_submul_1 _PROTO ((struct speed_params *s));
176: double speed_mpn_toom3_mul_n _PROTO ((struct speed_params *s));
177: double speed_mpn_toom3_sqr_n _PROTO ((struct speed_params *s));
178: double speed_mpn_udiv_qrnnd _PROTO ((struct speed_params *s));
179: double speed_mpn_umul_ppmm _PROTO ((struct speed_params *s));
180: double speed_mpn_xnor_n _PROTO ((struct speed_params *s));
181: double speed_mpn_xor_n _PROTO ((struct speed_params *s));
182:
183: double speed_mpq_init_clear _PROTO ((struct speed_params *s));
184:
185: double speed_mpz_add _PROTO ((struct speed_params *s));
186: double speed_mpz_bin_uiui _PROTO ((struct speed_params *s));
187: double speed_mpz_fac_ui _PROTO ((struct speed_params *s));
188: double speed_mpz_fib_ui _PROTO ((struct speed_params *s));
189: double speed_mpz_init_clear _PROTO ((struct speed_params *s));
190: double speed_mpz_init_realloc_clear _PROTO ((struct speed_params *s));
191: double speed_mpz_powm _PROTO ((struct speed_params *s));
192:
193: double speed_noop _PROTO ((struct speed_params *s));
194: double speed_noop_wxs _PROTO ((struct speed_params *s));
195: double speed_noop_wxys _PROTO ((struct speed_params *s));
196:
197: double speed_udiv_qrnnd _PROTO ((struct speed_params *s));
198: double speed_udiv_qrnnd_preinv _PROTO ((struct speed_params *s));
199: double speed_udiv_qrnnd_preinv2norm _PROTO ((struct speed_params *s));
200: double speed_umul_ppmm _PROTO ((struct speed_params *s));
201:
202:
203: /* Prototypes for other routines */
204:
205: /* low 32-bits in p[0], high 32-bits in p[1] */
206: void speed_cyclecounter _PROTO ((unsigned p[2]));
207:
208: void pentium_wbinvd _PROTO ((void));
209:
210: void noop _PROTO ((void));
211: void noop_1 _PROTO ((mp_limb_t n));
212: void noop_wxs _PROTO ((mp_ptr wp, mp_srcptr xp, mp_size_t size));
213: void noop_wxys _PROTO ((mp_ptr wp, mp_srcptr xp, mp_srcptr yp,
214: mp_size_t size));
215: void mpn_cache_fill _PROTO ((mp_srcptr ptr, mp_size_t size));
216: void mpn_cache_fill_dummy _PROTO ((mp_limb_t n));
217: mp_ptr speed_tmp_alloc_adjust _PROTO ((void *ptr, mp_size_t align));
218: void *_mp_allocate_or_reallocate _PROTO ((void *ptr,
219: size_t oldsize, size_t newsize));
220: void *align_pointer _PROTO ((void *p, size_t align));
221: void *_mp_allocate_func_aligned _PROTO ((size_t bytes, size_t align));
222: void speed_cache_fill _PROTO ((struct speed_params *s));
223: void speed_operand_src _PROTO ((struct speed_params *s,
224: mp_ptr ptr, mp_size_t size));
225: void speed_operand_dst _PROTO ((struct speed_params *s,
226: mp_ptr ptr, mp_size_t size));
227: void mpz_set_n _PROTO ((mpz_ptr z, mp_srcptr p, mp_size_t size));
228:
229: extern int speed_option_addrs;
230: void speed_option_set _PROTO((const char *s));
231:
232:
233: #define SPEED_RESTRICT_COND(cond) if (!(cond)) return -1.0;
234:
235: /* For mpn_copy or similar. */
236: #define SPEED_ROUTINE_MPN_COPY_CALL(call) \
237: { \
238: mp_ptr wp; \
239: unsigned i; \
240: double t; \
241: TMP_DECL (marker); \
242: \
243: SPEED_RESTRICT_COND (s->size >= 0); \
244: \
245: TMP_MARK (marker); \
246: wp = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp); \
247: \
248: speed_operand_src (s, s->xp, s->size); \
249: speed_operand_dst (s, wp, s->size); \
250: speed_cache_fill (s); \
251: \
252: speed_starttime (); \
253: i = s->reps; \
254: do \
255: call; \
256: while (--i != 0); \
257: t = speed_endtime (); \
258: \
259: TMP_FREE (marker); \
260: return t; \
261: }
262:
263: #define SPEED_ROUTINE_MPN_COPY(function) \
264: SPEED_ROUTINE_MPN_COPY_CALL(function (wp, s->xp, s->size))
265: #define SPEED_ROUTINE_MPN_COPYC(function) \
266: SPEED_ROUTINE_MPN_COPY_CALL(function (wp, s->xp, s->size, 0))
267:
268:
269: /* For mpn_add_n, mpn_sub_n, or similar. */
270: #define SPEED_ROUTINE_MPN_BINARY_N_CALL(call) \
271: { \
272: mp_ptr wp; \
273: unsigned i; \
274: double t; \
275: TMP_DECL (marker); \
276: \
277: SPEED_RESTRICT_COND (s->size >= 1); \
278: \
279: TMP_MARK (marker); \
280: wp = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp); \
281: \
282: speed_operand_src (s, s->xp, s->size); \
283: speed_operand_src (s, s->yp, s->size); \
284: speed_operand_dst (s, wp, s->size); \
285: speed_cache_fill (s); \
286: \
287: speed_starttime (); \
288: i = s->reps; \
289: do \
290: call; \
291: while (--i != 0); \
292: t = speed_endtime (); \
293: \
294: TMP_FREE (marker); \
295: return t; \
296: }
297:
298: #define SPEED_ROUTINE_MPN_BINARY_N(function) \
299: SPEED_ROUTINE_MPN_BINARY_N_CALL ((*function) (wp, s->xp, s->yp, s->size))
300:
301: #define SPEED_ROUTINE_MPN_BINARY_NC(function) \
302: SPEED_ROUTINE_MPN_BINARY_N_CALL ((*function) (wp, s->xp, s->yp, s->size, 0))
303:
304: #define SPEED_ROUTINE_MPN_BINARY_N_SELF(function) \
305: SPEED_ROUTINE_MPN_BINARY_N_CALL ((*function) (wp, s->xp, s->xp, s->size))
306:
307: #define SPEED_ROUTINE_MPN_BINARY_N_INPLACE(function) \
308: SPEED_ROUTINE_MPN_BINARY_N_CALL ((*function) (wp, wp, s->xp, s->size))
309:
310:
311: /* For mpn_lshift, mpn_rshift, mpn_mul_1, with r, or similar. */
312: #define SPEED_ROUTINE_MPN_UNARY_1_CALL(call) \
313: { \
314: mp_ptr wp; \
315: unsigned i; \
316: double t; \
317: TMP_DECL (marker); \
318: \
319: SPEED_RESTRICT_COND (s->size >= 1); \
320: \
321: TMP_MARK (marker); \
322: wp = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp); \
323: \
324: speed_operand_src (s, s->xp, s->size); \
325: speed_operand_dst (s, wp, s->size); \
326: speed_cache_fill (s); \
327: \
328: speed_starttime (); \
329: i = s->reps; \
330: do \
331: call; \
332: while (--i != 0); \
333: t = speed_endtime (); \
334: \
335: TMP_FREE (marker); \
336: return t; \
337: }
338:
339: #define SPEED_ROUTINE_MPN_UNARY_1(function) \
340: SPEED_ROUTINE_MPN_UNARY_1_CALL ((*function) (wp, s->xp, s->size, s->r))
341:
342: #define SPEED_ROUTINE_MPN_UNARY_1C(function) \
343: SPEED_ROUTINE_MPN_UNARY_1_CALL ((*function) (wp, s->xp, s->size, s->r, 0))
344:
345: #define SPEED_ROUTINE_MPN_DIVREM_1(function) \
346: SPEED_ROUTINE_MPN_UNARY_1_CALL ((*function) (wp, 0, s->xp, s->size, s->r))
347:
348: #define SPEED_ROUTINE_MPN_DIVREM_1C(function) \
349: SPEED_ROUTINE_MPN_UNARY_1_CALL ((*function) (wp, 0, s->xp, s->size, s->r, 0))
350:
351: #define SPEED_ROUTINE_MPN_DIVREM_1F(function) \
352: SPEED_ROUTINE_MPN_UNARY_1_CALL ((*function) (wp, s->size, s->xp, 0, s->r))
353:
354: #define SPEED_ROUTINE_MPN_DIVREM_1CF(function) \
355: SPEED_ROUTINE_MPN_UNARY_1_CALL ((*function) (wp, s->size, s->xp, 0, s->r, 0))
356:
357:
358: /* For mpn_mul_basecase, xsize=r, ysize=s->size. */
359: #define SPEED_ROUTINE_MPN_MUL_BASECASE(function) \
360: { \
361: mp_ptr wp; \
362: mp_size_t size1; \
363: unsigned i; \
364: double t; \
365: TMP_DECL (marker); \
366: \
367: size1 = (s->r == 0 ? s->size : s->r); \
368: \
369: SPEED_RESTRICT_COND (s->size >= 1); \
370: SPEED_RESTRICT_COND (size1 >= s->size); \
371: \
372: TMP_MARK (marker); \
373: wp = SPEED_TMP_ALLOC_LIMBS (size1 + s->size, s->align_wp); \
374: \
375: speed_operand_src (s, s->xp, size1); \
376: speed_operand_src (s, s->yp, s->size); \
377: speed_operand_dst (s, wp, size1 + s->size); \
378: speed_cache_fill (s); \
379: \
380: speed_starttime (); \
381: i = s->reps; \
382: do \
383: function (wp, s->xp, size1, s->yp, s->size); \
384: while (--i != 0); \
385: t = speed_endtime (); \
386: \
387: TMP_FREE (marker); \
388: return t; \
389: }
390:
391:
392: #define SPEED_ROUTINE_MPN_MUL_N_CALL(call) \
393: { \
394: mp_ptr wp; \
395: unsigned i; \
396: double t; \
397: TMP_DECL (marker); \
398: \
399: SPEED_RESTRICT_COND (s->size >= 1); \
400: \
401: TMP_MARK (marker); \
402: wp = SPEED_TMP_ALLOC_LIMBS (2*s->size, s->align_wp); \
403: \
404: speed_operand_src (s, s->xp, s->size); \
405: speed_operand_src (s, s->yp, s->size); \
406: speed_operand_dst (s, wp, 2*s->size); \
407: speed_cache_fill (s); \
408: \
409: speed_starttime (); \
410: i = s->reps; \
411: do \
412: call; \
413: while (--i != 0); \
414: t = speed_endtime (); \
415: \
416: TMP_FREE (marker); \
417: return t; \
418: }
419:
420: #define SPEED_ROUTINE_MPN_MUL_N(function) \
421: SPEED_ROUTINE_MPN_MUL_N_CALL (function (wp, s->xp, s->yp, s->size));
422:
423:
424: #define SPEED_ROUTINE_MPN_MUL_N_TSPACE(call, tsize) \
425: { \
426: mp_ptr wp, tspace; \
427: unsigned i; \
428: double t; \
429: TMP_DECL (marker); \
430: \
431: SPEED_RESTRICT_COND (s->size >= 1); \
432: \
433: TMP_MARK (marker); \
434: wp = SPEED_TMP_ALLOC_LIMBS (2*s->size, s->align_wp); \
435: tspace = SPEED_TMP_ALLOC_LIMBS (tsize, s->align_wp2); \
436: \
437: speed_operand_src (s, s->xp, s->size); \
438: speed_operand_src (s, s->yp, s->size); \
439: speed_operand_dst (s, wp, 2*s->size); \
440: speed_operand_dst (s, tspace, tsize); \
441: speed_cache_fill (s); \
442: \
443: speed_starttime (); \
444: i = s->reps; \
445: do \
446: call; \
447: while (--i != 0); \
448: t = speed_endtime (); \
449: \
450: TMP_FREE (marker); \
451: return t; \
452: }
453:
454: /* FIXME: size restrictions */
455: #define SPEED_ROUTINE_MPN_KARA_MUL_N(function) \
456: SPEED_ROUTINE_MPN_MUL_N_TSPACE \
457: (function (wp, s->xp, s->xp, s->size, tspace), \
458: MPN_KARA_MUL_N_TSIZE (s->size))
459:
460: /* FIXME: size restrictions */
461: #define SPEED_ROUTINE_MPN_TOOM3_MUL_N(function) \
462: SPEED_ROUTINE_MPN_MUL_N_TSPACE \
463: (function (wp, s->xp, s->yp, s->size, tspace), \
464: MPN_TOOM3_MUL_N_TSIZE (s->size))
465:
466:
467: #define SPEED_ROUTINE_MPN_SQR_CALL(call) \
468: { \
469: mp_ptr wp; \
470: unsigned i; \
471: double t; \
472: TMP_DECL (marker); \
473: \
474: SPEED_RESTRICT_COND (s->size >= 1); \
475: \
476: TMP_MARK (marker); \
477: wp = SPEED_TMP_ALLOC_LIMBS (2*s->size, s->align_wp); \
478: \
479: speed_operand_src (s, s->xp, s->size); \
480: speed_operand_dst (s, wp, 2*s->size); \
481: speed_cache_fill (s); \
482: \
483: speed_starttime (); \
484: i = s->reps; \
485: do \
486: call; \
487: while (--i != 0); \
488: t = speed_endtime (); \
489: \
490: TMP_FREE (marker); \
491: return t; \
492: }
493:
494: #define SPEED_ROUTINE_MPN_SQR(function) \
495: SPEED_ROUTINE_MPN_SQR_CALL (function (wp, s->xp, s->size))
496:
497:
498: #define SPEED_ROUTINE_MPN_SQR_TSPACE(call, tsize) \
499: { \
500: mp_ptr wp, tspace; \
501: unsigned i; \
502: double t; \
503: TMP_DECL (marker); \
504: \
505: SPEED_RESTRICT_COND (s->size >= 1); \
506: \
507: TMP_MARK (marker); \
508: wp = SPEED_TMP_ALLOC_LIMBS (2*s->size, s->align_wp); \
509: tspace = SPEED_TMP_ALLOC_LIMBS (tsize, s->align_wp2); \
510: \
511: speed_operand_src (s, s->xp, s->size); \
512: speed_operand_dst (s, wp, 2*s->size); \
513: speed_operand_dst (s, tspace, tsize); \
514: speed_cache_fill (s); \
515: \
516: speed_starttime (); \
517: i = s->reps; \
518: do \
519: call; \
520: while (--i != 0); \
521: t = speed_endtime (); \
522: \
523: TMP_FREE (marker); \
524: return t; \
525: }
526:
527: /* FIXME: size restrictions */
528: #define SPEED_ROUTINE_MPN_KARA_SQR_N(function) \
529: SPEED_ROUTINE_MPN_SQR_TSPACE (function (wp, s->xp, s->size, tspace), \
530: MPN_KARA_SQR_N_TSIZE (s->size))
531:
532: /* FIXME: size restrictions */
533: #define SPEED_ROUTINE_MPN_TOOM3_SQR_N(function) \
534: SPEED_ROUTINE_MPN_SQR_TSPACE (function (wp, s->xp, s->size, tspace), \
535: MPN_TOOM3_SQR_N_TSIZE (s->size))
536:
537:
538: #define SPEED_ROUTINE_MPN_MOD_CALL(call) \
539: { \
540: unsigned i; \
541: \
542: SPEED_RESTRICT_COND (s->size >= 0); \
543: \
544: speed_operand_src (s, s->xp, s->size); \
545: speed_cache_fill (s); \
546: \
547: speed_starttime (); \
548: i = s->reps; \
549: do \
550: call; \
551: while (--i != 0); \
552: return speed_endtime (); \
553: }
554:
555: #define SPEED_ROUTINE_MPN_MOD_1(function) \
556: SPEED_ROUTINE_MPN_MOD_CALL ((*function) (s->xp, s->size, s->r))
557:
558: #define SPEED_ROUTINE_MPN_MOD_1C(function) \
559: SPEED_ROUTINE_MPN_MOD_CALL ((*function) (s->xp, s->size, s->r, 0))
560:
561:
562: /* A division of 2*s->size by s->size limbs */
563:
564: #define SPEED_ROUTINE_MPN_BZ_DIVREM_CALL(call) \
565: { \
566: unsigned i; \
567: mp_ptr a, d, q, r; \
568: double t; \
569: TMP_DECL (marker); \
570: \
571: SPEED_RESTRICT_COND (s->size >= 1); \
572: \
573: TMP_MARK (marker); \
574: a = SPEED_TMP_ALLOC_LIMBS (2*s->size, s->align_xp); \
575: d = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_yp); \
576: q = SPEED_TMP_ALLOC_LIMBS (s->size+1, s->align_wp); \
577: r = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp2); \
578: \
579: MPN_COPY (a, s->xp, s->size); \
580: MPN_COPY (a+s->size, s->xp, s->size); \
581: \
582: MPN_COPY (d, s->yp, s->size); \
583: \
584: /* normalize the data */ \
585: d[s->size-1] |= MP_LIMB_T_HIGHBIT; \
586: a[2*s->size-1] = d[s->size-1] - 1; \
587: \
588: speed_operand_src (s, a, 2*s->size); \
589: speed_operand_src (s, d, s->size); \
590: speed_operand_dst (s, q, s->size+1); \
591: speed_operand_dst (s, r, s->size); \
592: speed_cache_fill (s); \
593: \
594: speed_starttime (); \
595: i = s->reps; \
596: do \
597: call; \
598: while (--i != 0); \
599: t = speed_endtime (); \
600: \
601: TMP_FREE (marker); \
602: return t; \
603: }
604:
605: #define SPEED_ROUTINE_MPN_BZ_DIVREM_N(function) \
606: SPEED_ROUTINE_MPN_BZ_DIVREM_CALL((*function) (q, a, d, s->size))
607:
608: #define SPEED_ROUTINE_MPN_BZ_DIVREM_SB(function) \
609: SPEED_ROUTINE_MPN_BZ_DIVREM_CALL \
610: ((*function) (q, a, 2*s->size, d, s->size))
611:
612: #define SPEED_ROUTINE_MPN_BZ_TDIV_QR(function) \
613: SPEED_ROUTINE_MPN_BZ_DIVREM_CALL \
614: ((*function) (q, r, 0, a, 2*s->size, d, s->size))
615:
616:
617: #define SPEED_ROUTINE_MPN_POPCOUNT(function) \
618: { \
619: unsigned i; \
620: \
621: SPEED_RESTRICT_COND (s->size >= 1); \
622: \
623: speed_operand_src (s, s->xp, s->size); \
624: speed_cache_fill (s); \
625: \
626: speed_starttime (); \
627: i = s->reps; \
628: do \
629: function (s->xp, s->size); \
630: while (--i != 0); \
631: return speed_endtime (); \
632: }
633:
634: #define SPEED_ROUTINE_MPN_HAMDIST(function) \
635: { \
636: unsigned i; \
637: \
638: SPEED_RESTRICT_COND (s->size >= 1); \
639: \
640: speed_operand_src (s, s->xp, s->size); \
641: speed_operand_src (s, s->yp, s->size); \
642: speed_cache_fill (s); \
643: \
644: speed_starttime (); \
645: i = s->reps; \
646: do \
647: function (s->xp, s->yp, s->size); \
648: while (--i != 0); \
649: return speed_endtime (); \
650: }
651:
652:
653: /* For mpz_fib_ui, mpz_fac_ui, etc */
654:
655: #define SPEED_ROUTINE_MPZ_UI(function) \
656: { \
657: mpz_t z; \
658: unsigned i; \
659: double t; \
660: \
661: SPEED_RESTRICT_COND (s->size >= 0); \
662: \
663: mpz_init (z); \
664: \
665: speed_starttime (); \
666: i = s->reps; \
667: do \
668: function (z, s->size); \
669: while (--i != 0); \
670: t = speed_endtime (); \
671: \
672: mpz_clear (z); \
673: return t; \
674: }
675:
676:
677: /* Calculate 2^(m-1) mod m for random odd m of s->size limbs. Having m odd
678: allows redc to be used. Actually the exponent (m-1) is cut down to at
679: most 6 limbs so the calculation doesn't take too long. */
680: #define SPEED_ROUTINE_MPZ_POWM(function) \
681: { \
682: mpz_t r, b, e, m; \
683: unsigned i; \
684: double t; \
685: \
686: SPEED_RESTRICT_COND (s->size >= 1); \
687: \
688: mpz_init (r); \
689: mpz_init_set_ui (b, 2); \
690: \
691: /* force m to odd */ \
692: mpz_init (m); \
693: mpz_set_n (m, s->xp, s->size); \
694: PTR(m)[0] |= 1; \
695: \
696: mpz_init_set (e, m); \
697: mpz_sub_ui (e, e, 1); \
698: SIZ(e) = MIN (SIZ(e), 6); \
699: \
700: speed_starttime (); \
701: i = s->reps; \
702: do \
703: function (r, b, e, m); \
704: while (--i != 0); \
705: t = speed_endtime (); \
706: \
707: mpz_clear (r); \
708: mpz_clear (b); \
709: mpz_clear (e); \
710: mpz_clear (m); \
711: return t; \
712: }
713:
714:
715: #define SPEED_ROUTINE_MPN_ADDSUB_CALL(call) \
716: { \
717: mp_ptr wp, wp2, xp, yp; \
718: unsigned i; \
719: double t; \
720: TMP_DECL (marker); \
721: \
722: SPEED_RESTRICT_COND (s->size >= 0); \
723: \
724: TMP_MARK (marker); \
725: wp = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp); \
726: wp2 = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp2); \
727: xp = s->xp; \
728: yp = s->yp; \
729: \
730: switch (s->r) { \
731: case 0: break; \
732: case 1: xp = wp; break; \
733: case 2: yp = wp2; break; \
734: case 3: xp = wp; yp = wp2; break; \
735: case 4: xp = wp2; yp = wp; break; \
736: default: \
737: fprintf (stderr, "Unrecognised r=%ld in addsub measuring\n", s->r); \
738: abort (); \
739: } \
740: if (xp != s->xp) MPN_COPY (xp, s->xp, s->size); \
741: if (yp != s->yp) MPN_COPY (yp, s->yp, s->size); \
742: \
743: speed_operand_src (s, xp, s->size); \
744: speed_operand_src (s, yp, s->size); \
745: speed_operand_dst (s, wp, s->size); \
746: speed_operand_dst (s, wp2, s->size); \
747: speed_cache_fill (s); \
748: \
749: speed_starttime (); \
750: i = s->reps; \
751: do \
752: call; \
753: while (--i != 0); \
754: t = speed_endtime (); \
755: \
756: TMP_FREE (marker); \
757: return t; \
758: }
759:
760: #define SPEED_ROUTINE_MPN_ADDSUB_N(function) \
761: SPEED_ROUTINE_MPN_ADDSUB_CALL \
762: (function (wp, wp2, xp, yp, s->size));
763:
764: #define SPEED_ROUTINE_MPN_ADDSUB_NC(function) \
765: SPEED_ROUTINE_MPN_ADDSUB_CALL \
766: (function (wp, wp2, xp, yp, s->size, 0));
767:
768:
769: #define SPEED_ROUTINE_MPN_GCD_1xN(function) \
770: { \
771: unsigned i; \
772: double t; \
773: TMP_DECL (marker); \
774: \
775: SPEED_RESTRICT_COND (s->size >= 1); \
776: SPEED_RESTRICT_COND (s->r != 0); \
777: \
778: TMP_MARK (marker); \
779: \
780: speed_operand_src (s, s->xp, s->size); \
781: speed_cache_fill (s); \
782: \
783: speed_starttime (); \
784: i = s->reps; \
785: do \
786: function (s->xp, s->size, s->r); \
787: while (--i != 0); \
788: t = speed_endtime (); \
789: \
790: TMP_FREE (marker); \
791: return t; \
792: }
793:
794:
795: /* SPEED_BLOCK_SIZE many one GCDs of s->size bits each. */
796:
797: #define SPEED_ROUTINE_MPN_GCD_1_CALL(setup, call) \
798: { \
799: unsigned i, j; \
800: mp_ptr px, py; \
801: mp_limb_t x_mask, y_mask; \
802: double t; \
803: TMP_DECL (marker); \
804: \
805: SPEED_RESTRICT_COND (s->size >= 1); \
806: SPEED_RESTRICT_COND (s->size <= mp_bits_per_limb); \
807: \
808: TMP_MARK (marker); \
809: px = SPEED_TMP_ALLOC_LIMBS (SPEED_BLOCK_SIZE, s->align_xp); \
810: py = SPEED_TMP_ALLOC_LIMBS (SPEED_BLOCK_SIZE, s->align_yp); \
811: MPN_COPY (px, s->xp_block, SPEED_BLOCK_SIZE); \
812: MPN_COPY (py, s->yp_block, SPEED_BLOCK_SIZE); \
813: \
814: x_mask = MP_LIMB_T_LOWBITMASK (s->size); \
815: y_mask = MP_LIMB_T_LOWBITMASK (s->r != 0 ? s->r : s->size); \
816: for (i = 0; i < SPEED_BLOCK_SIZE; i++) \
817: { \
818: px[i] &= x_mask; px[i] += (px[i] == 0); \
819: py[i] &= y_mask; py[i] += (py[i] == 0); \
820: setup; \
821: } \
822: \
823: speed_operand_src (s, px, SPEED_BLOCK_SIZE); \
824: speed_operand_src (s, py, SPEED_BLOCK_SIZE); \
825: speed_cache_fill (s); \
826: \
827: speed_starttime (); \
828: i = s->reps; \
829: do \
830: { \
831: j = SPEED_BLOCK_SIZE; \
832: do \
833: { \
834: call; \
835: } \
836: while (--j != 0); \
837: } \
838: while (--i != 0); \
839: t = speed_endtime (); \
840: \
841: TMP_FREE (marker); \
842: \
843: s->time_divisor = SPEED_BLOCK_SIZE; \
844: return t; \
845: }
846:
847: #define SPEED_ROUTINE_MPN_GCD_1(function) \
848: SPEED_ROUTINE_MPN_GCD_1_CALL( , function (&px[j-1], 1, py[j-1]))
849:
850: #define SPEED_ROUTINE_MPN_JACBASE(function) \
851: SPEED_ROUTINE_MPN_GCD_1_CALL \
852: ({ \
853: px[i] %= py[i]; \
854: px[i] |= 1; \
855: py[i] |= 1; \
856: if (py[i]==1) py[i]=3; \
857: }, \
858: function (px[j-1], py[j-1], 0))
859:
860:
861: /* Run some GCDs of s->size limbs each. The number of different data values
862: is decreased as s->size**2, since GCD is a quadratic algorithm.
863: SPEED_ROUTINE_MPN_GCD runs more times than SPEED_ROUTINE_MPN_GCDEXT
864: though, because the plain gcd is about twice as fast as gcdext. */
865:
866: #define SPEED_ROUTINE_MPN_GCD_CALL(datafactor, call) \
867: { \
868: unsigned i; \
869: mp_size_t j, pieces, psize; \
870: mp_ptr wp, wp2, xtmp, ytmp, px, py; \
871: double t; \
872: TMP_DECL (marker); \
873: \
874: SPEED_RESTRICT_COND (s->size >= 1); \
875: \
876: TMP_MARK (marker); \
877: xtmp = SPEED_TMP_ALLOC_LIMBS (s->size+1, s->align_xp); \
878: ytmp = SPEED_TMP_ALLOC_LIMBS (s->size+1, s->align_yp); \
879: wp = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp); \
880: wp2 = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp2); \
881: \
882: pieces = SPEED_BLOCK_SIZE * datafactor / s->size / s->size; \
883: pieces = MAX (pieces, 1); \
884: pieces = MIN (pieces, SPEED_BLOCK_SIZE / s->size); \
885: \
886: psize = pieces * s->size; \
887: px = TMP_ALLOC_LIMBS (psize); \
888: py = TMP_ALLOC_LIMBS (psize); \
889: MPN_COPY (px, pieces==1 ? s->xp : s->xp_block, psize); \
890: MPN_COPY (py, pieces==1 ? s->yp : s->yp_block, psize); \
891: \
892: /* y must be odd, x must have at least as many bits as y */ \
893: for (j = 0; j < pieces; j++) \
894: { \
895: mp_ptr x = px+j*s->size; \
896: mp_ptr y = py+j*s->size; \
897: y[0] |= 1; \
898: if (x[s->size-1] == 0) x[s->size-1] = 1; \
899: if (y[s->size-1] == 0) y[s->size-1] = 1; \
900: x[s->size-1] = MAX (x[s->size-1], y[s->size-1]); \
901: } \
902: \
903: speed_operand_src (s, px, psize); \
904: speed_operand_src (s, py, psize); \
905: speed_operand_dst (s, xtmp, s->size); \
906: speed_operand_dst (s, ytmp, s->size); \
907: speed_operand_dst (s, wp, s->size); \
908: speed_cache_fill (s); \
909: \
910: speed_starttime (); \
911: i = s->reps; \
912: do \
913: { \
914: j = pieces; \
915: do \
916: { \
917: MPN_COPY (xtmp, px+(j-1)*s->size, s->size); \
918: MPN_COPY (ytmp, py+(j-1)*s->size, s->size); \
919: call; \
920: } \
921: while (--j != 0); \
922: } \
923: while (--i != 0); \
924: t = speed_endtime (); \
925: \
926: TMP_FREE (marker); \
927: \
928: s->time_divisor = pieces; \
929: return t; \
930: }
931:
932: #define SPEED_ROUTINE_MPN_GCD(function) \
933: SPEED_ROUTINE_MPN_GCD_CALL (8, function (wp, xtmp, s->size, ytmp, s->size))
934:
935: #define SPEED_ROUTINE_MPN_GCDEXT(function) \
936: SPEED_ROUTINE_MPN_GCD_CALL \
937: (4, { mp_size_t wp2size; \
938: function (wp, wp2, &wp2size, xtmp, s->size, ytmp, s->size); })
939:
940:
941: #define SPEED_ROUTINE_MPN_DIVREM_2(function) \
942: { \
943: mp_ptr wp, xp; \
944: mp_limb_t yp[2]; \
945: unsigned i; \
946: double t; \
947: TMP_DECL (marker); \
948: \
949: SPEED_RESTRICT_COND (s->size >= 1); \
950: \
951: TMP_MARK (marker); \
952: xp = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_xp); \
953: wp = SPEED_TMP_ALLOC_LIMBS (s->size, s->align_wp); \
954: \
955: /* source is destroyed */ \
956: MPN_COPY (xp, s->xp, s->size); \
957: \
958: /* divisor must be normalized */ \
959: MPN_COPY (yp, s->yp_block, 2); \
960: yp[1] |= MP_LIMB_T_HIGHBIT; \
961: \
962: speed_operand_src (s, xp, s->size); \
963: speed_operand_src (s, yp, 2); \
964: speed_operand_dst (s, wp, s->size); \
965: speed_cache_fill (s); \
966: \
967: speed_starttime (); \
968: i = s->reps; \
969: do \
970: function (wp, 0, xp, s->size, yp); \
971: while (--i != 0); \
972: t = speed_endtime (); \
973: \
974: TMP_FREE (marker); \
975: return t; \
976: }
977:
978:
979: #define SPEED_ROUTINE_MODLIMB_INVERT(function) \
980: { \
981: unsigned i, j; \
982: mp_ptr xp; \
983: mp_limb_t n = 1; \
984: double t; \
985: \
986: xp = s->xp_block-1; \
987: \
988: speed_operand_src (s, s->xp_block, SPEED_BLOCK_SIZE); \
989: speed_cache_fill (s); \
990: \
991: speed_starttime (); \
992: i = s->reps; \
993: do \
994: { \
995: j = SPEED_BLOCK_SIZE; \
996: do \
997: { \
998: /* randomized but successively dependent */ \
999: n += (xp[j] << 1); \
1000: \
1001: function (n, n); \
1002: } \
1003: while (--j != 0); \
1004: } \
1005: while (--i != 0); \
1006: t = speed_endtime (); \
1007: \
1008: /* make sure the compiler won't optimize away n */ \
1009: noop_1 (n); \
1010: \
1011: s->time_divisor = SPEED_BLOCK_SIZE; \
1012: return t; \
1013: }
1014:
1015: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>