content: package dk.alexandra.fresco.lib.common.math.integer.exp;
  
  import dk.alexandra.fresco.framework.DRes;
  import dk.alexandra.fresco.framework.builder.Computation;
  import dk.alexandra.fresco.framework.builder.numeric.Numeric;
  import dk.alexandra.fresco.framework.builder.numeric.ProtocolBuilderNumeric;
  import dk.alexandra.fresco.framework.value.SInt;
  import dk.alexandra.fresco.lib.common.math.AdvancedNumeric;
  import java.math.BigInteger;
  
  /**
   * Computes the exponentiation when only the exponent is secret. We require the knowledge of the
   * maximum bit size of the exponent.
   */
  public class ExponentiationOpenBase implements Computation<SInt, ProtocolBuilderNumeric> {
  
    private final BigInteger base;
    private final DRes<SInt> exponent;
    private final int maxExponentBitLength;
  
    public ExponentiationOpenBase(BigInteger base, DRes<SInt> exponent,
        int maxExponentBitLength) {
      this.base = base;
      this.exponent = exponent;
      this.maxExponentBitLength = maxExponentBitLength;
    }
  
    @Override
    public DRes<SInt> buildComputation(ProtocolBuilderNumeric builder) {
      return builder.seq(seq ->
              AdvancedNumeric.using(seq).toBits(exponent, maxExponentBitLength)
          ).seq((seq, bits) -> {
            BigInteger e = base;
            Numeric numeric = seq.numeric();
            DRes<SInt> result = null;
            for (DRes<SInt> bit : bits) {
              /*
               * result += bits[i] * (result * r - r) + r
               *
               *  aka.
               *
               *            result       if bits[i] = 0
               * result = {
               *            result * e   if bits[i] = 1
               */
              if (result == null) {
                BigInteger sub = e.subtract(BigInteger.ONE);
                result = numeric.add(BigInteger.ONE, numeric.mult(sub, bit));
              } else {
                DRes<SInt> sub = numeric.sub(numeric.mult(e, result), result);
                result = numeric.add(result, numeric.mult(sub, bit));
              }
              e = e.multiply(e);
            }
            return result;
          });
    }
  }
  