/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*             ********   ***                                 SparseLib++    */
/*          *******  **  ***       ***      ***                              */
/*           *****      ***     ******** ********                            */
/*            *****    ***     ******** ********              R. Pozo        */
/*       **  *******  ***   **   ***      ***                 K. Remington   */
/*        ********   ********                                 A. Lumsdaine   */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*                                                                           */
/*                                                                           */
/*                     SparseLib++ : Sparse Matrix Library                   */
/*                                                                           */
/*               National Institute of Standards and Technology              */
/*                        University of Notre Dame                           */
/*              Authors: R. Pozo, K. Remington, A. Lumsdaine                 */
/*                                                                           */
/*                                 NOTICE                                    */
/*                                                                           */
/* Permission to use, copy, modify, and distribute this software and         */
/* its documentation for any purpose and without fee is hereby granted       */
/* provided that the above notice appear in all copies and supporting        */
/* documentation.                                                            */
/*                                                                           */
/* Neither the Institutions (National Institute of Standards and Technology, */
/* University of Notre Dame) nor the Authors make any representations about  */
/* the suitability of this software for any purpose.  This software is       */
/* provided ``as is'' without expressed or implied warranty.                 */
/*                                                                           */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*
 * Home Grown Sparse BLAS
 *
 * These are just a subset of the functions described in SPARKER
 * Working Note #3.
 *
 * Would be great if these could be templated some day
 *
 */

#include <stdlib.h>
#include <iostream>
#include "spblas.h"

#define _SpMatVal(_a, _lda, _row, _col) ( (_a)[(_lda) * (_col) + (_row)])

/*
 * int &m   Number of rows in matrix c
 *
 * int &n   Number of columns in matrix c
 *
 * int &k   Number of rows in matrix b
 *
 * Assume diagonal elements are in proper place
 *
 * unitd = 1    D = I
 * unitd = 2    left (row scaling)
 * unitd = 3    right (column scaling)
 */

static void
CopyRectangularArray_double(int m, int n,
                            const double *b, int ldb, double *c, int ldc)
{
  int i, l;

  if( b == c )
    {
    return;
    }

  if( n == 1 )
    {
    for( i = 0; i < m; i++ )
      {
      c[i] = b[i];
      }
    }
  else
    {
    for( l = 0; l < n; l++ )
      {
      for( i = 0; i < m; i++ )
        {
        _SpMatVal(c, ldc, i, l) = _SpMatVal(b, ldb, i, l);
        }
      }
    }
}

static void
CopyRectangularArray_float(int m, int n,
                           const float *b, int ldb, float *c, int ldc)
{
  int i, l;

  if( b == c )
    {
    return;
    }

  if( n == 1 )
    {
    for( i = 0; i < m; i++ )
      {
      c[i] = b[i];
      }
    }
  else
    {
    for( l = 0; l < n; l++ )
      {
      for( i = 0; i < m; i++ )
        {
        _SpMatVal(c, ldc, i, l) = _SpMatVal(b, ldb, i, l);
        }
      }
    }
}

static void
CompCol_LowerUnitSolve_double(int m, int n, int unitd, const double *dv,
                              double alpha, const double *val, const int *indx, const int *pntr,
                              const double *b, int ldb, double *c, int ldc)
{
  int    i, j, l;
  double z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  CopyRectangularArray_double(m, n, b, ldb, &c[pntr[0] - 1], ldc);

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = c[i + pntr[0]];
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = _SpMatVal(c, ldc, i + pntr[0], l);
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = alpha * c[i + pntr[0]];
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = alpha * _SpMatVal(c, ldc, i + pntr[0], l);
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
}

static void
CompCol_LowerUnitSolve_float(int m, int n, int unitd, const float *dv,
                             float alpha, const float *val, const int *indx, const int *pntr,
                             const float *b, int ldb, float *c, int ldc)
{
  int   i, j, l;
  float z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  CopyRectangularArray_float(m, n, b, ldb, &c[pntr[0] - 1], ldc);

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = c[i + pntr[0]];
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = _SpMatVal(c, ldc, i + pntr[0], l);
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = alpha * c[i + pntr[0]];
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = alpha * _SpMatVal(c, ldc, i + pntr[0], l);
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
}

