1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450(* File: utils.ml
Copyright (C) 2001-
Markus Mottl
email: markus.mottl@gmail.com
WWW: http://www.ocaml.info
Liam Stewart
email: liam@cs.toronto.edu
WWW: http://www.cs.toronto.edu/~liam
Christophe Troestler
email: Christophe.Troestler@umons.ac.be
WWW: http://math.umh.ac.be/an/
Florent Hoareau
email: h.florent@gmail.com
WWW: none
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
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 GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*)(** General auxiliary functions *)openPrintfopenBigarrayopenCommon(* Zero-sized dummy vector (int) *)letempty_int32_vec=create_int32_vec0(* Char indicating type of norm to retrieve for XlanYY routines *)letget_norm_char=function`M->'M'|`O->'O'|`I->'I'|`F->'F'(* Char indicating whether the "U"pper or "L"ower triangle of a matrix
is stored *)letget_uplo_charup=ifupthen'U'else'L'(* Char indicating whether some operation operates on a "N"ormal,
"T"ransposed or "C"onjugated transposed matrix. *)letget_trans_char=function`N->'N'|`T->'T'|`C->'C'(* Char indicating which side of the matrix B matrix A should be on *)letget_side_char=function`L->'L'|`R->'R'(* Char indicating whether a diagonal is unit or non-unit *)letget_diag_char=function`U->'U'|`N->'N'(* Char indicating whether/how the left/right singular vectors
should be computed *)letget_s_d_job_char=function`A->'A'|`S->'S'|`O->'O'|`N->'N'(* Char indicating whether the eigen"V"ectors are computed or "N"ot *)letget_job_char=functiontrue->'V'|_->'N'letjob_char_true=get_job_chartrueletjob_char_false=get_job_charfalse(** Preallocated strings (names) *)leta_str="a"letab_str="ab"letalphas_str="alphas"letap_str="ap"letb_str="b"letbr_str="br"letbc_str="bc"letc_str="c"letcr_str="cr"letcc_str="cc"letd_str="d"letdl_str="dl"letdu_str="du"lete_str="e"letipiv_str="ipiv"letiseed_str="iseed"letk_str="k"letka_str="ka"letkb_str="kb"letwork_str="work"letlwork_str="lwork"letliwork_str="liwork"letk1_str="k1"letk2_str="k2"letkd_str="kd"letkl_str="kl"letku_str="ku"letm_str="m"letn_str="n"letnrhs_str="nrhs"letofs_str="ofs"letr_str="r"lets_str="s"lettau_str="tau"letu_str="u"letum_str="um"letun_str="un"letvm_str="vm"letvn_str="vn"letvs_str="vs"letvsr_str="vsr"letvsc_str="vsc"letvt_str="vt"letw_str="w"letwi_str="wi"letwr_str="wr"letx_str="x"lety_str="y"letz_str="z"(** Range checking *)(** [raise_var_lt0 ~loc ~name var] @raise Invalid_argument to indicate
that integer variable [var] with name [name] at location [loc] is lower
than [0]. *)letraise_var_lt0~loc~namevar=invalid_arg(sprintf"%s: %s < 0: %d"locnamevar)(** [check_var_lt0 ~loc ~name var] checks whether integer variable [var] with
name [name] at location [loc] is lower than [0]. @raise Invalid_argument
in that case. *)letcheck_var_lt0~loc~namevar=ifvar<0thenraise_var_lt0~loc~namevarletcheck_var_withinlocvar_namevarlbubc=ifvar<lbtheninvalid_arg(sprintf"%s: %s %s < %s"locvar_name(cvar)(clb))elseifvar>ubtheninvalid_arg(sprintf"%s: %s %s > %s"locvar_name(cvar)(cub))else()(** Valueless vector checking and allocation functions (do not require a
vector value as argument *)(** [calc_vec_min_dim ~n ~ofs ~inc] @return minimum vector dimension given
offset [ofs], increment [inc], and operation size [n] for a vector. *)letcalc_vec_min_dim~n~ofs~inc=ifn=0thenofs-1elseofs+(n-1)*absinc(** [raise_vec_min_dim ~loc ~vec_name ~dim ~min_dim] @raise Invalid_argument
to indicate that dimension [dim] of a vector with name [vec_name]
exceeds the minimum [min_dim] at location [loc]. *)letraise_vec_min_dim~loc~vec_name~dim~min_dim=invalid_arg(sprintf"%s: dim(%s): valid=[%d..[ got=%d"locvec_namemin_dimdim)(** [check_vec_min_dim ~loc ~vec_name ~dim ~min_dim] checks whether vector
with name [vec_name] and dimension [dim] satisfies minimum dimension
[min_dim]. @raise Invalid_argument otherwise. *)letcheck_vec_min_dim~loc~vec_name~dim~min_dim=ifdim<min_dimthenraise_vec_min_dim~loc~vec_name~dim~min_dim(** [raise_vec_bad_ofs ~loc ~vec_name ~ofs ~max_ofs] @raise Invalid_argument
to indicate that vector offset [ofs] is invalid (i.e. is outside of
[1..max_ofs]). *)letraise_vec_bad_ofs~loc~vec_name~ofs~max_ofs=invalid_arg(sprintf"%s: ofs%s: valid=[1..%d] got=%d"locvec_namemax_ofsofs)(** [bad_n ~n ~max_n] @return [true] iff [n] is smaller than zero or larger
than [max_n]. *)letbad_n~n~max_n=n<0||n>max_n(** [bad_ofs ~ofs ~max_ofs] @return [true] iff [ofs] is smaller than one or
exceeds [max_ofs]. *)letbad_ofs~ofs~max_ofs=ofs<1||ofs>max_ofs(** [bad_inc inc] @return [true] iff [inc] is illegal. *)letbad_incinc=inc=0(** [check_vec_ofs ~loc ~vec_name ~ofs ~max_ofs] checks whether vector
offset [ofs] for vector of name [vec_name] is invalid (i.e. outside of
[1..max_ofs]). @raise Invalid_argument in that case. *)letcheck_vec_ofs~loc~vec_name~ofs~max_ofs=ifbad_ofs~ofs~max_ofsthenraise_vec_bad_ofs~loc~vec_name~ofs~max_ofs(** [check_vec_inc ~loc ~vec_name inc] checks whether vector increment [inc]
for vector of name [vec_name] is invalid (i.e. [0]). @raise
Invalid_argument in that case. *)letcheck_vec_inc~loc~vec_nameinc=ifbad_incinctheninvalid_arg(sprintf"%s: inc%s = 0"locvec_name)(** [calc_vec_max_n ~dim ~ofs ~inc] @return maximum operation length [n]
for a vector given the dimension [dim] of the vector, the offset [ofs],
and increment [inc]. Assumes that the offset has already been validated
to not exceed [dim], i.e. the returned [max_n] is at least [1]. *)letcalc_vec_max_n~dim~ofs~inc=1+(dim-ofs)/absinc(** [calc_vec_opt_max_n ?ofs ?inc dim] @return maximum operation length [n]
for a vector given the dimension [dim] of the vector, the optional offset
[ofs], and optional increment [inc]. Assumes that the offset has already
been validated to not exceed [dim], i.e. the returned [max_n] is at least
[1]. *)letcalc_vec_opt_max_n?(ofs=1)?(inc=1)dim=calc_vec_max_n~dim~ofs~inc(** [raise_max_len ~loc ~len_name ~len ~max_len] @raise Invalid_argument
that the maximum operation size (e.g. [m] or [n] for vectors and matrices)
has been exceeded. *)letraise_max_len~loc~len_name~len~max_len=invalid_arg(sprintf"%s: %s: valid=[0..%d] got=%d"loclen_namemax_lenlen)(** [check_vec_dim ~loc ~vec_name ~dim ~ofs ~inc ~n_name ~n] checks the vector
operation length in parameter [n] with name [n_name] at location [loc]
for vector with name [vec_name] and dimension [dim] given the operation
offset [ofs] and increment [inc]. @raise Invalid_argument if any
arguments are invalid. *)letcheck_vec_dim~loc~vec_name~dim~ofs~inc~n_name~n=check_vec_inc~loc~vec_nameinc;check_var_lt0~loc~name:n_namen;ifn=0thencheck_vec_ofs~loc~vec_name~ofs~max_ofs:(dim+1)elsebegincheck_vec_ofs~loc~vec_name~ofs~max_ofs:dim;letmax_n=calc_vec_max_n~dim~ofs~incinifn>max_nthenraise_max_len~loc~len_name:n_name~len:n~max_len:max_nend(** [get_vec_n ~loc ~vec_name ~dim ~ofs ~inc ~n_name n] checks or infers
the vector operation length in the option parameter [n] with name [n_name]
at location [loc] for vector with name [vec_name] and dimension [dim] given
the operation offset [ofs] and increment [inc]. @raise Invalid_argument
if any arguments are invalid. *)letget_vec_n~loc~vec_name~dim~ofs~inc~n_name=function|Nonewhendim=0->check_vec_inc~loc~vec_nameinc;ifofs=1thendimelseraise_vec_bad_ofs~loc~vec_name~ofs~max_ofs:1|None->check_vec_inc~loc~vec_nameinc;ifofs=dim+1then0elsebegincheck_vec_ofs~loc~vec_name~ofs~max_ofs:dim;calc_vec_max_n~dim~ofs~incend|Somen->check_vec_dim~loc~vec_name~dim~ofs~inc~n_name~n;n(** [get_vec_min_dim ~loc ~vec_name ~ofs ~inc ~n] @return minimum vector
dimension given offset [ofs], increment [inc], and operation size [n]
for a vector named [vec_name] at location [loc]. @raise Invalid_argument
if any of the parameters are illegal. *)letget_vec_min_dim~loc~vec_name~ofs~inc~n=check_vec_inc~loc~vec_nameinc;ifofs>=1thencalc_vec_min_dim~ofs~inc~nelseinvalid_arg(sprintf"%s: ofs%s: valid=[1..] got=%d"locvec_nameofs)(** [get_vec_start_stop ~ofsx ~incx ~n] @return [(start, stop)] where [start]
and [stop] reflect the start and stop of an iteration respectively. *)letget_vec_start_stop~ofsx~incx~n=ifn=0then0,0elseifincx>0thenofsx,ofsx+n*incxelseofsx-(n-1)*incx,ofsx+incx(** Valueless matrix checking and allocation functions (do not require a
matrix value as argument *)(** [raise_bad_mat_ofs ~loc ~name ~ofs_name ~ofs ~max_ofs] @raise
Invalid_argument to indicate that a matrix offset [ofs] named [ofs_name]
for a matrix having [name] is invalid (i.e. is outside of [1..max_ofs]). *)letraise_bad_mat_ofs~loc~name~ofs_name~ofs~max_ofs=invalid_arg(sprintf"%s: %s%s: valid=[1..%d] got=%d"locnameofs_namemax_ofsofs)(** [raise_mat_bad_r ~loc ~mat_name ~r ~max_r] @raise Invalid_argument
to indicate that matrix row offset [r] is invalid (i.e. is outside of
[1..max_r]). *)letraise_mat_bad_r~loc~mat_name~r~max_r=raise_bad_mat_ofs~loc~name:mat_name~ofs_name:r_str~ofs:r~max_ofs:max_r(** [raise_mat_bad_c ~loc ~mat_name ~c ~max_c] @raise Invalid_argument
to indicate that matrix column offset [c] is invalid (i.e. is outside of
[1..max_c]). *)letraise_mat_bad_c~loc~mat_name~c~max_c=raise_bad_mat_ofs~loc~name:mat_name~ofs_name:c_str~ofs:c~max_ofs:max_c(** [check_mat_r ~loc ~vec_name ~r ~max_r] checks whether matrix row
offset [r] for vector of name [vec_name] is invalid (i.e. outside of
[1..max_r]). @raise Invalid_argument in that case. *)letcheck_mat_r~loc~mat_name~r~max_r=ifr<1||r>max_rthenraise_mat_bad_r~loc~mat_name~r~max_r(** [check_mat_c ~loc ~vec_name ~c ~max_c] checks whether matrix column
offset [c] for vector of name [vec_name] is invalid (i.e. outside of
[1..max_c]). @raise Invalid_argument in that case. *)letcheck_mat_c~loc~mat_name~c~max_c=ifc<1||c>max_cthenraise_mat_bad_c~loc~mat_name~c~max_c(** [calc_mat_max_rows ~dim1 ~r] @return maximum row operation length [m] for a
matrix given the dimension [dim1] of the matrix and the start row [r]. *)letcalc_mat_max_rows~dim1~r=dim1-r+1(** [calc_mat_opt_max_rows ?r dim1] @return maximum row operation length
[m] for a matrix given the dimension [dim1] of the matrix and the optional
start row [r]. Assumes that the offset has already been validated to
not exceed [dim1], i.e. the returned [max_m] is at least [1]. *)letcalc_mat_opt_max_rows?(r=1)dim1=calc_mat_max_rows~dim1~r(** [calc_mat_max_cols ~dim2 ~c] @return maximum column operation length
[n] for a matrix given the dimension [dim1] of the matrix and the start
column [c]. *)letcalc_mat_max_cols~dim2~c=dim2-c+1(** [calc_mat_opt_max_cols ?c dim1] @return maximum column operation length
[m] for a matrix given the dimension [dim2] of the matrix and the optional
start column [c]. Assumes that the offset has already been validated to
not exceed [dim2], i.e. the returned [max_n] is at least [1]. *)letcalc_mat_opt_max_cols?(c=1)dim2=calc_mat_max_cols~dim2~c(** [check_mat_rows ~loc ~mat_name ~dim1 ~r ~p ~param_name] checks the matrix
row operation length in parameter [p] with name [param_name] at
location [loc] for matrix with name [mat_name] and dimension [dim1]
given the operation row [r]. @raise Invalid_argument if any arguments
are invalid. *)letcheck_mat_rows~loc~mat_name~dim1~r~p~param_name=check_var_lt0~loc~name:param_namep;ifp=0thencheck_mat_r~loc~mat_name~r~max_r:(dim1+1)elsebegincheck_mat_r~loc~mat_name~r~max_r:dim1;letmax_rows=calc_mat_max_rows~dim1~rinifp>max_rowsthenraise_max_len~loc~len_name:param_name~len:p~max_len:max_rowsend(** [check_mat_m ~loc ~mat_name ~dim1 ~r ~m] checks the matrix row operation
length in parameter [m] at location [loc] for matrix with name [mat_name]
and dimension [dim1] given the operation row [r]. @raise Invalid_argument
if any arguments are invalid. *)letcheck_mat_m~loc~mat_name~dim1~r~m=check_mat_rows~loc~mat_name~dim1~r~p:m~param_name:m_str(** [check_mat_cols ~loc ~mat_name ~dim2 ~c ~p ~param_name] checks the
matrix column operation length in parameter [p] with name [param_name]
at location [loc] for matrix with name [mat_name] and dimension [dim2]
given the operation column [c]. @raise Invalid_argument if any arguments
are invalid. *)letcheck_mat_cols~loc~mat_name~dim2~c~p~param_name=check_var_lt0~loc~name:param_namep;ifp=0thencheck_mat_c~loc~mat_name~c~max_c:(dim2+1)elsebegincheck_mat_c~loc~mat_name~c~max_c:dim2;letmax_cols=calc_mat_max_cols~dim2~cinifp>max_colsthenraise_max_len~loc~len_name:param_name~len:p~max_len:max_colsend(** [check_mat_n ~loc ~mat_name ~dim2 ~c ~n] checks the matrix column
operation length in parameter [n] at location [loc] for matrix with
name [mat_name] and dimension [dim2] given the operation column [c].
@raise Invalid_argument if any arguments are invalid. *)letcheck_mat_n~loc~mat_name~dim2~c~n=check_mat_cols~loc~mat_name~dim2~c~p:n~param_name:n_str(** [check_mat_mn ~loc ~mat_name ~dim1 ~dim2 ~r ~c ~m ~n] checks the matrix
operation lengths in parameters [m] and [n] at location [loc] for matrix
with name [mat_name] and dimensions [dim1] and [dim2] given the operation
row [r] and column [c]. @raise Invalid_argument if any arguments are
invalid. *)letcheck_mat_mn~loc~mat_name~dim1~dim2~r~c~m~n=check_mat_m~loc~mat_name~dim1~r~m;check_mat_n~loc~mat_name~dim2~c~n(** [get_mat_rows ~loc ~mat_name ~dim1 ~r p ~param_name] checks or infers
the matrix row operation length in the option parameter [p] with
name [param_name] at location [loc] for matrix with name [mat_name]
and dimension [dim1] given the row operation offset [r]. @raise
Invalid_argument if any arguments are invalid. *)letget_mat_rows~loc~mat_name~dim1~r~p~param_name=matchpwith|Nonewhendim1=0->ifr=1thendim1elseraise_mat_bad_r~loc~mat_name~r~max_r:1|None->letmax_r=dim1+1incheck_mat_r~loc~mat_name~r~max_r;max_r-r|Somep->check_mat_rows~loc~mat_name~dim1~r~p~param_name;p(** [get_mat_dim1 ~loc ~mat_name ~dim1 ~r ~m ~m_name] checks or infers the
matrix row operation length in the option parameter [m] with name [m_name]
at location [loc] for matrix with name [mat_name] and dimension [dim1]
given the row operation offset [r]. @raise Invalid_argument if any
arguments are invalid. *)letget_mat_dim1~loc~mat_name~dim1~r~m~m_name=get_mat_rows~loc~mat_name~dim1~r~p:m~param_name:m_name(** [get_mat_m ~loc ~mat_name ~dim1 ~r ~m] checks or infers the matrix row
operation length in the option parameter [m] at location [loc] for matrix
with name [mat_name] and dimension [dim1] given the row operation offset
[r]. @raise Invalid_argument if any arguments are invalid. *)letget_mat_m~loc~mat_name~dim1~r~m=get_mat_dim1~loc~mat_name~dim1~r~m_name:m_str~m(** [get_mat_cols ~loc ~mat_name ~dim2 ~c ~param_name p] checks or infers
the matrix column operation length in the option parameter [p] with
name [param_name] at location [loc] for matrix with name [mat_name]
and dimension [dim2] given the column operation offset [c]. @raise
Invalid_argument if any arguments are invalid. *)letget_mat_cols~loc~mat_name~dim2~c~p~param_name=matchpwith|Nonewhendim2=0->ifc=1thendim2elseraise_mat_bad_c~loc~mat_name~c~max_c:1|None->letmax_c=dim2+1incheck_mat_c~loc~mat_name~c~max_c;max_c-c|Somep->check_mat_cols~loc~mat_name~dim2~c~p~param_name;p(** [get_mat_dim2 ~loc ~mat_name ~dim2 ~c ~n ~n_name] checks or infers the
matrix column operation length in the option parameter [n] with name
[n_name] at location [loc] for matrix with name [mat_name] and dimension
[dim2] given the column operation offset [c]. @raise Invalid_argument
if any arguments are invalid. *)letget_mat_dim2~loc~mat_name~dim2~c~n~n_name=get_mat_cols~loc~mat_name~dim2~c~p:n~param_name:n_name(** [get_mat_n ~loc ~mat_name ~dim2 ~c ~n] checks or infers the matrix column
operation length in the option parameter [n] at location [loc] for matrix
with name [mat_name] and dimension [dim2] given the column operation
offset [c]. @raise Invalid_argument if any arguments are invalid. *)letget_mat_n~loc~mat_name~dim2~c~n=get_mat_dim2~loc~mat_name~dim2~c~n~n_name:n_str(** [get_mat_min_dim1 ~loc ~mat_name ~r ~m] @return the minimum row dimension
of a matrix with name [mat_name] at location [loc] given row [r] and
row operation length [m]. @raise Invalid_argument if any arguments
are invalid. *)letget_mat_min_dim1~loc~mat_name~r~m=ifr>0thenr+m-1elseinvalid_arg(sprintf"%s: %sr < 1: %d"locmat_namer)(** [get_mat_min_dim2 ~loc ~mat_name ~c ~n] @return the minimum column
dimension of a matrix with name [mat_name] at location [loc] given column
[c] and row operation length [n]. @raise Invalid_argument if any
arguments are invalid. *)letget_mat_min_dim2~loc~mat_name~c~n=ifc>0thenc+n-1elseinvalid_arg(sprintf"%s: %sc < 1: %d"locmat_namec)(** [check_mat_min_dim1 ~loc ~mat_name ~dim1 ~min_dim1] checks the minimum
row dimension [min_dim1] of a matrix with name [mat_name] at location
[loc] given its row dimension [dim1]. @raise Invalid_argument if
any arguments are invalid. *)letcheck_mat_min_dim1~loc~mat_name~dim1~min_dim1=ifdim1<min_dim1theninvalid_arg(sprintf"%s: dim1(%s): valid=[%d..[ got=%d"locmat_namemin_dim1dim1)(** [check_mat_min_dim2 ~loc ~mat_name ~dim2 ~min_dim2] checks the minimum
column dimension [min_dim2] of a matrix with name [mat_name] at location
[loc] given its column dimension [dim2]. @raise Invalid_argument if
any arguments are invalid. *)letcheck_mat_min_dim2~loc~mat_name~dim2~min_dim2=ifdim2<min_dim2theninvalid_arg(sprintf"%s: dim2(%s): valid=[%d..[ got=%d"locmat_namemin_dim2dim2)(** [check_mat_min_dim2 ~loc ~mat_name ~dim2 ~min_dim2] checks the minimum
column dimension [min_dim2] of a matrix with name [mat_name] at location
[loc] given its column dimension [dim2]. @raise Invalid_argument if
any arguments are invalid. *)letcheck_mat_min_dims~loc~mat_name~dim1~dim2~min_dim1~min_dim2=check_mat_min_dim1~loc~mat_name~dim1~min_dim1;check_mat_min_dim2~loc~mat_name~dim2~min_dim2(** (Old) Vector checking and allocation functions *)letcheck_veclocvec_namevecmin_dim=check_vec_min_dim~loc~vec_name~dim:(Array1.dimvec)~min_dim(** [check_vec_is_perm loc vec_name vec n] checks whether [vec]
is a valid permutation vector. *)letcheck_vec_is_permlocvec_namevecn=letdim=Array1.dimvecinifdim<>ntheninvalid_arg(sprintf"%s: dim(%s): valid=%d got=%d"locvec_namendim)elseletub=Int32.of_intninfori=1todimdoletr=Array1.getveciincheck_var_withinloc(sprintf"%s(%d)"k_stri)r1lubInt32.to_stringdoneletget_veclocvec_namevecofsincnvec_create=letmin_dim=get_vec_min_dim~loc~vec_name~ofs~inc~ninmatchvecwith|Somevec->check_veclocvec_namevecmin_dim;vec|None->vec_createmin_dim(** [get_dim_vec loc vec_name ofs inc vec n_name n] if the dimension [n]
is given, check that the vector [vec] is big enough, otherwise return
the maximal [n] for the given vector [vec]. *)letget_dim_veclocvec_nameofsincvecn_namen=get_vec_n~loc~vec_name~dim:(Array1.dimvec)~ofs~inc~n_namenletcheck_vec_empty~loc~vec_name~dim=ifdim=0theninvalid_arg(sprintf"%s: dimension of vector %s is zero"locvec_name)else()(** (Old) Matrix checking and allocation functions *)letget_matlocmat_namemat_creatercmatmn=letmin_dim1=get_mat_min_dim1~loc~mat_name~r~minletmin_dim2=get_mat_min_dim2~loc~mat_name~c~ninmatchmatwith|None->mat_createmin_dim1min_dim2|Somemat->letdim1=Array2.dim1matinletdim2=Array2.dim2matincheck_mat_min_dims~loc~mat_name~dim1~dim2~min_dim1~min_dim2;matletcheck_dim1_matlocmat_namematmat_rm_namem=letdim1=Array2.dim1matincheck_mat_rows~loc~mat_name~dim1~r:mat_r~p:m~param_name:m_nameletcheck_dim2_matlocmat_namematmat_cn_namen=letdim2=Array2.dim2matincheck_mat_cols~loc~mat_name~dim2~c:mat_c~p:n~param_name:n_nameletcheck_dim_matlocmat_namemat_rmat_cmatmn=check_dim1_matlocmat_namematmat_rm_strm;check_dim2_matlocmat_namematmat_cn_strnletget_dim1_matlocmat_namematrm_namem=letdim1=Array2.dim1matinget_mat_dim1~loc~mat_name~dim1~r~m~m_nameletget_dim2_matlocmat_namematcn_namen=letdim2=Array2.dim2matinget_mat_dim2~loc~mat_name~dim2~c~n~n_nameletcheck_mat_empty~loc~mat_name~dim1~dim2=ifdim1=0theninvalid_arg(sprintf"%s: dim1 of matrix %s is zero"locmat_name)elseifdim2=0theninvalid_arg(sprintf"%s: dim2 of matrix %s is zero"locmat_name)else()letget_vec_inclocvec_name=function|Someinc->check_vec_inc~loc~vec_nameinc;inc|None->1letget_vec_ofslocvar=function|Someofswhenofs<1->invalid_arg(sprintf"%s: ofs%s < 1"locvar)|Someofs->ofs|None->1(**)(* Dealing with pattern arguments in matrices *)moduleMat_patt=structtypekind=Upper|Lowerletcheck_upent~loc~l~m=ifl<=0thenfailwith(sprintf"%s: illegal initial rows (%d) of upper pentagon"locl)elseifl>mthenfailwith(sprintf"%s: initial rows (%d) of upper pentagon exceed maximum [m] (%d)"loclm)letcheck_lpent~loc~l~n=ifl<=0thenfailwith(sprintf"%s: illegal initial columns (%d) of lower pentagon"locl)elseifl>nthenfailwith(sprintf"%s: initial columns (%d) of lower pentagon exceed maximum [n] (%d)"locln)letcheck_args~loc~m~n:Types.Mat.pattoption->unit=function|None|Some`Full|Some`Utr|Some`Ltr->()|Some`Upentl->check_upent~loc~l~m|Some`Lpentl->check_lpent~loc~l~nletnormalize_args~loc~m~n:Types.Mat.pattoption->kind*int=function|None|Some`Full->Lower,n|Some`Utr->Upper,1|Some`Ltr->Lower,1|Some`Upentl->check_upent~loc~l~m;Upper,l|Some`Lpentl->check_lpent~loc~l~n;Lower,lletpatt_of_uplo~(uplo:[`U|`L]option)~(patt:Types.Mat.pattoption)=matchuplowith|Some`U->Some`Utr|Some`L->Some`Ltr|None->pattletpatt_of_up~up~(patt:Types.Mat.pattoption)=matchupwith|Sometrue->Some`Utr|Somefalse->Some`Ltr|None->pattend(* Mat_patt *)(**)(* Fetches problem-dependent parameters for LAPACK-functions *)externalilaenv:(int[@untagged])->string->string->(int[@untagged])->(int[@untagged])->(int[@untagged])->(int[@untagged])->(int[@untagged])="lacaml_ilaenv_stub_bc""lacaml_ilaenv_stub"[@@noalloc](* Get a work array *)letget_worklocvec_createworkmin_lworkopt_lworklwork_str=matchworkwith|Somework->letlwork=Array1.dimworkiniflwork<min_lworktheninvalid_arg(sprintf"%s: %s: valid=[%d..[ got=%d"loclwork_strmin_lworklwork)elsework,lwork|None->vec_createopt_lwork,opt_lworkletcalc_unpacked_dimlocn_vec=letn=truncate(sqrt(float(8*n_vec+1))*.0.5)inif(n*n+n)/2<>n_vecthenfailwith(sprintf"%s: illegal vector length: %d"locn_vec)elsen(* Calculate the dimension of a packed square matrix given the vector length *)letget_unpacked_dimloc?nn_vec=matchnwith|None->calc_unpacked_dimlocn_vec|Somen->letn_unpacked=calc_unpacked_dimlocn_vecinifn<0||n>n_unpackedtheninvalid_arg(sprintf"%s: n: valid=[0..%d] got=%d"locn_unpackedn)elsenletget_vec_geomlocvarofsinc=get_vec_ofslocvarofs,get_vec_inclocvarinc(* A symmetric band (SB) or triangular band (TB) matrix has physical size
[k+1]*[n] for a logical matrix of size [n]*[n]. Check and return the [k]
(possibly also given by the optional argument [k]). *)letget_k_mat_sblocmat_namematmat_rk_namek=letdim1=Array2.dim1matinletmax_k=dim1-mat_rinifmat_r<1||max_k<0theninvalid_arg(sprintf"%s: mat_r(%s): valid=[1..%d] got=%d"locmat_namedim1mat_r);matchkwith|None->max_k|Somek->ifk<0||max_k<ktheninvalid_arg(sprintf"%s: %s(%s): valid=[0..%d] got=%d"lock_namemat_namemax_kk)elsekletget_dim_mat_packedlocmat_nameofsmatmatn_namen=letdim=Array1.dimmatinmatchnwith|Somen->letn1=ofsmat+(n-1)*(n+2)/2(* ?overflow? *)inifn<0||dim<n1theninvalid_arg(sprintf"%s: %s(%s): valid=[0..%d] got=%d"locn_namemat_namedimn1)elsen|None->(* the greater n s.t. ofsmat - 1 + n(n+1)/2 <= dim mat *)max0(truncate((sqrt(9.+.8.*.float(dim-ofsmat))-.1.)/.2.))(* Makes sure that [mat] is a square matrix and [n] is within range *)letget_n_of_squarelocmat_namercmatn=letn=get_dim2_matlocmat_namematcn_strnincheck_dim1_matlocmat_namematrn_strn;nletget_n_of_alocaracan=get_n_of_squareloca_straracanletget_nrhs_of_blocnbrbcbnrhs=letnrhs=get_dim2_matlocb_strbbcnrhs_strnrhsincheck_dim1_matlocb_strbbrn_strn;nrhs(* ORGQR - Auxiliary Functions *)letorgqr_err~loc~m~n~k~work~a~err=letmsg=matcherrwith|-1->sprintf"m: valid=[0..[ got=%d"m|-2->sprintf"n: valid=[0..%d] got=%d"mn|-3->sprintf"k: valid=[0..%d] got=%d"nk|-5->sprintf"dim2(a): valid=[%d..[ got=%d"n(Array2.dim2a)|-8->sprintf"dim1(work): valid=[%d..[ got=%d"(max1n)(Array1.dimwork)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)letorgqr_get_paramsloc?m?n?k~tau~ar~aca=letm=get_dim1_matloca_straarm_strminletn=get_dim2_matloca_straacn_strninifm<ntheninvalid_arg(sprintf"%s: m(%d) < n(%d)"locmn)elseletk=get_dim_vecloctau_str11tauk_strkinm,n,k(* ORMQR - Auxiliary Functions *)letormqr_err~loc~side~m~n~k~lwork~a~c~err=letnq,nw=matchsidewith|`L->m,n|`R->n,minletmsg=matcherrwith|-3->sprintf"m: valid=[0..[ got=%d"m|-4->sprintf"n: valid=[0..[ got=%d"n|-5->sprintf"k: valid=[0..%d] got=%d"knq|-7->sprintf"dim1(a): valid=[%d..[ got=%d"(max1nq)(Array2.dim1a)|-10->sprintf"dim1(c): valid=[%d..[ got=%d"(max1m)(Array2.dim1c)|-12->letmin_lwork=max1nwinsprintf"lwork: valid=[%d..[ got=%d"min_lworklwork|_->raise(InternalError(sprintf"%s: error code %d"locerr))ininvalid_arg(sprintf"%s: %s"locmsg)letormqr_get_paramsloc~side?m?n?k~tau~ar~aca~cr~ccc=letm=get_dim1_matlocc_strccrm_strminletn=get_dim2_matlocc_strcccn_strninletk=get_dim2_matloca_straack_strkinbeginmatchsidewith|`L->ifm<kthenfailwith(sprintf"%s: m(%d) < k(%d)"locmk);check_dim1_matloca_straarm_str(max1m)|`R->ifn<kthenfailwith(sprintf"%s: n(%d) < k(%d)"locnk);check_dim1_matloca_straarn_str(max1n)end;check_vecloctau_strtauk;m,n,k(* GELS? - Auxiliary Functions *)letgelsX_errlocgelsX_min_workaramnlworknrhsbrberr=iferr>0thenfailwith(sprintf"%s: failed to converge on off-diagonal element %d"locerr)elseletmsg=matcherrwith|-1->sprintf"m: valid=[0..[ got=%d"m|-2->sprintf"n: valid=[0..[ got=%d"n|-3->sprintf"nrhs: valid=[0..[ got=%d"nrhs|-5->sprintf"dim1(a): valid=[%d..[ got=%d"(max1m+ar-1)(Array2.dim1a)|-7->letmin_dim=max1(maxmn)+br-1insprintf"dim1(b): valid=[%d..[ got=%d"min_dim(Array2.dim1b)|-12->letmin_lwork=gelsX_min_work~m~n~nrhsinsprintf"lwork: valid=[%d..[ got=%d"min_lworklwork|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)letgelsX_get_svec_createlocmin_dimofss=function|Somes->letdim_s=Array1.dimsinletmin_dim_ofs=ofss-1+min_diminifdim_s<min_dim_ofstheninvalid_arg(sprintf"%s: s: valid=[%d..[ got=%d"locmin_dim_ofsdim_s)elses|None->vec_createmin_dimletgelsX_get_paramslocaracamnnrhsbrbcb=letm=get_dim1_matloca_straarm_strminletn=get_dim2_matloca_straacn_strninletnrhs=get_dim2_matlocb_strbbcnrhs_strnrhsincheck_dim1_matlocb_strbbrm_str(maxmn);m,n,nrhs(* ??ev -- auxiliary functions *)letxxev_get_paramslocaracanvectorsup=letn=get_n_of_alocaracaninletjobz=get_job_charvectorsinletuplo=get_uplo_charupinn,jobz,uploletxxev_get_wxvec_createlocwnameofswwn=matchwwith|None->vec_create(ofsw-1+n)|Somew->check_veclocwnamew(ofsw-1+n);w(* geev -- auxiliary functions *)letgeev_get_job_sidelocmat_emptymat_createmat_namenrcmat_opt=matchmat_optwith|None->ifr<1thenfailwith(sprintf"%s: %sr < 1"locmat_name)elseifc<1thenfailwith(sprintf"%s: %sc < 1"locmat_name)elser,c,mat_create(n+r-1)(n+c-1),job_char_true,true|SomeNone->1,1,mat_empty,job_char_false,false|Some(Somemat)->check_dim1_matlocmat_namematrn_strn;check_dim2_matlocmat_namematcn_strn;r,c,mat,job_char_true,trueletgeev_gen_get_paramslocmat_emptymat_createaracanleftrleftcleftrightrrightcright=letn=get_n_of_alocaracaninletleftr,leftc,vl,jobvl,lvs=geev_get_job_sidelocmat_emptymat_create"vl"nleftrleftcleftinletrightr,rightc,vr,jobvr,rvs=geev_get_job_sidelocmat_emptymat_create"vr"nrightrrightcrightinn,leftr,leftc,vl,jobvl,rightr,rightc,vr,jobvr,lvs||rvs(* g?mv -- auxiliary functions *)letgXmv_get_paramslocvec_createmnofsxincxxofsyincyytrans=letofsx,incx=get_vec_geomlocx_strofsxincxinletofsy,incy=get_vec_geomlocy_strofsyincyinletlx,ly,trans_char=lettrans_char=get_trans_chartransiniftrans=`Nthenn,m,trans_charelsem,n,trans_charincheck_veclocx_strx(ofsx+(lx-1)*absincx);lety=get_veclocy_stryofsyincylyvec_createinofsx,incx,ofsy,incy,y,trans_char(* symv -- auxiliary functions *)letsymv_get_paramslocvec_createaracanofsxincxxofsyincyyup=letn=get_dim1_matloca_straarn_strnincheck_dim2_matloca_straacn_strn;letofsx,incx=get_vec_geomlocx_strofsxincxinletofsy,incy=get_vec_geomlocy_strofsyincyincheck_veclocx_strx(ofsx+(n-1)*absincx);lety=get_veclocy_stryofsyincynvec_createincheck_veclocy_stry(ofsy+(n-1)*absincy);n,ofsx,incx,ofsy,incy,y,get_uplo_charup(* tr?v -- auxiliary functions *)lettrXv_get_paramslocaracanofsxincxxuptransunit_triangular=letn=get_dim1_matloca_straarn_strnincheck_dim2_matloca_straacn_strn;lettrans_char=get_trans_chartransinletdiag_char=get_diag_charunit_triangularinletofsx,incx=get_vec_geomlocx_strofsxincxincheck_veclocx_strx(ofsx+(n-1)*absincx);n,ofsx,incx,get_uplo_charup,trans_char,diag_char(* tp?v -- auxiliary functions *)lettpXv_get_paramslocofsapap?nofsxincxxuptransunit_triangular=letofsap=get_vec_ofslocap_strofsapinletn=get_unpacked_dimloc?n(Array1.dimap-ofsap+1)inlettrans_char=get_trans_chartransinletdiag_char=get_diag_charunit_triangularinletofsx,incx=get_vec_geomlocx_strofsxincxincheck_veclocx_strx(ofsx+(n-1)*absincx);n,ofsap,ofsx,incx,get_uplo_charup,trans_char,diag_char(* gemm -- auxiliary functions *)letget_clocmat_createcrcccmn=get_matlocc_strmat_createcrcccmnletget_rows_mat_trlocmat_strmatmat_rmat_ctranspdim_strdim=matchtranspwith|`N->get_dim1_matlocmat_strmatmat_rdim_strdim|_->get_dim2_matlocmat_strmatmat_cdim_strdimletget_cols_mat_trlocmat_strmatmat_rmat_ctranspdim_strdim=matchtranspwith|`N->get_dim2_matlocmat_strmatmat_cdim_strdim|_->get_dim1_matlocmat_strmatmat_rdim_strdimletget_inner_dimlocmat1_strmat1mat1_rmat1_ctr1mat2_strmat2mat2_rmat2_ctr2dim_strk=letk1=get_cols_mat_trlocmat1_strmat1mat1_rmat1_ctr1dim_strkinletk2=get_rows_mat_trlocmat2_strmat2mat2_rmat2_ctr2dim_strkinifk=None&&k1<>k2thenfailwith(sprintf"%s: inner dimensions of matrices do not match (%d,%d)"lock1k2)elsek1letgemm_get_paramslocmat_createaracatransabrbcbcrtransbcccmnk=letm=get_rows_mat_trloca_straaractransam_strminletn=get_cols_mat_trlocb_strbbrbctransbn_strninletk=get_inner_dimloca_straaractransab_strbbrbctransbk_strkinlettransa=get_trans_chartransainlettransb=get_trans_chartransbinletc=get_clocmat_createcrcccmninm,n,k,transa,transb,c(* symm -- auxiliary functions *)letcheck_mat_squarelocmat_strmatmat_rmat_cn=check_dim1_matlocmat_strmatmat_rn_strn;check_dim2_matlocmat_strmatmat_cn_strnletsymm_get_paramslocmat_createaracabrbcbcrcccmnsideup=letm=get_dim1_matlocb_strbbrm_strminletn=get_dim2_matlocb_strbbcn_strninifside=`Lthencheck_mat_squareloca_straaracmelsecheck_mat_squareloca_straaracn;letside_char=get_side_charsideinletuplo_char=get_uplo_charupinletc=get_clocmat_createcrcccmninm,n,side_char,uplo_char,c(* trmm -- auxiliary functions *)lettrXm_get_paramslocaracabrbcbmnsideuptransadiag=letm=get_dim1_matlocb_strbbrm_strminletn=get_dim2_matlocb_strbbcn_strninifside=`Lthencheck_mat_squareloca_straaracmelsecheck_mat_squareloca_straaracn;letside_char=get_side_charsideinletuplo_char=get_uplo_charupinlettransa=get_trans_chartransainletdiag_char=get_diag_chardiaginm,n,side_char,uplo_char,transa,diag_char(* syrk -- auxiliary functions *)letsyrk_get_paramslocmat_createaracacrcccnkuptrans=letn=get_rows_mat_trloca_straaractransn_strninletk=get_cols_mat_trloca_straaractransk_strkinlettrans_char=get_trans_chartransinletuplo_char=get_uplo_charupinletc=get_clocmat_createcrcccnninn,k,uplo_char,trans_char,c(* syr2k -- auxiliary functions *)letsyr2k_get_paramslocmat_createaracabrbcbcrcccnkuptrans=letn=get_rows_mat_trloca_straaractransn_strninletk=get_cols_mat_trloca_straaractransk_strkinbeginmatchtranswith|`N->check_dim1_matlocb_strbbrn_strn;check_dim2_matlocb_strbbck_strk;|_->check_dim1_matlocb_strbbrk_strk;check_dim2_matlocb_strbbcn_strn;end;lettrans_char=get_trans_chartransinletuplo_char=get_uplo_charupinletc=get_clocmat_createcrcccnninn,k,uplo_char,trans_char,c(* ?lange -- auxiliary functions *)letxlange_get_paramslocmnaraca=letm=get_dim1_matloca_straarm_strminletn=get_dim2_matloca_straacn_strninm,n(* ??trs -- auxiliary functions *)letxxtrs_get_paramslocaracanbrbcbnrhs=letn=get_n_of_alocaracaninletnrhs=get_nrhs_of_blocnbrbcbnrhsinn,nrhsletxxtrs_errlocnnrhsaberr=letmsg=matcherrwith|-2->sprintf"n: valid=[0..[ got=%d"n|-3->sprintf"nrhs: valid=[0..[ got=%d"nrhs|-5->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|-8->sprintf"dim1(b): valid=[%d..[ got=%d"(max1n)(Array2.dim1b)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* ??tri -- auxiliary functions *)letxxtri_singular_errlocerr=failwith(sprintf"%s: singular on index %i"locerr)letxxtri_errlocnaerr=letmsg=matcherrwith|-2->sprintf"n: valid=[0..[ got=%d"n|-4->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* ??con -- auxiliary functions *)letxxcon_errlocnaerr=letmsg=matcherrwith|-2->sprintf"n: valid=[0..[ got=%d"n|-4->sprintf"dim1(a): valid=%d..[ got=%d"(max1n)(Array2.dim1a)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* geXrf -- auxiliary functions *)letgeXrf_get_paramslocmnaraca=letm=get_dim1_matloca_straarm_strminletn=get_dim2_matloca_straacn_strninm,n(* getrf -- auxiliary functions *)letgetrf_errlocmnaerr=letmsg=matcherrwith|-1->sprintf"n: valid=[0..[ got=%d"n|-2->sprintf"m: valid=[0..[ got=%d"m|-4->sprintf"dim1(a): valid=[%d..[ got=%d"(max1m)(Array2.dim1a)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)letgetrf_lu_errlocerr=failwith(sprintf"%s: U(%i,%i)=0 in the LU factorization"locerrerr)letgetrf_get_ipivlocipivmn=matchipivwith|None->create_int32_vec(minmn)|Someipiv->check_veclocipiv_stripiv(minmn);ipiv(* sytrf -- auxiliary functions *)letsytrf_get_ipivlocipivn=matchipivwith|None->create_int32_vecn|Someipiv->check_veclocipiv_stripivn;ipivletsytrf_errlocnaerr=letmsg=matcherrwith|-2->sprintf"n: valid=[0..[ got=%d"n|-4->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)letsytrf_fact_errlocerr=failwith(sprintf"%s: D(%i,%i)=0 in the factorization"locerrerr)(* potrf -- auxiliary functions *)letpotrf_chol_errlocerr=failwith(sprintf"%s: leading minor of order %d is not positive definite"locerr)letpotrf_errlocnaerr=letmsg=matcherrwith|-2->sprintf"n: valid=[0..[ got=%d"n|-4->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|_->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* potrs -- auxiliary functions *)letpotrs_errlocnnrhsaberr=letmsg=matcherrwith|-2->sprintf"n: valid=[0..[ got=%d"n|-3->sprintf"nrhs: valid=[0..[ got=%d"nrhs|-5->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|-7->sprintf"dim1(b): valid=[%d..[ got=%d"(max1n)(Array2.dim1b)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* trtrs -- auxiliary functions *)lettrtrs_errlocnnrhsaberr=letmsg=matcherrwith|-4->sprintf"n: valid=[0..[ got=%d"n|-5->sprintf"nrhs: valid=[0..[ got=%d"nrhs|-7->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|-9->sprintf"dim1(b): valid=[%d..[ got=%d"(max1n)(Array2.dim1b)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* tbtrs -- auxiliary functions *)lettbtrs_errlocnnrhskdabberr=letmsg=matcherrwith|-4->sprintf"n: valid=[0..[ got=%d"n|-5->sprintf"kd: valid=[0..[ got=%d"kd|-6->sprintf"nrhs: valid=[0..[ got=%d"nrhs|-8->sprintf"dim1(ab): valid=[%d..[ got=%d"(max1n)(Array2.dim1ab)|-10->sprintf"dim1(b): valid=[%d..[ got=%d"(max1n)(Array2.dim1b)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* getri -- auxiliary functions *)letgetri_errlocgetri_min_lworknalworkerr=letmsg=matcherrwith|-1->sprintf"n: valid=[0..[ got=%d"n|-3->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|-6->letmin_lwork=getri_min_lworkninsprintf"lwork: valid=[%d..[ got=%d"min_lworklwork|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* trtri -- auxiliary functions *)lettrtri_errlocnaerr=letmsg=matcherrwith|-3->sprintf"n: valid=[0..[ got=%d"n|-5->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* geqrf -- auxiliary functions *)letgeqrf_errlocmnaerr=letmsg=matcherrwith|-1->sprintf"m: valid=[0..[ got=%d"m|-2->sprintf"n: valid=[0..[ got=%d"n|-4->sprintf"dim1(a): valid=[%d..[ got=%d"(max1n)(Array2.dim1a)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* gecon -- auxiliary functions *)letgecon_errlocnorm_charnaerr=letmsg=matcherrwith|-1->sprintf"norm: valid=['O', I'] got='%c'"norm_char|-2->sprintf"n: valid=[0..[ got=%d"n|-4->sprintf"dim1(a): valid=%d..[ got=%d"(max1n)(Array2.dim1a)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)(* gees -- auxiliary functions *)letgees_errlocnerrjobvssort=iferr>0&&err<=nthenfailwith(sprintf"%s: %d eigenvalue elements did not converge"locerr)elseiferr=n+1thenfailwith(sprintf"%s: eigenvalues not reordered, too close to separate"loc)elseiferr=n+2thenfailwith(sprintf"%s: after reordering, roundoff changed values of some \
complex eigenvalues so that leading eigenvalues in \
the Schur form no longer satisfy SELECT"loc)elseletmsg=matcherrwith|-1->sprintf"JOBVS: valid=['N', V'] got='%c'"jobvs|-2->sprintf"SORT: valid=['N', S'] got='%c'"sort|-4->sprintf"n: valid=[0..[ got=%d"n|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)letdummy_select_fun_=falseletgees_get_params_genericlocmat_createmat_emptyjobvssortnaracavsrvscvs=letn=get_n_of_alocaracaninletjobvs,min_ldvs=matchjobvswith|`No_Schur_vectors->'N',1|`Compute_Schur_vectors->'V',ninletvs=matchvswith|Somevs->check_dim1_matlocvs_strvsvsrvsr_strmin_ldvs;check_dim2_matlocvs_strvsvscvsc_strn;vs|Nonewhenjobvs='N'->mat_empty|None->mat_createmin_ldvsninletsort,select,select_fun=matchsortwith|`No_sort->'N',0,dummy_select_fun|`Select_left_plane->'S',0,dummy_select_fun|`Select_right_plane->'S',1,dummy_select_fun|`Select_interior_disk->'S',2,dummy_select_fun|`Select_exterior_disk->'S',3,dummy_select_fun|`Select_customselect_fun->'S',4,select_funinjobvs,sort,select,select_fun,n,vsletgees_get_params_reallocvec_createmat_createmat_emptyjobvssortnaracawrwivsrvscvs=letjobvs,sort,select,select_fun,n,vs=gees_get_params_genericlocmat_createmat_emptyjobvssortnaracavsrvscvsinletwr=matchwrwith|None->vec_createn|Somewr->check_veclocwr_strwrn;wrinletwi=matchwiwith|None->vec_createn|Somewi->check_veclocwi_strwin;wiinjobvs,sort,select,select_fun,n,vs,wr,wiletgees_get_params_complexlocvec_createmat_createmat_emptyjobvssortnaracawvsrvscvs=letjobvs,sort,select,select_fun,n,vs=gees_get_params_genericlocmat_createmat_emptyjobvssortnaracavsrvscvsinletw=matchwwith|None->vec_createn|Somew->check_veclocw_strwn;winjobvs,sort,select,select_fun,n,vs,w(* gesvd -- auxiliary functions *)letgesvd_errlocjobujobvtmnauvtlworkerr=iferr>0thenfailwith(sprintf"%s: %d off-diagonal elements did not converge"locerr)elseletmsg=matcherrwith|-3->sprintf"m: valid=[0..[ got=%d"m|-4->sprintf"n: valid=[0..[ got=%d"n|-6->sprintf"dim1(a): valid=[%d..[ got=%d"(max1m)(Array2.dim1a)|-9->sprintf"dim1(u): valid=[%d..[ got=%d"(matchjobuwith'A'|'S'->max1m|_->1)(Array2.dim1u)|-11->sprintf"dim1(vt): valid=[%d..[ got=%d"(matchjobvtwith|'A'->max1n|'S'->max1(minmn)|_->1)(Array2.dim1vt)|-13->sprintf"lwork: valid=[%d..[ got=%d"1lwork|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)letgesvd_get_paramslocvec_createmat_createjobujobvtmnaracasurucuvtrvtcvt=letm=get_dim1_matloca_straarm_strminletn=get_dim2_matloca_straacn_strninlets=get_veclocs_strs11(minmn)vec_createinletum,un=matchjobuwith|`A->m,m|`S->m,minmn|`O|`N->1,1in(* LDU >= 1 even when U not referenced *)letu=matchuwith|Someu->check_dim1_matlocu_struurum_strum;check_dim2_matlocu_struucun_strun;u|None->mat_createumuninletvm,vn=matchjobvtwith|`A->n,n|`S->minmn,n|`O|`N->1,1in(* LDVT >= 1 even when VT not referenced *)letvt=matchvtwith|Somevt->check_dim1_matlocvt_strvtvtrvm_strvm;check_dim2_matlocvt_strvtvtcvn_strvn;vt|None->mat_createvmvninletjobu_c=get_s_d_job_charjobuinletjobvt_c=get_s_d_job_charjobvtinjobu_c,jobvt_c,m,n,s,u,vt(* gesdd -- auxiliary functions *)letgesdd_errlocjobzmnauvtlworkerr=iferr>0thenfailwith(sprintf"%s: %d DBDSDC did not converge, updating process failed"locerr)elseletmsg=matcherrwith|-2->sprintf"m: valid=[0..[ got=%d"m|-3->sprintf"n: valid=[0..[ got=%d"n|-5->sprintf"dim1(a): valid=[%d..[ got=%d"(max1m)(Array2.dim1a)|-8->sprintf"dim1(u): valid=[%d..[ got=%d"(ifjobz='A'||jobz='S'||(jobz='O'&&m<n)thenmax1melse1)(Array2.dim1u)|-10->sprintf"dim1(vt): valid=[%d..[ got=%d"(ifjobz='A'||(jobz='O'&&m>=n)thenmax1nelseifjobz='S'thenmax1(minmn)else1)(Array2.dim1vt)|-12->sprintf"lwork: valid=[%d..[ got=%d"1lwork|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)letgesdd_get_paramslocvec_createmat_createjobzmnaracasurucuvtrvtcvt=letm=get_dim1_matloca_straarm_strminletn=get_dim2_matloca_straacn_strninletmin_m_n=minmninlets=get_veclocs_strs11min_m_nvec_createinletum,un,vm,vn=matchjobzwith|`A->m,m,n,n|`S->m,min_m_n,min_m_n,n|`O->ifm>=nthen1,1,n,nelsem,m,m,n|`N->1,1,1,1in(* LDU >= 1 even when U not referenced *)letu=matchuwith|Someu->check_dim1_matlocu_struurum_strum;check_dim2_matlocu_struucun_strun;u|None->mat_createumuninletvt=matchvtwith|Somevt->check_dim1_matlocvt_strvtvtrvm_strvm;check_dim2_matlocvt_strvtvtcvn_strvn;vt|None->mat_createvmvninletjobz_c=get_s_d_job_charjobzinjobz_c,m,n,s,u,vt(* ??sv -- auxiliary functions *)letxxsv_errlocnnrhsberr=letmsg=matcherrwith|-1->sprintf"n: valid=[0..[ got=%d"n|-2->sprintf"nrhs: valid=[0..[ got=%d"nrhs|-7->sprintf"dim1(b): valid=[%d..[ got=%d"(max1n)(Array2.dim1b)|n->raise(InternalError(sprintf"%s: error code %d"locn))ininvalid_arg(sprintf"%s: %s"locmsg)letxxsv_lu_errlocerr=failwith(sprintf"%s: U(%i,%i)=0 in the LU factorization"locerrerr)letxxsv_pos_errlocerr=letmsg=sprintf"%s: the leading minor of order %i is not positive definite"locerrinfailwithmsgletxxsv_ind_errlocerr=letmsg=sprintf"%s: D(%i,%i)=0 in the diagonal pivoting factorization"locerrerrinfailwithmsgletxxsv_a_errlocan=letmsg=sprintf"%s: dim1(a): valid=[%d..[ got=%d"loc(max1n)(Array2.dim1a)ininvalid_argmsgletxxsv_work_errloclwork=invalid_arg(sprintf"%s: dim(work): valid=[1..[ got=%d"loclwork)letxxsv_get_ipivlocipivn=matchipivwith|None->create_int32_vecn|Someipiv->check_veclocipiv_stripivn;ipivletxxsv_get_paramslocaracanbrbcbnrhs=letn=get_n_of_alocaracaninletnrhs=get_nrhs_of_blocnbrbcbnrhsinn,nrhs