UNPKG

algebrite

Version:

Computer Algebra System in Coffeescript

368 lines (293 loc) 5.53 kB
# Factor a polynomial #define POLY p1 #define X p2 #define Z p3 #define A p4 #define B p5 #define Q p6 #define RESULT p7 #define FACTOR p8 polycoeff = 0 factpoly_expo = 0 factorpoly = -> save() p2 = pop() p1 = pop() if (!Find(p1, p2)) push(p1) restore() return if (!ispoly(p1, p2)) push(p1) restore() return if (!issymbol(p2)) push(p1) restore() return push(p1) push(p2) yyfactorpoly() restore() #----------------------------------------------------------------------------- # # Input: tos-2 true polynomial # # tos-1 free variable # # Output: factored polynomial on stack # #----------------------------------------------------------------------------- yyfactorpoly = -> h = 0 i = 0 save() p2 = pop() p1 = pop() h = tos if (isfloating(p1)) stop("floating point numbers in polynomial") polycoeff = tos push(p1) push(p2) factpoly_expo = coeff() - 1 rationalize_coefficients(h) # for univariate polynomials we could do factpoly_expo > 1 while (factpoly_expo > 0) if (iszero(stack[polycoeff+0])) push_integer(1) p4 = pop() push_integer(0) p5 = pop() else if (get_factor() == 0) if (verbosing) printf("no factor found\n") break push(p4) push(p2) multiply() push(p5) add() p8 = pop() if (verbosing) printf("success\nFACTOR=") print(p8) printf("\n") # factor out negative sign (not req'd because p4 > 1) #if 0 ### if (isnegativeterm(p4)) push(p8) negate() p8 = pop() push(p7) negate_noexpand() p7 = pop() ### #endif push(p7) push(p8) multiply_noexpand() p7 = pop() yydivpoly() while (factpoly_expo and iszero(stack[polycoeff+factpoly_expo])) factpoly_expo-- # unfactored polynomial push(zero) for i in [0..factpoly_expo] push(stack[polycoeff+i]) push(p2) push_integer(i) power() multiply() add() p1 = pop() if (verbosing) printf("POLY=") print(p1) printf("\n") # factor out negative sign if (factpoly_expo > 0 && isnegativeterm(stack[polycoeff+factpoly_expo])) push(p1) negate() p1 = pop() push(p7) negate_noexpand() p7 = pop() push(p7) push(p1) multiply_noexpand() p7 = pop() if (verbosing) printf("RESULT=") print(p7) printf("\n") stack[h] = p7 tos = h + 1 restore() rationalize_coefficients = (h) -> i = 0 # LCM of all polynomial coefficients p7 = one for i in [h...tos] push(stack[i]) denominator() push(p7) lcm() p7 = pop() # multiply each coefficient by RESULT for i in [h...tos] push(p7) push(stack[i]) multiply() stack[i] = pop() # reciprocate RESULT push(p7) reciprocate() p7 = pop() if DEBUG then console.log("rationalize_coefficients result") #print1(p7) get_factor = -> i = 0 j = 0 h = 0 a0 = 0 an = 0 na0 = 0 nan = 0 if (verbosing) push(zero) for i in [0..factpoly_expo] push(stack[polycoeff+i]) push(p2) push_integer(i) power() multiply() add() p1 = pop() printf("POLY=") print(p1) printf("\n") h = tos an = tos push(stack[polycoeff+factpoly_expo]) divisors_onstack() nan = tos - an a0 = tos push(stack[polycoeff+0]) divisors_onstack() na0 = tos - a0 if (verbosing) printf("divisors of base term") for i in [0...na0] printf(", ") print(stack[a0 + i]) printf("\n") printf("divisors of leading term") for i in [0...nan] printf(", ") print(stack[an + i]) printf("\n") # try roots for rootsTries_i in [0...nan] for rootsTries_j in [0...na0] #if DEBUG then console.log "nan: " + nan + " na0: " + na0 + " i: " + rootsTries_i + " j: " + rootsTries_j p4 = stack[an + rootsTries_i] p5 = stack[a0 + rootsTries_j] push(p5) push(p4) divide() negate() p3 = pop() Evalpoly() if (verbosing) printf("try A=") print(p4) printf(", B=") print(p5) printf(", root ") print(p2) printf("=-B/A=") print(p3) printf(", POLY(") print(p3) printf(")=") print(p6) printf("\n") if (iszero(p6)) tos = h if DEBUG then console.log "get_factor returning 1" return 1 push(p5) negate() p5 = pop() push(p3) negate() p3 = pop() Evalpoly() if (verbosing) printf("try A=") print(p4) printf(", B=") print(p5) printf(", root ") print(p2) printf("=-B/A=") print(p3) printf(", POLY(") print(p3) printf(")=") print(p6) printf("\n") if (iszero(p6)) tos = h if DEBUG then console.log "get_factor returning 1" return 1 tos = h if DEBUG then console.log "get_factor returning 0" return 0 #----------------------------------------------------------------------------- # # Divide a polynomial by Ax+B # # Input: polycoeff Dividend coefficients # # factpoly_expo Degree of dividend # # A As above # # B As above # # Output: polycoeff Contains quotient coefficients # #----------------------------------------------------------------------------- yydivpoly = -> i = 0 p6 = zero for i in [factpoly_expo...0] push(stack[polycoeff+i]) stack[polycoeff+i] = p6 push(p4) divide() p6 = pop() push(stack[polycoeff+i - 1]) push(p6) push(p5) multiply() subtract() stack[polycoeff+i - 1] = pop() stack[polycoeff+0] = p6 if DEBUG then console.log("yydivpoly Q:") #print1(p6) Evalpoly = -> i = 0 push(zero) for i in [factpoly_expo..0] push(p3) multiply() push(stack[polycoeff+i]) if DEBUG console.log("Evalpoly top of stack:") print1(stack[tos-i]) add() p6 = pop()