1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405# 1 "src/owl/dense/owl_dense_matrix_generic.ml"(*
* OWL - OCaml Scientific and Engineering Computing
* Copyright (c) 2016-2020 Liang Wang <liang.wang@cl.cam.ac.uk>
*)openBigarrayopenOwl_ndarrayopenOwl_base_dense_commonincludeOwl_dense_ndarray_generic(* area function *)letshapex=letx_shape=shapexinassert(Array.lengthx_shape=2);x_shape.(0),x_shape.(1)(* creation functions *)letemptykmn=Owl_dense_ndarray_generic.emptyk[|m;n|]letcreatekmna=Owl_dense_ndarray_generic.createk[|m;n|]aletzeroskmn=Owl_dense_ndarray_generic.zerosk[|m;n|]letoneskmn=Owl_dense_ndarray_generic.onesk[|m;n|]letinitkmnf=Owl_dense_ndarray_generic.initk[|m;n|]fletinit_2dkmnf=letx=emptykmninlety=Bigarray.array2_of_genarrayxinfori=0tom-1doforj=0ton-1doBigarray.Array2.unsafe_setyij(fij)donedone;xleteyekn=Owl_dense_ndarray_generic.eyeknletsequentialk?a?stepmn=Owl_dense_ndarray_generic.sequentialk?a?step[|m;n|]letlinspacekabn=letx=Owl_dense_ndarray_generic.linspacekabninreshapex[|1;n|]letlogspacek?baseabn=letx=Owl_dense_ndarray_generic.logspacek?baseabninOwl_dense_ndarray_generic.reshapex[|1;n|]letdiagm?(k=0)v=letopenStdlibinletn=numelvinletu=reshapev[|n|]inletx=zeros(kindv)(n+absk)(n+absk)inleti,j=matchk<0with|true->absk,0|false->0,abskinfork=0ton-1dosetx[|i+k;j+k|](getu[|k|])done;xlettriu?(k=0)x=let_kind=kindxinletm,n=shapexinlety=zeros_kindmninletofs=refStdlib.(minn(max0k))inletlen=refStdlib.(max0(minn(n-k)))inletloops=Stdlib.(max0(minm(n-k)))infori=0toloops-1do_owl_copy_kind!len~ofsx:!ofs~incx:1~ofsy:!ofs~incy:1xy;ifi+k>=0then(ofs:=!ofs+n+1;len:=!len-1)elseofs:=!ofs+ndone;(* return the final upper triangular matrix *)ylettril?(k=0)x=let_kind=kindxinletm,n=shapexinlety=zeros_kindmninletrow_i=Stdlib.(minm(abs(min0k)))inletlen=refStdlib.(minn(max0k+1))inletofs=ref(row_i*n)infor_i=row_itom-1do_owl_copy_kind!len~ofsx:!ofs~incx:1~ofsy:!ofs~incy:1xy;ofs:=!ofs+n;if!len<nthenlen:=!len+1done;(* return the final lower triangular matrix *)yletsymmetric?(upper=true)x=let_kind=kindxinletm,n=shapexinOwl_exception.(check(m=n)(NOT_SQUARE[|m;n|]));lety=copyxinletofs=ref0inletincx,incy=matchupperwith|true->1,m|false->m,1infori=0tom-1do_owl_copy_kind(m-i)~ofsx:!ofs~incx~ofsy:!ofs~incyyy;ofs:=!ofs+n+1done;(* return the symmetric matrix *)yletbidiagonal?(upper=true)dvev=letm=numeldvinletn=numelevinassert(m-n=1);letx=zeros(kinddv)mminlet_x=Bigarray.array2_of_genarrayxinlet_dv=flattendv|>Bigarray.array1_of_genarrayinlet_ev=flattenev|>Bigarray.array1_of_genarrayinleti,j=matchupperwith|true->0,1|false->1,0infork=0tom-2do_x.{k,k}<-_dv.{k};_x.{k+i,k+j}<-_ev.{k}done;_x.{m-1,m-1}<-_dv.{m-1};xlethermitian?(upper=true)x=letm,n=shapexinOwl_exception.(check(m=n)(NOT_SQUARE[|m;n|]));lety=copyxinlet_y=flatteny|>Bigarray.array1_of_genarrayinlet_conj_op=_owl_conj(kindx)inletofs=ref0inletincx,incy=matchupperwith|true->1,m|false->m,1infori=0tom-1do(* copy and conjugate *)_conj_op(m-i)~ofsx:!ofs~incx~ofsy:!ofs~incyyy;(* set the imaginary part to zero by default. *)leta=_y.{!ofs}in_y.{!ofs}<-Complex.{re=a.re;im=0.};ofs:=!ofs+n+1done;(* return the symmetric matrix *)yletuniformk?a?bmn=Owl_dense_ndarray_generic.uniformk?a?b[|m;n|]letgaussiank?mu?sigmamn=Owl_dense_ndarray_generic.gaussiank?mu?sigma[|m;n|]letpoissonk~mumn=Owl_dense_ndarray_generic.poissonk~mu[|m;n|]letbernoullik?pmn=Owl_dense_ndarray_generic.bernoullik?p[|m;n|]letunit_basiskni=letx=Owl_dense_ndarray_generic.unit_basiskniinreshapex[|1;n|]lettoeplitz?cr=letc=matchcwith|Somec->c|None->conjrinletm=numelcinletn=numelrinOwl_dense_ndarray_generic.(setc[|0;0|](getr[|0;0|]));let_kind=kindrinletx=empty_kindmninletofs=ref0inletloops=Stdlib.minmninfori=0toloops-1do_owl_copy_kind(n-i)~ofsx:0~incx:1~ofsy:!ofs~incy:1rx;_owl_copy_kind(m-i)~ofsx:0~incx:1~ofsy:!ofs~incy:ncx;ofs:=!ofs+n+1done;xlethankel?rc=letm=numelcinletr=matchrwith|Somer->r|None->zeros(kindc)1minletn=numelrinOwl_dense_ndarray_generic.(setr[|0;0|](getc[|0;m-1|]));let_kind=kindrinletx=empty_kindmninletofs=ref((m-1)*n)inletloops=Stdlib.minmninfori=0toloops-1do_owl_copy_kind(n-i)~ofsx:0~incx:1~ofsy:!ofs~incy:1rx;_owl_copy_kind(m-i)~ofsx:i~incx:1~ofsy:i~incy:ncx;ofs:=!ofs-n+1done;xletkronab=letint_floorqr=int_of_float(float_of_intq/.float_of_intr)inletnra,nca=shapeainletnrb,ncb=shapebinletnrk,nck=nra*nrb,nca*ncbinletk=empty(kinda)nrknckinlet_mul_op=_mul_elt(kinda)inlet_a=Bigarray.array2_of_genarrayainlet_b=Bigarray.array2_of_genarraybinlet_k=Bigarray.array2_of_genarraykinfori=1tonrkdoforj=1tonckdoletai=int_floor(i-1)nrb+1inletaj=int_floor(j-1)ncb+1inletbi=((i-1)modnrb)+1inletbj=((j-1)modncb)+1in_k.{i-1,j-1}<-_mul_op_a.{ai-1,aj-1}_b.{bi-1,bj-1}donedone;k(* obtain properties *)letgetxij=Owl_dense_ndarray_generic.getx[|i;j|]letsetxija=Owl_dense_ndarray_generic.setx[|i;j|]aletswap_rowsxii'=letm,n=shapexinOwl_matrix._matrix_swap_rows(kindx)xmnii'letswap_colsxjj'=letm,n=shapexinOwl_matrix._matrix_swap_cols(kindx)xmnjj'lettransposex=letk=kindxinletm,n=shapexinlety=emptyknminOwl_matrix._matrix_transposekxy;yletctransposex=letk=kindxinletm,n=shapexinlety=emptyknminOwl_matrix._matrix_ctransposekxy;y(* iteration functions *)letiteri_rowsfx=fori=0torow_numx-1dofi(rowxi)doneletiter_rowsfx=iteri_rows(fun_y->fy)xletiter2i_rowsfxy=assert(row_numx=row_numy);iteri_rows(funiu->fiu(rowyi))xletiter2_rowsfxy=iter2i_rows(fun_uv->fuv)xylet_rowxi=(* get row i of x, but return as a column vector *)lety=slice_leftx[|i|]inreshapey[|col_numx;1|]letiteri_colsfx=lety=transposexinfori=0tocol_numx-1dofi(_rowyi)doneletiter_colsfx=iteri_cols(fun_y->fy)xletmapi_rowsfx=Array.init(row_numx)(funi->fi(rowxi))letmap_rowsfx=mapi_rows(fun_y->fy)xletmapi_colsfx=lety=transposexinArray.init(col_numx)(funi->fi(_rowyi))letmap_colsfx=mapi_cols(fun_y->fy)xletmapi_by_rowdfx=lety=empty(kindx)(row_numx)diniteri_rows(funiz->copy_row_to(fiz)yi)x;yletmap_by_rowdfx=mapi_by_rowd(fun_y->fy)xletmapi_by_coldfx=lety=empty(kindx)d(col_numx)initeri_cols(funjz->copy_col_to(fjz)yj)x;yletmap_by_coldfx=mapi_by_cold(fun_y->fy)xletmapi_at_rowfxi=letv=mapi(funjy->fjy)(rowxi)inlety=copyxincopy_row_tovyi;yletmap_at_rowfxi=mapi_at_row(fun_y->fy)xiletmapi_at_colfxj=letv=mapi(funiy->fiy)(colxj)inlety=copyxincopy_col_tovyj;yletmap_at_colfxj=mapi_at_col(fun_y->fy)xjletfilteri_rowsfx=lets=Owl_utils.Stack.make()initeri_rows(funiv->iffivthenOwl_utils.Stack.pushsi)x;Owl_utils.Stack.to_arraysletfilter_rowsfx=filteri_rows(fun_v->fv)xletfilteri_colsfx=lets=Owl_utils.Stack.make()initeri_cols(funiv->iffivthenOwl_utils.Stack.pushsi)x;Owl_utils.Stack.to_arraysletfilter_colsfx=filteri_cols(fun_v->fv)xlet_fold_basiciter_funfax=letr=refainiter_fun(funy->r:=f!ry)x;!rletfold_rowsfax=_fold_basiciter_rowsfaxletfold_colsfax=_fold_basiciter_colsfaxletiteri_2dfx=lety=array2_of_genarrayxinletm,n=shapexinfori=0tom-1doforj=0ton-1dofij(Array2.unsafe_getyij)donedoneletmapi_2dfx=lety=copyxinletz=array2_of_genarrayyinletm,n=shapeyinfori=0tom-1doforj=0ton-1doleta=Array2.unsafe_getzijinArray2.unsafe_setzij(fija)donedone;yletfilteri_2dfx=lets=Owl_utils.Stack.make()inlety=array2_of_genarrayxinletm,n=shapexinfori=0tom-1doforj=0ton-1doleta=Array2.unsafe_getyijiniffija=truethenOwl_utils.Stack.pushs(i,j)donedone;Owl_utils.Stack.to_arraysletfoldi_2d?axisfax=foldi_nd?axis(funkaccb->leti=k.(0)andj=k.(1)infijaccb)axletscani_2d?axisfx=scani_nd?axis(funkab->leti=k.(0)andj=k.(1)infijab)xletiter2i_2dfxy=assert(same_shapexy);letm,n=shapexinletx=array2_of_genarrayxinlety=array2_of_genarrayyinfori=0tom-1doforj=0ton-1doleta=Array2.unsafe_getxijinletb=Array2.unsafe_getyijinfijabdonedoneletmap2i_2dfxy=assert(same_shapexy);letm,n=shapexinletz=copyxinletx=array2_of_genarrayzinlety=array2_of_genarrayyinfori=0tom-1doforj=0ton-1doleta=Array2.unsafe_getxijinletb=Array2.unsafe_getyijinArray2.unsafe_setxij(fijab)donedone;zletsum_cols?(keep_dims=true)x=sum~axis:1~keep_dimsxletsum_rows?(keep_dims=true)x=sum~axis:0~keep_dimsxletmean_cols?(keep_dims=true)x=mean~axis:1~keep_dimsxletmean_rows?(keep_dims=true)x=mean~axis:0~keep_dimsxletmin_colsx=mapi_cols(funjv->letr,i=min_ivinr,i.(0),j)xletmin_rowsx=mapi_rows(funiv->letr,j=min_ivinr,i,j.(1))xletmax_colsx=mapi_cols(funjv->letr,i=max_ivinr,i.(0),j)xletmax_rowsx=mapi_rows(funiv->letr,j=max_ivinr,i,j.(1))xletmean'x=_mean_elt(kindx)(sum'x)(numelx)letadd_diagxa=letm,n=shapexinletm=Stdlib.minmninlety=copyxinlet_op=_add_elt(kindx)infori=0tom-1doletb=Owl_dense_ndarray_generic.getx[|i;i|]inOwl_dense_ndarray_generic.sety[|i;i|](_opba)done;y(* io operations *)letof_arraykxmn=letopenBigarrayinlety=Array1.of_arraykC_layoutx|>genarray_of_array1inOwl_dense_ndarray_generic.reshapey[|m;n|]letsave_txt?(sep="\t")?(append=false)~outx=letperm=0o666in(* will be AND'ed with user's umask *)letopen_flags=ifappendthen[Open_wronly;Open_creat;Open_append;Open_text]else[Open_wronly;Open_creat;Open_trunc;Open_text]inlet_op=Owl_utils.elt_to_str(kindx)inleth=open_out_genopen_flagspermoutinFun.protect(fun()->iter_rows(funy->iter(funz->Printf.fprintfh"%s%s"(_opz)sep)y;Printf.fprintfh"\n")x)~finally:(fun()->close_outh)letload_txt?(sep="\t")kf=let_op=Owl_utils.elt_of_strkinleth=open_infinFun.protect(fun()->lets=input_linehinletn=List.length(Str.split(Str.regexpsep)s)inletm=ref1in(* count lines in the input file *)(trywhiletruedoignore(input_lineh);m:=!m+1donewith|End_of_file->());letx=zerosk!mninseek_inh0;fori=0to!m-1dolets=Str.split(Str.regexpsep)(input_lineh)inList.iteri(funjy->setxij(_opy))sdone;x)~finally:(fun()->close_inh)letsemidefkn=letx=uniformknnindot(transposex)xletshuffle_rowsx=letm,_n=shapexinlety=copyxinfori=0tom-1doswap_rowsyi(Owl_stats.uniform_int_rvs~a:0~b:(m-1))done;yletshuffle_colsx=let_m,n=shapexinlety=copyxinfori=0ton-1doswap_colsyi(Owl_stats.uniform_int_rvs~a:0~b:(n-1))done;yletshufflex=x|>shuffle_rows|>shuffle_colsletmeshgridkxaxbyaybxnyn=letu=linspacekxaxbxninletv=linspacekyaybyninletx=map_by_rowxn(fun_->u)(emptykynxn)inlety=map_by_rowyn(fun_->v)(emptykxnyn)inx,transposeyletmeshupxy=letk=kindxinletxn=numelxinletyn=numelyinletx=map_by_rowxn(fun_->x)(emptykynxn)inlety=map_by_rowyn(fun_->y)(emptykxnyn)inx,transposey(* Hadamard Matrix *)let_hadamard_12=Array.mapfloat_of_int[|1;1;1;1;1;1;1;1;1;1;1;1;1;-1;1;-1;1;1;1;-1;-1;-1;1;-1;1;-1;-1;1;-1;1;1;1;-1;-1;-1;1;1;1;-1;-1;1;-1;1;1;1;-1;-1;-1;1;-1;1;-1;-1;1;-1;1;1;1;-1;-1;1;-1;-1;1;-1;-1;1;-1;1;1;1;-1;1;-1;-1;-1;1;-1;-1;1;-1;1;1;1;1;1;-1;-1;-1;1;-1;-1;1;-1;1;1;1;1;1;-1;-1;-1;1;-1;-1;1;-1;1;1;1;1;1;-1;-1;-1;1;-1;-1;1;-1;1;-1;1;1;1;-1;-1;-1;1;-1;-1;1;1;1;-1;1;1;1;-1;-1;-1;1;-1;-1|]let_hadamard_20=Array.mapfloat_of_int[|1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;1;-1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;1;1;-1;-1;1;1;-1;-1;-1;-1;1;-1;1;-1;1;1;1;1;-1;-1|]lethadamardkn=(* function to build up hadamard matrix recursively *)letrec_make_hadamard(cp_op:('a,'b)Owl_core_types.owl_arr_op18)(neg_op:('a,'b)Owl_core_types.owl_arr_op18)lennbasex=iflen=basethen()else(letlen'=len/2in_make_hadamardcp_opneg_oplen'nbasex;letofsx=ref0infor_i=0tolen'-1doletx1_ofs=!ofsx+len'inletx2_ofs=!ofsx+(len'*n)inletx3_ofs=x2_ofs+len'incp_oplen'~ofsx:!ofsx~incx:1~ofsy:x1_ofs~incy:1xx;cp_oplen'~ofsx:!ofsx~incx:1~ofsy:x2_ofs~incy:1xx;cp_oplen'~ofsx:!ofsx~incx:1~ofsy:x3_ofs~incy:1xx;(* negate the bottom right block *)neg_oplen'~ofsx:x3_ofs~incx:1~ofsy:x3_ofs~incy:1xx;ofsx:=!ofsx+ndone)in(* function to convert the pre-calculated hadamard array into type k *)let_float_array_to_k:typeab.(a,b)kind->floatarray->aarray=funka->matchkwith|Bigarray.Float32->a|Bigarray.Float64->a|Bigarray.Complex32->Array.map(funb->Complex.{re=b;im=0.})a|Bigarray.Complex64->Array.map(funb->Complex.{re=b;im=0.})a|_->failwith"Owl_dense_matrix_generic.hadamard"in(* start building, only deal with pow2 of n, n/12, n/20. *)letx=emptyknninletcp_op=_owl_copykinletneg_op=_owl_negkinifOwl_maths.is_pow2nthen(Owl_dense_ndarray_generic.setx[|0;0|](Owl_const.onek);_make_hadamardcp_opneg_opnn1x;x)elseifOwl_maths.is_pow2(n/12)&&Stdlib.(nmod12)=0then(lety=_float_array_to_kk_hadamard_12inlety=of_arrayky1212inlet_area=area001111incopy_area_toy_areax_area;_make_hadamardcp_opneg_opnn12x;x)elseifOwl_maths.is_pow2(n/20)&&Stdlib.(nmod20)=0then(lety=_float_array_to_kk_hadamard_20inlety=of_arrayky2020inlet_area=area001919incopy_area_toy_areax_area;_make_hadamardcp_opneg_opnn20x;x)elsefailwith"Owl_dense_matrix_generic:hadamard"letmagickn=leterror()=lets=Printf.sprintf"magic requires n >= 3, whereas input n = %i"ninOwl_exception.INVALID_ARGUMENTsinOwl_exception.verify(n>=3)error;leta0=Owl_const.zerokinleta1=Owl_const.onekinlet_magic_oddna=letx=zerosknninleti=ref0inletj=ref(n/2)inletac=ref(float_of_inta|>_float_typ_eltk)inletm=(n*n)+a-1|>float_of_int|>_float_typ_eltkinwhile!ac<=mdoifgetx!i!j=a0then(setx!i!j!ac;ac:=_add_eltk!aca1)else(leti'=(!i-1+n)modninletj'=(!j+1)modninifgetxi'j'=a0then(i:=i';j:=j')elsei:=(!i+1)modn)done;xinlet_magic_doubly_evenn=letx=zerosknninlet_seq_incxi0j0i1j1=fori=i0toi1doletac=ref((n*i)+j0+1|>float_of_int|>_float_typ_eltk)inforj=j0toj1dosetxij!ac;ac:=_add_eltk!aca1donedoneinlet_seq_decxi0j0i1j1=letac=ref(n*n|>float_of_int|>_float_typ_eltk)infori=i0toi1doforj=j0toj1doifgetxij=a0thensetxij!ac;ac:=_sub_eltk!aca1donedoneinletm=n/4in_seq_incx00(m-1)(m-1);_seq_incx0(3*m)(m-1)((4*m)-1);_seq_incxmm((3*m)-1)((3*m)-1);_seq_incx(3*m)0((4*m)-1)(m-1);_seq_incx(3*m)(3*m)((4*m)-1)((4*m)-1);_seq_decx00(n-1)(n-1);xinlet_magic_singly_evenn=letm=n/2inletm2=m*minletxa=_magic_oddm1inletxb=_magic_oddm(m2+1)inletxc=_magic_oddm((2*m2)+1)inletxd=_magic_oddm((3*m2)+1)inletm3=m/2inletxa'=concat_horizontal(get_slice[[];[0;m3-1]]xd)(get_slice[[];[m3;-1]]xa)inletxd'=concat_horizontal(get_slice[[];[0;m3-1]]xa)(get_slice[[];[m3;-1]]xd)inletxb'=ifm3-1=0thenxbelseconcat_horizontal(get_slice[[];[0;m-m3]]xb)(get_slice[[];[1-m3;-1]]xc)inletxc'=ifm3-1=0thenxcelseconcat_horizontal(get_slice[[];[0;m-m3]]xc)(get_slice[[];[1-m3;-1]]xb)insetxa'm30(getxam30);setxa'm3m3(getxdm3m3);setxd'm30(getxdm30);setxd'm3m3(getxam3m3);concat_horizontal(concat_verticalxa'xd')(concat_verticalxc'xb')in(* n is odd *)ifOwl_maths.is_oddnthen_magic_oddn1(* n is doubly even *)elseifnmod4=0then_magic_doubly_evenn(* n is singly even *)else_magic_singly_evennletmax_pool?paddingxkernelstride=letm,n=shapexinletx=Owl_dense_ndarray_generic.reshapex[|1;m;n;1|]inlety=Owl_dense_ndarray_generic.max_pool2d?paddingxkernelstrideinlets=Owl_dense_ndarray_generic.shapeyinletm,n=s.(1),s.(2)inOwl_dense_ndarray_generic.reshapey[|m;n|]letavg_pool?paddingxkernelstride=letm,n=shapexinletx=Owl_dense_ndarray_generic.reshapex[|1;m;n;1|]inlety=Owl_dense_ndarray_generic.avg_pool2d?paddingxkernelstrideinlets=Owl_dense_ndarray_generic.shapeyinletm,n=s.(1),s.(2)inOwl_dense_ndarray_generic.reshapey[|m;n|]letcov?b~a=leta=matchbwith|Someb->letna=numelainletnb=numelbinassert(na=nb);leta=reshapea[|na;1|]inletb=reshapeb[|nb;1|]inconcat_horizontalab|None->ainletmu=mean_rowsainleta=subamuinleta'=ctransposeainletc=dota'ainletn=row_numa-1|>Stdlib.max1|>float_of_int|>_float_typ_elt(kinda)indiv_scalarcnletmat2gray?amin?amaxx=letamin=matchaminwith|Somea->a|None->min'xinletamax=matchamaxwith|Somea->a|None->max'xinletx=clip_by_value~amin~amaxxinletx=sub_scalarxaminindiv_scalarx(_sub_elt(kindx)amaxamin)(* end here *)