123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186type+'at=|T0|T1of'a*'at'|T2of'a*'a*'at'|T3of'a*'a*'a*'at'|T4of'a*'a*'a*'a*'at'and+'at'=('a*'a*'a*'a)tletempty=T0letreccons:typea.a->at->at=funa0at->matchatwith|T0->T1(a0,T0)|T1(a1,at')->T2(a0,a1,at')|T2(a1,a2,at')->T3(a0,a1,a2,at')|T3(a1,a2,a3,at')->T4(a0,a1,a2,a3,at')|T4(a1,a2,a3,a4,at')->T1(a0,cons(a1,a2,a3,a4)at')letrecflatten:typea.(a*a*a*a)t->at=function|T0->T0|T1((a0,a1,a2,a3),at)->T4(a0,a1,a2,a3,flattenat)|T2((a0,a1,a2,a3),aa1,at)->T4(a0,a1,a2,a3,T1(aa1,at))|T3((a0,a1,a2,a3),aa1,aa2,at)->T4(a0,a1,a2,a3,T2(aa1,aa2,at))|T4((a0,a1,a2,a3),aa1,aa2,aa3,at)->T4(a0,a1,a2,a3,T3(aa1,aa2,aa3,at))letrecdrop:typea.int->at->at=funnat->ifn=0thenatelsematchn,atwith|_,T0->T0|1,T2(_,a1,at)|2,T3(_,_,a1,at)|3,T4(_,_,_,a1,at)->T1(a1,at)|1,T3(_,a1,a2,at)|2,T4(_,_,a1,a2,at)->T2(a1,a2,at)|1,T4(_,a1,a2,a3,at)->T3(a1,a2,a3,at)|_,T1(_,at)->drop_rest(n-1)at|_,T2(_,_,at)->drop_rest(n-2)at|_,T3(_,_,_,at)->drop_rest(n-3)at|_,T4(_,_,_,_,at)->drop_rest(n-4)atanddrop_rest:typea.int->(a*a*a*a)t->at=funnat->letn'=n/4inletat'=dropn'atindrop(nland3)(flattenat')letuncons:typea.at->(a*at)option=funat->matchatwith|T0->None|T1(a1,at')->Some(a1,flattenat')|T2(a1,a2,at')->Some(a1,T1(a2,at'))|T3(a1,a2,a3,at')->Some(a1,T2(a2,a3,at'))|T4(a1,a2,a3,a4,at')->Some(a1,T3(a2,a3,a4,at'))letrecget:typea.int->at->a=funnat->matchn,atwith|_,T0->raiseNot_found|0,(T1(a0,_)|T2(a0,_,_)|T3(a0,_,_,_)|T4(a0,_,_,_,_))->a0|1,(T2(_,a1,_)|T3(_,a1,_,_)|T4(_,a1,_,_,_))->a1|2,(T3(_,_,a2,_)|T4(_,_,a2,_,_))->a2|3,(T4(_,_,_,a3,_))->a3|n,(T1(_,at))->get'(n-1)at|n,(T2(_,_,at))->get'(n-2)at|n,(T3(_,_,_,at))->get'(n-3)at|n,(T4(_,_,_,_,at))->get'(n-4)atandget':typea.int->at'->a=funnat->letn'=nlsr2inlet(a0,a1,a2,a3)=getn'atinmatchnland3with|0->a0|1->a1|2->a2|_->a3letrecupdate:typea.at->int->(a->a)->at=funatnu->matchn,atwith|_,T0->raiseNot_found|0,T1(a0,at)->T1(ua0,at)|0,T2(a0,a1,at)->T2(ua0,a1,at)|0,T3(a0,a1,a2,at)->T3(ua0,a1,a2,at)|0,T4(a0,a1,a2,a3,at)->T4(ua0,a1,a2,a3,at)|1,T2(a0,a1,at)->T2(a0,ua1,at)|1,T3(a0,a1,a2,at)->T3(a0,ua1,a2,at)|1,T4(a0,a1,a2,a3,at)->T4(a0,ua1,a2,a3,at)|2,T3(a0,a1,a2,at)->T3(a0,a1,ua2,at)|2,T4(a0,a1,a2,a3,at)->T4(a0,a1,ua2,a3,at)|3,T4(a0,a1,a2,a3,at)->T4(a0,a1,a2,ua3,at)|n,T1(a0,at)->T1(a0,update'at(n-1)u)|n,T2(a0,a1,at)->T2(a0,a1,update'at(n-2)u)|n,T3(a0,a1,a2,at)->T3(a0,a1,a2,update'at(n-3)u)|n,T4(a0,a1,a2,a3,at)->T4(a0,a1,a2,a3,update'at(n-4)u)andupdate':typea.at'->int->(a->a)->at'=funatnu->letn'=nlsr2inletu=matchnland3with|0->(fun(a0,a1,a2,a3)->(ua0,a1,a2,a3))|1->(fun(a0,a1,a2,a3)->(a0,ua1,a2,a3))|2->(fun(a0,a1,a2,a3)->(a0,a1,ua2,a3))|_->(fun(a0,a1,a2,a3)->(a0,a1,a2,ua3))inupdateatn'uletsetnxt=updatetn(fun_->x)letreclength:typea.at->int=funat->matchatwith|T0->0|T1(_,at)->1+4*lengthat|T2(_,_,at)->2+4*lengthat|T3(_,_,_,at)->3+4*lengthat|T4(_,_,_,_,at)->4+4*lengthatletis_empty=function|T0->true|_->false(* minimal bench, adding elements:
let () =
let i = int_of_string Sys.argv.(1) in
let j = int_of_string Sys.argv.(2) in
let time = Sys.time () in
for j = 1 to j do
let v = ref T0 in
for i = 1 to i do
v := add i !v
done
done;
let time = Sys.time () -. time in
Printf.printf "adding %d elements %d times took %.03fs (%.03fs per pass)\n"
i j time (time /. float j)
*)letseq_consxxs()=Seq.Cons(x,xs)letrecseq_flatten:typea.(a*a*a*a)Seq.t->aSeq.t=funseq()->matchseq()with|Seq.Nil->Seq.Nil|Seq.Cons((a1,a2,a3,a4),seq')->Seq.Cons(a1,seq_consa2(seq_consa3(seq_consa4(seq_flattenseq'))))letrecto_seq:typea.at->aSeq.t=function|T0->Seq.empty|T1(a1,at)->seq_consa1(seq_flatten(to_seqat))|T2(a1,a2,at)->seq_consa1(seq_consa2(seq_flatten(to_seqat)))|T3(a1,a2,a3,at)->seq_consa1(seq_consa2(seq_consa3(seq_flatten(to_seqat))))|T4(a1,a2,a3,a4,at)->seq_consa1(seq_consa2(seq_consa3(seq_consa4(seq_flatten(to_seqat)))))letrecseq_rev_flatten:typea.(a*a*a*a)Seq.t->aSeq.t->aSeq.t=funseqk()->matchseq()with|Seq.Nil->k()|Seq.Cons((a1,a2,a3,a4),seq')->Seq.Cons(a4,seq_consa3(seq_consa2(seq_consa1(seq_rev_flattenseq'k))))letrecto_rev_seq:typea.at->aSeq.t=funt->matchtwith|T0->Seq.empty|T1(a1,at)->seq_rev_flatten(to_rev_seqat)(seq_consa1Seq.empty)|T2(a1,a2,at)->seq_rev_flatten(to_rev_seqat)(seq_consa2(seq_consa1Seq.empty))|T3(a1,a2,a3,at)->seq_rev_flatten(to_rev_seqat)(seq_consa3(seq_consa2(seq_consa1Seq.empty)))|T4(a1,a2,a3,a4,at)->seq_rev_flatten(to_rev_seqat)(seq_consa4(seq_consa3(seq_consa2(seq_consa1Seq.empty))))