#**********************************************************************
#**********************************************************************
#*****   ELMCLQ ..... NEW ELIMINATION CLIQUE   ************************
#**********************************************************************
#**********************************************************************
#
#     AUTHORS:
#       ESMOND G. NG, LAWRENCE BERKELEY NATIONAL LABORAOTY
#       BARRY W. PEYTON, DALTON STATE COLLEGE
#
#     LAST UPDATED:
#       2025-09-22
#
#**********************************************************************
#
#     PURPOSE:
#       THIS SUBROUTINE COMPUTES THE NEW ELIMINATION CLIQUE THAT WILL 
#       BE CREATED BY THE ELIMINATION OF ENODE.
#
#       NOTES:
#         THIS ROUTINE ONLY COMPUTES ENODE'S NEW ELIMINATION CLIQUE
#         (IN A WORK VECTOR ECLIQ(*)).  IT DOES NOT PERFORM THE 
#         QUOTIENT GRAPH TRANSFORMATION DUE TO ENODE'S ELIMINATION.
#         THAT TRANSFORMATION IS PERFORMED LATER BY ROUTINE ELMTRA.F.
#
#     INPUT PARAMETERS:
#       ENODE       - NODE TO BE ELIMINATED.
#       NEQNS       - NUMBER OF EQUATIONS.
#       ADJLEN      - LENGTH OF THE ADJACENCY STRUCTURE (ADJNCY(*)).
#                     IDEALLY SHOULD BE AT LEAST NEQNS GREATER THAN
#                     THE INITIAL VALUE STORED IN XADJ(NEQNS+1)-1.
#       XADJ(*)     - ARRAY OF LENGTH NEQNS+1, CONTAINING POINTERS
#                     FOR THE QUOTIENT GRAPH.
#       ADJNCY(*)   - ARRAY OF LENGTH ADJLEN, CONTAINING THE
#                     QUOTIENT GRAPH.
#       NVTXS(*)    - ARRAY OF LENGTH NEQNS.
#                       ACTIVE ELIMINATED:  NUMBER OF VERTICES IN
#                                           THE ELIMINATION CLIQUE.
#                       MERGED ELIMINATED:  -1.
#                       UNELIMINATED:       NUMBER OF UNELIMINATED
#                                           VERTEX NEIGHBORS IN
#                                           CURRENT QUOTIENT GRAPH.
#                       ABSORBED:           -1.
#       WORK(*)     - ARRAY OF LENGTH NEQNS.
#                       ACTIVE ELIMINATED:  >=0, NOT USED AT THIS
#                                           POINT FOR THESE NODES.
#                       UNELIMINATED:       NUMBER OF ELIMINATION
#                                           CLIQUES VERTEX IS
#                                           ADJACENT TO IN THE
#                                           QUOTIENT GRAPH.
#                       ABSORBED:           MAPS ABSORBED VERTEX
#                                           TO MINUS THE ABSORBING
#                                           VERTEX
#                                           (I.E., -ABSORBEE).
#
#     MODIFIED PARAMETERS:
#       QSIZE(*)    - ARRAY OF SIZE NEQNS.
#                       ELIMINATED:   NOT USED AT THIS POINT.
#                       UNELIMINATED AND NOT IN ENODE'S ELIMINATION
#                         CLIQUE:     SUPERNODE SIZE.
#                       UNELIMINATED AND IN ENODE'S ELIMINATION
#                         CLIQUE:     NEGATIVE OF SUPERNODE SIZE.
#                                     CHANGED BACK AT END OF THE
#                                     QUOTIENT GRAPH TRANSFORMATION
#                                     (ELMTRA).
#                       ABSORBED:     0.
#       CHANGED(*)  - ARRAY OF SIZE NEQNS.
#                     ON INPUT, VALUE IS -1 FOR EVERY ACTIVE VERTEX
#                     IN THE QUOTIENT GRAPH.
#                     ASSIGNED THE VALUE 1 IN THIS ROUTINE FOR EVERY
#                     VERTEX IN THE ELIMINATION CLIQUE BECAUSE ITS
#                     DEFICIENCY VALUE POTENTIALLY CHANGES.
#
#     OUTPUT PARAMETERS:
#       CLQSIZ      - ACTUAL SIZE OF THE CLIQUE GENERATED BY
#                     ENODE'S ELIMINATION.
#       FNODE       - POINTER TO FIRST SUPERNODE IN ENODE'S
#                     ELIMINATION CLIQUE MERGED INTO THE CLIQUE
#                     AFTER THE NODES OF QUOTIENT GRAPH NEIGHBOR
#                     C = CSTOP.
#       NNODES      - NUMBER OF SUPERNODES IN ENODE'S ELIMINATION 
#                     CLIQUE.
#       ECLIQ(*)    - ARRAY OF LENGTH NEQNS, CONTAINS ENODE'S  
#                     ELIMINATION CLIQUE.
#
#**********************************************************************
#
function elmclq(
        enode::V,
        neqns::V,
        adjlen::E,
        xadj::AbstractVector{E},
        adjncy::AbstractVector{V},
        nvtxs::AbstractVector{V},
        work::AbstractVector{V},
        qsize::AbstractVector{W},
        changed::AbstractVector{Bool},
        ecliq::AbstractVector{V},
    ) where {V, E, W}
    
    #       -------------------
    #       LOCAL VARIABLES ...
    #       -------------------
    
    #       -----------------------------------------------------------
    #       MARK ENODE SO IT WILL NOT APPEAR IN QUOTIENT GRAPH LISTS
    #       WHEN THE ELIMINATION GRAPH TRANSFORMATION IS COMPUTED LATER
    #       IN THE ELMTRA ROUTINE.
    #       -----------------------------------------------------------
    qsize[enode] = -qsize[enode]
    
    #       ****************************************
    #       FORM NEW ELIMINATION CLIQUE IN ECLIQ(*).
    #       ****************************************
    
    clqsiz = zero(W)
    
    #       ***********************************************
    #       MERGE ELIMINATION CLIQUES CONTAINING ENODE INTO 
    #       ENODE'S ELIMINATION CLIQUE.
    #       ***********************************************
    #       ------------------------------------------------------------
    #       FOR EACH ELIMINATION CLIQUE CNODE TO WHICH ENODE BELONGS ...
    #       ------------------------------------------------------------
    
    cstart = xadj[enode] + convert(E, nvtxs[enode])
    cstop = cstart + convert(E, work[enode]) - one(E)
    ipnt = zero(V)
    fnode = one(V)

    for c in reverse(cstart:cstop)
        cnode = adjncy[c]
        jstart = xadj[cnode]
        jstop = jstart + convert(E, nvtxs[cnode]) - one(E)
        #           ---------------------------------------------
        #           ... FOR EACH VERTEX JNODE IN CLIQUE CNODE ...
        #           ---------------------------------------------
        for j in jstart:jstop
            jnode = adjncy[j]
            #               ------------------------------------------------
            #               ... IF JNODE HAS NOT YET BEEN ADDED TO ENODE'S
            #               ELIMINATION CLIQUE AND HAS NOT BEEN ABSORBED ...
            #               ------------------------------------------------
            if ispositive(qsize[jnode])
                #                   ----------------------------------------
                #                   ADD JNODE TO ENODE'S ELIMINATION CLIQUE.
                #                   ----------------------------------------
                ipnt += one(V)
                ecliq[ipnt] = jnode
                clqsiz += qsize[jnode]
                qsize[jnode] = -qsize[jnode]
                #                   -----------------------------------
                #                   MARK JNODE'S DEFICIENCY AS CHANGED.
                #                   -----------------------------------
                changed[jnode] = true
            end
        end
        #           --------------------------------------------------
        #           RECORD THE LOCATION OF THE FIRST NODE THAT WILL BE
        #           INSERTED INTO ENODE'S ELIMINATION CLIQUE AFTER THE
        #           NODES OF CLIQUE CSTOP HAVE BEEN INTRODUCED.
        #           --------------------------------------------------
        if c == cstop
            fnode = max(fnode, ipnt + one(V))
        end
    end

    #       ******************************************************
    #       PUT VERTEX NEIGHBORS OF ENODE INTO ENODE'S ELIMINATION
    #       CLIQUE.
    #       ******************************************************
    #       ----------------------------------------------
    #       COPY ENODE'S VERTICES INTO ENODE'S NEW CLIQUE.
    #       ----------------------------------------------
    jstart = xadj[enode]
    jstop = jstart + convert(E, nvtxs[enode]) - one(E)
    #       ------------------------------------------------
    #       ... FOR EACH VERTEX JNODE IN THE VERTEX LIST ...
    #       ------------------------------------------------
    for j in jstart:jstop
        jnode = adjncy[j]
        #           --------------------------------------
        #           ... IF JNODE HAS NOT BEEN ABSORBED ...
        #           --------------------------------------
        if !iszero(qsize[jnode])
            #               ----------------------------------------
            #               ADD JNODE TO ENODE'S ELIMINATION CLIQUE.
            #               ----------------------------------------
            ipnt += one(V)
            ecliq[ipnt] = jnode
            clqsiz += qsize[jnode]
            qsize[jnode] = -qsize[jnode]
            #               -----------------------------------
            #               MARK JNODE'S DEFICIENCY AS CHANGED.
            #               -----------------------------------
            changed[jnode] = true
        end
    end
    
    #       ----------------------------------------------------------------
    #       RECORD THE NUMBER OF (SUPER)NODES IN ENODE'S ELIMINATION CLIQUE.
    #       ----------------------------------------------------------------
    nnodes = ipnt
    
    return clqsiz, fnode, nnodes
end
