Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
5
Task/Square-form-factorization/00-META.yaml
Normal file
5
Task/Square-form-factorization/00-META.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
category:
|
||||
- Prime Numbers
|
||||
from: http://rosettacode.org/wiki/Square_form_factorization
|
||||
note: Mathematics
|
||||
47
Task/Square-form-factorization/00-TASK.txt
Normal file
47
Task/Square-form-factorization/00-TASK.txt
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
;Task.
|
||||
[[wp:Daniel_Shanks|Daniel Shanks]]'s Square Form Factorization [[wp:Shanks%27s_square_forms_factorization|(SquFoF)]].
|
||||
|
||||
Invented around 1975, ''‘On a 32-bit computer, SquFoF is the clear champion factoring algorithm''
|
||||
''for numbers between 10<sup>10</sup> and 10<sup>18</sup>, and will likely remain so.’''
|
||||
|
||||
|
||||
An integral [[wp:Binary_quadratic_form|binary quadratic form]] is a polynomial
|
||||
{{math|''f''(''x,y'') = ''ax<sup>2</sup>'' + ''bxy'' + ''cy<sup>2</sup>''}}
|
||||
with integer coefficients and discriminant {{math|''D'' = ''b<sup>2</sup>'' – ''4ac''}}.
|
||||
For each positive discriminant there are multiple forms {{math|(''a, b, c'')}}.
|
||||
|
||||
The next form in a periodic sequence (cycle) of adjacent forms is found by applying a reduction operator
|
||||
''rho'', essentially a variant of Euclid's algorithm for finding the continued fraction of a square root.
|
||||
Using {{math|floor(''√N'')}}, rho constructs a ''principal form''
|
||||
{{math|(''1, b, c'')}} with {{math|''D'' = ''4N''}}.
|
||||
|
||||
SquFoF is based on the existence of cycles containing ''ambiguous forms'', with the property that ''a'' divides ''b''.
|
||||
They come in pairs of associated forms {{math|(''a, b, c'') and (''c, b, a'')}} called symmetry points.
|
||||
If an ambiguous form is found (there is one for each divisor of D), write the discriminant as
|
||||
{{math|(''ak'')''<sup>2</sup>'' – ''4ac'' = ''a''(''a·k<sup>2</sup>'' – ''4c'') = ''4N''}}
|
||||
and (if a is not equal to 1 or 2) N is split.
|
||||
|
||||
Shanks used ''square forms'' to jump to a random ambiguous cycle. Fact: if any form in an ambiguous cycle
|
||||
is squared, that square form will always land in the principal cycle. Conversely, the square root of any
|
||||
form in the principal cycle lies in an ambiguous cycle. (Possibly the principal cycle itself).
|
||||
|
||||
A square form is easy to find: the last coefficient ''c'' is a perfect square. This happens about once
|
||||
every ∜N-th cycle step and for even indices only. Let rho compute the inverse square root form and track
|
||||
the ambiguous cycle backward until the symmetry point is reached. (Taking the inverse reverses the cycle).
|
||||
Then ''a'' or ''a/2'' divides D and therefore N.
|
||||
|
||||
To avoid trivial factorizations, Shanks created a list (queue) to hold small coefficients appearing
|
||||
early in the principal cycle, that may be roots of square forms found later on. If these forms are skipped,
|
||||
no roots land in the principal cycle itself and cases a = 1 or a = 2 do not happen.
|
||||
|
||||
Sometimes the cycle length is too short to find a proper square form. This is fixed by running five instances
|
||||
of SquFoF in parallel, with input N and 3, 5, 7, 11 times N; the discriminants then will have different periods.
|
||||
If N is prime or the cube of a prime, there are improper squares only and the program will duly report failure.
|
||||
|
||||
;Reference.
|
||||
|
||||
[https://homes.cerias.purdue.edu/~ssw/squfof.pdf] A detailed analysis of SquFoF (2007)
|
||||
|
||||
|
||||
__TOC__
|
||||
|
||||
110
Task/Square-form-factorization/C/square-form-factorization-1.c
Normal file
110
Task/Square-form-factorization/C/square-form-factorization-1.c
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define nelems(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
const unsigned long multiplier[] = {1, 3, 5, 7, 11, 3*5, 3*7, 3*11, 5*7, 5*11, 7*11, 3*5*7, 3*5*11, 3*7*11, 5*7*11, 3*5*7*11};
|
||||
|
||||
unsigned long long gcd(unsigned long long a, unsigned long long b)
|
||||
{
|
||||
while (b != 0)
|
||||
{
|
||||
a %= b;
|
||||
a ^= b;
|
||||
b ^= a;
|
||||
a ^= b;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
unsigned long long SQUFOF( unsigned long long N )
|
||||
{
|
||||
unsigned long long D, Po, P, Pprev, Q, Qprev, q, b, r, s;
|
||||
unsigned long L, B, i;
|
||||
s = (unsigned long long)(sqrtl(N)+0.5);
|
||||
if (s*s == N) return s;
|
||||
for (int k = 0; k < nelems(multiplier) && N <= 0xffffffffffffffff/multiplier[k]; k++) {
|
||||
D = multiplier[k]*N;
|
||||
Po = Pprev = P = sqrtl(D);
|
||||
Qprev = 1;
|
||||
Q = D - Po*Po;
|
||||
L = 2 * sqrtl( 2*s );
|
||||
B = 3 * L;
|
||||
for (i = 2 ; i < B ; i++) {
|
||||
b = (unsigned long long)((Po + P)/Q);
|
||||
P = b*Q - P;
|
||||
q = Q;
|
||||
Q = Qprev + b*(Pprev - P);
|
||||
r = (unsigned long long)(sqrtl(Q)+0.5);
|
||||
if (!(i & 1) && r*r == Q) break;
|
||||
Qprev = q;
|
||||
Pprev = P;
|
||||
};
|
||||
if (i >= B) continue;
|
||||
b = (unsigned long long)((Po - P)/r);
|
||||
Pprev = P = b*r + P;
|
||||
Qprev = r;
|
||||
Q = (D - Pprev*Pprev)/Qprev;
|
||||
i = 0;
|
||||
do {
|
||||
b = (unsigned long long)((Po + P)/Q);
|
||||
Pprev = P;
|
||||
P = b*Q - P;
|
||||
q = Q;
|
||||
Q = Qprev + b*(Pprev - P);
|
||||
Qprev = q;
|
||||
i++;
|
||||
} while (P != Pprev);
|
||||
r = gcd(N, Qprev);
|
||||
if (r != 1 && r != N) return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
const unsigned long long data[] = {
|
||||
2501,
|
||||
12851,
|
||||
13289,
|
||||
75301,
|
||||
120787,
|
||||
967009,
|
||||
997417,
|
||||
7091569,
|
||||
13290059,
|
||||
42854447,
|
||||
223553581,
|
||||
2027651281,
|
||||
11111111111,
|
||||
100895598169,
|
||||
1002742628021,
|
||||
60012462237239,
|
||||
287129523414791,
|
||||
9007199254740931,
|
||||
11111111111111111,
|
||||
314159265358979323,
|
||||
384307168202281507,
|
||||
419244183493398773,
|
||||
658812288346769681,
|
||||
922337203685477563,
|
||||
1000000000000000127,
|
||||
1152921505680588799,
|
||||
1537228672809128917,
|
||||
4611686018427387877};
|
||||
|
||||
for(int i = 0; i < nelems(data); i++) {
|
||||
unsigned long long example, factor, quotient;
|
||||
example = data[i];
|
||||
factor = SQUFOF(example);
|
||||
if(factor == 0) {
|
||||
printf("%llu was not factored.\n", example);
|
||||
}
|
||||
else {
|
||||
quotient = example / factor;
|
||||
printf("Integer %llu has factors %llu and %llu\n",
|
||||
example, factor, quotient);
|
||||
}
|
||||
}
|
||||
}
|
||||
139
Task/Square-form-factorization/C/square-form-factorization-2.c
Normal file
139
Task/Square-form-factorization/C/square-form-factorization-2.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
//SquFoF: minimalistic version without queue.
|
||||
//Classical heuristic. Tested: tcc 0.9.27
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//input maximum
|
||||
#define MxN ((unsigned long long) 1 << 62)
|
||||
|
||||
//reduce indefinite form
|
||||
#define rho(a, b, c) { \
|
||||
t = c; c = a; a = t; t = b; \
|
||||
q = (rN + b) / a; \
|
||||
b = q * a - b; \
|
||||
c += q * (t - b); }
|
||||
|
||||
//initialize
|
||||
#define rhoin(a, b, c) { \
|
||||
rho(a, b, c) h = b; \
|
||||
c = (mN - h * h) / a; }
|
||||
|
||||
#define gcd(a, b) while (b) { \
|
||||
t = a % b; a = b; b = t; }
|
||||
|
||||
//multipliers
|
||||
const unsigned long m[] = {1, 3, 5, 7, 11, 0};
|
||||
|
||||
//square form factorization
|
||||
unsigned long squfof( unsigned long long N ) {
|
||||
unsigned long a, b, c, u, v, w, rN, q, t, r;
|
||||
unsigned long long mN, h;
|
||||
int i, ix, k = 0;
|
||||
|
||||
if ((N & 1)==0) return 2;
|
||||
|
||||
h = floor(sqrt(N)+ 0.5);
|
||||
if (h * h == N) return h;
|
||||
|
||||
while (m[k]) {
|
||||
if (k && N % m[k]==0) return m[k];
|
||||
//check overflow m * N
|
||||
if (N > MxN / m[k]) break;
|
||||
mN = N * m[k++];
|
||||
|
||||
r = floor(sqrt(mN));
|
||||
h = r; //float64 fix
|
||||
if (h * h > mN) r -= 1;
|
||||
rN = r;
|
||||
|
||||
//principal form
|
||||
b = r; c = 1;
|
||||
rhoin(a, b, c)
|
||||
|
||||
//iteration bound
|
||||
ix = floor(sqrt(2*r)) * 4;
|
||||
|
||||
//search principal cycle
|
||||
for (i = 2; i < ix; i += 2) {
|
||||
rho(a, b, c)
|
||||
//even step
|
||||
|
||||
r = floor(sqrt(c)+ 0.5);
|
||||
if (r * r == c) {
|
||||
//square form found
|
||||
|
||||
//inverse square root
|
||||
v = -b; w = r;
|
||||
rhoin(u, v, w)
|
||||
|
||||
//search ambiguous cycle
|
||||
do { r = v;
|
||||
rho(u, v, w)
|
||||
} while (v != r);
|
||||
//symmetry point
|
||||
|
||||
h = N; gcd(h, u)
|
||||
if (h != 1) return h;
|
||||
}
|
||||
rho(a, b, c)
|
||||
//odd step
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
const unsigned long long data[] = {
|
||||
2501,
|
||||
12851,
|
||||
13289,
|
||||
75301,
|
||||
120787,
|
||||
967009,
|
||||
997417,
|
||||
7091569,
|
||||
|
||||
5214317,
|
||||
20834839,
|
||||
23515517,
|
||||
33409583,
|
||||
44524219,
|
||||
|
||||
13290059,
|
||||
223553581,
|
||||
2027651281,
|
||||
11111111111,
|
||||
100895598169,
|
||||
1002742628021,
|
||||
60012462237239,
|
||||
287129523414791,
|
||||
9007199254740931,
|
||||
11111111111111111,
|
||||
314159265358979323,
|
||||
384307168202281507,
|
||||
419244183493398773,
|
||||
658812288346769681,
|
||||
922337203685477563,
|
||||
1000000000000000127,
|
||||
1152921505680588799,
|
||||
1537228672809128917,
|
||||
4611686018427387877,
|
||||
0};
|
||||
|
||||
unsigned long long N, f;
|
||||
int i = 0;
|
||||
|
||||
while (1) {
|
||||
N = data[i++];
|
||||
//scanf("%llu", &N);
|
||||
if (N < 2) break;
|
||||
|
||||
printf("N = %llu\n", N);
|
||||
|
||||
f = squfof(N);
|
||||
if (N % f) f = 1;
|
||||
|
||||
if (f == 1) printf("fail\n\n");
|
||||
else printf("f = %llu N/f = %llu\n\n", f, N/f);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,323 @@
|
|||
' ***********************************************
|
||||
'subject: Shanks's square form factorization:
|
||||
' ambiguous forms of discriminant 4N
|
||||
' give factors of N.
|
||||
'tested : FreeBasic 1.08.1
|
||||
|
||||
|
||||
'------------------------------------------------
|
||||
const MxN = culngint(1) shl 62
|
||||
'input maximum
|
||||
|
||||
const qx = (1 shl 5) - 1
|
||||
'queue size
|
||||
|
||||
type arg
|
||||
'squfof arguments
|
||||
as ulong m, f
|
||||
as integer vb
|
||||
end type
|
||||
|
||||
type bqf
|
||||
declare sub rho ()
|
||||
'reduce indefinite form
|
||||
declare function issq (byref r as ulong) as integer
|
||||
'return -1 if c is square, set r:= sqrt(c)
|
||||
declare sub qform (byref g as string, byval t as integer)
|
||||
'print binary quadratic form #t (a, 2b, c)
|
||||
|
||||
as ulong rN, a, b, c
|
||||
as integer vb
|
||||
end type
|
||||
|
||||
type queue
|
||||
declare sub enq (byref P as bqf)
|
||||
'enqueue P.c, P.b if appropriate
|
||||
declare function pro (byref P as bqf, byval r as ulong) as integer
|
||||
'return -1 if a proper square form is found
|
||||
|
||||
as ulong a(qx), L, m
|
||||
as integer k, t
|
||||
end type
|
||||
|
||||
'global variables
|
||||
dim shared N as ulongint
|
||||
'the number to split
|
||||
|
||||
dim shared flag as integer
|
||||
'signal to end all threads
|
||||
|
||||
dim shared as ubyte q1024(1023), q3465(3464)
|
||||
'quadratic residue tables
|
||||
|
||||
|
||||
'------------------------------------------------
|
||||
sub bqf.rho ()
|
||||
dim as ulong q, t
|
||||
swap a, c
|
||||
'residue
|
||||
q = culng(rN + b) \ a
|
||||
t = b: b = q * a - b
|
||||
'pseudo-square
|
||||
c += q * (t - b)
|
||||
end sub
|
||||
|
||||
'initialize form
|
||||
#macro rhoin(F)
|
||||
F.rho : h = F.b
|
||||
F.c = (mN - h * h) \ F.a
|
||||
#endmacro
|
||||
|
||||
function bqf.issq (byref r as ulong) as integer
|
||||
if q1024(c and 1023) andalso q3465(c mod 3465) then
|
||||
'98.6% non-squares filtered
|
||||
r = culng(sqr(c))
|
||||
if r * r = c then return -1
|
||||
end if
|
||||
issq = 0
|
||||
end function
|
||||
|
||||
sub bqf.qform (byref g as string, byval t as integer)
|
||||
if vb = 0 then exit sub
|
||||
dim as longint u = a, v = b, w = c
|
||||
if t and 1 then
|
||||
w = -w
|
||||
else
|
||||
u = -u
|
||||
end if
|
||||
v shl= 1
|
||||
print g;str(t);" = (";u;",";v;",";w;")"
|
||||
end sub
|
||||
|
||||
'------------------------------------------------
|
||||
#macro red(r, a)
|
||||
r = iif(a and 1, a, a shr 1)
|
||||
if m > 2 then
|
||||
r = iif(r mod m, r, r \ m)
|
||||
end if
|
||||
#endmacro
|
||||
|
||||
sub queue.enq (byref P as bqf)
|
||||
dim s as ulong
|
||||
red(s, P.c)
|
||||
if s < L then
|
||||
'circular queue
|
||||
k = (k + 2) and qx
|
||||
if k > t then t = k
|
||||
'enqueue P.b, P.c
|
||||
a(k) = P.b mod s
|
||||
a(k + 1) = s
|
||||
end if
|
||||
end sub
|
||||
|
||||
function queue.pro (byref P as bqf, byval r as ulong) as integer
|
||||
dim as integer i, sw
|
||||
'skip improper square forms
|
||||
for i = 0 to t step 2
|
||||
sw = (P.b - a(i)) mod r = 0
|
||||
sw and= a(i + 1) = r
|
||||
if sw then return 0
|
||||
next i
|
||||
pro = -1
|
||||
end function
|
||||
|
||||
'------------------------------------------------
|
||||
sub squfof (byval ap as any ptr)
|
||||
dim as arg ptr rp = cptr(arg ptr, ap)
|
||||
dim as ulong L2, m, r, t, f = 1
|
||||
dim as integer ix, i, j
|
||||
dim as ulongint mN, h
|
||||
'principal and ambiguous cycles
|
||||
dim as bqf P, A
|
||||
dim Q as queue
|
||||
|
||||
if (N and 1) = 0 then
|
||||
rp->f = 2 ' even N
|
||||
flag =-1: exit sub
|
||||
end if
|
||||
|
||||
h = culngint(sqr(N))
|
||||
if h * h = N then
|
||||
'N is square
|
||||
rp->f = culng(h)
|
||||
flag =-1: exit sub
|
||||
end if
|
||||
|
||||
rp->f = 1
|
||||
'multiplier
|
||||
m = rp->m
|
||||
if m > 1 then
|
||||
if (N mod m) = 0 then
|
||||
rp->f = m ' m | N
|
||||
flag =-1: exit sub
|
||||
end if
|
||||
|
||||
'check overflow m * N
|
||||
if N > (MxN \ m) then exit sub
|
||||
end if
|
||||
mN = N * m
|
||||
|
||||
r = int(sqr(mN))
|
||||
'float64 fix
|
||||
if culngint(r) * r > mN then r -= 1
|
||||
P.rN = r
|
||||
A.rN = r
|
||||
|
||||
P.vb = rp->vb
|
||||
A.vb = rp->vb
|
||||
'verbosity switch
|
||||
if P.vb then print "r = "; r
|
||||
|
||||
Q.k = -2: Q.t = -1: Q.m = m
|
||||
'Queue entry bounds
|
||||
Q.L = int(sqr(r * 2))
|
||||
L2 = Q.L * m shl 1
|
||||
|
||||
'principal form
|
||||
P.b = r: P.c = 1
|
||||
rhoin(P)
|
||||
P.qform("P", 1)
|
||||
|
||||
ix = Q.L shl 2
|
||||
for i = 2 to ix
|
||||
'search principal cycle
|
||||
|
||||
if P.c < L2 then Q.enq(P)
|
||||
|
||||
P.rho
|
||||
if (i and 1) = 0 andalso P.issq(r) then
|
||||
'square form found
|
||||
|
||||
if Q.pro(P, r) then
|
||||
|
||||
P.qform("P", i)
|
||||
'inverse square root
|
||||
A.b =-P.b: A.c = r
|
||||
rhoin(A): j = 1
|
||||
A.qform("A", j)
|
||||
|
||||
do
|
||||
'search ambiguous cycle
|
||||
t = A.b
|
||||
A.rho: j += 1
|
||||
|
||||
if A.b = t then
|
||||
'symmetry point
|
||||
A.qform("A", j)
|
||||
red(f, A.a)
|
||||
if f = 1 then exit do
|
||||
|
||||
flag = -1
|
||||
'factor found
|
||||
end if
|
||||
loop until flag
|
||||
|
||||
end if ' proper square
|
||||
end if ' square form
|
||||
|
||||
if flag then exit for
|
||||
next i
|
||||
|
||||
rp->f = f
|
||||
end sub
|
||||
|
||||
'------------------------------------------------
|
||||
data 2501
|
||||
data 12851
|
||||
data 13289
|
||||
data 75301
|
||||
data 120787
|
||||
data 967009
|
||||
data 997417
|
||||
data 7091569
|
||||
data 13290059
|
||||
data 23515517
|
||||
data 42854447
|
||||
data 223553581
|
||||
data 2027651281
|
||||
data 11111111111
|
||||
data 100895598169
|
||||
data 1002742628021
|
||||
data 60012462237239
|
||||
data 287129523414791
|
||||
data 9007199254740931
|
||||
data 11111111111111111
|
||||
data 314159265358979323
|
||||
data 384307168202281507
|
||||
data 419244183493398773
|
||||
data 658812288346769681
|
||||
data 922337203685477563
|
||||
data 1000000000000000127
|
||||
data 1152921505680588799
|
||||
data 1537228672809128917
|
||||
data 4611686018427387877
|
||||
data 0
|
||||
|
||||
'main
|
||||
'------------------------------------------------
|
||||
const tx = 4
|
||||
dim as double tim = timer
|
||||
dim h(4) as any ptr
|
||||
dim a(4) as arg
|
||||
dim as ulongint f
|
||||
dim as integer s, t
|
||||
|
||||
width 64, 30
|
||||
cls
|
||||
|
||||
'tabulate quadratic residues
|
||||
for t = 0 to 1540
|
||||
s = t * t
|
||||
q1024(s and 1023) =-1
|
||||
q3465(s mod 3465) =-1
|
||||
next t
|
||||
|
||||
a(0).vb = 0
|
||||
'set one verbosity switch only
|
||||
|
||||
a(0).m = 1
|
||||
'multipliers
|
||||
a(1).m = 3
|
||||
a(2).m = 5
|
||||
a(3).m = 7
|
||||
a(4).m = 11
|
||||
|
||||
do
|
||||
print
|
||||
|
||||
do : read N
|
||||
loop until N < MxN
|
||||
if N < 2 then exit do
|
||||
|
||||
print "N = "; N
|
||||
|
||||
flag = 0
|
||||
|
||||
for t = 1 to tx + 1 step 2
|
||||
if t < tx then
|
||||
h(t) = threadcreate(@squfof, @a(t))
|
||||
end if
|
||||
|
||||
squfof(@a(t - 1))
|
||||
f = a(t - 1).f
|
||||
|
||||
if t < tx then
|
||||
threadwait(h(t))
|
||||
if f = 1 then f = a(t).f
|
||||
end if
|
||||
|
||||
if f > 1 then exit for
|
||||
next t
|
||||
|
||||
'assert
|
||||
if N mod f then f = 1
|
||||
|
||||
if f = 1 then
|
||||
print "fail"
|
||||
else
|
||||
print "f = ";f;" N/f = ";N \ f
|
||||
end if
|
||||
loop
|
||||
|
||||
print "total time:"; csng(timer - tim); " s"
|
||||
end
|
||||
127
Task/Square-form-factorization/Go/square-form-factorization.go
Normal file
127
Task/Square-form-factorization/Go/square-form-factorization.go
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
func isqrt(x uint64) uint64 {
|
||||
x0 := x >> 1
|
||||
x1 := (x0 + x/x0) >> 1
|
||||
for x1 < x0 {
|
||||
x0 = x1
|
||||
x1 = (x0 + x/x0) >> 1
|
||||
}
|
||||
return x0
|
||||
}
|
||||
|
||||
func gcd(x, y uint64) uint64 {
|
||||
for y != 0 {
|
||||
x, y = y, x%y
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
var multiplier = []uint64{
|
||||
1, 3, 5, 7, 11, 3 * 5, 3 * 7, 3 * 11, 5 * 7, 5 * 11, 7 * 11, 3 * 5 * 7, 3 * 5 * 11, 3 * 7 * 11, 5 * 7 * 11, 3 * 5 * 7 * 11,
|
||||
}
|
||||
|
||||
func squfof(N uint64) uint64 {
|
||||
s := uint64(math.Sqrt(float64(N)) + 0.5)
|
||||
if s*s == N {
|
||||
return s
|
||||
}
|
||||
for k := 0; k < len(multiplier) && N <= math.MaxUint64/multiplier[k]; k++ {
|
||||
D := multiplier[k] * N
|
||||
P := isqrt(D)
|
||||
Pprev := P
|
||||
Po := Pprev
|
||||
Qprev := uint64(1)
|
||||
Q := D - Po*Po
|
||||
L := uint32(isqrt(8 * s))
|
||||
B := 3 * L
|
||||
i := uint32(2)
|
||||
var b, q, r uint64
|
||||
for ; i < B; i++ {
|
||||
b = uint64((Po + P) / Q)
|
||||
P = b*Q - P
|
||||
q = Q
|
||||
Q = Qprev + b*(Pprev-P)
|
||||
r = uint64(math.Sqrt(float64(Q)) + 0.5)
|
||||
if (i&1) == 0 && r*r == Q {
|
||||
break
|
||||
}
|
||||
Qprev = q
|
||||
Pprev = P
|
||||
}
|
||||
if i >= B {
|
||||
continue
|
||||
}
|
||||
b = uint64((Po - P) / r)
|
||||
P = b*r + P
|
||||
Pprev = P
|
||||
Qprev = r
|
||||
Q = (D - Pprev*Pprev) / Qprev
|
||||
i = 0
|
||||
for {
|
||||
b = uint64((Po + P) / Q)
|
||||
Pprev = P
|
||||
P = b*Q - P
|
||||
q = Q
|
||||
Q = Qprev + b*(Pprev-P)
|
||||
Qprev = q
|
||||
i++
|
||||
if P == Pprev {
|
||||
break
|
||||
}
|
||||
}
|
||||
r = gcd(N, Qprev)
|
||||
if r != 1 && r != N {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func main() {
|
||||
examples := []uint64{
|
||||
2501,
|
||||
12851,
|
||||
13289,
|
||||
75301,
|
||||
120787,
|
||||
967009,
|
||||
997417,
|
||||
7091569,
|
||||
13290059,
|
||||
42854447,
|
||||
223553581,
|
||||
2027651281,
|
||||
11111111111,
|
||||
100895598169,
|
||||
1002742628021,
|
||||
60012462237239,
|
||||
287129523414791,
|
||||
9007199254740931,
|
||||
11111111111111111,
|
||||
314159265358979323,
|
||||
384307168202281507,
|
||||
419244183493398773,
|
||||
658812288346769681,
|
||||
922337203685477563,
|
||||
1000000000000000127,
|
||||
1152921505680588799,
|
||||
1537228672809128917,
|
||||
4611686018427387877,
|
||||
}
|
||||
fmt.Println("Integer Factor Quotient")
|
||||
fmt.Println("------------------------------------------")
|
||||
for _, N := range examples {
|
||||
fact := squfof(N)
|
||||
quot := "fail"
|
||||
if fact > 0 {
|
||||
quot = fmt.Sprintf("%d", N/fact)
|
||||
}
|
||||
fmt.Printf("%-20d %-10d %s\n", N, fact, quot)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
sqff=: {{
|
||||
s=. <.%:y
|
||||
if. y=*:s do. s return. end.
|
||||
for_D. (x:y)*/:~*/@>,{1,each}.p:i.5 do.
|
||||
if. -.'integer'-:datatype D=. x:inv D do. break. end.
|
||||
P=. <.%:D
|
||||
Q=. 1, D-P*P
|
||||
lim=. <:6*<.%:2*s
|
||||
for_i. }.i.lim do.
|
||||
b=. <.(+/0 _1{P)%{:Q
|
||||
P=. P,|(b*{:Q)-{:P
|
||||
Q=. Q,|(_2{Q)+b*-/_2{.P
|
||||
if. 2|i do. if. (=<.&.%:){:Q do. break. end. end.
|
||||
end.
|
||||
if. i>:lim do. continue. end.
|
||||
Q=. <.%:{:Q
|
||||
b=. <.(-/0 _1{P)%Q
|
||||
P=. ,(b*Q)+{:P
|
||||
Q=. Q, <.|(D-*:P)%Q
|
||||
whilst. ~:/_2{.P do.
|
||||
b=. <.(+/0 _1{P)%{:Q
|
||||
P=. P,|(b*{:Q)-{:P
|
||||
Q=. Q,|(_2{Q)+b*-/_2{.P
|
||||
end.
|
||||
f=. y+.x:_2{Q
|
||||
if. -. f e. 1,y do. f return. end.
|
||||
end.
|
||||
1
|
||||
}}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
task ''
|
||||
2501: 61 * 41
|
||||
12851: 71 * 181
|
||||
13289: 137 * 97
|
||||
75301: 293 * 257
|
||||
120787: 43 * 2809
|
||||
967009: 601 * 1609
|
||||
997417: 257 * 3881
|
||||
7091569: 2663 * 2663
|
||||
13290059: 3119 * 4261
|
||||
42854447: 9689 * 4423
|
||||
223553581: 11213 * 19937
|
||||
2027651281: 46061 * 44021
|
||||
11111111111: 21649 * 513239
|
||||
100895598169: 112303 * 898423
|
||||
1002742628021 was not factored
|
||||
60012462237239: 6862753 * 8744663
|
||||
287129523414791: 6059887 * 47381993
|
||||
9007199254740931: 10624181 * 847801751
|
||||
11111111111111111: 2071723 * 5363222357
|
||||
314159265358979323: 317213509 * 990371647
|
||||
384307168202281507: 415718707 * 924440401
|
||||
419244183493398773: 48009977 * 8732438749
|
||||
658812288346769681: 62222119 * 10588072199
|
||||
922337203685477563: 110075821 * 8379108103
|
||||
1000000000000000127 was not factored
|
||||
1152921505680588799: 139001459 * 8294312261
|
||||
1537228672809128917 was not factored
|
||||
4611686018427387877 was not factored
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
task=: {{
|
||||
for_num. nums do.
|
||||
factor=. x:sqff num
|
||||
if. 1=factor do. echo num,&":' was not factored'
|
||||
else. echo num,&":': ',factor,&":' * ',":x:num%factor
|
||||
end.
|
||||
end.
|
||||
}}
|
||||
|
||||
nums=: ".{{)n
|
||||
2501
|
||||
12851
|
||||
13289
|
||||
75301
|
||||
120787
|
||||
967009
|
||||
997417
|
||||
7091569
|
||||
13290059
|
||||
42854447
|
||||
223553581
|
||||
2027651281
|
||||
11111111111
|
||||
100895598169
|
||||
1002742628021
|
||||
60012462237239
|
||||
287129523414791
|
||||
9007199254740931
|
||||
11111111111111111
|
||||
314159265358979323
|
||||
384307168202281507
|
||||
419244183493398773
|
||||
658812288346769681
|
||||
922337203685477563
|
||||
1000000000000000127
|
||||
1152921505680588799
|
||||
1537228672809128917
|
||||
4611686018427387877x
|
||||
}}-.LF
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
def gcd(a; b):
|
||||
# subfunction expects [a,b] as input
|
||||
# i.e. a ~ .[0] and b ~ .[1]
|
||||
def rgcd: if .[1] == 0 then .[0]
|
||||
else [.[1], .[0] % .[1]] | rgcd
|
||||
end;
|
||||
[a,b] | rgcd;
|
||||
|
||||
# for infinite precision integer-arithmetic
|
||||
def idivide($p; $q): ($p - ($p % $q)) / $q ;
|
||||
def idivide($q): (. - (. % $q)) / $q ;
|
||||
|
||||
def isqrt:
|
||||
def irt:
|
||||
. as $x
|
||||
| 1 | until(. > $x; . * 4) as $q
|
||||
| {$q, $x, r: 0}
|
||||
| until( .q <= 1;
|
||||
.q |= idivide(4)
|
||||
| .t = .x - .r - .q
|
||||
| .r |= idivide(2)
|
||||
| if .t >= 0
|
||||
then .x = .t
|
||||
| .r += .q
|
||||
else .
|
||||
end)
|
||||
| .r ;
|
||||
if type == "number" and (isinfinite|not) and (isnan|not) and . >= 0
|
||||
then irt
|
||||
else "isqrt requires a non-negative integer for accuracy" | error
|
||||
end ;
|
||||
107
Task/Square-form-factorization/Jq/square-form-factorization-2.jq
Normal file
107
Task/Square-form-factorization/Jq/square-form-factorization-2.jq
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
def multipliers:
|
||||
[
|
||||
1, 3, 5, 7, 11, 3*5, 3*7, 3*11, 5*7, 5*11, 7*11, 3*5*7, 3*5*11, 3*7*11, 5*7*11, 3*5*7*11
|
||||
];
|
||||
|
||||
# input should be a number
|
||||
def squfof:
|
||||
def toi : floor | tostring | tonumber;
|
||||
. as $N
|
||||
| (($N|sqrt + 0.5)|toi) as $s
|
||||
| if ($s*$s == $N) then $s
|
||||
else label $out
|
||||
| {}
|
||||
| multipliers[] as $multiplier
|
||||
| ($N * $multiplier) as $D
|
||||
| .P = ($D|isqrt)
|
||||
| .Pprev = .P
|
||||
| .Pprev as $Po
|
||||
| .Qprev = 1
|
||||
| .Q = $D - $Po*$Po
|
||||
| (($s * 8)|isqrt) as $L
|
||||
| (3 * $L) as $B
|
||||
| .i = 2
|
||||
| .b = 0
|
||||
| .q = 0
|
||||
| .r = 0
|
||||
| .stop = false
|
||||
| until( (.i >= $B) or .stop;
|
||||
.b = idivide($Po + .P; .Q)
|
||||
| .P = .b * .Q - .P
|
||||
| .q = .Q
|
||||
| .Q = .Qprev + .b * (.Pprev - .P)
|
||||
|
||||
| .r = (((.Q|isqrt) + 0.5)|toi)
|
||||
|
||||
| if ((.i % 2) == 0 and (.r*.r) == .Q) then .stop = true
|
||||
else
|
||||
.Qprev = .q
|
||||
| .Pprev = .P
|
||||
| .i += 1
|
||||
end )
|
||||
| if .i < $B
|
||||
then
|
||||
.b = idivide($Po - .P; .r)
|
||||
| .P = .b*.r + .P
|
||||
| .Pprev = .P
|
||||
| .Qprev = .r
|
||||
| .Q = idivide($D - .Pprev*.Pprev; .Qprev)
|
||||
| .i = 0
|
||||
| .stop = false
|
||||
| until (.stop;
|
||||
.b = idivide($Po + .P; .Q)
|
||||
| .Pprev = .P
|
||||
| .P = .b * .Q - .P
|
||||
| .q = .Q
|
||||
| .Q = .Qprev + .b * (.Pprev - .P)
|
||||
| .Qprev = .q
|
||||
| .i += 1
|
||||
| if (.P == .Pprev) then .stop = true else . end )
|
||||
| .r = gcd($N; .Qprev)
|
||||
| if .r != 1 and .r != $N then .r, break $out else empty end
|
||||
else empty
|
||||
end
|
||||
end
|
||||
// 0 ;
|
||||
|
||||
def examples: [
|
||||
"2501",
|
||||
"12851",
|
||||
"13289",
|
||||
"75301",
|
||||
"120787",
|
||||
"967009",
|
||||
"997417",
|
||||
"7091569",
|
||||
"13290059",
|
||||
"42854447",
|
||||
"223553581",
|
||||
"2027651281",
|
||||
"11111111111",
|
||||
"100895598169",
|
||||
"1002742628021",
|
||||
"60012462237239",
|
||||
"287129523414791",
|
||||
"9007199254740931",
|
||||
"11111111111111111",
|
||||
"314159265358979323",
|
||||
"384307168202281507",
|
||||
"419244183493398773",
|
||||
"658812288346769681",
|
||||
"922337203685477563",
|
||||
"1000000000000000127",
|
||||
"1152921505680588799",
|
||||
"1537228672809128917",
|
||||
"4611686018427387877"
|
||||
];
|
||||
|
||||
"[Integer, Factor, Quotient]"
|
||||
"---------------------------",
|
||||
(examples[] as $example
|
||||
| ($example|tonumber) as $N
|
||||
| ($N | squfof) as $fact
|
||||
| if $fact == 0 then "fail"
|
||||
else idivide($N; $fact) as $quot
|
||||
| [$N, $fact, $quot]
|
||||
end
|
||||
)
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
function square_form_factor(n::T)::T where T <: Integer
|
||||
multiplier = T.([1, 3, 5, 7, 11, 3*5, 3*7, 3*11, 5*7, 5*11, 7*11, 3*5*7, 3*5*11, 3*7*11, 5*7*11, 3*5*7*11])
|
||||
s = T(round(sqrt(n)))
|
||||
s * s == n && return s
|
||||
for k in multiplier
|
||||
T != BigInt && n > typemax(T) ÷ k && break
|
||||
d = k * n
|
||||
p0 = pprev = p = isqrt(d)
|
||||
qprev = one(T)
|
||||
Q = d - p0 * p0
|
||||
l = T(floor(2 * sqrt(2 * s)))
|
||||
B, i = 3 * l, 2
|
||||
while i < B
|
||||
b = (p0 + p) ÷ Q
|
||||
p = b * Q - p
|
||||
q = Q
|
||||
Q = qprev + b * (pprev - p)
|
||||
r = T(round(sqrt(Q)))
|
||||
iseven(i) && r * r == Q && break
|
||||
qprev, pprev = q, p
|
||||
i += 1
|
||||
end
|
||||
i >= B && continue
|
||||
b = (p0 - p) ÷ r
|
||||
pprev = p = b * r + p
|
||||
qprev = r
|
||||
Q = (d - pprev * pprev) ÷ qprev
|
||||
i = 0
|
||||
while true
|
||||
b = (p0 + p) ÷ Q
|
||||
pprev = p
|
||||
p = b * Q - p
|
||||
q = Q
|
||||
Q = qprev + b * (pprev - p)
|
||||
qprev = q
|
||||
i += 1
|
||||
p == pprev && break
|
||||
end
|
||||
r = gcd(n, qprev)
|
||||
r != 1 && r != n && return r
|
||||
end
|
||||
return zero(T)
|
||||
end
|
||||
|
||||
println("Integer Factor Quotient\n", "-"^45)
|
||||
@time for n in Int128.([
|
||||
2501, 12851, 13289, 75301, 120787, 967009, 997417, 7091569, 13290059, 42854447, 223553581,
|
||||
2027651281, 11111111111, 100895598169, 1002742628021, 60012462237239, 287129523414791,
|
||||
9007199254740931, 11111111111111111, 314159265358979323, 384307168202281507, 419244183493398773,
|
||||
658812288346769681, 922337203685477563, 1000000000000000127, 1152921505680588799,
|
||||
1537228672809128917, 4611686018427387877])
|
||||
print(rpad(n, 22))
|
||||
factr = square_form_factor(n)
|
||||
print(rpad(factr, 10))
|
||||
println(factr == 0 ? "fail" : n ÷ factr)
|
||||
end
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
import math, strformat
|
||||
|
||||
const M = [uint64 1, 3, 5, 7, 11]
|
||||
|
||||
template isqrt(n: uint64): uint64 = uint64(sqrt(float(n)))
|
||||
template isEven(n: uint64): bool = (n and 1) == 0
|
||||
|
||||
proc squfof(n: uint64): uint64 =
|
||||
|
||||
if n.isEven: return 2
|
||||
var h = uint64(sqrt(float(n)) + 0.5)
|
||||
if h * h == n: return h
|
||||
|
||||
for m in M:
|
||||
if m > 1 and (n mod m == 0): return m
|
||||
# Check overflow m * n.
|
||||
if n > uint64.high div m: break
|
||||
let mn = m * n
|
||||
var r = isqrt(mn)
|
||||
if r * r > mn: dec r
|
||||
let rn = r
|
||||
|
||||
# Principal form.
|
||||
var b = r
|
||||
var a = 1u64
|
||||
h = (rn + b) div a * a - b
|
||||
var c = (mn - h * h) div a
|
||||
|
||||
for i in 2..<(4 * isqrt(2 * r)):
|
||||
# Search principal cycle.
|
||||
swap a, c
|
||||
var q = (rn + b) div a
|
||||
let t = b
|
||||
b = q * a - b
|
||||
c += q * (t - b)
|
||||
|
||||
if i.isEven:
|
||||
r = uint64(sqrt(float(c)) + 0.5)
|
||||
if r * r == c: # Square form found?
|
||||
|
||||
# Inverse square root.
|
||||
q = (rn - b) div r
|
||||
var v = q * r + b
|
||||
var w = (mn - v * v) div r
|
||||
|
||||
# Search ambiguous cycle.
|
||||
var u = r
|
||||
while true:
|
||||
swap w, u
|
||||
r = v
|
||||
q = (rn + v) div u
|
||||
v = q * u - v
|
||||
if v == r: break
|
||||
w += q * (r - v)
|
||||
|
||||
# Symmetry point.
|
||||
h = gcd(n, u)
|
||||
if h != 1: return h
|
||||
|
||||
result = 1
|
||||
|
||||
const Data = [2501u64,
|
||||
12851u64,
|
||||
13289u64,
|
||||
75301u64,
|
||||
120787u64,
|
||||
967009u64,
|
||||
997417u64,
|
||||
7091569u64,
|
||||
13290059u64,
|
||||
42854447u64,
|
||||
223553581u64,
|
||||
2027651281u64,
|
||||
11111111111u64,
|
||||
100895598169u64,
|
||||
1002742628021u64,
|
||||
60012462237239u64,
|
||||
287129523414791u64,
|
||||
9007199254740931u64,
|
||||
11111111111111111u64,
|
||||
314159265358979323u64,
|
||||
384307168202281507u64,
|
||||
419244183493398773u64,
|
||||
658812288346769681u64,
|
||||
922337203685477563u64,
|
||||
1000000000000000127u64,
|
||||
1152921505680588799u64,
|
||||
1537228672809128917u64,
|
||||
4611686018427387877u64]
|
||||
|
||||
echo "N f N/f"
|
||||
echo "======================================"
|
||||
for n in Data:
|
||||
let f = squfof(n)
|
||||
let res = if f == 1: "fail" else: &"{f:<10} {n div f}"
|
||||
echo &"{n:<22} {res}"
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
use ntheory <is_prime gcd forcomb vecprod>;
|
||||
|
||||
my @multiplier;
|
||||
my @p = <3 5 7 11>;
|
||||
forcomb { push @multiplier, vecprod @p[@_] } scalar @p;
|
||||
|
||||
sub sff {
|
||||
my($N) = shift;
|
||||
return 1 if is_prime $N; # if n is prime
|
||||
return sqrt $N if sqrt($N) == int sqrt $N; # if n is a perfect square
|
||||
|
||||
for my $k (@multiplier) {
|
||||
my $P0 = int sqrt($k*$N); # P[0]=floor(sqrt(N)
|
||||
my $Q0 = 1; # Q[0]=1
|
||||
my $Q = $k*$N - $P0**2; # Q[1]=N-P[0]^2 & Q[i]
|
||||
my $P1 = $P0; # P[i-1] = P[0]
|
||||
my $Q1 = $Q0; # Q[i-1] = Q[0]
|
||||
my $P = 0; # P[i]
|
||||
my $Qn = 0; # $P[$i+1];
|
||||
my $b = 0; # b[i]
|
||||
|
||||
until (sqrt($Q) == int(sqrt($Q))) { # until Q[i] is a perfect square
|
||||
$b = int( int(sqrt($k*$N) + $P1 ) / $Q); # floor(floor(sqrt(N+P[i-1])/Q[i])
|
||||
$P = $b*$Q - $P1; # P[i]=b*Q[i]-P[i-1]
|
||||
$Qn = $Q1 + $b*($P1 - $P); # Q[i+1]=Q[i-1]+b(P[i-1]-P[i])
|
||||
($Q1, $Q, $P1) = ($Q, $Qn, $P);
|
||||
}
|
||||
|
||||
$b = int( int( sqrt($k*$N)+$P ) / $Q ); # b=floor((floor(sqrt(N)+P[i])/Q[0])
|
||||
$P1 = $b*$Q0 - $P; # P[i-1]=b*Q[0]-P[i]
|
||||
$Q = ( $k*$N - $P1**2 )/$Q0; # Q[1]=(N-P[0]^2)/Q[0] & Q[i]
|
||||
$Q1 = $Q0; # Q[i-1] = Q[0]
|
||||
|
||||
while () {
|
||||
$b = int( int(sqrt($k*$N)+$P1 ) / $Q ); # b=floor(floor(sqrt(N)+P[i-1])/Q[i])
|
||||
$P = $b*$Q - $P1; # P[i]=b*Q[i]-P[i-1]
|
||||
$Qn = $Q1 + $b*($P1 - $P); # Q[i+1]=Q[i-1]+b(P[i-1]-P[i])
|
||||
last if $P == $P1; # until P[i+1]=P[i]
|
||||
($Q1, $Q, $P1) = ($Q, $Qn, $P);
|
||||
}
|
||||
for (gcd $N, $P) { return $_ if $_ != 1 and $_ != $N }
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
for my $data (
|
||||
11111, 2501, 12851, 13289, 75301, 120787, 967009, 997417, 4558849, 7091569, 13290059,
|
||||
42854447, 223553581, 2027651281, 11111111111, 100895598169, 1002742628021, 60012462237239,
|
||||
287129523414791, 11111111111111111, 384307168202281507, 1000000000000000127, 9007199254740931,
|
||||
922337203685477563, 314159265358979323, 1152921505680588799, 658812288346769681,
|
||||
419244183493398773, 1537228672809128917) {
|
||||
my $v = sff($data);
|
||||
if ($v == 0) { say 'The number ' . $data . ' is not factored.' }
|
||||
elsif ($v == 1) { say 'The number ' . $data . ' is a prime.' }
|
||||
else { say "$data = " . join ' * ', sort {$a <=> $b} $v, int $data/int($v) }
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #000080;font-style:italic;">--requires(64) -- (decided to limit 32-bit explicitly instead)</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">MxN</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power<span style="color: #0000FF;">(<span style="color: #000000;">2<span style="color: #0000FF;">,<span style="color: #008080;">iff<span style="color: #0000FF;">(<span style="color: #7060A8;">machine_bits<span style="color: #0000FF;">(<span style="color: #0000FF;">)<span style="color: #0000FF;">=<span style="color: #000000;">32<span style="color: #0000FF;">?<span style="color: #000000;">53<span style="color: #0000FF;">:<span style="color: #000000;">63<span style="color: #0000FF;">)<span style="color: #0000FF;">)<span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{<span style="color: #000000;">1<span style="color: #0000FF;">,</span> <span style="color: #000000;">3<span style="color: #0000FF;">,</span> <span style="color: #000000;">5<span style="color: #0000FF;">,</span> <span style="color: #000000;">7<span style="color: #0000FF;">,</span> <span style="color: #000000;">11<span style="color: #0000FF;">}</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">squfof<span style="color: #0000FF;">(<span style="color: #004080;">atom</span> <span style="color: #000000;">N<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">-- square form factorization</span>
|
||||
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">h<span style="color: #0000FF;">,</span> <span style="color: #000000;">a<span style="color: #0000FF;">=<span style="color: #000000;">0<span style="color: #0000FF;">,</span> <span style="color: #000000;">b<span style="color: #0000FF;">,</span> <span style="color: #000000;">c<span style="color: #0000FF;">,</span> <span style="color: #000000;">u<span style="color: #0000FF;">=<span style="color: #000000;">0<span style="color: #0000FF;">,</span> <span style="color: #000000;">v<span style="color: #0000FF;">,</span> <span style="color: #000000;">w<span style="color: #0000FF;">,</span> <span style="color: #000000;">rN<span style="color: #0000FF;">,</span> <span style="color: #000000;">q<span style="color: #0000FF;">,</span> <span style="color: #000000;">r<span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span>
|
||||
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder<span style="color: #0000FF;">(<span style="color: #000000;">N<span style="color: #0000FF;">,<span style="color: #000000;">2<span style="color: #0000FF;">)<span style="color: #0000FF;">==<span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">2</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #7060A8;">sqrt<span style="color: #0000FF;">(<span style="color: #000000;">N<span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">0.5<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">h<span style="color: #0000FF;">*<span style="color: #000000;">h<span style="color: #0000FF;">==<span style="color: #000000;">N</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">h</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">k<span style="color: #0000FF;">=<span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length<span style="color: #0000FF;">(<span style="color: #000000;">m<span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">mk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m<span style="color: #0000FF;">[<span style="color: #000000;">k<span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">mk<span style="color: #0000FF;">><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">remainder<span style="color: #0000FF;">(<span style="color: #000000;">N<span style="color: #0000FF;">,<span style="color: #000000;">mk<span style="color: #0000FF;">)<span style="color: #0000FF;">==<span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">mk</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000080;font-style:italic;">//check overflow m * N</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">N<span style="color: #0000FF;">><span style="color: #000000;">MxN<span style="color: #0000FF;">/<span style="color: #000000;">mk</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">mN</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">N<span style="color: #0000FF;">*<span style="color: #000000;">mk</span>
|
||||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #7060A8;">sqrt<span style="color: #0000FF;">(<span style="color: #000000;">mN<span style="color: #0000FF;">)<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">r<span style="color: #0000FF;">*<span style="color: #000000;">r<span style="color: #0000FF;">><span style="color: #000000;">mN</span> <span style="color: #008080;">then</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">rN</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span>
|
||||
|
||||
<span style="color: #000080;font-style:italic;">//principal form</span>
|
||||
<span style="color: #0000FF;">{<span style="color: #000000;">b<span style="color: #0000FF;">,<span style="color: #000000;">a<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{<span style="color: #000000;">r<span style="color: #0000FF;">,<span style="color: #000000;">1<span style="color: #0000FF;">}</span>
|
||||
<span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #0000FF;">(<span style="color: #000000;">rN<span style="color: #0000FF;">+<span style="color: #000000;">b<span style="color: #0000FF;">)<span style="color: #0000FF;">/<span style="color: #000000;">a<span style="color: #0000FF;">)<span style="color: #0000FF;">*<span style="color: #000000;">a<span style="color: #0000FF;">-<span style="color: #000000;">b</span>
|
||||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #0000FF;">(<span style="color: #000000;">mN<span style="color: #0000FF;">-<span style="color: #000000;">h<span style="color: #0000FF;">*<span style="color: #000000;">h<span style="color: #0000FF;">)<span style="color: #0000FF;">/<span style="color: #000000;">a<span style="color: #0000FF;">)</span>
|
||||
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i<span style="color: #0000FF;">=<span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #7060A8;">sqrt<span style="color: #0000FF;">(<span style="color: #000000;">2<span style="color: #0000FF;">*<span style="color: #000000;">r<span style="color: #0000FF;">)<span style="color: #0000FF;">)</span> <span style="color: #0000FF;">*</span> <span style="color: #000000;">4<span style="color: #0000FF;">-<span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000080;font-style:italic;">//search principal cycle</span>
|
||||
|
||||
<span style="color: #0000FF;">{<span style="color: #000000;">a<span style="color: #0000FF;">,<span style="color: #000000;">c<span style="color: #0000FF;">,<span style="color: #000000;">t<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{<span style="color: #000000;">c<span style="color: #0000FF;">,<span style="color: #000000;">a<span style="color: #0000FF;">,<span style="color: #000000;">b<span style="color: #0000FF;">}</span>
|
||||
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #0000FF;">(<span style="color: #000000;">rN<span style="color: #0000FF;">+<span style="color: #000000;">b<span style="color: #0000FF;">)<span style="color: #0000FF;">/<span style="color: #000000;">a<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">q<span style="color: #0000FF;">*<span style="color: #000000;">a<span style="color: #0000FF;">-<span style="color: #000000;">b</span>
|
||||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">q<span style="color: #0000FF;">*<span style="color: #0000FF;">(<span style="color: #000000;">t<span style="color: #0000FF;">-<span style="color: #000000;">b<span style="color: #0000FF;">)</span>
|
||||
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder<span style="color: #0000FF;">(<span style="color: #000000;">i<span style="color: #0000FF;">,<span style="color: #000000;">2<span style="color: #0000FF;">)<span style="color: #0000FF;">==<span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #7060A8;">sqrt<span style="color: #0000FF;">(<span style="color: #000000;">c<span style="color: #0000FF;">)<span style="color: #0000FF;">+<span style="color: #000000;">0.5<span style="color: #0000FF;">)</span>
|
||||
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">r<span style="color: #0000FF;">*<span style="color: #000000;">r<span style="color: #0000FF;">==<span style="color: #000000;">c</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000080;font-style:italic;">//square form found
|
||||
|
||||
//inverse square root</span>
|
||||
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #0000FF;">(<span style="color: #000000;">rN<span style="color: #0000FF;">-<span style="color: #000000;">b<span style="color: #0000FF;">)<span style="color: #0000FF;">/<span style="color: #000000;">r<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">q<span style="color: #0000FF;">*<span style="color: #000000;">r<span style="color: #0000FF;">+<span style="color: #000000;">b</span>
|
||||
<span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #0000FF;">(<span style="color: #000000;">mN<span style="color: #0000FF;">-<span style="color: #000000;">v<span style="color: #0000FF;">*<span style="color: #000000;">v<span style="color: #0000FF;">)<span style="color: #0000FF;">/<span style="color: #000000;">r<span style="color: #0000FF;">)</span>
|
||||
|
||||
<span style="color: #000080;font-style:italic;">//search ambiguous cycle</span>
|
||||
<span style="color: #000000;">u</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #0000FF;">{<span style="color: #000000;">u<span style="color: #0000FF;">,<span style="color: #000000;">w<span style="color: #0000FF;">,<span style="color: #000000;">r<span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{<span style="color: #000000;">w<span style="color: #0000FF;">,<span style="color: #000000;">u<span style="color: #0000FF;">,<span style="color: #000000;">v<span style="color: #0000FF;">}</span>
|
||||
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor<span style="color: #0000FF;">(<span style="color: #0000FF;">(<span style="color: #000000;">rN<span style="color: #0000FF;">+<span style="color: #000000;">v<span style="color: #0000FF;">)<span style="color: #0000FF;">/<span style="color: #000000;">u<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">q<span style="color: #0000FF;">*<span style="color: #000000;">u<span style="color: #0000FF;">-<span style="color: #000000;">v</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">v<span style="color: #0000FF;">==<span style="color: #000000;">r</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">w</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">q<span style="color: #0000FF;">*<span style="color: #0000FF;">(<span style="color: #000000;">r<span style="color: #0000FF;">-<span style="color: #000000;">v<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
|
||||
<span style="color: #000080;font-style:italic;">//symmetry point</span>
|
||||
<span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">gcd<span style="color: #0000FF;">(<span style="color: #000000;">N<span style="color: #0000FF;">,<span style="color: #000000;">u<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">h<span style="color: #0000FF;">!=<span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">h</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{<span style="color: #000000;">2501<span style="color: #0000FF;">,</span> <span style="color: #000000;">12851<span style="color: #0000FF;">,</span> <span style="color: #000000;">13289<span style="color: #0000FF;">,</span> <span style="color: #000000;">75301<span style="color: #0000FF;">,</span> <span style="color: #000000;">120787<span style="color: #0000FF;">,</span> <span style="color: #000000;">967009<span style="color: #0000FF;">,</span> <span style="color: #000000;">997417<span style="color: #0000FF;">,</span> <span style="color: #000000;">7091569<span style="color: #0000FF;">,</span> <span style="color: #000000;">5214317<span style="color: #0000FF;">,</span> <span style="color: #000000;">20834839<span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">23515517<span style="color: #0000FF;">,</span> <span style="color: #000000;">33409583<span style="color: #0000FF;">,</span> <span style="color: #000000;">44524219<span style="color: #0000FF;">,</span> <span style="color: #000000;">13290059<span style="color: #0000FF;">,</span> <span style="color: #000000;">223553581<span style="color: #0000FF;">,</span> <span style="color: #000000;">42854447<span style="color: #0000FF;">,</span> <span style="color: #000000;">223553581<span style="color: #0000FF;">,</span> <span style="color: #000000;">2027651281<span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">11111111111<span style="color: #0000FF;">,</span> <span style="color: #000000;">100895598169<span style="color: #0000FF;">,</span> <span style="color: #000000;">1002742628021<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (prime/expected to fail)</span>
|
||||
<span style="color: #000000;">60012462237239<span style="color: #0000FF;">,</span> <span style="color: #000000;">287129523414791<span style="color: #0000FF;">,</span> <span style="color: #000000;">9007199254740931<span style="color: #0000FF;">,</span> <span style="color: #000000;">32<span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (limit of 32-bit)</span>
|
||||
<span style="color: #000000;">11111111111111111<span style="color: #0000FF;">,</span> <span style="color: #000000;">314159265358979323<span style="color: #0000FF;">,</span> <span style="color: #000000;">384307168202281507<span style="color: #0000FF;">,</span> <span style="color: #000000;">419244183493398773<span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">658812288346769681<span style="color: #0000FF;">,</span> <span style="color: #000000;">922337203685477563<span style="color: #0000FF;">,</span> <span style="color: #000000;">1000000000000000127<span style="color: #0000FF;">,</span> <span style="color: #000000;">1152921505680588799<span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">1537228672809128917<span style="color: #0000FF;">,</span> <span style="color: #000000;">4611686018427387877<span style="color: #0000FF;">}</span>
|
||||
|
||||
<span style="color: #7060A8;">printf<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #008000;">"N f N/f\n"<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #008000;">"======================================\n"<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i<span style="color: #0000FF;">=<span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length<span style="color: #0000FF;">(<span style="color: #000000;">tests<span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">N</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests<span style="color: #0000FF;">[<span style="color: #000000;">i<span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">N<span style="color: #0000FF;">=<span style="color: #000000;">32</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">machine_bits<span style="color: #0000FF;">(<span style="color: #0000FF;">)<span style="color: #0000FF;">=<span style="color: #000000;">32</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">squfof<span style="color: #0000FF;">(<span style="color: #000000;">N<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf<span style="color: #0000FF;">(<span style="color: #000000;">1<span style="color: #0000FF;">,<span style="color: #008000;">"%-22d %s\n"<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #000000;">N<span style="color: #0000FF;">,<span style="color: #008080;">iff<span style="color: #0000FF;">(<span style="color: #000000;">f<span style="color: #0000FF;">=<span style="color: #000000;">1<span style="color: #0000FF;">?<span style="color: #008000;">"fail"<span style="color: #0000FF;">:<span style="color: #7060A8;">sprintf<span style="color: #0000FF;">(<span style="color: #008000;">"%-10d %d"<span style="color: #0000FF;">,<span style="color: #0000FF;">{<span style="color: #000000;">f<span style="color: #0000FF;">,<span style="color: #000000;">N<span style="color: #0000FF;">/<span style="color: #000000;">f<span style="color: #0000FF;">}<span style="color: #0000FF;">)<span style="color: #0000FF;">)<span style="color: #0000FF;">}<span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for
|
||||
<!--
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*REXX pgm factors an integer using Daniel Shanks' (1917-1996) square form factorization*/
|
||||
numeric digits 100 /*ensure enough decimal digits.*/
|
||||
call dMults 1,3,5,7,11,3*5,3*7,3*11,5*7,5*11,7*11, 3*5*7, 3*5*11, 3*7*11, 5*7*11, 3*5*7*11
|
||||
call dTests 2501, 12851, 13289, 75301, 120787, 967009, 997417, 7091569, 13290059, ,
|
||||
42854447, 223553581, 2027651281, 11111111111, 100895598169, 1002742628021, ,
|
||||
60012462237239, 287129523414791, 9007199254740931, 11111111111111111, ,
|
||||
314159265358979323, 384307168202281507, 419244183493398773, ,
|
||||
658812288346769681, 922337203685477563, 1000000000000000127, ,
|
||||
1152921505680588799, 1537228672809128917, 4611686018427387877
|
||||
w= length( commas(!.$) ) /*the max width of test numbers*/
|
||||
do tests=1 for !.0; n= !.tests; nc= commas(n)
|
||||
f= ssff(n); fc= commas(f); wf= length(fc); if f\==0 then nf= commas(n%f)
|
||||
if f\==0 then do; nfc= commas(n%f); wnfc= length(nfc); end
|
||||
if f ==0 then _= " (Shank's square form factor failed.)"
|
||||
else _= ' factors are: ' right( fc, max(w%2 , wf ) ) " and " ,
|
||||
right(nfc, max(w%2+4, wnfc) )
|
||||
say right(nc, w+5) _
|
||||
end /*tests*/
|
||||
exit 0 /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
commas: parse arg ?; do jc=length(?)-3 to 1 by -3; ?=insert(',', ?, jc); end; return ?
|
||||
dMults: @.$= 0; do j=1 for arg(); @.j= arg(j); @.$=max(@.$, @.j); end; @.0=j-1; return
|
||||
dTests: !.$= 0; do j=1 for arg(); !.j= arg(j); !.$=max(!.$, !.j); end; !.0=j-1; return
|
||||
gcd: procedure; parse arg x,y; do until _==0; _= x // y; x= y; y= _; end; return x
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
iSqrt: procedure; parse arg x; r=0; q=1; do while q<=x; q=q*4; end
|
||||
do while q>1; q=q%4; _=x-r-q; r=r%2; if _>=0 then do;x=_;r=r+q; end; end
|
||||
return r
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
ssff: procedure expose @.; parse arg n; n= abs(n); er= '***error***'
|
||||
s= iSqrt(n); if s**2==n then return s; big= 2**digits()
|
||||
do #=1 for @.0; k= @.# /*get a # from the list of low factors*/
|
||||
if n>big/k then do; say er 'number is too large: ' commas(k); exit 8; end
|
||||
d= n*k; po= iSqrt(d); p= po
|
||||
pprev= po; QQ= d - po*po
|
||||
qprev= 1; BB= iSqrt(s+s)*6
|
||||
do i=2 while i<BB; b= (po+p)%QQ
|
||||
p= b*QQ - p; q= QQ
|
||||
QQ= qprev + b*(pprev-p); r= iSqrt(QQ)
|
||||
if i//2==0 then if r*r==QQ then leave
|
||||
qprev= q; pprev= p
|
||||
end /*i*/
|
||||
if i>=BB then iterate
|
||||
b= (po-p)%r; p= b*r + p
|
||||
pprev= p; qprev= r
|
||||
QQ= (d - pprev*pprev)%qprev
|
||||
do until p==pprev; pprev= p
|
||||
b= (po+p)%QQ; q= QQ; p= b*QQ - p
|
||||
QQ= qprev + b*(pprev-p); qprev= q
|
||||
end /*until*/
|
||||
r= gcd(n, qprev)
|
||||
if r\==1 then if r\==n then return r
|
||||
end /*#*/
|
||||
return 0
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# 20210325 Raku programming solution
|
||||
|
||||
my @multiplier = ( 1, 3, 5, 7, 11, 3*5, 3*7, 3*11, 5*7, 5*11, 7*11, 3*5*7, 3*5*11, 3*7*11, 5*7*11, 3*5*7*11 );
|
||||
|
||||
sub circumfix:<⌊ ⌋>{ $^n.floor }; sub prefix:<√>{ $^n.sqrt }; # just for fun
|
||||
|
||||
sub SQUFOF ( \𝑁 ) {
|
||||
|
||||
return 1 if 𝑁.is-prime; # if n is prime return 1
|
||||
return √𝑁 if √𝑁 == Int(√𝑁); # if n is a perfect square return √𝑁
|
||||
|
||||
for @multiplier -> \𝑘 {
|
||||
my \Pₒ = $ = ⌊ √(𝑘*𝑁) ⌋; # P[0]=floor(√N)
|
||||
my \Qₒ = $ = 1 ; # Q[0]=1
|
||||
my \Q = $ = 𝑘*𝑁 - Pₒ²; # Q[1]=N-P[0]^2 & Q[i]
|
||||
my \Pₚᵣₑᵥ = $ = Pₒ; # P[i-1] = P[0]
|
||||
my \Qₚᵣₑᵥ = $ = Qₒ; # Q[i-1] = Q[0]ₒ
|
||||
my \P = $ = 0; # P[i]
|
||||
my \Qₙₑₓₜ = $ = 0; # P[i+1]
|
||||
my \b = $ = 0; # b[i]
|
||||
# i = 1
|
||||
repeat until √Q == Int(√Q) { # until Q[i] is a perfect square==
|
||||
b = ⌊⌊ √(𝑘*𝑁) + Pₚᵣₑᵥ ⌋ / Q ⌋; # floor(floor(√N+P[i-1])/Q[i])⌋
|
||||
P = b*Q - Pₚᵣₑᵥ; # P[i]=b*Q[i]-P[i-1]
|
||||
Qₙₑₓₜ = Qₚᵣₑᵥ + b*(Pₚᵣₑᵥ - P); # Q[i+1]=Q[i-1]+b(P[i-1]-P[i])ₙ
|
||||
( Qₚᵣₑᵥ, Q, Pₚᵣₑᵥ ) = Q, Qₙₑₓₜ, P; # i++
|
||||
}
|
||||
|
||||
b = ⌊ ⌊ √(𝑘*𝑁)+P ⌋ / Q ⌋; # b=floor((floor(√N)+P[i])/Q[0])⌋
|
||||
Pₚᵣₑᵥ = b*Qₒ - P; # P[i-1]=b*Q[0]-P[i]ₒ
|
||||
Q = ( 𝑘*𝑁 - Pₚᵣₑᵥ² )/Qₒ; # Q[1]=(N-P[0]^2)/Q[0] & Q[i]
|
||||
Qₚᵣₑᵥ = Qₒ; # Q[i-1] = Q[0]ₚ
|
||||
# i = 1
|
||||
loop { # repeat
|
||||
b = ⌊ ⌊ √(𝑘*𝑁)+Pₚᵣₑᵥ ⌋ / Q ⌋; # b=floor(floor(√N)+P[i-1])/Q[i])⌋
|
||||
P = b*Q - Pₚᵣₑᵥ; # P[i]=b*Q[i]-P[i-1]
|
||||
Qₙₑₓₜ = Qₚᵣₑᵥ + b*(Pₚᵣₑᵥ - P); # Q[i+1]=Q[i-1]+b(P[i-1]-P[i])ₙ
|
||||
last if (P == Pₚᵣₑᵥ); # until P[i+1]=P[i]
|
||||
( Qₚᵣₑᵥ, Q, Pₚᵣₑᵥ ) = Q, Qₙₑₓₜ, P; # i++
|
||||
}
|
||||
given 𝑁 gcd P { return $_ if $_ != 1|𝑁 }
|
||||
} # gcd(N,P[i]) (if != 1 or N) is a factor of N, otherwise try next k
|
||||
return 0 # give up
|
||||
}
|
||||
|
||||
race for (
|
||||
11111, # wikipedia.org/wiki/Shanks%27s_square_forms_factorization#Example
|
||||
4558849, # example from talk page
|
||||
# all of the rest are taken from the FreeBASIC entry
|
||||
2501,12851,13289,75301,120787,967009,997417,7091569,13290059,
|
||||
42854447,223553581,2027651281,11111111111,100895598169,1002742628021,
|
||||
# time hoarders
|
||||
60012462237239, # = 6862753 * 8744663 15s
|
||||
287129523414791, # = 6059887 * 47381993 80s
|
||||
11111111111111111, # = 2071723 * 5363222357 2m
|
||||
384307168202281507, # = 415718707 * 924440401 5m
|
||||
1000000000000000127, # = 111756107 * 8948056861 12m
|
||||
9007199254740931, # = 10624181 * 847801751 17m
|
||||
922337203685477563, # = 110075821 * 8379108103 41m
|
||||
314159265358979323, # = 317213509 * 990371647 61m
|
||||
1152921505680588799, # = 139001459 * 8294312261 93m
|
||||
658812288346769681, # = 62222119 * 10588072199 112m
|
||||
419244183493398773, # = 48009977 * 8732438749 135m
|
||||
1537228672809128917, # = 26675843 * 57626245319 254m
|
||||
# don't know how to handle this one
|
||||
# for 1e-323, 1e-324 { my $*TOLERANCE = $_ ;
|
||||
# say 4611686018427387877.sqrt ≅ 4611686018427387877.sqrt.Int }
|
||||
# skip the perfect square check and start k with 3 to get the following
|
||||
# 4611686018427387877, # = 343242169 * 13435662733 217m
|
||||
) -> \data {
|
||||
given data.&SQUFOF {
|
||||
when 0 { say "The number ", data, " is not factored." }
|
||||
when 1 { say "The number ", data, " is a prime." }
|
||||
default { say data, " = ", $_, " * ", data div $_.Int }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# 20210326 Raku programming solution
|
||||
|
||||
use NativeCall;
|
||||
|
||||
constant LIBSQUFOF = '/home/user/LibSQUFOF.so';
|
||||
|
||||
sub squfof(uint64 $n) returns uint64 is native(LIBSQUFOF) { * };
|
||||
|
||||
race for (
|
||||
11111, # wikipedia.org/wiki/Shanks%27s_square_forms_factorization#Example
|
||||
4558849, # example from talk page
|
||||
# all of the rest are taken from the FreeBASIC entry
|
||||
2501,12851,13289,75301,120787,967009,997417,7091569,13290059,
|
||||
42854447,223553581,2027651281,11111111111,100895598169,1002742628021,
|
||||
60012462237239, # = 6862753 * 8744663
|
||||
287129523414791, # = 6059887 * 47381993
|
||||
11111111111111111, # = 2071723 * 5363222357
|
||||
384307168202281507, # = 415718707 * 924440401
|
||||
1000000000000000127, # = 111756107 * 8948056861
|
||||
9007199254740931, # = 10624181 * 847801751
|
||||
922337203685477563, # = 110075821 * 8379108103
|
||||
314159265358979323, # = 317213509 * 990371647
|
||||
1152921505680588799, # = 139001459 * 8294312261
|
||||
658812288346769681, # = 62222119 * 10588072199
|
||||
419244183493398773, # = 48009977 * 8732438749
|
||||
1537228672809128917, # = 26675843 * 57626245319
|
||||
4611686018427387877, # = 343242169 * 13435662733
|
||||
) -> \data {
|
||||
given squfof(data) { say data, " = ", $_, " * ", data div $_ }
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
import "/long" for ULong
|
||||
import "/big" for BigInt
|
||||
import "/fmt" for Fmt
|
||||
|
||||
var multipliers = [
|
||||
1, 3, 5, 7, 11, 3*5, 3*7, 3*11, 5*7, 5*11, 7*11, 3*5*7, 3*5*11, 3*7*11, 5*7*11, 3*5*7*11
|
||||
]
|
||||
|
||||
var squfof = Fn.new { |N|
|
||||
var s = ULong.new((N.toNum.sqrt + 0.5).floor)
|
||||
if (s*s == N) return s
|
||||
for (multiplier in multipliers) {
|
||||
var T = ULong
|
||||
var n = N
|
||||
if (n > ULong.largest/multiplier) {
|
||||
T = BigInt
|
||||
n = BigInt.new(n.toString)
|
||||
}
|
||||
var D = n * multiplier
|
||||
var P = D.isqrt
|
||||
var Pprev = P
|
||||
var Po = Pprev
|
||||
var Qprev = T.one
|
||||
var Q = D - Po*Po
|
||||
var L = (s * 8).isqrt.toSmall
|
||||
var B = 3 * L
|
||||
var i = 2
|
||||
var b = T.zero
|
||||
var q = T.zero
|
||||
var r = T.zero
|
||||
while (i < B) {
|
||||
b = (Po + P) / Q
|
||||
P = b * Q - P
|
||||
q = Q
|
||||
Q = Qprev + b * (Pprev - P)
|
||||
r = T.new((Q.toNum.sqrt + 0.5).floor)
|
||||
if ((i & 1) == 0 && r*r == Q) break
|
||||
Qprev = q
|
||||
Pprev = P
|
||||
i = i + 1
|
||||
}
|
||||
if (i < B) {
|
||||
b = (Po - P) / r
|
||||
Pprev = P = b*r + P
|
||||
Qprev = r
|
||||
Q = (D - Pprev*Pprev) / Qprev
|
||||
i = 0
|
||||
while (true) {
|
||||
b = (Po + P) / Q
|
||||
Pprev = P
|
||||
P = b * Q - P
|
||||
q = Q
|
||||
Q = Qprev + b * (Pprev - P)
|
||||
Qprev = q
|
||||
i = i + 1
|
||||
if (P == Pprev) break
|
||||
}
|
||||
r = T.gcd(n, Qprev)
|
||||
if (r != T.one && r != n) return (r is ULong) ? r : ULong.new(r.toString)
|
||||
}
|
||||
}
|
||||
return ULong.zero
|
||||
}
|
||||
|
||||
var examples = [
|
||||
"2501",
|
||||
"12851",
|
||||
"13289",
|
||||
"75301",
|
||||
"120787",
|
||||
"967009",
|
||||
"997417",
|
||||
"7091569",
|
||||
"13290059",
|
||||
"42854447",
|
||||
"223553581",
|
||||
"2027651281",
|
||||
"11111111111",
|
||||
"100895598169",
|
||||
"1002742628021",
|
||||
"60012462237239",
|
||||
"287129523414791",
|
||||
"9007199254740931",
|
||||
"11111111111111111",
|
||||
"314159265358979323",
|
||||
"384307168202281507",
|
||||
"419244183493398773",
|
||||
"658812288346769681",
|
||||
"922337203685477563",
|
||||
"1000000000000000127",
|
||||
"1152921505680588799",
|
||||
"1537228672809128917",
|
||||
"4611686018427387877"
|
||||
]
|
||||
|
||||
System.print("Integer Factor Quotient")
|
||||
System.print("------------------------------------------")
|
||||
for (example in examples) {
|
||||
var N = ULong.new(example)
|
||||
var fact = squfof.call(N)
|
||||
var quot = (fact.isZero) ? "fail" : (N / fact).toString
|
||||
Fmt.print("$-20s $-10s $s", N, fact, quot)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue