void test04 ( )

/******************************************************************************/
/*
  Purpose:

    TEST04 works with a CC sparse matrix with many repeated index pairs.

  Discussion:

    To complete this test, I want to compare AST * X and ACC * X.

  Licensing:

    This code is distributed under the GNU LGPL license.

  Modified:

    23 July 2014

  Author:

    John Burkardt
*/
{
  double *acc;
  double *ast;
  double *b1;
  double *b2;
  int *ccc;
  int i_max;
  int i_min;
  int *icc;
  int *ist;
  int j_max;
  int j_min;
  int *jst;
  int m;
  int n;
  int ncc;
  int nst;
  int nx;
  int ny;
  double r;
  int seed;
  double *x;

  printf ( "\n" );
  printf ( "TEST04\n" );
  printf ( "  Convert a sparse matrix from ST to CC format.\n" );
  printf ( "  ST: sparse triplet,    I, J,  A.\n" );
  printf ( "  CC: compressed column, I, CC, A.\n" );
  printf ( "  The ST matrix is the Wathen finite element matrix.\n" );
  printf ( "  It has many repeated index pairs.\n" );
  printf ( "  To check, compare ACC*X - AST*X for a random X.\n" );
/*
  Get the size of the ST matrix.
*/
  nx = 3;
  ny = 3;
  nst = wathen_st_size ( nx, ny );

  printf ( "\n" );
  printf ( "  Number of ST values = %d\n", nst );
/*
  Set the formal matrix size
*/
  m = 3 * nx * ny + 2 * nx + 2 * ny + 1;
  n = m;
/*
  Set a random vector.
*/
  seed = 123456789;
  x = r8vec_uniform_01_new ( n, &seed );
/*
  Allocate space.
*/
  ist = ( int * ) malloc ( nst * sizeof ( int ) );
  jst = ( int * ) malloc ( nst * sizeof ( int ) );
/*
  Create the ST matrix.
*/
  seed = 123456789;
  ast = wathen_st ( nx, ny, nst, &seed, ist, jst );

  i_min = i4vec_min ( nst, ist );
  i_max = i4vec_max ( nst, ist );
  j_min = i4vec_min ( nst, jst );
  j_max = i4vec_max ( nst, jst );

  st_header_print ( i_min, i_max, j_min, j_max, m, n, nst );
/*
  Compute B1 = AST * X
*/
  b1 = st_mv ( m, n, nst, ist, jst, ast, x );
/*
  Get the CC size.
*/
  ncc = st_to_cc_size ( nst, ist, jst );

  printf ( "  Number of CC values = %d\n", ncc );
/*
  Create the CC indices.
*/
  icc = ( int * ) malloc ( ncc * sizeof ( int ) );
  ccc = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) );
  st_to_cc_index ( nst, ist, jst, ncc, n, icc, ccc );
/*
  Create the CC values.
*/
  acc = st_to_cc_values ( nst, ist, jst, ast, ncc, n, icc, ccc );
/*
  Compute B2 = ACC * X.
*/
  b2 = cc_mv ( m, n, ncc, icc, ccc, acc, x );
/*
  Compare B1 and B2.
*/
  r = r8vec_diff_norm ( n, b1, b2 );
  printf ( "  || ACC*X - AST*X|| = %g\n", r );
/*
  Free memory.
*/
  free ( acc );
  free ( ast );
  free ( b1 );
  free ( b2 );
  free ( ccc );
  free ( icc );
  free ( ist );
  free ( jst );
  free ( x );

  return;
}
void test01 ( )

