function monomial_symmetrize_test ( )

%*****************************************************************************80
%
%% monomial_symmetrize_test() tests monomial_symmetrize().
%
%  Discussion:
%
%    This code implements a gather/scatter operation to symmetrize the coefficients
%    of equivalent monomials in a polynomial.
%
%    In particular, the code will see coefficients for the six equivalent monomials:
%      c123 x1 x2 x3
%      c132 x1 x3 x2
%      c213 x2 x1 x3
%      c231 x2 x3 x1
%      c312 x3 x1 x2
%      c321 x3 x2 x1
%    and compute cave, the average value of c123, c132, c213, c231, c312, c321,
%    and then overwrite the original coefficients by cave.
%
%    This is done separately for every set of equivalent monomials.
%
%    The monomials are assumed to all be of total degree D.
%
%    The number of distince variables x is assumed to be B.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    06 November 2022
%
%  Author:
%
%    John Burkardt
%
%  Local:
%
%    integer d: the vector dimension.
%
%    integer b: vector entries range from 1 to b.
%
  addpath ( '../monomial_symmetrize' )

  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'monomial_symmetrize_test():\n' );
  fprintf ( 1, '  monomial_symmetrize() symmetrizes the coefficients of equivalent\n' );
  fprintf ( 1, '  monomials, all of degree D, in B variables.\n' );
  
  for test = 1 : 2

    if ( test == 1 )
      b = 3;
      d = 3;
    elseif ( test == 2 )
      b = 4;
      d = 3;
    end

    n = b^d;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Test #%d\n', test );
    fprintf ( 1, '    b = %d\n', b );
    fprintf ( 1, '    d = %d\n', d );
    fprintf ( 1, '    n = %d\n', n );
%
%  Create data vector C.
%
    c = demo_data ( d, b );
%
%  Report C.
%
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Original data C:\n' );
    a = [];
    more = false;
    i = 0;
  
    while ( true )

      [ a, more ] = vector_next ( d, b, a, more );

      if ( ~ more )
        break
      end

      i = i + 1;
      fprintf ( 1, '  #%2d  C=%g, [ %d, %d, %d ]\n', i, c(i), a );

    end

    c2 = monomial_symmetrize ( d, b, c );
%
%  Report Symmetrized C.
%
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Symmetric C:\n' );
    a = [];
    more = false;
    i = 0;
  
    while ( true )

      [ a, more ] = vector_next ( d, b, a, more );

      if ( ~ more )
        break
      end

      i = i + 1;
      fprintf ( 1, '  #%2d  C=%g, [ %d, %d, %d ]\n', i, c2(i), a );

    end

  end
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'monomial_symmetrize_test():\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  timestamp ( );

  rmpath ( '../monomial_symmetrize' );

  return
end
function c = demo_data ( d, b )

%*****************************************************************************80
%
%% demo_data() defines a data vector for the gather/scatter demo.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    01 November 2022
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    integer d: the vector dimension.
%
%    integer b: vector entries range from 1 to b.
%
%  Output:
%
%    integer c(b^d): a data value for every unique d-dimensional vector
%    with entries from 1 to b.  Lexicographic order is assumed.
%
  n = b^d;
  c = zeros ( 1, n );
  f = linspace ( 1, d, d );
%
%  Generate each vector A, and compute the corresponding C.
%
  a = [];
  more = false;
  i = 0;
  
  while ( true )

    [ a, more ] = vector_next ( d, b, a, more );

    if ( ~ more )
      break
    end

    i = i + 1;
    c(i) = f * a';

  end

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% timestamp() prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end
function [ a, more ] = vector_next ( d, b, a, more )

%*****************************************************************************80
%
%% vector_next() generates vectors in lexicographic order.
%
%  Discussion:
%
%    The vectors are produced in lexical order, starting with
%    (1,1,...,1),
%    (1,1,...,2),
%    ...
%    (B,B,...,B).
%
%  Example:
%
%    d = 2,
%    b = 3
%
%    1   1
%    1   2
%    1   3
%    2   1
%    2   2
%    2   3
%    3   1
%    3   2
%    3   3
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    31 October 2022
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    integer d: the vector dimension.
%
%    integer b: vector entries range from 1 to b.
%
%    integer A(D): except on the first call, this should
%    be the output value of A on the last call.
%
%    logical MORE: should be FALSE on the first call, and
%    thereafter should be the output value of MORE from the previous call.  
%
%  Output:
%
%    integer A(D): the next vector.
%
%    logical MORE: is TRUE if another vector was computed.
%    If MORE is FALSE on return, then ignore the output value A, and
%    stop calling the routine.
%
  if ( ~ more )

    a(1:d) = 1;
    more = true;

  else
      
    for i = d : -1 : 1

      a(i) = a(i) + 1;

      if ( a(i) <= b )
        return
      end

      a(i) = 1;

    end

    more = false;

  end

  return
end

