1/* Test for sqrlo function.
2
3Copyright 2009, 2015 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the 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/* Sizes are up to 2^SIZE_LOG limbs */
28#ifndef SIZE_LOG
29#define SIZE_LOG 10
30#endif
31
32#ifndef COUNT
33#define COUNT 10000
34#endif
35
36#define MAX_N (1L << SIZE_LOG)
37#define MIN_N (1)
38
39int
40main (int argc, char **argv)
41{
42  mp_ptr ap, refp, pp, scratch;
43  int count = COUNT;
44  int test;
45  gmp_randstate_ptr rands;
46  TMP_DECL;
47  TMP_MARK;
48
49  TESTS_REPS (count, argv, argc);
50
51  tests_start ();
52  rands = RANDS;
53
54#define mpn_sqrlo_itch(n) (0)
55
56  ap = TMP_ALLOC_LIMBS (MAX_N);
57  refp = TMP_ALLOC_LIMBS (MAX_N * 2);
58  pp = 1+TMP_ALLOC_LIMBS (MAX_N + 2);
59  scratch
60    = 1+TMP_ALLOC_LIMBS (mpn_sqrlo_itch (MAX_N) + 2);
61
62  for (test = 0; test < count; test++)
63    {
64      unsigned size_min;
65      unsigned size_range;
66      mp_size_t n;
67      mp_size_t itch;
68      mp_limb_t p_before, p_after, s_before, s_after;
69
70      for (size_min = 1; (1L << size_min) < MIN_N; size_min++)
71	;
72
73      /* We generate an in the MIN_N <= n <= (1 << size_range). */
74      size_range = size_min
75	+ gmp_urandomm_ui (rands, SIZE_LOG + 1 - size_min);
76
77      n = MIN_N
78	+ gmp_urandomm_ui (rands, (1L << size_range) + 1 - MIN_N);
79
80      mpn_random2 (ap, n);
81      mpn_random2 (pp-1, n + 2);
82      p_before = pp[-1];
83      p_after = pp[n];
84
85      itch = mpn_sqrlo_itch (n);
86      ASSERT_ALWAYS (itch <= mpn_sqrlo_itch (MAX_N));
87      mpn_random2 (scratch-1, itch+2);
88      s_before = scratch[-1];
89      s_after = scratch[itch];
90
91      mpn_sqrlo (pp, ap, n);
92      mpn_sqr (refp, ap, n);
93      if (pp[-1] != p_before || pp[n] != p_after
94	  || scratch[-1] != s_before || scratch[itch] != s_after
95	  || mpn_cmp (refp, pp, n) != 0)
96	{
97	  printf ("ERROR in test %d, n = %d",
98		  test, (int) n);
99	  if (pp[-1] != p_before)
100	    {
101	      printf ("before pp:"); mpn_dump (pp -1, 1);
102	      printf ("keep:   "); mpn_dump (&p_before, 1);
103	    }
104	  if (pp[n] != p_after)
105	    {
106	      printf ("after pp:"); mpn_dump (pp + n, 1);
107	      printf ("keep:   "); mpn_dump (&p_after, 1);
108	    }
109	  if (scratch[-1] != s_before)
110	    {
111	      printf ("before scratch:"); mpn_dump (scratch-1, 1);
112	      printf ("keep:   "); mpn_dump (&s_before, 1);
113	    }
114	  if (scratch[itch] != s_after)
115	    {
116	      printf ("after scratch:"); mpn_dump (scratch + itch, 1);
117	      printf ("keep:   "); mpn_dump (&s_after, 1);
118	    }
119	  mpn_dump (ap, n);
120	  mpn_dump (pp, n);
121	  mpn_dump (refp, n);
122
123	  abort();
124	}
125    }
126  TMP_FREE;
127  tests_end ();
128  return 0;
129}
130