Add primality testing and next_prime()/prev_prime()

This commit is contained in:
Bruce Hill 2024-08-18 15:22:51 -04:00
parent f4b04a1b8c
commit a49870f810
6 changed files with 69 additions and 4 deletions

View File

@ -330,6 +330,33 @@ public Int_t Int$from_text(CORD text) {
return Int$from_mpz(i);
}
public bool Int$is_prime(Int_t x, Int_t reps)
{
mpz_t p;
mpz_init_set_int(p, x);
if (Int$compare(&reps, (Int_t[1]){I_small(9999)}, &$Int) > 0)
fail("Number of prime-test repetitions should not be above 9999");
int reps_int = Int_to_Int32(reps, false);
return (mpz_probab_prime_p(p, reps_int) != 0);
}
public Int_t Int$next_prime(Int_t x)
{
mpz_t p;
mpz_init_set_int(p, x);
mpz_nextprime(p, p);
return Int$from_mpz(p);
}
public Int_t Int$prev_prime(Int_t x)
{
mpz_t p;
mpz_init_set_int(p, x);
if (mpz_prevprime(p, p) == 0)
fail("There is no prime number before %r", Int$as_text(&x, false, &$Int));
return Int$from_mpz(p);
}
public const TypeInfo $Int = {
.size=sizeof(Int_t),
.align=__alignof__(Int_t),

View File

@ -117,6 +117,9 @@ Int_t Int$slow_bit_xor(Int_t x, Int_t y);
Int_t Int$slow_negative(Int_t x);
Int_t Int$slow_negated(Int_t x);
Int_t Int$abs(Int_t x);
bool Int$is_prime(Int_t x, Int_t reps);
Int_t Int$next_prime(Int_t x);
Int_t Int$prev_prime(Int_t x);
extern const TypeInfo $Int;

View File

@ -200,7 +200,7 @@ static CORD compile_lvalue(env_t *env, ast_t *ast)
ast_t *subject = ast->tag == Index ? Match(ast, Index)->indexed : Match(ast, FieldAccess)->fielded;
code_err(subject, "This is an immutable value, you can't assign to it");
} else {
code_err(ast, "This is a value of type %T and can't be assigned to", get_type(env, ast));
code_err(ast, "This is a value of type %T and can't be used as an assignment target", get_type(env, ast));
}
}
@ -209,7 +209,7 @@ static CORD compile_lvalue(env_t *env, ast_t *ast)
type_t *container_t = get_type(env, index->indexed);
if (!index->index && container_t->tag == PointerType) {
if (Match(container_t, PointerType)->is_optional)
code_err(index->indexed, "This pointer might be null, so it can't be safely assigned to");
code_err(index->indexed, "This pointer might be null, so it can't be safely used as an assignment target");
return compile(env, ast);
}
container_t = value_type(container_t);

View File

@ -110,6 +110,9 @@ env_t *new_compilation_unit(CORD *libname)
{"abs", "Int$abs", "func(x:Int)->Int"},
{"sqrt", "Int$sqrt", "func(x:Int)->Int"},
{"power", "Int$power", "func(base:Int,exponent:Int)->Int"},
{"is_prime", "Int$is_prime", "func(x:Int,reps=50)->Bool"},
{"next_prime", "Int$next_prime", "func(x:Int)->Int"},
{"prev_prime", "Int$prev_prime", "func(x:Int)->Int"},
)},
{"Int64", Type(IntType, .bits=TYPE_IBITS64), "Int64_t", "$Int64", TypedArray(ns_entry_t,
{"format", "Int64$format", "func(i:Int64, digits=0)->Text"},

View File

@ -930,10 +930,13 @@ ast_t *parse_comprehension_suffix(parse_ctx_t *ctx, ast_t *expr) {
expect_str(ctx, start, &pos, "in", "I expected an 'in' for this 'for'");
ast_t *iter = expect(ctx, start, &pos, parse_expr, "I expected an iterable value for this 'for'");
whitespace(&pos);
const char *next_pos = pos;
whitespace(&next_pos);
ast_t *filter = NULL;
if (match_word(&pos, "if"))
if (match_word(&next_pos, "if")) {
pos = next_pos;
filter = expect(ctx, pos-2, &pos, parse_expr, "I expected a condition for this 'if'");
}
return NewAST(ctx->file, start, pos, Comprehension, .expr=expr, .vars=vars, .iter=iter, .filter=filter);
}

View File

@ -82,3 +82,32 @@ func main():
//! n=$n, d=$d:
>> (n/d)*d + (n mod d) == n
= yes
>> 0:next_prime()
= 2
>> 7:next_prime()
= 11
>> 11:prev_prime()
= 7
>> (and) p:is_prime() for p in [
2, 3, 5, 7,
137372146048179869781170214707,
811418847921670560768224995279,
292590241572454328697048860273,
754893741683930091960170890717,
319651808258437169510475301537,
323890224935694708770556249787,
507626552342376235511933571091,
548605069630614185274710840981,
121475876690852432982324195553,
771958616175795150904761471637,
]
= yes
>> (or) p:is_prime() for p in [
-1, 0, 1, 4, 6,
137372146048179869781170214707*2,
811418847921670560768224995279*3,
292590241572454328697048860273*754893741683930091960170890717,
]
= no