Skip to content

Commit

Permalink
fast_primes_ll 1.30
Browse files Browse the repository at this point in the history
  • Loading branch information
SamuraiDangyo authored Nov 19, 2019
1 parent 394d140 commit bcca1ef
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 47 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ A fast prime number generator in C Language
```fast_primes_ll -h```

### Usage
```fast_primes_ll -nth 10001 # Find out what's the 10,001st prime?```
```fast_primes_ll -nth 10001 # Find out what's the 10,001st prime?```
140 changes: 101 additions & 39 deletions fast_primes_ll.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include "fast_primes_ll.h"

#define NAME "fast_primes_ll"
#define VERSION "1.29"
#define VERSION "1.30"
#define AUTHOR "Toni Helminen"

#define MAX_TOKENS 32
Expand All @@ -34,17 +34,17 @@ typedef struct {
int last_size;
} PRIMES_T;

static char TOKENS[MAX_TOKENS][64] = {{0}};
static int TOKENS_N = 0;
static int TOKENS_I = 0;
static PRIMES_T PRIMES = {0};
static char TOKENS[MAX_TOKENS][64] = {{0}};
static int TOKENS_N = 0;
static int TOKENS_I = 0;
static PRIMES_T PRIMES = {0};

static inline /* <- make me faster! */ int Max(const int a, const int b)
static int Max(const int a, const int b)
{
return a > b ? a : b;
}

static inline int Min(const int a, const int b)
static int Min(const int a, const int b)
{
return a < b ? a : b;
}
Expand All @@ -57,7 +57,9 @@ static bool Equal_strings(const char *a, const char *b)
static BITBOARD Now()
{
static struct timeval t;

FCP_ASSERT(gettimeofday(&t, NULL) == 0)

return 1000 * t.tv_sec + t.tv_usec / 1000;
}

