import java.rmi.*;
import java.math.*;
import java.rmi.server.UnicastRemoteObject;

public class PiServerLeibnitz
        extends UnicastRemoteObject
        implements MyServer
{
    /** constants used in pi computation */
    private static final BigDecimal ZERO = 
        BigDecimal.valueOf(0);
    private static final BigDecimal  ONE = 
        BigDecimal.valueOf(1);

    /** rounding mode to use during pi computation */
    private static final int roundingMode = 
        BigDecimal.ROUND_HALF_EVEN;

    /** digits of precision after the decimal point */
    private int digits;
    

    /**
     * Construct a task to calculate pi to the specified
     * precision.
     */
    public PiServerLeibnitz() throws RemoteException {
        System.out.println("\tPiServerLeibnitz: PiServerLeibnitz()");
    }
    /**
     * Compute the value of pi to the specified number of 
     * digits after the decimal point.  The value is 
     * computed using Leibnitz's formula (1674):
     *
     *          pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 ...
     *
     */
    public BigDecimal computePi(int digits) throws RemoteException {
        int scale = digits + 5;
        BigDecimal piD4 = calculateSum(5, scale);
        BigDecimal pi = piD4.multiply( new BigDecimal((float)4));

        return pi.setScale(digits, BigDecimal.ROUND_HALF_UP);
    }
    public static BigDecimal calculateSum(int inverseX, int scale) 
    {
        BigDecimal ONE    =  new BigDecimal((float)1.0);
        BigDecimal result =  new BigDecimal((float)1.0);
	BigDecimal term;

        int i = 3;
        do {
	    BigDecimal numer  =  new BigDecimal((float)i);
	    term = ONE.divide (numer, scale, roundingMode) ;
            result = result.subtract( term );

	    i += 2;
	    numer  =  new BigDecimal((float)i);
	    term = ONE.divide (numer, scale, roundingMode) ;
            result = result.add( term );
	    i += 2;

        } while (term.compareTo(ZERO) != 0);
        return result;
    }


        public static void main(String args[])
        {
                // Create and install a security manager
                // System.setSecurityManager(new RMISecurityManager());

                try {
                        PiServerLeibnitz obj = new PiServerLeibnitz();
                        Naming.rebind("//yps:2042/PiServer", obj);
                        System.out.println("PiServerLeibnitz bound in registry");
                } catch (Exception e) {
                        System.out.println("PiServerLeibnitz err: " + e.getMessage());
                        e.printStackTrace();
                }
        }
}

