#!/usr/bin/env rdmd
// Build with: dmd main.d -L-lgmp
import std.stdio;
import std.string;
import core.stdc.string;
import core.stdc.stdlib;
pragma(lib, "gmp"); // for RDMD
// Direct C bindings to GMP
extern (C)
{
struct __mpz_struct
{
int _mp_alloc;
int _mp_size;
void* _mp_d;
}
alias mpz_t = __mpz_struct[1];
alias mpz_ptr = __mpz_struct*;
// GMP function declarations
void __gmpz_init(mpz_ptr);
void __gmpz_clear(mpz_ptr);
int __gmpz_set_str(mpz_ptr, const char*, int);
char* __gmpz_get_str(char*, int, mpz_ptr);
int __gmpz_probab_prime_p(mpz_ptr, int);
void __gmpz_set_ui(mpz_ptr, ulong);
}
// Convenient aliases
alias mpz_init = __gmpz_init;
alias mpz_clear = __gmpz_clear;
alias mpz_set_str = __gmpz_set_str;
alias mpz_get_str = __gmpz_get_str;
alias mpz_probab_prime_p = __gmpz_probab_prime_p;
alias mpz_set_ui = __gmpz_set_ui;
/**
* RAII wrapper for GMP integers
*/
struct MpzWrapper
{
mpz_t value;
this(string str)
{
mpz_init(value.ptr);
if (mpz_set_str(value.ptr, str.toStringz(), 10) != 0)
{
mpz_clear(value.ptr);
throw new Exception("Invalid number format: " ~ str);
}
}
this(ulong num)
{
mpz_init(value.ptr);
mpz_set_ui(value.ptr, num);
}
~this()
{
mpz_clear(value.ptr);
}
// Disable copying to avoid double-free
@disable this(this);
@disable void opAssign(MpzWrapper);
bool isPrime(int rounds = 25) const
{
return mpz_probab_prime_p(cast(mpz_ptr) value.ptr, rounds) > 0;
}
string toString() const
{
char* str = mpz_get_str(null, 10, cast(mpz_ptr) value.ptr);
scope (exit)
free(str);
return str.fromStringz().idup;
}
}
/**
* Simple isPrime functions
*/
bool isPrime(string str, int rounds = 25)
{
try
{
auto n = MpzWrapper(str);
return n.isPrime(rounds);
}
catch (Exception)
{
return false;
}
}
bool isPrime(ulong num, int rounds = 25)
{
auto n = MpzWrapper(num);
return n.isPrime(rounds);
}
void main()
{
writeln("=== D GMP Direct Bindings Prime Testing ===\n");
// Test small numbers
writeln("Testing small numbers:");
foreach (i; 2 .. 21)
{
writefln("%d is %s", i, isPrime(i) ? "prime" : "composite");
}
// Test large numbers from strings
writeln("\nTesting large numbers:");
string[] testNumbers = [
"2", "3", "4", "97", "98", "982451653", // Prime
"982451654", // Composite
"170141183460469231731687303715884105727", // 2^127 - 1 (Mersenne prime)
"170141183460469231731687303715884105728" // 2^127 (composite)
];
foreach (numStr; testNumbers)
{
writefln("%s is %s", numStr, isPrime(numStr) ? "prime" : "composite");
}
// Interactive test
write("\nEnter a number to test: ");
string input = readln().strip();
if (input.length > 0)
{
writefln("%s is %s", input, isPrime(input) ? "prime" : "composite");
}
}