import com.perisic.ring.*;
import java.math.*;
import java.io.*;

public class PolTest {

    public static void testDivMod(PolynomialRing P, 
                 RingElt b, RingElt a) {
         RingElt q = P.div(b,a);
         RingElt r = P.mod(b,a);
         RingElt s = P.add(P.mult(q,a), r);
         if( !P.equal(s,b) ) {
               System.out.println("Err: b = " + b);
                System.out.println("Err: a = " + a);
                System.out.println("Err: q = " + q);
                System.out.println("Err: r = " + r);
                System.out.println("Err: s = " + s);
                System.exit(0);
                }
           }     
    public static void makeComputation(Ring Q, RingElt c) {
         RingElt a = Q.map(8);
         RingElt b = Q.map(5);

        PolynomialRing PQ = new PolynomialRing( Q,"Y");
        
        RingElt p = PQ.one();
        System.out.println("p = " + p);

        PolynomialRing PX = new PolynomialRing(Q, "X");
        RingElt q = PX.construct(10,c);
        System.out.println("q = " + q);
        RingElt r  = PX.sub(p,q);
        System.out.println("p - q  = "+ r);
        RingElt s = PX.mult(p,q);
        System.out.println("p * q  = "+ s);
        RingElt t = PX.div(s,p);
        System.out.println("(p * q) div p = " + t);
        RingElt t1 = PX.div(s,q);
        System.out.println("(p * q) div q = " + t1);
        
        for(int j = 1; j < 5; j++ ) {
             testDivMod(PX,s,r);
             testDivMod(PX,s,q);
             testDivMod(PX,r,s);
             testDivMod(PX,s,q);
             testDivMod(PX,s,s);
             s = PX.mult(s,r);
             s = PX.add(s,q);
             }
        System.out.println("s = "+s);
         }

