blob: b131a9e47c8462ca7836b917d9f658e7a557ea7c [file] [log] [blame]
Austin Schuhdace2a62020-08-18 10:56:48 -07001/*
2
3Copyright 2013-2015, 2018 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#include "testutils.h"
21
22/* Include it here, so we we could tweak, e.g., how MPZ_REALLOC
23 works. */
24#include "../mini-gmp.c"
25#include "../mini-mpq.c"
26
27static size_t total_alloc = 0;
28
29/* Custom memory allocation to track memory usage, and add a small red
30 zone.
31
32 About alignment: In general, getting a block from malloc, and
33 incrementing it by sizeof(size_t), like we do here, might give a
34 pointer which is not properly aligned for all types. But the
35 largest type we allocate space for is unsigned long (mp_limb_t),
36 which shouldn't have stricter alignment requirements than
37 size_t. */
38
39static unsigned char block_end[8] =
40 { 0x7c, 0x37, 0xd6, 0x12, 0xa8, 0x6c, 0x01, 0xd1 };
41
42static void *
43block_init (size_t *block, size_t size)
44{
45 char *p;
46 *block++ = size;
47
48 p = (char *) block;
49 memcpy (p + size, block_end, sizeof(block_end));
50
51 total_alloc += size;
52 return p;
53}
54
55/* Check small redzone, return pointer to malloced block. */
56static size_t *
57block_check (void *p)
58{
59 size_t *block = (size_t *) p - 1;
60 size_t size = block[0];
61
62 if (memcmp ((char *)p + size, block_end, sizeof(block_end)) != 0)
63 {
64 fprintf (stderr, "red zone overwritten.\n");
65 abort ();
66 }
67 total_alloc -= size;
68 return block;
69}
70
71static void *
72tu_alloc (size_t size)
73{
74 size_t *block = (size_t *) malloc (sizeof(size_t) + size + sizeof(block_end));
75 if (!block)
76 {
77 fprintf (stderr, "Virtual memory exhausted.\n");
78 abort ();
79 }
80
81 return block_init (block, size);
82}
83
84static void *
85tu_realloc (void *p, size_t old_size, size_t new_size)
86{
87 size_t *block = block_check (p);
88 block = (size_t *) realloc (block, sizeof(size_t) + new_size + sizeof(block_end));
89 if (!block)
90 {
91 fprintf (stderr, "Virtual memory exhausted.\n");
92 abort ();
93 }
94
95 return block_init (block, new_size);
96}
97
98static void
99tu_free (void *p, size_t old_size)
100{
101 free (block_check (p));
102}
103
104/* Free memory allocated via mini-gmp allocation function. */
105void
106testfree (void *p)
107{
108 void (*freefunc) (void *, size_t);
109 mp_get_memory_functions (NULL, NULL, &freefunc);
110
111 freefunc (p, 0);
112}
113
114int
115main (int argc, char **argv)
116{
117 hex_random_init ();
118
119 mp_set_memory_functions (tu_alloc, tu_realloc, tu_free);
120
121 /* Currently, t-comb seems to be the only program accepting any
122 arguments. It might make sense to parse common arguments here. */
123 testmain (argc, argv);
124
125 if (total_alloc != 0)
126 {
127 fprintf (stderr, "Memory leaked: %lu bytes.\n",
128 (unsigned long) total_alloc);
129 abort ();
130 }
131 return 0;
132}
133
134void
135testhalves (int count, void (*tested_fun) (int))
136{
137 void (*freefunc) (void *, size_t);
138 void *(*reallocfunc) (void *, size_t, size_t);
139 void *(*allocfunc) (size_t);
140 size_t initial_alloc;
141
142 mp_get_memory_functions (&allocfunc, &reallocfunc, &freefunc);
143 initial_alloc = total_alloc;
144 (*tested_fun) (count / 2);
145 if (initial_alloc != total_alloc)
146 {
147 fprintf (stderr, "First half, memory leaked: %lu bytes.\n",
148 (unsigned long) total_alloc - initial_alloc);
149 abort ();
150 }
151 mp_set_memory_functions (NULL, NULL, NULL);
152 (*tested_fun) (count / 2);
153 mp_set_memory_functions (allocfunc, reallocfunc, freefunc);
154}
155
156void
157dump (const char *label, const mpz_t x)
158{
159 char *buf = mpz_get_str (NULL, 16, x);
160 fprintf (stderr, "%s: %s\n", label, buf);
161 testfree (buf);
162}
163
164void
165mpz_set_str_or_abort (mpz_ptr z, const char *str, int base)
166{
167 if (mpz_set_str (z, str, base) != 0)
168 {
169 fprintf (stderr, "ERROR: mpz_set_str failed\n");
170 fprintf (stderr, " str = \"%s\"\n", str);
171 fprintf (stderr, " base = %d\n", base);
172 abort();
173 }
174}
175
176int
177mpz_lucas_mod (mpz_t V, mpz_t Qk, long Q,
178 mp_bitcnt_t b0, const mpz_t n)
179{
180 return gmp_lucas_mod (V, Qk, Q, b0, n);
181}