public Number calculateValue(Number rootVal) {
    Number val = coeffs[this.getDegree()];

    for (int i = this.getDegree() - 1; i >= 0; --i) {
      Number val2 = coeffs[i];
      Number prod = baseRing.mul(val, rootVal);
      val = baseRing.add(prod, val2);
    }
    return val;
  }
 public Polynomial sub(Polynomial poly) {
   int deg = degree > poly.degree ? degree : poly.degree;
   Number lcoeffs[] = new Number[deg + 1];
   for (int i = 0; i <= deg; ++i) {
     if (i <= degree && i <= poly.degree) lcoeffs[i] = baseRing.sub(coeffs[i], poly.coeffs[i]);
     else if (i <= degree) lcoeffs[i] = coeffs[i];
     else lcoeffs[i] = baseRing.getInverse(poly.coeffs[i]);
   }
   return valueOf(lcoeffs);
 }
  public Polynomial mul(Polynomial poly) {
    int deg = degree + poly.degree;
    Number lcoeffs[] = new Number[deg + 1];
    for (int i = 0; i <= deg; ++i) lcoeffs[i] = baseRing.getZERO();

    for (int i = 0; i <= degree; ++i)
      for (int j = 0; j <= poly.degree; ++j) {
        lcoeffs[i + j] = baseRing.add(lcoeffs[i + j], baseRing.mul(coeffs[i], poly.coeffs[j]));
      }
    return valueOf(lcoeffs);
  }
 /**
  * Construct a polynomial over a ring. In general the valueOf method should be used to construct a
  * new polynomial.
  *
  * @param baseRing the underlying ring of the polynomial.
  * @param symbol the symbol used to display the polynomial
  * @param coeffs an array of coefficients in the base ring coeff[0] is constant, coeff[1] is
  *     coefficient of t etc.
  */
 public Polynomial(RingI baseRing, String symbol, Number coeffs[]) {
   this.baseRing = baseRing;
   this.symbol = symbol;
   int deg = 0;
   for (int i = coeffs.length - 1; i > 0; --i)
     if (!baseRing.equals(coeffs[i], baseRing.getZERO())) {
       deg = i;
       break;
     }
   if (deg == coeffs.length - 1) this.coeffs = coeffs;
   else {
     this.coeffs = new Number[deg + 1];
     System.arraycopy(coeffs, 0, this.coeffs, 0, deg + 1);
   }
   this.degree = deg;
 }
  public Polynomial pow(int exp) {
    if (exp == 0) return valueOf(new Number[] {baseRing.getONE()});
    if (exp == 1) return valueOf(this.getCoeffs());
    if (exp < 0)
      throw new IllegalArgumentException("Tried to raise a Polynomial to a negative power");

    Polynomial res = valueOf(new Number[] {baseRing.getONE()});
    Polynomial currentPower = this;
    int ex = exp;
    while (ex != 0) {
      if ((ex & 1) == 1) res = res.mul(currentPower);
      ex >>= 1;
      if (ex == 0) break;
      currentPower = currentPower.mul(currentPower);
    }
    return res;
  }
  public String toString() {
    if (degree == 0) return coeffs[0].toString();
    StringBuffer sb = new StringBuffer("");
    for (int i = degree; i >= 0; --i) {
      String s = coeffs[i].toString();

      // don't bother if a zero coeff
      if (s.equals("0") || this.baseRing.equals(coeffs[i], baseRing.getZERO())) continue;

      // apart from first add a + sign if positive
      if (i != degree && !s.startsWith("-")) sb.append("+");

      // always print the final coeff (if non zero)
      if (i == 0) {
        String s1 = coeffs[i].toString();
        sb.append(s1);
        // if(s1.startsWith("(") && s1.endsWith(")"))
        // {
        //		sb.append(s1.substring(1,s1.length()-1));
        // }
        // else 	sb.append(s1);
        break;
      }
      // if its -1 t^i just print -
      if (s.equals("-1")) sb.append("-");
      else if (s.equals("1") || this.baseRing.equals(coeffs[i], baseRing.getONE())) {
      } // don't print 1
      else {
        if (needsBrackets(coeffs[i].toString())) {
          sb.append("(");
          sb.append(coeffs[i].toString());
          sb.append(")");
        } else sb.append(coeffs[i].toString());
        // sb.append(stripBrackets(coeffs[i]));
        sb.append(" ");
      }
      if (i >= 2) sb.append(symbol + "^" + i);
      else if (i == 1) sb.append(symbol);
    }
    sb.append("");
    return sb.toString();
  }
 public boolean equalsPoly(Polynomial n) {
   if (this.getDegree() != n.getDegree()) return false;
   for (int i = 0; i <= this.getDegree(); ++i)
     if (!baseRing.equals(this.getCoeff(i), n.getCoeff(i))) return false;
   return true;
 }
 /** Is this a constant polynomial? * */
 public boolean isConstantPoly() {
   if (coeffs.length > 1) return false;
   return baseRing.isConstantPoly(coeffs[0]);
 }