UNPKG

algebrite

Version:

Computer Algebra System in Coffeescript

176 lines (116 loc) 2.56 kB
# Factor using the Pollard rho method n_factor_number = 0 factor_number = -> h = 0 save() p1 = pop() # 0 or 1? if (equaln(p1, 0) || equaln(p1, 1) || equaln(p1, -1)) push(p1) restore() return n_factor_number = p1.q.a h = tos factor_a() if (tos - h > 1) list(tos - h) push_symbol(MULTIPLY) swap() cons() restore() # factor using table look-up, then switch to rho method if necessary # From TAOCP Vol. 2 by Knuth, p. 380 (Algorithm A) factor_a = -> k = 0 if (n_factor_number.isNegative()) n_factor_number = setSignTo(n_factor_number, 1) push_integer(-1) for k in [0...10000] try_kth_prime(k) # if n_factor_number is 1 then we're done if (n_factor_number.compare(1) == 0) return factor_b() try_kth_prime = (k) -> count = 0 d = mint(primetab[k]) count = 0 while (1) # if n_factor_number is 1 then we're done if (n_factor_number.compare(1) == 0) if (count) push_factor(d, count) return [q,r] = mdivrem(n_factor_number, d) # continue looping while remainder is zero if (r.isZero()) count++ n_factor_number = q else break if (count) push_factor(d, count) # q = n_factor_number/d, hence if q < d then # n_factor_number < d^2 so n_factor_number is prime if (mcmp(q, d) == -1) push_factor(n_factor_number, 1) n_factor_number = mint(1) # From TAOCP Vol. 2 by Knuth, p. 385 (Algorithm B) factor_b = -> k = 0 l = 0 bigint_one = mint(1) x = mint(5) xprime = mint(2) k = 1 l = 1 while (1) if (mprime(n_factor_number)) push_factor(n_factor_number, 1) return 0 while (1) if (esc_flag) stop("esc") # g = gcd(x' - x, n_factor_number) t = msub(xprime, x) t = setSignTo(t,1) g = mgcd(t, n_factor_number) if (MEQUAL(g, 1)) if (--k == 0) xprime = x l *= 2 k = l # x = (x ^ 2 + 1) mod n_factor_number t = mmul(x, x) x = madd(t, bigint_one) t = mmod(x, n_factor_number) x = t continue push_factor(g, 1) if (mcmp(g, n_factor_number) == 0) return -1 # n_factor_number = n_factor_number / g t = mdiv(n_factor_number, g) n_factor_number = t # x = x mod n_factor_number t = mmod(x, n_factor_number) x = t # xprime = xprime mod n_factor_number t = mmod(xprime, n_factor_number) xprime = t break push_factor = (d, count) -> p1 = new U() p1.k = NUM p1.q.a = d p1.q.b = mint(1) push(p1) if (count > 1) push_symbol(POWER) swap() p1 = new U() p1.k = NUM p1.q.a = mint(count) p1.q.b = mint(1) push(p1) list(3)