001// ***** This file is automatically generated from SequencesJoin.java.jpp
002
003package daikon.derive.binary;
004
005import org.checkerframework.checker.lock.qual.GuardSatisfied;
006import org.checkerframework.dataflow.qual.Pure;
007import org.checkerframework.dataflow.qual.SideEffectFree;
008import daikon.*;
009import daikon.derive.*;
010import java.util.logging.Level;
011import java.util.logging.Logger;
012import org.plumelib.util.Intern;
013
014/**
015 * Derived variable representing the "join" of two sequences. That is, if the two sequences came
016 * from the same original data structure (like an array of multi-field objects) then we join the two
017 * sequences and generate a hashcode of the join value. This allows us to detect uniqueness and
018 * equality style invariants across the data structure rather than just one slice of it. Works for
019 * number and string arrays.
020 */
021public final class SequencesJoinFloat extends BinaryDerivation {
022  static final long serialVersionUID = 20020122L;
023
024  /** Debug tracer. */
025  public static final Logger debug = Logger.getLogger("daikon.derive.binary.SequencesJoinFloat");
026
027  // Variables starting with dkconfig_ should only be set via the
028  // daikon.config.Configuration interface.
029  /** Boolean. True iff SequencesJoin derived variables should be generated. */
030  public static boolean dkconfig_enabled = false;
031
032  @Override
033  public VarInfo var1(@GuardSatisfied SequencesJoinFloat this) {
034    return base1;
035  }
036
037  @Override
038  public VarInfo var2(@GuardSatisfied SequencesJoinFloat this) {
039    return base2;
040  }
041
042  /**
043   * Create a new SequencesJoin derivation.
044   *
045   * @param vi1 the first of the two variables this is based on
046   * @param vi2 the second of the two variables this is based on
047   */
048  SequencesJoinFloat(VarInfo vi1, VarInfo vi2) {
049    super(vi1, vi2);
050  }
051
052  /**
053   * Returns a new sequence of hashcodes that is the join of the hashcodes of the component
054   * sequences. This is modified whenever either component sequence is modified.
055   *
056   * @param full_vt the value tuple of a program point to compute the derived value from
057   */
058  @Override
059  public ValueAndModified computeValueAndModifiedImpl(ValueTuple full_vt) {
060    Object val1 = var1().getValue(full_vt);
061    Object val2 = var2().getValue(full_vt);
062
063    int length1 = -1;
064    int length2 = -2; // They must equal in the end
065
066    if (val1 == null) {
067      length1 = 0;
068    }
069
070    if (val2 == null) {
071      length2 = 0;
072    }
073
074    if (val1 instanceof double[]) {
075      length1 = ((double[]) val1).length;
076    }
077
078    if (val2 instanceof double[]) {
079      length2 = ((double[]) val2).length;
080    }
081
082    if (val1 instanceof double[]) {
083      length1 = ((double[]) val1).length;
084    }
085
086    if (val2 instanceof double[]) {
087      length2 = ((double[]) val2).length;
088    }
089
090    assert length1 == length2;
091
092    double[] result = new double[length1];
093
094    for (int i = 0; i < length1; i++) {
095      Object e1 = null;
096      Object e2 = null;
097      if (val1 instanceof double[]) {
098        e1 = Double.valueOf(((double[]) val1)[i]);
099      }
100      if (val2 instanceof double[]) {
101        e2 = Double.valueOf(((double[]) val2)[i]);
102      }
103      if (val1 instanceof Object[]) {
104        e1 = ((Object[]) val1)[i];
105      }
106      if (val2 instanceof Object[]) {
107        e2 = ((Object[]) val2)[i];
108      }
109      if (e1 == null) {
110        e1 = Double.valueOf(0);
111      }
112      if (e2 == null) {
113        e2 = Double.valueOf(0);
114      }
115      // Loses top 8 bits, but we're just mixing two hashCodes.
116      result[i] = ((long) e1.hashCode() << 8L) + e2.hashCode();
117    }
118
119    /*
120       Use this if you don't see no duplicates where you should
121    if (debug.isLoggable(Level.FINE)) {
122      debug.fine(var1().name.toString() + " " + var2().name.toString());
123      if (val1 instanceof double[]) {
124        debug.fine(Arrays.toString((double[]) val1));
125      } else {
126        debug.fine(Arrays.toString((Object[]) val1));
127      }
128      if (val2 instanceof double[]) {
129        debug.fine(Arrays.toString((double[]) val2));
130      } else {
131        debug.fine(Arrays.toString((Object[]) val2));
132      }
133      debug.fine(Arrays.toString(result));
134
135      }
136    */
137
138    int mod = ValueTuple.UNMODIFIED;
139    int mod1 = var1().getModified(full_vt);
140    int mod2 = var2().getModified(full_vt);
141
142    if (mod1 == ValueTuple.MODIFIED) {
143      mod = ValueTuple.MODIFIED;
144    }
145    if (mod2 == ValueTuple.MODIFIED) {
146      mod = ValueTuple.MODIFIED;
147    }
148    if (mod1 == ValueTuple.MISSING_NONSENSICAL) {
149      mod = ValueTuple.MISSING_NONSENSICAL;
150    }
151    if (mod2 == ValueTuple.MISSING_NONSENSICAL) {
152      mod = ValueTuple.MISSING_NONSENSICAL;
153    }
154    /*
155     * v1\v2  Unm  Mod  Mis
156     *
157     * Unm    Unm  Mod  Mis
158     * Mod    Mod  Mod  Mis
159     * Mis    Mis  Mis  Mis
160     */
161
162    return new ValueAndModified(Intern.intern(result), mod);
163  }
164
165  @Override
166  protected VarInfo makeVarInfo() {
167    VarInfo var1 = var1();
168    VarInfo var2 = var2();
169
170    VarInfo vi = VarInfo.make_function("join", var1, var2);
171
172    // Set the declared type and file rep types
173    String newTypeName = "Join(" + var1.type.toString() + "," + var2.type.toString() + ")";
174    vi.type = ProglangType.parse(newTypeName + "[]");
175    if (debug.isLoggable(Level.FINE)) {
176      debug.fine("New decl type is " + vi.type.toString());
177    }
178    vi.file_rep_type = ProglangType.HASHCODE_ARRAY;
179
180    // Generate a new comparability based on base comparabilities' indices
181    vi.comparability =
182        VarComparability.makeComparabilitySameIndices(newTypeName, var1.comparability);
183
184    return vi;
185  }
186
187  @SideEffectFree
188  @Override
189  public String toString(@GuardSatisfied SequencesJoinFloat this) {
190    return "[SequencesJoinFloat of " + var1().name() + " " + var2().name() + "]";
191  }
192
193  @Pure
194  @Override
195  public boolean isSameFormula(Derivation other) {
196    return (other instanceof SequencesJoinFloat);
197  }
198
199  @SideEffectFree
200  @Override
201  public String esc_name(String index) {
202    return String.format("join[%s,%s]", var1().esc_name(), var2().esc_name());
203  }
204}