/* SparseSet implementation.
   Copyright (C) 2007-2021 Free Software Foundation, Inc.
   Contributed by Peter Bergner <bergner@vnet.ibm.com>

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "sparseset.h"

/* Allocate and clear a n_elms SparseSet.  */

sparseset
sparseset_alloc (SPARSESET_ELT_TYPE n_elms)
{
  unsigned int n_bytes = sizeof (struct sparseset_def)
			 + ((n_elms - 1) * 2 * sizeof (SPARSESET_ELT_TYPE));

  sparseset set = XNEWVAR (struct sparseset_def, n_bytes);

  /* Mark the sparseset as defined to silence some valgrind uninitialized
     read errors when accessing set->sparse[n] when "n" is not, and never has
     been, in the set.  These uninitialized reads are expected, by design and
     harmless.  */
  VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (set, n_bytes));

  set->dense = &(set->elms[0]);
  set->sparse = &(set->elms[n_elms]);
  set->size = n_elms;
  sparseset_clear (set);
  return set;
}

/* Low level routine not meant for use outside of sparseset.[ch].
   Assumes idx1 < s->members and idx2 < s->members.  */

static inline void
sparseset_swap (sparseset s, SPARSESET_ELT_TYPE idx1, SPARSESET_ELT_TYPE idx2)
{
  SPARSESET_ELT_TYPE tmp = s->dense[idx2];
  sparseset_insert_bit (s, s->dense[idx1], idx2);
  sparseset_insert_bit (s, tmp, idx1);
}

/* Operation: S = S - {e}
   Delete e from the set S if it is a member of S.  */

void
sparseset_clear_bit (sparseset s, SPARSESET_ELT_TYPE e)
{
  if (sparseset_bit_p (s, e))
    {
      SPARSESET_ELT_TYPE idx = s->sparse[e];
      SPARSESET_ELT_TYPE iter = s->iter;
      SPARSESET_ELT_TYPE mem = s->members - 1;

      /* If we are iterating over this set and we want to delete a
	 member we've already visited, then we swap the element we
	 want to delete with the element at the current iteration
	 index so that it plays well together with the code below
	 that actually removes the element.  */
      if (s->iterating && idx <= iter)
	{
	  if (idx < iter)
	    {
	      sparseset_swap (s, idx, iter);
	      idx = iter;
	    }
	  s->iter_inc = 0;
	}

      /* Replace the element we want to delete with the last element
	 in the dense array and then decrement s->members, effectively
	 removing the element we want to delete.  */
      sparseset_insert_bit (s, s->dense[mem], idx);
      s->members = mem;
    }
}

/* Operation: D = S
   Restrictions: none.  */

void
sparseset_copy (sparseset d, sparseset s)
{
  SPARSESET_ELT_TYPE i;

  if (d == s)
    return;

  sparseset_clear (d);
  for (i = 0; i < s->members; i++)
    sparseset_insert_bit (d, s->dense[i], i);
  d->members = s->members;
}

/* Operation: D = A & B.
   Restrictions: none.  */

void
sparseset_and (sparseset d, sparseset a, sparseset b)
{
  SPARSESET_ELT_TYPE e;

  if (a == b)
    {
      if (d != a)
	sparseset_copy (d, a);
      return;
    }

  if (d == a || d == b)
    {
      sparseset s = (d == a) ? b : a;

      EXECUTE_IF_SET_IN_SPARSESET (d, e)
	if (!sparseset_bit_p (s, e))
	  sparseset_clear_bit (d, e);
    }
  else
    {
      sparseset sml, lrg;

      if (sparseset_cardinality (a) < sparseset_cardinality (b))
	{
	  sml = a;
	  lrg = b;
	}
      else
	{
	  sml = b;
	  lrg = a;
	}

      sparseset_clear (d);
      EXECUTE_IF_SET_IN_SPARSESET (sml, e)
	if (sparseset_bit_p (lrg, e))
	  sparseset_set_bit (d, e);
    }
}

/* Operation: D = A & ~B.
   Restrictions: D != B, unless D == A == B.  */

void
sparseset_and_compl (sparseset d, sparseset a, sparseset b)
{
  SPARSESET_ELT_TYPE e;

  if (a == b)
    {
      sparseset_clear (d);
      return;
    }

  gcc_assert (d != b);

  if (d == a)
    {
      if (sparseset_cardinality (d) < sparseset_cardinality (b))
	{
	  EXECUTE_IF_SET_IN_SPARSESET (d, e)
	    if (sparseset_bit_p (b, e))
	      sparseset_clear_bit (d, e);
	}
      else
	{
	  EXECUTE_IF_SET_IN_SPARSESET (b, e)
	    sparseset_clear_bit (d, e);
	}
    }
  else
    {
      sparseset_clear (d);
      EXECUTE_IF_SET_IN_SPARSESET (a, e)
	if (!sparseset_bit_p (b, e))
	  sparseset_set_bit (d, e);
    }
}

/* Operation: D = A | B.
   Restrictions: none.  */

void
sparseset_ior (sparseset d, sparseset a, sparseset b)
{
  SPARSESET_ELT_TYPE e;

  if (a == b)
    sparseset_copy (d, a);
  else if (d == b)
    {
      EXECUTE_IF_SET_IN_SPARSESET (a, e)
	sparseset_set_bit (d, e);
    }
  else
    {
      if (d != a)
        sparseset_copy (d, a);
      EXECUTE_IF_SET_IN_SPARSESET (b, e)
	sparseset_set_bit (d, e);
    }
}

/* Operation: A == B
   Restrictions: none.  */

bool
sparseset_equal_p (sparseset a, sparseset b)
{
  SPARSESET_ELT_TYPE e;

  if (a == b)
    return true;

  if (sparseset_cardinality (a) != sparseset_cardinality (b))
    return false;

  EXECUTE_IF_SET_IN_SPARSESET (a, e)
    if (!sparseset_bit_p (b, e))
      return false;

  return true;
}

