tasks a-s

This commit is contained in:
Ingy döt Net 2013-04-10 23:57:08 -07:00
parent 47bf37c096
commit b83f433714
12433 changed files with 156208 additions and 123 deletions

View file

@ -0,0 +1,171 @@
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef uint32_t pint;
typedef uint64_t xint;
typedef unsigned int uint;
#define PRIuPINT PRIu32 /* printf macro for pint */
#define PRIuXINT PRIu64 /* printf macro for xint */
#define MAX_FACTORS 63 /* because 2^64 is too large for xint */
uint8_t *pbits;
#define MAX_PRIME (~(pint)0)
#define MAX_PRIME_SQ 65535U
#define PBITS (MAX_PRIME / 30 + 1)
pint next_prime(pint);
int is_prime(xint);
void sieve(pint);
uint8_t bit_pos[30] = {
0, 1<<0, 0, 0, 0, 0,
0, 1<<1, 0, 0, 0, 1<<2,
0, 1<<3, 0, 0, 0, 1<<4,
0, 1<<5, 0, 0, 0, 1<<6,
0, 0, 0, 0, 0, 1<<7,
};
uint8_t rem_num[] = { 1, 7, 11, 13, 17, 19, 23, 29 };
void init_primes()
{
FILE *fp;
pint s, tgt = 4;
if (!(pbits = malloc(PBITS))) {
perror("malloc");
exit(1);
}
if ((fp = fopen("primebits", "r"))) {
fread(pbits, 1, PBITS, fp);
fclose(fp);
return;
}
memset(pbits, 255, PBITS);
for (s = 7; s <= MAX_PRIME_SQ; s = next_prime(s)) {
if (s > tgt) {
tgt *= 2;
fprintf(stderr, "sieve %"PRIuPINT"\n", s);
}
sieve(s);
}
fp = fopen("primebits", "w");
fwrite(pbits, 1, PBITS, fp);
fclose(fp);
}
int is_prime(xint x)
{
pint p;
if (x > 5) {
if (x < MAX_PRIME)
return pbits[x/30] & bit_pos[x % 30];
for (p = 2; p && (xint)p * p <= x; p = next_prime(p))
if (x % p == 0) return 0;
return 1;
}
return x == 2 || x == 3 || x == 5;
}
void sieve(pint p)
{
unsigned char b[8];
off_t ofs[8];
int i, q;
for (i = 0; i < 8; i++) {
q = rem_num[i] * p;
b[i] = ~bit_pos[q % 30];
ofs[i] = q / 30;
}
for (q = ofs[1], i = 7; i; i--)
ofs[i] -= ofs[i-1];
for (ofs[0] = p, i = 1; i < 8; i++)
ofs[0] -= ofs[i];
for (i = 1; q < PBITS; q += ofs[i = (i + 1) & 7])
pbits[q] &= b[i];
}
pint next_prime(pint p)
{
off_t addr;
uint8_t bits, rem;
if (p > 5) {
addr = p / 30;
bits = bit_pos[ p % 30 ] << 1;
for (rem = 0; (1 << rem) < bits; rem++);
while (pbits[addr] < bits || !bits) {
if (++addr >= PBITS) return 0;
bits = 1;
rem = 0;
}
if (addr >= PBITS) return 0;
while (!(pbits[addr] & bits)) {
rem++;
bits <<= 1;
}
return p = addr * 30 + rem_num[rem];
}
switch(p) {
case 2: return 3;
case 3: return 5;
case 5: return 7;
}
return 2;
}
int decompose(xint n, xint *f)
{
pint p = 0;
int i = 0;
/* check small primes: not strictly necessary */
if (n <= MAX_PRIME && is_prime(n)) {
f[0] = n;
return 1;
}
while (n >= (xint)p * p) {
if (!(p = next_prime(p))) break;
while (n % p == 0) {
n /= p;
f[i++] = p;
}
}
if (n > 1) f[i++] = n;
return i;
}
int main()
{
int i, len;
pint p = 0;
xint f[MAX_FACTORS], po;
init_primes();
for (p = 1; p < 64; p++) {
po = (1LLU << p) - 1;
printf("2^%"PRIuPINT" - 1 = %"PRIuXINT, p, po);
fflush(stdout);
if ((len = decompose(po, f)) > 1)
for (i = 0; i < len; i++)
printf(" %c %"PRIuXINT, i?'x':'=', f[i]);
putchar('\n');
}
return 0;
}

View file

