Home My Page Projects Code Snippets Project Openings 3D graphics for Standard ML
Summary Activity SCM

SCM Repository

[sml3d] View of /trunk/sml3d/src/particles/compiler/constants.sml
ViewVC logotype

View of /trunk/sml3d/src/particles/compiler/constants.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1160 - (download) (annotate)
Sun May 22 21:55:20 2011 UTC (8 years, 4 months ago) by pavelk
File size: 11266 byte(s)
* Added a new primitive: ACOS. It's the arc cosine function.
* Fixed a bug where in generating points in a disc, if the vector to the center of the disc was parallel to the normal, the points would only be generated at the center.
* Added implementations for generating vectors within the remaining domains. Generating a vector within a plane results in an error due to the domain being unbounded.
* Removed the "blob" domain as it has no use outside of generating points, but this effect can be simulated by providing different random distributions to the generation routine. (Not implemented yet)
* Updated the README to reflect changes.

(* constants.sml
 *
 * COPYRIGHT (c) 2011 John Reppy (http://cs.uchicago.edu/~jhr)
 * All rights reserved.
 *)

structure ConstantFolder :> PSYSIR_OPTIMIZATION =
  struct

  val gProgramChanged = ref false;
  structure IR = PSysIR

  (* Constant folding
   *
   * Condense most of our constants so that we have a smaller code size. We
   * already know what most of these operations do...
   *)
  
    
  fun allConsts([]) = true
    | allConsts(v as IR.V{scope, ...} :: vl) = 
      case scope 
        of IR.S_CONST(c) => allConsts(vl) 
         | _ => false
  
  fun extractConstVec(IR.V{scope, ...}) = (case scope 
    of IR.S_CONST c => (case c 
      of IR.C_VEC v => v
       | _ => raise Fail ("Expected const vec.")
      (* end case *))
     | _ => raise Fail ("Expected const vec.")
    (* end case *))
    
  fun extractConstInt(IR.V{scope, ...}) = (case scope 
    of IR.S_CONST c => (case c 
      of IR.C_INT i => i
       | _ => raise Fail ("Expected const int.")
      (* end case *))
     | _ => raise Fail ("Expected const int.")
    (* end case *))
       
  fun extractConstFloat(IR.V{scope, ...}) = (case scope 
    of IR.S_CONST c => (case c 
      of IR.C_FLOAT f => f
       | IR.C_INT i => Float.fromInt i
       | _ => raise Fail ("Expected const float.")
      (* end case *))
     | _ => raise Fail ("Expected const float.")
    (* end case *))

  fun extractConstBool(IR.V{scope, ...}) = (case scope 
    of IR.S_CONST c => (case c 
      of IR.C_BOOL b => b
       | _ => raise Fail ("Expected const bool.")
      (* end case *))
     | _ => raise Fail ("Expected const bool.")
    (* end case *))
  
  fun createConst(v as IR.V{scope, varType, name, ...}) = (case scope
    of IR.S_LOCAL(rhs) => let
      val (p, vl) = !rhs
     in
      (case p 
	of IR.ADD_VEC => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstVec(List.nth(vl, 0))
	     val v2 = extractConstVec(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_VEC(Vec3f.add(v1, v2)))
	    end
	  else v

	| IR.SUB_VEC => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstVec(List.nth(vl, 0))
	     val v2 = extractConstVec(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_VEC(Vec3f.sub(v1, v2)))
	    end
	  else v

	| IR.LEN_SQ => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstVec(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Vec3f.lengthSq(v1)))
	    end
	  else v

	| IR.LEN =>
	  if allConsts(vl) then
	    let
	     val v1 = extractConstVec(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Vec3f.length(v1)))
	    end
	  else v

	| IR.NORM => 
	  if allConsts(vl) then
	    let
	     val vec = extractConstVec(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_VEC(Vec3f.normalize(vec)))
	    end
	  else v

	| IR.SCALE => 
	  if allConsts(vl) then 
	    let 
	     val scale = extractConstFloat(List.nth(vl, 0))
	     val vec = extractConstVec(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_VEC(Vec3f.scale(scale, vec)))
	    end (*let*)
	  else v

	| IR.DOT => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstVec(List.nth(vl, 0))
	     val v2 = extractConstVec(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Vec3f.dot(v1, v2)))
	    end
	  else v

	| IR.CROSS => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstVec(List.nth(vl, 0))
	     val v2 = extractConstVec(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_VEC(Vec3f.cross(v1, v2)))
	    end
	  else v

	| IR.ADD => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(v1 + v2))
	    end
	  else v

	| IR.SUB => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(v1 - v2))
	    end
	  else v

	| IR.MULT => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(v1 * v2))
	    end
	  else v

	| IR.DIV => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(v1 / v2))
	    end
	  else v

	| IR.SQRT => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Float.sqrt v1))
	    end
	  else v
	  
	| IR.ABS =>
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Float.abs v1))
	    end
	  else v	  

	| IR.COS => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Float.cos v1))
	    end
	  else v

	| IR.ACOS => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Float.acos v1))
	    end
	  else v

	| IR.SIN => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Float.sin v1))
	    end
	  else v
	  
    | IR.MAX => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(if v1 > v2 then v1 else v2))
	    end
	  else v
	  
    | IR.MIN => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(if v1 < v2 then v1 else v2))
	    end
	  else v
	  
    | IR.MIX => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	     val v3 = extractConstFloat(List.nth(vl, 2))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(((1.0 - v3) * v1) + (v3 * v2)))
	    end
	  else v
	  
    | IR.CLAMP =>
  	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	     val v3 = extractConstFloat(List.nth(vl, 2))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(if v1 < v2 then v2 else if v1 > v3 then v3 else v1))
	    end
	  else v

	| IR.GT =>
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_BOOL(v1 > v2))
	    end
	  else v

	| IR.EQUALS => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstFloat(List.nth(vl, 0))
	     val v2 = extractConstFloat(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     (* Not proper equality, but will likely generate
	      * better results. *)
	     IR.newConst(name, IR.C_BOOL(Float.abs(v1 - v2) < Float.epsilon))
	    end
	  else v

	| IR.AND => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstBool(List.nth(vl, 0))
	     val v2 = extractConstBool(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_BOOL(v1 andalso v2))
	    end
	  else v

	| IR.OR => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstBool(List.nth(vl, 0))
	     val v2 = extractConstBool(List.nth(vl, 1))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_BOOL(v1 orelse v2))
	    end
	  else v

	| IR.NOT => 
	  if allConsts(vl) then
	    let
	     val v1 = extractConstBool(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_BOOL(not v1))
	    end
	  else v

	| IR.RAND => v
	
	| IR.ITOF => 
	  if allConsts(vl) then
	    let 
	     val intVal = extractConstInt(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(Float.fromInt (intVal)))
	    end
	  else v
	  
	(* So, this isn't really a constant fold, but we can definitely
	 * replace whatever variables we need if they're just copies of
	 * other variables. *)
	| IR.COPY => List.nth(vl, 0)
	
	| IR.EXTRACT_X => 
	  if allConsts(vl) then
	    let
	     val {x, y, z} = extractConstVec(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(x))
	    end
	  else v
	  
	| IR.EXTRACT_Y => 
	  if allConsts(vl) then
	    let
	     val {x, y, z} = extractConstVec(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(y))
	    end
	  else v
	  
	| IR.EXTRACT_Z => 
	  if allConsts(vl) then
	    let
	     val {x, y, z} = extractConstVec(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_FLOAT(z))
	    end
	  else v
	  
	| IR.GEN_VEC =>
	  if allConsts(vl) then
	    let
	     val x = extractConstFloat(List.nth(vl, 0))
	     val y = extractConstFloat(List.nth(vl, 1))
	     val z = extractConstFloat(List.nth(vl, 2))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_VEC({x=x, y=y, z=z}))
	    end
	  else v
	  
	| IR.NEG_VEC =>
	  if allConsts(vl) then
	    let
	     val {x, y, z} = extractConstVec(List.nth(vl, 0))
	    in
	     gProgramChanged := true;
	     IR.newConst(name, IR.C_VEC({x=(x * ~1.0), y=(y * ~1.0), z=(z * ~1.0)}))
	    end
	  else v
	  
       (* end case *))
       end
     | _ => v
    (* end case *))
    
  fun foldConstantsInBlock(IR.BLK{id, params, body, visited, refCount, props}) = let 
    fun foldStmt(IR.PRIM(v as IR.V{scope, ...}, p, vl, s)) = 
      let
       val foldedArgs = List.map createConst vl
      in
       (case scope
	of IR.S_LOCAL(rhs) => rhs := (p, foldedArgs)
	 | _ => ()
       (* end case *));
       IR.PRIM(v, p, foldedArgs, foldStmt(s))
      end
      | foldStmt(IR.IF(v, s1, s2)) =
        IR.IF(v, foldStmt(s1), foldStmt(s2))
      | foldStmt(IR.GOTO(blk, vl)) =
        IR.GOTO(foldConstantsInBlock(blk), List.map createConst vl)
      | foldStmt(IR.RETURN(vl)) =
        IR.RETURN(List.map createConst vl)
      | foldStmt(IR.DISCARD) = 
        IR.DISCARD
   in
    IR.BLK{id=id, params=params, body=foldStmt(body), visited=visited, refCount=refCount, props=props}
   end

  fun foldConstants(block) = let
    val _ = gProgramChanged := false
    val optimizedBlock = foldConstantsInBlock block
   in
    if (!gProgramChanged) then
     foldConstants(optimizedBlock)
    else
     optimizedBlock
   end

  fun optimize (IR.PGM{globals, emitter, physics, render}) = IR.PGM {
    globals = globals,
    emitter = foldConstants(emitter),
    physics = foldConstants(physics),
    render = render
  }

end

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