import edu.rice.cs.mint.runtime.Code;
import edu.rice.cs.mint.runtime.SafeCode;

public class Power2{
    public static void main(String[] args){
        System.out.println(power(2, 17));
        long start = System.nanoTime();
        for (int x = 0; x < 20000; x++)
            power(2, 17);
        long unstaged = System.nanoTime() - start;
        
        Code<? extends PowerFun> CodePower17 = <| new PowerFun() {
            public int power(final int x){
                return `(power2(<|x|>, 17));
            }
        } |>;
        PowerFun spower17 = CodePower17.run();
        
        System.out.println(spower17.power(2));
        start = System.nanoTime();
        for (int x = 0; x < 20000; x++)
            spower17.power(2);
        long staged = System.nanoTime() - start;
        
        System.out.println("Unstaged -> " + unstaged + " ms");
        System.out.println("Staged ->   " + staged + " ms");
    }
    
    public static int power(int x, int n){
        if (n == 0)
            return 1;
        else if ((n % 2) == 0)
            return power (x * x, n/2);
        else
            return x * power(x, n-1);
    }
    
    public static separable SafeCode<Integer> power2(SafeCode<Integer> x, int n){
        if (n == 0)
            return <| 1 |>;
        else if ((n % 2) == 0)
            return power2 (<| `x * `x |>, n/2);
        else
            return <| `x * `(power2(x, n-1)) |>;
    }
    
    public static abstract class PowerFun{
        public abstract int power(int x);
    }
}
