// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

/*

 * NOTE: This file is the modified version of [s,d,c,z]pruneL.c file in SuperLU

 * -- SuperLU routine (version 2.0) --
 * Univ. of California Berkeley, Xerox Palo Alto Research Center,
 * and Lawrence Berkeley National Lab.
 * November 15, 1997
 *
 * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
 *
 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
 * EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
 *
 * Permission is hereby granted to use or copy this program for any
 * purpose, provided the above notices are retained on all copies.
 * Permission to modify the code and to distribute modified code is
 * granted, provided the above notices are retained, and a notice that
 * the code was modified is included with the above copyright notice.
 */
#ifndef SPARSELU_PRUNEL_H
#define SPARSELU_PRUNEL_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {
namespace internal {

/**
 * \brief Prunes the L-structure.
 *
 * It prunes the L-structure  of supernodes whose L-structure contains the current pivot row "pivrow"
 *
 *
 * \param jcol The current column of L
 * \param[in] perm_r Row permutation
 * \param[out] pivrow  The pivot row
 * \param nseg Number of segments
 * \param segrep
 * \param repfnz
 * \param[out] xprune
 * \param glu Global LU data
 *
 */
template <typename Scalar, typename StorageIndex>
void SparseLUImpl<Scalar, StorageIndex>::pruneL(const Index jcol, const IndexVector& perm_r, const Index pivrow,
                                                const Index nseg, const IndexVector& segrep, BlockIndexVector repfnz,
                                                IndexVector& xprune, GlobalLU_t& glu) {
  // For each supernode-rep irep in U(*,j]
  Index jsupno = glu.supno(jcol);
  Index i, irep, irep1;
  bool movnum, do_prune = false;
  Index kmin = 0, kmax = 0, minloc, maxloc, krow;
  for (i = 0; i < nseg; i++) {
    irep = segrep(i);
    irep1 = irep + 1;
    do_prune = false;

    // Don't prune with a zero U-segment
    if (repfnz(irep) == emptyIdxLU) continue;

    // If a snode overlaps with the next panel, then the U-segment
    // is fragmented into two parts -- irep and irep1. We should let
    // pruning occur at the rep-column in irep1s snode.
    if (glu.supno(irep) == glu.supno(irep1)) continue;  // don't prune

    // If it has not been pruned & it has a nonz in row L(pivrow,i)
    if (glu.supno(irep) != jsupno) {
      if (xprune(irep) >= glu.xlsub(irep1)) {
        kmin = glu.xlsub(irep);
        kmax = glu.xlsub(irep1) - 1;
        for (krow = kmin; krow <= kmax; krow++) {
          if (glu.lsub(krow) == pivrow) {
            do_prune = true;
            break;
          }
        }
      }

      if (do_prune) {
        // do a quicksort-type partition
        // movnum=true means that the num values have to be exchanged
        movnum = false;
        if (irep == glu.xsup(glu.supno(irep)))  // Snode of size 1
          movnum = true;

        while (kmin <= kmax) {
          if (perm_r(glu.lsub(kmax)) == emptyIdxLU)
            kmax--;
          else if (perm_r(glu.lsub(kmin)) != emptyIdxLU)
            kmin++;
          else {
            // kmin below pivrow (not yet pivoted), and kmax
            // above pivrow: interchange the two subscripts
            std::swap(glu.lsub(kmin), glu.lsub(kmax));

            // If the supernode has only one column, then we
            // only keep one set of subscripts. For any subscript
            // intercnahge performed, similar interchange must be
            // done on the numerical values.
            if (movnum) {
              minloc = glu.xlusup(irep) + (kmin - glu.xlsub(irep));
              maxloc = glu.xlusup(irep) + (kmax - glu.xlsub(irep));
              std::swap(glu.lusup(minloc), glu.lusup(maxloc));
            }
            kmin++;
            kmax--;
          }
        }  // end while

        xprune(irep) = StorageIndex(kmin);  // Pruning
      }                                     // end if do_prune
    }                                       // end pruning
  }                                         // End for each U-segment
}

}  // end namespace internal
}  // end namespace Eigen

#endif  // SPARSELU_PRUNEL_H
