001// ***** This file is automatically generated from NonZero.java.jpp 002 003package daikon.inv.unary.scalar; 004 005import daikon.*; 006import daikon.derive.unary.*; 007import daikon.inv.*; 008import daikon.inv.binary.sequenceScalar.*; 009import daikon.inv.unary.sequence.*; 010import java.util.*; 011import java.util.logging.Level; 012import java.util.logging.Logger; 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.plumelib.util.Intern; 018import typequals.prototype.qual.NonPrototype; 019import typequals.prototype.qual.Prototype; 020 021// This also serves as NonNull. 022 023/** 024 * Represents long scalars that are non-zero. Prints as {@code x != 0}, or as {@code x != 025 * null} for pointer types. 026 */ 027 028public class NonZero extends SingleScalar { 029 // We are Serializable, so we specify a version to allow changes to 030 // method signatures without breaking serialization. If you add or 031 // remove fields, you should change this number to the current date. 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 NonZero invariants should be considered. */ 037 public static boolean dkconfig_enabled = Invariant.invariantEnabledDefault; 038 039 /** Debug tracer. */ 040 public static final Logger debug = Logger.getLogger("daikon.inv.unary.scalar.NonZero"); 041 042 /** Maximum value ever used for max-min in confidence calculation. */ 043 static long range_max = 50; 044 045 private NonZero(PptSlice ppt) { 046 super(ppt); 047 } 048 049 private @Prototype NonZero() { 050 super(); 051 } 052 053 private static @Prototype NonZero proto = new @Prototype NonZero(); 054 055 /** Returns the prototype invariant for NonZero */ 056 public static @Prototype NonZero get_proto() { 057 return proto; 058 } 059 060 /** returns whether or not this invariant is enabled */ 061 @Override 062 public boolean enabled() { 063 return dkconfig_enabled; 064 } 065 066 /** Make sure the NonZero make sense on these vars. */ 067 @Override 068 public boolean instantiate_ok(VarInfo[] vis) { 069 070 if (!valid_types(vis)) { 071 return false; 072 } 073 074 if (vis[0].aux.isStruct() 075 || vis[0].aux.isNonNull() 076 || !vis[0].aux.hasNull()) 077 return false; 078 079 return true; 080 } 081 082 /** instantiate an invariant on the specified slice */ 083 @Override 084 public NonZero instantiate_dyn(@Prototype NonZero this, PptSlice slice) { 085 return new NonZero(slice); 086 } 087 088 private String zero(@GuardSatisfied @Prototype NonZero this, @SuppressWarnings("UnusedVariable") OutputFormat format) { 089 090 if (is_pointer()) { 091 return "null"; 092 } else { 093 return "0"; 094 } 095 096 } 097 098 @SideEffectFree 099 @Override 100 public String format_using(@GuardSatisfied @Prototype NonZero this, OutputFormat format) { 101 // // var() fails for prototype invariants 102 // if (ppt == null) { 103 // return "Prototype NonZero invariant (ppt == null)"; 104 // } 105 106 String name = var().name_using(format); 107 108 if (format.isJavaFamily()) { 109 110 return name + " != " + zero(format); 111 } 112 113 if ((format == OutputFormat.DAIKON) 114 || (format == OutputFormat.ESCJAVA) 115 || (format == OutputFormat.CSHARPCONTRACT)) { 116 return name + " != " + zero(format); 117 } 118 119 if (format == OutputFormat.SIMPLIFY) { 120 return "(NEQ " + var().simplifyFixup(name) + " " + zero(format) + ")"; 121 } 122 123 return format_unimplemented(format); 124 } 125 126 @Override 127 public InvariantStatus check_modified(long v, int count) { 128 if (v == 0) { 129 return InvariantStatus.FALSIFIED; 130 } else { 131 return InvariantStatus.NO_CHANGE; 132 } 133 } 134 135 @Override 136 public InvariantStatus add_modified(long v, int count) { 137 InvariantStatus status = check_modified(v, count); 138 if (status == InvariantStatus.FALSIFIED) { 139 if (logOn()) { 140 log(debug, "falsified (value = " + v + ")"); 141 } 142 } // else if (logDetail()) 143 // log ("add_modified (" + v + ")"); 144 return status; 145 } 146 147 /** Returns whether or not the variable is a pointer. */ 148 @Pure 149 private boolean is_pointer(@GuardSatisfied NonZero this) { 150 return ppt.var_infos[0].file_rep_type == ProglangType.HASHCODE; 151 } 152 153 @Override 154 protected double computeConfidence() { 155 return 1 - computeProbability(); 156 } 157 158 // used by computeConfidence 159 protected double computeProbability() { 160 assert ! falsified; 161 // This method works by looking at all sample values and 162 // calculating the probability that they were all non-zero by 163 // chance (assuming a uniform distribution). If the variable is 164 // not a pointer, the range used is the observed range from sample 165 // data. Further observed constraints are used to change the 166 // returned probability, such as all samples being congruent some 167 // modulus. 168 169 ValueSet.ValueSetScalar vs = (ValueSet.ValueSetScalar) ppt.var_infos[0].get_value_set(); 170 171 // If greater than or less than 0, the bounds invariant will be more 172 // interesting 173 if (!is_pointer() && ((vs.min() > 0) || (vs.max() < 0))) { 174 175 // Maybe just use 0 as the min or max instead, and see what happens: 176 // see whether the "nonzero" invariant holds anyway. (Perhaps only 177 // makes sense to do if the {Lower,Upper}Bound invariant doesn't imply 178 // the non-zeroness.) In that case, do still check for no values yet 179 // received. 180 return Invariant.PROBABILITY_UNJUSTIFIED; 181 } else { 182 long range; 183 if (is_pointer()) { 184 range = 3; 185 } else { 186 long modulus = 1; 187 { 188 Modulus mi = Modulus.find(ppt); 189 if (mi != null) { 190 modulus = mi.modulus; 191 } 192 } 193 // Perhaps I ought to check that it's possible (given the modulus 194 // constraints) for the value to be zero; otherwise, the modulus 195 // constraint implies non-zero. 196 range = (vs.max() - vs.min() + 1) / modulus; 197 } 198 if ((range_max != 0) && (range > range_max)) { 199 range = range_max; 200 } 201 202 double probability_one_elt_nonzero = 1 - 1.0/range; 203 // This could underflow; so consider doing 204 // double log_probability = self.samples*math.log(probability); 205 // then calling Math.exp (if the value is in the range that wouldn't 206 // cause underflow). 207 // return Math.pow(probability_one_elt_nonzero, ppt.num_mod_samples()); 208 return Math.pow(probability_one_elt_nonzero, ppt.num_samples()); 209 } 210 } 211 212 @Pure 213 @Override 214 public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) { 215 VarInfo var = vis[0]; 216 217 if (var.aux.isStruct()) { 218 return new DiscardInfo(this, DiscardCode.obvious, 219 var.name() + " is a struct"); 220 } 221 222 if (var.aux.isNonNull()) { 223 return new DiscardInfo(this, DiscardCode.obvious, 224 "aux information says " + var.name() + " is non-null"); 225 } 226 227 if (!var.aux.hasNull()) { 228 return new DiscardInfo(this, DiscardCode.obvious, 229 "'null' has no special meaning for " + var.name()); 230 } 231 232 return super.isObviousStatically(vis); 233 } 234 235 @Pure 236 @Override 237 public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) { 238 DiscardInfo super_result = super.isObviousDynamically(vis); 239 if (super_result != null) { 240 return super_result; 241 } 242 243 VarInfo var = vis[0]; 244 245 Debug dlog = new Debug(getClass(), ppt, vis); 246 247 if (logOn()) { 248 dlog.log("Checking IsObviousDynamically"); 249 } 250 251 // System.out.println("isObviousImplied: " + format()); 252 253 // For every EltNonZero at this program point, see if this variable is 254 // an obvious member of that sequence. 255 PptTopLevel parent = ppt.parent; 256 for (Iterator<Invariant> itor = parent.invariants_iterator(); itor.hasNext(); ) { 257 Invariant inv = itor.next(); 258 if ((inv instanceof EltNonZero) && inv.enoughSamples()) { 259 VarInfo v2 = inv.ppt.var_infos[0]; 260 // System.out.println("NonZero.isObviousImplied: calling Member.isObviousMember(" + var.name + ", " + v2.name + ")"); 261 // Don't use isEqualToObviousMember: that is too subtle 262 // and eliminates desirable invariants such as "return != null". 263 if (Member.isObviousMember(var, v2)) { 264 // System.out.println("NonZero.isObviousImplied: Member.isObviousMember(" + var.name + ", " + v2.name + ") = true"); 265 if (logOn()) { 266 dlog.log("isObvDyn- true, arg is member of nonzero sequence"); 267 } 268 String discardString = var.name() + " is a member of the non-zero sequence " + v2.name(); 269 if (logOn()) { 270 log("%s obviously implied from %s", format(), inv.format()); 271 } 272 return new DiscardInfo(this, DiscardCode.obvious, discardString); 273 } 274 } 275 } 276 277 if ((var.derived != null) 278 && (var.derived instanceof SequenceInitial)) { 279 SequenceInitial si = (SequenceInitial) var.derived; 280 if (si.index == 0) { 281 282 // For each sequence variable, if var is an obvious member, and 283 // the sequence has the same invariant, then this one is obvious. 284 PptTopLevel pptt = ppt.parent; 285 for (int i = 0; i < pptt.var_infos.length; i++) { 286 VarInfo vi = pptt.var_infos[i]; 287 if (Member.isObviousMember(var, vi)) { 288 PptSlice1 other_slice = pptt.findSlice(vi); 289 if (other_slice != null) { 290 SeqIndexIntNonEqual sine = SeqIndexIntNonEqual.find(other_slice); 291 if ((sine != null) && sine.enoughSamples()) { 292 // System.out.println("NonZero.isObviousImplied true due to: " + sine.format()); 293 if (logOn()) { 294 dlog.log("isObvDyn- true due to " + sine.format()); 295 } 296 String discardString = var.name() + " is a member of the non-zero sequence " + vi.name(); 297 return new DiscardInfo(this, DiscardCode.obvious, discardString); 298 } 299 } 300 } 301 } 302 } 303 } 304 305 return null; 306 } 307 308 @Pure 309 @Override 310 public boolean isSameFormula(Invariant other) { 311 assert other instanceof NonZero; 312 return true; 313 } 314 315 @Pure 316 @Override 317 public boolean isExclusiveFormula(Invariant other) { 318 if (other instanceof OneOfScalar) { 319 OneOfScalar oos = (OneOfScalar) other; 320 if ((oos.num_elts() == 1) && (((Long)oos.elt()).longValue() == 0)) { 321 return true; 322 } 323 } 324 return false; 325 } 326}