@ -0,0 +1,107 @@
#include <limits.h>
#include <stdio.h>
#include <math.h>
typedef enum{false=0, true=1}bool;
const int max_lint = LONG_MAX;
typedef long long int lint;
#assert sizeof_long_long_int (LONG_MAX>=8) /* XXX */
/* the following line is the only time I have ever required "auto" */
#define FOR(i,iterator) auto bool lambda(i); yield_init = (void *)&lambda; iterator; bool lambda(i)
#define DO {
#define YIELD(x) if(!yield(x))return
#define BREAK return false
#define CONTINUE return true
#define OD CONTINUE; }
/* Warning: _Most_ FOR(,){ } loops _must_ have a CONTINUE as the last statement.
* Otherwise the lambda will return random value from stack, and may terminate early */
typedef void iterator, lint_iterator; /* hint at procedure purpose */
static volatile void *yield_init; /* not thread safe */
#define YIELDS(type) bool (*yield)(type) = yield_init
typedef unsigned int bits;
#define ELEM(shift, bits) ( (bits >> shift) & 0b1 )
bits cache = 0b0, cached = 0b0;
const lint upb_cache = 8 * sizeof(cache);
lint_iterator decompose(lint); /* forward declaration */
bool is_prime(lint n){
bool has_factor = false, out = true;
/* for factor in decompose(n) do */
FOR(lint factor, decompose(n)){
if( has_factor ){ out = false; BREAK; }
has_factor = true;
CONTINUE;
}
return out;
}
bool is_prime_cached (lint n){
lint half_n = n / 2 - 2;
if( half_n <= upb_cache){
/* dont cache the initial four, nor the even numbers */
if (ELEM(half_n,cached)){
return ELEM(half_n,cache);
} else {
bool out = is_prime(n);
cache = cache | out << half_n;
cached = cached | 0b1 << half_n;
return out;
}
} else {
return is_prime(n);
}
}
lint_iterator primes (){
YIELDS(lint);
YIELD(2);
lint n = 3;
while( n < max_lint - 2 ){
YIELD(n);
n += 2;
while( n < max_lint - 2 && ! is_prime_cached(n) ){
n += 2;
}
}
}
lint_iterator decompose (lint in_n){
YIELDS(lint);
lint n = in_n;
/* for p in primes do */
FOR(lint p, primes()){
if( p*p > n ){
BREAK;
} else {
while( n % p == 0 ){
YIELD(p);
n = n / p;
}
}
CONTINUE;
}
if( n > 1 ){
YIELD(n);
}
}
main(){
FOR(lint m, primes()){
lint p = powl(2, m) - 1;
printf("2**%lld-1 = %lld, with factors:",m,p);
FOR(lint factor, decompose(p)){
printf(" %lld",factor);
fflush(stdout);
CONTINUE;
}
printf("\n",m);
if( m >= 59 )BREAK;
CONTINUE;
}
}

View file

@ -0,0 +1,73 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint32_t pint;
typedef uint64_t xint;
typedef unsigned int uint;
int is_prime(xint);
inline int next_prime(pint p)
{
if (p == 2) return 3;
for (p += 2; p > 1 && !is_prime(p); p += 2);
if (p == 1) return 0;
return p;
}
int is_prime(xint n)
{
# define NCACHE 256
# define S (sizeof(uint) * 2)
static uint cache[NCACHE] = {0};
pint p = 2;
int ofs, bit = -1;
if (n < NCACHE * S) {
ofs = n / S;
bit = 1 << ((n & (S - 1)) >> 1);
if (cache[ofs] & bit) return 1;
}
do {
if (n % p == 0) return 0;
if (p * p > n) break;
} while ((p = next_prime(p)));
if (bit != -1) cache[ofs] |= bit;
return 1;
}
int decompose(xint n, pint *out)
{
int i = 0;
pint p = 2;
while (n > p * p) {
while (n % p == 0) {
out[i++] = p;
n /= p;
}
if (!(p = next_prime(p))) break;
}
if (n > 1) out[i++] = n;
return i;
}
int main()
{
int i, j, len;
xint z;
pint out[100];
for (i = 2; i < 64; i = next_prime(i)) {
z = (1ULL << i) - 1;
printf("2^%d - 1 = %llu = ", i, z);
fflush(stdout);
len = decompose(z, out);
for (j = 0; j < len; j++)
printf("%u%s", out[j], j < len - 1 ? " x " : "\n");
}
return 0;
}