/************************************************************************ * HELPERS * ************************************************************************/ void *sieve_range(void *arg) { bool (*flip_fun)(const int, struct SquareTerms *); struct IntNode *cand; struct SieveArg *params = (struct SieveArg *) arg; struct IntNode **prv = ¶ms->head; const int until = params->until; /* * case where x will be largest corresponds to the third flipping * quadratic: * * 3x² - y² = n where x > y * * when y = one less than x = (x - 1) * * substituting: * * 3x² - (x - 1)² = n * 2x² + 2x - (1 + n) = 0 * * from quadratic equation: * x_max = (-1 + sqrt(3 + 2n)) / 2 * * add one to ensure that range of x includes x_max: */ const int LENGTH_TERMS = ((((int) sqrtf((float) ((until * 2) + 3))) - 1) / 2) + 1; int x_sq_3[LENGTH_TERMS]; int x_sq_4[LENGTH_TERMS]; for (int x = 2, x_sq; x < LENGTH_TERMS; ++x) { x_sq = x * x; x_sq_3[x] = 3 * x_sq; x_sq_4[x] = 4 * x_sq; } struct SquareTerms SQ_TERMS = { .X_SQ_3 = x_sq_3, .X_SQ_4 = x_sq_4 }; for (int n = params->start; n < until; n+=2) { flip_fun = FLIP_MAP[n % 60]; if (flip_fun && flip_fun(n, &SQ_TERMS)) { cand = handle_malloc(sizeof(struct IntNode)); cand->val = n; *prv = cand; prv = &cand->nxt; } } params->last = cand; pthread_exit(NULL); }
struct IntNode *prime_sieve(const int sup) { struct IntNode *primes = handle_malloc(sizeof(struct IntNode)); struct IntNode *num; struct IntNode *prv; struct IntNode *prime; int prime_val; num = primes; num->val = 2; /* initialize sieve to all odd numbers between '2' and input supremum 'sup' */ for (int odd = 3; odd < sup; odd += 2) { num->nxt = handle_malloc(sizeof(struct IntNode)); num = num->nxt; num->val = odd; } num->nxt = NULL; for (prime = primes->nxt; prime != NULL; prime = prime->nxt) { prime_val = prime->val; prv = prime; num = prv->nxt; while (num != NULL) { if (num->val % prime_val == 0) { prv->nxt = num->nxt; free(num); num = prv->nxt; } else { prv = num; num = num->nxt; } } } return primes; }
struct IntNode *atkin_sieve(const int sup) { pthread_t sieve_threads[4]; struct SieveArg args[4]; struct IntNode *primes; struct IntNode *prime; struct IntNode *prev; struct IntNode *cand; int q_i; int start; int prime_val; int sq_val; int mult_val; int mult_sq; const int DELTA = (sup - 13) / 4; /* initialize result list 'primes' with first 5 prime numbers */ primes = handle_malloc(sizeof(struct IntNode) * 5); prime = primes; prime->val = 2; prime->nxt = prime + 1; ++prime; prime->val = 3; prime->nxt = prime + 1; ++prime; prime->val = 5; prime->nxt = prime + 1; ++prime; prime->val = 7; prime->nxt = prime + 1; ++prime; prime->val = 11; /* split range into 4 intervals and sieve in parallel */ for (q_i = 0, start = 13; q_i < 3; ++q_i) { args[q_i].start = start; start += DELTA; args[q_i].until = start; handle_pthread_create(&sieve_threads[q_i], NULL, sieve_range, (void *) &args[q_i]); } /* ensure final sieve interval ends at input supremum 'sup' */ args[3].start = start; args[3].until = sup; handle_pthread_create(&sieve_threads[3], NULL, sieve_range, (void *) &args[3]); /* await threads, join candidates and append to 'primes' */ handle_pthread_join(sieve_threads[0], NULL); prime->nxt = args[0].head; cand = args[0].last; for (q_i = 1; q_i < 4; ++q_i) { handle_pthread_join(sieve_threads[q_i], NULL); cand->nxt = args[q_i].head; cand = args[q_i].last; } cand->nxt = NULL; const int SQ_CUTOFF = cand->val; /* starting at node 7... */ --prime; prime_val = 7; sq_val = 49; while (1) { prev = prime; cand = prime->nxt; mult_sq = sq_val; while (1) { if (cand->val < mult_sq) { prev = cand; cand = cand->nxt; continue; } if (cand->val == mult_sq) { prev->nxt = cand->nxt; free(cand); cand = prev->nxt; } else { prev = cand; cand = cand->nxt; } mult_sq += sq_val; if (mult_sq > SQ_CUTOFF) break; } prime = prime->nxt; prime_val = prime->val; sq_val = prime_val * prime_val; if (sq_val > SQ_CUTOFF) return primes; } }
static void _pascal parsemail(char *keyword, char *value) { char *s = value; char *e = NULL; AREA *t; AREA a; check(username); memset(&a,0,sizeof a); switch (tolower(*keyword)) { /* one letter is enough for now */ default : case 'f' : a.msgtype = FIDO; break; case 'q' : a.msgtype = QUICK; break; } while (*s && isspace(*s)) s++; if (!*s) return; switch (tolower(*s)) { /* one letter is enough */ case 'n' : a.news = 1; break; case 'u' : a.uucp = 1; break; case 'm' : a.netmail = 1; break; case 'e' : a.echomail = 1; break; case 'l' : default : a.local = 1; break; } while (*s && !isspace(*s)) s++; /* skip the rest */ while (*s && isspace(*s)) s++; if (!*s) return; if (*s != '\"') { while (*s && !isspace(*s)) { switch (tolower(*s)) { case 'p' : a.priv = 1; break; case 'h' : a.hold = 1; break; case 'd' : a.direct = 1; break; case 'c' : a.crash = 1; break; case 'k' : a.killsent = 1; break; case 0 : return; } s++; } while (*s && isspace(*s)) s++; if (!*s) return; } if ((e = strchr(++s,'\"')) == NULL) return; *e++ = '\0'; a.description = strdup(s); s = e; while (*s && isspace(*s)) s++; if (!*s) { free(a.description); return; } if ((e = strchr(s,' ')) == NULL) e = strchr(s,'\t'); if (e == NULL) e = s; else *e++ = '\0'; while (*s && isspace(*s)) s++; if (!*s) { free(a.description); return; } switch (a.msgtype) { default : case FIDO : a.path = strdup(strlwr(s)); break; case QUICK : a.board = atoi(s); break; } if (a.msgtype == FIDO) { if (chdir(a.path) != 0) { free(a.path); free(a.description); return; } else setcwd(home); } if (a.echomail) { s = e; while (*s && isspace(*s)) s++; if (s && *s) a.tag = strdup(s); else a.tag = NULL; } for (area = 0; area < areas; area++) { /* this is a sneaky use of the ternary operator */ if (((a.msgtype == QUICK) && (arealist[area].msgtype == QUICK))? (a.board == arealist[area].board): (strcmp(a.path,arealist[area].path)==0)) { arealist[area].priv |= a.priv; arealist[area].hold |= a.hold; arealist[area].direct |= a.direct; arealist[area].crash |= a.crash; arealist[area].killsent |= a.killsent; arealist[area].news |= a.news; arealist[area].echomail |= a.echomail; arealist[area].uucp |= a.uucp; arealist[area].netmail |= a.netmail; arealist[area].local |= a.local; if (arealist[area].description == NULL) arealist[area].description = a.description; else if (a.description) free(a.description); if (arealist[area].tag == NULL) arealist[area].tag = a.tag; else if (a.tag) free(a.tag); if ((a.msgtype == FIDO) && (a.path)) free(a.path); return; } } areas++; area = areas - 1; check(username); if (arealist == NULL) arealist = handle_malloc(areas * sizeof(struct _area)); else { check(username); arealist = handle_realloc(arealist, areas * sizeof(struct _area)); check(username); } check(username); if (arealist == NULL) outamemory(); check(username); checkp(arealist); t = arealist + area; checkp(t); checkp(arealist); check(username); *t = a; checkp(t); check(username); }