import java.math.BigInteger;
@author
class FutureFactorial {
public static BigInteger factorial(final BigInteger n) {
if (1 == n.signum()) return rangeProduct(ONE, n);
else
throw new IllegalArgumentException("n < 1");
}
static final BigInteger ONE = BigInteger.ONE;
static final BigInteger TWO = new BigInteger("2");
public static BigInteger rangeProduct(final BigInteger lo,
final BigInteger hi) {
if (lo.equals(hi)) return lo;
else if ((lo.add(ONE)).equals(hi)) return lo.multiply(hi);
else {
final BigInteger mid = (lo.add(hi)).divide(TWO);
Future loProd = (new Future() { { start(); }
public Object compute() {
return rangeProduct(lo, mid); }});
Future hiProd = (new Future() { { start(); }
public Object compute() {
return rangeProduct(mid.add(ONE), hi); }});
return ((BigInteger)loProd.value()).multiply((BigInteger)hiProd.value());
}
}
public static void main(String[] parameters) {
BigInteger parameter =
new BigInteger(parameters.length == 0 ? "10" : parameters[0]);
System.out.print("factorial("+parameter+") = "); System.out.flush();
BigInteger result = factorial(parameter);
System.out.println(result);
}
}
abstract class Future implements Runnable {
private State myState = UNINITIALIZED;
private Object myValue = null;
private static class State {
private String stateName;
State(String stateName) { this.stateName = stateName; }
public String toString() { return stateName; }
}
private static final
State UNINITIALIZED = new State("Uninitialized");
private static final
State INITIALIZED_AND_STARTED= new State("Initialized and started");
private static final
State COMPLETED_RETURN = new State("Completed with return");
private static final
State COMPLETED_THROW = new State("Completed with throw");
Future() {}
@throwsIllegalStateException
public synchronized void start() {
if (myState == UNINITIALIZED) {
Thread thread = new Thread(this);
thread.start();
myState = INITIALIZED_AND_STARTED;
return;
} else {
throw new IllegalStateException("Already started.");
}
}
protected abstract Object compute();
public synchronized void run() {
while (myState == UNINITIALIZED)
try { this.wait(); } catch (InterruptedException e) {}
if (myState == INITIALIZED_AND_STARTED) {
try {
myValue = compute();
myState = COMPLETED_RETURN;
} catch(Throwable t) {
myValue = t;
myState = COMPLETED_THROW;
}
this.notifyAll();
}
}
@throwsError{@link #compute()}@throwsRuntimeException{@link #compute()}
public synchronized Object value() {
while (! (myState == COMPLETED_RETURN || myState == COMPLETED_THROW)) {
try {
this.wait();
}
catch (InterruptedException e) {
throw new Error(e.toString());
}
}
if (myState == COMPLETED_RETURN)
return myValue;
else { Throwable thrown = (Throwable) myValue;
if (dbgLev> 0) thrown.printStackTrace();
if (thrown instanceof Error) throw (Error) thrown;
else throw (RuntimeException) thrown;
}
}
public String toString() {
return "Future(state="+myState+", value="+myValue+")";}
public static int dbgLev = 1;
}