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}