static void
CompCol_LowerDiagSolve_double(int m, int n, int unitd, const double *dv, double alpha,
                              const double *val, const int *indx, const int *pntr,
                              const double *b, int ldb, double *c, int ldc)
{
  int    i, j, l;
  double z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  CopyRectangularArray_double(m, n, b, ldb, &c[pntr[0] - 1], ldc);

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = c[i + pntr[0]] / val[pntr[i]];
        c[i + pntr[0]] = z;
        for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = _SpMatVal(c, ldc, i + pntr[0], l) / val[pntr[i]];
          _SpMatVal(c, ldc, i + pntr[0], l) = z;
          for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = alpha * c[i + pntr[0]] / val[pntr[i]];
        c[i + pntr[0]] = z;
        for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = alpha * _SpMatVal(c, ldc, i + pntr[0], l) / val[pntr[i]];
          _SpMatVal(c, ldc, i, l) = z;
          for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
}

static void
CompCol_LowerDiagSolve_float(int m, int n, int unitd, const float *dv,
                             float alpha,
                             const float *val, const int *indx, const int *pntr,
                             const float *b, int ldb, float *c, int ldc)
{
  int   i, j, l;
  float z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  CopyRectangularArray_float(m, n, b, ldb, &c[pntr[0] - 1], ldc);

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = c[i + pntr[0]] / val[pntr[i]];
        c[i + pntr[0]] = z;
        for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = _SpMatVal(c, ldc, i + pntr[0], l) / val[pntr[i]];
          _SpMatVal(c, ldc, i + pntr[0], l) = z;
          for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = alpha * c[i + pntr[0]] / val[pntr[i]];
        c[i + pntr[0]] = z;
        for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = alpha * _SpMatVal(c, ldc, i + pntr[0], l) / val[pntr[i]];
          _SpMatVal(c, ldc, i, l) = z;
          for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
}

static void
CompCol_UpperUnitSolve_double(int m, int n, int unitd, const double *dv,
                              double alpha,
                              const double *val, const int *indx, const int *pntr,
                              const double *b, int ldb, double *c, int ldc)
{
  int    i, j, l;
  double z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  CopyRectangularArray_double(m, n, b, ldb, &c[pntr[0] - 1], ldc);

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = c[i + pntr[0]];
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = _SpMatVal(c, ldc, i + pntr[0], l);
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = alpha * c[i + pntr[0]];
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = alpha * _SpMatVal(c, ldc, i + pntr[0], l);
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
}

static void
CompCol_UpperUnitSolve_float(int m, int n, int unitd, const float *dv,
                             float alpha,
                             const float *val, const int *indx, const int *pntr,
                             const float *b, int ldb, float *c, int ldc)
{
  int   i, j, l;
  float z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  CopyRectangularArray_float(m, n, b, ldb, &c[pntr[0] - 1], ldc);

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = c[i + pntr[0]];
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = _SpMatVal(c, ldc, i + pntr[0], l);
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = alpha * c[i + pntr[0]];
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = alpha * _SpMatVal(c, ldc, i + pntr[0], l);
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
}

static void
CompCol_UpperDiagSolve_double(int m, int n, int unitd, const double *dv,
                              double alpha,
                              const double *val, const int *indx, const int *pntr,
                              const double *b, int ldb, double *c, int ldc)
{
  int    i, j, l;
  double z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  CopyRectangularArray_double(m, n, b, ldb, &c[pntr[0] - 1], ldc);

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = c[i + pntr[0]] / val[pntr[i + 1] - 1];
        c[i + pntr[0]] = z;
        for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = _SpMatVal(c, ldc, i + pntr[0], l) / val[pntr[i + 1] - 1];
          _SpMatVal(c, ldc, i + pntr[0], l) = z;
          for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = alpha * c[i + pntr[0]] / val[pntr[i + 1] - 1];
        c[i + pntr[0]] = z;
        for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = alpha * _SpMatVal(c, ldc, i + pntr[0], l) / val[pntr[i + 1] - 1];
          _SpMatVal(c, ldc, i + pntr[0], l) = z;
          for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
}

