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

SCM Repository

[diderot] View of /branches/charisee/src/compiler/mid-to-low/evalKrn.sml
ViewVC logotype

View of /branches/charisee/src/compiler/mid-to-low/evalKrn.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2845 - (download) (annotate)
Fri Dec 12 06:46:23 2014 UTC (4 years, 7 months ago) by cchiw
File size: 5518 byte(s)
added norm
(* Split Functions before code generation process*)
structure evalKrn = struct
    local
    structure DstIL = LowIL
    structure DstTy = LowILTypes
    structure DstOp = LowOps
    structure Var = LowIL.Var
    structure S3=step3
 
    in
     
     fun createProdVec(args,dim)=S3.aaV( DstOp.prodVec dim,args,"prodVec",DstTy.TensorTy([dim]))
     fun createAddVec(args,dim)=S3.aaV(DstOp.addVec dim,args,"AddVec",DstTy.TensorTy([dim]))
     fun createAddVecPre(pre,args,dim)=S3.aaV(DstOp.addVec dim,args,pre^"_AddVec",DstTy.TensorTy([dim]))
     
     (* convert a rational to a FloatLit.float value.  We do this by long division
     * with a cutoff when we get to 12 digits.
     *)
     fun ratToFloat r = (case Rational.explode r
         of {sign=0, ...} => FloatLit.zero false
         | {sign, num, denom=1} => FloatLit.fromInt(IntInf.fromInt sign * num)
         | {sign, num, denom} => let
            (* normalize so that num <= denom *)
             val (denom, exp) = let
                 fun lp (n, denom) = if (denom < num)
                    then lp(n+1, denom*10)
                    else (denom, n)
                    in
                        lp (1, denom)
                    end
             (* normalize so that num <= denom < 10*num *)
             val (num, exp) = let
                fun lp (n, num) = if (10*num < denom)
                    then lp(n-1, 10*num)
                    else (num, n)
                    in
                        lp (exp, num)
                    end
             (* divide num/denom, computing the resulting digits *)
             fun divLp (n, a) = let
                val (q, r) = IntInf.divMod(a, denom)
                in
                    if (r = 0) then (q, [])
                    else if (n < 12) then let
                        val (d, dd) = divLp(n+1, 10*r)
                        in
                            if (d < 10)
                            then (q, (IntInf.toInt d)::dd)
                            else (q+1, 0::dd)
                        end
                    else if (IntInf.div(10*r, denom) < 5)
                        then (q, [])
                        else (q+1, []) (* round up *)
                end
             val digits = let
                val (d, dd) = divLp (0, num)
                in
                    (IntInf.toInt d)::dd
                end
             in
                FloatLit.fromDigits{isNeg=(sign < 0), digits=digits, exp=exp}
            end
        (* end case *))
 
 
(* expand the EvalKernel operations into vector operations.  The parameters
* are
*	result	-- the lhs variable to store the result
*	d	-- the vector width of the operation, which should be equal
*		   to twice the support of the kernel
*	h	-- the kernel
*	k	-- the derivative of the kernel to evaluate
*
* The generated code is computing
*
*	result = a_0 + x*(a_1 + x*(a_2 + ... x*a_n) ... )
*
* as a d-wide vector operation, where n is the degree of the kth derivative
* of h and the a_i are coefficient vectors that have an element for each
* piece of h.  The computation is implemented as follows
*
*	m_n	= x * a_n
*	s_{n-1}	= a_{n-1} + m_n
*	m_{n-1}	= x * s_{n-1}
*	s_{n-2}	= a_{n-2} + m_{n-1}
*	m_{n-2}	= x * s_{n-2}
*	...
*	s_1	= a_1 + m_2
*	m_1	= x * s_1
*	result	= a_0 + m_1
*
* Note that the coeffient vectors are flipped (cf high-to-low/probe.sml).
*)
    fun expandEvalKernel (pre,d, h, k, x,axis) = let
     val {isCont, segs} = Kernel.curve (h, k)
     (* degree of polynomial *)
     val deg = List.length(hd segs) - 1
     val dd=List.length(hd segs)
     val ss=Kernel.support(h)
        (*segs is length 2*support, inner list is listof poynomial*)
                (*val m=print(String.concat["Axis: ", Int.toString(axis)," 
                    Length of segs:",Int.toString(length(segs)),
                        " segs next",Int.toString(dd)," k:", Int.toString(k),"SUpport:",Int.toString(ss)])*)
     
     val segs = Vector.fromList (List.rev (List.map Vector.fromList segs))
     fun coefficient d i =
         Literal.Float(ratToFloat (Vector.sub (Vector.sub(segs, i), d)))
      val ty = DstTy.vecTy d
     val coeffs = List.tabulate (deg+1,fn i => Var.new("P"^Int.toString i, ty))
     
     (* code to define the coefficient vectors *)
     val coeffVecs = let
        fun mk (x, (i, code)) = let
                val lits = List.tabulate(d, coefficient i)
                val vars = List.tabulate(d, fn _ => Var.new("_f", DstTy.realTy))
                val code =
                    ListPair.map (fn (x, lit) => (x, DstIL.LIT lit)) (vars, lits) @(x, DstIL.CONS(Var.ty x, vars)) :: code
                in
                    (i-1, code)
                end
        in
            #2 (List.foldr mk (deg, []) coeffs)
        end
     
     val coeffVecsCode=List.map (fn(x,y)=>DstIL.ASSGN (x,y)) coeffVecs

 
    (*get dot product and addition of list of coeffs*)
     fun mkdot([e2,e1],code)=let
            val (vA,A)= createProdVec([x,e2],d)
            val (vB,B)=createAddVecPre(pre,[e1,vA],d)
            in
                (vB,code@A@B)
            end
        | mkdot(e2::e1::es,code)= let
            val (vA,A)= createProdVec([x,e2],d)
            val (vB,B)=createAddVec([e1,vA],d)
            in
                mkdot(vB::es,code@A@B)
            end
        | mkdot ([e1],[])= createProdVec([x,e1],d)
        | mkdot _ = raise Fail "0 or 1 item in Kernel coeffs"
     val (vC,code)= mkdot(List.rev coeffs, [])
    
     in
        (vC,coeffVecsCode@code)
    end



end (* local *)

end 

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