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

SCM Repository

[diderot] View of /branches/vis15/src/compiler/high-opt/eps-util.sml
ViewVC logotype

View of /branches/vis15/src/compiler/high-opt/eps-util.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3515 - (download) (annotate)
Sat Dec 19 03:01:31 2015 UTC (3 years, 11 months ago) by jhr
File size: 7176 byte(s)
working on merge
(* eps-util.sml
 *
 * This code is part of the Diderot Project (http://diderot-language.cs.uchicago.edu)
 *
 * COPYRIGHT (c) 2015 The University of Chicago
 * All rights reserved.
 *)

(* Helper functions for normalize-ein_exp
 * does the rewriting for Epsilon and deltas
 *)
structure EpsUtil : sig

    val epsToDels : Ein.ein_exp list
	  -> bool * Ein.ein_exp * Ein.sumrange list * Ein.ein_exp list * Ein.ein_exp list

    val reduceDelta : Ein.ein_exp list * Ein.ein_exp list * Ein.ein_exp list
	  -> bool * Ein.ein_exp

    val matchEps : Ein.mu list * Ein.index_id list -> bool

  end = struct

    structure E = Ein
    structure F = Filter

    fun err str = raise Fail (String.concat["Ill-formed EIN Operator",str])

  (* check to see if a pair of Epsilon expressions can be converted to deltas *)
    fun doubleEps (E.Epsilon(a,b,c), E.Epsilon(d,e,f)) = let
	  fun createDeltas (s, t, u, v) =
(* FIXME: what does the following comment mean? *)
            (*If multiple summation ids are the same, it might not remove from the summation queue*)
                if (s=u andalso t=v) orelse (s=v andalso t=u)
		  then NONE
		  else let
		    val d1 = [E.Delta(E.V s, E.V u), E.Delta(E.V t, E.V v)]
		    val d2 = [E.Delta(E.V s, E.V v), E.Delta(E.V t, E.V u)]
		    in
		      SOME(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 NONE
          end 
      | doubleEps _ = raise Fail "None Epsilon Argument"


  (* distributeEps (epsAll, sumexp)
   * ???
   *)
    (*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 ([], _) = NONE
            | distEps ([e1], eps) = (case sumexp
		 of [E.Sum(sx, E.Opn(E.Prod, e2::ps))] => (case doubleEps(e1, e2)
		       of SOME(d1, d2) => SOME(eps, d1, d2, sx, ps)
			| NONE => NONE
		      (* end case *))
		  | _ => NONE
		(* end case *))
	    | distEps (e1::e2::current,eps) = (case doubleEps(e1, e2)
		 of SOME(d1, d2) => SOME(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 exps = let
	  val (epsAll, rest, sumexp) = F.filterEps exps
	  in
	    case distributeEps(epsAll, sumexp)
             of NONE => (false, E.Const 0, [], epsAll, rest@sumexp)
	      | SOME(epsUnused, d1, d2, sx, ps) => let
		  val a = E.Opn(E.Prod, epsUnused@d1@rest@ps)
		  val b = E.Opn(E.Prod, epsUnused@d2@rest@ps)
		  in
		    (true, E.Op2(E.Sub, 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 (changed, [], beta, mu, nu) = (changed, beta, mu@nu)
	    | appDel (changed, a::alpha, beta, [], nu) = appDel(changed, alpha, beta@[a], nu, [])
	    | appDel (changed, a::alpha, beta, E.Delta(i, j)::mu, nu) =
		if (a = j)
		  then appDel(true, alpha, beta@[i], mu, nu)
		  else appDel(changed, a::alpha, beta, mu, nu@[E.Delta(i, j)])
	(* *)
(* FIXME: instead of appending singletons, build results in reverse order! *)
	  fun distribute (changed, [], rest, mu) = (changed, E.Opn(E.Prod, eps@mu@rest))
	    | distribute (changed, p1::ps, rest, mu) = (case p1
	         of E.Tensor(id, alpha) => let
		      val (changed, alpha_betas, nu) = appDel(changed, alpha, [], mu, [])
		      in
			distribute(changed, ps, rest@[E.Tensor(id, alpha_betas)], nu)
		      end
		  | E.Field(id, alpha) => let
		      val (changed, alpha_betas, nu) = appDel(changed, alpha, [], mu, [])
		      in
			distribute(changed, ps, rest@[E.Field(id, alpha_betas)], nu)
		      end
		  | E.Conv(v, alpha, h, dx) => let
		      val (changed, alpha_betas, nu1) = appDel(changed, alpha, [] ,mu, [])
		      val (changed, dx_betas, nu2) = appDel(changed, dx, [], nu1, [])
		      in
		        distribute(changed, ps, rest@[E.Conv(v,alpha_betas, h ,dx_betas)], nu2)
		      end
		  | E.Probe(E.Conv(v, alpha, h, dx), t) => let
		      val (changed, alpha_betas, nu1) = appDel(changed, alpha, [], mu, [])
		      val (changed, dx_betas, nu2) = appDel(changed, dx, [], nu1, [])
		      in
		        distribute(
			  changed, ps, rest@[E.Probe(E.Conv(v,alpha_betas, h ,dx_betas),t)], nu2)
		      end
		  | E.Apply(E.Partial d, e) => let
		      val (changed, d_betas, nu) = appDel(changed,d,[],mu,[])
		      in
			distribute(changed, ps, rest@[E.Apply(E.Partial d_betas,e)],nu)
		      end
		  | _ => distribute(changed, ps, rest@[p1], mu)
		(* end case *))
	  in
	    distribute (false, es, [], dels)
	  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
    *)
(* FIXME: rewrite once we understand what this is supposed to be doing *)
    fun matchEps (mus, epsx) = let
	  fun match (2, _, _, _) = true (* matched two *)
	    | match (_, _, _, []) = false
	    | match (0, _, _, [_]) = false
	    | match (num, [], rest, eps::epsx) = match (num, rest, [], epsx)
	    | match (num, E.V p :: px, rest, eps::epsx) =
		if (p = eps)
		  then match (num+1, rest@px, [], epsx)
		  else match (num, px, rest@[E.V p], eps::epsx)
	    | match (num, p::px, rest, eps) = match (num, px, rest, eps)
	  in
	    match (0, mus, [], epsx)
	  end

  end

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