// ***** This file is automatically generated from SequencesUnion.java.jpp

package daikon.derive.binary;

import org.checkerframework.checker.interning.qual.Interned;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.dataflow.qual.SideEffectFree;
import daikon.*;
import daikon.derive.*;
import org.plumelib.util.ArraysPlume;
import org.plumelib.util.Intern;

/**
 * Represents the setwise union of two base variables, each of which is a collection. This variable
 * contains every element that is in either of the base variables, but this variable contains no
 * duplicate elements. Elements are in order of first appearance in the base variables (base1
 * first).
 */
public final class SequenceScalarUnion extends BinaryDerivation {
  static final long serialVersionUID = 20020122L;

  // Variables starting with dkconfig_ should only be set via the
  // daikon.config.Configuration interface.
  /** Boolean. True iff SequenceScalarUnion derived variables should be generated. */
  public static boolean dkconfig_enabled = false;

  SequenceScalarUnion(VarInfo vi1, VarInfo vi2) {
    super(vi1, vi2);
  }

  @Override
  public ValueAndModified computeValueAndModifiedImpl(ValueTuple full_vt) {
    int mod1 = base1.getModified(full_vt);
    if (mod1 == ValueTuple.MISSING_NONSENSICAL) {
      return ValueAndModified.MISSING_NONSENSICAL;
    }
    int mod2 = base2.getModified(full_vt);
    if (mod2 == ValueTuple.MISSING_NONSENSICAL) {
      return ValueAndModified.MISSING_NONSENSICAL;
    }
    Object val1 = base1.getValue(full_vt);
    if (val1 == null) {
      return ValueAndModified.MISSING_NONSENSICAL;
    }
    long[] val1_array = (long[]) val1;
    Object val2 = base2.getValue(full_vt);
    if (val2 == null) {
      return ValueAndModified.MISSING_NONSENSICAL;
    }
    long[] val2_array = (long[]) val2;

    long[] tmp = new long[val1_array.length + val2_array.length];
    int size = 0;
    for (int i = 0; i < val1_array.length; i++) {
      long v = val1_array[i];
      if ((size == 0) || (ArraysPlume.indexOf(ArraysPlume.subarray(tmp, 0, size), v) == -1)) {
        tmp[size++] = v;
      }
    }
    for (int i = 0; i < val2_array.length; i++) {
      long v = val2_array[i];
      if ((size == 0) || (ArraysPlume.indexOf(ArraysPlume.subarray(tmp, 0, size), v) == -1)) {
        tmp[size++] = v;
      }
    }

    long[] union = ArraysPlume.subarray(tmp, 0, size);
    union = Intern.intern(union);

    int mod =
        (((mod1 == ValueTuple.UNMODIFIED) && (mod2 == ValueTuple.UNMODIFIED))
         ? ValueTuple.UNMODIFIED
         : ValueTuple.MODIFIED);
    return new ValueAndModified(union, mod);
  }

  @Override
  protected VarInfo makeVarInfo() {
    return VarInfo.make_function("union", base1, base2);
  }

  @Pure
  @Override
  public boolean isSameFormula(Derivation other) {
    return (other instanceof SequenceScalarUnion);
  }

  @SideEffectFree
  @Override
  public String esc_name(String index) {
    return String.format("union(%s,%s)", var1().esc_name(), var2().esc_name());
  }
}
