Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/charisee/src/compiler/high-il/EpsHelpers.sml
ViewVC logotype

View of /branches/charisee/src/compiler/high-il/EpsHelpers.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3448 - (download) (annotate)
Fri Nov 20 20:33:38 2015 UTC (4 years ago) by cchiw
File size: 7024 byte(s)
merge over dev branch
(*Helper functions for normalize-ein_exp
* does the rewriting for Epsilon and deltas
*)
structure EpsHelpers = struct

    local

    structure E = Ein
    structure P=Printer
    structure F=Filter
    in

    fun err str=raise Fail (String.concat["Ill-formed EIN Operator",str])
    val testing=0
    fun testp n=(case testing
        of 0=> 1
        | _ =>(print(String.concat n);1)
    (*end case*))

    fun setDelta e = E.setDelta e
    fun setProd e= E.setProd e
    fun setSub e= E.setSub e
    fun setConst e= E.setConst e

    (*doubleEps:ein_exp*ein_exp-> int*ein_exp list*ein_exp list
    *Decide if two Eps changes to Deltas
    *If so does the rewrite 
    *Return:change, Deltas1, Deltas2
    *)
    fun doubleEps(E.G(E.Epsilon (a,b,c)),E.G(E.Epsilon(d,e,f)))=let
        (*Function is called when eps are being changed to deltas*)
        fun createDeltas(s,t,u,v)=
            (*If multiple summation ids are the same, it might not remove from the summation queue*)
            if(s=u andalso t=v) then (0,[],[])
            else if(s=v andalso t=u) then (0,[],[])
            else let
                val d1= [setDelta(E.V s,E.V u), setDelta(E.V t,E.V v)]
                val d2= [setDelta(E.V s,E.V v), setDelta(E.V t,E.V u)]
                in
                    (1,d1,d2)
                end
        in
            if(a=d) then createDeltas(b,c,e,f)
            else if(a=e) then createDeltas(b,c,f,d)
            else if(a=f) then createDeltas(b,c,d,e)
            else if(b=d) then createDeltas(c,a,e,f)
            else if(b=e) then createDeltas(c,a,f,d)
            else if(b=f) then createDeltas(c,a,d,e)
            else if(c=d) then createDeltas(a,b,e,f)
            else if(c=e) then createDeltas(a,b,f,d)
            else if(c=f) then createDeltas(a,b,d,e)
            else (0,[],[])
        end 
    |doubleEps _ = raise Fail"None Epsilon Arguement"


    (*distributeEps:ein_exp list* ein_exp list
    -> int*ein_exp list * ein_exp list *ein_exp list *sum_index_id list
        * ein_exp list
    *epsAll is a list of epsilons
    *sumExp is a summation expression with epsilon
    * Before this function, there is call to filter all the epislons
    * in a product expression.
    *Sometimes a matching epislon can be hidden in a SummationExp, so that makes the search a little more complicated
    *The arguments to this function are either
    *(1) a list of epsilons in epsAll
    *(2) or a single item in both epsAll and sumExp.
    *In case (1), We check two epislons at a time for a match
    *If there is match then we return unused epsilon list, and rewriten deltas pairs
    *In case (2) We check the embedded eps for a match and if we find one return sum_ids and the rest of the product
      *)
    fun distributeEps(epsAll,sumexp)=let
        fun distEps([],_)     =(0,[],[],[],[],[])
          | distEps([e1],eps)=(case sumexp
            of  [E.Sum(sx,E.Opn(E.Prod,(e2::ps)))] =>  (case doubleEps(e1,e2)
                of (1,d1,d2)    => (1, eps, d1,d2,sx, ps)
                | _             =>(0,[],[],[],[],[])
                (*end case*))
            | _ => (0,[],[],[],[],[]))
        | distEps(e1::e2::current,eps) = (case doubleEps(e1,e2)
            of (1,d1,d2)    => (1, eps@current, d1,d2,[],sumexp)
            | _             => distEps(e2::current, eps@[e1])
            (*end case*))
        in
            distEps(epsAll,[])
        end


    (*epsToDels:ein_exp list
        -> int*ein_exp * sum_index_id*ein_exp list *ein_exp list
    *Looks at ein_exp list and searches for epsilons
    *calls above function to look for transition
    *return: change, e', sx
    *)
    fun epsToDels e= let
        val (epsAll,rest,sumexp) = F.filterEps e
        in (case (distributeEps(epsAll,sumexp))
            of (0, _ , _ , _ , _ , _)  => (0,setConst 0,[],epsAll,rest@sumexp)
            | (change, epsUnused,d1,d2,sx,ps)  => let
                val a=setProd(epsUnused@d1@rest@ps)
                val b=setProd(epsUnused@d2@rest@ps)
                in
                    (1,setSub(a,b),sx,[],[])
                end 
            (*end case *))
        end
                
    (*reduceDelta:ein_exp*ein_exp* ein_exp list ->int *ein_exp
    *Apply deltas to tensors/fields
    *returns change or rewriten ein_exp
    *
    * distPart:mu list*mu*mu* mu list
    * looks for match with index_id and delta
    * current delta is Delta_{i,j},Differentiation has index_ids pd
    *
    *  distribute:int*ein_exp list*ein_exp list *ein_exp list*ein_exp list
    *  distribute deltas of ein_exp list
    *)
    fun reduceDelta(eps, dels, es)=let


        fun appDel(change,[],beta,mu,nu)=(change,beta,mu@nu)
          | appDel(change,a::alpha,beta,[],nu)=appDel(change,alpha,beta@[a],nu,[])
          | appDel(change,a::alpha,beta,E.G(E.Delta(i,j))::mu,nu)=
            if(a=j) then appDel(1,alpha,beta@[i],mu,nu) else appDel(change,a::alpha,beta,mu,nu@[E.G(E.Delta(i,j))])

        fun distribute(change,[],rest,mu)=(change,setProd(eps@mu@rest))
          | distribute(change,p1::ps,rest,mu)=(case p1
            of  E.Tensor(id,alpha)=>let
                val (change,alpha_betas,nu)=appDel(change,alpha,[],mu,[])
                in distribute(change,ps,rest@[E.Tensor(id, alpha_betas)],nu)end
            | E.Field(id,alpha)=>let
                val (change,alpha_betas,nu)=appDel(change,alpha,[],mu,[])
                in distribute(change,ps,rest@[E.Field(id, alpha_betas)],nu)end
            | E.Conv(v,alpha, h ,dx)=>let
                  val (change,alpha_betas,nu1)=appDel(change,alpha,[],mu,[])
                  val (change,dx_betas,nu2)=appDel(change,dx,[],nu1,[])
                  in distribute(change,ps,rest@[E.Conv(v,alpha_betas, h ,dx_betas)],nu2) end
            | E.Probe(E.Conv(v,alpha, h ,dx),t)=>let
                val (change,alpha_betas,nu1)=appDel(change,alpha,[],mu,[])
                val (change,dx_betas,nu2)=appDel(change,dx,[],nu1,[])
                in distribute(change,ps,rest@[E.Probe(E.Conv(v,alpha_betas, h ,dx_betas),t)],nu2)  end
            | E.Apply(E.Partial d,e)=>let
                val (change,d_betas,nu)=appDel(change,d,[],mu,[])
                in distribute(change,ps,rest@[E.Apply(E.Partial d_betas,e)],nu) end
            | _ => distribute(change,ps,rest@[p1],mu)
            (*end case*))
        val (change,e)= distribute(0,es,[],dels)
        in
            (change,e)
        end



    (*matchEps:int*mu list *mu list  * index_id list->int
    *looks to see if two indices in delta(px) matches 2 in epsilon ids
    *if so returns 1 so the ein_exp becomes 0
    *)
    fun matchEps(2,_,_,_)= 1 (*matched 2*)
      | matchEps(num,_,_,[])=0
      | matchEps(0,_,_,[eps])=0
      | matchEps(num,[],rest,eps::epsx)=
        matchEps(num,rest,[],epsx)
      | matchEps(num,E.V p::px,rest,eps::epsx)=
        if(p=eps) then matchEps(num+1,rest@px,[],epsx)
        else matchEps(num,px,rest@[E.V p], eps::epsx)
      | matchEps(num,p::px,rest,eps)= matchEps(num,px,rest,eps)

   end
                

end (* local *)

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0