Package: lapack3-dev
Version: 3.0.20000531a-6
Severity: normal

Hi, I'm a little hesitant to file this bug report, since lapack is
such a well-tested package.

BACKGROUND:
The lapack function dgesdd_(), used for computing the SVD of a general
matrix, requires an externally supplied workspace.  One way to know
how big this workspace must be is to call dgesdd_() with parameter 12,
LWORK, set to -1.  In this case the usual SVD commputation is not
carried out.  Instead, the optimal workspace size is returned through
parameter 11, WORK.  A correctly sized workspace can then be allocated
and used in subsequent calls to dgesdd_().

PROBLEM:
After upgrading to lapack3-dev, I'm observing that the initial call to
dgesdd_() no longer returns a valid workspace size.  Attempting to use
the returned value results in an error and, apparently, a call to
exit().

System info is at the end of this email.

EXAMPLE:
I've included a code snippet below which exercises the bug.  You can
compile it by saving as dgesddExample.c:

> gcc dgesddExample.c -o dgesddExample -llapack

You can then run it with no arguments, in which case the erronious
return value from dgesdd_() will be corrected:

> ./dgesddExample
Warning: corrected LWORK from 1 to 27.
Both calls to dgesdd() completed successfully.

Or you can run it with an argument, in which case the erronious return
value from dgesdd_() will not be corrected, and the second call to
dgesdd_() will raise an error:

> ./dgesddExample crash
 ** On entry to DGEBRD parameter number 10 had an illegal value

Thanks for your help and hard work,
David

--------------------- Code starts here ---------------------

/**
 * This file exercises a bug in the lapack routine dgesdd(), in which
 * the reported workspace requirement is insufficient.
 */

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>

/**
 * This is a declaration for the LAPACK routine dgesdd(), which
 * computes the singular value decomposition of a matrix using a
 * fast divide & conquer algorithm.
 */
void dgesdd_(char* JOBZ, long int* M, long int* N, double* A,
             long int* LDA, double* S, double* U, long int* LDU,
             double* VT, long int* LDVT, double* WORK, long int* LWORK,
             long int* IWORK, long int* INFO);


/**
 * The main() function here simply computes the SVD of a 4x3 matrix:
 *
 *
 *       |1.0, 5.0.  9.0|
 *   A = |2.0, 6.0, 10.0|
 *       |3.0, 7.0, 11.0|
 *       |4.0, 8.0, 12.0|
 *
 * When called with no arguments, the program checks the LWORK size
 * returned from dgesdd_(), and corrects it.  If an input argument is
 * supplied, then the value of LWORK is not corrected, and the program 
 * crashes.
 */
int main(int argc, char* argv[])
{
  const int A_ROWS = 4;
  const int A_COLUMNS = 3;
  const int A_SIZE = A_ROWS * A_COLUMNS;
  const int MINIMUM_DIMENSION = A_ROWS > A_COLUMNS ? A_COLUMNS : A_ROWS;
  const int MAXIMUM_DIMENSION = A_ROWS > A_COLUMNS ? A_ROWS : A_COLUMNS;

  /* We define a couple of constants to find the minimum acceptable */
  /* size of the WORK array which will be passed to dgesdd()        */
  const int tempVal0 = (MAXIMUM_DIMENSION > 6 * MINIMUM_DIMENSION ?
                        MAXIMUM_DIMENSION : 6 * MINIMUM_DIMENSION);
  const long int minimumLWORK = 3 * MINIMUM_DIMENSION + tempVal0;

  /* Arguments for lapack call. */
  char JOBZ = 'N';         /* Compute no columns of U and no rows of VT. */
  double A[A_SIZE];                      /* We'll have a 4x3 matrix. */
  double S[MINIMUM_DIMENSION];           /* We'll compute 3 singular values. */
  long int IWORK[8 * MINIMUM_DIMENSION]; /* Workspace required by lapack. */
  long int M = A_ROWS;
  long int N = A_COLUMNS;
  long int LDA = M; 
  double U;                /* Since JOBZ == 'N', U is not referenced. */
  long int LDU = 1;
  double VT;               /* Since JOBZ == 'N', VT is not referenced. */
  long int LDVT = 1;
  double* WORK = (double*)malloc(sizeof(double));
  long int LWORK = -1;     /* Request info on optimal workspace size. */
  long int INFO;
  
  /* Initialize the matrix A. */
  int aIndex;
  for(aIndex = 0; aIndex < A_SIZE; ++aIndex) {
    A[aIndex] = aIndex + 1;
  }

  /* Call once to request optimal workspace size. */
  dgesdd_(&JOBZ, &M, &N, A, &LDA, S, &U, &LDU, &VT, &LDVT,
          WORK, &LWORK, IWORK, &INFO);

  /* Check for errors. */
  if(INFO != 0L) {
    fprintf(stderr, "Error: first call to dgesdd_ returns &ld.\n",
            INFO);
    exit(1);
  }
    
  /* Recover optimal workspace size. */
  LWORK = (long int)(WORK[0]);

  /* Sanity check.  Is the returned value of LWORK legal? */
  if(LWORK < minimumLWORK) {
    if(argc == 1) {
      fprintf(stderr, "Warning: changing LWORK from %ld to %ld.\n",
              LWORK, minimumLWORK);
      LWORK = minimumLWORK;
    }
  } else {
    fprintf(stderr,
            "Submitter was mistaken: the returned value for LWORK "
            "is perfectly legal");
  }

  /* Resize workspace. */
  free(WORK);
  WORK = (double*)malloc(LWORK * sizeof(double));
      
  /* Call dgesdd() again to do the SVD. */
  dgesdd_(&JOBZ, &M, &N, A, &LDA, S, &U, &LDU, &VT, &LDVT,
          WORK, &LWORK, IWORK, &INFO);

  /* Check for errors. */
  if(INFO != 0L) {
    fprintf(stderr, "Error: secondd call to dgesdd_ returns &ld.\n",
            INFO);
    exit(3);
  }

  // Phew!  Made it.
  fprintf(stderr, "Both calls to dgesdd() completed successfully.\n");
  exit(0);
}

--------------------- Code ends here ---------------------


-- System Information:
Debian Release: testing/unstable
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.9-1-686-smp
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages lapack3-dev depends on:
ii  g77                      4:3.4.4-5       The GNU Fortran 77 compiler
ii  lapack3                  3.0.20000531a-6 library of linear algebra routines
ii  libc6-dev                2.3.5-6         GNU C Library: Development Librari
ii  refblas3-dev [libblas-3. 1.2-8           Basic Linear Algebra Subroutines 3

lapack3-dev recommends no packages.

-- no debconf information


-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to