Expand All @@ -69,6 +71,7 @@ static BITBOARD Pps(const BITBOARD nodes, const BITBOARD ms)
static void P(const char *format, ...)
{
va_list a;

va_start(a, format);
vfprintf(stdout, format, a);
va_end(a);
Expand Down Expand Up @@ -112,9 +115,13 @@ static bool Token_is(const char *s)
static void Token_expect(const char *s)
{
if ( ! Token_is(s)) {
P("{ Error: expected: '%s', but_found: '%s' }", s, Token_current());
P("{ # Error");
P(" expected = '%s',", s);
P(" but_found = '%s'", Token_current());
P("}");
exit(0);
}

Token_pop();
}

Expand All @@ -129,20 +136,23 @@ static bool Token_next(const char *s)
static int Token_next_int()
{
int r = 0;

if (Token_ok() && ! Token_is(";")) { // Assume number
r = atoi(TOKENS[TOKENS_I]);
Token_pop();
}

return r;
}

static void Primestable_free_memory()
{
if (PRIMES.size > 0) {
free(PRIMES.primes);
PRIMES.primes = 0;
PRIMES.size = 0;
}
if (PRIMES.size <= 0)
return;

free(PRIMES.primes);
PRIMES.primes = 0;
PRIMES.size = 0;
}

static void Free_memory()
Expand All @@ -153,18 +163,25 @@ static void Free_memory()
static void Primestable_set_size(const int usize /* MB */)
{
BITBOARD size = ULL(usize);

Primestable_free_memory();

size = MAX(size, 1);
size = MIN(size, 1024 * 1024); // 1 PB
size = (1 << 20) * size; // To MB

PRIMES.size = 1;

while (PRIMES.size <= size) // Calculate needed memory in bytes
PRIMES.size <<= 1;
PRIMES.size >>= 1;

PRIMES.size >>= 1;
PRIMES.primes_n = 0;
PRIMES.count = INT(PRIMES.size / sizeof(BITBOARD));
PRIMES.primes = calloc(PRIMES.count, sizeof(BITBOARD));
PRIMES.count = INT(PRIMES.size / sizeof(BITBOARD));
PRIMES.primes = calloc(PRIMES.count, sizeof(BITBOARD));

FCP_ASSERT(PRIMES.primes != NULL) // Make sure there is enough space

Init_primes();
}

Expand Down Expand Up @@ -197,24 +214,25 @@ static void Print_version()
static void Print_help()
{
P("{ # Help");
P("}");
P("");
P(" Usage = fast_primes_ll [OPTION]... [PARAM]...");
P("}\n");

P("{ # General information");
P(" what = fast_primes_ll is a fast prime number generator,");
P(" usage = fast_primes_ll [COMMAND]... [OPTION]...,");
P(" example = fast_primes_ll -nth 100001 # Find out what's the 10,001st prime?");
P("}");
P("");
P(" what = fast_primes_ll is a fast prime number generator,");
P(" usage = fast_primes_ll [COMMAND]... [OPTION]...,");
P(" example = fast_primes_ll -nth 10001 # What's the 10,001st prime?");
P("}\n");

P("{ # Commands");
P(" -h(elp) = This help,");
P(" -v(ersion) = Version,");
P(" -bench = Benchmarking,");
P(" -system = System info,");
P(" -v(ersion) = Show version,");
P(" -bench = Run benchmarks,");
P(" -system = Show system info,");
P(" -is(prime) N = See if N is a prime,");
P(" -nth(prime) N = Print Nth prime,");
P(" -primes N = Print all primes up to N");
P("}");
P("");
P(" -nth(prime) N = Show Nth prime,");
P(" -primes N = Show all primes up to N");
P("}\n");

P("{ # Full source code, please see:");
P(" <https://github.com/SamuraiDangyo/fast_primes_ll/>");
P("}");
Expand All @@ -224,15 +242,19 @@ static void Print_help()
static void Command_isprime()
{
int n = Token_next_int();

P("{ # isprime");
if (Is_prime(n))
P("{ Yes, %i is a prime number. }", n);
P(" result = Yes, %i is a prime number.", n);
else
P("{ No, %i is not a prime number. }", n);
P(" result = No, %i is not a prime number.", n);
P("}");
}

static BITBOARD Nth_prime(const int prime_n)
{
int n = Max(0, prime_n - 1);

if (prime_n == 0)
return 0;
if (n < PRIMES.primes_n)
Expand All @@ -245,7 +267,8 @@ static BITBOARD Nth_prime(const int prime_n)
static void Command_nthprime()
{
int n = Max(0, Token_next_int());
P("{ # Results nth");

P("{ # nthprime");
P(" nth = %i,", n);
P(" prime = %llu", Nth_prime(n));
P("}");
Expand All @@ -254,6 +277,7 @@ static void Command_nthprime()
static void Command_primes()
{
int n = Max(2, Token_next_int());

P("{ # First %i primes generated by %s v%s ", n, NAME, VERSION);
Print_primes(n);
Insert_primes(n);
Expand All @@ -264,28 +288,35 @@ static void Add_prime(const BITBOARD prime)
{
if (PRIMES.primes_n >= PRIMES.count)
Primestable_make_bigger();

PRIMES.primes[PRIMES.primes_n] = prime;
PRIMES.primes_n++;
}

static bool Is_prime_nogen(const BITBOARD prime)
{
int i;

if (prime < 2)
return 1;

for (i = 0; i < PRIMES.primes_n && PRIMES.primes[i] * PRIMES.primes[i] <= prime; i++)
if (prime % PRIMES.primes[i] == 0)
return 0;

return 1;
}

static bool Is_prime(const BITBOARD prime)
{

int i, p;

if (prime <= 1) return 0;

for (i = 0; i < PRIMES.primes_n; i++)
if (PRIMES.primes[i] == prime) return 1;

while (1) {
p = Next_prime();
Add_prime(p);
Expand All @@ -294,6 +325,7 @@ static bool Is_prime(const BITBOARD prime)
if (p > prime)
return 0;
}

return 0;
}

Expand All @@ -305,18 +337,21 @@ static int Last_prime()
static int Next_prime()
{
int candidate = Last_prime() + 1;

while (1)
if (Is_prime_nogen(candidate))
return candidate;
else
candidate++;

FCP_ASSERT(0)
}

static void Insert_primes(const int n)
{
int i = 0;
int l = PRIMES.primes_n;

while (PRIMES.primes_n < n) {
Add_prime(Next_prime());
P(" %i = %llu%s", i + 1 + l, Last_prime(), i + 1 + l < n ? ",": "");
Expand All @@ -327,9 +362,12 @@ static void Insert_primes(const int n)
static void Init_primes()
{
int i;

PRIMES.primes_n = 0;

Add_prime(2);
Add_prime(3);

for (i = 0; i < 10; i++)
Add_prime(Next_prime());
}
Expand All @@ -338,18 +376,22 @@ static void Bench()
{
BITBOARD diff;
BITBOARD start = Now();
P("> Benching ...\n");

P("{ # Benching ...\n}\n");

PRIMES.primes_n = 0;
Add_prime(2);
Add_prime(3);

while (PRIMES.primes_n < 1000000) {
Add_prime(Next_prime());
if (PRIMES.primes_n % 100000 == 0)
P("{ progress = %i%% }", PRIMES.primes_n / 10000);
P("{ Progress = %i%% }", PRIMES.primes_n / 10000);
}

diff = Now() - start;
P("");
P("{ # Benchmarks");

P("\n{ # Benchmarks");
P(" time = %.3fs,", 0.001f * DOUBLE(diff));
P(" primes_per_second = %llu,", Pps(PRIMES.primes_n, diff));
P(" primes = %i", PRIMES.primes_n);
Expand All @@ -360,13 +402,15 @@ static void Print_primes(const int usize)
{
int i;
int n = Min(PRIMES.primes_n, usize);

for (i = 0; i < n; i++)
P(" %i = %llu%s", i + 1, PRIMES.primes[i], i + 1 < n ? ",": "");
}

static void FCP_commands()
{
Token_expect(";");

if (Token_next("v") || Token_next("version"))
Print_version();
else if (Token_next("h") || Token_next("help"))
Expand All @@ -381,33 +425,48 @@ static void FCP_commands()
Command_primes();
else if (Token_next("nthprime") || Token_next("nth"))
Command_nthprime();

Token_expect(";");

if (TOKENS_N <= 2)
Print_help();
}

static void Init_tokens(int argc, char **argv)
{
int i;

Token_reset();
Token_add(";");

for (i = 1 /* skip ./fast_primes_ll */; i < argc; i++) {
if (argv[i][0] == '-' && strlen(argv[i]) > 1)
Token_add(argv[i] + 1);
else
Token_add(argv[i]);
}

Token_add(";");
}

static void Ok()
{
// Yes

FCP_ASSERT(Is_prime(37));
FCP_ASSERT(Is_prime(53));
FCP_ASSERT( ! Is_prime(55));
FCP_ASSERT( ! Is_prime(0));
FCP_ASSERT(Is_prime(2131));


FCP_ASSERT(Nth_prime(17) == 59);
FCP_ASSERT(Nth_prime(34) == 139);

// Nope

FCP_ASSERT( ! Is_prime(55));
FCP_ASSERT( ! Is_prime(0));
FCP_ASSERT( ! Is_prime(100));
FCP_ASSERT( ! Is_prime(2220));
}

static void Go()
Expand All @@ -421,7 +480,10 @@ static void Go()
int main(int argc, char **argv)
{
atexit(Free_memory); // No memory leaks

Init_tokens(argc, argv);

Go();

return EXIT_SUCCESS;
}
Loading

0 comments on commit bcca1ef

Please sign in to comment.