(root)/
gmp-6.3.0/
tests/
mpn/
toom-shared.h
       1  /* Test for various Toom functions.
       2  
       3  Copyright 2009 Free Software Foundation, Inc.
       4  
       5  This file is part of the GNU MP Library test suite.
       6  
       7  The GNU MP Library test suite is free software; you can redistribute it
       8  and/or modify it under the terms of the GNU General Public License as
       9  published by the Free Software Foundation; either version 3 of the License,
      10  or (at your option) any later version.
      11  
      12  The GNU MP Library test suite is distributed in the hope that it will be
      13  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
      15  Public License for more details.
      16  
      17  You should have received a copy of the GNU General Public License along with
      18  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
      19  
      20  
      21  #include <stdlib.h>
      22  #include <stdio.h>
      23  
      24  #include "gmp-impl.h"
      25  #include "tests.h"
      26  
      27  /* Main file is expected to define mpn_toomMN_mul,
      28   * mpn_toomMN_mul_itch, MIN_AN, MIN_BN(an), MAX_BN(an) and then
      29   * include this file. */
      30  
      31  /* Sizes are up to 2^SIZE_LOG limbs */
      32  #ifndef SIZE_LOG
      33  #define SIZE_LOG 10
      34  #endif
      35  
      36  #ifndef COUNT
      37  #define COUNT 2000
      38  #endif
      39  
      40  #define MAX_AN (1L << SIZE_LOG)
      41  
      42  #ifndef MAX_BN
      43  #define MAX_BN(an) (an)
      44  #endif
      45  
      46  /* For general toomMN_mul, we need
      47   *
      48   * MIN_BN(an) = N + floor(((N-1)*an + M - N)/M)
      49   *
      50   * MAX_BN(an) = floor(N*(an-1)/(M-1)) - N + 1
      51   */
      52  
      53  int
      54  main (int argc, char **argv)
      55  {
      56    mp_ptr ap, bp, refp, pp, scratch;
      57    int count = COUNT;
      58    int test;
      59    gmp_randstate_ptr rands;
      60    TMP_DECL;
      61    TMP_MARK;
      62  
      63    TESTS_REPS (count, argv, argc);
      64  
      65    tests_start ();
      66    rands = RANDS;
      67  
      68    ap = TMP_ALLOC_LIMBS (MAX_AN);
      69    bp = TMP_ALLOC_LIMBS (MAX_BN(MAX_AN));
      70    refp = TMP_ALLOC_LIMBS (MAX_AN + MAX_BN(MAX_AN));
      71    pp = 1+TMP_ALLOC_LIMBS (MAX_AN + MAX_BN(MAX_AN)+2);
      72    scratch
      73      = 1+TMP_ALLOC_LIMBS (mpn_toomMN_mul_itch (MAX_AN, MAX_BN(MAX_AN))
      74  			 + 2);
      75  
      76    for (test = 0; test < count; test++)
      77      {
      78        unsigned size_min;
      79        unsigned size_range;
      80        mp_size_t an, bn;
      81        mp_size_t itch;
      82        mp_limb_t p_before, p_after, s_before, s_after;
      83  
      84        for (size_min = 1; (1L << size_min) < MIN_AN; size_min++)
      85  	;
      86  
      87        /* We generate an in the MIN_AN <= an <= (1 << size_range). */
      88        size_range = size_min
      89  	+ gmp_urandomm_ui (rands, SIZE_LOG + 1 - size_min);
      90  
      91        an = MIN_AN
      92  	+ gmp_urandomm_ui (rands, (1L << size_range) + 1 - MIN_AN);
      93        bn = MIN_BN(an)
      94  	+ gmp_urandomm_ui (rands, MAX_BN(an) + 1 - MIN_BN(an));
      95  
      96        mpn_random2 (ap, an);
      97        mpn_random2 (bp, bn);
      98        mpn_random2 (pp-1, an + bn + 2);
      99        p_before = pp[-1];
     100        p_after = pp[an + bn];
     101  
     102        itch = mpn_toomMN_mul_itch (an, bn);
     103        ASSERT_ALWAYS (itch <= mpn_toomMN_mul_itch (MAX_AN, MAX_BN(MAX_AN)));
     104        mpn_random2 (scratch-1, itch+2);
     105        s_before = scratch[-1];
     106        s_after = scratch[itch];
     107  
     108        mpn_toomMN_mul (pp, ap, an, bp, bn, scratch);
     109        refmpn_mul (refp, ap, an, bp, bn);
     110        if (pp[-1] != p_before || pp[an + bn] != p_after
     111  	  || scratch[-1] != s_before || scratch[itch] != s_after
     112  	  || mpn_cmp (refp, pp, an + bn) != 0)
     113  	{
     114  	  printf ("ERROR in test %d, an = %d, bn = %d\n",
     115  		  test, (int) an, (int) bn);
     116  	  if (pp[-1] != p_before)
     117  	    {
     118  	      printf ("before pp:"); mpn_dump (pp -1, 1);
     119  	      printf ("keep:   "); mpn_dump (&p_before, 1);
     120  	    }
     121  	  if (pp[an + bn] != p_after)
     122  	    {
     123  	      printf ("after pp:"); mpn_dump (pp + an + bn, 1);
     124  	      printf ("keep:   "); mpn_dump (&p_after, 1);
     125  	    }
     126  	  if (scratch[-1] != s_before)
     127  	    {
     128  	      printf ("before scratch:"); mpn_dump (scratch-1, 1);
     129  	      printf ("keep:   "); mpn_dump (&s_before, 1);
     130  	    }
     131  	  if (scratch[itch] != s_after)
     132  	    {
     133  	      printf ("after scratch:"); mpn_dump (scratch + itch, 1);
     134  	      printf ("keep:   "); mpn_dump (&s_after, 1);
     135  	    }
     136  	  mpn_dump (ap, an);
     137  	  mpn_dump (bp, bn);
     138  	  mpn_dump (pp, an + bn);
     139  	  mpn_dump (refp, an + bn);
     140  
     141  	  abort();
     142  	}
     143      }
     144    TMP_FREE;
     145  
     146    tests_end ();
     147    return 0;
     148  }