%mathpiper,def="Factors"

/*------------------------------------------------------------------------
 *    Started 091222
 *    revised 100108-22
 *    revised 100215
 *    major refactoring 100425
 *    convert polynomial factoring to use JAS library  100511
 *    Another major refactoring -- 100529
 *    Ready for initial commit     100610
 *    Modifications                100727
 *------------------------------------------------------------------------*/

//Retract("Factors",*);


/* --------------    LISTS    ---------------*/

10 # Factors( L_IsList ) <-- nFactors /@ L;


/* -------------    NUMBERS    --------------*/


10 # Factors(n_IsPositiveInteger) <--  
[
    If( n < 1600, FactorsSmallInteger(n), FactorizeInt(n) );
];



15 # Factors(n_IsNegativeInteger) <--
[
    If(InVerboseMode(),Tell("Factors_negInt",n));
    Local(en,ans);
    en  := -n;
    ans := {-1,1}:If( en < 1600, FactorsSmallInteger(en), FactorizeInt(en) );
];


20 # Factors(p_IsRational)_(Denominator(p) != 1) <-- 
[
    If(InVerboseMode(),Tell("Factors_ratNum",p));
    Local(sgn,num,den,fn,fd,f,ans);
    sgn := 1;
    If(p < 0, [p := -p; sgn := -1;]);
    num := Numerator(p);
    den := Denominator(p);
    fn := FactorizeInt(num);
    If(sgn < 0, fn := {-1,1}:fn );
    fd := FactorizeInt(den);
    If(InVerboseMode(),Tell("  ",{fn,fd}));
    ForEach(f,fd)
     [
         DestructiveReplace(f,2,-f[2]);
         DestructiveAppend(fn,f);
     ];
    ans := fn;
]; 
             

25 # Factors(p_IsGaussianInteger)	<-- GaussianFactors(p);


30 # Factors(_p)_(Length(VarList(p))=0) <-- {{p,1}};


//40 # Factors(p_IsRationalFunction) <-- 
//[
//    If(InVerboseMode(),Tell("Factors_ratFunc",p));
//    jFactorsRationalFunc(p);
//];


50 # Factors( p_CanBeUni ) <-- 
[
    If(InVerboseMode(),Tell("Factors_uni",p));
    Local(res,len,newRes,ii,accum,n);
    res    := jFactorsPoly(p);
    //
    // Now, do a bit of fix-up for factors of (-1)^n
    //
    len    := Length(res);
    newRes := {};
    accum  := 1;    //  initialize number accumulator
    
    ForEach(r,res)
    [
        If(InVerboseMode(),Tell("      ",r));
        If( IsNumber(Eval(r[1])), 
          [ 
              n := r[1]^r[2];
              If(InVerboseMode(),Tell("            ",n));              
              accum := accum * n;
          ],
          DestructiveAppend(newRes,r)
        );
    ];
    If(InVerboseMode(),Tell("   ",{newRes,accum}));
    If(accum != 1, DestructiveInsert(newRes,1,{accum,1}));
    newRes;
];


60 # Factors( p_IsRationalFunction ) <--
[
    If(InVerboseMode(),Tell("Factors_ratFunc",p));
    Local(num,den,fn,fd,f);
    num := Numerator(p);
    den := Denominator(p);
    If(InVerboseMode(),Tell("   ",{num,den}));
    fn  := Factors(num);
    fd  := Factors(den);
    If(Not IsListOfLists(fd), fd := {fd});
    If(InVerboseMode(),Tell("       r ",{fn,fd}));
    ForEach(f,fd)
     [
         DestructiveReplace(f,2,-f[2]);
         DestructiveAppend(fn,f);
     ];
    fn;
];

100 # Factors( _p ) <--
[
    Tell("Factors__Fall-Through_cases",p);
];

%/mathpiper

    %output,preserve="false"
      Result: True
.   %/output

    %output,preserve="false"
      Processing...
.   %/output

    %output,preserve="false"
      Processing...
.   %/output





%mathpiper_docs,name="Factors",categories="User Functions;Number Theory"
*CMD Factors --- factorization
*STD
*CALL
	Factors(x)

*PARMS

{x} -- integer or univariate polynomial

*DESC

This function decomposes the integer number {x} into a product of
numbers. 
Alternatively, if {x} is a univariate polynomial, it is
decomposed into irreducible polynomials.  If {x} is a polynomial
"over the integers", the irreducible polynomial factors will also
be returned in the (unique) form with integer coefficients.

The factorization is returned as a list of pairs. The first member of
each pair is the factor, while the second member denotes the power to
which this factor should be raised. So the factorization
$x = p1^n1 * ... * p9^n9$
is returned as {{{p1,n1}, ..., {p9,n9}}}.

Programmer: Yacas Team + Sherm Ostrowsky

*E.G.
In> Factors(24)
Result: {{2,3},{3,1}}

In> Factors(32*x^3+32*x^2-70*x-75)
Result: {{4*x+5,2},{2*x-3,1}}

*SEE Factor, IsPrime, GaussianFactors
%/mathpiper_docs