static void
CompCol_UpperDiagSolve_float(int m, int n, int unitd, const float *dv,
                             float alpha,
                             const float *val, const int *indx, const int *pntr,
                             const float *b, int ldb, float *c, int ldc)
{
  int   i, j, l;
  float z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  CopyRectangularArray_float(m, n, b, ldb, &c[pntr[0] - 1], ldc);

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = c[i + pntr[0]] / val[pntr[i + 1] - 1];
        c[i + pntr[0]] = z;
        for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = _SpMatVal(c, ldc, i + pntr[0], l) / val[pntr[i + 1] - 1];
          _SpMatVal(c, ldc, i + pntr[0], l) = z;
          for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = alpha * c[i + pntr[0]] / val[pntr[i + 1] - 1];
        c[i + pntr[0]] = z;
        for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
          {
          c[indx[j]] -= z * val[j];
          }
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = alpha * _SpMatVal(c, ldc, i + pntr[0], l) / val[pntr[i + 1] - 1];
          _SpMatVal(c, ldc, i + pntr[0], l) = z;
          for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
            {
            _SpMatVal(c, ldc, indx[j], l) -= z * val[j];
            }
          }
        }
      }
    }
}

static void
CompRow_LowerUnitSolve_double(int m, int n, int unitd, const double *dv,
                              double alpha,
                              const double *val, const int *indx, const int *pntr,
                              const double *b, int ldb, double *c, int ldc)
{
  int    i, j, l;
  double z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = b[i] - z;
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) = (_SpMatVal(b, ldb, i, l) - z);
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + 1] = alpha * (b[i] - z);
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) = alpha * (_SpMatVal(b, ldb, i, l) - z);
          }
        }
      }
    }
}

static void
CompRow_LowerUnitSolve_float(int m, int n, int unitd, const float *dv,
                             float alpha,
                             const float *val, const int *indx, const int *pntr,
                             const float *b, int ldb, float *c, int ldc)
{
  int   i, j, l;
  float z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = b[i] - z;
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) = (_SpMatVal(b, ldb, i, l) - z);
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + 1] = alpha * (b[i] - z);
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) = alpha * (_SpMatVal(b, ldb, i, l) - z);
          }
        }
      }
    }
}

static void
CompRow_LowerDiagSolve_double(int m, int n, int unitd, const double *dv,
                              double alpha,
                              const double *val, const int *indx, const int *pntr,
                              const double *b, int ldb, double *c, int ldc)
{
  int    i, j, l;
  double z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = (b[i] - z) / val[pntr[i + 1] - 1];
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) =
            (_SpMatVal(b, ldb, i, l) - z) / val[pntr[i + 1] - 1];
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = alpha * (b[i] - z) / val[pntr[i + 1] - 1];
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) =
            alpha * (_SpMatVal(b, ldb, i, l) - z) / val[pntr[i + 1] - 1];
          }
        }
      }
    }
}

static void
CompRow_LowerDiagSolve_float(int m, int n, int unitd, const float *dv,
                             float alpha,
                             const float *val, const int *indx, const int *pntr,
                             const float *b, int ldb, float *c, int ldc)
{
  int   i, j, l;
  float z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = (b[i] - z) / val[pntr[i + 1] - 1];
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) =
            (_SpMatVal(b, ldb, i, l) - z) / val[pntr[i + 1] - 1];
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = 0; i < m; i++ )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = alpha * (b[i] - z) / val[pntr[i + 1] - 1];
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = 0; i < m; i++ )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1] - 1; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) =
            alpha * (_SpMatVal(b, ldb, i, l) - z) / val[pntr[i + 1] - 1];
          }
        }
      }
    }
}

static void
CompRow_UpperUnitSolve_double(int m, int n, int unitd, const double *dv, double alpha,
                              const double *val, const int *indx, const int *pntr,
                              const double *b, int ldb, double *c, int ldc)

{
  int    i, j, l;
  double z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = b[i] - z;
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) = (_SpMatVal(b, ldb, i, l) - z);
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = alpha * (b[i] - z);
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) = alpha * (_SpMatVal(b, ldb, i, l) - z);
          }
        }
      }
    }
}

static void
CompRow_UpperUnitSolve_float(int m, int n, int unitd, const float *dv, float alpha,
                             const float *val, const int *indx, const int *pntr,
                             const float *b, int ldb, float *c, int ldc)

{
  int   i, j, l;
  float z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = b[i] - z;
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) = (_SpMatVal(b, ldb, i, l) - z);
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = 0;
        for( j = pntr[i]; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = alpha * (b[i] - z);
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = 0;
          for( j = pntr[i]; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) = alpha * (_SpMatVal(b, ldb, i, l) - z);
          }
        }
      }
    }
}

