001// ***** This file is automatically generated from SequenceArbitrarySubsequence.java.jpp
002
003package daikon.derive.ternary;
004
005import org.checkerframework.checker.interning.qual.Interned;
006import org.checkerframework.dataflow.qual.Pure;
007import org.checkerframework.dataflow.qual.SideEffectFree;
008import daikon.*;
009import daikon.derive.*;
010import org.plumelib.util.ArraysPlume;
011import org.plumelib.util.Intern;
012
013public final class SequenceFloatArbitrarySubsequence extends TernaryDerivation {
014  static final long serialVersionUID = 20020122L;
015
016  // Variables starting with dkconfig_ should only be set via the
017  // daikon.config.Configuration interface.
018  /** Boolean. True iff SequenceFloatArbitrarySubsequence derived variables should be generated. */
019  public static boolean dkconfig_enabled = false;
020
021  // base1 is the sequence
022  // base2 is the starting index
023  // base3 is the ending index
024  public VarInfo seqvar() {
025    return base1;
026  }
027
028  public VarInfo startvar() {
029    return base2;
030  }
031
032  public VarInfo endvar() {
033    return base3;
034  }
035
036  // True if the subsequence includes its left endpoint.
037  public final boolean left_closed;
038
039  // True if the subsequence includes its right endpoint.
040  public final boolean right_closed;
041
042  /**
043   * Represents a subsequence of a sequence. The subsequence a[i..j] includes the endpoints i and j.
044   * The subsequence is meaningful if:
045   *
046   * <pre>
047   *  i &ge; 0
048   *  i &le; a.length
049   *  j &ge; -1
050   *  j &le; a.length-1
051   *  i &le; j+1
052   * </pre>
053   *
054   * These are the empty array:
055   *
056   * <pre>
057   *   a[0..-1]
058   *   a[a.length..a.length-1]
059   * </pre>
060   *
061   * These are illegal:
062   *
063   * <pre>
064   *   a[1..-1]
065   *   a[a.length..a.length-2]
066   *   a[a.length+1..a.length]
067   * </pre>
068   *
069   * @param left_closed true means the range starts at i; false means it starts at i+1
070   * @param right_closed true means the range ends at j; false means it ends at j-1
071   */
072  SequenceFloatArbitrarySubsequence(
073      VarInfo vi1, VarInfo vi2, VarInfo vi3, boolean left_closed, boolean right_closed) {
074    super(vi1, vi2, vi3);
075    this.left_closed = left_closed;
076    this.right_closed = right_closed;
077  }
078
079  @Override
080  public ValueAndModified computeValueAndModified(ValueTuple full_vt) {
081    int mod1 = base1.getModified(full_vt);
082    if (mod1 == ValueTuple.MISSING_NONSENSICAL) {
083      return ValueAndModified.MISSING_NONSENSICAL;
084    }
085    int mod2 = base2.getModified(full_vt);
086    if (mod2 == ValueTuple.MISSING_NONSENSICAL) {
087      return ValueAndModified.MISSING_NONSENSICAL;
088    }
089    int mod3 = base2.getModified(full_vt);
090    if (mod3 == ValueTuple.MISSING_NONSENSICAL) {
091      return ValueAndModified.MISSING_NONSENSICAL;
092    }
093
094    Object val1 = base1.getValue(full_vt);
095    if (val1 == null) {
096      return ValueAndModified.MISSING_NONSENSICAL;
097    }
098    double[] val1_array = (double[]) val1;
099    int val2 = base2.getIndexValue(full_vt);
100    int val3 = base3.getIndexValue(full_vt);
101
102    // One could argue that if the range exceeds the array bounds, one
103    // should just return the whole array; but we don't do that.  We
104    // say MISSING instead.
105
106    // Note that the resulting array
107    // is a[begin_inclusive..end_exclusive-1],
108    // not a[begin_inclusive..end_exclusive].
109    int begin_inclusive;
110    int end_exclusive;
111    if (left_closed) {
112      begin_inclusive = val2;
113    } else {
114      begin_inclusive = val2 + 1;
115    }
116    // begin_inclusive = val1_array.length is acceptable; that means the
117    // empty array (given that end_exclusive is val1_arrayl.length)
118    // (It is permitted to have a[a.length..a.length-1], which means
119    // the empty array.  But a[MAX_INT..MAX_INT-1] is not meaningful.)
120    if ((begin_inclusive < 0) || (begin_inclusive > val1_array.length)) {
121      missing_array_bounds = true;
122      return ValueAndModified.MISSING_NONSENSICAL;
123    }
124
125    if (right_closed) {
126      end_exclusive = val3 + 1;
127    } else {
128      end_exclusive = val3;
129    }
130    // end_exclusive = 0 is acceptable; that means the empty array (given
131    // that begin_inclusive is 0)
132    if ((end_exclusive < 0) || (end_exclusive > val1_array.length)) {
133      missing_array_bounds = true;
134      return ValueAndModified.MISSING_NONSENSICAL;
135    }
136
137    if (end_exclusive - begin_inclusive < 0) {
138      missing_array_bounds = true;
139      return ValueAndModified.MISSING_NONSENSICAL;
140    }
141
142    int mod =
143        (((mod1 == ValueTuple.UNMODIFIED)
144          && (mod2 == ValueTuple.UNMODIFIED)
145          && (mod3 == ValueTuple.UNMODIFIED))
146         ? ValueTuple.UNMODIFIED
147         : ValueTuple.MODIFIED);
148
149    if ((begin_inclusive == 0) && (end_exclusive == val1_array.length)) {
150      return new ValueAndModified(val1, mod);
151    }
152
153    double[] subarr =
154        ArraysPlume.subarray(val1_array, begin_inclusive, end_exclusive - begin_inclusive);
155    subarr = Intern.intern(subarr);
156    return new ValueAndModified(subarr, mod);
157  }
158
159  @Override
160  protected VarInfo makeVarInfo() {
161
162    return VarInfo.make_subsequence(
163        seqvar(), startvar(), (left_closed ? 0 : 1), endvar(), (right_closed ? 0 : -1));
164  }
165
166  @Override
167  public Quantify.Term get_lower_bound() {
168    return new Quantify.VarPlusOffset(startvar(), (left_closed ? 0 : 1));
169  }
170
171  @Override
172  public Quantify.Term get_upper_bound() {
173    return new Quantify.VarPlusOffset(endvar(), (right_closed ? 0 : 1));
174  }
175
176  @Override
177  public VarInfo get_array_var() {
178    return seqvar();
179  }
180
181  @Pure
182  @Override
183  public boolean isSameFormula(Derivation other) {
184    return (other instanceof SequenceFloatArbitrarySubsequence)
185        && (((SequenceFloatArbitrarySubsequence) other).left_closed == this.left_closed)
186        && (((SequenceFloatArbitrarySubsequence) other).right_closed == this.right_closed);
187  }
188
189  /** Returns the csharp name. */
190  @SideEffectFree
191  @Override
192  public String csharp_name(String index) {
193    String lower = get_lower_bound().csharp_name();
194    String upper = get_upper_bound().csharp_name();
195    // We do not need to check if seqvar().isPrestate() because it is redundant.
196    return seqvar().csharp_name() + ".Slice(" + lower + ", " + upper + ")";
197  }
198
199  @SideEffectFree
200  @Override
201  public String esc_name(String index) {
202    return String.format(
203       "%s[%s..%s]",
204       seqvar().esc_name(), get_lower_bound().esc_name(), get_upper_bound().esc_name());
205  }
206}