/******************************************************************************/
/*
  Purpose:

    TEST01 tests ST_TO_CC using a tiny matrix.

  Discussion:

    This test uses a trivial matrix whose full representation is:

          2  3  0  0  0
          3  0  4  0  6
      A = 0 -1 -3  2  0
          0  0  1  0  0
          0  4  2  0  1

    A (1-based) ST representation, reading in order by rows is:

      I  J   A
     -- --  --
      1  1   2
      1  2   3

      2  1   3
      2  3   4
      2  5   6

      3  2  -1
      3  3  -3
      3  4   2

      4  3   1

      5  2   4
      5  3   2
      5  5   1

    The CC representation (which goes in order by columns) is

      #   I  JC   A
     --  --  --  --
      1   1   1   2
      2   2       3

      3   1   3   3
      4   3      -1
      5   5       4

      6   2   6   4
      7   3      -3
      8   4       1
      9   5       2

     10   3  10   2

     11   2  11   6
     12   5       1

     13   *  13

  Licensing:

    This code is distributed under the GNU LGPL license.

  Modified:

    23 July 2014

  Author:

    John Burkardt
*/
{
# define NST 12

  double *acc;
  double ast[NST] = {
    2.0,  3.0, 
    3.0,  4.0,  6.0, 
   -1.0, -3.0,  2.0, 
    1.0, 
    4.0,  2.0,  1.0 };
  int *ccc;
  int i_max;
  int i_min;
  int *icc;
  int ist[NST] = {
    1, 1, 
    2, 2, 2, 
    3, 3, 3, 
    4, 
    5, 5, 5 };
  int j_max;
  int j_min;
  int jst[NST] = {
    1, 2, 
    1, 3, 5, 
    2, 3, 4, 
    3, 
    2, 3, 5 };
  int m = 5;
  int n = 5;
  int ncc;
  int nst = NST;

  printf ( "\n" );
  printf ( "TEST01\n" );
  printf ( "  Convert a sparse matrix from ST to CC format.\n" );
  printf ( "  ST: sparse triplet,    I, J,  A.\n" );
  printf ( "  CC: compressed column, I, CC, A.\n" );

  i_min = i4vec_min ( nst, ist );
  i_max = i4vec_max ( nst, ist );
  j_min = i4vec_min ( nst, jst );
  j_max = i4vec_max ( nst, jst );

  st_header_print ( i_min, i_max, j_min, j_max, m, n, nst );
/*
  Decrement the 1-based data.
*/
  i4vec_dec ( nst, ist );
  i4vec_dec ( nst, jst );
/*
  Print the ST matrix.
*/
  st_print ( m, n, nst, ist, jst, ast, "  The matrix in ST format:" );
/*
  Get the CC size.
*/
  ncc = st_to_cc_size ( nst, ist, jst );

  printf ( "\n" );
  printf ( "  Number of CC values = %d\n", ncc );
/*
  Create the CC indices.
*/
  icc = ( int * ) malloc ( ncc * sizeof ( int ) );
  ccc = ( int * ) malloc ( ( n + 1 ) * sizeof ( int ) );

  st_to_cc_index ( nst, ist, jst, ncc, n, icc, ccc );
/*
  Create the CC values.
*/
  acc = st_to_cc_values ( nst, ist, jst, ast, ncc, n, icc, ccc );
/*
  Print the CC matrix.
*/
  cc_print ( m, n, ncc, icc, ccc, acc, "  CC Matrix:" );
/*
  Free memory.
*/
  free ( acc );
  free ( ccc );
  free ( icc );

  return;
# undef NST
}
void perm_inverse ( int n, int p[] )
{
  int base;
  int i;
  int i0;
  int i1;
  int i2;
  int is;
  int p_min;

  if ( n <= 0 )
  {
    std::cout << "\n";
    std::cout << "PERM_INVERSE - Fatal error!\n";
    std::cout << "  Input value of N = " << n << "\n";
    exit ( 1 );
  }
//
//  Find the least value, and shift data so it begins at 1.
//
  p_min = i4vec_min ( n, p );
  base = 1;

  for ( i = 0; i < n; i++ )
  {
    p[i] = p[i] - p_min + base;
  }
//
//  Now we can safely check the permutation.
//
  if ( !perm_check ( n, p, base ) )
  {
    std::cerr << "\n";
    std::cerr << "PERM_INVERSE - Fatal error!\n";
    std::cerr << "  PERM_CHECK rejects this permutation.\n";
    exit ( 1 );
  }
//
//  Now we can invert the permutation.
//
  is = 1;

  for ( i = 1; i <= n; i++ )
  {
    i1 = p[i-1];

    while ( i < i1 )
    {
      i2 = p[i1-1];
      p[i1-1] = -i2;
      i1 = i2;
    }

    is = - i4_sign ( p[i-1] );
    p[i-1] = i4_sign ( is ) * abs ( p[i-1] );
  }

  for ( i = 1; i <= n; i++ )
  {
    i1 = - p[i-1];

    if ( 0 <= i1 )
    {
      i0 = i;

      for ( ; ; )
      {
        i2 = p[i1-1];
        p[i1-1] = i0;

        if ( i2 < 0 )
        {
          break;
        }
        i0 = i1;
        i1 = i2;
      }
    }
  }
//
//  Now we can restore the permutation.
//
  for ( i = 0; i < n; i++ )
  {
    p[i] = p[i] + p_min - base;
  }

  return;
}