type ('a,'c,'d) container2d = {
get: ('a,'c) code -> ('a,int) code ->
('a,int) code -> ('a,'d) code ;
set: ('a,'c) code -> ('a,int) code ->
('a,int) code -> ('a,'d) code -> ('a,unit) code;
dim1: ('a,'c) code -> ('a,int) code;
dim2: ('a,'c) code -> ('a,int) code;
mapper: ('a, 'd->'d) code -> ('a,'c) code ->
('a,'c) code;
copy: ('a, 'c) code -> ('a,'c) code
} ;;
type ('a,'c,'d) state = {b:('a,'c) code;
r:('a,int ref) code; c:('a,int ref) code;
m:('a,int) code; n:('a,int) code;
det:('a,'d ref) code; detsign:('a,'d ref) code};;
type ('a,'b) domain = {
zero:('a,'b) code; one:('a,'b) code;
minusone:('a,'b) code;
plus:('a,'b) code -> ('a,'b) code -> ('a,'b) code;
times:('a,'b) code -> ('a,'b) code -> ('a,'b) code;
minus:('a,'b) code -> ('a,'b) code -> ('a,'b) code;
div:('a,'b) code -> ('a,'b) code ->('a,'b) code;
smaller_than:(('a,'b) code -> ('a,'b) code ->
('a,bool) code) option;
normalizerf:(('a,'b -> 'b) code ) option;
normalizerg:(('a,'b) code -> ('a,'b) code ) option;
} ;;
type ('b,'c) outputs =
Matrix of 'b
| MatrixRank of 'b * int
| MatrixDet of 'b * 'c
| MatrixRankDet of 'b * int * 'c ;;
type outchoice = JustMatrix | Rank | Det | RankDet;;
type dettrack = TrackNothing | TrackDet ;;
type ge_choices =
{fracfree:bool; track:dettrack; outputs:outchoice} ;;
let orcond_gen main_cond = function
| Some alt_cond -> .< .~main_cond || .~alt_cond >.
| None -> main_cond ;;
let seq a b = .< begin .~a ; .~b end >. ;;
let sapply2 g c1 c2 = match g with
| Some f -> Some (f c1 c2)
| None -> None ;;
let dapply1 g c1 = match g with
| Some f -> f c1
| None -> c1 ;;
let mdapply1 mapper g c1 = match g with
| Some f -> .< .~(mapper f c1) >.
| None -> c1 ;;
let choose_output dom s = function
| JustMatrix -> .< Matrix (.~s.b) >.
| Rank -> .< MatrixRank((.~s.b), ! .~(s.r)) >.
| Det -> .< MatrixDet((.~s.b),
.~(dom.times .<! .~(s.det)>. .<! .~(s.detsign)>. ))>.
| RankDet -> .<MatrixRankDet((.~s.b),
! .~(s.r), .~(dom.times .<! .~(s.det)>.
.< ! .~(s.detsign) >. )) >.
let ge_state_gen dom contr findpivot swap zerobelow choice=
let main_loop s =
.< while !(.~s.c) < .~s.m && !(.~s.r) < .~s.n do
begin
match .~(findpivot s) with
Some i -> begin
if i <> !(.~s.r) then
for j = !(.~s.c) to .~s.m-1 do
.~(swap s .<i>. .<j>.);
done;
.~(zerobelow s) ;
(.~s.r) := !(.~s.r) + 1;
end;
| None -> .~(match choice.track with
| TrackNothing -> .< () >. ;
| TrackDet -> .< .~s.detsign := .~dom.zero >.;
) ;
end;
.~s.c := !(.~s.c) + 1;
done >. in
.< fun a ->
let b= .~(mdapply1 contr.mapper dom.normalizerf
(contr.copy .<a>. )) and
r=ref 0 and c=ref 0 and
m= .~(contr.dim1 .<a>. ) and
n= .~(contr.dim2 .<a>. ) and
det=ref .~(dom.one) and detsign=ref .~(dom.one) in
.~(let st = {b= .<b>.; r= .<r>.; c= .<c>.; m= .<m>.;
n= .<n>.; det= .<det>.;
detsign= .<detsign>.} in
seq
(main_loop st )
(choose_output dom st choice.outputs ) )
>. ;;
let swapr_gen dom contr track s i j =
let swap =
.< let t = .~(contr.get .<.~(s.b)>. .<.~i>. .<.~j>. ) in begin
.~(seq
(contr.set .<.~(s.b)>. .<.~i>. .<.~j>.
(contr.get .<.~(s.b)>. .< !(.~s.r)>. .<.~j>. ))
(contr.set .<.~(s.b)>. .< !(.~s.r)>. .<.~j>. .<t>. ) );
end >. in
let tds = .< .~s.detsign :=
.~(dom.times .<! .~s.detsign>. dom.minusone) >. in
match track with
| TrackNothing -> swap
| TrackDet -> seq swap tds ;;
let findpivot_gen dom contr orcond_gen = fun s ->
.< let i = ref (-1) in begin
for j = ! .~s.r to .~s.n-1 do
if not ( .~(contr.get .< .~s.b>. .<j>.
.<!( .~s.c)>. ) = .~(dom.zero)) then
if (.~(orcond_gen .< !i = (-1) >.
(sapply2 dom.smaller_than
.< .~(contr.get .< .~s.b>. .<j>. .<! .~s.c>. )>.
.< .~(contr.get .< .~s.b>. .<!i>. .<! .~s.c>. )>.
))) then
i := j;
done;
if !i == -1 then None else Some !i;
end >. ;;
let zerobelow_gen dom contr choice s =
let inner_loop =
if not choice.fracfree then fun i s ->
.< let t = .~(dom.div
(contr.get .<.~s.b>. .< .~i>. .<!(.~s.c)>. )
(contr.get .<.~s.b>. .<!(.~s.r)>. .<!(.~s.c)>. ) ) in
for j = !(.~s.c)+1 to .~s.m-1 do
.~(contr.set .<.~s.b>. .<.~i>. .<j>.
(dapply1 dom.normalizerg
(dom.minus (contr.get .<.~s.b>. .<.~i>. .<j>.)
(dom.times .<t>.
(contr.get .<.~s.b>. .<!(.~s.r)>. .<j>. )))))
done; >.
else fun i s ->
.< for j = !(.~s.c)+1 to .~s.m-1 do
let t = .~(dapply1 dom.normalizerg (dom.minus
(dom.times
(contr.get .<.~s.b>. .<.~i>. .<j>. )
(contr.get .<.~s.b>. .<! .~s.r>. .<! .~s.c>. ))
(dom.times
(contr.get .<.~s.b>. .<!(.~s.r)>. .<j>. )
(contr.get .<.~s.b>. .<.~i>. .<! .~s.r>. )))) in
.~(contr.set .<.~s.b>. .<.~i>. .<j>.
(dom.div .<t>. .<! .~s.det>. ))
done >. in
let outer_loop =
.< for i = !(.~s.r)+1 to .~s.n-1 do
if not ( .~(contr.get .<.~s.b>. .<i>. .<! .~s.c>. )
= .~dom.zero) then
begin
.~(inner_loop .<i>. s );
.~(contr.set .<.~s.b>. .<i>. .<! .~s.c>. dom.zero)
end;
done >. in
match choice.track with
| TrackNothing -> outer_loop
| TrackDet -> seq outer_loop
(if choice.fracfree then
.< .~s.det :=
.~(contr.get .<.~s.b>. .<! .~s.r>. .<! .~s.c>. )>.
else
.< .~s.det := .~(dom.times .<! .~s.det>.
(contr.get .<.~s.b>.
.<! .~s.r>. .<! .~s.c>. ))>. );;
let specializer dom container ~fracfree ~outputs =
let t = (if fracfree || outputs == Det
|| outputs == RankDet then
TrackDet else TrackNothing ) in
let choice =
{fracfree=fracfree; track=t; outputs=outputs} in
let fp = findpivot_gen dom container orcond_gen in
let swap = swapr_gen dom container choice.track in
let zb = zerobelow_gen dom container choice in
ge_state_gen dom container fp swap zb choice;;
let dom_float = {
zero = .< 0. >. ;
one = .< 1. >. ;
minusone = .< -1. >. ;
plus = (fun x y -> .<.~x +. .~y>.) ;
times = (fun x y -> .<.~x *. .~y>.) ;
minus = (fun x y -> .<.~x -. .~y>.) ;
div = (fun x y -> .<.~x /. .~y>.) ;
smaller_than =
Some(fun x y -> .<abs_float .~x < abs_float .~y >.);
normalizerf = None ;
normalizerg = None };;
let dom_int = {
zero = .< 0 >. ;
one = .< 1 >. ;
minusone = .< -1 >. ;
plus = (fun x y -> .<.~x + .~y>.) ;
times = (fun x y -> .<.~x * .~y>.) ;
minus = (fun x y -> .<.~x - .~y>.) ;
div = (fun x y -> .<.~x / .~y>.) ;
smaller_than = Some(fun x y -> .<abs.~x < abs.~y >.);
normalizerf = None ;
normalizerg = None };;
let array_container = {
get = (fun x n m -> .< (.~x).(.~n).(.~m) >. );
set = (fun x n m y -> .< (.~x).(.~n).(.~m) <- .~y >. );
dim2 = (fun x -> .< Array.length .~x >.) ;
dim1 = (fun x -> .< Array.length (.~x).(0) >. ) ;
mapper = (fun f a -> .< Array.map
(fun x -> Array.map .~f x) .~a >.);
copy = (fun a -> .<Array.map (fun x -> Array.copy x)
(Array.copy .~a) >. )
};;
let spec_ge_float =
specializer dom_float array_container
~fracfree:false ~outputs:RankDet ;;
let spec_ge_int =
specializer dom_int array_container
~fracfree:true ~outputs:RankDet ;;
let ge_float3 = .! spec_ge_float ;;
let ge_int3 = .! spec_ge_int ;;