static void
CompRow_UpperDiagSolve_double(int m, int n, int unitd, const double *dv, double alpha,
                              const double *val, const int *indx, const int *pntr,
                              const double *b, int ldb, double *c, int ldc)
{
  int    i, j, l;
  double z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = 0;
        for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = (b[i] - z) / val[pntr[i]];
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = 0;
          for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) =
            (_SpMatVal(b, ldb, i, l) - z) / val[pntr[i]];
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = 0;
        for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = alpha * (b[i] - z) / val[pntr[i]];
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = 0;
          for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) =
            alpha * (_SpMatVal(b, ldb, i, l) - z) / val[pntr[i]];
          }
        }
      }
    }
}

static void
CompRow_UpperDiagSolve_float(int m, int n, int unitd, const float *dv, float alpha,
                             const float *val, const int *indx, const int *pntr,
                             const float *b, int ldb, float *c, int ldc)
{
  int   i, j, l;
  float z;

  // To make the compiler happy
  if( dv )
    {
    ;
    }

  if( unitd != 1 )
    {
    std::cerr << "unitd != 1 not implemented" << "\n";
    exit(1);
    }

  if( alpha == 0.0 )
    {
    return;
    }

  c -= 1;
  val -= pntr[0];
  indx -= pntr[0];

  if( alpha == 1.0 )
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = 0;
        for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = (b[i] - z) / val[pntr[i]];
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = 0;
          for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) =
            (_SpMatVal(b, ldb, i, l) - z) / val[pntr[i]];
          }
        }
      }
    }
  else
    {
    if( n == 1 )
      {
      for( i = m - 1; i >= 0; i-- )
        {
        z = 0;
        for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
          {
          z += c[indx[j]] * val[j];
          }
        c[i + pntr[0]] = alpha * (b[i] - z) / val[pntr[i]];
        }
      }
    else
      {
      for( l = 0; l < n; l++ )
        {
        for( i = m - 1; i >= 0; i-- )
          {
          z = 0;
          for( j = pntr[i] + 1; j < pntr[i + 1]; j++ )
            {
            z += _SpMatVal(c, ldc, indx[j], l) * val[j];
            }
          _SpMatVal(c, ldc, i + pntr[0], l) =
            alpha * (_SpMatVal(b, ldb, i, l) - z) / val[pntr[i]];
          }
        }
      }
    }
}

/*
 * C <- alpha D A^{-1} B + beta C
 * C <- alpha A^{-1} D B + beta C
 */
