log_value<dcomplex>
TransposeInverseMatrix(const Array2 < complex <doublevar> > & a, 
                       Array2 < complex <doublevar> > & a1, 
                       const int n)
{
  Array2 <complex <doublevar> >  temp(n,n);
  Array1 <int> indx(n);
  doublevar d;

  // a(i,j) first index i is row index (convention)
  // elements of column vectors are stored contiguous in memory in C style arrays
  // a(i) refers to a column vector

  // calculate the inverse of the transposed matrix because this
  // allows to pass a column vector to lubksb() instead of a row

  // put the transposed matrix in temp
  //cout << "temp " << endl;
  for(int i=0;i<n;++i)
  {
    for(int j=0;j<n;++j)
    {
      temp(i,j)=a(i,j);
      a1(i,j)=complex <doublevar> (0.0,0.0);
    }
    a1(i,i)=complex <doublevar> (1.0,0.0);
  }

  //cout << "ludcmp" << endl;
  //if the matrix is singular, the determinant is zero.
  if(ludcmp(temp,n,indx,d)==0) { 
#ifdef SUPERDEBUG
    cout << "log_value<dcomplex>TransposeInverseMatrix:zero determinant " << endl;
#endif
    return dcomplex(0.0,0.0);
  }

  //cout << "lubksb" << endl;

  for(int j=0;j<n;++j)
  {
    // get column vector
    Array1 <complex <doublevar> > yy;//(a1(j));
    yy.refer(a1(j));
    lubksb(temp,n,indx,yy);
  }


  //complex <doublevar> det(d,0);
  log_value<dcomplex> det=dcomplex(d,0);
  for(int j=0;j<n;++j) {
    det *= temp(j,j);
  }
  return det;
}
// Invert matrix a, but do not change a
// Inverse in a1
void InvertMatrix(const Array2 <doublevar> & a, Array2 <doublevar> & a1, const int n)
{
  Array2 <doublevar>& temp(tmp2);
  temp.Resize(n,n);
  Array1 <int>& indx(itmp1);
  indx.Resize(n);
  doublevar d;
  // a(i,j) first index i is row index (convention)
  // elements of column vectors are stored contiguous in memory in C style arrays
  // a(i) refers to a column vector

  // calculate the inverse of the transposed matrix because this
  // allows to pass a column vector to lubksb() instead of a row

  // put the transposed matrix in temp
  for(int i=0;i<n;++i)
  {
    for(int j=0;j<n;++j)
    {
      temp(i,j)=a(j,i);
      a1(i,j)=0.0;
    }
    a1(i,i)=1.0;
  }
  

  if(!ludcmp(temp,n,indx,d)) error("singular matrix in inversion");

  
  
  for(int j=0;j<n;++j)
  {
    // get column vector
    Array1 <doublevar> yy;//(a1(j));
    yy.refer(a1(j));
    lubksb(temp,n,indx,yy);
  }

  
  
}
// Calculate the transpose inverse of matrix a
// and return the determinant
log_real_value TransposeInverseMatrix(const Array2 <doublevar> & a, Array2 <doublevar> & a1, const int n)
{
  Array2 <doublevar> &temp(tmp2);
  temp.Resize(n,n);
  Array1 <int>& indx(itmp1);
  indx.Resize(n);
  doublevar d=1;
 
  log_real_value logdet;
  logdet.logval=0; logdet.sign=1;
  //for(int i=0; i< n; i++) { 
  //  cout << "matrix ";
  //  for(int j=0; j< n; j++) cout << a(i,j) << " ";
  //  cout << endl;
  //}
  
#ifdef USE_LAPACK
  //LAPACK routines don't handle n==1 case??
  if(n==1) { 
    a1(0,0)=1.0/a(0,0);
    logdet.logval=log(fabs(a(0,0)));
    logdet.sign=a(0,0)<0?-1:1;
    return logdet;
  }
  else { 
  
    for(int i=0; i < n;++i) {
      for(int j=0; j< n; ++j) { 
        temp(j,i)=a(i,j);
        a1(i,j)=0.0;
      }
      a1(i,i)=1.0;
    }
    if(dgetrf(n, n, temp.v, n, indx.v)> 0) { 
      return 0.0;
    }
    for(int j=0; j< n; ++j) { 
      dgetrs('N',n,1,temp.v,n,indx.v,a1.v+j*n,n);
    }
  }

  for(int i=0; i< n; i++) { 
    if(indx(i)!=i+1) logdet.sign*=-1;
    logdet.logval+=log(fabs(temp(i,i)));
    if(temp(i,i) <0) logdet.sign*=-1;
  }

  //cout << " det " << det << " logval " << logdet.val() << endl;
  //return det;
  return logdet;
//#endif  
#else 
  
  // a(i,j) first index i is row index (convention)
  // elements of column vectors are stored contiguous in memory in C style arrays
  // a(i) refers to a column vector

  // calculate the inverse of the transposed matrix because this
  // allows to pass a column vector to lubksb() instead of a row

  // put the transposed matrix in temp
  //cout << "temp " << endl;
  for(int i=0;i<n;++i)
  {
    for(int j=0;j<n;++j)
    {
      temp(i,j)=a(i,j);
      a1(i,j)=0.0;
    }
    a1(i,i)=1.0;
  }

  //cout << "ludcmp" << endl;
  //if the matrix is singular, the determinant is zero.
  d=1;
  if(ludcmp(temp,n,indx,d)==0)
    return 0;

  //cout << "lubksb" << endl;

  for(int j=0;j<n;++j)
  {
    // get column vector
    Array1 <doublevar> yy;//(a1(j));
    yy.refer(a1(j));
    lubksb(temp,n,indx,yy);
  }
  
  //for(int j=0;j<n;++j) {
  //  d *= temp(j,j);
  //}

  logdet.logval=0;
  logdet.sign=1;
  for(int i=0; i< n; i++) { 
    if(indx(i)!=i) logdet.sign*=-1;
    logdet.logval+=log(fabs(temp(i,i)));
    if(temp(i,i) <0) logdet.sign*=-1;
  }

  //cout << " det " << d << " logval " << logdet.val() << endl;
  

  return logdet;
#endif
}