001// ***** This file is automatically generated from LinearTernary.java.jpp 002 003package daikon.inv.ternary.threeScalar; 004 005import daikon.*; 006import daikon.inv.* ; 007import daikon.inv.DiscardCode; 008import daikon.inv.DiscardInfo; 009import daikon.inv.binary.twoScalar.*; 010import daikon.inv.unary.scalar.*; 011import daikon.suppress.NIS; 012import java.util.*; 013import org.checkerframework.checker.lock.qual.GuardSatisfied; 014import org.checkerframework.checker.nullness.qual.Nullable; 015import org.checkerframework.dataflow.qual.Pure; 016import org.checkerframework.dataflow.qual.SideEffectFree; 017import org.checkerframework.framework.qual.Unused; 018import typequals.prototype.qual.NonPrototype; 019import typequals.prototype.qual.Prototype; 020 021/** 022 * Represents a Linear invariant over three double scalars {@code x}, 023 * {@code y}, and {@code z}, of the form 024 * {@code ax + by + cz + d = 0}. 025 * The constants {@code a}, {@code b}, {@code c}, and 026 * {@code d} are mutually relatively prime, and the constant 027 * {@code a} is always positive. 028 */ 029 030@SuppressWarnings("UnnecessaryParentheses") // generated code, parens are sometimes necessary 031public class LinearTernaryFloat extends ThreeFloat { 032 static final long serialVersionUID = 20030822L; 033 034 // Variables starting with dkconfig_ should only be set via the 035 // daikon.config.Configuration interface. 036 /** Boolean. True iff LinearTernary invariants should be considered. */ 037 public static boolean dkconfig_enabled = Invariant.invariantEnabledDefault; 038 039 public static final boolean debugLinearTernary = false; 040 // public static final boolean debugLinearTernary = true; 041 042 @Unused(when=Prototype.class) 043 public LinearTernaryCoreFloat core; 044 045 @SuppressWarnings("nullness") // circular initialization 046 protected LinearTernaryFloat(PptSlice ppt) { 047 super(ppt); 048 core = new LinearTernaryCoreFloat(this); 049 } 050 051 protected @Prototype LinearTernaryFloat() { 052 super(); 053 } 054 055 private static @Prototype LinearTernaryFloat proto = new @Prototype LinearTernaryFloat(); 056 057 /** Returns the prototype invariant for LinearTernaryFloat */ 058 public static @Prototype LinearTernaryFloat get_proto() { 059 return proto; 060 } 061 062 @Override 063 public boolean enabled() { 064 return dkconfig_enabled; 065 } 066 067 @Override 068 public boolean instantiate_ok(VarInfo[] vis) { 069 070 if (!valid_types(vis)) { 071 return false; 072 } 073 074 // make sure the variables are integral 075 if (!vis[0].file_rep_type.isFloat() 076 || !vis[1].file_rep_type.isFloat() 077 || !vis[2].file_rep_type.isFloat()) 078 return false; 079 080 // Don't create if any of the variables are constant. 081 // DynamicConstants will create this from LinearBinary 082 // and the constant value if/when all of its variables are non-constant 083 PptTopLevel parent = vis[0].ppt; 084 if (NIS.dkconfig_enabled && (parent.is_constant(vis[0]) 085 || parent.is_constant(vis[1]) 086 || parent.is_constant(vis[2]))) 087 return false; 088 089 /* 090 // JHP: This code is removed because these sorts of static checks 091 // can't be reliably performed with equality sets (just because 092 // the leaders are obvious subsets, does not imply that all members 093 // are. Eventually this should be moved to isObviousStatically() 094 095 VarInfo x = ppt.var_infos[0]; 096 VarInfo y = ppt.var_infos[1]; 097 VarInfo z = ppt.var_infos[2]; 098 099 if (((x.derived instanceof SequenceLength) 100 && (((SequenceLength) x.derived).shift != 0)) 101 || ((y.derived instanceof SequenceLength) 102 && (((SequenceLength) y.derived).shift != 0)) 103 || ((z.derived instanceof SequenceLength) 104 && (((SequenceLength) z.derived).shift != 0))) { 105 // Do not instantiate z-1 = ax + by + c. Instead, choose a different c. 106 Global.implied_noninstantiated_invariants += 1; 107 return null; 108 } 109 110 VarInfo x_summand = null; 111 VarInfo y_summand = null; 112 VarInfo z_summand = null; 113 if (x.derived instanceof SequenceSum) { 114 x_summand = ((SequenceSum) x.derived).base; 115 } 116 if (y.derived instanceof SequenceSum) { 117 y_summand = ((SequenceSum) y.derived).base; 118 } 119 if (z.derived instanceof SequenceSum) { 120 z_summand = ((SequenceSum) z.derived).base; 121 } 122 123 if ((x_summand != null) && (y_summand != null) && (z_summand != null)) { 124 // all 3 of x, y, and z are "sum(...)" 125 // avoid sum(a[0..i]) + sum(a[i..]) = sum(a[]) 126 127 if (debugLinearTernary) { 128 System.out.println(ppt.varNames() + " 3 summands: " + x_summand.name + " " + y_summand.name + " " + z_summand.name); 129 } 130 131 VarInfo x_seq = x_summand.isDerivedSubSequenceOf(); 132 VarInfo y_seq = y_summand.isDerivedSubSequenceOf(); 133 VarInfo z_seq = z_summand.isDerivedSubSequenceOf(); 134 if (x_seq == null) x_seq = x_summand; 135 if (y_seq == null) y_seq = y_summand; 136 if (z_seq == null) z_seq = z_summand; 137 VarInfo seq = x_seq; 138 139 if (debugLinearTernary) { 140 System.out.println(ppt.varNames() + " 3 sequences: " + x_seq.name + " " + y_seq.name + " " + z_seq.name); 141 } 142 143 if (((seq == x_summand) || (seq == y_summand) || (seq == z_summand)) 144 && (x_seq == y_seq) && (x_seq == z_seq)) { 145 assert y_seq == z_seq; 146 if (debugLinearTernary) { 147 System.out.println(ppt.varNames() + " 3 sequences match"); 148 } 149 150 SequenceFloatSubsequence part1 = null; 151 SequenceFloatSubsequence part2 = null; 152 for (int i = 0; i < 3; i++) { 153 VarInfo vi = ppt.var_infos[i]; 154 VarInfo summand = ((SequenceSum) vi.derived).base; 155 if (debugLinearTernary) { 156 System.out.println("considering: " + summand.name + " " + vi.name); 157 } 158 if (summand.derived instanceof SequenceFloatSubsequence) { 159 SequenceFloatSubsequence sss = (SequenceFloatSubsequence) summand.derived; 160 if (sss.from_start) { 161 part1 = sss; 162 } else { 163 part2 = sss; 164 } 165 } else { 166 if (debugLinearTernary) { 167 System.out.println("Not subseq: " + summand.name + " " + vi.name); 168 } 169 } 170 } 171 if (debugLinearTernary) { 172 System.out.println(ppt.varNames() + " part1=" + part1 + ", part2=" + part2 + ", seq=" + seq.name); 173 } 174 if ((part1 != null) && (part2 != null)) { 175 // now part1, and part2 are set 176 if ((part1.sclvar() == part2.sclvar()) 177 && (part1.index_shift + 1 == part2.index_shift)) { 178 if (debugLinearTernary) { 179 System.out.println("LinearTernary suppressed: " + ppt.varNames()); 180 } 181 Global.implied_noninstantiated_invariants += 1; 182 return null; 183 } 184 } 185 } 186 } else if ((x_summand != null) && (y_summand != null) 187 || ((x_summand != null) && (z_summand != null)) 188 || ((y_summand != null) && (z_summand != null))) { 189 // two of x, y, and z are "sum(...)" 190 // avoid sum(a[0..i-1]) + a[i] = sum(a[0..i]) 191 192 // if (debugLinearTernary) { 193 // System.out.println(ppt.varNames() + " 2 summands: " + x_summand + " " + y_summand + " " + z_summand); 194 // } 195 196 // The intention is that parta is a[0..i], partb is a[0..i-1], and 197 // notpart is a[i]. 198 VarInfo parta; 199 VarInfo partb; 200 VarInfo notpart; 201 202 if (x_summand != null) { 203 parta = x; 204 if (y_summand != null) { 205 partb = y; 206 notpart = z; 207 } else { 208 partb = z; 209 notpart = y; 210 } 211 } else { 212 notpart = x; 213 parta = y; 214 partb = z; 215 } 216 parta = ((SequenceSum) parta.derived).base; 217 partb = ((SequenceSum) partb.derived).base; 218 VarInfo seq = null; 219 VarInfo eltindex = null; 220 if (notpart.derived instanceof SequenceFloatSubscript) { 221 SequenceFloatSubscript sss = (SequenceFloatSubscript) notpart.derived; 222 seq = sss.seqvar(); 223 eltindex = sss.sclvar(); 224 } 225 if ((seq != null) 226 && (seq == parta.isDerivedSubSequenceOf()) 227 && (seq == partb.isDerivedSubSequenceOf())) { 228 // For now, don't deal with case where one variable is the entire 229 // sequence. 230 if (!((parta == seq) || (partb == seq))) { 231 SequenceFloatSubsequence a_sss = (SequenceFloatSubsequence) parta.derived; 232 SequenceFloatSubsequence b_sss = (SequenceFloatSubsequence) partb.derived; 233 if ((a_sss.sclvar() == eltindex) 234 && (b_sss.sclvar() == eltindex)) { 235 if ((a_sss.from_start 236 && b_sss.from_start 237 && (((a_sss.index_shift == -1) && (b_sss.index_shift == 0)) 238 || ((a_sss.index_shift == 0) && (b_sss.index_shift == -1)))) 239 || ((!a_sss.from_start) 240 && (!b_sss.from_start) 241 && (((a_sss.index_shift == 0) && (b_sss.index_shift == 1)) 242 || ((a_sss.index_shift == 1) && (b_sss.index_shift == 0))))) { 243 Global.implied_noninstantiated_invariants += 1; 244 return null; 245 } 246 } 247 } 248 } 249 } 250 */ 251 252 return true; 253 } 254 255 @Override 256 public LinearTernaryFloat instantiate_dyn(@Prototype LinearTernaryFloat this, PptSlice slice) { 257 return new LinearTernaryFloat(slice); 258 } 259 260 @SideEffectFree 261 @Override 262 public LinearTernaryFloat clone(@GuardSatisfied LinearTernaryFloat this) { 263 LinearTernaryFloat result = (LinearTernaryFloat) super.clone(); 264 result.core = core.clone(); 265 result.core.wrapper = result; 266 return result; 267 } 268 269 @Override 270 protected Invariant resurrect_done(int[] permutation) { 271 core.permute(permutation); 272 return this; 273 } 274 275 @Override 276 public String repr(@GuardSatisfied LinearTernaryFloat this) { 277 return "LinearTernaryFloat" + varNames() + ": falsified=" + falsified 278 + "; " + core.repr(); 279 } 280 281 @SideEffectFree 282 @Override 283 public String format_using(@GuardSatisfied LinearTernaryFloat this, OutputFormat format) { 284 return core.format_using(format, var1().name_using(format), 285 var2().name_using(format), var3().name_using(format)); 286 } 287 288 // public String format_reversed() { 289 // return core.format_reversed(var1().name.name(), var2().name.name(), var3().name.name()); 290 // } 291 292 @Pure 293 @Override 294 public boolean isActive() { 295 return core.isActive(); 296 } 297 298 public InvariantStatus setup(LinearBinaryFloat lb, VarInfo con_var, 299 double con_val) { 300 return core.setup(lb, con_var, con_val); 301 } 302 303 public InvariantStatus setup(OneOfFloat oo, VarInfo v1, double con1, 304 VarInfo v2, double con2) { 305 return core.setup(oo, v1, con1, v2, con2); 306 } 307 308 @Override 309 public InvariantStatus check_modified(double x, double y, double z, int count) { 310 return clone().add_modified(x, y, z, count); 311 } 312 313 @Override 314 public InvariantStatus add_modified(double x, double y, double z, int count) { 315 return core.add_modified(x, y, z, count); 316 } 317 318 @Override 319 public boolean enoughSamples(@GuardSatisfied LinearTernaryFloat this) { 320 return core.enoughSamples(); 321 } 322 323 @Override 324 protected double computeConfidence() { 325 return core.computeConfidence(); 326 } 327 328 @Pure 329 @Override 330 public boolean isExact() { 331 return true; 332 } 333 334 @Pure 335 @Override 336 public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) { 337 DiscardInfo super_result = super.isObviousDynamically(vis); 338 if (super_result != null) { 339 return super_result; 340 } 341 342 if (core.a == 0 || core.b == 0 || core.c == 0) { 343 return new DiscardInfo(this, DiscardCode.obvious, "If a coefficient is 0, a LinearBinary should" 344 + " exist over the other two variables"); 345 } 346 347 return null; 348 } 349 350 @Pure 351 @Override 352 public boolean isSameFormula(Invariant other) { 353 return core.isSameFormula(((LinearTernaryFloat) other).core); 354 } 355 356 @Pure 357 @Override 358 public boolean isExclusiveFormula(Invariant other) { 359 if (other instanceof LinearTernaryFloat) { 360 return core.isExclusiveFormula(((LinearTernaryFloat) other).core); 361 } 362 return false; 363 } 364 365 // Look up a previously instantiated invariant. 366 public static @Nullable LinearTernaryFloat find(PptSlice ppt) { 367 assert ppt.arity() == 3; 368 for (Invariant inv : ppt.invs) { 369 if (inv instanceof LinearTernaryFloat) { 370 return (LinearTernaryFloat) inv; 371 } 372 } 373 return null; 374 } 375 376 // Returns a vector of LinearTernaryFloat objects. 377 // This ought to produce an iterator instead. 378 public static List<LinearTernaryFloat> findAll(VarInfo vi) { 379 List<LinearTernaryFloat> result = new ArrayList<>(); 380 for (PptSlice view : vi.ppt.views_iterable()) { 381 if ((view.arity() == 3) && view.usesVar(vi)) { 382 LinearTernaryFloat lt = LinearTernaryFloat.find(view); 383 if (lt != null) { 384 result.add(lt); 385 } 386 } 387 } 388 return result; 389 } 390 391 @Override 392 public boolean mergeFormulasOk() { 393 return core.mergeFormulasOk(); 394 } 395 396 /** 397 * Merge the invariants in invs to form a new invariant. Each must be a LinearTernaryFloat invariant. The 398 * work is done by the LinearTernary core 399 * 400 * @param invs list of invariants to merge. They should all be permuted to match the variable 401 * order in parent_ppt. 402 * @param parent_ppt slice that will contain the new invariant 403 */ 404 @Override 405 public @Nullable LinearTernaryFloat merge(List<Invariant> invs, PptSlice parent_ppt) { 406 407 // Create a matching list of cores 408 List<LinearTernaryCoreFloat> cores = new ArrayList<>(); 409 for (Invariant inv : invs) { 410 cores.add(((LinearTernaryFloat) inv).core); 411 } 412 413 // Merge the cores and build a new invariant containing the merged core 414 LinearTernaryFloat result = new LinearTernaryFloat(parent_ppt); 415 LinearTernaryCoreFloat newcore = core.merge(cores, result); 416 if (newcore == null) { 417 return null; 418 } 419 result.core = newcore; 420 return result; 421 } 422}