Home My Page Projects Code Snippets Project Openings diderot

# SCM Repository

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

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]))

(* 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)
in
(vB,code@A@B)
end
| mkdot(e2::e1::es,code)= let
val (vA,A)= createProdVec([x,e2],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 ```