/**
   * Multiplies a {@link noconflict.org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} by <code>k
   * </code> using the reduced <code>&tau;</code>-adic NAF (RTNAF) method.
   *
   * @param p The ECPoint.F2m to multiply.
   * @param k The integer by which to multiply <code>k</code>.
   * @return <code>p</code> multiplied by <code>k</code>.
   */
  public ECPoint multiply(ECPoint point, BigInteger k, PreCompInfo preCompInfo) {
    if (!(point instanceof ECPoint.F2m)) {
      throw new IllegalArgumentException("Only ECPoint.F2m can be " + "used in WTauNafMultiplier");
    }

    ECPoint.F2m p = (ECPoint.F2m) point;

    ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
    int m = curve.getM();
    byte a = curve.getA().toBigInteger().byteValue();
    byte mu = curve.getMu();
    BigInteger[] s = curve.getSi();

    ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte) 10);

    return multiplyWTnaf(p, rho, preCompInfo, a, mu);
  }
  /**
   * Multiplies a {@link noconflict.org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} by an element
   * <code>&lambda;</code> of <code><b>Z</b>[&tau;]</code> using the window <code>&tau;</code>-adic
   * NAF (TNAF) method, given the WTNAF of <code>&lambda;</code>.
   *
   * @param p The ECPoint.F2m to multiply.
   * @param u The the WTNAF of <code>&lambda;</code>..
   * @return <code>&lambda; * p</code>
   */
  private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u, PreCompInfo preCompInfo) {
    ECCurve.F2m curve = (ECCurve.F2m) p.getCurve();
    byte a = curve.getA().toBigInteger().byteValue();

    ECPoint.F2m[] pu;
    if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo)) {
      pu = Tnaf.getPreComp(p, a);
      p.setPreCompInfo(new WTauNafPreCompInfo(pu));
    } else {
      pu = ((WTauNafPreCompInfo) preCompInfo).getPreComp();
    }

    // q = infinity
    ECPoint.F2m q = (ECPoint.F2m) p.getCurve().getInfinity();
    for (int i = u.length - 1; i >= 0; i--) {
      q = Tnaf.tau(q);
      if (u[i] != 0) {
        if (u[i] > 0) {
          q = q.addSimple(pu[u[i]]);
        } else {
          // u[i] < 0
          q = q.subtractSimple(pu[-u[i]]);
        }
      }
    }

    return q;
  }