001// ***** This file is automatically generated from PairwiseIntComparison.java.jpp 002 003package daikon.inv.binary.twoSequence; 004 005import daikon.*; 006import daikon.Quantify.QuantFlags; 007import daikon.derive.binary.*; 008import daikon.inv.*; 009import daikon.inv.binary.twoScalar.*; 010import daikon.suppress.*; 011import java.util.Arrays; 012import java.util.Iterator; 013import java.util.logging.Level; 014import java.util.logging.Logger; 015import org.checkerframework.checker.interning.qual.Interned; 016import org.checkerframework.checker.lock.qual.GuardSatisfied; 017import org.checkerframework.checker.nullness.qual.NonNull; 018import org.checkerframework.checker.nullness.qual.Nullable; 019import org.checkerframework.dataflow.qual.Pure; 020import org.checkerframework.dataflow.qual.SideEffectFree; 021import org.plumelib.util.ArraysPlume; 022import org.plumelib.util.Intern; 023import typequals.prototype.qual.NonPrototype; 024import typequals.prototype.qual.Prototype; 025 026/** 027 * Represents an invariant between corresponding elements of two sequences of double values. The 028 * length of the sequences must match for the invariant to hold. A comparison is made over each 029 * {@code (x[i], y[i])} pair. Thus, {@code x[0]} is compared to {@code y[0]}, 030 * {@code x[1]} to {@code y[1]}, and so forth. Prints as {@code x[] == y[]}. 031 */ 032public class PairwiseFloatEqual extends TwoSequenceFloat { 033 static final long serialVersionUID = 20030822L; 034 035 /** Debug tracer. */ 036 public static final Logger debug = 037 Logger.getLogger("daikon.inv.binary.twoSequence.PairwiseFloatEqual"); 038 039 // Variables starting with dkconfig_ should only be set via the 040 // daikon.config.Configuration interface. 041 /** Boolean. True iff PairwiseIntComparison invariants should be considered. */ 042 public static boolean dkconfig_enabled = Invariant.invariantEnabledDefault; 043 044 static final boolean debugPairwiseIntComparison = false; 045 046 protected PairwiseFloatEqual(PptSlice ppt) { 047 super(ppt); 048 } 049 050 protected @Prototype PairwiseFloatEqual() { 051 super(); 052 } 053 054 private static @Prototype PairwiseFloatEqual proto = new @Prototype PairwiseFloatEqual(); 055 056 /** Returns the prototype invariant for PairwiseFloatEqual. */ 057 public static @Prototype PairwiseFloatEqual get_proto() { 058 return proto; 059 } 060 061 @Override 062 public boolean enabled() { 063 return dkconfig_enabled; 064 } 065 066 @Override 067 public boolean instantiate_ok(VarInfo[] vis) { 068 069 if (!valid_types(vis)) { 070 return false; 071 } 072 073 return true; 074 } 075 076 @Override 077 protected PairwiseFloatEqual instantiate_dyn(@Prototype PairwiseFloatEqual this, PptSlice slice) { 078 PairwiseFloatEqual inv = new PairwiseFloatEqual(slice); 079 if (logOn()) { 080 inv.log("instantiate"); 081 } 082 return inv; 083 } 084 085 @Pure 086 @Override 087 public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) { 088 VarInfo var1 = vis[0]; 089 VarInfo var2 = vis[1]; 090 091 DiscardInfo di = SubSequence.isObviousSubSequence(this, var1, var2); 092 if (di == null) { 093 di = SubSequence.isObviousSubSequence(this, var2, var1); 094 } 095 if (di != null) { 096 Global.implied_noninstantiated_invariants++; 097 return di; 098 } 099 100 // Don't instantiate if the variables can't have order 101 if (!var1.aux.hasOrder() || !var2.aux.hasOrder()) { 102 if (debug.isLoggable(Level.FINE)) { 103 debug.fine("Not instantitating for because order has no meaning: " 104 + var1.name() + " and " + var2.name()); 105 } 106 return new DiscardInfo(this, DiscardCode.obvious, "Obvious statically since order has no meaning"); 107 } 108 109 return super.isObviousStatically(vis); 110 } 111 112 @Pure 113 @Override 114 public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) { 115 DiscardInfo super_result = super.isObviousDynamically(vis); 116 if (super_result != null) { 117 return super_result; 118 } 119 120 // Subsequence invariants are implied by the same invariant over 121 // the supersequence 122 DiscardInfo di = superseq_implies(vis); 123 if (di != null) { 124 return di; 125 } 126 127 return null; 128 } 129 130 /** 131 * Checks to see if the same invariant exists over supersequences of these variables: 132 * 133 * <pre> 134 * (A[] op B[]) ^ (i == j) ⇒ A[i..] op B[j..] 135 * (A[] op B[]) ^ (i == j) ⇒ A[..i] op B[..j] 136 * </pre> 137 */ 138 private @Nullable DiscardInfo superseq_implies(VarInfo[] vis) { 139 140 // Make sure the variables are SequenceFloatSubsequence with the same start/end 141 VarInfo v1 = vis[0]; 142 VarInfo v2 = vis[1]; 143 if (!v1.isDerived() || !(v1.derived instanceof SequenceFloatSubsequence)) { 144 return null; 145 } 146 if (!v2.isDerived() || !(v2.derived instanceof SequenceFloatSubsequence)) { 147 return null; 148 } 149 @NonNull SequenceFloatSubsequence der1 = (SequenceFloatSubsequence) v1.derived; 150 @NonNull SequenceFloatSubsequence der2 = (SequenceFloatSubsequence) v2.derived; 151 if ((der1.from_start != der2.from_start) 152 || (der1.index_shift != der2.index_shift)) 153 return null; 154 155 // Make sure the subscripts are equal 156 DiscardInfo di = new DiscardInfo(this, DiscardCode.obvious, ""); 157 if (!ppt.parent.check_implied_canonical(di, der1.sclvar(), der2.sclvar(), 158 IntEqual.get_proto())) 159 return null; 160 161 // See if the super-sequences have the same invariant 162 if (!ppt.parent.check_implied_canonical(di, der1.seqvar(), der2.seqvar(), 163 PairwiseFloatEqual.get_proto())) 164 return null; 165 166 // Add in the vis variables to di reason (if they are different) 167 di.add_implied_vis(vis); 168 return di; 169 } 170 171 @Override 172 protected Invariant resurrect_done_swapped() { 173 174 return this; 175 } 176 177 @Pure 178 @Override 179 public boolean is_symmetric() { 180 return true; 181 } 182 183 @Override 184 public String repr(@GuardSatisfied PairwiseFloatEqual this) { 185 return "PairwiseFloatEqual" + varNames() + ": "; 186 } 187 188 public String getComparator() { 189 return "=="; 190 } 191 192 @SideEffectFree 193 @Override 194 public String format_using(@GuardSatisfied PairwiseFloatEqual this, OutputFormat format) { 195 196 if (format.isJavaFamily()) { 197 return format_java_family(format); 198 } 199 200 if (format == OutputFormat.DAIKON) { 201 return format_daikon(); 202 } 203 if (format == OutputFormat.ESCJAVA) { 204 return format_esc(); 205 } 206 if (format == OutputFormat.SIMPLIFY) { 207 return format_simplify(); 208 } 209 if (format == OutputFormat.CSHARPCONTRACT) { 210 return format_csharp(); 211 } 212 213 return format_unimplemented(format); 214 } 215 216 public String format_daikon(@GuardSatisfied PairwiseFloatEqual this) { 217 return var1().name() + " == " + var2().name() + " (elementwise)"; 218 } 219 220 public String format_esc(@GuardSatisfied PairwiseFloatEqual this) { 221 String[] form = VarInfo.esc_quantify(var1(), var2()); 222 return form[0] + "(" + form[1] + " == " + form[2] + ")" + form[3]; 223 } 224 225 public String format_simplify(@GuardSatisfied PairwiseFloatEqual this) { 226 String[] form = VarInfo.simplify_quantify(QuantFlags.element_wise(), var1(), var2()); 227 return form[0] + "(EQ " + form[1] + " " + form[2] + ")" + form[3]; 228 } 229 230 public String format_java_family(@GuardSatisfied PairwiseFloatEqual this, OutputFormat format) { 231 return "daikon.Quant.pairwiseEqual(" + var1().name_using(format) 232 + ", " + var2().name_using(format) + ")"; 233 } 234 235 public String format_csharp(@GuardSatisfied PairwiseFloatEqual this) { 236 237 String[] split1 = var1().csharp_array_split(); 238 String[] split2 = var2().csharp_array_split(); 239 240 String equals_str; 241 String end_str; 242 243 equals_str = " == "; 244 end_str = ""; 245 246 return "Contract.ForAll(0, " + split1[0] + ".Count(), i => " + split1[0] + "[i]" + split1[1] + equals_str + split2[0] + "[i]" + split2[1] + end_str + ")"; 247 } 248 249 @Override 250 public InvariantStatus check_modified(double @Interned [] a1, double @Interned [] a2, int count) { 251 assert a1 != null && a2 != null 252 : var1() + " " + var2() + " " + FileIO.get_linenum(); 253 if (a1.length != a2.length || a1.length == 0 || a2.length == 0) { 254 // destroyAndFlow(); 255 return InvariantStatus.FALSIFIED; 256 } 257 258 int len = a1.length; 259 // int len = Math.min(a1.length, a2.length); 260 261 for (int i = 0; i < len; i++) { 262 double v1 = a1[i]; 263 double v2 = a2[i]; 264 if (!Global.fuzzy.eq(v1, v2) ) { 265 // destroyAndFlow(); 266 return InvariantStatus.FALSIFIED; 267 } 268 } 269 return InvariantStatus.NO_CHANGE; 270 } 271 272 @Override 273 public InvariantStatus add_modified(double @Interned [] a1, double @Interned [] a2, 274 int count) { 275 if (logDetail()) { 276 log(debug, "saw add_modified (" + Arrays.toString(a1) 277 + ", " + Arrays.toString(a2) + ")"); 278 } 279 return check_modified(a1, a2, count); 280 } 281 282 @Override 283 protected double computeConfidence() { 284 // num_elt_values() would be more appropriate 285 // int num_values = ((PptSlice2) ppt).num_elt_values(); 286 int num_values = ppt.num_samples(); 287 if (num_values == 0) { 288 return Invariant.CONFIDENCE_UNJUSTIFIED; 289 } else { 290 291 // It's an equality invariant 292 return Invariant.CONFIDENCE_JUSTIFIED; 293 } 294 } 295 296 @Pure 297 @Override 298 public boolean isSameFormula(Invariant other) { 299 return true; 300 } 301 302 @Pure 303 @Override 304 public boolean isExclusiveFormula(Invariant other) { 305 return false; 306 } 307 308 // Look up a previously instantiated invariant. 309 public static @Nullable PairwiseFloatEqual find(PptSlice ppt) { 310 assert ppt.arity() == 2; 311 for (Invariant inv : ppt.invs) { 312 if (inv instanceof PairwiseFloatEqual) { 313 return (PairwiseFloatEqual) inv; 314 } 315 } 316 return null; 317 } 318 319 /** Returns a list of non-instantiating suppressions for this invariant. */ 320 @Pure 321 @Override 322 public @Nullable NISuppressionSet get_ni_suppressions() { 323 return suppressions; 324 } 325 326 private static @Nullable NISuppressionSet suppressions = null; 327 328}