void F77NAME(scscsm)
  (const int & transa, const int & m, const int & n,
  const int & unitd, const float * dv, const float & alpha,
  const int descra[], const float * val,
  const int * indx, const int * pntr, const float * b, int & ldb,
  const float & beta, float * c, const int & ldc,
  float * work, const int & lwork)
  {
  if( descra[0] != 0 )
    {
    std::cerr << "Must have general matrix" << "\n";
    exit(1);
    }

  if( beta != 0.0 )
    {
    std::cerr << "beta != 0 not implemented" << "\n";
    exit(1);
    }

  // To make the compiler happy
  if( work && lwork )
    {
    ;
    }

  if( transa == 0 )
    {
    if( descra[1] == 1 )
      {
      if( descra[2] == 0 )
        {
        CompCol_LowerDiagSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompCol_LowerUnitSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else if( descra[1] == 2 )
      {
      if( descra[2] == 0 )
        {
        CompCol_UpperDiagSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompCol_UpperUnitSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    }
  else if( transa == 1 || transa == 2 )
    {
    if( descra[1] == 1 )
      {
      if( descra[2] == 0 )
        {
        CompRow_UpperDiagSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompRow_UpperUnitSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else if( descra[1] == 2 )
      {
      if( descra[2] == 0 )
        {
        CompRow_LowerDiagSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompRow_LowerUnitSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else
      {
      std::cerr << "Bad descra[1]" << "\n";
      exit(1);
      }
    }
  else
    {
    std::cerr << "Bad transa" << "\n";
    exit(1);
    }
  }

void F77NAME(scsrsm)
  (const int & transa, const int & m, const int & n,
  const int & unitd, const float * dv, const float & alpha,
  const int descra[], const float * val,
  const int * indx, const int * pntr, const float * b, int & ldb,
  const float & beta, float * c, const int & ldc,
  float * work, const int & lwork)
  {
  if( descra[0] != 0 )
    {
    std::cerr << "Must have general matrix" << "\n";
    exit(1);
    }

  if( beta != 0.0 )
    {
    std::cerr << "beta != 0 not implemented" << "\n";
    exit(1);
    }

  // To make the compiler happy
  if( work && lwork )
    {
    ;
    }

  if( transa == 0 )
    {
    if( descra[1] == 1 )
      {
      if( descra[2] == 0 )
        {
        CompRow_LowerDiagSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompRow_LowerUnitSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else if( descra[1] == 2 )
      {
      if( descra[2] == 0 )
        {
        CompRow_UpperDiagSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompRow_UpperUnitSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    }
  else if( transa == 1 || transa == 2 )
    {
    if( descra[1] == 1 )
      {
      if( descra[2] == 0 )
        {
        CompCol_UpperDiagSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompCol_UpperUnitSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else if( descra[1] == 2 )
      {
      if( descra[2] == 0 )
        {
        CompCol_LowerDiagSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompCol_LowerUnitSolve_float(m, n, unitd, dv, alpha, val, indx, pntr,
                                     b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else
      {
      std::cerr << "Bad descra[1]" << "\n";
      exit(1);
      }
    }
  else
    {
    std::cerr << "Bad transa" << "\n";
    exit(1);
    }
  }

void F77NAME(dcscsm)
  (const int & transa, const int & m, const int & n,
  const int & unitd, const double * dv, const double & alpha,
  const int descra[], const double * val,
  const int * indx, const int * pntr, const double * b, int & ldb,
  const double & beta, double * c, const int & ldc,
  double * work, const int & lwork)
  {
  if( descra[0] != 0 )
    {
    std::cerr << "Must have general matrix" << "\n";
    exit(1);
    }

  if( beta != 0.0 )
    {
    std::cerr << "beta != 0 not implemented" << "\n";
    exit(1);
    }

  // To make the compiler happy
  if( work && lwork )
    {
    ;
    }

  if( transa == 0 )
    {
    if( descra[1] == 1 )
      {
      if( descra[2] == 0 )
        {
        CompCol_LowerDiagSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompCol_LowerUnitSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else if( descra[1] == 2 )
      {
      if( descra[2] == 0 )
        {
        CompCol_UpperDiagSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompCol_UpperUnitSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    }
  else if( transa == 1 || transa == 2 )
    {
    if( descra[1] == 1 )
      {
      if( descra[2] == 0 )
        {
        CompRow_UpperDiagSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompRow_UpperUnitSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else if( descra[1] == 2 )
      {
      if( descra[2] == 0 )
        {
        CompRow_LowerDiagSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompRow_LowerUnitSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else
      {
      std::cerr << "Bad descra[1]" << "\n";
      exit(1);
      }
    }
  else
    {
    std::cerr << "Bad transa" << "\n";
    exit(1);
    }
  }

void F77NAME(dcsrsm)
  (const int & transa, const int & m, const int & n,
  const int & unitd, const double * dv, const double & alpha,
  const int descra[], const double * val,
  const int * indx, const int * pntr, const double * b, int & ldb,
  const double & beta, double * c, const int & ldc,
  double * work, const int & lwork)
  {
  if( descra[0] != 0 )
    {
    std::cerr << "Must have general matrix" << "\n";
    exit(1);
    }

  if( beta != 0.0 )
    {
    std::cerr << "beta != 0 not implemented" << "\n";
    exit(1);
    }

  // To make the compiler happy
  if( work && lwork )
    {
    ;
    }

  if( transa == 0 )
    {
    if( descra[1] == 1 )
      {
      if( descra[2] == 0 )
        {
        CompRow_LowerDiagSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompRow_LowerUnitSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else if( descra[1] == 2 )
      {
      if( descra[2] == 0 )
        {
        CompRow_UpperDiagSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompRow_UpperUnitSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    }
  else if( transa == 1 || transa == 2 )
    {
    if( descra[1] == 1 )
      {
      if( descra[2] == 0 )
        {
        CompCol_UpperDiagSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompCol_UpperUnitSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else if( descra[1] == 2 )
      {
      if( descra[2] == 0 )
        {
        CompCol_LowerDiagSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else if( descra[2] == 1 )
        {
        CompCol_LowerUnitSolve_double(m, n, unitd, dv, alpha, val, indx, pntr,
                                      b, ldb, c, ldc);
        }
      else
        {
        std::cerr << "Bad descra[2]" << "\n";
        exit(1);
        }
      }
    else
      {
      std::cerr << "Bad descra[1]" << "\n";
      exit(1);
      }
    }
  else
    {
    std::cerr << "Bad transa" << "\n";
    exit(1);
    }
  }
