#if !defined  HAVE_CATALAN_RGS_TO_NONCROSSING_SETPART_RGS_H__
#define       HAVE_CATALAN_RGS_TO_NONCROSSING_SETPART_RGS_H__
// This file is part of the FXT library.
// Copyright (C) 2015, 2021, 2024 Joerg Arndt
// License: GNU General Public License version 3 or later,
// see the file COPYING.txt in the main directory.

#include "fxtalloca.h"

#include "fxttypes.h"


inline void catalan_rgs_to_noncrossing_setpart_rgs(const ulong *A, ulong n,
                                                   ulong *P)
// Compute the RGS for a noncrossing set partition from the
//   Catalan RGS given in A[].  Result is written to P[].
// Complexity is O(n).
// Example:
//       Catalan RGS    setpart RGS    set partition
//   1:  [ . . . . ]    [ . . . . ]    {1, 2, 3, 4}
//   2:  [ . . . 1 ]    [ . . . 1 ]    {1, 2, 3}, {4}
//   3:  [ . . 1 . ]    [ . . 1 . ]    {1, 2, 4}, {3}
//   4:  [ . . 1 1 ]    [ . . 1 1 ]    {1, 2}, {3, 4}
//   5:  [ . . 1 2 ]    [ . . 1 2 ]    {1, 2}, {3}, {4}
//   6:  [ . 1 . . ]    [ . 1 . . ]    {1, 3, 4}, {2}
//   7:  [ . 1 . 1 ]    [ . 1 . 2 ]    {1, 3}, {2}, {4}  <--= RGS differ
//   8:  [ . 1 1 . ]    [ . 1 1 . ]    {1, 4}, {2, 3}
//   9:  [ . 1 1 1 ]    [ . 1 1 1 ]    {1}, {2, 3, 4}
//  10:  [ . 1 1 2 ]    [ . 1 1 2 ]    {1}, {2, 3}, {4}
//  11:  [ . 1 2 . ]    [ . 1 2 . ]    {1, 4}, {2}, {3}
//  12:  [ . 1 2 1 ]    [ . 1 2 1 ]    {1}, {2, 4}, {3}
//  13:  [ . 1 2 2 ]    [ . 1 2 2 ]    {1}, {2}, {3, 4}
//  14:  [ . 1 2 3 ]    [ . 1 2 3 ]    {1}, {2}, {3}, {4}
// Note that the set partitions can also be read as
//   cycle forms of genus-0 permutations.
{
    if ( n==0 )  return;

    P[0] = 0;

    ALLOCA(ulong, B, n);  // P[x] is the current offset for element x
    // P[j] == z + B[z] where z = A[j] (during processing)
    for (ulong k=0; k<n; ++k)  B[k] = 0;

    ulong d = 0;  // total of down steps so far
    ulong y = 0;  // element before current

    for (ulong j=1; j<n; ++j)
    {
        const ulong z = A[j];  // current element

        // Update from below if needed:
        if ( z != 0 )
        {
            const ulong bz = B[z];
            const ulong b1 = B[z-1];
            if ( b1 > bz )  B[z] = b1;
        }

        P[j] = z + B[z];

        if ( y > z )  // down step
        {
            d += (y-z);

//            Now increase offset for all i > z:
//            for (ulong i=z+1; i<n; ++i)  B[i] = d;
            // better:
            B[z+1] = d;  // later updated upwards
        }

        y = z;
    }
}
// -------------------------


#endif // !defined HAVE_CATALAN_RGS_TO_NONCROSSING_SETPART_RGS_H__
