lapack.c 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113
  1. /* this file interfaces to a couple of linear algebra functions from lapack
  2. Copyright (C) 2006,2009 Dennis Furey
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software Foundation,
  13. Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  14. */
  15. #include <avm/common.h>
  16. #include <avm/error.h>
  17. #include <avm/lists.h>
  18. #include <avm/compare.h>
  19. #include <avm/listfuns.h>
  20. #include <avm/matcon.h>
  21. #include <avm/chrcodes.h>
  22. #include <avm/lapack.h>
  23. #if HAVE_LAPACK
  24. typedef double complex[2];
  25. #define RE 0
  26. #define IM 1
  27. #endif
  28. /* non-zero means static variables are initialized */
  29. static int initialized = 0;
  30. /* error messages as lists of lists of character representations */
  31. static list lapack_error = NULL;
  32. static list bad_lapack_spec = NULL;
  33. static list memory_overflow = NULL;
  34. static list unrecognized_function_name = NULL;
  35. /* function names as lists of lists of character representations */
  36. static list wild = NULL;
  37. static list funs = NULL;
  38. #define MIN(x,y) ((x < y) ? x : y)
  39. #define MAX(x,y) ((x < y) ? y : x)
  40. /* the smallest number whose inverse is finitely representable */
  41. static double safemin = 0.0;
  42. #if HAVE_LAPACK
  43. /* use the LU factorization to compute the solution to a real system of linear equations A * X = B */
  44. extern void
  45. dgesvx_(char *fact, char *trans, int *n, int *nrhs, double *a, int *lda, double *af, int *ldaf, int *ipiv, char *equed,
  46. double *r, double *c, double *b, int *ldb, double *x, int *ldx, double *rcond, double *ferr, double *berr,
  47. double *work, int *iwork, int *info);
  48. /* use the LU factorization to compute the solution to a complex system of linear equations A * X = B */
  49. extern void
  50. zgesvx_(char *fact, char *trans, int *n, int *nrhs, complex *a, int *lda, complex *af, int *ldaf, int *ipiv,
  51. char *equed, double *r, double *c, complex *b, int *ldb, complex *x, int *ldx, double *rcond, double *ferr,
  52. double *berr, complex *work, double *rwork, int *info);
  53. /* compute the singular value decomposition (SVD) of a real M-by-N matrix A */
  54. extern void
  55. dgesdd_(char *jobz, int *m, int *n, double *a, int *lda, double *s, double *u, int *ldu, double *vt, int *ldvt,
  56. double *work, int *lwork, int *iwork, int *info);
  57. /* compute the singular value decomposition (SVD) of a complex M-by-N matrix A */
  58. extern void
  59. zgesdd_(char *jobz, int *m, int *n, complex *a, int *lda, double *s, complex *u, int *ldu, complex *vt, int *ldvt,
  60. complex *work, int *lwork, double *rwork, int *iwork, int *info);
  61. /* compute the minimum-norm solution to a real linear least squares problem */
  62. extern void
  63. dgelsd_(int *m, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, double *s, double *rcond, int *rank,
  64. double *work, int *lwork, int *iwork, int *info);
  65. /* compute the minimum-norm solution to a complex linear least squares problem */
  66. extern void
  67. zgelsd_(int *m, int *n, int *nrhs, complex *a, int *lda, complex *b, int *ldb, double *s, double *rcond, int *rank,
  68. complex *work, int *lwork, double *rwork, int *iwork, int *info);
  69. /* compute all the eigenvalues and, optionally, eigenvectors of a real symmetric matrix A in packed storage */
  70. extern void
  71. dspev_(char *jobz, char *uplo, int *n, double *ap, double *w, double *z, int *ldz, double *work, int *info);
  72. /* compute selected eigenvalues and, optionally, eigenvectors of a real symmetric matrix */
  73. extern void
  74. dsyevr_(char *jobz, char *range, char *uplo, int *n, double *a, int *lda, double *vl, double *vu, int *il, int *iu,
  75. double *abstol, int *m, double *w, double *z, int *ldz, int *isuppz, double *work, int *lwork, int *iwork,
  76. int *liwork, int *info);
  77. /* compute all the eigenvalues and, optionally, eigenvectors of a complex Hermitian matrix A in packed storage */
  78. extern void
  79. zhpev_(char *jobz, char *uplo, int *n, complex *ap, double *w, complex *z, int *ldz, complex *work, double *rwork,
  80. int *info);
  81. /* compute selected eigenvalues and, optionally, eigenvectors of a complex Hermitian matrix */
  82. extern void
  83. zheevr_(char *jobz, char *range, char *uplo, int *n, complex *a, int *lda, double *vl, double *vu, int *il, int *iu,
  84. double *abstol, int *m, double *w, complex *z, int *ldz, int *isuppz, complex *work, int *lwork, double *rwork,
  85. int *lrwork, int *iwork, int *liwork, int *info);
  86. /* compute for an N-by-N real nonsymmetric matrix A, the eigenvalues and, optionally, the left and/or right eigenvectors */
  87. extern void
  88. dgeevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, double *a, int *lda, double *wr, double *wi,
  89. double *vl, int *ldvl, double *vr, int *ldvr, int *ilo, int *ihi, double *scale, double *abnrm, double *rconde,
  90. double *rcondv, double *work, int *lwork, int *iwork, int *info);
  91. /* compute for an N-by-N complex nonsymmetric matrix A, the eigenvalues and, optionally, the left and/or right eigenvectors */
  92. extern void
  93. zgeevx_(char *balanc, char *jobvl, char *jobvr, char *sense, int *n, complex *a, int *lda, complex *w, complex *vl,
  94. int *ldvl, complex *vr, int *ldvr, int *ilo, int *ihi, double *scale, double *abnrm, double *rconde,
  95. double *rcondv, complex *work, int *lwork, double *rwork, int *info);
  96. /* compute the Shur decomposition for an N-by-N real non-symmetric matrix A */
  97. extern void
  98. dgeesx_(char *jobvs, char *sort, void *select, char *sense, int *n, double *a, int *lda, int *sdim, double *wr, double *wi,
  99. double *vs, int *ldvs, double *rconde, double *rcondv, double *work, int * lwork, int *iwork, int *liwork, int *bwork,
  100. int *info);
  101. /* compute the Shur decomposition for an N-by-N complex non-symmetric matrix A */
  102. extern void
  103. zgeesx_(char *jobvs, char *sort, void *select, char *sense, int *n, complex *a, int *lda, int *sdim, complex *w, complex *vs,
  104. int *ldvs, double *rconde, double *rcondv, complex *work, int *lwork, double *rwork, int *bwork, int *info);
  105. /* compute the Cholesky factorization of a real symmetric positive definite matrix A stored in packed format */
  106. extern void
  107. dpptrf_(char *uplo, int *n, double *ap, int *info);
  108. /* compute the Cholesky factorization of a complex Hermitian positive definite matrix A stored in packed format */
  109. extern void
  110. zpptrf_(char *uplo, int *n, complex *ap, int *info);
  111. /* determines double precision machine parameters */
  112. extern double
  113. dlamch_(char *cmach);
  114. /* choose problem-dependent parameters for the local environment */
  115. extern int
  116. ilaenv_(int *ispec,char *name,char *opts,int *n1, int *n2,int *n3,int *n4);
  117. /* solve the linear equality-constrained least squares (LSE) problem */
  118. extern void
  119. dgglse_(int *m, int *n, int *p, double *a, int *lda, double *b, int *ldb, double *c, double *d, double *x, double *work,
  120. int *lwork, int *info);
  121. /* solve the linear equality-constrained least squares (LSE) problem */
  122. extern void
  123. zgglse_(int *m, int *n, int *p, complex *a, int *lda, complex *b, int *ldb, complex *c, complex *d, complex *x, complex *work,
  124. int *lwork, int *info);
  125. /* solve a general Gauss-Markov linear model (GLM) problem */
  126. extern void
  127. dggglm_(int *n, int *m, int *p, double *a, int *lda, double *b, int *ldb, double *d, double *x, double *y, double *work,
  128. int *lwork, int *info);
  129. /* solve a general Gauss-Markov linear model (GLM) problem */
  130. extern void
  131. zggglm_(int *n, int *m, int *p, complex *a, int *lda, complex *b, int *ldb, complex *d, complex *x, complex *y, complex *work,
  132. int *lwork, int *info);
  133. static list
  134. dgesvx_caller (ab, fault)
  135. list ab;
  136. int *fault;
  137. /* takes a list representing a pair (<<a..>..>,<b..>) where the
  138. left is a row ordered square matrix and returns the solution
  139. of the corresponding system of linear equations as a list of
  140. numbers; returns an empty list if the matrix is singular */
  141. {
  142. char fact;
  143. char trans;
  144. int n;
  145. int nrhs;
  146. double *a;
  147. int lda;
  148. double *af;
  149. int ldaf,*ipiv;
  150. char equed;
  151. double *r,*c,*b;
  152. int ldb;
  153. double *x;
  154. int ldx;
  155. double rcond,*ferr,*berr,*work;
  156. int *iwork,info;
  157. list result;
  158. if (*fault)
  159. return NULL;
  160. result = NULL;
  161. if (*fault = !(ab ? (avm_length(ab->head) == avm_length(ab->tail)) : 0))
  162. return avm_copied(bad_lapack_spec);
  163. fact = 'E';
  164. trans = 'N';
  165. n = avm_length(ab->head);
  166. nrhs = 1;
  167. a = (double *) avm_matrix_of_list(1,0,0,1,ab->head,sizeof(double),&result,fault);
  168. lda = n;
  169. af = (double *) malloc(n * n * sizeof(double));
  170. ldaf = n;
  171. ipiv = (int *) malloc(n * sizeof(int));
  172. r = (double *) malloc(n * sizeof(double));
  173. c = (double *) malloc(n * sizeof(double));
  174. b = (double *) avm_vector_of_list(ab->tail,sizeof(double),&result,fault);
  175. ldb = n;
  176. x = (double *) malloc(n * sizeof(double));
  177. ldx = n;
  178. ferr = (double *) malloc(nrhs * sizeof(double));
  179. berr = (double *) malloc(nrhs * sizeof(double));
  180. work = (double *) malloc(4 * n * sizeof(double));
  181. iwork = (int *) malloc(n * sizeof(int));
  182. if (!*fault)
  183. *fault = !(a ? (af ? (ipiv ? (r ? (c ? (b ? (x ? (ferr ? (berr ? (work ? !!iwork : 0):0):0):0):0):0):0):0):0):0);
  184. if (*fault)
  185. result = (result ? result : avm_copied(memory_overflow));
  186. else
  187. dgesvx_(&fact,&trans,&n,&nrhs,a,&lda,af,&ldaf,ipiv,&equed,r,c,b,&ldb,x,&ldx,&rcond,ferr,berr,work,iwork,&info);
  188. if (a)
  189. free(a);
  190. if (af)
  191. free (af);
  192. if (ipiv)
  193. free (ipiv);
  194. if (r)
  195. free(r);
  196. if (c)
  197. free (c);
  198. if (b)
  199. free (b);
  200. if (ferr)
  201. free (ferr);
  202. if (berr)
  203. free (berr);
  204. if (work)
  205. free (work);
  206. if (iwork)
  207. free (iwork);
  208. if (*fault ? 1 : (info > n))
  209. result = (result ? result : avm_copied(lapack_error));
  210. else if (info < 0)
  211. avm_internal_error (84);
  212. else if (info == 0)
  213. result = avm_list_of_vector((void *) x,n,sizeof(double),fault);
  214. if (x)
  215. free (x);
  216. return result;
  217. }
  218. static list
  219. zgesvx_caller (operand, fault)
  220. list operand;
  221. int *fault;
  222. /* same as above but for complex numbers */
  223. {
  224. char fact;
  225. char trans;
  226. int n;
  227. int nrhs;
  228. complex *a;
  229. int lda;
  230. complex *af;
  231. int ldaf;
  232. int *ipiv;
  233. char equed;
  234. double *r;
  235. double *c;
  236. complex *b;
  237. int ldb;
  238. complex *x;
  239. int ldx;
  240. double rcond;
  241. double *ferr;
  242. double *berr;
  243. complex *work;
  244. double *rwork;
  245. int info;
  246. list result;
  247. if (*fault)
  248. return NULL;
  249. if (*fault = !(operand ? (avm_length(operand->head) == avm_length(operand->tail)) : 0))
  250. result = avm_copied (bad_lapack_spec);
  251. fact = 'E';
  252. trans = 'N';
  253. n = (int) avm_length(operand);
  254. nrhs = 1;
  255. a = (*fault ? NULL : (complex *) avm_matrix_of_list(1,0,0,1,operand->head,sizeof(complex),&result,fault));
  256. lda = n;
  257. ldaf = n;
  258. af = malloc(sizeof(complex) * ldaf * n);
  259. ipiv = (int *) malloc(sizeof(int) * n);
  260. r = (double *) malloc(sizeof(double) * n);
  261. c = (double *) malloc(sizeof(double) * n);
  262. ldb = n;
  263. b = (*fault ? NULL : (complex *) avm_vector_of_list(operand->tail,sizeof(double),&result,fault));
  264. ldx = n;
  265. x = (complex *) malloc(sizeof(complex) * ldx * nrhs);
  266. ferr = (double *) malloc(sizeof(double) * nrhs);
  267. berr = (double *) malloc(sizeof(double) * nrhs);
  268. work = (complex *) malloc(sizeof(complex) * 2 * n);
  269. rwork = (double *) malloc(sizeof(double) * 2 * n);
  270. if (!*fault)
  271. *fault = !(a ? (af ? (ipiv ? (r ? (c ? (b ? (x ? (ferr ? (berr ? (work ? !!rwork : 0):0):0):0):0):0):0):0):0):0);
  272. if (!*fault)
  273. zgesvx_(&fact,&trans,&n,&nrhs,a,&lda,af,&ldaf,ipiv,&equed,r,c,b,&ldb,x,&ldx,&rcond,ferr,berr,work,rwork,&info);
  274. if (a)
  275. free(a);
  276. if (af)
  277. free (af);
  278. if (ipiv)
  279. free (ipiv);
  280. if (r)
  281. free(r);
  282. if (c)
  283. free (c);
  284. if (b)
  285. free (b);
  286. if (ferr)
  287. free (ferr);
  288. if (berr)
  289. free (berr);
  290. if (work)
  291. free (work);
  292. if (rwork)
  293. free (rwork);
  294. if (*fault ? 1 : (info > n))
  295. result = (result ? result : avm_copied(lapack_error));
  296. else if (info < 0)
  297. avm_internal_error (89);
  298. else if (info == 0)
  299. result = avm_list_of_vector((void *) x,n,sizeof(complex),fault);
  300. if (x)
  301. free (x);
  302. return result;
  303. }
  304. static list
  305. dgesdd_caller (operand, fault)
  306. list operand;
  307. int *fault;
  308. /* takes a list of m time series each of length n and returns a
  309. list of basis vectors each of length n for the singular value
  310. decomposition; the number of basis vectors is at most min(m,n)
  311. but could be less if the input time series aren't linearly
  312. independent; an empty list could be returned due to failure of
  313. convergence */
  314. {
  315. #define EPS 1.0e-8 /* for deciding the rank; consecutive singular values shouldn't fall by more than this ratio */
  316. char jobz;
  317. int m;
  318. int n;
  319. double *a;
  320. int lda;
  321. double *s;
  322. double *u;
  323. int ldu;
  324. double *vt;
  325. int ldvt;
  326. double *work;
  327. int lwork;
  328. int *iwork;
  329. int info;
  330. list result;
  331. int ucol,vtcol,prank,optimum_lwork;
  332. if (*fault)
  333. return NULL;
  334. if (*fault = !operand)
  335. return avm_copied(bad_lapack_spec);
  336. result = NULL;
  337. jobz = 'O';
  338. m = (int) avm_length(operand);
  339. n = (int) avm_length(operand->head);
  340. a = (double *) avm_matrix_of_list(0,0,0,1,operand,sizeof(double),&result,fault);
  341. lda = m;
  342. s = (double *) malloc(sizeof(double) * MIN(m,n));
  343. ucol = ldu = ((m < n) ? m : 1);
  344. u = (double *) malloc(ldu * ucol * sizeof(double));
  345. vtcol = ldvt = ((m < n) ? 1 : n);
  346. vt = (double *) malloc(ldvt * vtcol * sizeof(double));
  347. work = (double *) malloc(sizeof(double));
  348. lwork = (3 * MIN(m,n) * MIN(m,n)) + MAX(MAX(m,n),(5 * MIN(m,n) * MIN(m,n)) + (4 * MIN(m,n)));
  349. iwork = (int *) malloc(sizeof(int) * 8 * MIN(m,n));
  350. if (!(*fault = (*fault ? 1 : !(a ? (s ? (u ? (vt ? (work ? !!iwork : 0) : 0) : 0) : 0) : 0))))
  351. {
  352. optimum_lwork = -1;
  353. dgesdd_(&jobz,&m,&n,a,&lda,s,u,&ldu,vt,&ldvt,work,&optimum_lwork,iwork,&info);
  354. optimum_lwork = work[0];
  355. free(work);
  356. if (work = (double *) malloc(sizeof(double) * optimum_lwork))
  357. lwork = optimum_lwork;
  358. else
  359. *fault = !(work = (double *) malloc(sizeof(double) * lwork));
  360. }
  361. if (*fault)
  362. result = (result ? result : avm_copied(memory_overflow));
  363. else
  364. dgesdd_(&jobz,&m,&n,a,&lda,s,u,&ldu,vt,&ldvt,work,&lwork,iwork,&info);
  365. if (*fault ? 0 : (info < 0))
  366. avm_internal_error (85);
  367. if (u)
  368. free (u);
  369. if (work)
  370. free (work);
  371. if (iwork)
  372. free (iwork);
  373. prank = 1;
  374. if (s)
  375. {
  376. while (*fault ? 0 : ((prank < MIN(m,n) ? ((safemin < s[prank - 1]) ? ((s[prank] / s[prank - 1]) > EPS) : 0) : 0)))
  377. prank++;
  378. free (s);
  379. }
  380. if (*fault ? 0 : ((info == 0) ? (m < n) : 0))
  381. {
  382. free(vt);
  383. vt = NULL;
  384. a = (double *) avm_matrix_transposition((void *) a,n,m,sizeof(double));
  385. result = avm_list_of_matrix((void *) a,MIN(prank + 1,m),n,sizeof(double),fault);
  386. }
  387. else if (*fault ? 0 : (info == 0))
  388. {
  389. free (a);
  390. a = NULL;
  391. vt = (double *) avm_matrix_transposition((void *) vt,n,n,sizeof(double));
  392. result = avm_list_of_matrix((void *) vt,MIN(prank + 1,n),n,sizeof(double),fault);
  393. }
  394. if (a)
  395. free (a);
  396. if (vt)
  397. free (vt);
  398. return (*fault ? (result ? result : avm_copied(lapack_error)) : result);
  399. }
  400. static list
  401. zgesdd_caller (operand, fault)
  402. list operand;
  403. int *fault;
  404. /* same as above for complex numbers */
  405. {
  406. char jobz;
  407. int m;
  408. int n;
  409. complex *a;
  410. int lda;
  411. double *s;
  412. complex *u;
  413. int ldu;
  414. complex *vt;
  415. int ldvt;
  416. complex *work;
  417. int lwork;
  418. double *rwork;
  419. int *iwork;
  420. int info;
  421. list result;
  422. int ucol,vtcol,opt_lwork;
  423. int prank;
  424. #define EPS 1.0e-8 /* for deciding the rank; consecutive singular values shouldn't fall by more than this ratio */
  425. if (*fault)
  426. return NULL;
  427. if (*fault = !operand)
  428. return avm_copied(bad_lapack_spec);
  429. result = NULL;
  430. jobz = 'A';
  431. m = (int) avm_length(operand);
  432. n = (int) avm_length(operand->head);
  433. a = (complex *) avm_matrix_of_list(0,0,0,1,operand,sizeof(complex),&result,fault);
  434. lda = m;
  435. s = (double *) malloc(sizeof(double) * MIN(m,n));
  436. ucol = ldu = ((m < n) ? m : 1);
  437. u = (complex *) malloc(ldu * ucol * sizeof(complex));
  438. vtcol = ldvt = ((m < n) ? 1 : n);
  439. vt = (complex *) malloc(ldvt * vtcol * sizeof(complex));
  440. work = (complex *) malloc(sizeof(complex));
  441. lwork = (MIN(m,n) * MIN(m,n)) + (2 * MIN(m,n)) + MAX(m,n);
  442. rwork = (double *) malloc(sizeof(double) * (5 * MIN(m,n) * MIN(m,n) + 5 * MIN(m,n)));
  443. iwork = (int *) malloc(sizeof(int) * 8 * MIN(m,n));
  444. if (!(*fault = !(a ? (s ? (u ? (vt ? (work ? (rwork ? !!iwork : 0) : 0) : 0) : 0) : 0) : 0)))
  445. {
  446. opt_lwork = -1;
  447. zgesdd_(&jobz,&m,&n,a,&lda,s,u,&ldu,vt,&ldvt,work,&opt_lwork,rwork,iwork,&info);
  448. opt_lwork = work[0][RE];
  449. free(work);
  450. if (work = (complex *) malloc(sizeof(complex) * opt_lwork))
  451. lwork = opt_lwork;
  452. else
  453. *fault = !(work = (complex *) malloc(sizeof(complex) * lwork));
  454. }
  455. if (*fault)
  456. result = (result ? result : avm_copied(memory_overflow));
  457. else
  458. zgesdd_(&jobz,&m,&n,a,&lda,s,u,&ldu,vt,&ldvt,work,&lwork,rwork,iwork,&info);
  459. if (*fault ? 0 : (info < 0))
  460. avm_internal_error (90);
  461. if (u)
  462. free (u);
  463. if (work)
  464. free (work);
  465. if (iwork)
  466. free (iwork);
  467. if (rwork)
  468. free (rwork);
  469. prank = 1;
  470. if (s)
  471. {
  472. while (*fault ? 0 : ((prank < MIN(m,n) ? ((safemin < s[prank - 1]) ? ((s[prank] / s[prank - 1]) > EPS) : 0) : 0)))
  473. prank++;
  474. free (s);
  475. }
  476. if (*fault ? 0 : ((info == 0) ? (m < n) : 0))
  477. {
  478. free(vt);
  479. vt = NULL;
  480. a = (complex *) avm_matrix_transposition((void *) a,n,m,sizeof(complex));
  481. result = avm_list_of_matrix((void *) a,MIN(prank + 1,m),n,sizeof(complex),fault);
  482. }
  483. else if (*fault ? 0 : (info == 0))
  484. {
  485. free (a);
  486. a = NULL;
  487. vt = (complex *) avm_matrix_transposition((void *) vt,n,n,sizeof(complex));
  488. result = avm_list_of_matrix((void *) vt,MIN(prank + 1,n),n,sizeof(complex),fault);
  489. }
  490. if (a)
  491. free (a);
  492. if (vt)
  493. free (vt);
  494. return (*fault ? (result ? result : avm_copied(lapack_error)) : result);
  495. }
  496. static list
  497. dgelsd_caller (operand, fault)
  498. list operand;
  499. int *fault;
  500. /* operand represents a pair (a,b) of a matrix and a vector; a
  501. vector of coefficients for the least squares fit is returned,
  502. but it could be empty due to failure of convergence */
  503. {
  504. int m;
  505. int n;
  506. int nrhs;
  507. double *a;
  508. int lda;
  509. double *b;
  510. int ldb;
  511. double *s;
  512. double rcond;
  513. int rank;
  514. double *work;
  515. int lwork;
  516. int *iwork;
  517. int info;
  518. list result;
  519. int opt_lwork;
  520. double *req_b;
  521. int ispec;
  522. char *name = "DGELSD";
  523. char *opts = "";
  524. int smlsiz;
  525. int nlvl;
  526. if (*fault)
  527. return NULL;
  528. result = NULL;
  529. if (*fault = !(operand ? (operand->head ? (avm_length(operand->head) == avm_length(operand->tail)) : 0) : 0))
  530. return avm_copied (bad_lapack_spec);
  531. m = (int) avm_length(operand->head);
  532. n = (int) avm_length(operand->head->head);
  533. nrhs = 1;
  534. a = (double *) avm_matrix_of_list(0,0,0,1,operand->head,sizeof(double),&result,fault);
  535. lda = m;
  536. b = (*fault ? NULL : (double *) avm_vector_of_list(operand->tail,sizeof(double),&result,fault));
  537. if (*fault ? 0 : (n > m))
  538. if (!(*fault = !(req_b = (double *) realloc((void *) b,sizeof(double) * n))))
  539. b = req_b;
  540. ldb = MAX(n,m);
  541. s = (double *) malloc(sizeof(double) * MIN(m,n));
  542. rcond = -1.0;
  543. ispec = 9;
  544. smlsiz = ilaenv_(&ispec,name,opts,&n,&m,&nrhs,&lda);
  545. ispec = MIN(m,n) / ((smlsiz = MAX(smlsiz,25)) + 1);
  546. nlvl = 0;
  547. while (ispec)
  548. {
  549. ispec = ispec >> 1;
  550. nlvl++;
  551. }
  552. work = (double *) malloc(sizeof(double));
  553. lwork = (12 * MIN(m,n)) + (2 * MIN(m,n) * smlsiz) + (8 * MIN(m,n) * nlvl) + (MIN(m,n) * nrhs) + ((smlsiz+1) * (smlsiz+1));
  554. iwork = (int *) malloc(sizeof(int) * (3 * MIN(m,n) * nlvl + 11 * MIN(m,n)));
  555. if (!(*fault = (*fault ? 1 : !(a ? (b ? (s ? (work ? !!iwork : 0) : 0) : 0) : 0))))
  556. {
  557. opt_lwork = -1;
  558. dgelsd_(&m,&n,&nrhs,a,&lda,b,&ldb,s,&rcond,&rank,work,&opt_lwork,iwork,&info);
  559. opt_lwork = work[0];
  560. free(work);
  561. if (work = (double *) malloc(sizeof(double) * opt_lwork))
  562. lwork = opt_lwork;
  563. else
  564. *fault = !(work = (double *) malloc(sizeof(double) * lwork));
  565. }
  566. if (!*fault)
  567. {
  568. dgelsd_(&m,&n,&nrhs,a,&lda,b,&ldb,s,&rcond,&rank,work,&lwork,iwork,&info);
  569. if ((info < 0) ? (info >= -14) : 0)
  570. avm_internal_error (80);
  571. if (*fault = (info < 0))
  572. result = (result ? result : avm_copied (lapack_error));
  573. }
  574. if (a)
  575. free (a);
  576. if (s)
  577. free (s);
  578. if (work)
  579. free (work);
  580. if (iwork)
  581. free (iwork);
  582. if (*fault ? 0 : (info == 0))
  583. result = avm_list_of_vector((void *) b,n,sizeof(double),fault);
  584. if (b)
  585. free (b);
  586. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  587. }
  588. static list
  589. zgelsd_caller (operand, fault)
  590. list operand;
  591. int *fault;
  592. /* same as above for complex numbers */
  593. {
  594. int m;
  595. int n;
  596. int nrhs;
  597. complex *a;
  598. int lda;
  599. complex *b;
  600. int ldb;
  601. double *s;
  602. double rcond;
  603. int rank;
  604. complex *work;
  605. int lwork;
  606. double *rwork;
  607. int *iwork;
  608. int info;
  609. list result;
  610. int opt_lwork;
  611. complex *req_b;
  612. int ispec;
  613. char *name = "ZGELSD";
  614. char *opts = "";
  615. int smlsiz;
  616. int nlvl;
  617. if (*fault)
  618. return NULL;
  619. if (*fault = !(operand ? (operand->head ? (avm_length(operand->head) == avm_length(operand->tail)) : 0) : 0))
  620. return avm_copied (bad_lapack_spec);
  621. result = NULL;
  622. m = (int) avm_length(operand->head);
  623. n = (int) avm_length(operand->head->head);
  624. nrhs = 1;
  625. a = (complex *) avm_matrix_of_list(1,0,0,1,operand->head,sizeof(complex),&result,fault);
  626. lda = n;
  627. b = (*fault ? NULL : (complex *) avm_vector_of_list(operand->tail,sizeof(complex),&result,fault));
  628. if (*fault ? 0 : (n > m))
  629. if (!(*fault = !(req_b = (complex *) realloc((void *) b,sizeof(complex) * n))))
  630. b = req_b;
  631. ldb = 1;
  632. s = (double *) malloc(sizeof(double) * MIN(m,n));
  633. rcond = -1.0;
  634. work = (complex *) malloc(sizeof(complex));
  635. lwork = (2 * MIN(m,n)) + (MIN(m,n) * nrhs);
  636. ispec = 9;
  637. smlsiz = ilaenv_(&ispec,name,opts,&n,&m,&nrhs,&lda);
  638. ispec = MIN(m,n) / ((smlsiz = MAX(smlsiz,25)) + 1);
  639. nlvl = 0;
  640. while (ispec)
  641. {
  642. ispec = ispec >> 1;
  643. nlvl++;
  644. }
  645. if (n < m)
  646. rwork = (double *) malloc(sizeof(double) * ((10*n)+(2*n*smlsiz)+(8*n*nlvl)+(3*smlsiz*nrhs)+((smlsiz+1)*(smlsiz+1))));
  647. else
  648. rwork = (double *) malloc(sizeof(double) * ((10*m)+(2*m*smlsiz)+(8*m*nlvl)+(3*smlsiz*nrhs)+((smlsiz+1)*(smlsiz+1))));
  649. iwork = (int *) malloc(sizeof(int) * ((3 * MIN(m,n) * nlvl) + (11 * MIN(m,n))));
  650. if (!(*fault = (*fault ? 1 : !(a ? (b ? (s ? (work ? (rwork ? !!iwork : 0) : 0) : 0) : 0) : 0))))
  651. {
  652. opt_lwork = -1;
  653. zgelsd_(&m,&n,&nrhs,a,&lda,b,&ldb,s,&rcond,&rank,work,&opt_lwork,rwork,iwork,&info);
  654. opt_lwork = work[0][RE];
  655. free(work);
  656. if (work = (complex *) malloc(sizeof(complex) * opt_lwork))
  657. lwork = opt_lwork;
  658. else
  659. *fault = !(work = (complex *) malloc(sizeof(complex) * lwork));
  660. }
  661. if (!*fault)
  662. {
  663. zgelsd_(&m,&n,&nrhs,a,&lda,b,&ldb,s,&rcond,&rank,work,&lwork,rwork,iwork,&info);
  664. if ((info < 0) ? (info > -15) : 0)
  665. avm_internal_error (91);
  666. else if (info < 0)
  667. result = (result ? result : avm_copied(lapack_error));
  668. }
  669. if (a)
  670. free (a);
  671. if (s)
  672. free (s);
  673. if (work)
  674. free (work);
  675. if (rwork)
  676. free (rwork);
  677. if (iwork)
  678. free (iwork);
  679. if (*fault ? 0 : (info == 0))
  680. result = (result ? result : avm_list_of_vector((void *) b,n,sizeof(complex),fault));
  681. if (b)
  682. free (b);
  683. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  684. }
  685. static list
  686. dspev_caller (operand, fault)
  687. list operand;
  688. int *fault;
  689. /* computes eigenvectors and eigenvalues of a symmetric real
  690. matrix the same as dsyevr_caller but with a slower algorithm
  691. and using less memory and packed arrays */
  692. {
  693. char jobz;
  694. char uplo;
  695. int n;
  696. double *ap;
  697. double *w;
  698. double *z;
  699. int ldz;
  700. double *work;
  701. int info;
  702. list result;
  703. if (*fault)
  704. return NULL;
  705. result = NULL;
  706. jobz = 'V';
  707. uplo = ((operand ? (operand->head ? operand->head->tail : NULL) : NULL) ? 'U' : 'L');
  708. n = (int) avm_length(operand);
  709. ap = (double *) avm_packed_matrix_of_list(uplo == 'U',operand,n,sizeof(double),&result,fault);
  710. w = (double *) malloc(sizeof(double) * n);
  711. ldz = n;
  712. z = (double *) malloc(sizeof(double) * ldz * n);
  713. work = (double *) malloc(sizeof(double) * 3 * n);
  714. if (!(*fault = (*fault ? 1 : !(ap ? (w ? (z ? !!work : 0) : 0) : 0))))
  715. dspev_(&jobz,&uplo,&n,ap,w,z,&ldz,work,&info);
  716. if (*fault ? 0 : ((info < 0) ? (info >= -9) : 0))
  717. avm_internal_error (88);
  718. if (ap)
  719. free (ap);
  720. if (work)
  721. free (work);
  722. result = (*fault ? result : avm_list_of_matrix((void *) z,ldz,n,sizeof(double),fault));
  723. if (z)
  724. free (z);
  725. result = (*fault ? result : avm_recoverable_join(result,avm_list_of_vector((void *) w,n,sizeof(double),fault)));
  726. if (w)
  727. free (w);
  728. *fault = (*fault ? 1 : !result);
  729. return (result ? result : avm_copied (memory_overflow));
  730. }
  731. static list
  732. dsyevr_caller (operand, fault)
  733. list operand;
  734. int *fault;
  735. /* takes a list representing a symmetric real matrix and returns
  736. a list representing a pair (<<e..>..>,<l..>) with one item on
  737. the left for each eigenvector and one item on the right for
  738. each eigenvalue; since the input matrix is symmetric, the
  739. upper or lower triangular portion may be omitted, which would
  740. be indicated by the rows having increasing or decreasing
  741. lengths, respectively; if the whole matrix is given, the
  742. lower triangular part is ignored */
  743. {
  744. char jobz;
  745. char range;
  746. char uplo;
  747. int n;
  748. double *a;
  749. int lda;
  750. double vl;
  751. double vu;
  752. int il;
  753. int iu;
  754. double abstol;
  755. int m;
  756. double *w;
  757. double *z;
  758. int ldz;
  759. int *isuppz;
  760. double *work;
  761. int lwork;
  762. int *iwork;
  763. int liwork;
  764. int info;
  765. list result;
  766. int opt_lwork,opt_liwork;
  767. if (*fault)
  768. return NULL;
  769. result = NULL;
  770. if (*fault = !(operand ? operand->head : NULL))
  771. return avm_copied(bad_lapack_spec);
  772. jobz = 'V';
  773. range = 'A';
  774. uplo = (operand->head->tail ? 'U' : 'L');
  775. lda = n = (int) avm_length(operand);
  776. if (operand->tail ? (avm_length(operand->head) == avm_length(operand->tail->head)) : 1)
  777. a = (double *) avm_matrix_of_list(1,0,0,1,operand,sizeof(double),&result,fault);
  778. else
  779. a = (double *) avm_matrix_of_list(1,uplo == 'U',uplo == 'L',1,operand,sizeof(double),&result,fault);
  780. abstol = -1.0;
  781. m = n;
  782. w = (double *) malloc(sizeof(double) * n);
  783. ldz = n;
  784. z = (double *) malloc(sizeof(double) * ldz * m);
  785. isuppz = (int *) malloc(sizeof(int) * 2 * m);
  786. work = (double *) malloc(sizeof(double));
  787. lwork = 26 * n; /* bigger is better */
  788. iwork = (int *) malloc(sizeof(int));
  789. liwork = 10 * n; /* bigger is better */
  790. if (!(*fault = (*fault ? 1 : !(a ? (w ? (z ? (isuppz ? (work ? !!iwork : 0) : 0) : 0) : 0) : 0))))
  791. {
  792. opt_liwork = opt_lwork = -1;
  793. dsyevr_(&jobz,&range,&uplo,&n,a,&lda,&vl,&vu,&il,&iu,&abstol,&m,w,z,&ldz,isuppz,work,&opt_lwork,iwork,&opt_liwork,
  794. &info);
  795. opt_lwork = work[0];
  796. opt_liwork = iwork[0];
  797. free(work);
  798. free(iwork);
  799. if (work = (double *) malloc(sizeof(double) * opt_lwork))
  800. lwork = opt_lwork;
  801. else
  802. *fault = !(work = (double *) malloc(sizeof(double) * lwork));
  803. if (iwork = (int *) malloc(sizeof(int) * opt_liwork))
  804. liwork = opt_liwork;
  805. else
  806. *fault = (*fault ? 1 : !(iwork = (int *) malloc(sizeof(int) * liwork)));
  807. }
  808. if (!*fault)
  809. {
  810. dsyevr_(&jobz,&range,&uplo,&n,a,&lda,&vl,&vu,&il,&iu,&abstol,&m,w,z,&ldz,isuppz,work,&lwork,iwork,&liwork,&info);
  811. if ((info < 0) ? (info >= -21) : 0)
  812. avm_internal_error (86);
  813. if (*fault = (info != 0))
  814. result = (result ? result : avm_copied (lapack_error));
  815. }
  816. if (a)
  817. free (a);
  818. if (isuppz)
  819. free (isuppz);
  820. if (work)
  821. free (work);
  822. if (iwork)
  823. free (iwork);
  824. result = (*fault ? result : avm_list_of_matrix((void *) z,ldz,m,sizeof(double),fault));
  825. if (z)
  826. free (z);
  827. result = (*fault ? result : avm_recoverable_join(result,avm_list_of_vector((void *) w,n,sizeof(double),fault)));
  828. if (w)
  829. free (w);
  830. *fault = (*fault ? 1 : !result);
  831. if (*fault ? !result : 0)
  832. {
  833. *fault = 0;
  834. result = dspev_caller(operand, fault);
  835. }
  836. return (result ? result : avm_copied (memory_overflow));
  837. }
  838. static list
  839. zhpev_caller (operand, fault)
  840. list operand;
  841. int *fault;
  842. /* complex eigenvectors and real eigenvalues of a complex
  843. Hermitian matrix, as below but with less space and a slower
  844. or less accurate algorithm */
  845. {
  846. char jobz;
  847. char uplo;
  848. int n;
  849. complex *ap;
  850. double *w;
  851. complex *z;
  852. int ldz;
  853. complex *work;
  854. double *rwork;
  855. int info;
  856. list result;
  857. if (*fault)
  858. return NULL;
  859. if (*fault = !(operand ? operand->head : NULL))
  860. return avm_copied(bad_lapack_spec);
  861. result = NULL;
  862. jobz = 'V';
  863. uplo = (operand->head->tail ? 'U' : 'L');
  864. n = (int) avm_length (operand);
  865. ap = (complex *) avm_packed_matrix_of_list(uplo == 'U',operand,n,sizeof(complex),&result,fault);
  866. w = (double *) malloc(sizeof(double) * n);
  867. ldz = ((jobz == 'V') ? n : 1);
  868. z = (complex *) malloc(sizeof(complex) * ldz * n);
  869. work = (complex *) malloc((sizeof(complex) * 2 * n) - 1);
  870. rwork = (double *) malloc((sizeof(double) * 3 * n) - 2);
  871. if (!(*fault = (*fault ? 1 : (ap ? (w ? (z ? (work ? !!rwork : 0) : 0) : 0) : 0))))
  872. zhpev_(&jobz,&uplo,&n,ap,w,z,&ldz,work,rwork,&info);
  873. if (*fault ? 0 : ((info < 0) ? (info >= -10) : 0))
  874. avm_internal_error (94);
  875. if (ap)
  876. free (ap);
  877. if (work)
  878. free (work);
  879. if (rwork)
  880. free (rwork);
  881. result = (*fault ? result : avm_list_of_matrix((void *) z,n,ldz,sizeof(complex),fault));
  882. if (z)
  883. free (z);
  884. result = (*fault ? result : avm_recoverable_join(result,avm_list_of_vector((void *) w,n,sizeof(double),fault)));
  885. if (w)
  886. free (w);
  887. *fault = (*fault ? 1 : !result);
  888. return (result ? result : avm_copied (memory_overflow));
  889. }
  890. static list
  891. zheevr_caller (operand, fault)
  892. list operand;
  893. int *fault;
  894. /* complex eigenvectors and real eigenvalues of a Hermitian
  895. matrix, optionally in upper or lower triangular form */
  896. {
  897. char jobz;
  898. char range;
  899. char uplo;
  900. int n;
  901. complex *a;
  902. int lda;
  903. double vl;
  904. double vu;
  905. int il;
  906. int iu;
  907. double abstol;
  908. int m;
  909. double *w;
  910. complex *z;
  911. int ldz;
  912. int *isuppz;
  913. complex *work;
  914. int lwork;
  915. double *rwork;
  916. int lrwork;
  917. int *iwork;
  918. int liwork;
  919. int info;
  920. list result;
  921. int opt_lwork,opt_lrwork,opt_liwork;
  922. if (*fault)
  923. return NULL;
  924. if (*fault = !(operand ? operand->head : NULL))
  925. return avm_copied(bad_lapack_spec);
  926. result = NULL;
  927. jobz = 'V';
  928. range = 'A';
  929. uplo = (operand->head->tail ? 'U' : 'L');
  930. n = (int) avm_length (operand);
  931. lda = n;
  932. if (operand->tail ? (avm_length(operand->head) == avm_length(operand->tail->head)) : 1)
  933. a = (complex *) avm_matrix_of_list(1,0,0,1,operand,sizeof(complex),&result,fault);
  934. else
  935. a = (complex *) avm_matrix_of_list(1,uplo == 'U',uplo == 'L',1,operand,sizeof(complex),&result,fault);
  936. vl = vu = 0.0;
  937. il = iu = 0;
  938. abstol = -1.0;
  939. m = n;
  940. w = (double *) malloc(sizeof(complex) * m);
  941. ldz = ((jobz == 'V') ? n : 1);
  942. z = (complex *) malloc(sizeof(complex) * m * ldz);
  943. isuppz = (int *) malloc(sizeof(int) * 2 * m);
  944. work = (complex *) malloc(sizeof(complex));
  945. lwork = 2 * n;
  946. rwork = (double *) malloc(sizeof(double));
  947. lrwork = 24 * n;
  948. iwork = (int *) malloc(sizeof(int));
  949. liwork = 10 * n;
  950. if (!(*fault = !(a ? (w ? (z ? (isuppz ? (work ? (rwork ? !!iwork : 0) : 0) : 0) : 0) : 0) : 0)))
  951. {
  952. opt_lwork = opt_lrwork = opt_liwork = -1;
  953. zheevr_(&jobz,&range,&uplo,&n,a,&lda,&vl,&vu,&il,&iu,&abstol,&m,w,z,&ldz,isuppz,work,
  954. &opt_lwork,rwork,&opt_lrwork,iwork,&opt_liwork,&info);
  955. opt_lwork = work[0][RE];
  956. opt_lrwork = rwork[0];
  957. opt_liwork = iwork[0];
  958. free (work);
  959. free(rwork);
  960. free(iwork);
  961. if (work = (complex *) malloc(sizeof(complex) * opt_lwork))
  962. lwork = opt_lwork;
  963. else if (!(work = (complex *) malloc(sizeof(complex) * lwork)))
  964. *fault = 1;
  965. if (rwork = (double *) malloc(sizeof(double) * opt_lrwork))
  966. lrwork = opt_lrwork;
  967. else if (!(rwork = (double *) malloc(sizeof(double) * lrwork)))
  968. *fault = 1;
  969. if (iwork = (int *) malloc(sizeof(int) * opt_liwork))
  970. liwork = opt_liwork;
  971. else if (!(iwork = (int *) malloc(sizeof(int) * liwork)))
  972. *fault = 1;
  973. }
  974. if (!*fault)
  975. {
  976. zheevr_(&jobz,&range,&uplo,&n,a,&lda,&vl,&vu,&il,&iu,&abstol,&m,w,z,&ldz,isuppz,work,
  977. &lwork,rwork,&lrwork,iwork,&liwork,&info);
  978. if ((info < 0) ? (info >= -23) : 0)
  979. avm_internal_error (107);
  980. if (*fault = (info > 0))
  981. result = (result ? result : avm_copied(lapack_error));
  982. }
  983. if (a)
  984. free (a);
  985. if (isuppz)
  986. free (isuppz);
  987. if (work)
  988. free (work);
  989. if (rwork)
  990. free (rwork);
  991. if (iwork)
  992. free (iwork);
  993. result = (*fault ? result : avm_list_of_matrix((void *) z,ldz,m,sizeof(complex),fault));
  994. if (z)
  995. free (z);
  996. result = (*fault ? result : avm_recoverable_join(result,avm_list_of_vector((void *) w,n,sizeof(double),fault)));
  997. if (w)
  998. free (w);
  999. *fault = (*fault ? 1 : !result);
  1000. if (*fault ? !result : 0)
  1001. {
  1002. *fault = 0;
  1003. result = zhpev_caller(operand, fault);
  1004. }
  1005. return (result ? result : avm_copied(memory_overflow));
  1006. }
  1007. static list
  1008. dgeevx_decoder(wr,wi,vr,n,result,fault)
  1009. double *wr;
  1010. double *wi;
  1011. double *vr;
  1012. int n;
  1013. list result;
  1014. int *fault;
  1015. /* gets the eigenvectors and eigenvalues in complex form out of
  1016. the dgeevx parameters wr,wi,vr, and n, and also disposes of
  1017. the parameters; *fault could be true on entry in which case
  1018. the memory will still be freed if necessary but the given
  1019. result or a memory overflow message will be returned */
  1020. {
  1021. complex *wz,*vz;
  1022. list vectors,values;
  1023. int i,j;
  1024. values = NULL;
  1025. wz = (complex *) malloc(sizeof(complex) * n);
  1026. if (!(*fault = (*fault ? 1 : !wz)))
  1027. {
  1028. for (i = 0; i < n; i++)
  1029. {
  1030. wz[i][RE] = wr[i];
  1031. wz[i][IM] = wi[i];
  1032. }
  1033. values = avm_list_of_vector((void *) wz,n,sizeof(complex),fault);
  1034. if (*fault)
  1035. {
  1036. result = values;
  1037. values = NULL;
  1038. }
  1039. }
  1040. if (wz)
  1041. free (wz);
  1042. if (wr)
  1043. free (wr);
  1044. vectors = NULL;
  1045. vz = (complex *) malloc(sizeof(complex) * n * n);
  1046. if (!(*fault = (*fault ? 1 : !vz)))
  1047. {
  1048. i = 0;
  1049. while (i < n)
  1050. if (wi[i] == 0.0)
  1051. {
  1052. for (j = 0; j < n; j++)
  1053. {
  1054. vz[i * n + j][RE] = vr[j * n + i];
  1055. vz[i * n + j][IM] = 0.0;
  1056. }
  1057. i++;
  1058. }
  1059. else
  1060. {
  1061. for (j = 0; j < n; j++)
  1062. {
  1063. vz[i * n + j][RE] = vz[(i + 1) * n + j][RE] = vr[j * n + i];
  1064. vz[i * n + j][IM] = vr[j * n + i + 1];
  1065. vz[(i + 1) * n + j][IM] = -vr[j * n + i + 1];
  1066. }
  1067. i = i + 2;
  1068. }
  1069. vectors = avm_list_of_matrix((void *) vz,n,n,sizeof(complex),fault);
  1070. if (*fault)
  1071. {
  1072. result = vectors;
  1073. vectors = NULL;
  1074. }
  1075. else
  1076. {
  1077. *fault = !(result = avm_recoverable_join(vectors,values));
  1078. values = vectors = NULL;
  1079. }
  1080. }
  1081. if (wi)
  1082. free (wi);
  1083. if (values)
  1084. avm_dispose (values);
  1085. if (vectors)
  1086. avm_dispose (vectors);
  1087. if (vz)
  1088. free (vz);
  1089. if (vr)
  1090. free (vr);
  1091. return (*fault ? (result ? result : avm_copied (memory_overflow)) : result);
  1092. }
  1093. static list
  1094. dgeevx_caller (operand, fault)
  1095. list operand;
  1096. int *fault;
  1097. /* takes a list representing a non-symmetric real square matrix
  1098. and returns the complex right eigenvectors and eigenvalues
  1099. (<<e..>..>,<v..>) */
  1100. {
  1101. char balanc;
  1102. char jobvl;
  1103. char jobvr;
  1104. char sense;
  1105. int n;
  1106. double *a;
  1107. int lda;
  1108. double *wr;
  1109. double *wi;
  1110. double *vl;
  1111. int ldvl;
  1112. double *vr;
  1113. int ldvr;
  1114. int ilo;
  1115. int ihi;
  1116. double *scale;
  1117. double abnrm;
  1118. double *rconde;
  1119. double *rcondv;
  1120. double *work;
  1121. int lwork;
  1122. int *iwork;
  1123. int info;
  1124. list result;
  1125. int opt_lwork;
  1126. result = NULL;
  1127. if (*fault)
  1128. return NULL;
  1129. balanc = 'B';
  1130. jobvl = 'N';
  1131. jobvr = 'V';
  1132. sense = 'N';
  1133. n = (int) avm_length(operand);
  1134. a = (double *) avm_matrix_of_list(1,0,0,1,operand,sizeof(double),&result,fault);
  1135. lda = n;
  1136. wr = (double *) malloc(sizeof(double) * n);
  1137. wi = (double *) malloc(sizeof(double) * n);
  1138. ldvl = ((jobvl == 'V') ? n : 1);
  1139. vl = (double *) malloc(sizeof(double) * ldvl * ((jobvl == 'V') ? n : 1));
  1140. ldvr = ((jobvr == 'V') ? n : 1);
  1141. vr = (double *) malloc(sizeof(double) * ldvr * ((jobvr == 'V') ? n : 1));
  1142. scale = (double *) malloc(sizeof(double) * n);
  1143. rconde = (double *) malloc(sizeof(double) * n);
  1144. rcondv = (double *) malloc(sizeof(double) * n);
  1145. work = (double *) malloc(sizeof(double));
  1146. lwork = (((sense = 'V') ? 1 : (sense = 'B')) ? (n * (n + 6)) : (((jobvl = 'V') ? 1 : (jobvr = 'V')) ? (3 * n) : (2 * n)));
  1147. iwork = (int *) malloc(sizeof(int) * (((sense == 'N') ? 1 : (sense == 'E')) ? 1 : ((2 * n) - 2)));
  1148. if (!*fault)
  1149. *fault = !(a ? (wr ? (wi ? (vl ? (vr ? (scale ? (rconde ? (rcondv ? (work ? !!iwork : 0): 0): 0): 0): 0): 0): 0): 0): 0);
  1150. if (!*fault)
  1151. {
  1152. opt_lwork = -1;
  1153. dgeevx_(&balanc,&jobvl,&jobvr,&sense,&n,a,&lda,wr,wi,vl,&ldvl,vr,&ldvr,&ilo,&ihi,scale,&abnrm,rconde,rcondv,work,
  1154. &opt_lwork,iwork,&info);
  1155. opt_lwork = work[0];
  1156. free(work);
  1157. if (work = (double *) malloc(sizeof(double) * opt_lwork))
  1158. lwork = opt_lwork;
  1159. else
  1160. *fault = !(work = (double *) malloc(sizeof(double) * lwork));
  1161. }
  1162. if (!*fault)
  1163. {
  1164. dgeevx_(&balanc,&jobvl,&jobvr,&sense,&n,a,&lda,wr,wi,vl,&ldvl,vr,&ldvr,&ilo,&ihi,scale,&abnrm,rconde,rcondv,work,
  1165. &lwork,iwork,&info);
  1166. if ((info < 0) ? (info >= -23) : 0)
  1167. avm_internal_error (81);
  1168. if (*fault = (info != 0))
  1169. result = (result ? result : avm_copied (lapack_error));
  1170. }
  1171. if (a)
  1172. free (a);
  1173. if (vl)
  1174. free (vl);
  1175. if (scale)
  1176. free (scale);
  1177. if (rconde)
  1178. free (rconde);
  1179. if (rcondv)
  1180. free (rcondv);
  1181. if (work)
  1182. free (work);
  1183. if (iwork)
  1184. free(iwork);
  1185. return dgeevx_decoder(wr,wi,vr,n,result,fault);
  1186. }
  1187. static list
  1188. zgeevx_caller (operand, fault)
  1189. list operand;
  1190. int *fault;
  1191. /* complex eigenvectors and eigenvalues of a non-symmetric
  1192. complex square matrix; could return nil due to lack of
  1193. convergence, which isn't an exception */
  1194. {
  1195. char balanc;
  1196. char jobvl;
  1197. char jobvr;
  1198. char sense;
  1199. int n;
  1200. complex *a;
  1201. int lda;
  1202. complex *w;
  1203. complex *vl;
  1204. int ldvl;
  1205. complex *vr;
  1206. int ldvr;
  1207. int ilo;
  1208. int ihi;
  1209. double *scale;
  1210. double abnrm;
  1211. double *rconde;
  1212. double *rcondv;
  1213. complex *work;
  1214. int lwork;
  1215. double *rwork;
  1216. int info;
  1217. list result;
  1218. int opt_lwork;
  1219. if (*fault)
  1220. return NULL;
  1221. result = NULL;
  1222. balanc = 'B';
  1223. jobvl = 'N';
  1224. jobvr = 'V';
  1225. sense = 'N';
  1226. n = (int) avm_length(operand);
  1227. a = (complex *) avm_matrix_of_list(1,0,0,1,operand,sizeof(complex),&result,fault);
  1228. lda = n;
  1229. w = (complex *) malloc(sizeof(complex) * n);
  1230. ldvl = ((jobvl == 'V') ? n : 1);
  1231. vl = (complex *) malloc(sizeof(complex) * ldvl * n);
  1232. ldvr = ((jobvr == 'V') ? n : 1);
  1233. vr = (complex *) malloc(sizeof(complex) * ldvr * n);
  1234. scale = (double *) malloc(sizeof(double) * n);
  1235. rconde = (double *) malloc(sizeof(double) * n);
  1236. rcondv = (double *) malloc(sizeof(double) * n);
  1237. work = (complex *) malloc(sizeof(complex));
  1238. lwork = (((sense == 'N') ? 1 : (sense == 'E')) ? (2 * n) : ((n * n) + (2 * n)));
  1239. rwork = (double *) malloc(sizeof(double) * 2 * n);
  1240. if (!*fault)
  1241. *fault = !(a ? (w ? (vl ? (vr ? (scale ? (rconde ? (rcondv ? (work ? !!rwork : 0) : 0) : 0) : 0) : 0) : 0) : 0) : 0);
  1242. if (!*fault)
  1243. {
  1244. opt_lwork = -1;
  1245. zgeevx_(&balanc,&jobvl,&jobvr,&sense,&n,a,&lda,w,vl,&ldvl,vr,&ldvr,&ilo,&ihi,scale,&abnrm,rconde,rcondv,work,
  1246. &opt_lwork,rwork,&info);
  1247. opt_lwork = work[0][RE];
  1248. free(work);
  1249. if (work = (complex *) malloc(sizeof(complex) * opt_lwork))
  1250. lwork = opt_lwork;
  1251. else
  1252. *fault = !(work = (complex *) malloc(sizeof(complex) * lwork));
  1253. }
  1254. if (!*fault)
  1255. {
  1256. zgeevx_(&balanc,&jobvl,&jobvr,&sense,&n,a,&lda,w,vl,&ldvl,vr,&ldvr,&ilo,&ihi,scale,&abnrm,rconde,rcondv,work,
  1257. &lwork,rwork,&info);
  1258. if ((info < 0) ? (info >= -22) : 0)
  1259. avm_internal_error (93);
  1260. else if (*fault = (info < 0))
  1261. result = (result ? result : avm_copied(lapack_error));
  1262. }
  1263. if (a)
  1264. free (a);
  1265. if (vl)
  1266. free (vl);
  1267. if (scale)
  1268. free (scale);
  1269. if (rconde)
  1270. free (rconde);
  1271. if (rcondv)
  1272. free (rcondv);
  1273. if (work)
  1274. free (work);
  1275. if (rwork)
  1276. free (rwork);
  1277. result = ((*fault ? 1 : (info != 0)) ? result : avm_list_of_matrix((void *) vr,n,ldvr,sizeof(complex),fault));
  1278. if (vr)
  1279. free (vr);
  1280. if (*fault ? 0 : (info == 0))
  1281. result = avm_recoverable_join(result,avm_list_of_vector((void *) w,n,sizeof(complex),fault));
  1282. if (w)
  1283. free (w);
  1284. *fault = (*fault ? 1 : ((info == 0) ? !result : 0));
  1285. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  1286. }
  1287. static list
  1288. dpptrf_caller (operand, fault)
  1289. list operand;
  1290. int *fault;
  1291. /* returns either the upper or lower factor of the Cholesky
  1292. decomposition, depending on whether the upper or lower half of
  1293. the matrix is given; if the whole matrix is given the upper
  1294. factor is returned; if the matrix isn't positive definite, nil
  1295. is returned but it's not an exception */
  1296. {
  1297. char uplo;
  1298. int n;
  1299. double *ap;
  1300. int info;
  1301. list result;
  1302. if (*fault)
  1303. return NULL;
  1304. result = NULL;
  1305. uplo = (operand->head->tail ? 'U' : 'L');
  1306. n = (int) avm_length(operand);
  1307. ap = (double *) avm_packed_matrix_of_list(uplo == 'U',operand,n,sizeof(double),&result,fault);
  1308. if (!*fault)
  1309. dpptrf_(&uplo,&n,ap,&info);
  1310. if (*fault ? 0 : info < 0)
  1311. avm_internal_error (87);
  1312. if (*fault ? 0 : (info == 0))
  1313. result = avm_list_of_packed_matrix(uplo == 'U',(void *) ap,n,sizeof(double),fault);
  1314. if (ap)
  1315. free (ap);
  1316. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  1317. }
  1318. static list
  1319. zpptrf_caller (operand, fault)
  1320. list operand;
  1321. int *fault;
  1322. /* same as above but for complex numbers */
  1323. {
  1324. char uplo;
  1325. int n;
  1326. complex *ap;
  1327. int info;
  1328. list result;
  1329. if (*fault)
  1330. return NULL;
  1331. result = NULL;
  1332. uplo = (operand->head->tail ? 'U' : 'L');
  1333. n = (int) avm_length(operand);
  1334. ap = (complex *) avm_packed_matrix_of_list(uplo == 'U',operand,n,sizeof(complex),&result,fault);
  1335. if (!*fault)
  1336. zpptrf_(&uplo,&n,ap,&info);
  1337. if (*fault ? 0 : info < 0)
  1338. avm_internal_error (92);
  1339. if (*fault ? 0 : (info == 0))
  1340. result = avm_list_of_packed_matrix(uplo == 'U',(void *) ap,n,sizeof(complex),fault);
  1341. if (ap)
  1342. free (ap);
  1343. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  1344. }
  1345. static list
  1346. dgglse_caller (operand, fault)
  1347. list operand;
  1348. int *fault;
  1349. /* The operand represents ((A,c),(B,d)) where A and B are
  1350. matrices and c and d are vectors. A and c are of length m and
  1351. B and d are of length p. Both A and B are of width n. The
  1352. result is a vector x of length n to minimize |Ax-c| subject to
  1353. the constraint that Bx=d. */
  1354. {
  1355. int m;
  1356. int n;
  1357. int p;
  1358. double *a;
  1359. int lda;
  1360. double *b;
  1361. int ldb;
  1362. double *c;
  1363. double *d;
  1364. double *x;
  1365. double *work;
  1366. int lwork;
  1367. int info;
  1368. list result,ac,bd;
  1369. int opt_lwork;
  1370. if (*fault)
  1371. return NULL;
  1372. result = NULL;
  1373. if (*fault = !(operand ? ((ac = operand->head) ? ((bd = operand->tail) ? (ac->head ? !!(bd->head) : 0) : 0) : 0) : 0))
  1374. return avm_copied(bad_lapack_spec);
  1375. m = (int) avm_length(ac->head);
  1376. n = (int) avm_length(ac->head->head);
  1377. p = (int) avm_length(bd->head);
  1378. if (*fault = !((p <= n) ? ((n <= m + p) ? (n == (int) avm_length(bd->head->head)) : 0): 0))
  1379. return avm_copied(bad_lapack_spec);
  1380. if (*fault = ((m != (int) avm_length(ac->tail)) ? 1 : (p != (int) avm_length(bd->tail))))
  1381. return avm_copied(bad_lapack_spec);
  1382. a = (double *) avm_matrix_of_list(0,0,0,1,ac->head,sizeof(double),&result,fault);
  1383. lda = m;
  1384. b = (*fault ? NULL : (double *) avm_matrix_of_list(0,0,0,1,bd->head,sizeof(double),&result,fault));
  1385. ldb = p;
  1386. c = (*fault ? NULL : (double *) avm_vector_of_list(ac->tail,sizeof(double),&result,fault));
  1387. d = (*fault ? NULL : (double *) avm_vector_of_list(bd->tail,sizeof(double),&result,fault));
  1388. x = (double *) malloc(sizeof(double) * p);
  1389. work = (double *) malloc(sizeof(double));
  1390. lwork = m + n + p;
  1391. if (!(*fault = (*fault ? 1 : !(a ? (b ? (c ? (d ? (x ? !!work : 0) : 0) : 0) : 0) : 0))))
  1392. {
  1393. opt_lwork = -1;
  1394. dgglse_(&m,&n,&p,a,&lda,b,&ldb,c,d,x,work,&opt_lwork,&info);
  1395. opt_lwork = work[0];
  1396. free (work);
  1397. if (work = (double *) malloc(sizeof(double) * opt_lwork))
  1398. lwork = opt_lwork;
  1399. else
  1400. *fault = !(work = (double *) malloc(sizeof(double) * lwork));
  1401. }
  1402. if (!*fault)
  1403. {
  1404. dgglse_(&m,&n,&p,a,&lda,b,&ldb,c,d,x,work,&lwork,&info);
  1405. if ((info < 0) ? (info >= -13) : 0)
  1406. avm_internal_error (98);
  1407. if (*fault = (info != 0))
  1408. result = (result ? result : avm_copied(lapack_error));
  1409. }
  1410. if (a)
  1411. free (a);
  1412. if (b)
  1413. free (b);
  1414. if (c)
  1415. free (c);
  1416. if (d)
  1417. free (d);
  1418. if (work)
  1419. free (work);
  1420. result = (*fault ? result : avm_list_of_vector((void *) x,n,sizeof(double),fault));
  1421. if (x)
  1422. free (x);
  1423. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  1424. }
  1425. static list
  1426. zgglse_caller (operand, fault)
  1427. list operand;
  1428. int *fault;
  1429. /* same as above for complex numbers */
  1430. {
  1431. int m;
  1432. int n;
  1433. int p;
  1434. complex *a;
  1435. int lda;
  1436. complex *b;
  1437. int ldb;
  1438. complex *c;
  1439. complex *d;
  1440. complex *x;
  1441. complex *work;
  1442. int lwork;
  1443. int info;
  1444. list result,ac,bd;
  1445. int opt_lwork;
  1446. if (*fault)
  1447. return NULL;
  1448. result = NULL;
  1449. if (*fault = !(operand ? ((ac = operand->head) ? ((bd = operand->tail) ? (ac->head ? !!(bd->head) : 0) : 0) : 0) : 0))
  1450. return avm_copied(bad_lapack_spec);
  1451. m = (int) avm_length(ac->head);
  1452. n = (int) avm_length(ac->head->head);
  1453. p = (int) avm_length(bd->head);
  1454. if (*fault = !((p <= n) ? ((n <= m + p) ? (n == (int) avm_length(bd->head->head)) : 0): 0))
  1455. return avm_copied(bad_lapack_spec);
  1456. if (*fault = ((m != (int) avm_length(ac->tail)) ? 1 : (p != (int) avm_length(bd->tail))))
  1457. return avm_copied(bad_lapack_spec);
  1458. a = (complex *) avm_matrix_of_list(0,0,0,1,ac->head,sizeof(complex),&result,fault);
  1459. lda = m;
  1460. b = (*fault ? NULL : (complex *) avm_matrix_of_list(0,0,0,1,bd->head,sizeof(complex),&result,fault));
  1461. ldb = p;
  1462. c = (*fault ? NULL : (complex *) avm_vector_of_list(ac->tail,sizeof(complex),&result,fault));
  1463. d = (*fault ? NULL : (complex *) avm_vector_of_list(bd->tail,sizeof(complex),&result,fault));
  1464. x = (complex *) malloc(sizeof(complex) * p);
  1465. work = (complex *) malloc(sizeof(complex));
  1466. lwork = m + n + p;
  1467. if (!(*fault = (*fault ? 1 : !(a ? (b ? (c ? (d ? (x ? !!work : 0) : 0) : 0) : 0) : 0))))
  1468. {
  1469. opt_lwork = -1;
  1470. zgglse_(&m,&n,&p,a,&lda,b,&ldb,c,d,x,work,&opt_lwork,&info);
  1471. opt_lwork = work[0][RE];
  1472. free (work);
  1473. if (work = (complex *) malloc(sizeof(complex) * opt_lwork))
  1474. lwork = opt_lwork;
  1475. else
  1476. *fault = !(work = (complex *) malloc(sizeof(complex) * lwork));
  1477. }
  1478. if (!*fault)
  1479. {
  1480. zgglse_(&m,&n,&p,a,&lda,b,&ldb,c,d,x,work,&lwork,&info);
  1481. if ((info < 0) ? (info >= -13) : 0)
  1482. avm_internal_error (95);
  1483. if (*fault = (info != 0))
  1484. result = (result ? result : avm_copied(lapack_error));
  1485. }
  1486. if (a)
  1487. free (a);
  1488. if (b)
  1489. free (b);
  1490. if (c)
  1491. free (c);
  1492. if (d)
  1493. free (d);
  1494. if (work)
  1495. free (work);
  1496. result = (*fault ? result : avm_list_of_vector((void *) x,n,sizeof(complex),fault));
  1497. if (x)
  1498. free (x);
  1499. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  1500. }
  1501. static list
  1502. dggglm_caller (operand, fault)
  1503. list operand;
  1504. int *fault;
  1505. /* The operand represents a pair of matrices and a vector
  1506. ((A,B),d). The result is a pair of vectors (x,y) satisfying
  1507. Ax + By = d for which |y| is minimal */
  1508. {
  1509. int n;
  1510. int m;
  1511. int p;
  1512. double *a;
  1513. int lda;
  1514. double *b;
  1515. int ldb;
  1516. double *d;
  1517. double *x;
  1518. double *y;
  1519. double *work;
  1520. int lwork;
  1521. int info;
  1522. list result,ab;
  1523. int opt_lwork;
  1524. if (*fault)
  1525. return NULL;
  1526. result = NULL;
  1527. if (*fault = !(operand ? ((ab = operand->head) ? (ab->head ? !!(ab->tail) : 0) : 0) : 0))
  1528. return avm_copied(bad_lapack_spec);
  1529. n = (int) avm_length(ab->head);
  1530. m = (int) avm_length(ab->head->head);
  1531. p = (int) avm_length(ab->tail->head);
  1532. if (*fault = !(p ? (n ? (m ? ((m <= n) ? ((n <= m+p) ? (n == (int) avm_length(ab->tail)) : 0) : 0) : 0) : 0) : 0))
  1533. return avm_copied(bad_lapack_spec);
  1534. if (*fault = (n != (int) avm_length(operand->tail)))
  1535. return avm_copied(bad_lapack_spec);
  1536. lda = n;
  1537. a = (double *) avm_matrix_of_list(0,0,0,1,ab->head,sizeof(double),&result,fault);
  1538. ldb = n;
  1539. b = (*fault ? NULL : (double *) avm_matrix_of_list(0,0,0,1,ab->tail,sizeof(double),&result,fault));
  1540. d = (*fault ? NULL : (double *) avm_vector_of_list(operand->tail,sizeof(double),&result,fault));
  1541. x = (double *) malloc(sizeof(double) * m);
  1542. y = (double *) malloc(sizeof(double) * p);
  1543. work = (double *) malloc(sizeof(double));
  1544. lwork = n + m + p;
  1545. if (!(*fault = !(a ? (b ? (d ? (x ? (y ? !!work : 0) : 0) : 0) : 0) : 0)))
  1546. {
  1547. opt_lwork = -1;
  1548. dggglm_(&n,&m,&p,a,&lda,b,&ldb,d,x,y,work,&opt_lwork,&info);
  1549. opt_lwork = work[0];
  1550. free(work);
  1551. if (work = (double *) malloc(sizeof(double) * opt_lwork))
  1552. lwork = opt_lwork;
  1553. else
  1554. *fault = !(work = (double *) malloc(sizeof(double) * lwork));
  1555. }
  1556. if (!*fault)
  1557. {
  1558. dggglm_(&n,&m,&p,a,&lda,b,&ldb,d,x,y,work,&lwork,&info);
  1559. if ((info < 0) ? (info >= -13) : 0)
  1560. avm_internal_error (96);
  1561. if (*fault = (info != 0))
  1562. result = (result ? result : avm_copied(lapack_error));
  1563. }
  1564. if (a)
  1565. free (a);
  1566. if (b)
  1567. free (b);
  1568. if (d)
  1569. free (d);
  1570. if (work)
  1571. free (work);
  1572. result = (*fault ? result : avm_list_of_vector((void *) x,m,sizeof(double),fault));
  1573. if (x)
  1574. free (x);
  1575. if (!*fault)
  1576. result = avm_recoverable_join(result,avm_list_of_vector((void *) y,p,sizeof(double),fault));
  1577. if (y)
  1578. free (y);
  1579. *fault = (*fault ? 1 : !result);
  1580. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  1581. }
  1582. static list
  1583. zggglm_caller (operand, fault)
  1584. list operand;
  1585. int *fault;
  1586. /* same as above with complex numbers */
  1587. {
  1588. int n;
  1589. int m;
  1590. int p;
  1591. complex *a;
  1592. int lda;
  1593. complex *b;
  1594. int ldb;
  1595. complex *d;
  1596. complex *x;
  1597. complex *y;
  1598. complex *work;
  1599. int lwork;
  1600. int info;
  1601. list result,ab;
  1602. int opt_lwork;
  1603. if (*fault)
  1604. return NULL;
  1605. result = NULL;
  1606. if (*fault = !(operand ? ((ab = operand->head) ? (ab->head ? !!(ab->tail) : 0) : 0) : 0))
  1607. return avm_copied(bad_lapack_spec);
  1608. n = (int) avm_length(ab->head);
  1609. m = (int) avm_length(ab->head->head);
  1610. p = (int) avm_length(ab->tail->head);
  1611. if (*fault = !(p ? (n ? (m ? ((m <= n) ? ((n <= m+p) ? (n == (int) avm_length(ab->tail)) : 0) : 0) : 0) : 0) : 0))
  1612. return avm_copied(bad_lapack_spec);
  1613. if (*fault = (n != (int) avm_length(operand->tail)))
  1614. return avm_copied(bad_lapack_spec);
  1615. lda = n;
  1616. a = (complex *) avm_matrix_of_list(0,0,0,1,ab->head,sizeof(complex),&result,fault);
  1617. ldb = n;
  1618. b = (*fault ? NULL : (complex *) avm_matrix_of_list(0,0,0,1,ab->tail,sizeof(complex),&result,fault));
  1619. d = (*fault ? NULL : (complex *) avm_vector_of_list(operand->tail,sizeof(complex),&result,fault));
  1620. x = (complex *) malloc(sizeof(complex) * m);
  1621. y = (complex *) malloc(sizeof(complex) * p);
  1622. work = (complex *) malloc(sizeof(complex));
  1623. lwork = n + m + p;
  1624. if (!(*fault = !(a ? (b ? (d ? (x ? (y ? !!work : 0) : 0) : 0) : 0) : 0)))
  1625. {
  1626. opt_lwork = -1;
  1627. zggglm_(&n,&m,&p,a,&lda,b,&ldb,d,x,y,work,&opt_lwork,&info);
  1628. opt_lwork = work[0][RE];
  1629. free(work);
  1630. if (work = (complex *) malloc(sizeof(complex) * opt_lwork))
  1631. lwork = opt_lwork;
  1632. else
  1633. *fault = !(work = (complex *) malloc(sizeof(complex) * lwork));
  1634. }
  1635. if (!*fault)
  1636. {
  1637. zggglm_(&n,&m,&p,a,&lda,b,&ldb,d,x,y,work,&lwork,&info);
  1638. if ((info < 0) ? (info >= -13) : 0)
  1639. avm_internal_error (97);
  1640. if (*fault = (info != 0))
  1641. result = (result ? result : avm_copied(lapack_error));
  1642. }
  1643. if (a)
  1644. free (a);
  1645. if (b)
  1646. free (b);
  1647. if (d)
  1648. free (d);
  1649. if (work)
  1650. free (work);
  1651. result = (*fault ? result : avm_list_of_vector((void *) x,m,sizeof(complex),fault));
  1652. if (x)
  1653. free (x);
  1654. if (!*fault)
  1655. result = avm_recoverable_join(result,avm_list_of_vector((void *) y,p,sizeof(complex),fault));
  1656. if (y)
  1657. free (y);
  1658. *fault = (*fault ? 1 : !result);
  1659. return (*fault ? (result ? result : avm_copied(memory_overflow)) : result);
  1660. }
  1661. static list
  1662. dgeesx_caller (operand, fault)
  1663. list operand;
  1664. int *fault;
  1665. {
  1666. *fault = 1;
  1667. return avm_copied (unrecognized_function_name);
  1668. }
  1669. static list
  1670. zgeesx_caller (operand, fault)
  1671. list operand;
  1672. int *fault;
  1673. {
  1674. *fault = 1;
  1675. return avm_copied (unrecognized_function_name);
  1676. }
  1677. #endif
  1678. list
  1679. avm_have_lapack_call (function_name, fault)
  1680. list function_name;
  1681. int *fault;
  1682. /* this reports the availability of a function */
  1683. {
  1684. #if HAVE_LAPACK
  1685. list membership;
  1686. list comparison;
  1687. list result;
  1688. if (!initialized)
  1689. avm_initialize_lapack ();
  1690. if (*fault)
  1691. return NULL;
  1692. comparison = avm_binary_comparison (function_name, wild, fault);
  1693. if (*fault)
  1694. return comparison;
  1695. if (comparison)
  1696. {
  1697. avm_dispose(comparison);
  1698. return avm_copied(funs);
  1699. }
  1700. if (!(membership = avm_binary_membership (function_name, funs, fault)) ? 1 : *fault)
  1701. return membership;
  1702. avm_dispose(membership);
  1703. return ((*fault = !(result = avm_recoverable_join(avm_copied(function_name),NULL))) ? avm_copied(memory_overflow) : result);
  1704. #endif
  1705. return NULL;
  1706. }
  1707. list
  1708. avm_lapack_call (function_name, argument, fault)
  1709. list function_name;
  1710. list argument;
  1711. int *fault;
  1712. {
  1713. #if HAVE_LAPACK
  1714. list message;
  1715. int function_number;
  1716. if (*fault)
  1717. return NULL;
  1718. if (! initialized)
  1719. avm_initialize_lapack ();
  1720. if (!(function_number = 0xff & (function_name ? function_name->characterization : 0)))
  1721. {
  1722. message = avm_position (function_name, funs, fault);
  1723. if (*fault)
  1724. return (message);
  1725. if (*fault = !message)
  1726. return(avm_copied (unrecognized_function_name));
  1727. function_number = message->characterization;
  1728. function_name->characterization = function_number;
  1729. avm_dispose (message);
  1730. }
  1731. switch (function_number)
  1732. {
  1733. case 1: return dgesvx_caller (argument, fault);
  1734. case 2: return zgesvx_caller (argument, fault);
  1735. case 3: return dgesdd_caller (argument, fault);
  1736. case 4: return zgesdd_caller (argument, fault);
  1737. case 5: return dgelsd_caller (argument, fault);
  1738. case 6: return zgelsd_caller (argument, fault);
  1739. case 7: return dsyevr_caller (argument, fault);
  1740. case 8: return zheevr_caller (argument, fault);
  1741. case 9: return dgeevx_caller (argument, fault);
  1742. case 10: return zgeevx_caller (argument, fault);
  1743. case 11: return dpptrf_caller (argument, fault);
  1744. case 12: return zpptrf_caller (argument, fault);
  1745. case 13: return dspev_caller (argument, fault);
  1746. case 14: return zhpev_caller (argument, fault);
  1747. case 15: return dgglse_caller (argument, fault);
  1748. case 16: return zgglse_caller (argument, fault);
  1749. case 17: return dggglm_caller (argument, fault);
  1750. case 18: return zggglm_caller (argument, fault);
  1751. case 19: return dgeesx_caller (argument, fault);
  1752. case 20: return zgeesx_caller (argument, fault);
  1753. }
  1754. #endif /* HAVE_LAPACK */
  1755. *fault = 1;
  1756. return avm_copied (unrecognized_function_name);
  1757. }
  1758. void
  1759. avm_initialize_lapack ()
  1760. /* This initializes some static data structures. */
  1761. {
  1762. char *funames[] = {
  1763. "dgesvx",
  1764. "zgesvx",
  1765. "dgesdd",
  1766. "zgesdd",
  1767. "dgelsd",
  1768. "zgelsd",
  1769. "dsyevr",
  1770. "zheevr",
  1771. "dgeevx",
  1772. "zgeevx",
  1773. "dpptrf",
  1774. "zpptrf",
  1775. "dspev",
  1776. "zhpev",
  1777. "dgglse",
  1778. "zgglse",
  1779. "dggglm",
  1780. "zggglm",
  1781. "dgeesx",
  1782. "zgeesx",
  1783. NULL}; /* add more function names here up to a total of 255 */
  1784. list back;
  1785. int string_number;
  1786. char S;
  1787. S = 'S';
  1788. if (initialized)
  1789. return;
  1790. initialized = 1;
  1791. avm_initialize_lists ();
  1792. avm_initialize_matcon ();
  1793. avm_initialize_chrcodes ();
  1794. wild = avm_strung("*");
  1795. memory_overflow = avm_join (avm_strung ("memory overflow"), NULL);
  1796. lapack_error = avm_join (avm_strung ("lapack error"), NULL);
  1797. bad_lapack_spec = avm_join (avm_strung ("bad lapack specification"), NULL);
  1798. unrecognized_function_name = avm_join (avm_strung ("unrecognized lapack function name"), NULL);
  1799. #if HAVE_LAPACK
  1800. safemin = dlamch_(&S);
  1801. #endif
  1802. string_number = 0;
  1803. funs = back = NULL;
  1804. while (funames[string_number])
  1805. avm_enqueue (&funs, &back, avm_standard_strung (funames[string_number++]));
  1806. }
  1807. void
  1808. avm_count_lapack ()
  1809. /* This frees some static data structures as an aid to the
  1810. detection of memory leaks. */
  1811. {
  1812. if (!initialized)
  1813. return;
  1814. initialized = 0;
  1815. avm_dispose (funs);
  1816. avm_dispose (wild);
  1817. avm_dispose (lapack_error);
  1818. avm_dispose (bad_lapack_spec);
  1819. avm_dispose (memory_overflow);
  1820. avm_dispose (unrecognized_function_name);
  1821. funs = NULL;
  1822. wild = NULL;
  1823. lapack_error = NULL;
  1824. memory_overflow = NULL;
  1825. unrecognized_function_name = NULL;
  1826. }