123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219(* AUTOMATICALLY GENERATED from "fftw3_geomCF.ml". *)#1 "fftw3_geomCF.ml"(* File: fftw3_geomCF.ml
Copyright (C) 2008-
Christophe Troestler <Christophe.Troestler@umons.ac.be>
WWW: https://math.umons.ac.be/anum/software/
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2.1 or
later as published by the Free Software Foundation, with the special
exception on linking described in the file LICENSE.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
LICENSE for more details. *)(** Geometry checks. Uniform treatement of the C and FORTRAN layouts
through macros (for the bigarray interface). Does not depend on
the precision of the arrays. *)openPrintfopenBigarrayopenFftw3_utils(* Check whether the matrix given by [ofs], [inc], [n] is a valid
submatrix of [mat]. Return the (C) offset, stride array and
(logical) dimensions needed by the C wrappers. *)letget_geomnameofsnameofsincnameincnnamenmat=letnum_dims=Genarray.num_dimsmatinletofs=matchofswith|None->Array.makenum_dims1|Someo->ifArray.lengtho<>num_dimstheninvalid_arg(sprintf"%s: length %s <> %i"nameofsnamenum_dims);fork=0tonum_dims-1doifo.(k)<1theninvalid_arg(sprintf"%s: %s.(%i) = %i < 1 (fortran_layout)"nameofsnameko.(k));done;oandinc=matchincwith|None->Array.makenum_dims1|Somei->ifArray.lengthi<>num_dimstheninvalid_arg(sprintf"%s: length %s <> %i"nameincnamenum_dims);iandn=matchnwith|None->Array.makenum_dims0|Somen->(* FIXME: do we allow to modify [n] or do we want to copy it? *)ifArray.lengthn<>num_dimstheninvalid_arg(sprintf"%s: length %s <> %i"namennamenum_dims);fork=0tonum_dims-1doifn.(k)<0theninvalid_arg(sprintf"%s: %s.(%i) = %i < 0"namennamekn.(k));done;ninletrank=ref0(* Number of dims <> 1 in the transform. *)andup=Array.makenum_dims0(* submatrix "greater" corner *)in(* Compute the dimensions, rank and offset of the transform. *)letpdim=ref1(* product of physical dims > k; FORTRAN: < k *)andoffset=ref0(* offset for external functions which use C layout *)infork=0tonum_dims-1doletdimk=Genarray.nth_dimmatkinletabs_inck=absinc.(k)inifn.(k)=0&&abs_inck<>0then((* nk = max {n | ofs.(k) + (n-1) * abs inc.(k) <= dimk} *)letnk=1+(dimk-ofs.(k))/abs_inckinifnk>1thenincrrankelseifnk<1theninvalid_arg(sprintf"%s: dim %i empty; no n >= 1 s.t. %i + abs(%i)*\
(n-1) <= %i = dim %i"namekofs.(k)inc.(k)dimkk);n.(k)<-nk;up.(k)<-ofs.(k)+(nk-1)*abs_inck;)else((* n.(k) >= 1 || inc.(k) = 0; bound check. *)letlast=ofs.(k)+(n.(k)-1)*abs_inckiniflast>dimktheninvalid_arg(sprintf"%s: %s.(%i) + (%s.(%i) - 1) * abs %s.(%i) = %i \
> %i (fortran_layout) where %s.(%i) = %i, %s.(%i) = %i"nameofsnameknnamekincnameklastdimknnamekn.(k)incnamekinc.(k));iflast<>ofs.(k)thenincrrank;up.(k)<-last;);letstart=ifinc.(k)>=0thenofs.(k)elseup.(k)inoffset:=!offset+(start-1)*!pdim;pdim:=!pdim*dimk;done;(* [n_sub] and [stride] are for the C stubs (C layout) and do not
take into account dimensions [n.(k) = 1]. *)letn_sub=Array.make!rank0andstride=Array.make!rank0inletd=ref(!rank-1)inletpdim=ref1(* product of physical dims > k; FORTRAN: < k *)infork=0tonum_dims-1doifn.(k)>1&&inc.(k)<>0then(n_sub.(!d)<-n.(k);stride.(!d)<-inc.(k)*!pdim;decrd;);pdim:=!pdim*Genarray.nth_dimmatk;done;!offset,n_sub,stride,ofs,up;;(** [only_ones d] tells whether [d] entries are all [1] -- which is in
particular the case if [d] is empty. *)letonly_onesd=tryfori=0toArray.lengthd-1doifd.(i)<>1thenraiseExitdone;truewithExit->false(** Check whether the matrix given by [hm_n] (howmany matrix) and [hm]
is a valid submatrix of the hermitian matrix [mat]. @return the
[hm_stride], [hm_n] (howmany matrix), [stride] and [n] (logical
dimensions). *)letget_geom_hmnamehm_nnamehm_nhmnamehmlowupmat=letnum_dims=Genarray.num_dimsmatinifhm=[]thenifonly_oneshm_nthen[||],[||](* only one transform *)else(* Dimensions but no the corresponding vectors *)invalid_arg(sprintf"%s: %s = %s but %s = []"namehm_nname(string_of_arrayhm_n)hmname)elsebegin(* Transforms indices = vectors of [hm] with desired dims [hm_n]. *)lethm_rank=List.lengthhminlethm_n=ifhm_n=[||]thenArray.makehm_rank0elseifArray.lengthhm_n=hm_rankthen((* copy [hm_n] because 0 entries will be modified: *)letcopy_hmini=ifni>=0thennielseinvalid_arg(sprintf"%s: %s.(%i) < 0"namehm_nnamei)inArray.mapicopy_hmhm_n)elseinvalid_arg(sprintf"%s: length %s = %i <> length %s = %i"namehm_nname(Array.lengthhm_n)hmnamehm_rank)inlethm_stride=Array.makehm_rank0inList.iterihm~f:beginfuniv->(* [i]th translation vector [v] *)ifArray.lengthv<>num_dimstheninvalid_arg(sprintf"%s: length %ith array of %s <> %i \
= number of dimensions"nameihmnamenum_dims);lethm_s=ref0(* stride corresponding to [v] *)inifhm_n.(i)=0then((* Dimension for [i]th "howmany vector" [v] to determine *)letni=refmax_intinfork=num_dims-1downto0doletdimk=Genarray.nth_dimmatkinifv.(k)>0then(* max{j | up.(k) + v.(k)*(j-1) <= dimk} *)ni:=min!ni(1+(dimk-up.(k))/v.(k))elseifv.(k)<0then(* max{j | low.(k) + v.(k)*(j-1) >= 1} *)ni:=min!ni(1+(1-low.(k))/v.(k));hm_s:=!hm_s*dimk+v.(k);(* Horner *)done;hm_n.(i)<-!ni)else((* dimension [hm_n.(i)] provided; bound check *)fork=num_dims-1downto0doletdimk=Genarray.nth_dimmatkinif(v.(k)>0&&up.(k)+v.(k)*(hm_n.(i)-1)>dimk)||(v.(k)<0&&low.(k)+v.(k)*(hm_n.(i)-1)<1)theninvalid_arg(sprintf"%s: translating %i times by the %ith \
vector %s of %s exceeds the %ith dim bounds"namehm_n.(i)i(string_of_arrayv)hmnamek);hm_s:=!hm_s*dimk+v.(k);(* Horner *)done;);if!hm_s=0theninvalid_arg(sprintf"%s: %ith element of %s = [|0.;...;0.|]"nameihmname);hm_stride.(i)<-!hm_s;end;hm_n,hm_strideend(* Take the [make_plan] function creating plans, the dimensions, offsets
and increments of input/output arrays and compute the informations
needed by [make_plan]. Check the coherence of the data at the same
time. There may be more input (resp. output) arrays than [i]
(resp. [o]) but these must have the same dimensions. *)letapplynamemake_planhm_nhmi?niofsiinciihmo?noofsoincoo~logical_dims=letnum_dims=Genarray.num_dimsiinifnum_dims<>Genarray.num_dimsotheninvalid_arg(name^": input and output arrays do not have the same \
NUMBER of dimensions");letoffseti,ni,stridei,lowi,upi=get_geomname"ofsi"ofsi"inci"inci"ni"niiandoffseto,no,strideo,lowo,upo=get_geomname"ofso"ofso"inco"inco"no"nooinletn=(* or raise invalid_arg *)logical_dimsnino(sprintf"%s: dim input = %s incompatible with dim ouput = %s"name(string_of_arrayni)(string_of_arrayno))inlethm_ni,hm_stridei=get_geom_hmname"howmany_n"hm_n"howmanyi"hmilowiupiiandhm_no,hm_strideo=get_geom_hmname"howmany_n"hm_n"howmanyo"hmolowoupooinifhm_ni<>hm_notheninvalid_arg(sprintf"%s: howmany dim input = %s <> howmany dim output = %s"name(string_of_arrayhm_ni)(string_of_arrayhm_no));make_planoffsetioffsetonstrideistrideohm_nihm_strideihm_strideo