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}