common.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:57k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. /* Shared speed subroutines.
  2. Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010
  3. Free Software Foundation, Inc.
  4. This file is part of the GNU MP Library.
  5. The GNU MP Library is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or (at your
  8. option) any later version.
  9. The GNU MP Library is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  12. License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
  15. #define __GMP_NO_ATTRIBUTE_CONST_PURE
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <math.h>
  19. #include <stdio.h>
  20. #include <stdlib.h> /* for qsort */
  21. #include <string.h>
  22. #include <unistd.h>
  23. #if 0
  24. #include <sys/ioctl.h>
  25. #endif
  26. #include "gmp.h"
  27. #include "gmp-impl.h"
  28. #include "longlong.h"
  29. #include "tests.h"
  30. #include "speed.h"
  31. int   speed_option_addrs = 0;
  32. int   speed_option_verbose = 0;
  33. /* Provide __clz_tab even if it's not required, for the benefit of new code
  34.    being tested with many.pl. */
  35. #ifndef COUNT_LEADING_ZEROS_NEED_CLZ_TAB
  36. #define COUNT_LEADING_ZEROS_NEED_CLZ_TAB
  37. #include "mp_clz_tab.c"
  38. #undef COUNT_LEADING_ZEROS_NEED_CLZ_TAB
  39. #endif
  40. void
  41. pentium_wbinvd(void)
  42. {
  43. #if 0
  44.   {
  45.     static int  fd = -2;
  46.     if (fd == -2)
  47.       {
  48. fd = open ("/dev/wbinvd", O_RDWR);
  49. if (fd == -1)
  50.   perror ("open /dev/wbinvd");
  51.       }
  52.     if (fd != -1)
  53.       ioctl (fd, 0, 0);
  54.   }
  55. #endif
  56. #if 0
  57. #define WBINVDSIZE  1024*1024*2
  58.   {
  59.     static char  *p = NULL;
  60.     int   i, sum;
  61.     if (p == NULL)
  62.       p = malloc (WBINVDSIZE);
  63. #if 0
  64.     for (i = 0; i < WBINVDSIZE; i++)
  65.       p[i] = i & 0xFF;
  66. #endif
  67.     sum = 0;
  68.     for (i = 0; i < WBINVDSIZE; i++)
  69.       sum += p[i];
  70.     mpn_cache_fill_dummy (sum);
  71.   }
  72. #endif
  73. }
  74. int
  75. double_cmp_ptr (const double *p, const double *q)
  76. {
  77.   if (*p > *q)  return 1;
  78.   if (*p < *q)  return -1;
  79.   return 0;
  80. }
  81. /* Measure the speed of a given routine.
  82.    The routine is run with enough repetitions to make it take at least
  83.    speed_precision * speed_unittime.  This aims to minimize the effects of a
  84.    limited accuracy time base and the overhead of the measuring itself.
  85.    Measurements are made looking for 4 results within TOLERANCE of each
  86.    other (or 3 for routines taking longer than 2 seconds).  This aims to get
  87.    an accurate reading even if some runs are bloated by interrupts or task
  88.    switches or whatever.
  89.    The given (*fun)() is expected to run its function "s->reps" many times
  90.    and return the total elapsed time measured using speed_starttime() and
  91.    speed_endtime().  If the function doesn't support the given s->size or
  92.    s->r, -1.0 should be returned.  See the various base routines below.  */
  93. double
  94. speed_measure (double (*fun) __GMP_PROTO ((struct speed_params *s)),
  95.        struct speed_params *s)
  96. {
  97. #define TOLERANCE    1.005  /* 0.5% */
  98.   const int max_zeros = 10;
  99.   struct speed_params  s_dummy;
  100.   int     i, j, e;
  101.   double  t[30];
  102.   double  t_unsorted[30];
  103.   double  reps_d;
  104.   int     zeros = 0;
  105.   /* Use dummy parameters if caller doesn't provide any.  Only a few special
  106.      "fun"s will cope with this, speed_noop() is one.  */
  107.   if (s == NULL)
  108.     {
  109.       memset (&s_dummy, '', sizeof (s_dummy));
  110.       s = &s_dummy;
  111.     }
  112.   s->reps = 1;
  113.   s->time_divisor = 1.0;
  114.   for (i = 0; i < numberof (t); i++)
  115.     {
  116.       for (;;)
  117. {
  118.   s->src_num = 0;
  119.   s->dst_num = 0;
  120.   t[i] = (*fun) (s);
  121.   if (speed_option_verbose >= 3)
  122.     gmp_printf("size=%ld reps=%u r=%Md attempt=%d  %.9fn",
  123.        (long) s->size, s->reps, s->r, i, t[i]);
  124.   if (t[i] == 0.0)
  125.     {
  126.       zeros++;
  127.       if (zeros > max_zeros)
  128. {
  129.   fprintf (stderr, "Fatal error: too many (%d) failed measurements (0.0)n", zeros);
  130.   abort ();
  131. }
  132.       continue;
  133.     }
  134.   if (t[i] == -1.0)
  135.     return -1.0;
  136.   if (t[i] >= speed_unittime * speed_precision)
  137.     break;
  138.   /* go to a value of reps to make t[i] >= precision */
  139.   reps_d = ceil (1.1 * s->reps
  140.  * speed_unittime * speed_precision
  141.  / MAX (t[i], speed_unittime));
  142.   if (reps_d > 2e9 || reps_d < 1.0)
  143.     {
  144.       fprintf (stderr, "Fatal error: new reps bad: %.2fn", reps_d);
  145.       fprintf (stderr, "  (old reps %u, unittime %.4g, precision %d, t[i] %.4g)n",
  146.        s->reps, speed_unittime, speed_precision, t[i]);
  147.       abort ();
  148.     }
  149.   s->reps = (unsigned) reps_d;
  150. }
  151.       t[i] /= s->reps;
  152.       t_unsorted[i] = t[i];
  153.       if (speed_precision == 0)
  154. return t[i];
  155.       /* require 3 values within TOLERANCE when >= 2 secs, 4 when below */
  156.       if (t[0] >= 2.0)
  157. e = 3;
  158.       else
  159. e = 4;
  160.       /* Look for e many t[]'s within TOLERANCE of each other to consider a
  161.  valid measurement.  Return smallest among them.  */
  162.       if (i >= e)
  163. {
  164.   qsort (t, i+1, sizeof(t[0]), (qsort_function_t) double_cmp_ptr);
  165.   for (j = e-1; j < i; j++)
  166.     if (t[j] <= t[j-e+1] * TOLERANCE)
  167.       return t[j-e+1] / s->time_divisor;
  168. }
  169.     }
  170.   fprintf (stderr, "speed_measure() could not get %d results within %.1f%%n",
  171.    e, (TOLERANCE-1.0)*100.0);
  172.   fprintf (stderr, "    unsorted         sortedn");
  173.   fprintf (stderr, "  %.12f    %.12f    is about 0.5%%n",
  174.    t_unsorted[0]*(TOLERANCE-1.0), t[0]*(TOLERANCE-1.0));
  175.   for (i = 0; i < numberof (t); i++)
  176.     fprintf (stderr, "  %.09f       %.09fn", t_unsorted[i], t[i]);
  177.   return -1.0;
  178. }
  179. /* Read all of ptr,size to get it into the CPU memory cache.
  180.    A call to mpn_cache_fill_dummy() is used to make sure the compiler
  181.    doesn't optimize away the whole loop.  Using "volatile mp_limb_t sum"
  182.    would work too, but the function call means we don't rely on every
  183.    compiler actually implementing volatile properly.
  184.    mpn_cache_fill_dummy() is in a separate source file to stop gcc thinking
  185.    it can inline it.  */
  186. void
  187. mpn_cache_fill (mp_srcptr ptr, mp_size_t size)
  188. {
  189.   mp_limb_t  sum = 0;
  190.   mp_size_t  i;
  191.   for (i = 0; i < size; i++)
  192.     sum += ptr[i];
  193.   mpn_cache_fill_dummy(sum);
  194. }
  195. void
  196. mpn_cache_fill_write (mp_ptr ptr, mp_size_t size)
  197. {
  198.   mpn_cache_fill (ptr, size);
  199. #if 0
  200.   mpn_random (ptr, size);
  201. #endif
  202. #if 0
  203.   mp_size_t  i;
  204.   for (i = 0; i < size; i++)
  205.     ptr[i] = i;
  206. #endif
  207. }
  208. void
  209. speed_operand_src (struct speed_params *s, mp_ptr ptr, mp_size_t size)
  210. {
  211.   if (s->src_num >= numberof (s->src))
  212.     {
  213.       fprintf (stderr, "speed_operand_src: no room left in s->src[]n");
  214.       abort ();
  215.     }
  216.   s->src[s->src_num].ptr = ptr;
  217.   s->src[s->src_num].size = size;
  218.   s->src_num++;
  219. }
  220. void
  221. speed_operand_dst (struct speed_params *s, mp_ptr ptr, mp_size_t size)
  222. {
  223.   if (s->dst_num >= numberof (s->dst))
  224.     {
  225.       fprintf (stderr, "speed_operand_dst: no room left in s->dst[]n");
  226.       abort ();
  227.     }
  228.   s->dst[s->dst_num].ptr = ptr;
  229.   s->dst[s->dst_num].size = size;
  230.   s->dst_num++;
  231. }
  232. void
  233. speed_cache_fill (struct speed_params *s)
  234. {
  235.   static struct speed_params  prev;
  236.   int  i;
  237.   /* FIXME: need a better way to get the format string for a pointer */
  238.   if (speed_option_addrs)
  239.     {
  240.       int  different;
  241.       different = (s->dst_num != prev.dst_num || s->src_num != prev.src_num);
  242.       for (i = 0; i < s->dst_num; i++)
  243. different |= (s->dst[i].ptr != prev.dst[i].ptr);
  244.       for (i = 0; i < s->src_num; i++)
  245. different |= (s->src[i].ptr != prev.src[i].ptr);
  246.       if (different)
  247. {
  248.   if (s->dst_num != 0)
  249.     {
  250.       printf ("dst");
  251.       for (i = 0; i < s->dst_num; i++)
  252. printf (" %08lX", (unsigned long) s->dst[i].ptr);
  253.       printf (" ");
  254.     }
  255.   if (s->src_num != 0)
  256.     {
  257.       printf ("src");
  258.       for (i = 0; i < s->src_num; i++)
  259. printf (" %08lX", (unsigned long) s->src[i].ptr);
  260.       printf (" ");
  261.     }
  262.   printf ("  (cf sp approx %08lX)n", (unsigned long) &different);
  263. }
  264.       memcpy (&prev, s, sizeof(prev));
  265.     }
  266.   switch (s->cache) {
  267.   case 0:
  268.     for (i = 0; i < s->dst_num; i++)
  269.       mpn_cache_fill_write (s->dst[i].ptr, s->dst[i].size);
  270.     for (i = 0; i < s->src_num; i++)
  271.       mpn_cache_fill (s->src[i].ptr, s->src[i].size);
  272.     break;
  273.   case 1:
  274.     pentium_wbinvd();
  275.     break;
  276.   }
  277. }
  278. /* Miscellanous options accepted by tune and speed programs under -o. */
  279. void
  280. speed_option_set (const char *s)
  281. {
  282.   int  n;
  283.   if (strcmp (s, "addrs") == 0)
  284.     {
  285.       speed_option_addrs = 1;
  286.     }
  287.   else if (strcmp (s, "verbose") == 0)
  288.     {
  289.       speed_option_verbose++;
  290.     }
  291.   else if (sscanf (s, "verbose=%d", &n) == 1)
  292.     {
  293.       speed_option_verbose = n;
  294.     }
  295.   else
  296.     {
  297.       printf ("Unrecognised -o option: %sn", s);
  298.       exit (1);
  299.     }
  300. }
  301. /* The following are basic speed running routines for various gmp functions.
  302.    Many are very similar and use speed.h macros.
  303.    Each routine allocates it's own destination space for the result of the
  304.    function, because only it can know what the function needs.
  305.    speed_starttime() and speed_endtime() are put tight around the code to be
  306.    measured.  Any setups are done outside the timed portion.
  307.    Each routine is responsible for its own cache priming.
  308.    speed_cache_fill() is a good way to do this, see examples in speed.h.
  309.    One cache priming possibility, for CPUs with write-allocate cache, and
  310.    functions that don't take too long, is to do one dummy call before timing
  311.    so as to cache everything that gets used.  But speed_measure() runs a
  312.    routine at least twice and will take the smaller time, so this might not
  313.    be necessary.
  314.    Data alignment will be important, for source, destination and temporary
  315.    workspace.  A routine can align its destination and workspace.  Programs
  316.    using the routines will ensure s->xp and s->yp are aligned.  Aligning
  317.    onto a CACHE_LINE_SIZE boundary is suggested.  s->align_wp and
  318.    s->align_wp2 should be respected where it makes sense to do so.
  319.    SPEED_TMP_ALLOC_LIMBS is a good way to do this.
  320.    A loop of the following form can be expected to turn into good assembler
  321.    code on most CPUs, thereby minimizing overhead in the measurement.  It
  322.    can always be assumed s->reps >= 1.
  323.   i = s->reps
  324.   do
  325.     foo();
  326.   while (--i != 0);
  327.    Additional parameters might be added to "struct speed_params" in the
  328.    future.  Routines should ignore anything they don't use.
  329.    s->size can be used creatively, and s->xp and s->yp can be ignored.  For
  330.    example, speed_mpz_fac_ui() uses s->size as n for the factorial.  s->r is
  331.    just a user-supplied parameter.  speed_mpn_lshift() uses it as a shift,
  332.    speed_mpn_mul_1() uses it as a multiplier.  */
  333. /* MPN_COPY etc can be macros, so the _CALL forms are necessary */
  334. double
  335. speed_MPN_COPY (struct speed_params *s)
  336. {
  337.   SPEED_ROUTINE_MPN_COPY (MPN_COPY);
  338. }
  339. double
  340. speed_MPN_COPY_INCR (struct speed_params *s)
  341. {
  342.   SPEED_ROUTINE_MPN_COPY (MPN_COPY_INCR);
  343. }
  344. double
  345. speed_MPN_COPY_DECR (struct speed_params *s)
  346. {
  347.   SPEED_ROUTINE_MPN_COPY (MPN_COPY_DECR);
  348. }
  349. #if HAVE_NATIVE_mpn_copyi
  350. double
  351. speed_mpn_copyi (struct speed_params *s)
  352. {
  353.   SPEED_ROUTINE_MPN_COPY (mpn_copyi);
  354. }
  355. #endif
  356. #if HAVE_NATIVE_mpn_copyd
  357. double
  358. speed_mpn_copyd (struct speed_params *s)
  359. {
  360.   SPEED_ROUTINE_MPN_COPY (mpn_copyd);
  361. }
  362. #endif
  363. double
  364. speed_memcpy (struct speed_params *s)
  365. {
  366.   SPEED_ROUTINE_MPN_COPY_BYTES (memcpy);
  367. }
  368. double
  369. speed_mpn_com (struct speed_params *s)
  370. {
  371.   SPEED_ROUTINE_MPN_COPY (mpn_com);
  372. }
  373. double
  374. speed_mpn_addmul_1 (struct speed_params *s)
  375. {
  376.   SPEED_ROUTINE_MPN_UNARY_1 (mpn_addmul_1);
  377. }
  378. double
  379. speed_mpn_submul_1 (struct speed_params *s)
  380. {
  381.   SPEED_ROUTINE_MPN_UNARY_1 (mpn_submul_1);
  382. }
  383. #if HAVE_NATIVE_mpn_addmul_2
  384. double
  385. speed_mpn_addmul_2 (struct speed_params *s)
  386. {
  387.   SPEED_ROUTINE_MPN_UNARY_2 (mpn_addmul_2);
  388. }
  389. #endif
  390. #if HAVE_NATIVE_mpn_addmul_3
  391. double
  392. speed_mpn_addmul_3 (struct speed_params *s)
  393. {
  394.   SPEED_ROUTINE_MPN_UNARY_3 (mpn_addmul_3);
  395. }
  396. #endif
  397. #if HAVE_NATIVE_mpn_addmul_4
  398. double
  399. speed_mpn_addmul_4 (struct speed_params *s)
  400. {
  401.   SPEED_ROUTINE_MPN_UNARY_4 (mpn_addmul_4);
  402. }
  403. #endif
  404. #if HAVE_NATIVE_mpn_addmul_5
  405. double
  406. speed_mpn_addmul_5 (struct speed_params *s)
  407. {
  408.   SPEED_ROUTINE_MPN_UNARY_5 (mpn_addmul_5);
  409. }
  410. #endif
  411. #if HAVE_NATIVE_mpn_addmul_6
  412. double
  413. speed_mpn_addmul_6 (struct speed_params *s)
  414. {
  415.   SPEED_ROUTINE_MPN_UNARY_6 (mpn_addmul_6);
  416. }
  417. #endif
  418. #if HAVE_NATIVE_mpn_addmul_7
  419. double
  420. speed_mpn_addmul_7 (struct speed_params *s)
  421. {
  422.   SPEED_ROUTINE_MPN_UNARY_7 (mpn_addmul_7);
  423. }
  424. #endif
  425. #if HAVE_NATIVE_mpn_addmul_8
  426. double
  427. speed_mpn_addmul_8 (struct speed_params *s)
  428. {
  429.   SPEED_ROUTINE_MPN_UNARY_8 (mpn_addmul_8);
  430. }
  431. #endif
  432. double
  433. speed_mpn_mul_1 (struct speed_params *s)
  434. {
  435.   SPEED_ROUTINE_MPN_UNARY_1 (mpn_mul_1);
  436. }
  437. double
  438. speed_mpn_mul_1_inplace (struct speed_params *s)
  439. {
  440.   SPEED_ROUTINE_MPN_UNARY_1_INPLACE (mpn_mul_1);
  441. }
  442. #if HAVE_NATIVE_mpn_mul_2
  443. double
  444. speed_mpn_mul_2 (struct speed_params *s)
  445. {
  446.   SPEED_ROUTINE_MPN_UNARY_2 (mpn_mul_2);
  447. }
  448. #endif
  449. #if HAVE_NATIVE_mpn_mul_3
  450. double
  451. speed_mpn_mul_3 (struct speed_params *s)
  452. {
  453.   SPEED_ROUTINE_MPN_UNARY_3 (mpn_mul_3);
  454. }
  455. #endif
  456. #if HAVE_NATIVE_mpn_mul_4
  457. double
  458. speed_mpn_mul_4 (struct speed_params *s)
  459. {
  460.   SPEED_ROUTINE_MPN_UNARY_4 (mpn_mul_4);
  461. }
  462. #endif
  463. double
  464. speed_mpn_lshift (struct speed_params *s)
  465. {
  466.   SPEED_ROUTINE_MPN_UNARY_1 (mpn_lshift);
  467. }
  468. double
  469. speed_mpn_lshiftc (struct speed_params *s)
  470. {
  471.   SPEED_ROUTINE_MPN_UNARY_1 (mpn_lshiftc);
  472. }
  473. double
  474. speed_mpn_rshift (struct speed_params *s)
  475. {
  476.   SPEED_ROUTINE_MPN_UNARY_1 (mpn_rshift);
  477. }
  478. /* The carry-in variants (if available) are good for measuring because they
  479.    won't skip a division if high<divisor.  Alternately, use -1 as a divisor
  480.    with the plain _1 forms. */
  481. double
  482. speed_mpn_divrem_1 (struct speed_params *s)
  483. {
  484.   SPEED_ROUTINE_MPN_DIVREM_1 (mpn_divrem_1);
  485. }
  486. double
  487. speed_mpn_divrem_1f (struct speed_params *s)
  488. {
  489.   SPEED_ROUTINE_MPN_DIVREM_1F (mpn_divrem_1);
  490. }
  491. #if HAVE_NATIVE_mpn_divrem_1c
  492. double
  493. speed_mpn_divrem_1c (struct speed_params *s)
  494. {
  495.   SPEED_ROUTINE_MPN_DIVREM_1C (mpn_divrem_1c);
  496. }
  497. double
  498. speed_mpn_divrem_1cf (struct speed_params *s)
  499. {
  500.   SPEED_ROUTINE_MPN_DIVREM_1CF (mpn_divrem_1c);
  501. }
  502. #endif
  503. double
  504. speed_mpn_divrem_1_div (struct speed_params *s)
  505. {
  506.   SPEED_ROUTINE_MPN_DIVREM_1 (mpn_divrem_1_div);
  507. }
  508. double
  509. speed_mpn_divrem_1f_div (struct speed_params *s)
  510. {
  511.   SPEED_ROUTINE_MPN_DIVREM_1F (mpn_divrem_1_div);
  512. }
  513. double
  514. speed_mpn_divrem_1_inv (struct speed_params *s)
  515. {
  516.   SPEED_ROUTINE_MPN_DIVREM_1 (mpn_divrem_1_inv);
  517. }
  518. double
  519. speed_mpn_divrem_1f_inv (struct speed_params *s)
  520. {
  521.   SPEED_ROUTINE_MPN_DIVREM_1F (mpn_divrem_1_inv);
  522. }
  523. double
  524. speed_mpn_mod_1_div (struct speed_params *s)
  525. {
  526.   SPEED_ROUTINE_MPN_MOD_1 (mpn_mod_1_div);
  527. }
  528. double
  529. speed_mpn_mod_1_inv (struct speed_params *s)
  530. {
  531.   SPEED_ROUTINE_MPN_MOD_1 (mpn_mod_1_inv);
  532. }
  533. double
  534. speed_mpn_preinv_divrem_1 (struct speed_params *s)
  535. {
  536.   SPEED_ROUTINE_MPN_PREINV_DIVREM_1 (mpn_preinv_divrem_1);
  537. }
  538. double
  539. speed_mpn_preinv_divrem_1f (struct speed_params *s)
  540. {
  541.   SPEED_ROUTINE_MPN_PREINV_DIVREM_1F (mpn_preinv_divrem_1);
  542. }
  543. #if GMP_NUMB_BITS % 4 == 0
  544. double
  545. speed_mpn_mod_34lsub1 (struct speed_params *s)
  546. {
  547.   SPEED_ROUTINE_MPN_MOD_34LSUB1 (mpn_mod_34lsub1);
  548. }
  549. #endif
  550. double
  551. speed_mpn_divrem_2 (struct speed_params *s)
  552. {
  553.   SPEED_ROUTINE_MPN_DIVREM_2 (mpn_divrem_2);
  554. }
  555. double
  556. speed_mpn_divrem_2_div (struct speed_params *s)
  557. {
  558.   SPEED_ROUTINE_MPN_DIVREM_2 (mpn_divrem_2_div);
  559. }
  560. double
  561. speed_mpn_divrem_2_inv (struct speed_params *s)
  562. {
  563.   SPEED_ROUTINE_MPN_DIVREM_2 (mpn_divrem_2_inv);
  564. }
  565. double
  566. speed_mpn_mod_1 (struct speed_params *s)
  567. {
  568.   SPEED_ROUTINE_MPN_MOD_1 (mpn_mod_1);
  569. }
  570. #if HAVE_NATIVE_mpn_mod_1c
  571. double
  572. speed_mpn_mod_1c (struct speed_params *s)
  573. {
  574.   SPEED_ROUTINE_MPN_MOD_1C (mpn_mod_1c);
  575. }
  576. #endif
  577. double
  578. speed_mpn_preinv_mod_1 (struct speed_params *s)
  579. {
  580.   SPEED_ROUTINE_MPN_PREINV_MOD_1 (mpn_preinv_mod_1);
  581. }
  582. double
  583. speed_mpn_mod_1_1 (struct speed_params *s)
  584. {
  585.   SPEED_ROUTINE_MPN_MOD_1_1 (mpn_mod_1_1p,mpn_mod_1_1p_cps);
  586. }
  587. double
  588. speed_mpn_mod_1_2 (struct speed_params *s)
  589. {
  590.   SPEED_ROUTINE_MPN_MOD_1_N (mpn_mod_1s_2p,mpn_mod_1s_2p_cps,2);
  591. }
  592. double
  593. speed_mpn_mod_1_3 (struct speed_params *s)
  594. {
  595.   SPEED_ROUTINE_MPN_MOD_1_N (mpn_mod_1s_3p,mpn_mod_1s_3p_cps,3);
  596. }
  597. double
  598. speed_mpn_mod_1_4 (struct speed_params *s)
  599. {
  600.   SPEED_ROUTINE_MPN_MOD_1_N (mpn_mod_1s_4p,mpn_mod_1s_4p_cps,4);
  601. }
  602. double
  603. speed_mpn_divexact_1 (struct speed_params *s)
  604. {
  605.   SPEED_ROUTINE_MPN_DIVEXACT_1 (mpn_divexact_1);
  606. }
  607. double
  608. speed_mpn_divexact_by3 (struct speed_params *s)
  609. {
  610.   SPEED_ROUTINE_MPN_COPY (mpn_divexact_by3);
  611. }
  612. double
  613. speed_mpn_bdiv_dbm1c (struct speed_params *s)
  614. {
  615.   SPEED_ROUTINE_MPN_BDIV_DBM1C (mpn_bdiv_dbm1c);
  616. }
  617. double
  618. speed_mpn_bdiv_q_1 (struct speed_params *s)
  619. {
  620.   SPEED_ROUTINE_MPN_BDIV_Q_1 (mpn_bdiv_q_1);
  621. }
  622. double
  623. speed_mpn_pi1_bdiv_q_1 (struct speed_params *s)
  624. {
  625.   SPEED_ROUTINE_MPN_PI1_BDIV_Q_1 (mpn_pi1_bdiv_q_1);
  626. }
  627. #if HAVE_NATIVE_mpn_modexact_1_odd
  628. double
  629. speed_mpn_modexact_1_odd (struct speed_params *s)
  630. {
  631.   SPEED_ROUTINE_MPN_MODEXACT_1_ODD (mpn_modexact_1_odd);
  632. }
  633. #endif
  634. double
  635. speed_mpn_modexact_1c_odd (struct speed_params *s)
  636. {
  637.   SPEED_ROUTINE_MPN_MODEXACT_1C_ODD (mpn_modexact_1c_odd);
  638. }
  639. double
  640. speed_mpz_mod (struct speed_params *s)
  641. {
  642.   SPEED_ROUTINE_MPZ_MOD (mpz_mod);
  643. }
  644. double
  645. speed_mpn_sbpi1_div_qr (struct speed_params *s)
  646. {
  647.   SPEED_ROUTINE_MPN_PI1_DIV (mpn_sbpi1_div_qr, inv.inv32, 2,0);
  648. }
  649. double
  650. speed_mpn_dcpi1_div_qr (struct speed_params *s)
  651. {
  652.   SPEED_ROUTINE_MPN_PI1_DIV (mpn_dcpi1_div_qr, &inv, 6,3);
  653. }
  654. double
  655. speed_mpn_sbpi1_divappr_q (struct speed_params *s)
  656. {
  657.   SPEED_ROUTINE_MPN_PI1_DIV (mpn_sbpi1_divappr_q, inv.inv32, 2,0);
  658. }
  659. double
  660. speed_mpn_dcpi1_divappr_q (struct speed_params *s)
  661. {
  662.   SPEED_ROUTINE_MPN_PI1_DIV (mpn_dcpi1_divappr_q, &inv, 6,3);
  663. }
  664. double
  665. speed_mpn_mu_div_qr (struct speed_params *s)
  666. {
  667.   SPEED_ROUTINE_MPN_MU_DIV_QR (mpn_mu_div_qr, mpn_mu_div_qr_itch);
  668. }
  669. double
  670. speed_mpn_mu_divappr_q (struct speed_params *s)
  671. {
  672.   SPEED_ROUTINE_MPN_MU_DIV_Q (mpn_mu_divappr_q, mpn_mu_divappr_q_itch);
  673. }
  674. double
  675. speed_mpn_mu_div_q (struct speed_params *s)
  676. {
  677.   SPEED_ROUTINE_MPN_MU_DIV_Q (mpn_mu_div_q, mpn_mu_div_q_itch);
  678. }
  679. double
  680. speed_mpn_mupi_div_qr (struct speed_params *s)
  681. {
  682.   SPEED_ROUTINE_MPN_MUPI_DIV_QR (mpn_preinv_mu_div_qr, mpn_mu_div_qr_itch);
  683. }
  684. double
  685. speed_mpn_sbpi1_bdiv_qr (struct speed_params *s)
  686. {
  687.   SPEED_ROUTINE_MPN_PI1_BDIV_QR (mpn_sbpi1_bdiv_qr);
  688. }
  689. double
  690. speed_mpn_dcpi1_bdiv_qr (struct speed_params *s)
  691. {
  692.   SPEED_ROUTINE_MPN_PI1_BDIV_QR (mpn_dcpi1_bdiv_qr);
  693. }
  694. double
  695. speed_mpn_sbpi1_bdiv_q (struct speed_params *s)
  696. {
  697.   SPEED_ROUTINE_MPN_PI1_BDIV_Q (mpn_sbpi1_bdiv_q);
  698. }
  699. double
  700. speed_mpn_dcpi1_bdiv_q (struct speed_params *s)
  701. {
  702.   SPEED_ROUTINE_MPN_PI1_BDIV_Q (mpn_dcpi1_bdiv_q);
  703. }
  704. double
  705. speed_mpn_mu_bdiv_q (struct speed_params *s)
  706. {
  707.   SPEED_ROUTINE_MPN_MU_BDIV_Q (mpn_mu_bdiv_q, mpn_mu_bdiv_q_itch);
  708. }
  709. double
  710. speed_mpn_mu_bdiv_qr (struct speed_params *s)
  711. {
  712.   SPEED_ROUTINE_MPN_MU_BDIV_QR (mpn_mu_bdiv_qr, mpn_mu_bdiv_qr_itch);
  713. }
  714. double
  715. speed_mpn_binvert (struct speed_params *s)
  716. {
  717.   SPEED_ROUTINE_MPN_BINVERT (mpn_binvert, mpn_binvert_itch);
  718. }
  719. double
  720. speed_mpn_invert (struct speed_params *s)
  721. {
  722.   SPEED_ROUTINE_MPN_INVERT (mpn_invert, mpn_invert_itch);
  723. }
  724. double
  725. speed_mpn_invertappr (struct speed_params *s)
  726. {
  727.   SPEED_ROUTINE_MPN_INVERTAPPR (mpn_invertappr, mpn_invertappr_itch);
  728. }
  729. double
  730. speed_mpn_ni_invertappr (struct speed_params *s)
  731. {
  732.   SPEED_ROUTINE_MPN_INVERTAPPR (mpn_ni_invertappr, mpn_invertappr_itch);
  733. }
  734. double
  735. speed_mpn_redc_1 (struct speed_params *s)
  736. {
  737.   SPEED_ROUTINE_REDC_1 (mpn_redc_1);
  738. }
  739. double
  740. speed_mpn_redc_2 (struct speed_params *s)
  741. {
  742.   SPEED_ROUTINE_REDC_2 (mpn_redc_2);
  743. }
  744. double
  745. speed_mpn_redc_n (struct speed_params *s)
  746. {
  747.   SPEED_ROUTINE_REDC_N (mpn_redc_n);
  748. }
  749. double
  750. speed_mpn_popcount (struct speed_params *s)
  751. {
  752.   SPEED_ROUTINE_MPN_POPCOUNT (mpn_popcount);
  753. }
  754. double
  755. speed_mpn_hamdist (struct speed_params *s)
  756. {
  757.   SPEED_ROUTINE_MPN_HAMDIST (mpn_hamdist);
  758. }
  759. double
  760. speed_mpn_add_n (struct speed_params *s)
  761. {
  762.   SPEED_ROUTINE_MPN_BINARY_N (mpn_add_n);
  763. }
  764. double
  765. speed_mpn_sub_n (struct speed_params *s)
  766. {
  767. SPEED_ROUTINE_MPN_BINARY_N (mpn_sub_n);
  768. }
  769. #if HAVE_NATIVE_mpn_add_n_sub_n
  770. double
  771. speed_mpn_add_n_sub_n (struct speed_params *s)
  772. {
  773.   SPEED_ROUTINE_MPN_ADDSUB_N_CALL (mpn_add_n_sub_n (ap, sp, s->xp, s->yp, s->size));
  774. }
  775. #endif
  776. #if HAVE_NATIVE_mpn_addlsh1_n
  777. double
  778. speed_mpn_addlsh1_n (struct speed_params *s)
  779. {
  780.   SPEED_ROUTINE_MPN_BINARY_N (mpn_addlsh1_n);
  781. }
  782. #endif
  783. #if HAVE_NATIVE_mpn_sublsh1_n
  784. double
  785. speed_mpn_sublsh1_n (struct speed_params *s)
  786. {
  787.   SPEED_ROUTINE_MPN_BINARY_N (mpn_sublsh1_n);
  788. }
  789. #endif
  790. #if HAVE_NATIVE_mpn_rsblsh1_n
  791. double
  792. speed_mpn_rsblsh1_n (struct speed_params *s)
  793. {
  794.   SPEED_ROUTINE_MPN_BINARY_N (mpn_rsblsh1_n);
  795. }
  796. #endif
  797. #if HAVE_NATIVE_mpn_addlsh2_n
  798. double
  799. speed_mpn_addlsh2_n (struct speed_params *s)
  800. {
  801.   SPEED_ROUTINE_MPN_BINARY_N (mpn_addlsh2_n);
  802. }
  803. #endif
  804. #if HAVE_NATIVE_mpn_sublsh2_n
  805. double
  806. speed_mpn_sublsh2_n (struct speed_params *s)
  807. {
  808.   SPEED_ROUTINE_MPN_BINARY_N (mpn_sublsh2_n);
  809. }
  810. #endif
  811. #if HAVE_NATIVE_mpn_rsblsh2_n
  812. double
  813. speed_mpn_rsblsh2_n (struct speed_params *s)
  814. {
  815.   SPEED_ROUTINE_MPN_BINARY_N (mpn_rsblsh2_n);
  816. }
  817. #endif
  818. #if HAVE_NATIVE_mpn_rsh1add_n
  819. double
  820. speed_mpn_rsh1add_n (struct speed_params *s)
  821. {
  822.   SPEED_ROUTINE_MPN_BINARY_N (mpn_rsh1add_n);
  823. }
  824. #endif
  825. #if HAVE_NATIVE_mpn_rsh1sub_n
  826. double
  827. speed_mpn_rsh1sub_n (struct speed_params *s)
  828. {
  829.   SPEED_ROUTINE_MPN_BINARY_N (mpn_rsh1sub_n);
  830. }
  831. #endif
  832. /* mpn_and_n etc can be macros and so have to be handled with
  833.    SPEED_ROUTINE_MPN_BINARY_N_CALL forms */
  834. double
  835. speed_mpn_and_n (struct speed_params *s)
  836. {
  837.   SPEED_ROUTINE_MPN_BINARY_N_CALL (mpn_and_n (wp, s->xp, s->yp, s->size));
  838. }
  839. double
  840. speed_mpn_andn_n (struct speed_params *s)
  841. {
  842. SPEED_ROUTINE_MPN_BINARY_N_CALL (mpn_andn_n (wp, s->xp, s->yp, s->size));
  843. }
  844. double
  845. speed_mpn_nand_n (struct speed_params *s)
  846. {
  847.   SPEED_ROUTINE_MPN_BINARY_N_CALL (mpn_nand_n (wp, s->xp, s->yp, s->size));
  848. }
  849. double
  850. speed_mpn_ior_n (struct speed_params *s)
  851. {
  852. SPEED_ROUTINE_MPN_BINARY_N_CALL (mpn_ior_n (wp, s->xp, s->yp, s->size));
  853. }
  854. double
  855. speed_mpn_iorn_n (struct speed_params *s)
  856. {
  857.   SPEED_ROUTINE_MPN_BINARY_N_CALL (mpn_iorn_n (wp, s->xp, s->yp, s->size));
  858. }
  859. double
  860. speed_mpn_nior_n (struct speed_params *s)
  861. {
  862.   SPEED_ROUTINE_MPN_BINARY_N_CALL (mpn_nior_n (wp, s->xp, s->yp, s->size));
  863. }
  864. double
  865. speed_mpn_xor_n (struct speed_params *s)
  866. {
  867.   SPEED_ROUTINE_MPN_BINARY_N_CALL (mpn_xor_n (wp, s->xp, s->yp, s->size));
  868. }
  869. double
  870. speed_mpn_xnor_n (struct speed_params *s)
  871. {
  872.   SPEED_ROUTINE_MPN_BINARY_N_CALL (mpn_xnor_n (wp, s->xp, s->yp, s->size));
  873. }
  874. double
  875. speed_mpn_mul_n (struct speed_params *s)
  876. {
  877.   SPEED_ROUTINE_MPN_MUL_N (mpn_mul_n);
  878. }
  879. double
  880. speed_mpn_sqr (struct speed_params *s)
  881. {
  882.   SPEED_ROUTINE_MPN_SQR (mpn_sqr);
  883. }
  884. double
  885. speed_mpn_mul_n_sqr (struct speed_params *s)
  886. {
  887.   SPEED_ROUTINE_MPN_SQR_CALL (mpn_mul_n (wp, s->xp, s->xp, s->size));
  888. }
  889. double
  890. speed_mpn_mul_basecase (struct speed_params *s)
  891. {
  892.   SPEED_ROUTINE_MPN_MUL(mpn_mul_basecase);
  893. }
  894. double
  895. speed_mpn_mul (struct speed_params *s)
  896. {
  897.   SPEED_ROUTINE_MPN_MUL(mpn_mul);
  898. }
  899. double
  900. speed_mpn_sqr_basecase (struct speed_params *s)
  901. {
  902.   /* FIXME: size restrictions on some versions of sqr_basecase */
  903.   SPEED_ROUTINE_MPN_SQR (mpn_sqr_basecase);
  904. }
  905. #if HAVE_NATIVE_mpn_sqr_diagonal
  906. double
  907. speed_mpn_sqr_diagonal (struct speed_params *s)
  908. {
  909.   SPEED_ROUTINE_MPN_SQR (mpn_sqr_diagonal);
  910. }
  911. #endif
  912. double
  913. speed_mpn_toom2_sqr (struct speed_params *s)
  914. {
  915.   SPEED_ROUTINE_MPN_TOOM2_SQR (mpn_toom2_sqr);
  916. }
  917. double
  918. speed_mpn_toom3_sqr (struct speed_params *s)
  919. {
  920.   SPEED_ROUTINE_MPN_TOOM3_SQR (mpn_toom3_sqr);
  921. }
  922. double
  923. speed_mpn_toom4_sqr (struct speed_params *s)
  924. {
  925.   SPEED_ROUTINE_MPN_TOOM4_SQR (mpn_toom4_sqr);
  926. }
  927. double
  928. speed_mpn_toom6_sqr (struct speed_params *s)
  929. {
  930.   SPEED_ROUTINE_MPN_TOOM6_SQR (mpn_toom6_sqr);
  931. }
  932. double
  933. speed_mpn_toom8_sqr (struct speed_params *s)
  934. {
  935.   SPEED_ROUTINE_MPN_TOOM8_SQR (mpn_toom8_sqr);
  936. }
  937. double
  938. speed_mpn_toom22_mul (struct speed_params *s)
  939. {
  940.   SPEED_ROUTINE_MPN_TOOM22_MUL_N (mpn_toom22_mul);
  941. }
  942. double
  943. speed_mpn_toom33_mul (struct speed_params *s)
  944. {
  945.   SPEED_ROUTINE_MPN_TOOM33_MUL_N (mpn_toom33_mul);
  946. }
  947. double
  948. speed_mpn_toom44_mul (struct speed_params *s)
  949. {
  950.   SPEED_ROUTINE_MPN_TOOM44_MUL_N (mpn_toom44_mul);
  951. }
  952. double
  953. speed_mpn_toom6h_mul (struct speed_params *s)
  954. {
  955.   SPEED_ROUTINE_MPN_TOOM6H_MUL_N (mpn_toom6h_mul);
  956. }
  957. double
  958. speed_mpn_toom8h_mul (struct speed_params *s)
  959. {
  960.   SPEED_ROUTINE_MPN_TOOM8H_MUL_N (mpn_toom8h_mul);
  961. }
  962. double
  963. speed_mpn_toom32_mul (struct speed_params *s)
  964. {
  965.   SPEED_ROUTINE_MPN_TOOM32_MUL (mpn_toom32_mul);
  966. }
  967. double
  968. speed_mpn_toom42_mul (struct speed_params *s)
  969. {
  970.   SPEED_ROUTINE_MPN_TOOM42_MUL (mpn_toom42_mul);
  971. }
  972. double
  973. speed_mpn_toom43_mul (struct speed_params *s)
  974. {
  975.   SPEED_ROUTINE_MPN_TOOM43_MUL (mpn_toom43_mul);
  976. }
  977. double
  978. speed_mpn_toom63_mul (struct speed_params *s)
  979. {
  980.   SPEED_ROUTINE_MPN_TOOM63_MUL (mpn_toom63_mul);
  981. }
  982. double
  983. speed_mpn_toom32_for_toom43_mul (struct speed_params *s)
  984. {
  985.   SPEED_ROUTINE_MPN_TOOM32_FOR_TOOM43_MUL (mpn_toom32_mul);
  986. }
  987. double
  988. speed_mpn_toom43_for_toom32_mul (struct speed_params *s)
  989. {
  990.   SPEED_ROUTINE_MPN_TOOM43_FOR_TOOM32_MUL (mpn_toom43_mul);
  991. }
  992. double
  993. speed_mpn_toom32_for_toom53_mul (struct speed_params *s)
  994. {
  995.   SPEED_ROUTINE_MPN_TOOM32_FOR_TOOM53_MUL (mpn_toom32_mul);
  996. }
  997. double
  998. speed_mpn_toom53_for_toom32_mul (struct speed_params *s)
  999. {
  1000.   SPEED_ROUTINE_MPN_TOOM53_FOR_TOOM32_MUL (mpn_toom53_mul);
  1001. }
  1002. double
  1003. speed_mpn_toom42_for_toom53_mul (struct speed_params *s)
  1004. {
  1005.   SPEED_ROUTINE_MPN_TOOM42_FOR_TOOM53_MUL (mpn_toom42_mul);
  1006. }
  1007. double
  1008. speed_mpn_toom53_for_toom42_mul (struct speed_params *s)
  1009. {
  1010.   SPEED_ROUTINE_MPN_TOOM53_FOR_TOOM42_MUL (mpn_toom53_mul);
  1011. }
  1012. double
  1013. speed_mpn_nussbaumer_mul (struct speed_params *s)
  1014. {
  1015.   SPEED_ROUTINE_MPN_MUL_N_CALL
  1016.     (mpn_nussbaumer_mul (wp, s->xp, s->size, s->yp, s->size));
  1017. }
  1018. double
  1019. speed_mpn_nussbaumer_mul_sqr (struct speed_params *s)
  1020. {
  1021.   SPEED_ROUTINE_MPN_SQR_CALL
  1022.     (mpn_nussbaumer_mul (wp, s->xp, s->size, s->xp, s->size));
  1023. }
  1024. #if WANT_OLD_FFT_FULL
  1025. double
  1026. speed_mpn_mul_fft_full (struct speed_params *s)
  1027. {
  1028.   SPEED_ROUTINE_MPN_MUL_N_CALL
  1029.     (mpn_mul_fft_full (wp, s->xp, s->size, s->yp, s->size));
  1030. }
  1031. double
  1032. speed_mpn_mul_fft_full_sqr (struct speed_params *s)
  1033. {
  1034.   SPEED_ROUTINE_MPN_SQR_CALL
  1035.     (mpn_mul_fft_full (wp, s->xp, s->size, s->xp, s->size));
  1036. }
  1037. #endif
  1038. /* These are mod 2^N+1 multiplies and squares.  If s->r is supplied it's
  1039.    used as k, otherwise the best k for the size is used.  If s->size isn't a
  1040.    multiple of 2^k it's rounded up to make the effective operation size.  */
  1041. #define SPEED_ROUTINE_MPN_MUL_FFT_CALL(call, sqr)       
  1042.   {                                                     
  1043.     mp_ptr     wp;                                      
  1044.     mp_size_t  pl;                                      
  1045.     int        k;                                       
  1046.     unsigned   i;                                       
  1047.     double     t;                                       
  1048.     TMP_DECL;                                           
  1049.     SPEED_RESTRICT_COND (s->size >= 1);                 
  1050.     if (s->r != 0)                                      
  1051.       k = s->r;                                         
  1052.     else                                                
  1053.       k = mpn_fft_best_k (s->size, sqr);                
  1054.     TMP_MARK;                                           
  1055.     pl = mpn_fft_next_size (s->size, k);                
  1056.     SPEED_TMP_ALLOC_LIMBS (wp, pl+1, s->align_wp);      
  1057.     speed_operand_src (s, s->xp, s->size);              
  1058.     if (!sqr)                                           
  1059.       speed_operand_src (s, s->yp, s->size);            
  1060.     speed_operand_dst (s, wp, pl+1);                    
  1061.     speed_cache_fill (s);                               
  1062.     speed_starttime ();                                 
  1063.     i = s->reps;                                        
  1064.     do                                                  
  1065.       call;                                             
  1066.     while (--i != 0);                                   
  1067.     t = speed_endtime ();                               
  1068.     TMP_FREE;                                           
  1069.     return t;                                           
  1070.   }
  1071. double
  1072. speed_mpn_mul_fft (struct speed_params *s)
  1073. {
  1074.   SPEED_ROUTINE_MPN_MUL_FFT_CALL
  1075.     (mpn_mul_fft (wp, pl, s->xp, s->size, s->yp, s->size, k), 0);
  1076. }
  1077. double
  1078. speed_mpn_mul_fft_sqr (struct speed_params *s)
  1079. {
  1080.   SPEED_ROUTINE_MPN_MUL_FFT_CALL
  1081.     (mpn_mul_fft (wp, pl, s->xp, s->size, s->xp, s->size, k), 1);
  1082. }
  1083. double
  1084. speed_mpn_fft_mul (struct speed_params *s)
  1085. {
  1086.   SPEED_ROUTINE_MPN_MUL_N_CALL (mpn_fft_mul (wp, s->xp, s->size, s->yp, s->size));
  1087. }
  1088. double
  1089. speed_mpn_fft_sqr (struct speed_params *s)
  1090. {
  1091.   SPEED_ROUTINE_MPN_SQR_CALL (mpn_fft_mul (wp, s->xp, s->size, s->xp, s->size));
  1092. }
  1093. double
  1094. speed_mpn_mullo_n (struct speed_params *s)
  1095. {
  1096.   SPEED_ROUTINE_MPN_MULLO_N (mpn_mullo_n);
  1097. }
  1098. double
  1099. speed_mpn_mullo_basecase (struct speed_params *s)
  1100. {
  1101.   SPEED_ROUTINE_MPN_MULLO_BASECASE (mpn_mullo_basecase);
  1102. }
  1103. double
  1104. speed_mpn_mulmod_bnm1 (struct speed_params *s)
  1105. {
  1106.   SPEED_ROUTINE_MPN_MULMOD_BNM1_CALL (mpn_mulmod_bnm1 (wp, s->size, s->xp, s->size, s->yp, s->size, tp));
  1107. }
  1108. double
  1109. speed_mpn_bc_mulmod_bnm1 (struct speed_params *s)
  1110. {
  1111.   SPEED_ROUTINE_MPN_MULMOD_BNM1_CALL (mpn_bc_mulmod_bnm1 (wp, s->xp, s->yp, s->size, tp));
  1112. }
  1113. double
  1114. speed_mpn_mulmod_bnm1_rounded (struct speed_params *s)
  1115. {
  1116.   SPEED_ROUTINE_MPN_MULMOD_BNM1_ROUNDED (mpn_mulmod_bnm1);
  1117. }
  1118. double
  1119. speed_mpn_sqrmod_bnm1 (struct speed_params *s)
  1120. {
  1121.   SPEED_ROUTINE_MPN_MULMOD_BNM1_CALL (mpn_sqrmod_bnm1 (wp, s->size, s->xp, s->size, tp));
  1122. }
  1123. double
  1124. speed_mpn_matrix22_mul (struct speed_params *s)
  1125. {
  1126.   /* Speed params only includes 2 inputs, so we have to invent the
  1127.      other 6. */
  1128.   mp_ptr a;
  1129.   mp_ptr r;
  1130.   mp_ptr b;
  1131.   mp_ptr tp;
  1132.   mp_size_t itch;
  1133.   unsigned i;
  1134.   double t;
  1135.   TMP_DECL;
  1136.   TMP_MARK;
  1137.   SPEED_TMP_ALLOC_LIMBS (a, 4 * s->size, s->align_xp);
  1138.   SPEED_TMP_ALLOC_LIMBS (b, 4 * s->size, s->align_yp);
  1139.   SPEED_TMP_ALLOC_LIMBS (r, 8 * s->size + 4, s->align_wp);
  1140.   MPN_COPY (a, s->xp, s->size);
  1141.   mpn_random (a + s->size, 3 * s->size);
  1142.   MPN_COPY (b, s->yp, s->size);
  1143.   mpn_random (b + s->size, 3 * s->size);
  1144.   itch = mpn_matrix22_mul_itch (s->size, s->size);
  1145.   SPEED_TMP_ALLOC_LIMBS (tp, itch, s->align_wp2);
  1146.   speed_operand_src (s, a, 4 * s->size);
  1147.   speed_operand_src (s, b, 4 * s->size);
  1148.   speed_operand_dst (s, r, 8 * s->size + 4);
  1149.   speed_operand_dst (s, tp, itch);
  1150.   speed_cache_fill (s);
  1151.   speed_starttime ();
  1152.   i = s->reps;
  1153.   do
  1154.     {
  1155.       mp_size_t sz = s->size;
  1156.       MPN_COPY (r + 0 * sz + 0, a + 0 * sz, sz);
  1157.       MPN_COPY (r + 2 * sz + 1, a + 1 * sz, sz);
  1158.       MPN_COPY (r + 4 * sz + 2, a + 2 * sz, sz);
  1159.       MPN_COPY (r + 6 * sz + 3, a + 3 * sz, sz);
  1160.       mpn_matrix22_mul (r, r + 2 * sz + 1, r + 4 * sz + 2, r + 6 * sz + 3, sz,
  1161. b, b + 1 * sz,     b + 2 * sz,     b + 3 * sz,     sz,
  1162. tp);
  1163.     }
  1164.   while (--i != 0);
  1165.   t = speed_endtime();
  1166.   TMP_FREE;
  1167.   return t;
  1168. }
  1169. double
  1170. speed_mpn_hgcd (struct speed_params *s)
  1171. {
  1172.   mp_ptr wp;
  1173.   mp_size_t hgcd_init_scratch = MPN_HGCD_MATRIX_INIT_ITCH (s->size);
  1174.   mp_size_t hgcd_scratch = mpn_hgcd_itch (s->size);
  1175.   mp_ptr ap;
  1176.   mp_ptr bp;
  1177.   mp_ptr tmp1;
  1178.   struct hgcd_matrix hgcd;
  1179.   int res;
  1180.   unsigned i;
  1181.   double t;
  1182.   TMP_DECL;
  1183.   if (s->size < 2)
  1184.     return -1;
  1185.   TMP_MARK;
  1186.   SPEED_TMP_ALLOC_LIMBS (ap, s->size + 1, s->align_xp);
  1187.   SPEED_TMP_ALLOC_LIMBS (bp, s->size + 1, s->align_yp);
  1188.   s->xp[s->size - 1] |= 1;
  1189.   s->yp[s->size - 1] |= 1;
  1190.   SPEED_TMP_ALLOC_LIMBS (tmp1, hgcd_init_scratch, s->align_wp);
  1191.   SPEED_TMP_ALLOC_LIMBS (wp, hgcd_scratch, s->align_wp);
  1192.   speed_starttime ();
  1193.   i = s->reps;
  1194.   do
  1195.     {
  1196.       MPN_COPY (ap, s->xp, s->size);
  1197.       MPN_COPY (bp, s->yp, s->size);
  1198.       mpn_hgcd_matrix_init (&hgcd, s->size, tmp1);
  1199.       res = mpn_hgcd (ap, bp, s->size, &hgcd, wp);
  1200.     }
  1201.   while (--i != 0);
  1202.   t = speed_endtime ();
  1203.   TMP_FREE;
  1204.   return t;
  1205. }
  1206. double
  1207. speed_mpn_hgcd_lehmer (struct speed_params *s)
  1208. {
  1209.   mp_ptr wp;
  1210.   mp_size_t hgcd_init_scratch = MPN_HGCD_MATRIX_INIT_ITCH (s->size);
  1211.   mp_size_t hgcd_scratch = MPN_HGCD_LEHMER_ITCH (s->size);
  1212.   mp_ptr ap;
  1213.   mp_ptr bp;
  1214.   mp_ptr tmp1;
  1215.   struct hgcd_matrix hgcd;
  1216.   int res;
  1217.   unsigned i;
  1218.   double t;
  1219.   TMP_DECL;
  1220.   if (s->size < 2)
  1221.     return -1;
  1222.   TMP_MARK;
  1223.   SPEED_TMP_ALLOC_LIMBS (ap, s->size + 1, s->align_xp);
  1224.   SPEED_TMP_ALLOC_LIMBS (bp, s->size + 1, s->align_yp);
  1225.   s->xp[s->size - 1] |= 1;
  1226.   s->yp[s->size - 1] |= 1;
  1227.   SPEED_TMP_ALLOC_LIMBS (tmp1, hgcd_init_scratch, s->align_wp);
  1228.   SPEED_TMP_ALLOC_LIMBS (wp, hgcd_scratch, s->align_wp);
  1229.   speed_starttime ();
  1230.   i = s->reps;
  1231.   do
  1232.     {
  1233.       MPN_COPY (ap, s->xp, s->size);
  1234.       MPN_COPY (bp, s->yp, s->size);
  1235.       mpn_hgcd_matrix_init (&hgcd, s->size, tmp1);
  1236.       res = mpn_hgcd_lehmer (ap, bp, s->size, &hgcd, wp);
  1237.     }
  1238.   while (--i != 0);
  1239.   t = speed_endtime ();
  1240.   TMP_FREE;
  1241.   return t;
  1242. }
  1243. double
  1244. speed_mpn_gcd (struct speed_params *s)
  1245. {
  1246.   SPEED_ROUTINE_MPN_GCD (mpn_gcd);
  1247. }
  1248. double
  1249. speed_mpn_gcdext (struct speed_params *s)
  1250. {
  1251.   SPEED_ROUTINE_MPN_GCDEXT (mpn_gcdext);
  1252. }
  1253. #if 0
  1254. double
  1255. speed_mpn_gcdext_lehmer (struct speed_params *s)
  1256. {
  1257.   SPEED_ROUTINE_MPN_GCDEXT (__gmpn_gcdext_lehmer);
  1258. }
  1259. #endif
  1260. double
  1261. speed_mpn_gcdext_single (struct speed_params *s)
  1262. {
  1263.   SPEED_ROUTINE_MPN_GCDEXT (mpn_gcdext_single);
  1264. }
  1265. double
  1266. speed_mpn_gcdext_double (struct speed_params *s)
  1267. {
  1268.   SPEED_ROUTINE_MPN_GCDEXT (mpn_gcdext_double);
  1269. }
  1270. double
  1271. speed_mpn_gcdext_one_single (struct speed_params *s)
  1272. {
  1273.   SPEED_ROUTINE_MPN_GCDEXT_ONE (mpn_gcdext_one_single);
  1274. }
  1275. double
  1276. speed_mpn_gcdext_one_double (struct speed_params *s)
  1277. {
  1278.   SPEED_ROUTINE_MPN_GCDEXT_ONE (mpn_gcdext_one_double);
  1279. }
  1280. double
  1281. speed_mpn_gcd_1 (struct speed_params *s)
  1282. {
  1283.   SPEED_ROUTINE_MPN_GCD_1 (mpn_gcd_1);
  1284. }
  1285. double
  1286. speed_mpn_gcd_1N (struct speed_params *s)
  1287. {
  1288.   SPEED_ROUTINE_MPN_GCD_1N (mpn_gcd_1);
  1289. }
  1290. double
  1291. speed_mpz_jacobi (struct speed_params *s)
  1292. {
  1293.   SPEED_ROUTINE_MPZ_JACOBI (mpz_jacobi);
  1294. }
  1295. double
  1296. speed_mpn_jacobi_base (struct speed_params *s)
  1297. {
  1298.   SPEED_ROUTINE_MPN_JACBASE (mpn_jacobi_base);
  1299. }
  1300. double
  1301. speed_mpn_jacobi_base_1 (struct speed_params *s)
  1302. {
  1303.   SPEED_ROUTINE_MPN_JACBASE (mpn_jacobi_base_1);
  1304. }
  1305. double
  1306. speed_mpn_jacobi_base_2 (struct speed_params *s)
  1307. {
  1308.   SPEED_ROUTINE_MPN_JACBASE (mpn_jacobi_base_2);
  1309. }
  1310. double
  1311. speed_mpn_jacobi_base_3 (struct speed_params *s)
  1312. {
  1313.   SPEED_ROUTINE_MPN_JACBASE (mpn_jacobi_base_3);
  1314. }
  1315. double
  1316. speed_mpn_sqrtrem (struct speed_params *s)
  1317. {
  1318.   SPEED_ROUTINE_MPN_SQRTREM (mpn_sqrtrem);
  1319. }
  1320. double
  1321. speed_mpn_rootrem (struct speed_params *s)
  1322. {
  1323.   SPEED_ROUTINE_MPN_ROOTREM (mpn_rootrem);
  1324. }
  1325. double
  1326. speed_mpz_fac_ui (struct speed_params *s)
  1327. {
  1328.   SPEED_ROUTINE_MPZ_FAC_UI (mpz_fac_ui);
  1329. }
  1330. double
  1331. speed_mpn_fib2_ui (struct speed_params *s)
  1332. {
  1333.   SPEED_ROUTINE_MPN_FIB2_UI (mpn_fib2_ui);
  1334. }
  1335. double
  1336. speed_mpz_fib_ui (struct speed_params *s)
  1337. {
  1338.   SPEED_ROUTINE_MPZ_FIB_UI (mpz_fib_ui);
  1339. }
  1340. double
  1341. speed_mpz_fib2_ui (struct speed_params *s)
  1342. {
  1343.   SPEED_ROUTINE_MPZ_FIB2_UI (mpz_fib2_ui);
  1344. }
  1345. double
  1346. speed_mpz_lucnum_ui (struct speed_params *s)
  1347. {
  1348.   SPEED_ROUTINE_MPZ_LUCNUM_UI (mpz_lucnum_ui);
  1349. }
  1350. double
  1351. speed_mpz_lucnum2_ui (struct speed_params *s)
  1352. {
  1353.   SPEED_ROUTINE_MPZ_LUCNUM2_UI (mpz_lucnum2_ui);
  1354. }
  1355. double
  1356. speed_mpz_powm (struct speed_params *s)
  1357. {
  1358.   SPEED_ROUTINE_MPZ_POWM (mpz_powm);
  1359. }
  1360. double
  1361. speed_mpz_powm_mod (struct speed_params *s)
  1362. {
  1363.   SPEED_ROUTINE_MPZ_POWM (mpz_powm_mod);
  1364. }
  1365. double
  1366. speed_mpz_powm_redc (struct speed_params *s)
  1367. {
  1368.   SPEED_ROUTINE_MPZ_POWM (mpz_powm_redc);
  1369. }
  1370. double
  1371. speed_mpz_powm_ui (struct speed_params *s)
  1372. {
  1373.   SPEED_ROUTINE_MPZ_POWM_UI (mpz_powm_ui);
  1374. }
  1375. double
  1376. speed_binvert_limb (struct speed_params *s)
  1377. {
  1378.   SPEED_ROUTINE_MODLIMB_INVERT (binvert_limb);
  1379. }
  1380. double
  1381. speed_noop (struct speed_params *s)
  1382. {
  1383.   unsigned  i;
  1384.   speed_starttime ();
  1385.   i = s->reps;
  1386.   do
  1387.     noop ();
  1388.   while (--i != 0);
  1389.   return speed_endtime ();
  1390. }
  1391. double
  1392. speed_noop_wxs (struct speed_params *s)
  1393. {
  1394.   mp_ptr   wp;
  1395.   unsigned i;
  1396.   double   t;
  1397.   TMP_DECL;
  1398.   TMP_MARK;
  1399.   wp = TMP_ALLOC_LIMBS (1);
  1400.   speed_starttime ();
  1401.   i = s->reps;
  1402.   do
  1403.     noop_wxs (wp, s->xp, s->size);
  1404.   while (--i != 0);
  1405.   t = speed_endtime ();
  1406.   TMP_FREE;
  1407.   return t;
  1408. }
  1409. double
  1410. speed_noop_wxys (struct speed_params *s)
  1411. {
  1412.   mp_ptr   wp;
  1413.   unsigned i;
  1414.   double   t;
  1415.   TMP_DECL;
  1416.   TMP_MARK;
  1417.   wp = TMP_ALLOC_LIMBS (1);
  1418.   speed_starttime ();
  1419.   i = s->reps;
  1420.   do
  1421.     noop_wxys (wp, s->xp, s->yp, s->size);
  1422.   while (--i != 0);
  1423.   t = speed_endtime ();
  1424.   TMP_FREE;
  1425.   return t;
  1426. }
  1427. #define SPEED_ROUTINE_ALLOC_FREE(variables, calls)      
  1428.   {                                                     
  1429.     unsigned  i;                                        
  1430.     variables;                                          
  1431.     speed_starttime ();                                 
  1432.     i = s->reps;                                        
  1433.     do                                                  
  1434.       {                                                 
  1435. calls;                                          
  1436.       }                                                 
  1437.     while (--i != 0);                                   
  1438.     return speed_endtime ();                            
  1439.   }
  1440. /* Compare these to see how much malloc/free costs and then how much
  1441.    __gmp_default_allocate/free and mpz_init/clear add.  mpz_init/clear or
  1442.    mpq_init/clear will be doing a 1 limb allocate, so use that as the size
  1443.    when including them in comparisons.  */
  1444. double
  1445. speed_malloc_free (struct speed_params *s)
  1446. {
  1447.   size_t  bytes = s->size * BYTES_PER_MP_LIMB;
  1448.   SPEED_ROUTINE_ALLOC_FREE (void *p,
  1449.     p = malloc (bytes);
  1450.     free (p));
  1451. }
  1452. double
  1453. speed_malloc_realloc_free (struct speed_params *s)
  1454. {
  1455.   size_t  bytes = s->size * BYTES_PER_MP_LIMB;
  1456.   SPEED_ROUTINE_ALLOC_FREE (void *p,
  1457.     p = malloc (BYTES_PER_MP_LIMB);
  1458.     p = realloc (p, bytes);
  1459.     free (p));
  1460. }
  1461. double
  1462. speed_gmp_allocate_free (struct speed_params *s)
  1463. {
  1464.   size_t  bytes = s->size * BYTES_PER_MP_LIMB;
  1465.   SPEED_ROUTINE_ALLOC_FREE (void *p,
  1466.     p = (*__gmp_allocate_func) (bytes);
  1467.     (*__gmp_free_func) (p, bytes));
  1468. }
  1469. double
  1470. speed_gmp_allocate_reallocate_free (struct speed_params *s)
  1471. {
  1472.   size_t  bytes = s->size * BYTES_PER_MP_LIMB;
  1473.   SPEED_ROUTINE_ALLOC_FREE
  1474.     (void *p,
  1475.      p = (*__gmp_allocate_func) (BYTES_PER_MP_LIMB);
  1476.      p = (*__gmp_reallocate_func) (p, bytes, BYTES_PER_MP_LIMB);
  1477.      (*__gmp_free_func) (p, bytes));
  1478. }
  1479. double
  1480. speed_mpz_init_clear (struct speed_params *s)
  1481. {
  1482.   SPEED_ROUTINE_ALLOC_FREE (mpz_t z,
  1483.     mpz_init (z);
  1484.     mpz_clear (z));
  1485. }
  1486. double
  1487. speed_mpz_init_realloc_clear (struct speed_params *s)
  1488. {
  1489.   SPEED_ROUTINE_ALLOC_FREE (mpz_t z,
  1490.     mpz_init (z);
  1491.     _mpz_realloc (z, s->size);
  1492.     mpz_clear (z));
  1493. }
  1494. double
  1495. speed_mpq_init_clear (struct speed_params *s)
  1496. {
  1497.   SPEED_ROUTINE_ALLOC_FREE (mpq_t q,
  1498.     mpq_init (q);
  1499.     mpq_clear (q));
  1500. }
  1501. double
  1502. speed_mpf_init_clear (struct speed_params *s)
  1503. {
  1504.   SPEED_ROUTINE_ALLOC_FREE (mpf_t f,
  1505.     mpf_init (f);
  1506.     mpf_clear (f));
  1507. }
  1508. /* Compare this to mpn_add_n to see how much overhead mpz_add adds.  Note
  1509.    that repeatedly calling mpz_add with the same data gives branch prediction
  1510.    in it an advantage.  */
  1511. double
  1512. speed_mpz_add (struct speed_params *s)
  1513. {
  1514.   mpz_t     w, x, y;
  1515.   unsigned  i;
  1516.   double    t;
  1517.   mpz_init (w);
  1518.   mpz_init (x);
  1519.   mpz_init (y);
  1520.   mpz_set_n (x, s->xp, s->size);
  1521.   mpz_set_n (y, s->yp, s->size);
  1522.   mpz_add (w, x, y);
  1523.   speed_starttime ();
  1524.   i = s->reps;
  1525.   do
  1526.     {
  1527.       mpz_add (w, x, y);
  1528.     }
  1529.   while (--i != 0);
  1530.   t = speed_endtime ();
  1531.   mpz_clear (w);
  1532.   mpz_clear (x);
  1533.   mpz_clear (y);
  1534.   return t;
  1535. }
  1536. /* If r==0, calculate (size,size/2),
  1537.    otherwise calculate (size,r). */
  1538. double
  1539. speed_mpz_bin_uiui (struct speed_params *s)
  1540. {
  1541.   mpz_t          w;
  1542.   unsigned long  k;
  1543.   unsigned  i;
  1544.   double    t;
  1545.   mpz_init (w);
  1546.   if (s->r != 0)
  1547.     k = s->r;
  1548.   else
  1549.     k = s->size/2;
  1550.   speed_starttime ();
  1551.   i = s->reps;
  1552.   do
  1553.     {
  1554.       mpz_bin_uiui (w, s->size, k);
  1555.     }
  1556.   while (--i != 0);
  1557.   t = speed_endtime ();
  1558.   mpz_clear (w);
  1559.   return t;
  1560. }
  1561. /* The multiplies are successively dependent so the latency is measured, not
  1562.    the issue rate.  There's only 10 per loop so the code doesn't get too big
  1563.    since umul_ppmm is several instructions on some cpus.
  1564.    Putting the arguments as "h,l,l,h" gets slightly better code from gcc
  1565.    2.95.2 on x86, it puts only one mov between each mul, not two.  That mov
  1566.    though will probably show up as a bogus extra cycle though.
  1567.    The measuring function macros are into three parts to avoid overflowing
  1568.    preprocessor expansion space if umul_ppmm is big.
  1569.    Limitations:
  1570.    Don't blindly use this to set UMUL_TIME in gmp-mparam.h, check the code
  1571.    generated first, especially on CPUs with low latency multipliers.
  1572.    The default umul_ppmm doing h*l will be getting increasing numbers of
  1573.    high zero bits in the calculation.  CPUs with data-dependent multipliers
  1574.    will want to use umul_ppmm.1 to get some randomization into the
  1575.    calculation.  The extra xors and fetches will be a slowdown of course.  */
  1576. #define SPEED_MACRO_UMUL_PPMM_A 
  1577.   {                             
  1578.     mp_limb_t  h, l;            
  1579.     unsigned   i;               
  1580.     double     t;               
  1581.     s->time_divisor = 10;       
  1582.     h = s->xp[0];               
  1583.     l = s->yp[0];               
  1584.     if (s->r == 1)              
  1585.       {                         
  1586. speed_starttime ();     
  1587. i = s->reps;            
  1588. do                      
  1589.   {
  1590. #define SPEED_MACRO_UMUL_PPMM_B 
  1591.   }                     
  1592. while (--i != 0);       
  1593. t = speed_endtime ();   
  1594.       }                         
  1595.     else                        
  1596.       {                         
  1597. speed_starttime ();     
  1598. i = s->reps;            
  1599. do                      
  1600.   {
  1601. #define SPEED_MACRO_UMUL_PPMM_C                                         
  1602.   }                                                             
  1603. while (--i != 0);                                               
  1604. t = speed_endtime ();                                           
  1605.       }                                                                 
  1606.     /* stop the compiler optimizing away the whole calculation! */      
  1607.     noop_1 (h);                                                         
  1608.     noop_1 (l);                                                         
  1609.     return t;                                                           
  1610.   }
  1611. double
  1612. speed_umul_ppmm (struct speed_params *s)
  1613. {
  1614.   SPEED_MACRO_UMUL_PPMM_A;
  1615.   {
  1616.     umul_ppmm (h, l, l, h);  h ^= s->xp_block[0]; l ^= s->yp_block[0];
  1617.      umul_ppmm (h, l, l, h); h ^= s->xp_block[1]; l ^= s->yp_block[1];
  1618.      umul_ppmm (h, l, l, h); h ^= s->xp_block[2]; l ^= s->yp_block[2];
  1619.     umul_ppmm (h, l, l, h);  h ^= s->xp_block[3]; l ^= s->yp_block[3];
  1620.      umul_ppmm (h, l, l, h); h ^= s->xp_block[4]; l ^= s->yp_block[4];
  1621.      umul_ppmm (h, l, l, h); h ^= s->xp_block[5]; l ^= s->yp_block[5];
  1622.     umul_ppmm (h, l, l, h);  h ^= s->xp_block[6]; l ^= s->yp_block[6];
  1623.      umul_ppmm (h, l, l, h); h ^= s->xp_block[7]; l ^= s->yp_block[7];
  1624.      umul_ppmm (h, l, l, h); h ^= s->xp_block[8]; l ^= s->yp_block[8];
  1625.     umul_ppmm (h, l, l, h);  h ^= s->xp_block[9]; l ^= s->yp_block[9];
  1626.   }
  1627.   SPEED_MACRO_UMUL_PPMM_B;
  1628.   {
  1629.     umul_ppmm (h, l, l, h);
  1630.      umul_ppmm (h, l, l, h);
  1631.      umul_ppmm (h, l, l, h);
  1632.     umul_ppmm (h, l, l, h);
  1633.      umul_ppmm (h, l, l, h);
  1634.      umul_ppmm (h, l, l, h);
  1635.     umul_ppmm (h, l, l, h);
  1636.      umul_ppmm (h, l, l, h);
  1637.      umul_ppmm (h, l, l, h);
  1638.     umul_ppmm (h, l, l, h);
  1639.   }
  1640.   SPEED_MACRO_UMUL_PPMM_C;
  1641. }
  1642. #if HAVE_NATIVE_mpn_umul_ppmm
  1643. double
  1644. speed_mpn_umul_ppmm (struct speed_params *s)
  1645. {
  1646.   SPEED_MACRO_UMUL_PPMM_A;
  1647.   {
  1648.     h = mpn_umul_ppmm (&l, h, l);  h ^= s->xp_block[0]; l ^= s->yp_block[0];
  1649.      h = mpn_umul_ppmm (&l, h, l); h ^= s->xp_block[1]; l ^= s->yp_block[1];
  1650.      h = mpn_umul_ppmm (&l, h, l); h ^= s->xp_block[2]; l ^= s->yp_block[2];
  1651.     h = mpn_umul_ppmm (&l, h, l);  h ^= s->xp_block[3]; l ^= s->yp_block[3];
  1652.      h = mpn_umul_ppmm (&l, h, l); h ^= s->xp_block[4]; l ^= s->yp_block[4];
  1653.      h = mpn_umul_ppmm (&l, h, l); h ^= s->xp_block[5]; l ^= s->yp_block[5];
  1654.     h = mpn_umul_ppmm (&l, h, l);  h ^= s->xp_block[6]; l ^= s->yp_block[6];
  1655.      h = mpn_umul_ppmm (&l, h, l); h ^= s->xp_block[7]; l ^= s->yp_block[7];
  1656.      h = mpn_umul_ppmm (&l, h, l); h ^= s->xp_block[8]; l ^= s->yp_block[8];
  1657.     h = mpn_umul_ppmm (&l, h, l);  h ^= s->xp_block[9]; l ^= s->yp_block[9];
  1658.   }
  1659.   SPEED_MACRO_UMUL_PPMM_B;
  1660.   {
  1661.     h = mpn_umul_ppmm (&l, h, l);
  1662.      h = mpn_umul_ppmm (&l, h, l);
  1663.      h = mpn_umul_ppmm (&l, h, l);
  1664.     h = mpn_umul_ppmm (&l, h, l);
  1665.      h = mpn_umul_ppmm (&l, h, l);
  1666.      h = mpn_umul_ppmm (&l, h, l);
  1667.     h = mpn_umul_ppmm (&l, h, l);
  1668.      h = mpn_umul_ppmm (&l, h, l);
  1669.      h = mpn_umul_ppmm (&l, h, l);
  1670.     h = mpn_umul_ppmm (&l, h, l);
  1671.   }
  1672.   SPEED_MACRO_UMUL_PPMM_C;
  1673. }
  1674. #endif
  1675. #if HAVE_NATIVE_mpn_umul_ppmm_r
  1676. double
  1677. speed_mpn_umul_ppmm_r (struct speed_params *s)
  1678. {
  1679.   SPEED_MACRO_UMUL_PPMM_A;
  1680.   {
  1681.     h = mpn_umul_ppmm_r (h, l, &l);  h ^= s->xp_block[0]; l ^= s->yp_block[0];
  1682.      h = mpn_umul_ppmm_r (h, l, &l); h ^= s->xp_block[1]; l ^= s->yp_block[1];
  1683.      h = mpn_umul_ppmm_r (h, l, &l); h ^= s->xp_block[2]; l ^= s->yp_block[2];
  1684.     h = mpn_umul_ppmm_r (h, l, &l);  h ^= s->xp_block[3]; l ^= s->yp_block[3];
  1685.      h = mpn_umul_ppmm_r (h, l, &l); h ^= s->xp_block[4]; l ^= s->yp_block[4];
  1686.      h = mpn_umul_ppmm_r (h, l, &l); h ^= s->xp_block[5]; l ^= s->yp_block[5];
  1687.     h = mpn_umul_ppmm_r (h, l, &l);  h ^= s->xp_block[6]; l ^= s->yp_block[6];
  1688.      h = mpn_umul_ppmm_r (h, l, &l); h ^= s->xp_block[7]; l ^= s->yp_block[7];
  1689.      h = mpn_umul_ppmm_r (h, l, &l); h ^= s->xp_block[8]; l ^= s->yp_block[8];
  1690.     h = mpn_umul_ppmm_r (h, l, &l);  h ^= s->xp_block[9]; l ^= s->yp_block[9];
  1691.   }
  1692.   SPEED_MACRO_UMUL_PPMM_B;
  1693.   {
  1694.     h = mpn_umul_ppmm_r (h, l, &l);
  1695.      h = mpn_umul_ppmm_r (h, l, &l);
  1696.      h = mpn_umul_ppmm_r (h, l, &l);
  1697.     h = mpn_umul_ppmm_r (h, l, &l);
  1698.      h = mpn_umul_ppmm_r (h, l, &l);
  1699.      h = mpn_umul_ppmm_r (h, l, &l);
  1700.     h = mpn_umul_ppmm_r (h, l, &l);
  1701.      h = mpn_umul_ppmm_r (h, l, &l);
  1702.      h = mpn_umul_ppmm_r (h, l, &l);
  1703.     h = mpn_umul_ppmm_r (h, l, &l);
  1704.   }
  1705.   SPEED_MACRO_UMUL_PPMM_C;
  1706. }
  1707. #endif
  1708. /* The divisions are successively dependent so latency is measured, not
  1709.    issue rate.  There's only 10 per loop so the code doesn't get too big,
  1710.    especially for udiv_qrnnd_preinv and preinv2norm, which are several
  1711.    instructions each.
  1712.    Note that it's only the division which is measured here, there's no data
  1713.    fetching and no shifting if the divisor gets normalized.
  1714.    In speed_udiv_qrnnd with gcc 2.95.2 on x86 the parameters "q,r,r,q,d"
  1715.    generate x86 div instructions with nothing in between.
  1716.    The measuring function macros are in two parts to avoid overflowing
  1717.    preprocessor expansion space if udiv_qrnnd etc are big.
  1718.    Limitations:
  1719.    Don't blindly use this to set UDIV_TIME in gmp-mparam.h, check the code
  1720.    generated first.
  1721.    CPUs with data-dependent divisions may want more attention paid to the
  1722.    randomness of the data used.  Probably the measurement wanted is over
  1723.    uniformly distributed numbers, but what's here might not be giving that.  */
  1724. #define SPEED_ROUTINE_UDIV_QRNND_A(normalize)           
  1725.   {                                                     
  1726.     double     t;                                       
  1727.     unsigned   i;                                       
  1728.     mp_limb_t  q, r, d;                                 
  1729.     mp_limb_t  dinv;                                    
  1730.     s->time_divisor = 10;                               
  1731.     /* divisor from "r" parameter, or a default */      
  1732.     d = s->r;                                           
  1733.     if (d == 0)                                         
  1734.       d = mp_bases[10].big_base;                        
  1735.     if (normalize)                                      
  1736.       {                                                 
  1737. unsigned  norm;                                 
  1738. count_leading_zeros (norm, d);                  
  1739. d <<= norm;                                     
  1740. invert_limb (dinv, d);                          
  1741.       }                                                 
  1742.     q = s->xp[0];                                       
  1743.     r = s->yp[0] % d;                                   
  1744.     speed_starttime ();                                 
  1745.     i = s->reps;                                        
  1746.     do                                                  
  1747.       {
  1748. #define SPEED_ROUTINE_UDIV_QRNND_B                                      
  1749.       }                                                                 
  1750.     while (--i != 0);                                                   
  1751.     t = speed_endtime ();                                               
  1752.     /* stop the compiler optimizing away the whole calculation! */      
  1753.     noop_1 (q);                                                         
  1754.     noop_1 (r);                                                         
  1755.     return t;                                                           
  1756.   }
  1757. double
  1758. speed_udiv_qrnnd (struct speed_params *s)
  1759. {
  1760.   SPEED_ROUTINE_UDIV_QRNND_A (UDIV_NEEDS_NORMALIZATION);
  1761.   {
  1762.     udiv_qrnnd (q, r, r, q, d);
  1763.      udiv_qrnnd (q, r, r, q, d);
  1764.      udiv_qrnnd (q, r, r, q, d);
  1765.     udiv_qrnnd (q, r, r, q, d);
  1766.      udiv_qrnnd (q, r, r, q, d);
  1767.      udiv_qrnnd (q, r, r, q, d);
  1768.     udiv_qrnnd (q, r, r, q, d);
  1769.      udiv_qrnnd (q, r, r, q, d);
  1770.      udiv_qrnnd (q, r, r, q, d);
  1771.     udiv_qrnnd (q, r, r, q, d);
  1772.   }
  1773.   SPEED_ROUTINE_UDIV_QRNND_B;
  1774. }
  1775. double
  1776. speed_udiv_qrnnd_preinv1 (struct speed_params *s)
  1777. {
  1778.   SPEED_ROUTINE_UDIV_QRNND_A (1);
  1779.   {
  1780.     udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1781.      udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1782.      udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1783.     udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1784.      udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1785.      udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1786.     udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1787.      udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1788.      udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1789.     udiv_qrnnd_preinv1 (q, r, r, q, d, dinv);
  1790.   }
  1791.   SPEED_ROUTINE_UDIV_QRNND_B;
  1792. }
  1793. double
  1794. speed_udiv_qrnnd_preinv2 (struct speed_params *s)
  1795. {
  1796.   SPEED_ROUTINE_UDIV_QRNND_A (1);
  1797.   {
  1798.     udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1799.      udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1800.      udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1801.     udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1802.      udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1803.      udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1804.     udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1805.      udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1806.      udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1807.     udiv_qrnnd_preinv2 (q, r, r, q, d, dinv);
  1808.   }
  1809.   SPEED_ROUTINE_UDIV_QRNND_B;
  1810. }
  1811. double
  1812. speed_udiv_qrnnd_c (struct speed_params *s)
  1813. {
  1814.   SPEED_ROUTINE_UDIV_QRNND_A (1);
  1815.   {
  1816.     __udiv_qrnnd_c (q, r, r, q, d);
  1817.      __udiv_qrnnd_c (q, r, r, q, d);
  1818.      __udiv_qrnnd_c (q, r, r, q, d);
  1819.     __udiv_qrnnd_c (q, r, r, q, d);
  1820.      __udiv_qrnnd_c (q, r, r, q, d);
  1821.      __udiv_qrnnd_c (q, r, r, q, d);
  1822.     __udiv_qrnnd_c (q, r, r, q, d);
  1823.      __udiv_qrnnd_c (q, r, r, q, d);
  1824.      __udiv_qrnnd_c (q, r, r, q, d);
  1825.     __udiv_qrnnd_c (q, r, r, q, d);
  1826.   }
  1827.   SPEED_ROUTINE_UDIV_QRNND_B;
  1828. }
  1829. #if HAVE_NATIVE_mpn_udiv_qrnnd
  1830. double
  1831. speed_mpn_udiv_qrnnd (struct speed_params *s)
  1832. {
  1833.   SPEED_ROUTINE_UDIV_QRNND_A (1);
  1834.   {
  1835.     q = mpn_udiv_qrnnd (&r, r, q, d);
  1836.      q = mpn_udiv_qrnnd (&r, r, q, d);
  1837.      q = mpn_udiv_qrnnd (&r, r, q, d);
  1838.     q = mpn_udiv_qrnnd (&r, r, q, d);
  1839.      q = mpn_udiv_qrnnd (&r, r, q, d);
  1840.      q = mpn_udiv_qrnnd (&r, r, q, d);
  1841.     q = mpn_udiv_qrnnd (&r, r, q, d);
  1842.      q = mpn_udiv_qrnnd (&r, r, q, d);
  1843.      q = mpn_udiv_qrnnd (&r, r, q, d);
  1844.     q = mpn_udiv_qrnnd (&r, r, q, d);
  1845.   }
  1846.   SPEED_ROUTINE_UDIV_QRNND_B;
  1847. }
  1848. #endif
  1849. #if HAVE_NATIVE_mpn_udiv_qrnnd_r
  1850. double
  1851. speed_mpn_udiv_qrnnd_r (struct speed_params *s)
  1852. {
  1853.   SPEED_ROUTINE_UDIV_QRNND_A (1);
  1854.   {
  1855.     q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1856.      q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1857.      q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1858.     q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1859.      q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1860.      q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1861.     q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1862.      q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1863.      q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1864.     q = mpn_udiv_qrnnd_r (r, q, d, &r);
  1865.   }
  1866.   SPEED_ROUTINE_UDIV_QRNND_B;
  1867. }
  1868. #endif
  1869. double
  1870. speed_invert_limb (struct speed_params *s)
  1871. {
  1872.   SPEED_ROUTINE_INVERT_LIMB_CALL (invert_limb (dinv, d));
  1873. }
  1874. /* xp[0] might not be particularly random, but should give an indication how
  1875.    "/" runs.  Same for speed_operator_mod below.  */
  1876. double
  1877. speed_operator_div (struct speed_params *s)
  1878. {
  1879.   double     t;
  1880.   unsigned   i;
  1881.   mp_limb_t  x, q, d;
  1882.   s->time_divisor = 10;
  1883.   /* divisor from "r" parameter, or a default */
  1884.   d = s->r;
  1885.   if (d == 0)
  1886.     d = mp_bases[10].big_base;
  1887.   x = s->xp[0];
  1888.   q = 0;
  1889.   speed_starttime ();
  1890.   i = s->reps;
  1891.   do
  1892.     {
  1893.       q ^= x; q /= d;
  1894.        q ^= x; q /= d;
  1895.        q ^= x; q /= d;
  1896.       q ^= x; q /= d;
  1897.        q ^= x; q /= d;
  1898.        q ^= x; q /= d;
  1899.       q ^= x; q /= d;
  1900.        q ^= x; q /= d;
  1901.        q ^= x; q /= d;
  1902.       q ^= x; q /= d;
  1903.     }
  1904.   while (--i != 0);
  1905.   t = speed_endtime ();
  1906.   /* stop the compiler optimizing away the whole calculation! */
  1907.   noop_1 (q);
  1908.   return t;
  1909. }
  1910. double
  1911. speed_operator_mod (struct speed_params *s)
  1912. {
  1913.   double     t;
  1914.   unsigned   i;
  1915.   mp_limb_t  x, r, d;
  1916.   s->time_divisor = 10;
  1917.   /* divisor from "r" parameter, or a default */
  1918.   d = s->r;
  1919.   if (d == 0)
  1920.     d = mp_bases[10].big_base;
  1921.   x = s->xp[0];
  1922.   r = 0;
  1923.   speed_starttime ();
  1924.   i = s->reps;
  1925.   do
  1926.     {
  1927.       r ^= x; r %= d;
  1928.        r ^= x; r %= d;
  1929.        r ^= x; r %= d;
  1930.       r ^= x; r %= d;
  1931.        r ^= x; r %= d;
  1932.        r ^= x; r %= d;
  1933.       r ^= x; r %= d;
  1934.        r ^= x; r %= d;
  1935.        r ^= x; r %= d;
  1936.       r ^= x; r %= d;
  1937.     }
  1938.   while (--i != 0);
  1939.   t = speed_endtime ();
  1940.   /* stop the compiler optimizing away the whole calculation! */
  1941.   noop_1 (r);
  1942.   return t;
  1943. }
  1944. /* r==0 measures on data with the values uniformly distributed.  This will
  1945.    be typical for count_trailing_zeros in a GCD etc.
  1946.    r==1 measures on data with the resultant count uniformly distributed
  1947.    between 0 and GMP_LIMB_BITS-1.  This is probably sensible for
  1948.    count_leading_zeros on the high limbs of divisors.  */
  1949. int
  1950. speed_routine_count_zeros_setup (struct speed_params *s,
  1951.  mp_ptr xp, int leading, int zero)
  1952. {
  1953.   int        i, c;
  1954.   mp_limb_t  n;
  1955.   if (s->r == 0)
  1956.     {
  1957.       /* Make uniformly distributed data.  If zero isn't allowed then change
  1958.  it to 1 for leading, or 0x800..00 for trailing.  */
  1959.       MPN_COPY (xp, s->xp_block, SPEED_BLOCK_SIZE);
  1960.       if (! zero)
  1961. for (i = 0; i < SPEED_BLOCK_SIZE; i++)
  1962.   if (xp[i] == 0)
  1963.     xp[i] = leading ? 1 : GMP_LIMB_HIGHBIT;
  1964.     }
  1965.   else if (s->r == 1)
  1966.     {
  1967.       /* Make counts uniformly distributed.  A randomly chosen bit is set, and
  1968.  for leading the rest above it are cleared, or for trailing then the
  1969.  rest below.  */
  1970.       for (i = 0; i < SPEED_BLOCK_SIZE; i++)
  1971. {
  1972.   mp_limb_t  set = CNST_LIMB(1) << (s->yp_block[i] % GMP_LIMB_BITS);
  1973.   mp_limb_t  keep_below = set-1;
  1974.   mp_limb_t  keep_above = MP_LIMB_T_MAX ^ keep_below;
  1975.   mp_limb_t  keep = (leading ? keep_below : keep_above);
  1976.   xp[i] = (s->xp_block[i] & keep) | set;
  1977. }
  1978.     }
  1979.   else
  1980.     {
  1981.       return 0;
  1982.     }
  1983.   /* Account for the effect of n^=c. */
  1984.   c = 0;
  1985.   for (i = 0; i < SPEED_BLOCK_SIZE; i++)
  1986.     {
  1987.       n = xp[i];
  1988.       xp[i] ^= c;
  1989.       if (leading)
  1990. count_leading_zeros (c, n);
  1991.       else
  1992. count_trailing_zeros (c, n);
  1993.     }
  1994.   return 1;
  1995. }
  1996. double
  1997. speed_count_leading_zeros (struct speed_params *s)
  1998. {
  1999. #ifdef COUNT_LEADING_ZEROS_0
  2000. #define COUNT_LEADING_ZEROS_0_ALLOWED   1
  2001. #else
  2002. #define COUNT_LEADING_ZEROS_0_ALLOWED   0
  2003. #endif
  2004.   SPEED_ROUTINE_COUNT_ZEROS_A (1, COUNT_LEADING_ZEROS_0_ALLOWED);
  2005.   count_leading_zeros (c, n);
  2006.   SPEED_ROUTINE_COUNT_ZEROS_B ();
  2007. }
  2008. double
  2009. speed_count_trailing_zeros (struct speed_params *s)
  2010. {
  2011.   SPEED_ROUTINE_COUNT_ZEROS_A (0, 0);
  2012.   count_trailing_zeros (c, n);
  2013.   SPEED_ROUTINE_COUNT_ZEROS_B ();
  2014. }
  2015. double
  2016. speed_mpn_get_str (struct speed_params *s)
  2017. {
  2018.   SPEED_ROUTINE_MPN_GET_STR (mpn_get_str);
  2019. }
  2020. double
  2021. speed_mpn_set_str (struct speed_params *s)
  2022. {
  2023.   SPEED_ROUTINE_MPN_SET_STR_CALL (mpn_set_str (wp, xp, s->size, base));
  2024. }
  2025. double
  2026. speed_mpn_bc_set_str (struct speed_params *s)
  2027. {
  2028.   SPEED_ROUTINE_MPN_SET_STR_CALL (mpn_bc_set_str (wp, xp, s->size, base));
  2029. }
  2030. double
  2031. speed_MPN_ZERO (struct speed_params *s)
  2032. {
  2033.   SPEED_ROUTINE_MPN_ZERO_CALL (MPN_ZERO (wp, s->size));
  2034. }
  2035. int
  2036. speed_randinit (struct speed_params *s, gmp_randstate_ptr rstate)
  2037. {
  2038.   if (s->r == 0)
  2039.     gmp_randinit_default (rstate);
  2040.   else if (s->r == 1)
  2041.     gmp_randinit_mt (rstate);
  2042.   else
  2043.     {
  2044.       return gmp_randinit_lc_2exp_size (rstate, s->r);
  2045.     }
  2046.   return 1;
  2047. }
  2048. double
  2049. speed_gmp_randseed (struct speed_params *s)
  2050. {
  2051.   gmp_randstate_t  rstate;
  2052.   unsigned  i;
  2053.   double    t;
  2054.   mpz_t     x;
  2055.   SPEED_RESTRICT_COND (s->size >= 1);
  2056.   SPEED_RESTRICT_COND (speed_randinit (s, rstate));
  2057.   /* s->size bits of seed */
  2058.   mpz_init_set_n (x, s->xp, s->size);
  2059.   mpz_fdiv_r_2exp (x, x, (unsigned long) s->size);
  2060.   /* cache priming */
  2061.   gmp_randseed (rstate, x);
  2062.   speed_starttime ();
  2063.   i = s->reps;
  2064.   do
  2065.     gmp_randseed (rstate, x);
  2066.   while (--i != 0);
  2067.   t = speed_endtime ();
  2068.   gmp_randclear (rstate);
  2069.   mpz_clear (x);
  2070.   return t;
  2071. }
  2072. double
  2073. speed_gmp_randseed_ui (struct speed_params *s)
  2074. {
  2075.   gmp_randstate_t  rstate;
  2076.   unsigned  i, j;
  2077.   double    t;
  2078.   SPEED_RESTRICT_COND (speed_randinit (s, rstate));
  2079.   /* cache priming */
  2080.   gmp_randseed_ui (rstate, 123L);
  2081.   speed_starttime ();
  2082.   i = s->reps;
  2083.   j = 0;
  2084.   do
  2085.     {
  2086.       gmp_randseed_ui (rstate, (unsigned long) s->xp_block[j]);
  2087.       j++;
  2088.       if (j >= SPEED_BLOCK_SIZE)
  2089. j = 0;
  2090.     }
  2091.   while (--i != 0);
  2092.   t = speed_endtime ();
  2093.   gmp_randclear (rstate);
  2094.   return t;
  2095. }
  2096. double
  2097. speed_mpz_urandomb (struct speed_params *s)
  2098. {
  2099.   gmp_randstate_t  rstate;
  2100.   mpz_t     z;
  2101.   unsigned  i;
  2102.   double    t;
  2103.   SPEED_RESTRICT_COND (s->size >= 0);
  2104.   SPEED_RESTRICT_COND (speed_randinit (s, rstate));
  2105.   mpz_init (z);
  2106.   /* cache priming */
  2107.   mpz_urandomb (z, rstate, (unsigned long) s->size);
  2108.   mpz_urandomb (z, rstate, (unsigned long) s->size);
  2109.   speed_starttime ();
  2110.   i = s->reps;
  2111.   do
  2112.     mpz_urandomb (z, rstate, (unsigned long) s->size);
  2113.   while (--i != 0);
  2114.   t = speed_endtime ();
  2115.   mpz_clear (z);
  2116.   gmp_randclear (rstate);
  2117.   return t;
  2118. }