/*
 * $Id$
 * @author aakimov
 * @date   Jun 30, 2016 7:10:43 PM
 *
 * Copyright (C) 2016 Scytl Secure Electronic Voting SA
 *
 * All rights reserved.
 */
package com.scytl.math;

import java.math.BigInteger;
import java.util.List;

import javax.annotation.Nonnegative;
import javax.annotation.concurrent.ThreadSafe;

/**
 * This class performs multi-exponentiation operations modulo some given number.
 * <p>
 * A typical scenario looks like the following:
 * <ul>
 * <li>An instance of {@link MultiExponentiator} is created for a given list of
 * bases, modulus and the maximum number of bits in binary representation of
 * exponents.</li>
 * <li>Client calls possibly several times {@link #exponentiate(List)} method
 * specifying some list of exponents.</li>
 * </ul>
 * <p>
 * Client can get the parameters of the given instance by using {@link #bases()}
 * , {@link #modulus()} and {@link #maximumBitLengthOfExponent()} methods.
 * 
 * @author aakimov
 */
@ThreadSafe
public interface MultiExponentiator {

    /**
     * Returns the bases. The returned list is read-only.
     * 
     * @return the bases.
     */
    @Nonnegative
    List<BigInteger> bases();

    /**
     * Performs exponentiation for a given list of exponents.
     * 
     * @param exponents
     *            the exponents
     * @return the result of the exponentiation
     * @throws IllegalArgumentException
     *             the number of exponents does not match the number of bases,
     *             some exponents are negative or have bit length greater than
     *             {@link #maximumBitLengthOfExponent()}.
     */
    @Nonnegative
    BigInteger exponentiate(@Nonnegative List<BigInteger> exponents);

    /**
     * Returns the maximum {@link BigInteger#bitLength()} of exponents supplied
     * to {@link #exponentiate(List)} methods.
     * 
     * @return the maximum bit length of exponent.
     */
    @Nonnegative
    int maximumBitLengthOfExponent();

    /**
     * Returns the modulus. The returned value is positive.
     * 
     * @return the modulus.
     */
    @Nonnegative
    BigInteger modulus();
}
