(* * * * * * * * * * *
* Resource Aware ML *
* * * * * * * * * * *
*
* File:
* matrix.raml
*
* Author:
* Jan Hoffmann (2010,2011)
*
* Resource Bound:
* O(n*m*k*l)
*
* Description:
* Matrix multiplication.
*
*)
matrixMultList : (L(L(int)),L(L(L(int)))) -> L(L(int))
matrixMultList (acc,mm) = let _=tick(1) in
match mm with
| nil -> acc
| (m::ms) -> matrixMultList( matrixMult (acc,m),ms);
(* Multiply three matrices. Needs maximal degree 3. *)
matrixMult3 : (L(L(int)),L(L(int)),L(L(int))) -> L(L(int))
matrixMult3 (m1,m2,m3) = let _=tick(1) in
matrixMult (matrixMult (m1,m2), m3);
(*
eq(matrixmult3(A,B,C,D,E,F),1,[matrixmult(A,B,C,D),],[]).
*)
(* Multiply two matrices. Needs maximal degree 3. *)
matrixMultOld : (L(L(int)),L(L(int))) -> L(L(int))
matrixMultOld (m1,m2) = let _=tick(1) in
matrixMult'(m1,transpose m2);
(* A new version that uses an alternate implementation
of transpose. Allows for a better bound.*)
matrixMult : (L(L(int)),L(L(int))) -> L(L(int))
matrixMult (m1,m2) = let _=tick(1) in
matrixMult'(m1,transAcc(m2,makeBase m2));
(*
eq(matrixmult(A,B,C,D),1,[transAcc(C,D,C,0),matrixmultp(A,B,C,L),makeBase(C,D)],[L=A+D,A>=0,B>=0,C>=0,D>=0]).
*)
matrixMult' : (L(L(int)),L(L(int))) -> L(L(int))
matrixMult' (m1,m2) = let _=tick(1) in
match m1 with
| nil -> nil
| (l::ls) -> (lineMult (l,m2))::(matrixMult' (ls,m2));
(*
eq(matrixmultp(A,B,C,D),1,[],[A=0]).
eq(matrixmultp(A,B,C,D),1,[linemult(B,C,D),matrixmultp(Ap,B,C,D)],[A>=1,Ap=A-1]).
*)
lineMult : (L(int),L(L(int))) -> L(int)
lineMult (l,m2) = let _=tick(1) in
match m2 with
| nil -> nil
| (x::xs) -> (mult (l,x))::(lineMult (l,xs));
(*
eq(linemult(A,B,C),1,[],[B=0]).
eq(linemult(A,B,C),1,[mult(A,C),linemult(A,Bp,C)],[B>=1,Bp=B-1]).
*)
mult : (L(int),L(int)) -> int
mult (l1,l2) = let _=tick(1) in
match l1 with
| nil -> +0
| (x::xs) -> match l2 with
| nil -> +0
| (y::ys) -> x*y + (mult (xs,ys));
(*
eq(mult(A,B),1,[],[A=0]).
eq(mult(A,B),1,[],[A>=1,B=0]).
eq(mult(A,B),1,[mult(Ap,Bp)],[A>=1,B>=1, Ap=A-1,Bp=B-1]).
*)
(*Transposing matrices*)
transpose : L(L(int)) -> L(L(int))
transpose m = let _=tick(1) in
match m with
| nil -> nil
| (xs::xss) -> let (l,m') = split m in
match m' with
| nil -> nil
| (y::ys) -> l::transpose (y::ys);
(*
eq(transpose(R,C),1,[],[R=0]).
eq(transpose(R,C),1,[split(R,C)],[R>=1,C=1]).
eq(transpose(R,C),1,[split(R,C),transpose(R,Cp)],[R>=1,C>=2,Cp=C-1]).
*)
split : L(L(int)) -> (L(int),L(L(int)))
split m = let _=tick(1) in
match m with
| nil -> (nil,nil)
| (l::ls) -> match l with
| nil -> (nil,nil) (* This case won't happen! *)
| (x::xs) -> let (ys,m') = split ls
in (x::ys,xs::m');
(*
eq(out1_split(R,C),0,[],[R=0]).
eq(out1_split(R,C),1,[out1_split(Rp,C)],[R>=1,Rp=R-1]).
eq(out2_split(R,C),0,[],[R=0]).
eq(out2_split(R,C),1,[out2_split(Rp,C)],[R>=1,Rp=R-1]).
eq(out3_split(R,C),nat(C-1),[],[R=0]).
eq(out3_split(R,C),0,[out3_split(Rp,C)],[R>=1,Rp=R-1]).
eq(split(R,C),1,[],[R=0]).
eq(split(R,C),1,[split(Rp,C)],[R>=1, Rp=R-1]).
*)
transAcc : (L(L(int)), L(L(int))) -> L(L(int))
transAcc (m,base) = let _=tick(1) in
match m with
| nil -> base
| (l::m') -> attach(l,transAcc(m',base));
(*
eq(transAcc(A,B,C,D),1,[],[A=0]).
eq(transAcc(A,B,C,D),1,[attach(B,Ap,L),transAcc(Ap,B,C,D)],[A>=1,Ap=A-1, L=D+Ap]).
eq(out1_transAcc(A,B,C,D),nat(C),[],[A=0]).
eq(out1_transAcc(A,B,C,D),0,[out1_transAcc(Ap,B,C,D)],[A>=1,Ap=A-1]).
eq(out2_transAcc(A,B,C,D),nat(D),[],[A=0]).
eq(out2_transAcc(A,B,C,D),1,[out2_transAcc(Ap,B,C,D)],[A>=1,Ap=A-1]).
*)
makeBase : L(L(int)) -> L(L(int))
makeBase m = let _=tick(1) in
match m with
| nil -> nil
| (l::m') -> mkBase l;
mkBase : L(int) -> L(L(int))
mkBase m = let _=tick(1) in
match m with
| nil -> nil
| (l::m') -> nil::mkBase m';
(*
eq(out1_makeBase(A,B),0,[],[A=0]). %row
eq(out1_makeBase(A,B),0,[out_mkBase(B)],[A=0]).
eq(out2_makeBase(A,B),0,[],[A>=0]). %col
eq(out_mkBase(A),0,[],[A=0]).
eq(out_mkBase(A),1,[out_mkBase(Ap)],[A>=1,Ap=A-1]).
eq(makeBase(A,B),1,[],[A=0]).
eq(makeBase(A,B),1,[mkBase(B)],[A>=1]).
eq(mkBase(A),1,[],[A=0]).
eq(mkBase(A),1,[mkBase(Ap)],[A>=1,Ap=A-1]).
*)
attach : (L(int),L(L(int))) -> L(L(int))
attach (line,m) = let _=tick(1) in
match line with
| nil -> nil
| (x::xs) -> match m with
| nil -> nil
| (l::ls) -> (x::l)::attach(xs,ls);
(*
eq(attach(A,B,C),1,[],[A=0,B>=0]).
eq(attach(A,B,C),1,[],[A>=1,B=0]).
eq(attach(A,B,C),1,[attach(Ap,Bp,C)],[A>=1,Ap=A-1,Bp=B-1]).
*)
main = ()