mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 06:38:47 +00:00
big: Add int_is_square.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
@echo off
|
@echo off
|
||||||
odin run . -vet -o:size
|
odin run . -vet
|
||||||
: -o:size
|
: -o:size
|
||||||
:odin build . -build-mode:shared -show-timings -o:minimal -no-bounds-check -define:MATH_BIG_EXE=false && python test.py -fast-tests
|
:odin build . -build-mode:shared -show-timings -o:minimal -no-bounds-check -define:MATH_BIG_EXE=false && python test.py -fast-tests
|
||||||
:odin build . -build-mode:shared -show-timings -o:size -no-bounds-check -define:MATH_BIG_EXE=false && python test.py -fast-tests
|
:odin build . -build-mode:shared -show-timings -o:size -no-bounds-check -define:MATH_BIG_EXE=false && python test.py -fast-tests
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -861,7 +861,12 @@ internal_int_mod :: proc(remainder, numerator, denominator: ^Int, allocator := c
|
|||||||
|
|
||||||
return #force_inline internal_add(remainder, remainder, numerator, allocator);
|
return #force_inline internal_add(remainder, remainder, numerator, allocator);
|
||||||
}
|
}
|
||||||
internal_mod :: proc{ internal_int_mod, };
|
|
||||||
|
internal_int_mod_digit :: proc(numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
|
||||||
|
return internal_int_divmod_digit(nil, numerator, denominator, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_mod :: proc{ internal_int_mod, internal_int_mod_digit};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
remainder = (number + addend) % modulus.
|
remainder = (number + addend) % modulus.
|
||||||
@@ -1170,6 +1175,67 @@ internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison:
|
|||||||
internal_compare_magnitude :: proc { internal_int_compare_magnitude, };
|
internal_compare_magnitude :: proc { internal_int_compare_magnitude, };
|
||||||
internal_cmp_mag :: internal_compare_magnitude;
|
internal_cmp_mag :: internal_compare_magnitude;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if remainders are possible squares - fast exclude non-squares.
|
||||||
|
|
||||||
|
Returns `true` if `a` is a square, `false` if not.
|
||||||
|
Assumes `a` not to be `nil` and to have been initialized.
|
||||||
|
*/
|
||||||
|
internal_int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (square: bool, err: Error) {
|
||||||
|
context.allocator = allocator;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Default to Non-square :)
|
||||||
|
*/
|
||||||
|
square = false;
|
||||||
|
|
||||||
|
if internal_is_negative(a) { return; }
|
||||||
|
if internal_is_zero(a) { return; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
First check mod 128 (suppose that _DIGIT_BITS is at least 7).
|
||||||
|
*/
|
||||||
|
if _private_int_rem_128[127 & a.digit[0]] == 1 { return; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
Next check mod 105 (3*5*7).
|
||||||
|
*/
|
||||||
|
c: DIGIT;
|
||||||
|
c, err = internal_mod(a, 105);
|
||||||
|
if _private_int_rem_128[c] == 1 { return; }
|
||||||
|
|
||||||
|
t := &Int{};
|
||||||
|
defer destroy(t);
|
||||||
|
|
||||||
|
set(t, 11 * 13 * 17 * 19 * 23 * 29 * 31) or_return;
|
||||||
|
internal_mod(t, a, t) or_return;
|
||||||
|
|
||||||
|
r: u64;
|
||||||
|
r, err = internal_int_get(t, u64);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check for other prime modules, note it's not an ERROR but we must
|
||||||
|
free "t" so the easiest way is to goto LBL_ERR. We know that err
|
||||||
|
is already equal to MP_OKAY from the mp_mod call
|
||||||
|
*/
|
||||||
|
if (1 << (r % 11) & 0x5C4) != 0 { return; }
|
||||||
|
if (1 << (r % 13) & 0x9E4) != 0 { return; }
|
||||||
|
if (1 << (r % 17) & 0x5CE8) != 0 { return; }
|
||||||
|
if (1 << (r % 19) & 0x4F50C) != 0 { return; }
|
||||||
|
if (1 << (r % 23) & 0x7ACCA0) != 0 { return; }
|
||||||
|
if (1 << (r % 29) & 0xC2EDD0C) != 0 { return; }
|
||||||
|
if (1 << (r % 31) & 0x6DE2B848) != 0 { return; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
Final check - is sqr(sqrt(arg)) == arg?
|
||||||
|
*/
|
||||||
|
sqrt(t, a) or_return;
|
||||||
|
sqr(t, t) or_return;
|
||||||
|
|
||||||
|
square = internal_cmp_mag(t, a) == 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
========================= Logs, powers and roots ============================
|
========================= Logs, powers and roots ============================
|
||||||
|
|||||||
@@ -2007,6 +2007,27 @@ _private_copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0)) ->
|
|||||||
Tables used by `internal_*` and `_*`.
|
Tables used by `internal_*` and `_*`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
_private_int_rem_128 := [128]DIGIT{
|
||||||
|
0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||||
|
0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||||
|
0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
_private_int_rem_105 := [105]DIGIT{
|
||||||
|
0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
|
||||||
|
0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
|
||||||
|
0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
|
||||||
|
1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
|
||||||
|
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
|
||||||
|
};
|
||||||
|
|
||||||
_private_prime_table := []DIGIT{
|
_private_prime_table := []DIGIT{
|
||||||
0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
|
0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
|
||||||
0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
|
0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
|
||||||
|
|||||||
@@ -556,3 +556,18 @@ int_compare_magnitude :: proc(a, b: ^Int, allocator := context.allocator) -> (re
|
|||||||
|
|
||||||
return #force_inline internal_cmp_mag(a, b), nil;
|
return #force_inline internal_cmp_mag(a, b), nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if remainders are possible squares - fast exclude non-squares.
|
||||||
|
|
||||||
|
Returns `true` if `a` is a square, `false` if not.
|
||||||
|
Assumes `a` not to be `nil` and to have been initialized.
|
||||||
|
*/
|
||||||
|
int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (square: bool, err: Error) {
|
||||||
|
assert_if_nil(a);
|
||||||
|
context.allocator = allocator;
|
||||||
|
|
||||||
|
internal_clear_if_uninitialized(a) or_return;
|
||||||
|
|
||||||
|
return #force_inline internal_int_is_square(a);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user