1 /* Factoring of uintmax_t numbers. Generation of needed tables.
3 Contributed to the GNU project by Torbjörn Granlund and Niels Möller
4 Contains code from GNU MP.
6 Copyright 2012-2023 Free Software Foundation, Inc.
8 This program is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 3 of the License, or (at your option) any later
13 This program is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along with
18 this program. If not, see https://www.gnu.org/licenses/. */
22 #include <attribute.h>
32 /* Deactivate "rpl_"-prefixed definitions of these symbols. */
38 /* An unsigned type that is no narrower than 32 bits and no narrower
39 than unsigned int. It's best to make it as wide as possible.
40 For GCC 4.6 and later, use a heuristic to guess whether unsigned
41 __int128 works on your platform. If this heuristic does not work
42 for you, please report a bug; in the meantime compile with, e.g.,
43 -Dwide_uint='unsigned __int128' to override the heuristic. */
45 # if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) && ULONG_MAX >> 31 >> 31 >> 1 != 0
46 typedef unsigned __int128 wide_uint
;
48 typedef uintmax_t wide_uint
;
55 wide_uint pinv
; /* Inverse mod b = 2^{bitsize of wide_uint} */
56 wide_uint lim
; /* floor ((wide_uint) -1 / p) */
63 wide_uint x
= 0xf5397db1 >> (4 * ((a
/ 2) & 0x7));
66 wide_uint y
= 2 * x
- x
* x
* a
;
74 process_prime (struct prime
*info
, unsigned p
)
78 info
->pinv
= binvert (p
);
83 print_wide_uint (wide_uint n
, int nesting
, unsigned wide_uint_bits
)
85 /* Number of bits per integer literal. 8 is too many, because
86 uintmax_t is 32 bits on some machines so we cannot shift by 32 bits.
88 int hex_digits_per_literal
= 7;
89 int bits_per_literal
= hex_digits_per_literal
* 4;
91 unsigned remainder
= n
& ((1 << bits_per_literal
) - 1);
95 int needs_parentheses
= n
>> bits_per_literal
>> bits_per_literal
!= 0;
96 if (needs_parentheses
)
98 print_wide_uint (n
>> bits_per_literal
, nesting
+ 1, wide_uint_bits
);
99 if (needs_parentheses
)
100 printf (")\n%*s", nesting
+ 3, "");
101 printf (" << %d | ", bits_per_literal
);
105 printf ("(uintmax_t) ");
106 hex_digits_per_literal
107 = ((wide_uint_bits
- 1) % bits_per_literal
) % 4 + 1;
110 printf ("0x%0*xU", hex_digits_per_literal
, remainder
);
114 output_primes (const struct prime
*primes
, unsigned nprimes
)
120 /* Compute wide_uint_bits by repeated shifting, rather than by
121 multiplying sizeof by CHAR_BIT, as this works even if the
122 wide_uint representation has holes. */
123 unsigned wide_uint_bits
= 0;
125 for (wide_uint_bits
= 0; mask
; wide_uint_bits
++)
128 puts ("/* Generated file -- DO NOT EDIT */\n");
129 printf ("#define WIDE_UINT_BITS %u\n", wide_uint_bits
);
131 for (i
= 0, p
= 2; i
< nprimes
; i
++)
133 unsigned int d8
= i
+ 8 < nprimes
? primes
[i
+ 8].p
- primes
[i
].p
: 0xff;
134 if (255 < d8
) /* this happens at 668221 */
136 printf ("P (%u, %u,\n (", primes
[i
].p
- p
, d8
);
137 print_wide_uint (primes
[i
].pinv
, 0, wide_uint_bits
);
138 printf ("),\n UINTMAX_MAX / %u)\n", primes
[i
].p
);
142 printf ("\n#undef FIRST_OMITTED_PRIME\n");
144 /* Find next prime */
148 for (i
= 0, is_prime
= 1; is_prime
; i
++)
150 if (primes
[i
].p
* primes
[i
].p
> p
)
152 if (p
* primes
[i
].pinv
<= primes
[i
].lim
)
161 printf ("#define FIRST_OMITTED_PRIME %u\n", p
);
168 void *p
= malloc (s
);
172 fprintf (stderr
, "Virtual memory exhausted.\n");
177 main (int argc
, char **argv
)
184 struct prime
*prime_list
;
189 fprintf (stderr
, "Usage: %s LIMIT\n"
190 "Produces a list of odd primes <= LIMIT\n", argv
[0]);
193 limit
= atoi (argv
[1]);
201 size
= (limit
- 1) / 2;
202 /* sieve[i] represents 3+2*i */
203 sieve
= xalloc (size
);
204 memset (sieve
, 1, size
);
206 prime_list
= xalloc (size
* sizeof (*prime_list
));
209 for (i
= 0; i
< size
;)
211 unsigned p
= 3 + 2 * i
;
214 process_prime (&prime_list
[nprimes
++], p
);
216 for (j
= (p
* p
- 3) / 2; j
< size
; j
+= p
)
219 while (++i
< size
&& sieve
[i
] == 0)
223 output_primes (prime_list
, nprimes
);
228 if (ferror (stdout
) + fclose (stdout
))
230 fprintf (stderr
, "write error: %s\n", strerror (errno
));