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