001// ***** This file is automatically generated from EltNonZero.java.jpp
002
003package daikon.inv.unary.sequence;
004
005import daikon.*;
006import daikon.inv.*;
007import daikon.inv.ValueSet;
008import daikon.inv.binary.twoSequence.*;
009import daikon.inv.unary.scalar.*;
010import daikon.suppress.*;
011import java.util.*;
012import java.util.logging.Level;
013import java.util.logging.Logger;
014import org.checkerframework.checker.interning.qual.Interned;
015import org.checkerframework.checker.lock.qual.GuardSatisfied;
016import org.checkerframework.checker.nullness.qual.NonNull;
017import org.checkerframework.checker.nullness.qual.Nullable;
018import org.checkerframework.dataflow.qual.Pure;
019import org.checkerframework.dataflow.qual.SideEffectFree;
020import org.plumelib.util.Intern;
021import typequals.prototype.qual.NonPrototype;
022import typequals.prototype.qual.Prototype;
023
024/**
025 * Represents the invariant "x != 0" where x represents all of the elements of a sequence of
026 * long. Prints as {@code x[] elements != 0}.
027 */
028
029public final class EltNonZero extends SingleScalarSequence {
030  /** Debug tracer. */
031  public static final Logger debug =
032    Logger.getLogger("daikon.inv.unary.sequence.EltNonZero");
033
034  // We are Serializable, so we specify a version to allow changes to
035  // method signatures without breaking serialization.  If you add or
036  // remove fields, you should change this number to the current date.
037  static final long serialVersionUID = 20030822L;
038
039  // Variables starting with dkconfig_ should only be set via the
040  // daikon.config.Configuration interface.
041  /** Boolean. True iff EltNonZero invariants should be considered. */
042  public static boolean dkconfig_enabled = Invariant.invariantEnabledDefault;
043
044  EltNonZero(PptSlice ppt) {
045    super(ppt);
046  }
047
048  @Prototype EltNonZero() {
049    super();
050  }
051
052  private static @Prototype EltNonZero proto = new @Prototype EltNonZero();
053
054  /** Returns the prototype invariant for EltNonZero */
055  public static @Prototype EltNonZero get_proto() {
056    return proto;
057  }
058
059  /** returns whether or not this invariant is enabled */
060  @Override
061  public boolean enabled() {
062    return dkconfig_enabled;
063  }
064
065  /** instantiate an invariant on the specified slice */
066  @Override
067  protected EltNonZero instantiate_dyn(@Prototype EltNonZero this, PptSlice slice) {
068    return new EltNonZero(slice);
069  }
070
071  /** Returns whether or not the variable is a pointer. */
072  @Pure
073  private boolean is_pointer(@GuardSatisfied EltNonZero this) {
074    return !ppt.var_infos[0].type.baseIsIntegral();
075  }
076
077  @Override
078  public String repr(@GuardSatisfied EltNonZero this) {
079    return "EltNonZero" + varNames() + ": "
080      + !falsified;
081  }
082
083  @SideEffectFree
084  @Override
085  public String format_using(@GuardSatisfied EltNonZero this, OutputFormat format) {
086    if (format.isJavaFamily()) {
087      return format_java_family(format);
088    }
089
090    if (format == OutputFormat.DAIKON) {
091      return format_daikon();
092    }
093    if (format == OutputFormat.ESCJAVA) {
094      return format_esc();
095    }
096    if (format == OutputFormat.CSHARPCONTRACT) {
097      return format_csharp_contract();
098    }
099    if (format == OutputFormat.SIMPLIFY) {
100      return format_simplify();
101    }
102
103    return format_unimplemented(format);
104  }
105
106  public String format_daikon(@GuardSatisfied EltNonZero this) {
107    return var().name() + " elements != "
108           + (is_pointer() ? "null" : "0");
109  }
110
111  // We are a special case where a ghost field can actually talk about
112  // array contents.
113  @Pure
114  @Override
115  public boolean isValidEscExpression() {
116    return true;
117  }
118
119  public String format_esc(@GuardSatisfied EltNonZero this) {
120    // If this is an entire array or Collection (not a slice), then
121    //  * for arrays: use \nonnullelements(A)
122    //  * for Collections: use collection.containsNull == false
123    //    (the latter also requires that ghost field to get set)
124
125    // if (var().isDerivedSubSequenceOf() == null) {
126    if (var().is_direct_non_slice_array()) {
127      VarInfo term = var().get_enclosing_var();
128      String esc_name;
129      if (term == null) {
130        // Only happenes in internal format tests
131        esc_name = var().name().replace("[]", "");
132      } else {
133        // System.out.printf("term = %s, var = %s%n", term.name, var().name);
134        esc_name = term.esc_name();
135      }
136      if (var().type.isArray()) {
137        return "\\nonnullelements(" + esc_name + ")";
138      } else {
139        return esc_name + ".containsNull == false";
140      }
141    }
142
143    // If this is just part of an array or Collection (var is a
144    // slice), then calling viname.esc_name() will always throw an
145    // exception, since var() is certainly a sequence.  So use the
146    // standard quantification.
147
148    String[] form = VarInfo.esc_quantify(var());
149    return form[0] + "(" + form[1] + " != "
150           + (is_pointer() ? "null" : "0") + ")" + form[2];
151  }
152
153  public String format_java_family(@GuardSatisfied EltNonZero this, OutputFormat format) {
154    String retval =
155      "daikon.Quant.eltsNotEqual(" + var().name_using(format)
156      + (is_pointer() ? ", null" : ", 0") + ")";
157
158    return retval;
159  }
160
161  public String format_csharp_contract(@GuardSatisfied EltNonZero this) {
162    String[] split = var().csharp_array_split();
163    return "Contract.ForAll(" + split[0] + ", x => x" + split[1] + " != " + (is_pointer() ? "null" : "0") + ")";
164  }
165
166  public String format_simplify(@GuardSatisfied EltNonZero this) {
167    String[] form = VarInfo.simplify_quantify(var());
168    return form[0] + "(NEQ " + form[1] + " "
169      + (is_pointer() ? "null" : "0") + ")" + form[2];
170  }
171
172  @Override
173  @SuppressWarnings("UnnecessaryParentheses")  // generated code, parentheses are sometimes needed
174  public InvariantStatus check_modified(long @Interned [] a, int count) {
175    for (int ai = 0; ai < a.length; ai++) {
176      long v = a[ai];
177
178      if ((v == 0)) {
179        return InvariantStatus.FALSIFIED;
180      }
181    }
182    return InvariantStatus.NO_CHANGE;
183  }
184
185  @Override
186  public InvariantStatus add_modified(long @Interned [] a, int count) {
187
188    // if (logOn()) {
189    //  ValueSet.ValueSetScalarArray vs = (ValueSet.ValueSetScalarArray) ppt.var_infos[0].get_value_set();
190    //  log ("max=" + vs.max() + " array=" + Arrays.toString (a));
191    // }
192
193    return check_modified(a, count);
194  }
195
196  @Override
197  protected double computeConfidence() {
198    // Maybe just use 0 as the min or max instead, and see what happens:
199    // see whether the "nonzero" invariant holds anyway.  (Perhaps only
200    // makes sense to do if the {Lower,Upper}Bound invariant doesn't imply
201    // the non-zeroness.)  In that case, do still check for no values yet
202    // received.
203    ValueSet.ValueSetScalarArray vs = (ValueSet.ValueSetScalarArray) ppt.var_infos[0].get_value_set();
204    // log ("is_pointer()=" + is_pointer() + " vs.min=" + vs.min()
205    //       + " vs.max=" + vs.max());
206    if (!is_pointer() && ((vs.min() > 0) || (vs.max() < 0))) {
207      return Invariant.CONFIDENCE_UNJUSTIFIED;
208    } else {
209      double probability_one_elt_nonzero = 1 - confidence_one_elt_nonzero();
210      double result = 1 - Math.pow(probability_one_elt_nonzero, ppt.num_samples());
211      // if ((result < 0) || (result > 1))
212      //  System.err.println ("bad result: vs.max=" + vs.max() + " vs.min="
213      //                      + vs.min() + " conf="
214      //                      + confidence_one_elt_nonzero() + " range="
215      //                      + (vs.max() - vs.min() + 1)/ 1);
216      return result;
217    }
218  }
219
220  @SuppressWarnings("UnnecessaryParentheses")  // generated code, parentheses are sometimes needed
221  private double confidence_one_elt_nonzero() {
222    double range;
223    if (is_pointer()) {
224      range = 3;
225    } else {
226      int modulus = 1;
227
228      // I need to come back and make this work.
229      // {
230      //   for (Invariant inv : ppt.invs) {
231      //     if ((inv instanceof Modulus) && inv.enoughSamples()) {
232      //       modulus = ((Modulus) inv).modulus;
233      //       break;
234      //     }
235      //   }
236      // }
237
238      // Perhaps I ought to check that it's possible (given the modulus
239      // constraints) for the value to be zero; otherwise, the modulus
240      // constraint implies non-zero.
241      ValueSet.ValueSetScalarArray vs = (ValueSet.ValueSetScalarArray) ppt.var_infos[0].get_value_set();
242      range = (vs.max() - vs.min() + 1) / (double)(modulus);
243    }
244    return 1.0/range;
245  }
246
247  @Pure
248  @Override
249  public boolean isSameFormula(Invariant other) {
250    assert other instanceof EltNonZero;
251    return true;
252  }
253
254  @Pure
255  @Override
256  public boolean isExclusiveFormula(Invariant other) {
257    if (other instanceof EltOneOf) {
258      EltOneOf eoo = (EltOneOf) other;
259      if ((eoo.num_elts() == 1) && (((Long)eoo.elt()).longValue() == 0)) {
260        return true;
261      }
262    }
263    return false;
264  }
265
266  @Pure
267  @Override
268  public @Nullable DiscardInfo isObviousStatically(VarInfo[] vis) {
269    // This test doesn't seem right: the invariant is obvious if the
270    // elements don't have null, not if the collection doesn't have null.
271    if (!vis[0].aux.hasNull()) {
272      // If it's not a number and null doesn't have special meaning...
273      return new DiscardInfo(this, DiscardCode.obvious, "'null' has no special meaning for " + vis[0].name());
274    }
275    return super.isObviousStatically(vis);
276  }
277
278  @Pure
279  @Override
280  public @Nullable DiscardInfo isObviousDynamically(VarInfo[] vis) {
281    DiscardInfo super_result = super.isObviousDynamically(vis);
282    if (super_result != null) {
283      return super_result;
284    }
285
286    VarInfo v1 = vis[0];
287
288    // (a[] == []) ==> a[] != 0
289    if (ppt.parent.is_empty(v1)) {
290      return new DiscardInfo(this, DiscardCode.obvious, v1 + "is empty");
291    }
292
293    // (a[] > 0) v (a[] < 0) ==> a[] != 0
294    EltLowerBound lb = (EltLowerBound) ppt.parent.find_inv_by_class
295                                                    (vis, EltLowerBound.class);
296    if ((lb != null) && (lb.min() > 0)) {
297      return new DiscardInfo(this, DiscardCode.obvious, v1 + " > " + lb.min());
298    }
299    EltUpperBound ub = (EltUpperBound) ppt.parent.find_inv_by_class
300                                                    (vis, EltUpperBound.class);
301    if ((ub != null) && (ub.max() < 0)) {
302      return new DiscardInfo(this, DiscardCode.obvious, v1 + " < " + ub.max());
303    }
304
305    // For every other EltNonZero at this program point, see if there is a
306    // subsequence relationship between that array and this one.
307
308    if (debug.isLoggable(Level.FINE)) {
309      debug.fine("Testing isObviousDynamically for " + vis[0].name());
310    }
311
312    PptTopLevel parent = ppt.parent;
313    for (Iterator<Invariant> itor = parent.invariants_iterator(); itor.hasNext(); ) {
314      Invariant inv = itor.next();
315      if ((inv instanceof EltNonZero) && (inv != this) && inv.enoughSamples()) {
316        VarInfo v2 = inv.ppt.var_infos[0];
317        if (debug.isLoggable(Level.FINE)) {
318          debug.fine("  Have to test: " + inv.repr());
319        }
320
321        if (Debug.logOn()) {
322          Daikon.current_inv = this;
323        }
324        if (parent.is_subsequence(v1, v2)) {
325          return new DiscardInfo(this, DiscardCode.obvious, v1.name()
326                                  + " is a subsequence of " + v2.name());
327        }
328      }
329    }
330
331    return null;
332  }
333
334  // Look up a previously instantiated invariant.
335  public static @Nullable EltNonZero find(PptSlice ppt) {
336    assert ppt.arity() == 1;
337    for (Invariant inv : ppt.invs) {
338      if (inv instanceof EltNonZero) {
339        return (EltNonZero) inv;
340      }
341    }
342    return null;
343  }
344
345  /** NI suppressions, initialized in get_ni_suppressions() */
346  private static @Nullable NISuppressionSet suppressions = null;
347
348  /** returns the ni-suppressions for EltNonZero */
349  @Pure
350  @Override
351  public NISuppressionSet get_ni_suppressions() {
352    if (suppressions == null) {
353      NISuppressee suppressee = new NISuppressee(EltNonZero.class, 1);
354
355      // suppressor definitions (used in suppressions below)
356      NISuppressor v_eq_one = new NISuppressor(0, EltRangeInt.EqualOne.class);
357      NISuppressor v_eq_minus_one = new NISuppressor(0, EltRangeInt.EqualMinusOne.class);
358
359      suppressions = new NISuppressionSet(
360          new NISuppression[] {
361              // v == 1 ==> v != 0
362              new NISuppression(v_eq_one, suppressee),
363              // v == -1 ==> v != 0
364              new NISuppression(v_eq_minus_one, suppressee),
365          });
366    }
367
368    return suppressions;
369  }
370}