001// ***** This file is automatically generated from BinaryInvariant.java.jpp
002
003package daikon.inv.binary.twoSequence;
004
005import daikon.*;
006import daikon.inv.*;
007import daikon.inv.InvariantStatus;
008import daikon.inv.binary.*;
009import org.checkerframework.checker.interning.qual.Interned;
010import org.checkerframework.checker.lock.qual.GuardSatisfied;
011import org.checkerframework.dataflow.qual.Pure;
012import org.plumelib.util.ArraysPlume;
013import org.plumelib.util.Intern;
014import typequals.prototype.qual.NonPrototype;
015import typequals.prototype.qual.Prototype;
016
017/**
018 * Base class for invariants over two variables of type long[].
019 * An example is {@code a[] is a subsequence of b[]}.
020 *
021 * <p>Provides a simpler mechanism for non-symmetric invariants to function over both permutations
022 * of their variables.
023 *
024 * <p>Non-symmetric invariants must instantiate two objects (one for each argument order). This is
025 * tracked by the variable swap. They must always access their variables via the methods var1() and
026 * var2() which return the correct variable (based on the swap setting). No other work is necessary,
027 * all permuations and resurrection is handled here.
028 *
029 * <p>Symmetric invariants should define symmetric() to return true or override
030 * resurrect_done_swapped to do nothing. Non-symmetric invariants that use converse operations (eg,
031 * less than and greater than) rather than argument swapping should override resurrect_done_swapped
032 * to return the correct class.
033 */
034public abstract class TwoSequence extends BinaryInvariant {
035  // We are Serializable, so we specify a version to allow changes to
036  // method signatures without breaking serialization.  If you add or
037  // remove fields, you should change this number to the current date.
038  static final long serialVersionUID = 20040113L;
039
040  // if true, swap the order of the invariant variables
041  protected boolean swap = false;
042
043  protected TwoSequence(PptSlice ppt) {
044    super(ppt);
045  }
046
047  protected @Prototype TwoSequence() {
048    super();
049  }
050
051  /** Returns whether or not the specified types are valid. */
052  @Override
053  final public boolean valid_types(VarInfo[] vis) {
054
055    if (vis.length != 2) {
056      return false;
057    }
058
059      boolean dim_ok = vis[0].file_rep_type.isArray() && vis[1].file_rep_type.isArray();
060
061    return dim_ok && vis[0].file_rep_type.baseIsScalar() && vis[1].file_rep_type.baseIsScalar();
062  }
063
064  /** Returns whether or not the variable order is currently swapped for this invariant. */
065  @Override
066  public boolean get_swap() {
067    return swap;
068  }
069
070  /** Checks to see if the variable order was swapped and calls the correct routine to handle it. */
071  @Override
072  protected Invariant resurrect_done(int[] permutation) {
073    assert permutation.length == 2;
074    // assert ArraysPlume.fnIsPermutation(permutation);
075    if (permutation[0] == 1) {
076      return resurrect_done_swapped();
077    } else {
078      return resurrect_done_unswapped();
079    }
080  }
081
082  /** Swaps the variables by inverting the state of swap. */
083  protected Invariant resurrect_done_swapped() {
084    if (!is_symmetric()) {
085      swap = !swap;
086    }
087    return this;
088  }
089
090   /** Subclasses can override in the rare cases they need to fix things even when not swapped. */
091  protected Invariant resurrect_done_unswapped() {
092    // do nothing
093    return this;
094  }
095
096  /**
097   * Returns the first variable. This is the only mechanism by which subclasses should access
098   * variables.
099   */
100  public VarInfo var1(@GuardSatisfied TwoSequence this) {
101    if (swap) {
102      return ppt.var_infos[1];
103    } else {
104      return ppt.var_infos[0];
105    }
106  }
107
108  /**
109   * Returns the first variable. This is the only mechanism by which subclasses should access
110   * variables.
111   */
112  public VarInfo var2(@GuardSatisfied TwoSequence this) {
113    if (swap) {
114      return ppt.var_infos[0];
115    } else {
116      return ppt.var_infos[1];
117    }
118  }
119
120  /**
121   * Returns the first variable from the specified vis. This is the only mechanism by which
122   * subclasses should access variables.
123   */
124  public VarInfo var1(VarInfo[] vis) {
125    if (swap) {
126      return vis[1];
127    } else {
128      return vis[0];
129    }
130  }
131
132  /**
133   * Returns the first variable in the specified vis. This is the only mechanism by which subclasses
134   * should access variables.
135   */
136  public VarInfo var2(VarInfo[] vis) {
137    if (swap) {
138      return vis[0];
139    } else {
140      return vis[1];
141    }
142  }
143
144  @Override
145  public InvariantStatus check(
146      @Interned Object val1, @Interned Object val2, int mod_index, int count) {
147    // Tests for whether a value is missing should be performed before
148    // making this call, so as to reduce overall work.
149    assert ! falsified;
150    assert (mod_index >= 0) && (mod_index < 4);
151    long @Interned [] v1 = ((long @Interned []) val1);
152    long @Interned [] v2 = ((long @Interned []) val2);
153    if (mod_index == 0) {
154      if (swap) {
155        return check_unmodified(v2, v1, count);
156      } else {
157        return check_unmodified(v1, v2, count);
158      }
159    } else {
160      if (swap) {
161        return check_modified(v2, v1, count);
162      } else {
163        return check_modified(v1, v2, count);
164      }
165    }
166  }
167
168  @Override
169  public InvariantStatus add(
170      @Interned Object val1, @Interned Object val2, int mod_index, int count) {
171    // Tests for whether a value is missing should be performed before
172    // making this call, so as to reduce overall work.
173    assert ! falsified;
174    assert (mod_index >= 0) && (mod_index < 4);
175    long @Interned [] v1 = ((long @Interned []) val1);
176    long @Interned [] v2 = ((long @Interned []) val2);
177    if (mod_index == 0) {
178      if (swap) {
179        return add_unmodified(v2, v1, count);
180      } else {
181        return add_unmodified(v1, v2, count);
182      }
183    } else {
184      if (swap) {
185        return add_modified(v2, v1, count);
186      } else {
187        return add_modified(v1, v2, count);
188      }
189    }
190  }
191
192  /**
193   * Presents a sample to the invariant. Returns whether the sample is consistent with the
194   * invariant. Does not change the state of the invariant.
195   *
196   * @param count how many identical samples were observed in a row. For example, three calls to
197   *     check_modified with a count parameter of 1 is equivalent to one call to check_modified with
198   *     a count parameter of 3.
199   * @return whether or not the sample is consistent with the invariant
200   */
201  public abstract InvariantStatus check_modified(long @Interned [] v1, long @Interned [] v2, int count);
202
203  public InvariantStatus check_unmodified(long @Interned [] v1, long @Interned [] v2, int count) {
204    return InvariantStatus.NO_CHANGE;
205  }
206
207  /** Default implementation simply calls check. Subclasses can override. */
208  public InvariantStatus add_modified(long @Interned [] v1, long @Interned [] v2, int count) {
209    return check_modified(v1, v2, count);
210  }
211
212  /** By default, do nothing if the value hasn't been seen yet. Subclasses can override this. */
213  public InvariantStatus add_unmodified(long @Interned [] v1, long @Interned [] v2, int count) {
214    return InvariantStatus.NO_CHANGE;
215  }
216
217  /** Returns a representation of the class. This includes the classname, variables, and swap state. */
218  @Override
219  public String repr(@GuardSatisfied TwoSequence this) {
220    return getClass().getName() + " (" + var1().name() + ", "
221      + var2().name() + ") [swap=" + swap + "]";
222  }
223
224  /**
225   * Return true if both invariants are the same class and the order of the variables (swap) is the
226   * same.
227   */
228  @Pure
229  @Override
230  public boolean isSameFormula(Invariant other) {
231    TwoSequence inv = (TwoSequence) other;
232    return (this.getClass() == inv.getClass()) && (this.swap == inv.swap);
233  }
234
235  @Override
236  protected double computeConfidence() {
237    return Invariant.conf_is_ge(ppt.num_values(), 5);
238  }
239}