SCIP-SDP  4.0.0
lapack_interface.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of SCIPSDP - a solving framework for mixed-integer */
4 /* semidefinite programs based on SCIP. */
5 /* */
6 /* Copyright (C) 2011-2013 Discrete Optimization, TU Darmstadt */
7 /* EDOM, FAU Erlangen-Nürnberg */
8 /* 2014-2021 Discrete Optimization, TU Darmstadt */
9 /* */
10 /* */
11 /* This program is free software; you can redistribute it and/or */
12 /* modify it under the terms of the GNU Lesser General Public License */
13 /* as published by the Free Software Foundation; either version 3 */
14 /* of the License, or (at your option) any later version. */
15 /* */
16 /* This program is distributed in the hope that it will be useful, */
17 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19 /* GNU Lesser General Public License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with this program; if not, write to the Free Software */
23 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.*/
24 /* */
25 /* */
26 /* Based on SCIP - Solving Constraint Integer Programs */
27 /* Copyright (C) 2002-2021 Zuse Institute Berlin */
28 /* SCIP is distributed under the terms of the SCIP Academic Licence, */
29 /* see file COPYING in the SCIP distribution. */
30 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32 
49 /* #define PRINTMATRICES /\* Should all matrices appearing in best rank-1 approximation heuristic be printed? *\/ */
50 
51 #include <assert.h>
52 
53 #include "lapack_interface.h"
54 #include "config.h" /* for F77_FUNC */
55 
56 #include "scip/def.h"
57 #include "scip/pub_message.h" /* for debug and error message */
58 #include "blockmemshell/memory.h"
59 #include "scip/type_retcode.h"
60 
61 /* turn off lint warnings for whole file: */
62 /*lint --e{788,818}*/
63 
64 
65 /* we use 64 bit integers as the base type */
66 typedef long long int LAPACKINTTYPE;
67 
68 
70 #define BMS_CALL(x) do \
71  { \
72  if( NULL == (x) ) \
73  { \
74  SCIPerrorMessage("No memory in function call\n"); \
75  return SCIP_NOMEMORY; \
76  } \
77  } \
78  while( FALSE )
79 
81 #define SCIP_RealTOINT(x) ((LAPACKINTTYPE) (x + 0.5))
82 
83 /*
84  * BLAS/LAPACK Calls
85  */
86 
91 void F77_FUNC(dsyevr, DSYEVR)(char* JOBZ, char* RANGE, char* UPLO,
92  LAPACKINTTYPE* N, SCIP_Real* A, LAPACKINTTYPE* LDA,
93  SCIP_Real* VL, SCIP_Real* VU,
95  SCIP_Real* ABSTOL, LAPACKINTTYPE* M, SCIP_Real* W, SCIP_Real* Z,
96  LAPACKINTTYPE* LDZ, LAPACKINTTYPE* ISUPPZ, SCIP_Real* WORK,
97  LAPACKINTTYPE* LWORK, LAPACKINTTYPE* IWORK, LAPACKINTTYPE* LIWORK,
98  LAPACKINTTYPE* INFO);
99 
101 void F77_FUNC(dsyevx, DSYEVX)(char* JOBZ, char* RANGE, char* UPLO,
102  LAPACKINTTYPE* N, SCIP_Real* A, LAPACKINTTYPE* LDA,
103  SCIP_Real* VL, SCIP_Real* VU,
104  LAPACKINTTYPE* IL, LAPACKINTTYPE* IU,
105  SCIP_Real* ABSTOL, LAPACKINTTYPE* M, SCIP_Real* W, SCIP_Real* Z,
106  LAPACKINTTYPE* LDZ, SCIP_Real* WORK, LAPACKINTTYPE* LWORK, LAPACKINTTYPE* IWORK,
107  LAPACKINTTYPE* IFAIL, LAPACKINTTYPE* INFO);
108 
110 void F77_FUNC(dgemv, DGEMV)(char* TRANS, LAPACKINTTYPE* M,
111  LAPACKINTTYPE* N, SCIP_Real* ALPHA, SCIP_Real* A, LAPACKINTTYPE* LDA,
112  SCIP_Real* X, LAPACKINTTYPE* INCX, SCIP_Real* BETA, SCIP_Real* Y, LAPACKINTTYPE* INCY);
113 
115 void F77_FUNC(dgemm, DGEMM)(char* TRANSA, char* TRANSB, LAPACKINTTYPE* M, LAPACKINTTYPE* N, LAPACKINTTYPE* K, SCIP_Real* ALPHA,
116  SCIP_Real* A, LAPACKINTTYPE* LDA, SCIP_Real* B, LAPACKINTTYPE* LDB, SCIP_Real* BETA, SCIP_Real* C, LAPACKINTTYPE* LDC);
117 
118 /* LAPACK Fortran subroutine DGELSD */
119 void F77_FUNC(dgelsd, DGELSD)(LAPACKINTTYPE* M, LAPACKINTTYPE* N, LAPACKINTTYPE* NRHS,
120  SCIP_Real* A, LAPACKINTTYPE* LDA, SCIP_Real* b, LAPACKINTTYPE* LDB, SCIP_Real* S, SCIP_Real* RCOND, LAPACKINTTYPE* RANK,
121  SCIP_Real* WORK, LAPACKINTTYPE* LWORK, LAPACKINTTYPE* IWORK, LAPACKINTTYPE* INFO);
122 
131 static
132 int convertToInt(
133  long long int num
134  )
135 {
136  long long int work;
137  int checkval = 1;
138 
139  assert(sizeof(work) > sizeof(checkval)); /*lint !e506*/
140 
141  /* if we have a little-endian machine (e.g, x86), the sought value is in the bottom part */
142  if ( *(int8_t*)&checkval != 0 ) /*lint !e774*/
143  {
144  /* if the top part is nonzero, we assume that the number is negative */
145  if ( *((int8_t*)&num + 4) != 0 ) /*lint !e2662*/
146  {
147  work = -num;
148  return -(*((int*)&work));
149  }
150  return *((int*)&num);
151  }
152 
153  /* otherwise we have a big-endian machine (e.g., PowerPC); the sought value is in the top part */
154  assert( *(int8_t*)&checkval == 0 );
155 
156  /* if the bottom part is nonzero, we assume that the number is negative */
157  if ( *(int8_t*)&num != 0 ) /*lint !e774*/
158  {
159  work = -num;
160  return -(*((int*)&work + 4)); /*lint !e2662*/
161  }
162  return *((int*)&num + 4);
163 }
164 
165 
166 /*
167  * Functions
168  */
169 
175  BMS_BUFMEM* bufmem,
176  SCIP_Bool geteigenvectors,
177  int n,
178  SCIP_Real* A,
179  int i,
180  SCIP_Real* eigenvalue,
181  SCIP_Real* eigenvector
182  )
183 {
184  LAPACKINTTYPE* IWORK;
185  LAPACKINTTYPE* ISUPPZ;
186  LAPACKINTTYPE N;
187  LAPACKINTTYPE INFO;
188  LAPACKINTTYPE LDA;
189  LAPACKINTTYPE WISIZE;
190  LAPACKINTTYPE IL;
191  LAPACKINTTYPE IU;
192  LAPACKINTTYPE M;
193  LAPACKINTTYPE LDZ;
194  LAPACKINTTYPE LWORK;
195  LAPACKINTTYPE LIWORK;
196  SCIP_Real* WORK;
197  SCIP_Real* WTMP;
198  SCIP_Real ABSTOL;
199  SCIP_Real WSIZE;
200  SCIP_Real VL;
201  SCIP_Real VU;
202  char JOBZ;
203  char RANGE;
204  char UPLO;
205 
206  assert( bufmem != NULL );
207  assert( n > 0 );
208  assert( n < INT_MAX );
209  assert( A != NULL );
210  assert( 0 < i && i <= n );
211  assert( eigenvalue != NULL );
212  assert( ! geteigenvectors || eigenvector != NULL );
213 
214  N = n;
215  JOBZ = geteigenvectors ? 'V' : 'N';
216  RANGE = 'I';
217  UPLO = 'L';
218  LDA = n;
219  ABSTOL = 0.0; /* we use abstol = 0, since some lapack return an error otherwise */
220  VL = -1e20;
221  VU = 1e20;
222  IL = i;
223  IU = i;
224  M = 1;
225  LDZ = n;
226  INFO = 0LL;
227 
228  /* standard LAPACK workspace query, to get the amount of needed memory */
229  LWORK = -1LL;
230  LIWORK = -1LL;
231 
232  /* this computes the internally needed memory and returns this as (the first entries of [the 1x1 arrays]) WSIZE and WISIZE */
233  F77_FUNC(dsyevr, DSYEVR)( &JOBZ, &RANGE, &UPLO,
234  &N, NULL, &LDA,
235  NULL, NULL,
236  &IL, &IU,
237  &ABSTOL, &M, NULL, NULL,
238  &LDZ, NULL, &WSIZE,
239  &LWORK, &WISIZE, &LIWORK,
240  &INFO);
241 
242  if ( convertToInt(INFO) != 0 )
243  {
244  SCIPerrorMessage("There was an error when calling DSYEVR. INFO = %d.\n", convertToInt(INFO));
245  return SCIP_ERROR;
246  }
247 
248  /* allocate workspace */
249  LWORK = SCIP_RealTOINT(WSIZE);
250  LIWORK = WISIZE;
251 
252  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &WORK, (int) LWORK) );
253  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &IWORK, (int) LIWORK) );
254  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &WTMP, (int) N) );
255  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &ISUPPZ, 2) ); /*lint !e506*/
256 
257  /* call the function */
258  F77_FUNC(dsyevr, DSYEVR)( &JOBZ, &RANGE, &UPLO,
259  &N, A, &LDA,
260  &VL, &VU,
261  &IL, &IU,
262  &ABSTOL, &M, WTMP, eigenvector,
263  &LDZ, ISUPPZ, WORK,
264  &LWORK, IWORK, &LIWORK,
265  &INFO);
266 
267  /* handle output */
268  if ( convertToInt(INFO) == 0 )
269  *eigenvalue = WTMP[0];
270 
271  /* free memory */
272  BMSfreeBufferMemoryArray(bufmem, &ISUPPZ);
273  BMSfreeBufferMemoryArray(bufmem, &WTMP);
274  BMSfreeBufferMemoryArray(bufmem, &IWORK);
275  BMSfreeBufferMemoryArray(bufmem, &WORK);
276 
277  if ( convertToInt(INFO) != 0 )
278  {
279  SCIPerrorMessage("There was an error when calling DSYEVR. INFO = %d.\n", convertToInt(INFO));
280  return SCIP_ERROR;
281  }
282 
283  return SCIP_OKAY;
284 }
285 
288  BMS_BUFMEM* bufmem,
289  SCIP_Bool geteigenvectors,
290  int n,
291  SCIP_Real* A,
292  int i,
293  SCIP_Real* eigenvalue,
294  SCIP_Real* eigenvector
295  )
296 {
297  LAPACKINTTYPE* IWORK;
298  LAPACKINTTYPE* IFAIL;
299  LAPACKINTTYPE N;
300  LAPACKINTTYPE INFO;
301  LAPACKINTTYPE LDA;
302  LAPACKINTTYPE IL;
303  LAPACKINTTYPE IU;
304  LAPACKINTTYPE M;
305  LAPACKINTTYPE LDZ;
306  LAPACKINTTYPE LWORK;
307  SCIP_Real* WORK;
308  SCIP_Real* WTMP;
309  SCIP_Real WSIZE;
310  SCIP_Real ABSTOL;
311  SCIP_Real VL;
312  SCIP_Real VU;
313  char JOBZ;
314  char RANGE;
315  char UPLO;
316 
317  assert( bufmem != NULL );
318  assert( n > 0 );
319  assert( n < INT_MAX );
320  assert( A != NULL );
321  assert( 0 < i && i <= n );
322  assert( eigenvalue != NULL );
323  assert( ! geteigenvectors || eigenvector != NULL );
324 
325  N = n;
326  JOBZ = geteigenvectors ? 'V' : 'N';
327  RANGE = 'I';
328  UPLO = 'L';
329  LDA = n;
330  ABSTOL = 0.0; /* we use abstol = 0, since some lapack return an error otherwise */
331  VL = -1e20;
332  VU = 1e20;
333  IL = i;
334  IU = i;
335  M = 1;
336  LDZ = n;
337  INFO = 0LL;
338 
339  /* standard LAPACK workspace query, to get the amount of needed memory */
340  LWORK = -1LL;
341 
342  /* this computes the internally needed memory and returns this as (the first entries of [the 1x1 arrays]) WSIZE */
343  F77_FUNC(dsyevx, DSYEVX)( &JOBZ, &RANGE, &UPLO,
344  &N, NULL, &LDA,
345  NULL, NULL,
346  &IL, &IU,
347  &ABSTOL, &M, NULL, NULL,
348  &LDZ, &WSIZE, &LWORK, NULL, NULL,
349  &INFO);
350 
351  if ( convertToInt(INFO) != 0 )
352  {
353  SCIPerrorMessage("There was an error when calling DSYEVR. INFO = %d.\n", convertToInt(INFO));
354  return SCIP_ERROR;
355  }
356 
357  /* allocate workspace */
358  LWORK = SCIP_RealTOINT(WSIZE);
359 
360  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &WORK, (int) LWORK) );
361  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &IWORK, (int) 5 * N) );
362  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &WTMP, (int) N) );
363  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &IFAIL, (int) N) ); /*lint !e506*/
364 
365  /* call the function */
366  F77_FUNC(dsyevx, DSYEVX)( &JOBZ, &RANGE, &UPLO,
367  &N, A, &LDA,
368  &VL, &VU,
369  &IL, &IU,
370  &ABSTOL, &M, WTMP, eigenvector,
371  &LDZ, WORK, &LWORK, IWORK, IFAIL,
372  &INFO);
373 
374  /* handle output */
375  if ( convertToInt(INFO) == 0 )
376  *eigenvalue = WTMP[0];
377 
378  /* free memory */
379  BMSfreeBufferMemoryArray(bufmem, &IFAIL);
380  BMSfreeBufferMemoryArray(bufmem, &WTMP);
381  BMSfreeBufferMemoryArray(bufmem, &IWORK);
382  BMSfreeBufferMemoryArray(bufmem, &WORK);
383 
384  if ( convertToInt(INFO) != 0 )
385  {
386  SCIPerrorMessage("There was an error when calling DSYEVX. INFO = %d.\n", convertToInt(INFO));
387  return SCIP_ERROR;
388  }
389 
390  return SCIP_OKAY;
391 }
392 
395  BMS_BUFMEM* bufmem,
396  int n,
397  SCIP_Real* A,
398  SCIP_Real tol,
399  int* neigenvalues,
400  SCIP_Real* eigenvalues,
401  SCIP_Real* eigenvectors
402  )
403 {
404  LAPACKINTTYPE* ISUPPZ;
405  LAPACKINTTYPE* IWORK;
406  LAPACKINTTYPE N;
407  LAPACKINTTYPE INFO;
408  LAPACKINTTYPE LDA;
409  LAPACKINTTYPE LWORK;
410  LAPACKINTTYPE LIWORK;
411  LAPACKINTTYPE M;
412  LAPACKINTTYPE LDZ;
413  LAPACKINTTYPE WISIZE;
414  SCIP_Real* WORK;
415  SCIP_Real ABSTOL;
416  SCIP_Real WSIZE;
417  SCIP_Real VL;
418  SCIP_Real VU;
419  char JOBZ;
420  char RANGE;
421  char UPLO;
422 
423  assert( bufmem != NULL );
424  assert( n > 0 );
425  assert( n < INT_MAX );
426  assert( A != NULL );
427  assert( tol >= 0 );
428  assert( neigenvalues != NULL );
429  assert( eigenvalues != NULL );
430  assert( eigenvectors != NULL );
431 
432  N = n;
433  JOBZ = 'V';
434  RANGE = 'V';
435  UPLO = 'L';
436  LDA = n;
437  ABSTOL = 0.0; /* we use abstol = 0, since some lapack return an error otherwise */
438  LDZ = n;
439  M = -1;
440  INFO = 0LL;
441 
442  /* interval of allowed values */
443  VL = -1e30;
444  VU = -tol;
445 
446  /* standard LAPACK workspace query, to get the amount of needed memory */
447  LWORK = -1LL;
448  LIWORK = -1LL;
449 
450  /* this computes the internally needed memory and returns this as (the first entries of [the 1x1 arrays]) WSIZE and WISIZE */
451  F77_FUNC(dsyevr, DSYEVR)( &JOBZ, &RANGE, &UPLO,
452  &N, NULL, &LDA,
453  &VL, &VU,
454  NULL, NULL,
455  &ABSTOL, &M, NULL, NULL,
456  &LDZ, NULL, &WSIZE,
457  &LWORK, &WISIZE, &LIWORK,
458  &INFO);
459 
460  /* for some reason this code seems to be called with INFO=0 within UG */
461  if ( convertToInt(INFO) != 0 )
462  {
463  SCIPerrorMessage("There was an error when calling DSYEVR. INFO = %d.\n", convertToInt(INFO));
464  return SCIP_ERROR;
465  }
466 
467  /* allocate workspace */
468  LWORK = SCIP_RealTOINT(WSIZE);
469  LIWORK = WISIZE;
470 
471  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &WORK, (int) LWORK) );
472  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &IWORK, (int) LIWORK) );
473  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &ISUPPZ, (int) 2 * N) );
474 
475  /* call the function */
476  F77_FUNC(dsyevr, DSYEVR)( &JOBZ, &RANGE, &UPLO,
477  &N, A, &LDA,
478  &VL, &VU,
479  NULL, NULL,
480  &ABSTOL, &M, eigenvalues, eigenvectors,
481  &LDZ, ISUPPZ, WORK,
482  &LWORK, IWORK, &LIWORK,
483  &INFO);
484 
485  /* free memory */
486  BMSfreeBufferMemoryArray(bufmem, &ISUPPZ);
487  BMSfreeBufferMemoryArray(bufmem, &IWORK);
488  BMSfreeBufferMemoryArray(bufmem, &WORK);
489 
490  if ( convertToInt(INFO) != 0 )
491  {
492  SCIPerrorMessage("There was an error when calling DSYEVR. INFO = %d.\n", convertToInt(INFO));
493  return SCIP_ERROR;
494  }
495 
496  *neigenvalues = convertToInt(M);
497 
498  return SCIP_OKAY;
499 }
500 
501 
504  BMS_BUFMEM* bufmem,
505  int n,
506  SCIP_Real* A,
507  SCIP_Real* eigenvalues,
508  SCIP_Real* eigenvectors
509  )
510 {
511  LAPACKINTTYPE* ISUPPZ;
512  LAPACKINTTYPE* IWORK;
513  LAPACKINTTYPE N;
514  LAPACKINTTYPE INFO;
515  LAPACKINTTYPE LDA;
516  LAPACKINTTYPE LWORK;
517  LAPACKINTTYPE LIWORK;
518  LAPACKINTTYPE M;
519  LAPACKINTTYPE LDZ;
520  LAPACKINTTYPE WISIZE;
521  SCIP_Real* WORK;
522  SCIP_Real ABSTOL;
523  SCIP_Real WSIZE;
524  SCIP_Real VL;
525  SCIP_Real VU;
526  char JOBZ;
527  char RANGE;
528  char UPLO;
529 
530  assert( bufmem != NULL );
531  assert( n > 0 );
532  assert( n < INT_MAX );
533  assert( A != NULL );
534  assert( eigenvalues != NULL );
535  assert( eigenvectors != NULL );
536 
537  N = n;
538  JOBZ = 'V';
539  RANGE = 'A';
540  UPLO = 'L';
541  LDA = n;
542  ABSTOL = 0.0; /* we use abstol = 0, since some lapack return an error otherwise */
543  M = n;
544  LDZ = n;
545  VL = -1e20;
546  VU = 1e20;
547  INFO = 0LL;
548 
549  /* standard LAPACK workspace query, to get the amount of needed memory */
550  LWORK = -1LL;
551  LIWORK = -1LL;
552 
553  /* this computes the internally needed memory and returns this as (the first entries of [the 1x1 arrays]) WSIZE and WISIZE */
554  F77_FUNC(dsyevr, DSYEVR)( &JOBZ, &RANGE, &UPLO,
555  &N, NULL, &LDA,
556  NULL, NULL,
557  NULL, NULL,
558  &ABSTOL, &M, NULL, NULL,
559  &LDZ, NULL, &WSIZE,
560  &LWORK, &WISIZE, &LIWORK,
561  &INFO);
562 
563  if ( convertToInt(INFO) != 0 )
564  {
565  SCIPerrorMessage("There was an error when calling DSYEVR. INFO = %d.\n", convertToInt(INFO));
566  return SCIP_ERROR;
567  }
568 
569  /* allocate workspace */
570  LWORK = SCIP_RealTOINT(WSIZE);
571  LIWORK = WISIZE;
572 
573  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &WORK, (int) LWORK) );
574  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &IWORK, (int) LIWORK) );
575  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &ISUPPZ, (int) 2 * N) );
576 
577  /* call the function */
578  F77_FUNC(dsyevr, DSYEVR)( &JOBZ, &RANGE, &UPLO,
579  &N, A, &LDA,
580  &VL, &VU,
581  NULL, NULL,
582  &ABSTOL, &M, eigenvalues, eigenvectors,
583  &LDZ, ISUPPZ, WORK,
584  &LWORK, IWORK, &LIWORK,
585  &INFO);
586 
587  /* free memory */
588  BMSfreeBufferMemoryArray(bufmem, &ISUPPZ);
589  BMSfreeBufferMemoryArray(bufmem, &IWORK);
590  BMSfreeBufferMemoryArray(bufmem, &WORK);
591 
592  if ( convertToInt(INFO) != 0 )
593  {
594  SCIPerrorMessage("There was an error when calling DSYEVR. INFO = %d.\n", convertToInt(INFO));
595  return SCIP_ERROR;
596  }
597 
598  return SCIP_OKAY;
599 }
600 
601 
604  int nrows,
605  int ncols,
606  SCIP_Real* matrix,
607  SCIP_Real* vector,
608  SCIP_Real* result
609  )
610 {
611  LAPACKINTTYPE M;
612  LAPACKINTTYPE N;
613  LAPACKINTTYPE LDA;
614  LAPACKINTTYPE INCX;
615  LAPACKINTTYPE INCY;
616  SCIP_Real* A;
617  SCIP_Real* X;
618  SCIP_Real* Y;
619  SCIP_Real BETA;
620  SCIP_Real ALPHA;
621  char TRANS;
622 
623  assert( nrows > 0 );
624  assert( nrows < INT_MAX );
625  assert( ncols > 0 );
626  assert( ncols < INT_MAX );
627  assert( matrix != NULL );
628  assert( vector != NULL );
629  assert( result != NULL );
630 
631  TRANS = 'N';
632  M = nrows;
633  N = ncols;
634  ALPHA = 1.0;
635  A = matrix;
636  LDA = nrows;
637  X = vector;
638  INCX = 1;
639  BETA = 0.0;
640  Y = result;
641  INCY = 1;
642 
643  F77_FUNC(dgemv, DGEMV)(&TRANS, &M, &N, &ALPHA, A, &LDA, X, &INCX, &BETA, Y, &INCY);
644 
645  return SCIP_OKAY;
646 }
647 
648 
651  int nrowsA,
652  int ncolsA,
653  SCIP_Real* matrixA,
654  SCIP_Bool transposeA,
655  int nrowsB,
656  int ncolsB,
657  SCIP_Real* matrixB,
658  SCIP_Bool transposeB,
659  SCIP_Real* result
660  )
661 {
662  LAPACKINTTYPE M;
663  LAPACKINTTYPE N;
664  LAPACKINTTYPE K;
665  LAPACKINTTYPE LDA;
666  LAPACKINTTYPE LDB;
667  LAPACKINTTYPE LDC;
668  SCIP_Real ALPHA;
669  SCIP_Real BETA;
670  char TRANSA;
671  char TRANSB;
672 
673  assert( nrowsA > 0 );
674  assert( nrowsA < INT_MAX );
675  assert( ncolsA > 0 );
676  assert( ncolsA < INT_MAX );
677  assert( nrowsB > 0 );
678  assert( nrowsB < INT_MAX );
679  assert( ncolsB > 0 );
680  assert( ncolsB < INT_MAX );
681  assert( matrixA != NULL );
682  assert( matrixB != NULL );
683  assert( result != NULL );
684 
685  assert( (transposeA && transposeB && (nrowsA == ncolsB)) || (transposeA && !transposeB && (nrowsA == nrowsB))
686  || (!transposeA && transposeB && (ncolsA == ncolsB)) || (!transposeA && !transposeB && (ncolsA == nrowsB)) );
687 
688  TRANSA = transposeA ? 'T' : 'N';
689  TRANSB = transposeB ? 'T' : 'N';
690  M = transposeA ? ncolsA : nrowsA;
691  N = transposeB ? nrowsB : ncolsB;
692  K = transposeA ? nrowsA : ncolsA;
693  ALPHA = 1.0;
694  LDA = transposeA ? K : M;
695  LDB = transposeB ? N : K;
696  BETA = 0.0;
697  LDC = M;
698 
699  F77_FUNC(dgemm, DGEMM)(&TRANSA, &TRANSB, &M, &N, &K, &ALPHA, matrixA, &LDA, matrixB, &LDB, &BETA, result, &LDC);
700 
701  return SCIP_OKAY;
702 }
703 
704 
709  BMS_BUFMEM* bufmem,
710  int m,
711  int n,
712  SCIP_Real* A,
713  SCIP_Real* b,
714  SCIP_Real* x
715  )
716 {
717  LAPACKINTTYPE* IWORK;
718  LAPACKINTTYPE M;
719  LAPACKINTTYPE N;
720  LAPACKINTTYPE NRHS;
721  LAPACKINTTYPE LDA;
722  LAPACKINTTYPE LDB;
723  LAPACKINTTYPE RANK;
724  LAPACKINTTYPE LWORK;
725  LAPACKINTTYPE LIWORK;
726  LAPACKINTTYPE INFO;
727  LAPACKINTTYPE WISIZE;
728  SCIP_Real* WORK;
729  SCIP_Real* S;
730  SCIP_Real RCOND;
731  SCIP_Real WSIZE;
732  int i;
733 
734  assert( bufmem != NULL );
735  assert( m > 0 );
736  assert( m < INT_MAX );
737  assert( n > 0 );
738  assert( n < INT_MAX );
739  assert( A != NULL );
740  assert( b != NULL );
741  assert( x != NULL );
742 
743  M = m;
744  N = n;
745  NRHS = 1;
746  LDA = m;
747  LDB = MAX(M,N);
748  RCOND = 0.0;
749  INFO = 0LL;
750 
751  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &S, MIN(m,n)) );
752 
753  /* standard LAPACK workspace query, to get the amount of needed memory */
754  LWORK = -1LL;
755 
756  /* this computes the internally needed memory and returns this as (the first entry of [the 1x1 array]) WSIZE */
757  F77_FUNC(dgelsd, DGELSD)( &M, &N, &NRHS,
758  NULL, &LDA, NULL, &LDB, NULL,
759  &RCOND, &RANK, &WSIZE, &LWORK,
760  &WISIZE, &INFO);
761 
762  if ( convertToInt(INFO) != 0 )
763  {
764  SCIPerrorMessage("There was an error when calling DGELSD. INFO = %d\n", convertToInt(INFO));
765  return SCIP_ERROR;
766  }
767 
768  /* allocate workspace */
769  LWORK = SCIP_RealTOINT(WSIZE);
770  LIWORK = WISIZE;
771 
772  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &WORK, (int) LWORK) );
773  BMS_CALL( BMSallocBufferMemoryArray(bufmem, &IWORK, (int) LIWORK) );
774 
775  /* call the function */
776  F77_FUNC(dgelsd, DGELSD)( &M, &N, &NRHS,
777  A, &LDA, b, &LDB, S, &RCOND, &RANK,
778  WORK, &LWORK, IWORK, &INFO);
779 
780 #ifdef PRINTMATRICES
781  {
782  SCIP_Real residual = 0.0;
783 
784  printf("LWORK = %d\n", LWORK);
785  printf("LIWORK = %d\n", LIWORK);
786  printf("A has size (%d,%d), is of rank %d\n", M, N, RANK);
787  printf("Minimum l2-norm solution of linear equation system:\n");
788 
789  for (i = 0; i < n; ++i)
790  printf("(%d, %f) ", i, b[i]);
791 
792  for (i = n; i < m; ++i)
793  residual += b[i] * b[i];
794  printf("\n");
795 
796  printf("Residual sum-of-squares for the solution is %f\n", residual);
797  }
798 #endif
799 
800  /* free memory */
801  BMSfreeBufferMemoryArray(bufmem, &IWORK);
802  BMSfreeBufferMemoryArray(bufmem, &WORK);
803  BMSfreeBufferMemoryArray(bufmem, &S);
804 
805  if ( convertToInt(INFO) != 0 )
806  {
807  SCIPerrorMessage("There was an error when calling DGELSD. INFO = %d\n", convertToInt(INFO));
808  return SCIP_ERROR;
809  }
810 
811  /* LAPACK overwrites the right-hand side with the result */
812  for (i = 0; i < n; ++i)
813  x[i] = b[i];
814 
815  return SCIP_OKAY;
816 }
817 
#define SCIP_RealTOINT(x)
SCIP_RETCODE SCIPlapackComputeIthEigenvalueAlternative(BMS_BUFMEM *bufmem, SCIP_Bool geteigenvectors, int n, SCIP_Real *A, int i, SCIP_Real *eigenvalue, SCIP_Real *eigenvector)
Macros for calling Fortran-functions.
#define BMS_CALL(x)
SCIP_RETCODE SCIPlapackMatrixMatrixMult(int nrowsA, int ncolsA, SCIP_Real *matrixA, SCIP_Bool transposeA, int nrowsB, int ncolsB, SCIP_Real *matrixB, SCIP_Bool transposeB, SCIP_Real *result)
long long int LAPACKINTTYPE
SCIP_RETCODE SCIPlapackMatrixVectorMult(int nrows, int ncols, SCIP_Real *matrix, SCIP_Real *vector, SCIP_Real *result)
SCIP_RETCODE SCIPlapackLinearSolve(BMS_BUFMEM *bufmem, int m, int n, SCIP_Real *A, SCIP_Real *b, SCIP_Real *x)
interface methods for eigenvector computation and matrix multiplication using openblas ...
SCIP_RETCODE SCIPlapackComputeEigenvectorsNegative(BMS_BUFMEM *bufmem, int n, SCIP_Real *A, SCIP_Real tol, int *neigenvalues, SCIP_Real *eigenvalues, SCIP_Real *eigenvectors)
#define F77_FUNC(name, NAME)
Definition: config.h:43
SCIP_RETCODE SCIPlapackComputeEigenvectorDecomposition(BMS_BUFMEM *bufmem, int n, SCIP_Real *A, SCIP_Real *eigenvalues, SCIP_Real *eigenvectors)
SCIP_RETCODE SCIPlapackComputeIthEigenvalue(BMS_BUFMEM *bufmem, SCIP_Bool geteigenvectors, int n, SCIP_Real *A, int i, SCIP_Real *eigenvalue, SCIP_Real *eigenvector)