#!/usr/bin/python
# $Id$

"""
program tests for differentials of symbols
"""
test_header=""
test_header+="import esys.escriptcore.utestselect as unittest\n"
test_header+="import numarray\n"
test_header+="from esys.escript import *\n"
test_header+="class Test_util2(unittest.TestCase):\n"
test_header+="   RES_TOL=1.e-7\n"
test_tail=""
test_tail+="suite = unittest.TestSuite()\n"
test_tail+="suite.addTest(unittest.makeSuite(Test_util2))\n"
test_tail+="unittest.TextTestRunner(verbosity=2).run(suite)\n"

t_prog=""

import random 
import numarray
import math

def makeArray(shape,rng):
   l=rng[1]-rng[0]
   out=numarray.zeros(shape,numarray.Float64)
   if isinstance(l,int):
     if len(shape)==0:  
         out=int(l*random.random()+rng[0])*1.
     elif len(shape)==1:
         for i0 in range(shape[0]):
                     out[i0]=int(l*random.random()+rng[0])
     elif len(shape)==2:
         for i0 in range(shape[0]):
            for i1 in range(shape[1]):
                     out[i0,i1]=int(l*random.random()+rng[0])
     elif len(shape)==3:
         for i0 in range(shape[0]):
            for i1 in range(shape[1]):
               for i2 in range(shape[2]):
                     out[i0,i1,i2]=int(l*random.random()+rng[0])
     elif len(shape)==4:
         for i0 in range(shape[0]):
            for i1 in range(shape[1]):
               for i2 in range(shape[2]):
                  for i3 in range(shape[3]):
                     out[i0,i1,i2,i3]=int(l*random.random()+rng[0])
     elif len(shape)==5:
         for i0 in range(shape[0]):
            for i1 in range(shape[1]):
               for i2 in range(shape[2]):
                  for i3 in range(shape[3]):
                    for i4 in range(shape[4]):
                     out[i0,i1,i2,i3,i4]=int(l*ranm.random()+rng[0])
     else:
         raise SystemError,"rank is restricted to 5"
   else:
     if len(shape)==0:  
         out=l*random.random()+rng[0]
     elif len(shape)==1:
         for i0 in range(shape[0]):
                     out[i0]=l*random.random()+rng[0]
     elif len(shape)==2:
         for i0 in range(shape[0]):
            for i1 in range(shape[1]):
                     out[i0,i1]=l*random.random()+rng[0]
     elif len(shape)==3:
         for i0 in range(shape[0]):
            for i1 in range(shape[1]):
               for i2 in range(shape[2]):
                     out[i0,i1,i2]=l*random.random()+rng[0]
     elif len(shape)==4:
         for i0 in range(shape[0]):
            for i1 in range(shape[1]):
               for i2 in range(shape[2]):
                  for i3 in range(shape[3]):
                     out[i0,i1,i2,i3]=l*random.random()+rng[0]
     elif len(shape)==5:
         for i0 in range(shape[0]):
            for i1 in range(shape[1]):
               for i2 in range(shape[2]):
                  for i3 in range(shape[3]):
                    for i4 in range(shape[4]):
                     out[i0,i1,i2,i3,i4]=l*ranm.random()+rng[0]
     else:
         raise SystemError,"rank is restricted to 5"
   return out         

for sh0 in [ (3,), (3,4), (3,4,3) ,(4,3,5,3)]:
    # get perm:
    if len(sh0)==2:
        check=[[1,0]]
    elif len(sh0)==3:
        check=[[1,0,2],
               [1,2,0],
               [2,1,0],
               [2,0,2],
               [0,2,1]]
    elif len(sh0)==4:
        check=[[0,1,3,2],
               [0,2,1,3],
               [0,2,3,1],
               [0,3,2,1],
               [0,3,1,2] ,          
               [1,0,2,3],
               [1,0,3,2],
               [1,2,0,3],
               [1,2,3,0],
               [1,3,2,0],
               [1,3,0,2],
               [2,0,1,3],
               [2,0,3,1],
               [2,1,0,3],
               [2,1,3,0],
               [2,3,1,0],
               [2,3,0,1],
               [3,0,1,2],
               [3,0,2,1],
               [3,1,0,2],
               [3,1,2,0],
               [3,2,1,0],
               [3,2,0,1]]
    else:
         check=[]
    
    # create the test cases:
    processed=[]
    l=["R","U","L","P","C","N"]
    c=[""]
    for i in range(len(sh0)):
       tmp=[]
       for ci in c:
          tmp+=[ci+li for li in l]
       c=tmp
    # SHUFFLE
    c2=[]
    while len(c)>0:
        i=int(random.random()*len(c))
        c2.append(c[i])
        del c[i]
    c=c2
    for ci in c:
      t=""
      sh=()
      for i in range(len(ci)):
          if ci[i]=="R":
             s="%s:%s"%(1,sh0[i]-1)
             sh=sh+(sh0[i]-2,)             
          if ci[i]=="U":
              s=":%s"%(sh0[i]-1)
              sh=sh+(sh0[i]-1,)             
          if ci[i]=="L":
              s="2:"
              sh=sh+(sh0[i]-2,)             
          if ci[i]=="P":
              s="%s"%(int(sh0[i]/2))
          if ci[i]=="C":
              s=":"
              sh=sh+(sh0[i],)             
          if ci[i]=="N":
              s=""
              sh=sh+(sh0[i],)
          if len(s)>0:
             if not t=="": t+=","
             t+=s
      N_found=False
      noN_found=False
      process=len(t)>0
      for i in ci:
         if i=="N":
            if not noN_found and N_found: process=False
            N_found=True
         else:
           if N_found: process=False
           noNfound=True
      # is there a similar one processed allready
      if process and ci.find("N")==-1:
         for ci2 in processed:
           for chi in check:
               is_perm=True
               for i in range(len(chi)): 
                   if not ci[i]==ci2[chi[i]]: is_perm=False
               if is_perm: process=False
      # if not process: print ci," rejected" 
      if process:
       processed.append(ci)
       for sh_diff in [ (), (2,), (3,2)]: #, (2,3,4) ,(2,4,3,2)]:
         text="   #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
         tname="test_slice_rank%s_%s_D_rank%s"%(len(sh0),ci,len(sh_diff))
         text+="   def %s(self):\n"%tname
         text+="      u=Symbol(%s)\n"%str(sh_diff)
         ind=[[]]
         for i in sh_diff:
           ind0=[]
           for j in ind:
              for k in range(i): ind0.append(j+[k])
           ind=ind0
         coeff={}
         for k in ind:
          coeff[tuple(k)]=makeArray(sh0,[-5,5])
         a=makeArray(sh0,[-5,5])
         text2=""
         if len(sh_diff)==0:
              text2+="u*numarray.array(%s)"%(coeff[tuple()].tolist())
         else:
           for k in coeff.keys():
              if len(text2)>0: text2+="+"
              text2+="u%s*numarray.array(%s)"%(list(k),coeff[k].tolist())
         text+="      arg=%s\n"%text2
         text+="      res=arg[%s]\n"%s
         text+="      dres=res.diff(u)\n"
         text+="      
         print text
         1/0
