836 lines
22 KiB
Java
836 lines
22 KiB
Java
package org.nevec.rjm;
|
|
|
|
import java.math.BigInteger;
|
|
import java.util.Collections;
|
|
import java.util.Vector;
|
|
|
|
import it.cavallium.warppi.util.Error;
|
|
|
|
/**
|
|
* Factored integers.
|
|
* This class contains a non-negative integer with the prime factor
|
|
* decomposition attached.
|
|
*
|
|
* @since 2006-08-14
|
|
* @since 2012-02-14 The internal representation contains the bases, and becomes
|
|
* sparser if few
|
|
* prime factors are present.
|
|
* @author Richard J. Mathar
|
|
*/
|
|
public class Ifactor implements Cloneable, Comparable<Ifactor> {
|
|
/**
|
|
* The standard representation of the number
|
|
*/
|
|
public BigInteger n;
|
|
|
|
/*
|
|
* The bases and powers of the prime factorization.
|
|
* representation n = primeexp[0]^primeexp[1]*primeexp[2]^primeexp[3]*...
|
|
* The value 0 is represented by an empty vector, the value 1 by a vector of
|
|
* length 1
|
|
* with a single power of 0.
|
|
*/
|
|
public Vector<Integer> primeexp;
|
|
|
|
final public static Ifactor ONE = new Ifactor(1);
|
|
|
|
final public static Ifactor ZERO = new Ifactor(0);
|
|
|
|
/**
|
|
* Constructor given an integer.
|
|
* constructor with an ordinary integer
|
|
*
|
|
* @param number
|
|
* the standard representation of the integer
|
|
*/
|
|
public Ifactor(int number) {
|
|
n = new BigInteger("" + number);
|
|
primeexp = new Vector<>();
|
|
if (number > 1) {
|
|
int primindx = 0;
|
|
final Prime primes = new Prime();
|
|
/*
|
|
* Test division against all primes.
|
|
*/
|
|
while (number > 1) {
|
|
int ex = 0;
|
|
/*
|
|
* primindx=0 refers to 2, =1 to 3, =2 to 5, =3 to 7 etc
|
|
*/
|
|
final int p = primes.at(primindx).intValue();
|
|
while (number % p == 0) {
|
|
ex++;
|
|
number /= p;
|
|
if (number == 1) {
|
|
break;
|
|
}
|
|
}
|
|
if (ex > 0) {
|
|
primeexp.add(new Integer(p));
|
|
primeexp.add(new Integer(ex));
|
|
}
|
|
primindx++;
|
|
}
|
|
} else if (number == 1) {
|
|
primeexp.add(new Integer(1));
|
|
primeexp.add(new Integer(0));
|
|
}
|
|
} /* Ifactor */
|
|
|
|
/**
|
|
* Constructor given a BigInteger .
|
|
* Constructor with an ordinary integer, calling a prime factor
|
|
* decomposition.
|
|
*
|
|
* @param number
|
|
* the BigInteger representation of the integer
|
|
*/
|
|
public Ifactor(BigInteger number) {
|
|
n = number;
|
|
primeexp = new Vector<>();
|
|
if (number.compareTo(BigInteger.ONE) == 0) {
|
|
primeexp.add(new Integer(1));
|
|
primeexp.add(new Integer(0));
|
|
} else {
|
|
int primindx = 0;
|
|
final Prime primes = new Prime();
|
|
/*
|
|
* Test for division against all primes.
|
|
*/
|
|
while (number.compareTo(BigInteger.ONE) == 1) {
|
|
int ex = 0;
|
|
final BigInteger p = primes.at(primindx);
|
|
while (number.remainder(p).compareTo(BigInteger.ZERO) == 0) {
|
|
ex++;
|
|
number = number.divide(p);
|
|
if (number.compareTo(BigInteger.ONE) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (ex > 0) {
|
|
primeexp.add(new Integer(p.intValue()));
|
|
primeexp.add(new Integer(ex));
|
|
}
|
|
primindx++;
|
|
}
|
|
}
|
|
} /* Ifactor */
|
|
|
|
/**
|
|
* Constructor given a list of exponents of the prime factor decomposition.
|
|
*
|
|
* @param pows
|
|
* the vector with the sorted list of exponents.
|
|
* pows[0] is the exponent of 2, pows[1] the exponent of 3,
|
|
* pows[2] the exponent of 5 etc.
|
|
* Note that this list does not include the primes, but assumes a
|
|
* continuous prime-smooth basis.
|
|
*/
|
|
public Ifactor(final Vector<Integer> pows) {
|
|
primeexp = new Vector<>(2 * pows.size());
|
|
if (pows.size() > 0) {
|
|
n = BigInteger.ONE;
|
|
final Prime primes = new Prime();
|
|
/*
|
|
* Build the full number by the product of all powers of the primes.
|
|
*/
|
|
for (int primindx = 0; primindx < pows.size(); primindx++) {
|
|
final int ex = pows.elementAt(primindx).intValue();
|
|
final BigInteger p = primes.at(primindx);
|
|
n = n.multiply(p.pow(ex));
|
|
primeexp.add(new Integer(p.intValue()));
|
|
primeexp.add(new Integer(ex));
|
|
}
|
|
} else {
|
|
n = BigInteger.ZERO;
|
|
}
|
|
} /* Ifactor */
|
|
|
|
/**
|
|
* Copy constructor.
|
|
*
|
|
* @param oth
|
|
* the value to be copied
|
|
*/
|
|
public Ifactor(final Ifactor oth) {
|
|
n = oth.n;
|
|
primeexp = oth.primeexp;
|
|
} /* Ifactor */
|
|
|
|
/**
|
|
* Deep copy.
|
|
*
|
|
* @since 2009-08-14
|
|
*/
|
|
@Override
|
|
public Ifactor clone() {
|
|
/*
|
|
* Line not used:
|
|
*
|
|
* Vector<Integer> p = (Vector<Integer>)primeexp.clone();
|
|
*
|
|
*/
|
|
final Ifactor cl = new Ifactor(0);
|
|
cl.n = new BigInteger("" + n);
|
|
return cl;
|
|
} /* Ifactor.clone */
|
|
|
|
/**
|
|
* Comparison of two numbers.
|
|
* The value of this method is in allowing the Vector<>.contains() calls
|
|
* that use the value,
|
|
* not the reference for comparison.
|
|
*
|
|
* @param oth
|
|
* the number to compare this with.
|
|
* @return true if both are the same numbers, false otherwise.
|
|
*/
|
|
public boolean equals(final Ifactor oth) {
|
|
return n.compareTo(oth.n) == 0;
|
|
} /* Ifactor.equals */
|
|
|
|
/**
|
|
* Multiply with another positive integer.
|
|
*
|
|
* @param oth
|
|
* the second factor.
|
|
* @return the product of both numbers.
|
|
*/
|
|
public Ifactor multiply(final BigInteger oth) {
|
|
/*
|
|
* the optimization is to factorize oth _before_ multiplying
|
|
*/
|
|
return multiply(new Ifactor(oth));
|
|
} /* Ifactor.multiply */
|
|
|
|
/**
|
|
* Multiply with another positive integer.
|
|
*
|
|
* @param oth
|
|
* the second factor.
|
|
* @return the product of both numbers.
|
|
*/
|
|
public Ifactor multiply(final int oth) {
|
|
/*
|
|
* the optimization is to factorize oth _before_ multiplying
|
|
*/
|
|
return multiply(new Ifactor(oth));
|
|
} /* Ifactor.multiply */
|
|
|
|
/**
|
|
* Multiply with another positive integer.
|
|
*
|
|
* @param oth
|
|
* the second factor.
|
|
* @return the product of both numbers.
|
|
*/
|
|
public Ifactor multiply(final Ifactor oth) {
|
|
/*
|
|
* This might be done similar to the lcm() implementation by adding
|
|
* the powers of the components and calling the constructor with the
|
|
* list of exponents. This here is the simplest implementation, but slow
|
|
* because
|
|
* it calls another prime factorization of the product:
|
|
* return( new Ifactor(n.multiply(oth.n))) ;
|
|
*/
|
|
return multGcdLcm(oth, 0);
|
|
}
|
|
|
|
/**
|
|
* Lowest common multiple of this with oth.
|
|
*
|
|
* @param oth
|
|
* the second parameter of lcm(this,oth)
|
|
* @return the lowest common multiple of both numbers. Returns zero
|
|
* if any of both arguments is zero.
|
|
*/
|
|
public Ifactor lcm(final Ifactor oth) {
|
|
return multGcdLcm(oth, 2);
|
|
}
|
|
|
|
/**
|
|
* Greatest common divisor of this and oth.
|
|
*
|
|
* @param oth
|
|
* the second parameter of gcd(this,oth)
|
|
* @return the lowest common multiple of both numbers. Returns zero
|
|
* if any of both arguments is zero.
|
|
*/
|
|
public Ifactor gcd(final Ifactor oth) {
|
|
return multGcdLcm(oth, 1);
|
|
}
|
|
|
|
/**
|
|
* Multiply with another positive integer.
|
|
*
|
|
* @param oth
|
|
* the second factor.
|
|
* @param type
|
|
* 0 to multiply, 1 for gcd, 2 for lcm
|
|
* @return the product, gcd or lcm of both numbers.
|
|
*/
|
|
protected Ifactor multGcdLcm(final Ifactor oth, final int type) {
|
|
final Ifactor prod = new Ifactor(0);
|
|
/*
|
|
* skip the case where 0*something =0, falling thru to the empty
|
|
* representation for 0
|
|
*/
|
|
if (primeexp.size() != 0 && oth.primeexp.size() != 0) {
|
|
/*
|
|
* Cases of 1 times something return something.
|
|
* Cases of lcm(1, something) return something.
|
|
* Cases of gcd(1, something) return 1.
|
|
*/
|
|
if (primeexp.firstElement().intValue() == 1 && type == 0) {
|
|
return oth;
|
|
} else if (primeexp.firstElement().intValue() == 1 && type == 2) {
|
|
return oth;
|
|
} else if (primeexp.firstElement().intValue() == 1 && type == 1) {
|
|
return this;
|
|
} else if (oth.primeexp.firstElement().intValue() == 1 && type == 0) {
|
|
return this;
|
|
} else if (oth.primeexp.firstElement().intValue() == 1 && type == 2) {
|
|
return this;
|
|
} else if (oth.primeexp.firstElement().intValue() == 1 && type == 1) {
|
|
return oth;
|
|
} else {
|
|
int idxThis = 0;
|
|
int idxOth = 0;
|
|
switch (type) {
|
|
case 0:
|
|
prod.n = n.multiply(oth.n);
|
|
break;
|
|
case 1:
|
|
prod.n = n.gcd(oth.n);
|
|
break;
|
|
case 2:
|
|
/*
|
|
* the awkward way, lcm = product divided by gcd
|
|
*/
|
|
prod.n = n.multiply(oth.n).divide(n.gcd(oth.n));
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* scan both representations left to right, increasing prime
|
|
* powers
|
|
*/
|
|
while (idxOth < oth.primeexp.size() || idxThis < primeexp.size()) {
|
|
if (idxOth >= oth.primeexp.size()) {
|
|
/*
|
|
* exhausted the list in oth.primeexp; copy over the
|
|
* remaining 'this'
|
|
* if multiplying or lcm, discard if gcd.
|
|
*/
|
|
if (type == 0 || type == 2) {
|
|
prod.primeexp.add(primeexp.elementAt(idxThis));
|
|
prod.primeexp.add(primeexp.elementAt(idxThis + 1));
|
|
}
|
|
idxThis += 2;
|
|
} else if (idxThis >= primeexp.size()) {
|
|
/*
|
|
* exhausted the list in primeexp; copy over the
|
|
* remaining 'oth'
|
|
*/
|
|
if (type == 0 || type == 2) {
|
|
prod.primeexp.add(oth.primeexp.elementAt(idxOth));
|
|
prod.primeexp.add(oth.primeexp.elementAt(idxOth + 1));
|
|
}
|
|
idxOth += 2;
|
|
} else {
|
|
Integer p;
|
|
int ex;
|
|
switch (primeexp.elementAt(idxThis).compareTo(oth.primeexp.elementAt(idxOth))) {
|
|
case 0:
|
|
/* same prime bases p in both factors */
|
|
p = primeexp.elementAt(idxThis);
|
|
switch (type) {
|
|
case 0:
|
|
/* product means adding exponents */
|
|
ex = primeexp.elementAt(idxThis + 1).intValue() + oth.primeexp.elementAt(idxOth + 1).intValue();
|
|
break;
|
|
case 1:
|
|
/* gcd means minimum of exponents */
|
|
ex = Math.min(primeexp.elementAt(idxThis + 1).intValue(), oth.primeexp.elementAt(idxOth + 1).intValue());
|
|
break;
|
|
default:
|
|
/* lcm means maximum of exponents */
|
|
ex = Math.max(primeexp.elementAt(idxThis + 1).intValue(), oth.primeexp.elementAt(idxOth + 1).intValue());
|
|
break;
|
|
}
|
|
prod.primeexp.add(p);
|
|
prod.primeexp.add(new Integer(ex));
|
|
idxOth += 2;
|
|
idxThis += 2;
|
|
break;
|
|
case 1:
|
|
/*
|
|
* this prime base bigger than the other and
|
|
* taken later
|
|
*/
|
|
if (type == 0 || type == 2) {
|
|
prod.primeexp.add(oth.primeexp.elementAt(idxOth));
|
|
prod.primeexp.add(oth.primeexp.elementAt(idxOth + 1));
|
|
}
|
|
idxOth += 2;
|
|
break;
|
|
default:
|
|
/*
|
|
* this prime base smaller than the other and
|
|
* taken now
|
|
*/
|
|
if (type == 0 || type == 2) {
|
|
prod.primeexp.add(primeexp.elementAt(idxThis));
|
|
prod.primeexp.add(primeexp.elementAt(idxThis + 1));
|
|
}
|
|
idxThis += 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return prod;
|
|
} /* Ifactor.multGcdLcm */
|
|
|
|
/**
|
|
* Integer division through another positive integer.
|
|
*
|
|
* @param oth
|
|
* the denominator.
|
|
* @return the division of this through the oth, discarding the remainder.
|
|
*/
|
|
public Ifactor divide(final Ifactor oth) {
|
|
/*
|
|
* todo: it'd probably be faster to cancel the gcd(this,oth) first in
|
|
* the prime power
|
|
* representation, which would avoid a more strenous factorization of
|
|
* the integer ratio
|
|
*/
|
|
return new Ifactor(n.divide(oth.n));
|
|
} /* Ifactor.divide */
|
|
|
|
/**
|
|
* Summation with another positive integer
|
|
*
|
|
* @param oth
|
|
* the other term.
|
|
* @return the sum of both numbers
|
|
*/
|
|
public Ifactor add(final BigInteger oth) {
|
|
/*
|
|
* avoid refactorization if oth is zero...
|
|
*/
|
|
if (oth.compareTo(BigInteger.ZERO) != 0) {
|
|
return new Ifactor(n.add(oth));
|
|
} else {
|
|
return this;
|
|
}
|
|
} /* Ifactor.add */
|
|
|
|
/**
|
|
* Exponentiation with a positive integer.
|
|
*
|
|
* @param exponent
|
|
* the non-negative exponent
|
|
* @return n^exponent. If exponent=0, the result is 1.
|
|
*/
|
|
public Ifactor pow(final int exponent) throws ArithmeticException {
|
|
/*
|
|
* three simple cases first
|
|
*/
|
|
if (exponent < 0) {
|
|
throw new ArithmeticException("Cannot raise " + toString() + " to negative " + exponent);
|
|
} else if (exponent == 0) {
|
|
return new Ifactor(1);
|
|
} else if (exponent == 1) {
|
|
return this;
|
|
}
|
|
|
|
/*
|
|
* general case, the vector with the prime factor powers, which are
|
|
* component-wise
|
|
* exponentiation of the individual prime factor powers.
|
|
*/
|
|
final Ifactor pows = new Ifactor(0);
|
|
for (int i = 0; i < primeexp.size(); i += 2) {
|
|
final Integer p = primeexp.elementAt(i);
|
|
final int ex = primeexp.elementAt(i + 1).intValue();
|
|
pows.primeexp.add(p);
|
|
pows.primeexp.add(new Integer(ex * exponent));
|
|
}
|
|
return pows;
|
|
} /* Ifactor.pow */
|
|
|
|
/**
|
|
* Pulling the r-th root.
|
|
*
|
|
* @param r
|
|
* the positive or negative (nonzero) root.
|
|
* @return n^(1/r).
|
|
* The return value falls into the Ifactor class if r is positive,
|
|
* but if r is negative
|
|
* a Rational type is needed.
|
|
* @throws Error
|
|
* @since 2009-05-18
|
|
*/
|
|
public Rational root(final int r) throws ArithmeticException, Error {
|
|
if (r == 0) {
|
|
throw new ArithmeticException("Cannot pull zeroth root of " + toString());
|
|
} else if (r < 0) {
|
|
/*
|
|
* a^(-1/b)= 1/(a^(1/b))
|
|
*/
|
|
final Rational invRoot = root(-r);
|
|
return Rational.ONE.divide(invRoot);
|
|
} else {
|
|
final BigInteger pows = BigInteger.ONE;
|
|
for (int i = 0; i < primeexp.size(); i += 2) {
|
|
/*
|
|
* all exponents must be multiples of r to succeed (that is, to
|
|
* stay in the range of rational results).
|
|
*/
|
|
final int ex = primeexp.elementAt(i + 1).intValue();
|
|
if (ex % r != 0) {
|
|
throw new ArithmeticException("Cannot pull " + r + "th root of " + toString());
|
|
}
|
|
|
|
pows.multiply(new BigInteger("" + primeexp.elementAt(i)).pow(ex / r));
|
|
}
|
|
/*
|
|
* convert result to a Rational; unfortunately this will loose the
|
|
* prime factorization
|
|
*/
|
|
return new Rational(pows);
|
|
}
|
|
} /* Ifactor.root */
|
|
|
|
/**
|
|
* The set of positive divisors.
|
|
*
|
|
* @return the vector of divisors of the absolute value, sorted.
|
|
* @since 2010-08-27
|
|
*/
|
|
public Vector<BigInteger> divisors() {
|
|
/*
|
|
* Recursive approach: the divisors of p1^e1*p2^e2*..*py^ey*pz^ez are
|
|
* the divisors that don't contain the factor pz, and the
|
|
* the divisors that contain any power of pz between 1 and up to ez
|
|
* multiplied
|
|
* by 1 or by a product that contains the factors p1..py.
|
|
*/
|
|
final Vector<BigInteger> d = new Vector<>();
|
|
if (n.compareTo(BigInteger.ZERO) == 0) {
|
|
return d;
|
|
}
|
|
d.add(BigInteger.ONE);
|
|
if (n.compareTo(BigInteger.ONE) > 0) {
|
|
/* Computes sigmaIncopml(p1^e*p2^e2...*py^ey) */
|
|
final Ifactor dp = dropPrime();
|
|
|
|
/* get ez */
|
|
final int ez = primeexp.lastElement().intValue();
|
|
|
|
final Vector<BigInteger> partd = dp.divisors();
|
|
|
|
/* obtain pz by lookup in the prime list */
|
|
final BigInteger pz = new BigInteger(primeexp.elementAt(primeexp.size() - 2).toString());
|
|
|
|
/*
|
|
* the output contains all products of the form partd[]*pz^ez, ez>0,
|
|
* and with the exception of the 1, all these are appended.
|
|
*/
|
|
for (int i = 1; i < partd.size(); i++) {
|
|
d.add(partd.elementAt(i));
|
|
}
|
|
for (int e = 1; e <= ez; e++) {
|
|
final BigInteger pzez = pz.pow(e);
|
|
for (int i = 0; i < partd.size(); i++) {
|
|
d.add(partd.elementAt(i).multiply(pzez));
|
|
}
|
|
}
|
|
}
|
|
Collections.sort(d);
|
|
return d;
|
|
} /* Ifactor.divisors */
|
|
|
|
/**
|
|
* Sum of the divisors of the number.
|
|
*
|
|
* @return the sum of all divisors of the number, 1+....+n.
|
|
*/
|
|
public Ifactor sigma() {
|
|
return sigma(1);
|
|
} /* Ifactor.sigma */
|
|
|
|
/**
|
|
* Sum of the k-th powers of divisors of the number.
|
|
*
|
|
* @return the sum of all divisors of the number, 1^k+....+n^k.
|
|
*/
|
|
public Ifactor sigma(final int k) {
|
|
/*
|
|
* the question is whether keeping a factorization is worth the effort
|
|
* or whether one should simply multiply these to return a BigInteger...
|
|
*/
|
|
if (n.compareTo(BigInteger.ONE) == 0) {
|
|
return Ifactor.ONE;
|
|
} else if (n.compareTo(BigInteger.ZERO) == 0) {
|
|
return Ifactor.ZERO;
|
|
} else {
|
|
/*
|
|
* multiplicative: sigma_k(p^e) = [p^(k*(e+1))-1]/[p^k-1]
|
|
* sigma_0(p^e) = e+1.
|
|
*/
|
|
Ifactor resul = Ifactor.ONE;
|
|
for (int i = 0; i < primeexp.size(); i += 2) {
|
|
final int ex = primeexp.elementAt(i + 1).intValue();
|
|
if (k == 0) {
|
|
resul = resul.multiply(ex + 1);
|
|
} else {
|
|
final Integer p = primeexp.elementAt(i);
|
|
final BigInteger num = new BigInteger(p.toString()).pow(k * (ex + 1)).subtract(BigInteger.ONE);
|
|
final BigInteger deno = new BigInteger(p.toString()).pow(k).subtract(BigInteger.ONE);
|
|
/*
|
|
* This division is of course exact, no remainder
|
|
* The costly prime factorization is hidden here.
|
|
*/
|
|
final Ifactor f = new Ifactor(num.divide(deno));
|
|
resul = resul.multiply(f);
|
|
}
|
|
}
|
|
return resul;
|
|
}
|
|
} /* Ifactor.sigma */
|
|
|
|
/**
|
|
* Divide through the highest possible power of the highest prime.
|
|
* If the current number is the prime factor product p1^e1 * p2*e2*
|
|
* p3^e3*...*py^ey * pz^ez,
|
|
* the value returned has the final factor pz^ez eliminated, which gives
|
|
* p1^e1 * p2*e2* p3^e3*...*py^ey.
|
|
*
|
|
* @return the new integer obtained by removing the highest prime power.
|
|
* If this here represents 0 or 1, it is returned without change.
|
|
* @since 2006-08-20
|
|
*/
|
|
public Ifactor dropPrime() {
|
|
/*
|
|
* the cases n==1 or n ==0
|
|
*/
|
|
if (n.compareTo(BigInteger.ONE) <= 0) {
|
|
return this;
|
|
}
|
|
|
|
/*
|
|
* The cases n>1
|
|
* Start empty. Copy all but the last factor over to the result
|
|
* the vector with the new prime factor powers, which contain the
|
|
* old prime factor powers up to but not including the last one.
|
|
*/
|
|
final Ifactor pows = new Ifactor(0);
|
|
pows.n = BigInteger.ONE;
|
|
for (int i = 0; i < primeexp.size() - 2; i += 2) {
|
|
pows.primeexp.add(primeexp.elementAt(i));
|
|
pows.primeexp.add(primeexp.elementAt(i + 1));
|
|
final BigInteger p = new BigInteger(primeexp.elementAt(i).toString());
|
|
final int ex = primeexp.elementAt(i + 1).intValue();
|
|
pows.n = pows.n.multiply(p.pow(ex));
|
|
}
|
|
return pows;
|
|
} /* Ifactor.dropPrime */
|
|
|
|
/**
|
|
* Test whether this is a square of an integer (perfect square).
|
|
*
|
|
* @return true if this is an integer squared (including 0), else false
|
|
*/
|
|
public boolean issquare() {
|
|
/*
|
|
* check the exponents, located at the odd-indexed positions
|
|
*/
|
|
for (int i = 1; i < primeexp.size(); i += 2) {
|
|
if (primeexp.elementAt(i).intValue() % 2 != 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
} /* Ifactor.issquare */
|
|
|
|
/**
|
|
* The sum of the prime factor exponents, with multiplicity.
|
|
*
|
|
* @return the sum over the primeexp numbers
|
|
*/
|
|
public int bigomega() {
|
|
int resul = 0;
|
|
for (int i = 1; i < primeexp.size(); i += 2) {
|
|
resul += primeexp.elementAt(i).intValue();
|
|
}
|
|
return resul;
|
|
} /* Ifactor.bigomega */
|
|
|
|
/**
|
|
* The sum of the prime factor exponents, without multiplicity.
|
|
*
|
|
* @return the number of distinct prime factors.
|
|
* @since 2008-10-16
|
|
*/
|
|
public int omega() {
|
|
return primeexp.size() / 2;
|
|
} /* Ifactor.omega */
|
|
|
|
/**
|
|
* The square-free part.
|
|
*
|
|
* @return the minimum m such that m times this number is a square.
|
|
* @since 2008-10-16
|
|
*/
|
|
public BigInteger core() {
|
|
BigInteger resul = BigInteger.ONE;
|
|
for (int i = 0; i < primeexp.size(); i += 2) {
|
|
if (primeexp.elementAt(i + 1).intValue() % 2 != 0) {
|
|
resul = resul.multiply(new BigInteger(primeexp.elementAt(i).toString()));
|
|
}
|
|
}
|
|
return resul;
|
|
} /* Ifactor.core */
|
|
|
|
/**
|
|
* The Moebius function.
|
|
* 1 if n=1, else, if k is the number of distinct prime factors, return
|
|
* (-1)^k,
|
|
* else, if k has repeated prime factors, return 0.
|
|
*
|
|
* @return the moebius function.
|
|
*/
|
|
public int moebius() {
|
|
if (n.compareTo(BigInteger.ONE) <= 0) {
|
|
return 1;
|
|
}
|
|
/* accumulate number of different primes in k */
|
|
int k = 1;
|
|
for (int i = 0; i < primeexp.size(); i += 2) {
|
|
final int e = primeexp.elementAt(i + 1).intValue();
|
|
if (e > 1) {
|
|
return 0;
|
|
} else if (e == 1) {
|
|
/* accumulates (-1)^k */
|
|
k *= -1;
|
|
}
|
|
|
|
}
|
|
return k;
|
|
} /* Ifactor.moebius */
|
|
|
|
/**
|
|
* Maximum of two values.
|
|
*
|
|
* @param oth
|
|
* the number to compare this with.
|
|
* @return the larger of the two values.
|
|
*/
|
|
public Ifactor max(final Ifactor oth) {
|
|
if (n.compareTo(oth.n) >= 0) {
|
|
return this;
|
|
} else {
|
|
return oth;
|
|
}
|
|
} /* Ifactor.max */
|
|
|
|
/**
|
|
* Minimum of two values.
|
|
*
|
|
* @param oth
|
|
* the number to compare this with.
|
|
* @return the smaller of the two values.
|
|
*/
|
|
public Ifactor min(final Ifactor oth) {
|
|
if (n.compareTo(oth.n) <= 0) {
|
|
return this;
|
|
} else {
|
|
return oth;
|
|
}
|
|
} /* Ifactor.min */
|
|
|
|
/**
|
|
* Maximum of a list of values.
|
|
*
|
|
* @param set
|
|
* list of numbers.
|
|
* @return the largest in the list.
|
|
*/
|
|
public static Ifactor max(final Vector<Ifactor> set) {
|
|
Ifactor resul = set.elementAt(0);
|
|
for (int i = 1; i < set.size(); i++) {
|
|
resul = resul.max(set.elementAt(i));
|
|
}
|
|
return resul;
|
|
} /* Ifactor.max */
|
|
|
|
/**
|
|
* Minimum of a list of values.
|
|
*
|
|
* @param set
|
|
* list of numbers.
|
|
* @return the smallest in the list.
|
|
*/
|
|
public static Ifactor min(final Vector<Ifactor> set) {
|
|
Ifactor resul = set.elementAt(0);
|
|
for (int i = 1; i < set.size(); i++) {
|
|
resul = resul.min(set.elementAt(i));
|
|
}
|
|
return resul;
|
|
} /* Ifactor.min */
|
|
|
|
/**
|
|
* Compare value against another Ifactor
|
|
*
|
|
* @param oth
|
|
* The value to be compared agains.
|
|
* @return 1, 0 or -1 according to being larger, equal to or smaller than
|
|
* oth.
|
|
* @since 2012-02-15
|
|
*/
|
|
@Override
|
|
public int compareTo(final Ifactor oth) {
|
|
return n.compareTo(oth.n);
|
|
} /* compareTo */
|
|
|
|
/**
|
|
* Convert to printable format
|
|
*
|
|
* @return a string of the form n:prime^pow*prime^pow*prime^pow...
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
String resul = new String(n.toString() + ":");
|
|
if (n.compareTo(BigInteger.ONE) == 0) {
|
|
resul += "1";
|
|
} else {
|
|
boolean firstMul = true;
|
|
for (int i = 0; i < primeexp.size(); i += 2) {
|
|
if (!firstMul) {
|
|
resul += "*";
|
|
}
|
|
if (primeexp.elementAt(i + 1).intValue() > 1) {
|
|
resul += primeexp.elementAt(i).toString() + "^" + primeexp.elementAt(i + 1).toString();
|
|
} else {
|
|
resul += primeexp.elementAt(i).toString();
|
|
}
|
|
firstMul = false;
|
|
}
|
|
}
|
|
return resul;
|
|
} /* Ifactor.toString */
|
|
|
|
/**
|
|
* Test program.
|
|
* It takes a single argument n and prints the integer factorizaton.<br>
|
|
* java -cp . org.nevec.rjm.Ifactor n<br>
|
|
*/
|
|
public static void main(final String[] args) throws Exception {
|
|
final BigInteger n = new BigInteger(args[0]);
|
|
System.out.println(new Ifactor(n));
|
|
} /* Ifactor.main */
|
|
} /* Ifactor */
|