    public static void main(String [] args) {
        FinitePrimeField F2 = new FinitePrimeField(2);
        RationalField Q = Ring.Q;
        PolynomialRing PQY = new PolynomialRing(Q, "Y");

//        Object[] ppp = { { 13, 10, 0 }, 
//                    {"3/7", "888383",
//                  new BigInteger("99999999999999999999999") } };

        int [] pexp = {13, 10, 0}; 
        Object [] pcoef = {"3/7", "88", 
           new BigInteger("99999999999999999999999") }; 
        RingElt pt = PQY.construct(pexp, pcoef); 
        System.out.println("pt = "+pt); 
        RingElt pr = PQY.construct( new int[] { 1,2,3}, 
                     new  Object[] { "6", "1/7", "1" } ); //
        System.out.println("pr = "+pr); //
        
        PolynomialRing PQYZ = new PolynomialRing(Ring.Q, new String [] {"X", "Y", "Z"});
        System.out.println("PQYZ = "+PQYZ);
        RingElt w1 = PQYZ.map("Z + 2 * Y^3 + X * Y^5*Z^3 * 1/7");
        System.out.println("w1 = "+w1);
        RingElt pyz = PQYZ.construct( new int[] { 1, 2, 3, 17}, 
                           new Object[] { "Y", "X", "Y + X" , pr} );
        System.out.println("pyz = " + pyz );
        
        PolynomialRing PABCD = new PolynomialRing(Ring.Q, 
                      new String [] { "A", "B", "C", "D" } );
        PolynomialRing PBD = new PolynomialRing(Ring.Q, 
                      new String [] { "D", "B" } );
                      
      
        RingElt pbd = PBD.map("B + 2 * D");
        System.out.println("pbd = "+pbd);
          System.out.println("aaaaaaaaaaaaaaaaaaaaa");
        RingElt ww = PABCD.map(pbd);
          System.out.println("bbbbbbbbbbbbbbbbbbbb");
        
        System.out.println("pbd in PABCD = "+ww);//
        //RingElt p12 = PABCD.map("-((6 + 3 * A) - B * C^7) * (((2/3) + 3 +  4) * 5 * C^12)");//

        //System.out.println("p12 = "+p12);
        
        for( int i = 5; i < 7; i++ ) {
            CyclotomicField K5 = new CyclotomicField(i,"e");
            ModularIntegerRing M5 = new ModularIntegerRing(i);
             PolynomialRing Pe = (PolynomialRing) K5.getModulus().getRing();
             RingElt w = Pe.construct(1,"1");
             RingElt ph = CyclotomicField.getCyclotomicPolynomial(Ring.Q,i,"u");
             K5.hideMod();
                RingElt v = K5.pow(w,i -1);
                
                RingElt y = K5.evaluatePolynomial(ph,v);
                RingElt g = M5.evaluatePolynomial(ph,M5.map(2));
                System.out.print("n="+i+", "+w + "^"+(i-1)+": g = "+g); 
                System.out.println(" y = "+y);
                if( !K5.equal(y,K5.map(0))) {
                    
                     System.out.println("Fehler: y = " + y);
                     System.exit(1); 
                     }
                }
        RingElt p; 
        for( int i = 9; i < 12;i++) { //
         //    System.out.println("=============== " + i + " ================");
             RingElt aQ = CyclotomicField.getCyclotomicPolynomial(Ring.Q,i,"a");
             p = aQ; 
             PolynomialRing PP = (PolynomialRing) p.getRing();
             int z = 0; 
             for( int j = PP.degree(p); j >= 0; j-- ) { 
                   RingElt q = PP.getCoefficientAt(j, p); 
                   if( q != null )  { z++; } 
                   }
             RingElt aZ = 
               CyclotomicField.getCyclotomicPolynomial(Ring.Z,i,"a");
             p =  aZ;
             PP = (PolynomialRing) p.getRing(); 
             int zZ = 0; 
             for( int j = PP.degree(p); j >= 0; j-- ) { 
                   RingElt q = PP.getCoefficientAt(j, p); 
                   if( q != null )  { zZ++; } 
                   }
             RingElt a2 = CyclotomicField.getCyclotomicPolynomial(F2,i,"a");
             p =  a2; 
             PP = (PolynomialRing) p.getRing();
             int z2 = 0; 
             for( int j = PP.degree(p); j >= 0; j-- ) { 
                   RingElt q = PP.getCoefficientAt(j, p);  
                   if( q != null )  { z2++; } 
                   }
             System.out.println(" n = "+i+"  Q: "+z+" Z: "+zZ+ " F2: "+z2);
             RingElt diff = aQ.getRing().sub(aZ,aQ);
             
             //System.out.println("diff = "+diff);
             if( !diff.getRing().equalZero(diff) ) {
                 System.out.println("aZ = "+aZ);
                 System.out.println("a2 = "+a2);
                 System.out.println("aQ = "+aQ);
                 BufferedReader reader = new BufferedReader(
                              new InputStreamReader(System.in));
                 try {
                 
                         reader.readLine();
                         System.out.println("Input successfull.");
                    } catch (IOException e) { /* ... */ }
                  }
                  }
             BufferedReader reader = new BufferedReader(
                              new InputStreamReader(System.in));
             PolynomialRing PPP;
             RingElt ppp;
             do {
                String str = "0";
                try {
                System.out.println("Enter a Polynomial over Q in the variables a-m, 0 for exit");
                str = reader.readLine(); 
                } catch (IOException e) { System.out.println("Hat nicht geklappt."); }
                System.out.println("parsing: "+str);
                PPP = new PolynomialRing(
                    Ring.Q,"a,b,c,d,e,f,g,h,i,j,k,l,m");
                System.out.println("PPP = "+PPP);
                ppp = PPP.map(str);
                System.out.println("ppp = " + ppp);
                
                } while ( PPP.equalZero(ppp) == false);
        
}
}
       

//         while(true) { }

