| 300 | } |
| 301 | |
| 302 | int CombineOps(OpRcPtrVec & opVec, OptimizationFlags oFlags) |
| 303 | { |
| 304 | int count = 0; |
| 305 | int firstindex = 0; // this must be a signed int |
| 306 | |
| 307 | OpRcPtrVec tmpops; |
| 308 | |
| 309 | while (firstindex < (static_cast<int>(opVec.size()) - 1)) |
| 310 | { |
| 311 | ConstOpRcPtr op1 = opVec[firstindex]; |
| 312 | ConstOpRcPtr op2 = opVec[firstindex + 1]; |
| 313 | const auto type1 = op1->data()->getType(); |
| 314 | |
| 315 | if (IsCombineEnabled(type1, oFlags) && op1->canCombineWith(op2)) |
| 316 | { |
| 317 | tmpops.clear(); |
| 318 | op1->combineWith(tmpops, op2); |
| 319 | FinalizeOps(tmpops); |
| 320 | |
| 321 | // The tmpops may have any number of ops in it: (0, 1, 2, ...). |
| 322 | // (Size 0 would occur only if the combination results in a no-op, |
| 323 | // for example, a pair of matrices that compose into a no-op are |
| 324 | // returned as empty rather than as an identity matrix.) |
| 325 | // |
| 326 | // No matter the number, we need to swap them in for the original ops. |
| 327 | |
| 328 | // Erase the initial two ops we've combined. |
| 329 | opVec.erase(opVec.begin() + firstindex, opVec.begin() + firstindex + 2); |
| 330 | |
| 331 | // Insert the new ops (which may be empty) at this location. |
| 332 | opVec.insert(opVec.begin() + firstindex, tmpops.begin(), tmpops.end()); |
| 333 | |
| 334 | // Decrement firstindex by 1, |
| 335 | // to backstep and reconsider the A, A' case. |
| 336 | // See RemoveInverseOps for the full discussion of |
| 337 | // why this is appropriate. |
| 338 | firstindex = std::max(0, firstindex - 1); |
| 339 | |
| 340 | // We've done something so increment the count! |
| 341 | ++count; |
| 342 | |
| 343 | // Break, since combining ops is less desirable than other optimization options. |
| 344 | // For example, it is preferable to remove a pair of ops using RemoveInverseOps |
| 345 | // rather than combining them. Consider this example: |
| 346 | // Lut1D A --> Matrix B --> Matrix C --> Lut1D Ainv |
| 347 | // If Matrix B & C are not pair inverses but do combine into an identity, then |
| 348 | // CombineOps would compose Lut1D A & Ainv, into a new Lut1D rather than |
| 349 | // allowing another round of optimization which would remove them as inverses. |
| 350 | break; |
| 351 | } |
| 352 | else |
| 353 | { |
| 354 | ++firstindex; |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | return count; |
| 359 | } |