001// ***** This file is automatically generated from LinearBinary.java.jpp 002 003package daikon.inv.binary.twoScalar; 004 005import daikon.*; 006import daikon.derive.unary.SequenceLength; 007import daikon.inv.*; 008import java.util.*; 009import org.checkerframework.checker.lock.qual.GuardSatisfied; 010import org.checkerframework.checker.nullness.qual.NonNull; 011import org.checkerframework.checker.nullness.qual.Nullable; 012import org.checkerframework.dataflow.qual.Pure; 013import org.checkerframework.dataflow.qual.SideEffectFree; 014import typequals.prototype.qual.NonPrototype; 015import typequals.prototype.qual.Prototype; 016 017/** 018 * Represents a Linear invariant between two long scalars {@code x} and {@code y}, of 019 * the form {@code ax + by + c = 0}. The constants {@code a}, {@code b} and 020 * {@code c} are mutually relatively prime, and the constant {@code a} is always positive. 021 */ 022public class LinearBinary extends TwoScalar { 023 static final long serialVersionUID = 20030822L; 024 025 // Variables starting with dkconfig_ should only be set via the 026 // daikon.config.Configuration interface. 027 /** Boolean. True iff LinearBinary invariants should be considered. */ 028 public static boolean dkconfig_enabled = Invariant.invariantEnabledDefault; 029 030 public LinearBinaryCore core; 031 032 @SuppressWarnings("nullness") // circular initialization 033 protected LinearBinary(PptSlice ppt) { 034 super(ppt); 035 core = new LinearBinaryCore(this); 036 } 037 038 @SuppressWarnings("nullness") // circular initialization 039 protected @Prototype LinearBinary() { 040 super(); 041 // Do we need core to be set for a prototype invariant? 042 core = new LinearBinaryCore(this); 043 } 044 045 private static @Prototype LinearBinary proto = new @Prototype LinearBinary(); 046 047 /** Returns a prototype LinearBinary invariant. */ 048 public static @Prototype LinearBinary get_proto() { 049 return proto; 050 } 051 052 @Override 053 public boolean enabled() { 054 return dkconfig_enabled; 055 } 056 057 @Override 058 public boolean instantiate_ok(VarInfo[] vis) { 059 060 if (!valid_types(vis)) { 061 return false; 062 } 063 064 // Don't look for linearbinary over hashcodes and booleans 065 if (!vis[0].file_rep_type.isIntegral() 066 || !vis[1].file_rep_type.isIntegral()) 067 return false; 068 069 return true; 070 } 071 072 @Override 073 protected LinearBinary instantiate_dyn(@Prototype LinearBinary this, PptSlice slice) { 074 return new LinearBinary(slice); 075 } 076 077 @SideEffectFree 078 @Override 079 public LinearBinary clone(@GuardSatisfied LinearBinary this) { 080 LinearBinary result = (LinearBinary) super.clone(); 081 result.core = core.clone(); 082 result.core.wrapper = result; 083 return result; 084 } 085 086 @Override 087 protected Invariant resurrect_done_swapped() { 088 core.swap(); 089 return this; 090 } 091 092 @Override 093 public String repr(@GuardSatisfied LinearBinary this) { 094 return "LinearBinary" + varNames() + ": falsified=" + falsified 095 + "; " + core.repr(); 096 } 097 098 @SideEffectFree 099 @Override 100 public String format_using(@GuardSatisfied LinearBinary this, OutputFormat format) { 101 return core.format_using(format, var1().name_using(format), 102 var2().name_using(format)); 103 } 104 105 @Pure 106 @Override 107 public boolean isActive() { 108 return core.isActive(); 109 } 110 111 @Override 112 public boolean mergeFormulasOk() { 113 return core.mergeFormulasOk(); 114 } 115 116 /** 117 * Merge the invariants in invs to form a new invariant. Each must be a LinearBinary invariant. The 118 * work is done by the LinearBinary core 119 * 120 * @param invs list of invariants to merge. They should all be permuted to match the variable 121 * order in parent_ppt. 122 * @param parent_ppt slice that will contain the new invariant 123 */ 124 @Override 125 public @Nullable LinearBinary merge(List<Invariant> invs, PptSlice parent_ppt) { 126 127 // Create a matching list of cores 128 List<LinearBinaryCore> cores = new ArrayList<>(); 129 for (Invariant inv : invs) { 130 cores.add(((LinearBinary) inv).core); 131 } 132 133 // Merge the cores and build a new invariant containing the merged core 134 LinearBinary result = new LinearBinary(parent_ppt); 135 LinearBinaryCore newcore = core.merge(cores, result); 136 if (newcore == null) { 137 return null; 138 } 139 result.core = newcore; 140 return result; 141 } 142 143 @Override 144 public InvariantStatus check_modified(long x, long y, int count) { 145 return clone().add_modified(x, y, count); 146 } 147 148 @Override 149 public InvariantStatus add_modified(long x, long y, int count) { 150 return core.add_modified(x, y, count); 151 } 152 153 @Override 154 public boolean enoughSamples(@GuardSatisfied LinearBinary this) { 155 return core.enoughSamples(); 156 } 157 158 @Override 159 protected double computeConfidence() { 160 return core.computeConfidence(); 161 } 162 163 @Pure 164 @Override 165 public boolean isExact() { 166 return true; 167 } 168 169 @Pure 170 @Override 171 public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) { 172 // Obvious derived 173 VarInfo var1 = vis[0]; 174 VarInfo var2 = vis[1]; 175 // avoid comparing "size(a)" to "size(a)-1"; yields "size(a)-1 = size(a) - 1" 176 if (var1.isDerived() 177 && (var1.derived instanceof SequenceLength) 178 && var2.isDerived() 179 && (var2.derived instanceof SequenceLength)) { 180 @NonNull SequenceLength sl1 = (SequenceLength) var1.derived; 181 @NonNull SequenceLength sl2 = (SequenceLength) var2.derived; 182 if (sl1.base == sl2.base) { 183 String discardString = var1.name()+" and "+var2.name()+" derived from "+ 184 "same sequence: "+sl1.base.name(); 185 return new DiscardInfo(this, DiscardCode.obvious, discardString); 186 } 187 } 188 // avoid comparing "size(a)-1" to anything; should compare "size(a)" instead 189 if (var1.isDerived() 190 && (var1.derived instanceof SequenceLength) 191 && ((SequenceLength) var1.derived).shift != 0) { 192 String discardString = "Variables of the form 'size(a)-1' are not compared since 'size(a)' "+ 193 "will be compared"; 194 return new DiscardInfo(this, DiscardCode.obvious, discardString); 195 } 196 if (var2.isDerived() 197 && (var2.derived instanceof SequenceLength) 198 && ((SequenceLength) var2.derived).shift != 0) { 199 String discardString = "Variables of the form 'size(a)-1' are not compared since 'size(a)' "+ 200 "will be compared"; 201 return new DiscardInfo(this, DiscardCode.obvious, discardString); 202 } 203 204 return super.isObviousStatically(vis); 205 } 206 207 @Pure 208 @Override 209 public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) { 210 DiscardInfo super_result = super.isObviousDynamically(vis); 211 if (super_result != null) { 212 return super_result; 213 } 214 215 if (core.a == 0) { 216 return new DiscardInfo(this, DiscardCode.obvious, var2().name() + " is constant"); 217 } 218 if (core.b == 0) { 219 return new DiscardInfo(this, DiscardCode.obvious, var1().name() + " is constant"); 220 } 221// if (core.a == 1 && core.b == 0) { 222// return new DiscardInfo(this, DiscardCode.obvious, "Variables are equal"); 223// } 224 if (core.a == -core.b && core.c == 0) { 225 return new DiscardInfo(this, DiscardCode.obvious, "Variables are equal"); 226 } 227 return null; 228 } 229 230 @Pure 231 @Override 232 public boolean isSameFormula(Invariant other) { 233 return core.isSameFormula(((LinearBinary) other).core); 234 } 235 236 @Pure 237 @Override 238 public boolean isExclusiveFormula(Invariant other) { 239 if (other instanceof LinearBinary) { 240 return core.isExclusiveFormula(((LinearBinary) other).core); 241 } 242 return false; 243 } 244 245 // Look up a previously instantiated invariant. 246 public static @Nullable LinearBinary find(PptSlice ppt) { 247 assert ppt.arity() == 2; 248 for (Invariant inv : ppt.invs) { 249 if (inv instanceof LinearBinary) { 250 return (LinearBinary) inv; 251 } 252 } 253 return null; 254 } 255 256 // Returns a vector of LinearBinary objects. 257 // This ought to produce an iterator instead. 258 public static List<LinearBinary> findAll(VarInfo vi) { 259 List<LinearBinary> result = new ArrayList<>(); 260 for (PptSlice view : vi.ppt.views_iterable()) { 261 if ((view.arity() == 2) && view.usesVar(vi)) { 262 LinearBinary lb = LinearBinary.find(view); 263 if (lb != null) { 264 result.add(lb); 265 } 266 } 267 } 268 return result; 269 } 270}