001// ***** This file is automatically generated from SequenceArbitrarySubsequenceFactory.java.jpp 002 003package daikon.derive.ternary; 004 005import org.checkerframework.checker.nullness.qual.Nullable; 006import daikon.*; 007import daikon.inv.binary.twoScalar.*; // for IntComparison 008import java.util.*; 009 010public final class SequenceScalarArbitrarySubsequenceFactory extends TernaryDerivationFactory { 011 012 // When calling/creating the derivations, arrange that: 013 // base1 is the sequence 014 // base2 and base3 are the scalars 015 016 @Override 017 public TernaryDerivation @Nullable [] instantiate(VarInfo vi1, VarInfo vi2, VarInfo vi3) { 018 019 // check if the derivations are globally disabled 020 boolean enable_subsequence = SequenceScalarArbitrarySubsequence.dkconfig_enabled; 021 if (!enable_subsequence) { 022 return null; 023 } 024 025 // This is not the very most efficient way to do this, but at 026 // least it is comprehensible. 027 VarInfo seqvar; 028 VarInfo sclvar1; 029 VarInfo sclvar2; 030 031 if ((vi1.rep_type == ProglangType.INT_ARRAY) 032 && (vi2.rep_type == ProglangType.INT) 033 && (vi3.rep_type == ProglangType.INT)) { 034 seqvar = vi1; 035 sclvar1 = vi2; 036 sclvar2 = vi3; 037 } else if ((vi2.rep_type == ProglangType.INT_ARRAY) 038 && (vi1.rep_type == ProglangType.INT) 039 && (vi3.rep_type == ProglangType.INT)) { 040 seqvar = vi2; 041 sclvar1 = vi1; 042 sclvar2 = vi3; 043 } else if ((vi3.rep_type == ProglangType.INT_ARRAY) 044 && (vi1.rep_type == ProglangType.INT) 045 && (vi2.rep_type == ProglangType.INT)) { 046 seqvar = vi3; 047 sclvar1 = vi1; 048 sclvar2 = vi2; 049 } else { 050 return null; 051 } 052 053 if (!seqvar.aux.hasOrder()) { 054 // Indexing doesn't make sense if order doesn't matter 055 return null; 056 } 057 058 if (!seqvar.indexCompatible(sclvar1)) { 059 return null; 060 } 061 if (!seqvar.indexCompatible(sclvar2)) { 062 return null; 063 } 064 065 // For now, do nothing if the sequence is itself derived. 066 if (seqvar.derived != null) { 067 return null; 068 } 069 // For now, do nothing if the scalar is itself derived. 070 if (sclvar1.derived != null) { 071 return null; 072 } 073 if (sclvar2.derived != null) { 074 return null; 075 } 076 077 List<TernaryDerivation> results1 = instantiateWithOrder(seqvar, sclvar1, sclvar2); 078 List<TernaryDerivation> results2 = instantiateWithOrder(seqvar, sclvar2, sclvar1); 079 080 results1.addAll(results2); 081 return results1.toArray(new TernaryDerivation[0]); 082 } 083 084 private List<TernaryDerivation> instantiateWithOrder( 085 VarInfo seqvar, VarInfo startvar, VarInfo endvar) { 086 List<TernaryDerivation> results = new ArrayList<>(); 087 VarInfo seqsize = seqvar.sequenceSize(); 088 if (seqsize != null) { 089 seqsize = seqsize.canonicalRep(); 090 } 091 092 // SUPPRESS DERIVED VARIABLE: a[..i] where i == a.length 093 // SUPPRESS DERIVED VARIABLE: a[..i-1] where i == a.length 094 // SUPPRESS DERIVED VARIABLE: a[i..] where i == a.length 095 // SUPPRESS DERIVED VARIABLE: a[i+1..] where i == a.length 096 // Since both are canonical, this is equivalent to 097 // "if (sclvar.canonicalRep() == seqsize.canonicalRep()) ..." 098 if (startvar == seqsize || endvar == seqsize) { 099 Global.tautological_suppressed_derived_variables += 4; 100 return results; 101 } 102 103 // SUPPRESS DERIVED VARIABLE: a[i] where (i >= a.length) can be true 104 // SUPPRESS DERIVED VARIABLE: a[i-1] where (i > a.length) can be true 105 // SUPPRESS DERIVED VARIABLE: a[..i] where (i >= a.length) can be true 106 // SUPPRESS DERIVED VARIABLE: a[..i-1] where (i > a.length) can be true 107 // SUPPRESS DERIVED VARIABLE: a[i..] where (i > a.length) can be true 108 // SUPPRESS DERIVED VARIABLE: a[i+1..] where (i >= a.length) can be true 109 // ***** This eliminates the derivation if it can *ever* be 110 // nonsensical/missing. Is that what I want? 111 // Find an IntComparison relationship over the scalar and the sequence 112 // size, if possible. 113 // PptSlice compar_slice = null; 114 // if (seqsize != null) { 115 // assert sclvar.ppt == seqsize.ppt; 116 // compar_slice = sclvar.ppt.findSlice_unordered(sclvar, seqsize); 117 // } 118 // if (compar_slice != null) { 119 // if ((sclvar.varinfo_index < seqsize.varinfo_index) 120 // ? IntLessEqual.find(compar_slice) == null // sclvar can be more than seqsize 121 // : IntGreaterEqual.find(compar_slice) == null // seqsize can be less than sclvar 122 // ) { 123 // Global.nonsensical_suppressed_derived_variables += 6; 124 // return null; 125 // } else if (IntEqual.find(compar_slice) != null) { 126 // Global.nonsensical_suppressed_derived_variables += 3; 127 // ArrayList<BinaryDerivation> result = new ArrayList<>(); 128 // if (enable_subscript) { 129 // result.add(new SEQUENCESCALARSUBSCRIPT(seqvar, sclvar, true)); // a[i-1] 130 // } 131 // if (enable_subsequence) { 132 // result.add(new SequenceScalarArbitrarySubsequence(seqvar, sclvar, true, true)); // a[..i-1] 133 // result.add(new SequenceScalarArbitrarySubsequence(seqvar, sclvar, false, false)); // a[i..] 134 // }; 135 // return result.toArray(new BinaryDerivation[0]); 136 // } 137 // } 138 139 // Abstract out these next two. 140 141 // If the scalar is a constant, then do all the following checks: 142 // 143 // If the scalar is a constant < 0: 144 // all derived variables are nonsensical 145 // SUPPRESS DERIVED VARIABLE: a[i] where i<0 and i is constant 146 // SUPPRESS DERIVED VARIABLE: a[i-1] where i<0 and i is constant 147 // SUPPRESS DERIVED VARIABLE: a[..i] where i<0 and i is constant 148 // SUPPRESS DERIVED VARIABLE: a[..i-1] where i<0 and i is constant 149 // SUPPRESS DERIVED VARIABLE: a[i..] where i<0 and i is constant 150 // SUPPRESS DERIVED VARIABLE: a[i+1..] where i<0 and i is constant 151 // If the scalar is the constant 0: 152 // array[0] is already extracted 153 // array[-1] is nonsensical 154 // array[0..0] is already extracted 155 // array[0..-1] is nonsensical 156 // array[0..] is the same as array[] 157 // array[1..] should be extracted 158 // SUPPRESS DERIVED VARIABLE: a[i] where i==0 159 // SUPPRESS DERIVED VARIABLE: a[i-1] where i==0 160 // SUPPRESS DERIVED VARIABLE: a[..i] where i==0 161 // SUPPRESS DERIVED VARIABLE: a[..i-1] where i==0 162 // SUPPRESS DERIVED VARIABLE: a[i..] where i==0 163 // If the scalar is the constant 1: 164 // array[1] is already extracted 165 // array[0] is already extracted 166 // array[0..1] should be extracted 167 // array[0..0] is already extracted 168 // array[1..] should be extracted 169 // array[2..] should be extracted 170 // SUPPRESS DERIVED VARIABLE: a[i] where i==1 171 // SUPPRESS DERIVED VARIABLE: a[i-1] where i==1 172 // SUPPRESS DERIVED VARIABLE: a[..i] where i==1 173 // SUPPRESS DERIVED VARIABLE: a[..i-1] where i==1 174 boolean suppress_i = false; 175 boolean suppress_j = false; 176 boolean suppress_i_plus_1 = false; 177 boolean suppress_j_minus_1 = false; 178 179 // If, for some canonical k, k=index+1, don't create array[index+1..]. 180 // If k=index-1, then don't create array[index-1] or array[0..index-1]. 181 // (k can have higher or lower VarInfo index than i.) 182 183 { 184 assert startvar.ppt == seqvar.ppt; 185 List<LinearBinary> lbs = LinearBinary.findAll(startvar); 186 for (Object lbObject : lbs) { 187 LinearBinary lb = (LinearBinary) lbObject; 188 // lb asserts that lb.var2() = lb.core.a * lb.var1() + lb.core.b <-- old 189 // Note that var2 comes before var1; this makes the most sense 190 // if you think of them as "y" and "x". <-- old 191 192 // lb asserts that lb.core.a * lb.var1() + lb.core.b * lb.var2() + lb.core.c == 0 193 // or lb.var2() == - (lb.core.a / lb.core.b) * lb.var1() - lb.core.c / lb.core.b 194 195 // if (lb.core.a == 1) { 196 if (-lb.core.a / lb.core.b == 1) { 197 // Don't set unconditionally, and don't break: we want to check 198 // other variables as well. 199 // if (lb.core.b == -1) { 200 if (-lb.core.c / lb.core.b == -1) { 201 if (lb.var1() != startvar) { 202 // i = k - 1, so k = i + 1 203 suppress_i_plus_1 = true; 204 } 205 } 206 // if (lb.core.b == 1) { 207 if (-lb.core.c / lb.core.b == 1) { 208 if (lb.var1() == startvar) { 209 // k = i + 1 210 suppress_i_plus_1 = true; 211 } 212 } 213 } 214 } 215 } 216 217 { 218 assert endvar.ppt == seqvar.ppt; 219 List<LinearBinary> lbs = LinearBinary.findAll(endvar); 220 for (Object lbObject : lbs) { 221 LinearBinary lb = (LinearBinary) lbObject; 222 // lb asserts that lb.var2() = lb.core.a * lb.var1() + lb.core.b <-- old 223 // Note that var2 comes before var1; this makes the most sense 224 // if you think of them as "y" and "x". <-- old 225 226 // lb asserts that lb.core.a * lb.var1() + lb.core.b * lb.var2() + lb.core.c == 0 227 // or lb.var2() == - (lb.core.a / lb.core.b) * lb.var1() - lb.core.c / lb.core.b 228 229 // if (lb.core.a == 1) { 230 if (-lb.core.a / lb.core.b == 1) { 231 // Don't set unconditionally, and don't break: we want to check 232 // other variables as well. 233 // if (lb.core.b == -1) { 234 if (-lb.core.c / lb.core.b == -1) { 235 if (lb.var1() == endvar) { 236 // k = j - 1 237 suppress_j_minus_1 = true; 238 } 239 } 240 // if (lb.core.b == 1) { 241 if (-lb.core.c / lb.core.b == 1) { 242 if (lb.var1() != endvar) { 243 // j = k + 1, so k = j - 1 244 suppress_j_minus_1 = true; 245 } 246 } 247 } 248 } 249 } 250 251 // End of applicability tests; now actually create the invariants 252 253 // a[i..j] 254 if (suppress_i || suppress_j) { 255 results.add(new SequenceScalarArbitrarySubsequence(seqvar, startvar, endvar, true, true)); 256 } else { 257 Global.tautological_suppressed_derived_variables++; 258 } 259 260 // a[i+1..j] 261 if (suppress_i_plus_1 || suppress_j) { 262 Global.tautological_suppressed_derived_variables++; 263 } else { 264 results.add(new SequenceScalarArbitrarySubsequence(seqvar, startvar, endvar, false, true)); 265 } 266 267 // a[i..j-1] 268 if (suppress_j_minus_1 || suppress_i) { 269 Global.tautological_suppressed_derived_variables++; 270 } else { 271 results.add(new SequenceScalarArbitrarySubsequence(seqvar, startvar, endvar, true, false)); 272 } 273 274 // a[i+1..j-1] 275 if (suppress_i_plus_1 || suppress_j_minus_1) { 276 Global.tautological_suppressed_derived_variables++; 277 } else { 278 results.add(new SequenceScalarArbitrarySubsequence(seqvar, startvar, endvar, false, false)); 279 } 280 281 return results; 282 } 283}