docs: public void householderSymmetric( int row , double gamma )
      {
          int startU = row*N;
  
          // compute v = -gamma*A*u
          for( int i = row+1; i < N; i++ ) {
              double totalReal = 0;
              double totalImag = 0;
  
              // the lower triangle is not written to so it needs to traverse upwards
              // to get the information.  Reduces the number of matrix writes need
              // improving large matrix performance
              for( int j = row+1; j < i; j++ ) {
                  double realA = QT.data[(j*N+i)*2];
                  double imagA = -QT.data[(j*N+i)*2+1];
  
                  double realU = QT.data[(startU+j)*2];
                  double imagU = QT.data[(startU+j)*2+1];
  
                  totalReal += realA*realU - imagA*imagU;
                  totalImag += realA*imagU + imagA*realU;
              }
              for( int j = i; j < N; j++ ) {
                  double realA = QT.data[(i*N+j)*2];
                  double imagA = QT.data[(i*N+j)*2+1];
  
                  double realU = QT.data[(startU+j)*2];
                  double imagU = QT.data[(startU+j)*2+1];
  
                  totalReal += realA*realU - imagA*imagU;
                  totalImag += realA*imagU + imagA*realU;
              }
              w[i*2]   = -gamma*totalReal;
              w[i*2+1] = -gamma*totalImag;
          }
  
          // alpha = -0.5*gamma*u^T*v
          double realAplha = 0;
          double imageAlpha = 0;
  
          for( int i = row+1; i < N; i++ ) {
              double realU = QT.data[(startU+i)*2];
              double imagU = -QT.data[(startU+i)*2+1];
  
              double realV = w[i*2];
              double imagV = w[i*2+1];
  
              realAplha += realU*realV - imagU*imagV;
              imageAlpha += realU*imagV + imagU*realV;
          }
          realAplha *= -0.5*gamma;
          imageAlpha *= -0.5*gamma;
  
          // w = v + alpha*u
          for( int i = row+1; i < N; i++ ) {
              double realU = QT.data[(startU+i)*2];
              double imagU = QT.data[(startU+i)*2+1];
  
              w[i*2]   += realAplha*realU - imageAlpha*imagU;
              w[i*2+1] += realAplha*imagU + imageAlpha*realU;
          }
  
          // A = A + w*u^T + u*w^T
          for( int i = row+1; i < N; i++ ) {
  
              double realWW = w[i*2];
              double imagWW = w[i*2+1];
  
              double realUU = QT.data[(startU+i)*2];
              double imagUU = QT.data[(startU+i)*2+1];
  
              int indA = (i*N+i)*2;
              for( int j = i; j < N; j++ ) {
                  // only write to the upper portion of the matrix
                  // this reduces the number of cache misses
  
                  double realU = QT.data[(startU+j)*2];
                  double imagU = -QT.data[(startU+j)*2+1];
  
                  double realW = w[j*2];
                  double imagW = -w[j*2+1];
  
                  QT.data[indA++] += realWW*realU - imagWW*imagU + realW*realUU - imagW*imagUU;
                  QT.data[indA++] += realWW*imagU + imagWW*realU + realW*imagUU + imagW*realUU;
              }
          }
      }