<commit_before>//===- LoopInfo.cpp - Natural Loop Calculator -----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LoopInfo class that is used to identify natural loops
// and determine the loop depth of various nodes of the CFG.  Note that the
// loops identified may actually be several natural loops that share the same
// header node... not just a single natural loop.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <algorithm>
using namespace llvm;

char LoopInfo::ID = 0;
static RegisterPass<LoopInfo>
X("loops", "Natural Loop Information", true, true);

//===----------------------------------------------------------------------===//
// Loop implementation
//

/// isLoopInvariant - Return true if the specified value is loop invariant
///
bool Loop::isLoopInvariant(Value *V) const {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return isLoopInvariant(I);
  return true;  // All non-instructions are loop invariant
}

/// isLoopInvariant - Return true if the specified instruction is
/// loop-invariant.
///
bool Loop::isLoopInvariant(Instruction *I) const {
  return !contains(I->getParent());
}

/// makeLoopInvariant - If the given value is an instruciton inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
/// Return true if the value after any hoisting is loop invariant. This
/// function can be used as a slightly more aggressive replacement for
/// isLoopInvariant.
///
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
///
bool Loop::makeLoopInvariant(Value *V, bool &Changed,
                             Instruction *InsertPt) const {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return makeLoopInvariant(I, Changed, InsertPt);
  return true;  // All non-instructions are loop-invariant.
}

/// makeLoopInvariant - If the given instruction is inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
/// Return true if the instruction after any hoisting is loop invariant. This
/// function can be used as a slightly more aggressive replacement for
/// isLoopInvariant.
///
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
///
bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
                             Instruction *InsertPt) const {
  // Test if the value is already loop-invariant.
  if (isLoopInvariant(I))
    return true;
  if (!I->isSafeToSpeculativelyExecute())
    return false;
  if (I->mayReadFromMemory())
    return false;
  // Determine the insertion point, unless one was given.
  if (!InsertPt) {
    BasicBlock *Preheader = getLoopPreheader();
    // Without a preheader, hoisting is not feasible.
    if (!Preheader)
      return false;
    InsertPt = Preheader->getTerminator();
  }
  // Don't hoist instructions with loop-variant operands.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
    if (!makeLoopInvariant(I->getOperand(i), Changed, InsertPt))
      return false;
  // Hoist.
  I->moveBefore(InsertPt);
  Changed = true;
  return true;
}

/// getCanonicalInductionVariable - Check to see if the loop has a canonical
/// induction variable: an integer recurrence that starts at 0 and increments
/// by one each time through the loop.  If so, return the phi node that
/// corresponds to it.
///
/// The IndVarSimplify pass transforms loops to have a canonical induction
/// variable.
///
PHINode *Loop::getCanonicalInductionVariable() const {
  BasicBlock *H = getHeader();

  BasicBlock *Incoming = 0, *Backedge = 0;
  typedef GraphTraits<Inverse<BasicBlock*> > InvBlockTraits;
  InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(H);
  assert(PI != InvBlockTraits::child_end(H) &&
         "Loop must have at least one backedge!");
  Backedge = *PI++;
  if (PI == InvBlockTraits::child_end(H)) return 0;  // dead loop
  Incoming = *PI++;
  if (PI != InvBlockTraits::child_end(H)) return 0;  // multiple backedges?

  if (contains(Incoming)) {
    if (contains(Backedge))
      return 0;
    std::swap(Incoming, Backedge);
  } else if (!contains(Backedge))
    return 0;

  // Loop over all of the PHI nodes, looking for a canonical indvar.
  for (BasicBlock::iterator I = H->begin(); isa<PHINode>(I); ++I) {
    PHINode *PN = cast<PHINode>(I);
    if (ConstantInt *CI =
        dyn_cast<ConstantInt>(PN->getIncomingValueForBlock(Incoming)))
      if (CI->isNullValue())
        if (Instruction *Inc =
            dyn_cast<Instruction>(PN->getIncomingValueForBlock(Backedge)))
          if (Inc->getOpcode() == Instruction::Add &&
                Inc->getOperand(0) == PN)
            if (ConstantInt *CI = dyn_cast<ConstantInt>(Inc->getOperand(1)))
              if (CI->equalsInt(1))
                return PN;
  }
  return 0;
}

/// getCanonicalInductionVariableIncrement - Return the LLVM value that holds
/// the canonical induction variable value for the "next" iteration of the
/// loop.  This always succeeds if getCanonicalInductionVariable succeeds.
///
Instruction *Loop::getCanonicalInductionVariableIncrement() const {
  if (PHINode *PN = getCanonicalInductionVariable()) {
    bool P1InLoop = contains(PN->getIncomingBlock(1));
    return cast<Instruction>(PN->getIncomingValue(P1InLoop));
  }
  return 0;
}

/// getTripCount - Return a loop-invariant LLVM value indicating the number of
/// times the loop will be executed.  Note that this means that the backedge
/// of the loop executes N-1 times.  If the trip-count cannot be determined,
/// this returns null.
///
/// The IndVarSimplify pass transforms loops to have a form that this
/// function easily understands.
///
Value *Loop::getTripCount() const {
  // Canonical loops will end with a 'cmp ne I, V', where I is the incremented
  // canonical induction variable and V is the trip count of the loop.
  Instruction *Inc = getCanonicalInductionVariableIncrement();
  if (Inc == 0) return 0;
  PHINode *IV = cast<PHINode>(Inc->getOperand(0));

  BasicBlock *BackedgeBlock =
    IV->getIncomingBlock(contains(IV->getIncomingBlock(1)));

  if (BranchInst *BI = dyn_cast<BranchInst>(BackedgeBlock->getTerminator()))
    if (BI->isConditional()) {
      if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition())) {
        if (ICI->getOperand(0) == Inc) {
          if (BI->getSuccessor(0) == getHeader()) {
            if (ICI->getPredicate() == ICmpInst::ICMP_NE)
              return ICI->getOperand(1);
          } else if (ICI->getPredicate() == ICmpInst::ICMP_EQ) {
            return ICI->getOperand(1);
          }
        }
      }
    }

  return 0;
}

/// getSmallConstantTripCount - Returns the trip count of this loop as a
/// normal unsigned value, if possible. Returns 0 if the trip count is unknown
/// of not constant. Will also return 0 if the trip count is very large
/// (>= 2^32)
unsigned Loop::getSmallConstantTripCount() const {
  Value* TripCount = this->getTripCount();
  if (TripCount) {
    if (ConstantInt *TripCountC = dyn_cast<ConstantInt>(TripCount)) {
      // Guard against huge trip counts.
      if (TripCountC->getValue().getActiveBits() <= 32) {
        return (unsigned)TripCountC->getZExtValue();
      }
    }
  }
  return 0;
}

/// getSmallConstantTripMultiple - Returns the largest constant divisor of the
/// trip count of this loop as a normal unsigned value, if possible. This
/// means that the actual trip count is always a multiple of the returned
/// value (don't forget the trip count could very well be zero as well!).
///
/// Returns 1 if the trip count is unknown or not guaranteed to be the
/// multiple of a constant (which is also the case if the trip count is simply
/// constant, use getSmallConstantTripCount for that case), Will also return 1
/// if the trip count is very large (>= 2^32).
unsigned Loop::getSmallConstantTripMultiple() const {
  Value* TripCount = this->getTripCount();
  // This will hold the ConstantInt result, if any
  ConstantInt *Result = NULL;
  if (TripCount) {
    // See if the trip count is constant itself
    Result = dyn_cast<ConstantInt>(TripCount);
    // if not, see if it is a multiplication
    if (!Result)
      if (BinaryOperator *BO = dyn_cast<BinaryOperator>(TripCount)) {
        switch (BO->getOpcode()) {
        case BinaryOperator::Mul:
          Result = dyn_cast<ConstantInt>(BO->getOperand(1));
          break;
        default:
          break;
        }
      }
  }
  // Guard against huge trip counts.
  if (Result && Result->getValue().getActiveBits() <= 32) {
    return (unsigned)Result->getZExtValue();
  } else {
    return 1;
  }
}

/// isLCSSAForm - Return true if the Loop is in LCSSA form
bool Loop::isLCSSAForm() const {
  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end());

  for (block_iterator BI = block_begin(), E = block_end(); BI != E; ++BI) {
    BasicBlock  *BB = *BI;
    for (BasicBlock ::iterator I = BB->begin(), E = BB->end(); I != E;++I)
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI) {
        BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
        if (PHINode *P = dyn_cast<PHINode>(*UI)) {
          UserBB = P->getIncomingBlock(UI);
        }

        // Check the current block, as a fast-path.  Most values are used in
        // the same block they are defined in.
        if (UserBB != BB && !LoopBBs.count(UserBB))
          return false;
      }
  }

  return true;
}

/// isLoopSimplifyForm - Return true if the Loop is in the form that
/// the LoopSimplify form transforms loops to, which is sometimes called
/// normal form.
bool Loop::isLoopSimplifyForm() const {
  // Normal-form loops have a preheader.
  if (!getLoopPreheader())
    return false;
  // Normal-form loops have a single backedge.
  if (!getLoopLatch())
    return false;
  // Each predecessor of each exit block of a normal loop is contained
  // within the loop.
  SmallVector<BasicBlock *, 4> ExitBlocks;
  getExitBlocks(ExitBlocks);
  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
    for (pred_iterator PI = pred_begin(ExitBlocks[i]),
         PE = pred_end(ExitBlocks[i]); PI != PE; ++PI)
      if (!contains(*PI))
        return false;
  // All the requirements are met.
  return true;
}

/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
/// These are the blocks _outside of the current loop_ which are branched to.
/// This assumes that loop is in canonical form.
///
void
Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
  assert(isLoopSimplifyForm() &&
         "getUniqueExitBlocks assumes the loop is in canonical form!");

  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallVector<BasicBlock *, 128> LoopBBs(block_begin(), block_end());
  std::sort(LoopBBs.begin(), LoopBBs.end());

  std::vector<BasicBlock *> switchExitBlocks;

  for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) {

    BasicBlock *current = *BI;
    switchExitBlocks.clear();

    typedef GraphTraits<BasicBlock *> BlockTraits;
    typedef GraphTraits<Inverse<BasicBlock *> > InvBlockTraits;
    for (BlockTraits::ChildIteratorType I =
         BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
         I != E; ++I) {
      // If block is inside the loop then it is not a exit block.
      if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
        continue;

      InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(*I);
      BasicBlock *firstPred = *PI;

      // If current basic block is this exit block's first predecessor
      // then only insert exit block in to the output ExitBlocks vector.
      // This ensures that same exit block is not inserted twice into
      // ExitBlocks vector.
      if (current != firstPred)
        continue;

      // If a terminator has more then two successors, for example SwitchInst,
      // then it is possible that there are multiple edges from current block
      // to one exit block.
      if (std::distance(BlockTraits::child_begin(current),
                        BlockTraits::child_end(current)) <= 2) {
        ExitBlocks.push_back(*I);
        continue;
      }

      // In case of multiple edges from current block to exit block, collect
      // only one edge in ExitBlocks. Use switchExitBlocks to keep track of
      // duplicate edges.
      if (std::find(switchExitBlocks.begin(), switchExitBlocks.end(), *I)
          == switchExitBlocks.end()) {
        switchExitBlocks.push_back(*I);
        ExitBlocks.push_back(*I);
      }
    }
  }
}

/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one
/// block, return that block. Otherwise return null.
BasicBlock *Loop::getUniqueExitBlock() const {
  SmallVector<BasicBlock *, 8> UniqueExitBlocks;
  getUniqueExitBlocks(UniqueExitBlocks);
  if (UniqueExitBlocks.size() == 1)
    return UniqueExitBlocks[0];
  return 0;
}

//===----------------------------------------------------------------------===//
// LoopInfo implementation
//
bool LoopInfo::runOnFunction(Function &) {
  releaseMemory();
  LI.Calculate(getAnalysis<DominatorTree>().getBase());    // Update
  return false;
}

void LoopInfo::verifyAnalysis() const {
  for (iterator I = begin(), E = end(); I != E; ++I) {
    assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
    (*I)->verifyLoop();
  }
}

void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequired<DominatorTree>();
}

void LoopInfo::print(raw_ostream &OS, const Module*) const {
  LI.print(OS);
}

<commit_msg>Smallvectorize switchExitBlocks.<commit_after>//===- LoopInfo.cpp - Natural Loop Calculator -----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LoopInfo class that is used to identify natural loops
// and determine the loop depth of various nodes of the CFG.  Note that the
// loops identified may actually be several natural loops that share the same
// header node... not just a single natural loop.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <algorithm>
using namespace llvm;

char LoopInfo::ID = 0;
static RegisterPass<LoopInfo>
X("loops", "Natural Loop Information", true, true);

//===----------------------------------------------------------------------===//
// Loop implementation
//

/// isLoopInvariant - Return true if the specified value is loop invariant
///
bool Loop::isLoopInvariant(Value *V) const {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return isLoopInvariant(I);
  return true;  // All non-instructions are loop invariant
}

/// isLoopInvariant - Return true if the specified instruction is
/// loop-invariant.
///
bool Loop::isLoopInvariant(Instruction *I) const {
  return !contains(I->getParent());
}

/// makeLoopInvariant - If the given value is an instruciton inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
/// Return true if the value after any hoisting is loop invariant. This
/// function can be used as a slightly more aggressive replacement for
/// isLoopInvariant.
///
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
///
bool Loop::makeLoopInvariant(Value *V, bool &Changed,
                             Instruction *InsertPt) const {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return makeLoopInvariant(I, Changed, InsertPt);
  return true;  // All non-instructions are loop-invariant.
}

/// makeLoopInvariant - If the given instruction is inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
/// Return true if the instruction after any hoisting is loop invariant. This
/// function can be used as a slightly more aggressive replacement for
/// isLoopInvariant.
///
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
///
bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
                             Instruction *InsertPt) const {
  // Test if the value is already loop-invariant.
  if (isLoopInvariant(I))
    return true;
  if (!I->isSafeToSpeculativelyExecute())
    return false;
  if (I->mayReadFromMemory())
    return false;
  // Determine the insertion point, unless one was given.
  if (!InsertPt) {
    BasicBlock *Preheader = getLoopPreheader();
    // Without a preheader, hoisting is not feasible.
    if (!Preheader)
      return false;
    InsertPt = Preheader->getTerminator();
  }
  // Don't hoist instructions with loop-variant operands.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
    if (!makeLoopInvariant(I->getOperand(i), Changed, InsertPt))
      return false;
  // Hoist.
  I->moveBefore(InsertPt);
  Changed = true;
  return true;
}

/// getCanonicalInductionVariable - Check to see if the loop has a canonical
/// induction variable: an integer recurrence that starts at 0 and increments
/// by one each time through the loop.  If so, return the phi node that
/// corresponds to it.
///
/// The IndVarSimplify pass transforms loops to have a canonical induction
/// variable.
///
PHINode *Loop::getCanonicalInductionVariable() const {
  BasicBlock *H = getHeader();

  BasicBlock *Incoming = 0, *Backedge = 0;
  typedef GraphTraits<Inverse<BasicBlock*> > InvBlockTraits;
  InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(H);
  assert(PI != InvBlockTraits::child_end(H) &&
         "Loop must have at least one backedge!");
  Backedge = *PI++;
  if (PI == InvBlockTraits::child_end(H)) return 0;  // dead loop
  Incoming = *PI++;
  if (PI != InvBlockTraits::child_end(H)) return 0;  // multiple backedges?

  if (contains(Incoming)) {
    if (contains(Backedge))
      return 0;
    std::swap(Incoming, Backedge);
  } else if (!contains(Backedge))
    return 0;

  // Loop over all of the PHI nodes, looking for a canonical indvar.
  for (BasicBlock::iterator I = H->begin(); isa<PHINode>(I); ++I) {
    PHINode *PN = cast<PHINode>(I);
    if (ConstantInt *CI =
        dyn_cast<ConstantInt>(PN->getIncomingValueForBlock(Incoming)))
      if (CI->isNullValue())
        if (Instruction *Inc =
            dyn_cast<Instruction>(PN->getIncomingValueForBlock(Backedge)))
          if (Inc->getOpcode() == Instruction::Add &&
                Inc->getOperand(0) == PN)
            if (ConstantInt *CI = dyn_cast<ConstantInt>(Inc->getOperand(1)))
              if (CI->equalsInt(1))
                return PN;
  }
  return 0;
}

/// getCanonicalInductionVariableIncrement - Return the LLVM value that holds
/// the canonical induction variable value for the "next" iteration of the
/// loop.  This always succeeds if getCanonicalInductionVariable succeeds.
///
Instruction *Loop::getCanonicalInductionVariableIncrement() const {
  if (PHINode *PN = getCanonicalInductionVariable()) {
    bool P1InLoop = contains(PN->getIncomingBlock(1));
    return cast<Instruction>(PN->getIncomingValue(P1InLoop));
  }
  return 0;
}

/// getTripCount - Return a loop-invariant LLVM value indicating the number of
/// times the loop will be executed.  Note that this means that the backedge
/// of the loop executes N-1 times.  If the trip-count cannot be determined,
/// this returns null.
///
/// The IndVarSimplify pass transforms loops to have a form that this
/// function easily understands.
///
Value *Loop::getTripCount() const {
  // Canonical loops will end with a 'cmp ne I, V', where I is the incremented
  // canonical induction variable and V is the trip count of the loop.
  Instruction *Inc = getCanonicalInductionVariableIncrement();
  if (Inc == 0) return 0;
  PHINode *IV = cast<PHINode>(Inc->getOperand(0));

  BasicBlock *BackedgeBlock =
    IV->getIncomingBlock(contains(IV->getIncomingBlock(1)));

  if (BranchInst *BI = dyn_cast<BranchInst>(BackedgeBlock->getTerminator()))
    if (BI->isConditional()) {
      if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition())) {
        if (ICI->getOperand(0) == Inc) {
          if (BI->getSuccessor(0) == getHeader()) {
            if (ICI->getPredicate() == ICmpInst::ICMP_NE)
              return ICI->getOperand(1);
          } else if (ICI->getPredicate() == ICmpInst::ICMP_EQ) {
            return ICI->getOperand(1);
          }
        }
      }
    }

  return 0;
}

/// getSmallConstantTripCount - Returns the trip count of this loop as a
/// normal unsigned value, if possible. Returns 0 if the trip count is unknown
/// of not constant. Will also return 0 if the trip count is very large
/// (>= 2^32)
unsigned Loop::getSmallConstantTripCount() const {
  Value* TripCount = this->getTripCount();
  if (TripCount) {
    if (ConstantInt *TripCountC = dyn_cast<ConstantInt>(TripCount)) {
      // Guard against huge trip counts.
      if (TripCountC->getValue().getActiveBits() <= 32) {
        return (unsigned)TripCountC->getZExtValue();
      }
    }
  }
  return 0;
}

/// getSmallConstantTripMultiple - Returns the largest constant divisor of the
/// trip count of this loop as a normal unsigned value, if possible. This
/// means that the actual trip count is always a multiple of the returned
/// value (don't forget the trip count could very well be zero as well!).
///
/// Returns 1 if the trip count is unknown or not guaranteed to be the
/// multiple of a constant (which is also the case if the trip count is simply
/// constant, use getSmallConstantTripCount for that case), Will also return 1
/// if the trip count is very large (>= 2^32).
unsigned Loop::getSmallConstantTripMultiple() const {
  Value* TripCount = this->getTripCount();
  // This will hold the ConstantInt result, if any
  ConstantInt *Result = NULL;
  if (TripCount) {
    // See if the trip count is constant itself
    Result = dyn_cast<ConstantInt>(TripCount);
    // if not, see if it is a multiplication
    if (!Result)
      if (BinaryOperator *BO = dyn_cast<BinaryOperator>(TripCount)) {
        switch (BO->getOpcode()) {
        case BinaryOperator::Mul:
          Result = dyn_cast<ConstantInt>(BO->getOperand(1));
          break;
        default:
          break;
        }
      }
  }
  // Guard against huge trip counts.
  if (Result && Result->getValue().getActiveBits() <= 32) {
    return (unsigned)Result->getZExtValue();
  } else {
    return 1;
  }
}

/// isLCSSAForm - Return true if the Loop is in LCSSA form
bool Loop::isLCSSAForm() const {
  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end());

  for (block_iterator BI = block_begin(), E = block_end(); BI != E; ++BI) {
    BasicBlock  *BB = *BI;
    for (BasicBlock ::iterator I = BB->begin(), E = BB->end(); I != E;++I)
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI) {
        BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
        if (PHINode *P = dyn_cast<PHINode>(*UI)) {
          UserBB = P->getIncomingBlock(UI);
        }

        // Check the current block, as a fast-path.  Most values are used in
        // the same block they are defined in.
        if (UserBB != BB && !LoopBBs.count(UserBB))
          return false;
      }
  }

  return true;
}

/// isLoopSimplifyForm - Return true if the Loop is in the form that
/// the LoopSimplify form transforms loops to, which is sometimes called
/// normal form.
bool Loop::isLoopSimplifyForm() const {
  // Normal-form loops have a preheader.
  if (!getLoopPreheader())
    return false;
  // Normal-form loops have a single backedge.
  if (!getLoopLatch())
    return false;
  // Each predecessor of each exit block of a normal loop is contained
  // within the loop.
  SmallVector<BasicBlock *, 4> ExitBlocks;
  getExitBlocks(ExitBlocks);
  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
    for (pred_iterator PI = pred_begin(ExitBlocks[i]),
         PE = pred_end(ExitBlocks[i]); PI != PE; ++PI)
      if (!contains(*PI))
        return false;
  // All the requirements are met.
  return true;
}

/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
/// These are the blocks _outside of the current loop_ which are branched to.
/// This assumes that loop is in canonical form.
///
void
Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
  assert(isLoopSimplifyForm() &&
         "getUniqueExitBlocks assumes the loop is in canonical form!");

  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallVector<BasicBlock *, 128> LoopBBs(block_begin(), block_end());
  std::sort(LoopBBs.begin(), LoopBBs.end());

  SmallVector<BasicBlock *, 32> switchExitBlocks;

  for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) {

    BasicBlock *current = *BI;
    switchExitBlocks.clear();

    typedef GraphTraits<BasicBlock *> BlockTraits;
    typedef GraphTraits<Inverse<BasicBlock *> > InvBlockTraits;
    for (BlockTraits::ChildIteratorType I =
         BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
         I != E; ++I) {
      // If block is inside the loop then it is not a exit block.
      if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
        continue;

      InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(*I);
      BasicBlock *firstPred = *PI;

      // If current basic block is this exit block's first predecessor
      // then only insert exit block in to the output ExitBlocks vector.
      // This ensures that same exit block is not inserted twice into
      // ExitBlocks vector.
      if (current != firstPred)
        continue;

      // If a terminator has more then two successors, for example SwitchInst,
      // then it is possible that there are multiple edges from current block
      // to one exit block.
      if (std::distance(BlockTraits::child_begin(current),
                        BlockTraits::child_end(current)) <= 2) {
        ExitBlocks.push_back(*I);
        continue;
      }

      // In case of multiple edges from current block to exit block, collect
      // only one edge in ExitBlocks. Use switchExitBlocks to keep track of
      // duplicate edges.
      if (std::find(switchExitBlocks.begin(), switchExitBlocks.end(), *I)
          == switchExitBlocks.end()) {
        switchExitBlocks.push_back(*I);
        ExitBlocks.push_back(*I);
      }
    }
  }
}

/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one
/// block, return that block. Otherwise return null.
BasicBlock *Loop::getUniqueExitBlock() const {
  SmallVector<BasicBlock *, 8> UniqueExitBlocks;
  getUniqueExitBlocks(UniqueExitBlocks);
  if (UniqueExitBlocks.size() == 1)
    return UniqueExitBlocks[0];
  return 0;
}

//===----------------------------------------------------------------------===//
// LoopInfo implementation
//
bool LoopInfo::runOnFunction(Function &) {
  releaseMemory();
  LI.Calculate(getAnalysis<DominatorTree>().getBase());    // Update
  return false;
}

void LoopInfo::verifyAnalysis() const {
  for (iterator I = begin(), E = end(); I != E; ++I) {
    assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
    (*I)->verifyLoop();
  }
}

void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequired<DominatorTree>();
}

void LoopInfo::print(raw_ostream &OS, const Module*) const {
  LI.print(OS);
}

<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <math.h>
#include <cstdlib>
#include <iomanip>

#include "VerditeWriter.h"
#include "../intField.h"
#include "../doubleField.h"
#include "../progressBar.h"

VerditeWriter::VerditeWriter(){}

VerditeWriter::~VerditeWriter(){}

std::string space2comma(std::string text) {
    for(std::string::iterator it = text.begin(); it != text.end(); ++it) {
        if(*it == ' ') {
            *it = ',';
        }
    }
    return text;
}

void VerditeWriter::Write(std::string fname,
  std::map<std::string, std::string> parameters,
  double *positions,
  std::vector<IntField*> intFields,
  std::vector<DoubleField*> doubleFields,
  int dim,
  long numParticles
  )
{
  std::map<std::string, std::string>::iterator it;
  int progress = 1;
  int j = 0;
  int k = 0;

  if(numParticles == 0)
  {
    std::cout << "Error: Number of particles is 0, exiting" << std::endl;
    std::exit(1);
  }

  ProgressBar pb(intFields.size()+doubleFields.size()+parameters.size()+1,"Writing output");

  std::ofstream outfile((char*)fname.c_str(), std::ios::out);
  if(outfile.is_open())
  {
    std::cout << "Writing to output file..." << std::flush;

    outfile <<  "# vtk DataFile Version 1.0" << std::endl;
    outfile <<  "vtk output" << std::endl;
    outfile <<  "ASCII" << std::endl;
    outfile <<  "DATASET POLYDATA" << std::endl;
    outfile <<  "POINTS " << numParticles << " float" << std::endl;
   for ( int i = 0; i<numParticles; i++ ) // All positions, duplicate this loop to write extra arrays
   {
    j = 3*i;
    outfile <<  positions[j] << " " << positions[j+1] << " " << positions[j+2] << std::endl;

    outfile <<  "POINT_DATA " << numParticles << std::endl;

    outfile <<  "FIELD FieldData " << doubleFields.size()+intFields.size() << std::endl;

    for (long intf=0; intf < intFields.size(); intf++)
    {
      IntField *thisField = intFields[intf];

      outfile <<  thisField->name << " " << thisField->dim << " " << numParticles << " float" << std::endl;

      for ( int i = 0; i<numParticles; i++ )
      {

        k= thisField->dim * i;

        for( int l=0; l<thisField->dim; l++)
        {
          outfile << " " << thisField->data[k+l];
        }
        outfile << std::endl;
      }
    }

    for (long intf=0; intf < doubleFields.size(); intf++)
    {
      DoubleField *thisField = doubleFields[intf];

      outfile <<  thisField->name << " " << thisField->dim << " " << numParticles << " float" << std::endl;

      for ( int i = 0; i<numParticles; i++ )
      {
        k= thisField->dim * i;
        for( int l=0; l<thisField->dim; l++)
        {
          outfile << " " << thisField->data[k+l];
        }
        outfile << std::endl;
      }
    }

    outfile.close();
  }

  std::string fname_par = fname.substr(0, fname.find(".", 0));
  fname_par = fname_par + ".par";

  std::ofstream outfile((char*)fname_par.c_str(), std::ios::out);
  if(outfile.is_open())
  {

    outfile <<  "numParticles=" << numParticles << std::endl; // Number of particles

    for ( it = parameters.begin(); it != parameters.end(); it++ ) // All the parameters defined int he python script
    {
      outfile <<  it->first << "=" << space2comma(it->second) << std::endl;
    }

    outfile.close();
  }

  pb.Finish();
}
}
<commit_msg>Corrected misplaced bracket in verditeWrtier.<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <math.h>
#include <cstdlib>
#include <iomanip>

#include "verditeWriter.h"
#include "../intField.h"
#include "../doubleField.h"
#include "../progressBar.h"

VerditeWriter::VerditeWriter(){}

VerditeWriter::~VerditeWriter(){}

std::string space2comma(std::string text) {
    for(std::string::iterator it = text.begin(); it != text.end(); ++it) {
        if(*it == ' ') {
            *it = ',';
        }
    }
    return text;
}

void VerditeWriter::Write(std::string fname,
  std::map<std::string, std::string> parameters,
  double *positions,
  std::vector<IntField*> intFields,
  std::vector<DoubleField*> doubleFields,
  int dim,
  long numParticles
  )
{
  std::map<std::string, std::string>::iterator it;
  int progress = 1;
  int j = 0;
  int k = 0;

  if(numParticles == 0)
  {
    std::cout << "Error: Number of particles is 0, exiting" << std::endl;
    std::exit(1);
  }

  ProgressBar pb(intFields.size()+doubleFields.size()+parameters.size()+1,"Writing output");

  std::ofstream outfile((char*)fname.c_str(), std::ios::out);
  if(outfile.is_open())
  {
    std::cout << "Writing to output file..." << std::flush;

    outfile <<  "# vtk DataFile Version 1.0" << std::endl;
    outfile <<  "vtk output" << std::endl;
    outfile <<  "ASCII" << std::endl;
    outfile <<  "DATASET POLYDATA" << std::endl;
    outfile <<  "POINTS " << numParticles << " float" << std::endl;
   for ( int i = 0; i<numParticles; i++ ) // All positions, duplicate this loop to write extra arrays
   {
    j = 3*i;
    outfile <<  positions[j] << " " << positions[j+1] << " " << positions[j+2] << std::endl;
   }

    outfile <<  "POINT_DATA " << numParticles << std::endl;

    outfile <<  "FIELD FieldData " << doubleFields.size()+intFields.size() << std::endl;

    for (long intf=0; intf < intFields.size(); intf++)
    {
      IntField *thisField = intFields[intf];

      outfile <<  thisField->name << " " << thisField->dim << " " << numParticles << " float" << std::endl;

      for ( int i = 0; i<numParticles; i++ )
      {

        k= thisField->dim * i;

        for( int l=0; l<thisField->dim; l++)
        {
          outfile << " " << thisField->data[k+l];
        }
        outfile << std::endl;
      }
    }

    for (long intf=0; intf < doubleFields.size(); intf++)
    {
      DoubleField *thisField = doubleFields[intf];

      outfile <<  thisField->name << " " << thisField->dim << " " << numParticles << " float" << std::endl;

      for ( int i = 0; i<numParticles; i++ )
      {
        k= thisField->dim * i;
        for( int l=0; l<thisField->dim; l++)
        {
          outfile << " " << thisField->data[k+l];
        }
        outfile << std::endl;
      }
    }

    outfile.close();
  }

  std::string fname_par = fname.substr(0, fname.find(".", 0));
  fname_par = fname_par + ".par";

  std::ofstream outfile2((char*)fname_par.c_str(), std::ios::out);
  if(outfile2.is_open())
  {

    outfile2 <<  "numParticles=" << numParticles << std::endl; // Number of particles

    for ( it = parameters.begin(); it != parameters.end(); it++ ) // All the parameters defined int he python script
    {
      outfile2 <<  it->first << "=" << space2comma(it->second) << std::endl;
    }

    outfile2.close();
  }

  pb.Finish();
}
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/tools/evaluation/utils.h"

#include "tensorflow/lite/tools/delegates/delegate_provider.h"
#if defined(__APPLE__)
#include "TargetConditionals.h"
#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) || \
    (TARGET_OS_OSX && TARGET_CPU_ARM64)
// Only enable coreml delegate when using a real iPhone device or Apple Silicon.
#define REAL_IPHONE_DEVICE
#include "tensorflow/lite/delegates/coreml/coreml_delegate.h"
#endif
#endif

#if !defined(_WIN32)
#include <dirent.h>
#endif
#include <sys/stat.h>

#include <algorithm>
#include <fstream>
#include <memory>
#include <string>

namespace tflite {
namespace evaluation {

std::string StripTrailingSlashes(const std::string& path) {
  int end = path.size();
  while (end > 0 && path[end - 1] == '/') {
    end--;
  }
  return path.substr(0, end);
}

bool ReadFileLines(const std::string& file_path,
                   std::vector<std::string>* lines_output) {
  if (!lines_output) {
    return false;
  }
  std::ifstream stream(file_path.c_str());
  if (!stream) {
    return false;
  }
  std::string line;
  while (std::getline(stream, line)) {
    lines_output->push_back(line);
  }
  return true;
}

#if !defined(_WIN32)
TfLiteStatus GetSortedFileNames(
    const std::string& directory, std::vector<std::string>* result,
    const std::unordered_set<std::string>& extensions) {
  DIR* dir;
  struct dirent* ent;
  if (result == nullptr) {
    return kTfLiteError;
  }
  result->clear();
  std::string dir_path = StripTrailingSlashes(directory);
  if ((dir = opendir(dir_path.c_str())) != nullptr) {
    while ((ent = readdir(dir)) != nullptr) {
      if (ent->d_type == DT_DIR) continue;
      std::string filename(std::string(ent->d_name));
      size_t lastdot = filename.find_last_of('.');
      std::string ext = lastdot != std::string::npos ? filename.substr(lastdot)
                                                     : std::string();
      std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
      if (!extensions.empty() && extensions.find(ext) == extensions.end()) {
        continue;
      }
      result->emplace_back(dir_path + "/" + filename);
    }
    closedir(dir);
  } else {
    return kTfLiteError;
  }
  std::sort(result->begin(), result->end());
  return kTfLiteOk;
}
#endif

TfLiteDelegatePtr CreateNNAPIDelegate() {
#if defined(__ANDROID__)
  return TfLiteDelegatePtr(
      NnApiDelegate(),
      // NnApiDelegate() returns a singleton, so provide a no-op deleter.
      [](TfLiteDelegate*) {});
#else
  return tools::CreateNullDelegate();
#endif  // defined(__ANDROID__)
}

TfLiteDelegatePtr CreateNNAPIDelegate(StatefulNnApiDelegate::Options options) {
#if defined(__ANDROID__)
  return TfLiteDelegatePtr(
      new StatefulNnApiDelegate(options), [](TfLiteDelegate* delegate) {
        delete reinterpret_cast<StatefulNnApiDelegate*>(delegate);
      });
#else
  return tools::CreateNullDelegate();
#endif  // defined(__ANDROID__)
}

#if TFLITE_SUPPORTS_GPU_DELEGATE
TfLiteDelegatePtr CreateGPUDelegate(TfLiteGpuDelegateOptionsV2* options) {
  return TfLiteDelegatePtr(TfLiteGpuDelegateV2Create(options),
                           &TfLiteGpuDelegateV2Delete);
}
#endif  // TFLITE_SUPPORTS_GPU_DELEGATE

TfLiteDelegatePtr CreateGPUDelegate() {
#if TFLITE_SUPPORTS_GPU_DELEGATE
  TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default();
  options.inference_priority1 = TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY;
  options.inference_preference =
      TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED;

  return CreateGPUDelegate(&options);
#else
  return tools::CreateNullDelegate();
#endif  // TFLITE_SUPPORTS_GPU_DELEGATE
}

TfLiteDelegatePtr CreateHexagonDelegate(
    const std::string& library_directory_path, bool profiling) {
#if TFLITE_ENABLE_HEXAGON
  TfLiteHexagonDelegateOptions options = {0};
  options.print_graph_profile = profiling;
  return CreateHexagonDelegate(&options, library_directory_path);
#else
  return tools::CreateNullDelegate();
#endif  // TFLITE_ENABLE_HEXAGON
}

#if TFLITE_ENABLE_HEXAGON
TfLiteDelegatePtr CreateHexagonDelegate(
    const TfLiteHexagonDelegateOptions* options,
    const std::string& library_directory_path) {
  if (library_directory_path.empty()) {
    TfLiteHexagonInit();
  } else {
    TfLiteHexagonInitWithPath(library_directory_path.c_str());
  }

  TfLiteDelegate* delegate = TfLiteHexagonDelegateCreate(options);
  if (!delegate) {
    TfLiteHexagonTearDown();
    return tools::CreateNullDelegate();
  }
  return TfLiteDelegatePtr(delegate, [](TfLiteDelegate* delegate) {
    TfLiteHexagonDelegateDelete(delegate);
    TfLiteHexagonTearDown();
  });
}
#endif

#if defined(__s390x__) || defined(TFLITE_WITHOUT_XNNPACK)
TfLiteDelegatePtr CreateXNNPACKDelegate(int num_threads) {
  return tools::CreateNullDelegate();
}
#else
TfLiteDelegatePtr CreateXNNPACKDelegate() {
  TfLiteXNNPackDelegateOptions xnnpack_options =
      TfLiteXNNPackDelegateOptionsDefault();
  return CreateXNNPACKDelegate(&xnnpack_options);
}

TfLiteDelegatePtr CreateXNNPACKDelegate(
    const TfLiteXNNPackDelegateOptions* xnnpack_options) {
  auto xnnpack_delegate = TfLiteXNNPackDelegateCreate(xnnpack_options);
  return TfLiteDelegatePtr(xnnpack_delegate, [](TfLiteDelegate* delegate) {
    TfLiteXNNPackDelegateDelete(delegate);
  });
}

TfLiteDelegatePtr CreateXNNPACKDelegate(int num_threads) {
  auto opts = TfLiteXNNPackDelegateOptionsDefault();
  // Note that we don't want to use the thread pool for num_threads == 1.
  opts.num_threads = num_threads > 1 ? num_threads : 0;
  return CreateXNNPACKDelegate(&opts);
}

TfLiteDelegatePtr CreateCoreMlDelegate() {
#ifdef REAL_IPHONE_DEVICE
  TfLiteCoreMlDelegateOptions coreml_options = {
      .enabled_devices = TfLiteCoreMlDelegateAllDevices};
  TfLiteDelegate* delegate = TfLiteCoreMlDelegateCreate(&coreml_options);
  if (!delegate) {
    return tools::CreateNullDelegate();
  }
  return TfLiteDelegatePtr(delegate, &TfLiteCoreMlDelegateDelete);
#else
  return tools::CreateNullDelegate();
#endif
}

#endif
}  // namespace evaluation
}  // namespace tflite
<commit_msg>lite: Fix Linux build error of //tensorflow/lite/tools/evaluation/tasks/inference_diff:run_eval<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/tools/evaluation/utils.h"

#include "tensorflow/lite/tools/delegates/delegate_provider.h"
#if defined(__APPLE__)
#include "TargetConditionals.h"
#if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) || \
    (TARGET_OS_OSX && TARGET_CPU_ARM64)
// Only enable coreml delegate when using a real iPhone device or Apple Silicon.
#define REAL_IPHONE_DEVICE
#include "tensorflow/lite/delegates/coreml/coreml_delegate.h"
#endif
#endif

#if !defined(_WIN32)
#include <dirent.h>
#endif
#include <sys/stat.h>

#include <algorithm>
#include <fstream>
#include <memory>
#include <string>

namespace tflite {
namespace evaluation {

std::string StripTrailingSlashes(const std::string& path) {
  int end = path.size();
  while (end > 0 && path[end - 1] == '/') {
    end--;
  }
  return path.substr(0, end);
}

bool ReadFileLines(const std::string& file_path,
                   std::vector<std::string>* lines_output) {
  if (!lines_output) {
    return false;
  }
  std::ifstream stream(file_path.c_str());
  if (!stream) {
    return false;
  }
  std::string line;
  while (std::getline(stream, line)) {
    lines_output->push_back(line);
  }
  return true;
}

#if !defined(_WIN32)
TfLiteStatus GetSortedFileNames(
    const std::string& directory, std::vector<std::string>* result,
    const std::unordered_set<std::string>& extensions) {
  DIR* dir;
  struct dirent* ent;
  if (result == nullptr) {
    return kTfLiteError;
  }
  result->clear();
  std::string dir_path = StripTrailingSlashes(directory);
  if ((dir = opendir(dir_path.c_str())) != nullptr) {
    while ((ent = readdir(dir)) != nullptr) {
      if (ent->d_type == DT_DIR) continue;
      std::string filename(std::string(ent->d_name));
      size_t lastdot = filename.find_last_of('.');
      std::string ext = lastdot != std::string::npos ? filename.substr(lastdot)
                                                     : std::string();
      std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
      if (!extensions.empty() && extensions.find(ext) == extensions.end()) {
        continue;
      }
      result->emplace_back(dir_path + "/" + filename);
    }
    closedir(dir);
  } else {
    return kTfLiteError;
  }
  std::sort(result->begin(), result->end());
  return kTfLiteOk;
}
#endif

TfLiteDelegatePtr CreateNNAPIDelegate() {
#if defined(__ANDROID__)
  return TfLiteDelegatePtr(
      NnApiDelegate(),
      // NnApiDelegate() returns a singleton, so provide a no-op deleter.
      [](TfLiteDelegate*) {});
#else
  return tools::CreateNullDelegate();
#endif  // defined(__ANDROID__)
}

TfLiteDelegatePtr CreateNNAPIDelegate(StatefulNnApiDelegate::Options options) {
#if defined(__ANDROID__)
  return TfLiteDelegatePtr(
      new StatefulNnApiDelegate(options), [](TfLiteDelegate* delegate) {
        delete reinterpret_cast<StatefulNnApiDelegate*>(delegate);
      });
#else
  return tools::CreateNullDelegate();
#endif  // defined(__ANDROID__)
}

#if TFLITE_SUPPORTS_GPU_DELEGATE
TfLiteDelegatePtr CreateGPUDelegate(TfLiteGpuDelegateOptionsV2* options) {
  return TfLiteDelegatePtr(TfLiteGpuDelegateV2Create(options),
                           &TfLiteGpuDelegateV2Delete);
}
#endif  // TFLITE_SUPPORTS_GPU_DELEGATE

TfLiteDelegatePtr CreateGPUDelegate() {
#if TFLITE_SUPPORTS_GPU_DELEGATE
  TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default();
  options.inference_priority1 = TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY;
  options.inference_preference =
      TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED;

  return CreateGPUDelegate(&options);
#else
  return tools::CreateNullDelegate();
#endif  // TFLITE_SUPPORTS_GPU_DELEGATE
}

TfLiteDelegatePtr CreateHexagonDelegate(
    const std::string& library_directory_path, bool profiling) {
#if TFLITE_ENABLE_HEXAGON
  TfLiteHexagonDelegateOptions options = {0};
  options.print_graph_profile = profiling;
  return CreateHexagonDelegate(&options, library_directory_path);
#else
  return tools::CreateNullDelegate();
#endif  // TFLITE_ENABLE_HEXAGON
}

#if TFLITE_ENABLE_HEXAGON
TfLiteDelegatePtr CreateHexagonDelegate(
    const TfLiteHexagonDelegateOptions* options,
    const std::string& library_directory_path) {
  if (library_directory_path.empty()) {
    TfLiteHexagonInit();
  } else {
    TfLiteHexagonInitWithPath(library_directory_path.c_str());
  }

  TfLiteDelegate* delegate = TfLiteHexagonDelegateCreate(options);
  if (!delegate) {
    TfLiteHexagonTearDown();
    return tools::CreateNullDelegate();
  }
  return TfLiteDelegatePtr(delegate, [](TfLiteDelegate* delegate) {
    TfLiteHexagonDelegateDelete(delegate);
    TfLiteHexagonTearDown();
  });
}
#endif  // TFLITE_ENABLE_HEXAGON

#if defined(__s390x__) || defined(TFLITE_WITHOUT_XNNPACK)
TfLiteDelegatePtr CreateXNNPACKDelegate(int num_threads) {
  return tools::CreateNullDelegate();
}
#else
TfLiteDelegatePtr CreateXNNPACKDelegate() {
  TfLiteXNNPackDelegateOptions xnnpack_options =
      TfLiteXNNPackDelegateOptionsDefault();
  return CreateXNNPACKDelegate(&xnnpack_options);
}

TfLiteDelegatePtr CreateXNNPACKDelegate(
    const TfLiteXNNPackDelegateOptions* xnnpack_options) {
  auto xnnpack_delegate = TfLiteXNNPackDelegateCreate(xnnpack_options);
  return TfLiteDelegatePtr(xnnpack_delegate, [](TfLiteDelegate* delegate) {
    TfLiteXNNPackDelegateDelete(delegate);
  });
}

TfLiteDelegatePtr CreateXNNPACKDelegate(int num_threads) {
  auto opts = TfLiteXNNPackDelegateOptionsDefault();
  // Note that we don't want to use the thread pool for num_threads == 1.
  opts.num_threads = num_threads > 1 ? num_threads : 0;
  return CreateXNNPACKDelegate(&opts);
}
#endif  // defined(__s390x__) || defined(TFLITE_WITHOUT_XNNPACK)

TfLiteDelegatePtr CreateCoreMlDelegate() {
#ifdef REAL_IPHONE_DEVICE
  TfLiteCoreMlDelegateOptions coreml_options = {
      .enabled_devices = TfLiteCoreMlDelegateAllDevices};
  TfLiteDelegate* delegate = TfLiteCoreMlDelegateCreate(&coreml_options);
  if (!delegate) {
    return tools::CreateNullDelegate();
  }
  return TfLiteDelegatePtr(delegate, &TfLiteCoreMlDelegateDelete);
#else
  return tools::CreateNullDelegate();
#endif  // REAL_IPHONE_DEVICE
}

}  // namespace evaluation
}  // namespace tflite
<|endoftext|>


<commit_before>//   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/fluid/framework/channel.h"
#include "paddle/fluid/operators/reader/reader_op_registry.h"

namespace paddle {
namespace operators {
namespace reader {

class MultiFileReader : public framework::ReaderBase {
 public:
  MultiFileReader(const std::vector<std::string>& file_names,
                  const std::vector<framework::DDim>& dims, size_t thread_num,
                  size_t buffer_size)
      : file_names_(file_names), dims_(dims), buffer_size_(buffer_size) {
    prefetchers_.resize(thread_num);
    StartNewScheduler();
  }

  void ReadNext(std::vector<framework::LoDTensor>* out) override;
  void ReInit() override;

  ~MultiFileReader() { EndScheduler(); }

 private:
  bool HasNext();
  void StartNewScheduler();
  void EndScheduler();
  void ScheduleThreadFunc();
  void PrefetchThreadFunc(std::string file_name, size_t thread_idx);

  std::vector<std::string> file_names_;
  std::vector<framework::DDim> dims_;
  std::thread scheduler_;
  std::vector<std::thread> prefetchers_;
  size_t buffer_size_;
  framework::Channel<size_t>* waiting_file_idx_;
  framework::Channel<size_t>* available_thread_idx_;
  framework::Channel<std::vector<framework::LoDTensor>>* buffer_;
};

void MultiFileReader::ReadNext(std::vector<framework::LoDTensor>* out) {
  out->clear();
  if (HasNext()) {
    buffer_->Receive(out);
  }
}

void MultiFileReader::ReInit() {
  EndScheduler();
  StartNewScheduler();
}

bool MultiFileReader::HasNext() {
  while (!buffer_->IsClosed() && !buffer_->CanReceive()) {
  }
  return buffer_->CanReceive();
}

void MultiFileReader::StartNewScheduler() {
  size_t thread_num = prefetchers_.size();
  waiting_file_idx_ = framework::MakeChannel<size_t>(file_names_.size());
  available_thread_idx_ = framework::MakeChannel<size_t>(thread_num);
  buffer_ =
      framework::MakeChannel<std::vector<framework::LoDTensor>>(buffer_size_);

  for (size_t i = 0; i < file_names_.size(); ++i) {
    waiting_file_idx_->Send(&i);
  }
  waiting_file_idx_->Close();
  for (size_t i = 0; i < thread_num; ++i) {
    available_thread_idx_->Send(&i);
  }

  scheduler_ = std::thread([this] { ScheduleThreadFunc(); });
}

void MultiFileReader::EndScheduler() {
  available_thread_idx_->Close();
  buffer_->Close();
  waiting_file_idx_->Close();
  if (scheduler_.joinable()) {
    scheduler_.join();
  }
  delete buffer_;
  delete available_thread_idx_;
  delete waiting_file_idx_;
}

void MultiFileReader::ScheduleThreadFunc() {
  VLOG(5) << "MultiFileReader schedule thread starts.";
  size_t completed_thread_num = 0;
  size_t thread_idx;
  while (available_thread_idx_->Receive(&thread_idx)) {
    std::thread& prefetcher = prefetchers_[thread_idx];
    if (prefetcher.joinable()) {
      prefetcher.join();
    }
    size_t file_idx;
    if (waiting_file_idx_->Receive(&file_idx)) {
      // Still have files to read. Start a new prefetch thread.
      std::string file_name = file_names_[file_idx];
      prefetcher = std::thread([this, file_name, thread_idx] {
        PrefetchThreadFunc(file_name, thread_idx);
      });
    } else {
      // No more file to read.
      ++completed_thread_num;
      if (completed_thread_num == prefetchers_.size()) {
        buffer_->Close();
        break;
      }
    }
  }
  // If users invoke ReInit() when scheduler is running, it will close the
  // 'avaiable_thread_idx_' and prefecther threads have no way to tell scheduler
  // to release their resource. So a check is needed before scheduler ends.
  for (auto& p : prefetchers_) {
    if (p.joinable()) {
      p.join();
    }
  }
  VLOG(5) << "MultiFileReader schedule thread terminates.";
}

void MultiFileReader::PrefetchThreadFunc(std::string file_name,
                                         size_t thread_idx) {
  VLOG(5) << "The prefetch thread of file '" << file_name << "' starts.";
  std::unique_ptr<framework::ReaderBase> reader =
      CreateReaderByFileName(file_name, dims_);
  while (true) {
    std::vector<framework::LoDTensor> ins;
    reader->ReadNext(&ins);
    if (ins.empty()) {
      break;
    }
    try {
      buffer_->Send(&ins);
    } catch (paddle::platform::EnforceNotMet e) {
      VLOG(5) << "WARNING: The buffer channel has been closed. The prefetch "
                 "thread of file '"
              << file_name << "' will terminate.";
      break;
    }
  }

  try {
    available_thread_idx_->Send(&thread_idx);
  } catch (paddle::platform::EnforceNotMet e) {
    VLOG(5) << "WARNING: The available_thread_idx_ channel has been closed. "
               "Fail to send thread_idx.";
  }
  VLOG(5) << "The prefetch thread of file '" << file_name << "' terminates.";
}

class OpenFilesOp : public framework::OperatorBase {
 public:
  using framework::OperatorBase::OperatorBase;

 private:
  void RunImpl(const framework::Scope& scope,
               const platform::Place& dev_place) const override {
    const auto& shape_concat = Attr<std::vector<int>>("shape_concat");
    const auto& ranks = Attr<std::vector<int>>("ranks");
    PADDLE_ENFORCE(!shape_concat.empty() && !ranks.empty());
    PADDLE_ENFORCE_EQ(std::accumulate(ranks.begin(), ranks.end(), 0),
                      static_cast<int>(shape_concat.size()),
                      "The accumulate of all ranks should be equal to the "
                      "shape concat's length.");
    const auto& file_names = Attr<std::vector<std::string>>("file_names");
    PADDLE_ENFORCE(!file_names.empty(), "No file to be read!");
    const size_t thread_num = Attr<int>("thread_num");
    const size_t buffer_size = Attr<int>("buffer_size");

    auto* out = scope.FindVar(Output("Out"))
                    ->template GetMutable<framework::ReaderHolder>();
    out->Reset(new MultiFileReader(file_names,
                                   RestoreShapes(shape_concat, ranks),
                                   thread_num, buffer_size));
  }
};

class OpenFilesOpMaker : public FileReaderMakerBase {
 public:
  OpenFilesOpMaker(OpProto* op_proto, OpAttrChecker* op_checker)
      : FileReaderMakerBase(op_proto, op_checker) {
    AddAttr<std::vector<std::string>>("file_names", "Files to be read.");
    AddAttr<int>("thread_num", "The maximal concurrent prefetch thread number.")
        .GreaterThan(0);
    AddAttr<int>("buffer_size", "The size of prefetch buffer.").GreaterThan(0);

    AddComment(R"DOC(
      OpenFiles Operator

      An OpenFilesOp creates a MultiFileReader, which is able to
      read data multi-threaded from multiple files.
    )DOC");
  }
};

}  // namespace reader
}  // namespace operators
}  // namespace paddle

namespace reader = paddle::operators::reader;

REGISTER_FILE_READER_OPERATOR(open_files, reader::OpenFilesOp,
                              reader::OpenFilesOpMaker);
<commit_msg>Remove Readers' HasNext()<commit_after>//   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <thread>  // NOLINT

#include "paddle/fluid/framework/channel.h"
#include "paddle/fluid/operators/reader/reader_op_registry.h"

namespace paddle {
namespace operators {
namespace reader {

class MultiFileReader : public framework::ReaderBase {
 public:
  MultiFileReader(const std::vector<std::string>& file_names,
                  const std::vector<framework::DDim>& dims, size_t thread_num,
                  size_t buffer_size)
      : file_names_(file_names), dims_(dims), buffer_size_(buffer_size) {
    prefetchers_.resize(thread_num);
    StartNewScheduler();
  }

  void ReadNext(std::vector<framework::LoDTensor>* out) override;
  void ReInit() override;

  ~MultiFileReader() { EndScheduler(); }

 private:
  bool HasNext();
  void StartNewScheduler();
  void EndScheduler();
  void ScheduleThreadFunc();
  void PrefetchThreadFunc(std::string file_name, size_t thread_idx);

  std::vector<std::string> file_names_;
  std::vector<framework::DDim> dims_;
  std::thread scheduler_;
  std::vector<std::thread> prefetchers_;
  size_t buffer_size_;
  framework::Channel<size_t>* waiting_file_idx_;
  framework::Channel<size_t>* available_thread_idx_;
  framework::Channel<std::vector<framework::LoDTensor>>* buffer_;
};

void MultiFileReader::ReadNext(std::vector<framework::LoDTensor>* out) {
  out->clear();
  if (HasNext()) {
    buffer_->Receive(out);
  }
}

void MultiFileReader::ReInit() {
  EndScheduler();
  StartNewScheduler();
}

bool MultiFileReader::HasNext() {
  while (!buffer_->IsClosed() && !buffer_->CanReceive()) {
  }
  return buffer_->CanReceive();
}

void MultiFileReader::StartNewScheduler() {
  size_t thread_num = prefetchers_.size();
  waiting_file_idx_ = framework::MakeChannel<size_t>(file_names_.size());
  available_thread_idx_ = framework::MakeChannel<size_t>(thread_num);
  buffer_ =
      framework::MakeChannel<std::vector<framework::LoDTensor>>(buffer_size_);

  for (size_t i = 0; i < file_names_.size(); ++i) {
    waiting_file_idx_->Send(&i);
  }
  waiting_file_idx_->Close();
  for (size_t i = 0; i < thread_num; ++i) {
    available_thread_idx_->Send(&i);
  }

  scheduler_ = std::thread([this] { ScheduleThreadFunc(); });
}

void MultiFileReader::EndScheduler() {
  available_thread_idx_->Close();
  buffer_->Close();
  waiting_file_idx_->Close();
  if (scheduler_.joinable()) {
    scheduler_.join();
  }
  delete buffer_;
  delete available_thread_idx_;
  delete waiting_file_idx_;
}

void MultiFileReader::ScheduleThreadFunc() {
  VLOG(5) << "MultiFileReader schedule thread starts.";
  size_t completed_thread_num = 0;
  size_t thread_idx;
  while (available_thread_idx_->Receive(&thread_idx)) {
    std::thread& prefetcher = prefetchers_[thread_idx];
    if (prefetcher.joinable()) {
      prefetcher.join();
    }
    size_t file_idx;
    if (waiting_file_idx_->Receive(&file_idx)) {
      // Still have files to read. Start a new prefetch thread.
      std::string file_name = file_names_[file_idx];
      prefetcher = std::thread([this, file_name, thread_idx] {
        PrefetchThreadFunc(file_name, thread_idx);
      });
    } else {
      // No more file to read.
      ++completed_thread_num;
      if (completed_thread_num == prefetchers_.size()) {
        buffer_->Close();
        break;
      }
    }
  }
  // If users invoke ReInit() when scheduler is running, it will close the
  // 'avaiable_thread_idx_' and prefecther threads have no way to tell scheduler
  // to release their resource. So a check is needed before scheduler ends.
  for (auto& p : prefetchers_) {
    if (p.joinable()) {
      p.join();
    }
  }
  VLOG(5) << "MultiFileReader schedule thread terminates.";
}

void MultiFileReader::PrefetchThreadFunc(std::string file_name,
                                         size_t thread_idx) {
  VLOG(5) << "The prefetch thread of file '" << file_name << "' starts.";
  std::unique_ptr<framework::ReaderBase> reader =
      CreateReaderByFileName(file_name, dims_);
  while (true) {
    std::vector<framework::LoDTensor> ins;
    reader->ReadNext(&ins);
    if (ins.empty()) {
      break;
    }
    try {
      buffer_->Send(&ins);
    } catch (paddle::platform::EnforceNotMet e) {
      VLOG(5) << "WARNING: The buffer channel has been closed. The prefetch "
                 "thread of file '"
              << file_name << "' will terminate.";
      break;
    }
  }

  try {
    available_thread_idx_->Send(&thread_idx);
  } catch (paddle::platform::EnforceNotMet e) {
    VLOG(5) << "WARNING: The available_thread_idx_ channel has been closed. "
               "Fail to send thread_idx.";
  }
  VLOG(5) << "The prefetch thread of file '" << file_name << "' terminates.";
}

class OpenFilesOp : public framework::OperatorBase {
 public:
  using framework::OperatorBase::OperatorBase;

 private:
  void RunImpl(const framework::Scope& scope,
               const platform::Place& dev_place) const override {
    const auto& shape_concat = Attr<std::vector<int>>("shape_concat");
    const auto& ranks = Attr<std::vector<int>>("ranks");
    PADDLE_ENFORCE(!shape_concat.empty() && !ranks.empty());
    PADDLE_ENFORCE_EQ(std::accumulate(ranks.begin(), ranks.end(), 0),
                      static_cast<int>(shape_concat.size()),
                      "The accumulate of all ranks should be equal to the "
                      "shape concat's length.");
    const auto& file_names = Attr<std::vector<std::string>>("file_names");
    PADDLE_ENFORCE(!file_names.empty(), "No file to be read!");
    const size_t thread_num = Attr<int>("thread_num");
    const size_t buffer_size = Attr<int>("buffer_size");

    auto* out = scope.FindVar(Output("Out"))
                    ->template GetMutable<framework::ReaderHolder>();
    out->Reset(new MultiFileReader(file_names,
                                   RestoreShapes(shape_concat, ranks),
                                   thread_num, buffer_size));
  }
};

class OpenFilesOpMaker : public FileReaderMakerBase {
 public:
  OpenFilesOpMaker(OpProto* op_proto, OpAttrChecker* op_checker)
      : FileReaderMakerBase(op_proto, op_checker) {
    AddAttr<std::vector<std::string>>("file_names", "Files to be read.");
    AddAttr<int>("thread_num", "The maximal concurrent prefetch thread number.")
        .GreaterThan(0);
    AddAttr<int>("buffer_size", "The size of prefetch buffer.").GreaterThan(0);

    AddComment(R"DOC(
      OpenFiles Operator

      An OpenFilesOp creates a MultiFileReader, which is able to
      read data multi-threaded from multiple files.
    )DOC");
  }
};

}  // namespace reader
}  // namespace operators
}  // namespace paddle

namespace reader = paddle::operators::reader;

REGISTER_FILE_READER_OPERATOR(open_files, reader::OpenFilesOp,
                              reader::OpenFilesOpMaker);
<|endoftext|>


<commit_before>/* This file is part of the KDE libraries
   Copyright (C) 2010 Dominik Haumann <dhaumann kde org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "hlselectionplugin.h"
#include "hlselectionplugin.moc"

#include <ktexteditor/document.h>
#include <ktexteditor/attribute.h>
#include <ktexteditor/searchinterface.h>
#include <ktexteditor/movinginterface.h>
#include <ktexteditor/movingrange.h>

#include <assert.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kfiledialog.h>
#include <kpluginfactory.h>
#include <kpluginloader.h>
#include <klocale.h>
#include <kaboutdata.h>

K_PLUGIN_FACTORY( HighlightSelectionPluginFactory, registerPlugin<HighlightSelectionPlugin>(); )
K_EXPORT_PLUGIN( HighlightSelectionPluginFactory( KAboutData( "ktexteditor_insertfile", "ktexteditor_plugins", ki18n("Highlight Selection"), "1.0", ki18n("Highlight Selection"), KAboutData::License_LGPL_V2 ) ) )

//BEGIN HighlightSelectionPlugin
HighlightSelectionPlugin::HighlightSelectionPlugin( QObject *parent, const QVariantList& )
  : KTextEditor::Plugin ( parent )
{
}

HighlightSelectionPlugin::~HighlightSelectionPlugin()
{
}

void HighlightSelectionPlugin::addView(KTextEditor::View *view)
{
  HighlightSelectionPluginView *nview = new HighlightSelectionPluginView (view);
  m_views.append (nview);
}

void HighlightSelectionPlugin::removeView(KTextEditor::View *view)
{
  foreach (HighlightSelectionPluginView *pluginView, m_views) {
    if (pluginView->view() == view) {
      m_views.removeAll(pluginView);
      delete pluginView;
      break;
    }
  }
}
//END HighlightSelectionPlugin

//BEGIN HighlightSelectionPluginView
HighlightSelectionPluginView::HighlightSelectionPluginView( KTextEditor::View *view)
  : QObject( view )
//   , KXMLGUIClient( view ) // XMLGUI stuff not needed right now
{
  setObjectName("highlight-selection-plugin");

  m_view = view;

  // we don't need any XMLGUI stuff, so comment out
//  setComponentData( HighlightSelectionPluginFactory::componentData() );
//  setXMLFile( "ktexteditor_hlselectionui.rc" );

  connect(view, SIGNAL(selectionChanged(KTextEditor::View*)), this, SLOT(selectionChanged()));
  connect(view->document(), SIGNAL(aboutToReload(KTextEditor::Document*)), this, SLOT(clearHighlights()));
}

HighlightSelectionPluginView::~HighlightSelectionPluginView()
{
  clearHighlights();
}

KTextEditor::View* HighlightSelectionPluginView::view() const
{
  return m_view;
}

void HighlightSelectionPluginView::clearHighlights()
{
  qDeleteAll(m_ranges);
  m_ranges.clear();
  m_currentText.clear();
}

void HighlightSelectionPluginView::selectionChanged()
{
  QString text;
  // if text of selection is still the same, abort
  if (m_view->selection() && m_view->selectionRange().onSingleLine()) {
    text = m_view->selectionText();
    if (text == m_currentText) {
      return;
    }
  }

  // text changed: remove all highlights + create new ones
  // (do not call clearHighlights(), since this also resets the m_currentText
  qDeleteAll(m_ranges);
  m_ranges.clear();

  // do not highlight strings with leading and trailing spaces
  if (!text.isEmpty() && (text.at(0).isSpace() || text.at(text.length()-1).isSpace())) {
    return;
  }

  m_currentText = text;
  if (!m_currentText.isEmpty()) {
    createHighlights();
  }
}

void HighlightSelectionPluginView::createHighlights()
{
  m_currentText = m_view->selectionText();

  KTextEditor::SearchInterface* siface =
    qobject_cast<KTextEditor::SearchInterface*>(m_view->document());

  if (!siface) {
    return;
  }

  KTextEditor::MovingInterface* miface =
    qobject_cast<KTextEditor::MovingInterface*>(m_view->document());

  KTextEditor::Attribute::Ptr attr(new KTextEditor::Attribute());
  attr->setFontBold(true);
  attr->setBackground(Qt::yellow);

  KTextEditor::Cursor start(0, 0);
  KTextEditor::Range searchRange;

  QVector<KTextEditor::Range> matches;

  do {
    searchRange.setRange(start, m_view->document()->documentEnd());

    matches = siface->searchText(searchRange, m_currentText, KTextEditor::Search::WholeWords);

    if (matches.first().isValid()) {
      KTextEditor::MovingRange* mr = miface->newMovingRange(matches.first());
      mr->setAttribute(attr);
      mr->setView(m_view);
      mr->setAttributeOnlyForViews(true);
      m_ranges.append(mr);
      start = matches.first().end();
    }
  } while (matches.first().isValid());
}
//END HighlightSelectionPluginView

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>SVN commit 1210354 by zwabel:<commit_after>/* This file is part of the KDE libraries
   Copyright (C) 2010 Dominik Haumann <dhaumann kde org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#include "hlselectionplugin.h"
#include "hlselectionplugin.moc"

#include <ktexteditor/document.h>
#include <ktexteditor/attribute.h>
#include <ktexteditor/searchinterface.h>
#include <ktexteditor/movinginterface.h>
#include <ktexteditor/movingrange.h>

#include <assert.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kfiledialog.h>
#include <kpluginfactory.h>
#include <kpluginloader.h>
#include <klocale.h>
#include <kaboutdata.h>

K_PLUGIN_FACTORY( HighlightSelectionPluginFactory, registerPlugin<HighlightSelectionPlugin>(); )
K_EXPORT_PLUGIN( HighlightSelectionPluginFactory( KAboutData( "ktexteditor_insertfile", "ktexteditor_plugins", ki18n("Highlight Selection"), "1.0", ki18n("Highlight Selection"), KAboutData::License_LGPL_V2 ) ) )

//BEGIN HighlightSelectionPlugin
HighlightSelectionPlugin::HighlightSelectionPlugin( QObject *parent, const QVariantList& )
  : KTextEditor::Plugin ( parent )
{
}

HighlightSelectionPlugin::~HighlightSelectionPlugin()
{
}

void HighlightSelectionPlugin::addView(KTextEditor::View *view)
{
  HighlightSelectionPluginView *nview = new HighlightSelectionPluginView (view);
  m_views.append (nview);
}

void HighlightSelectionPlugin::removeView(KTextEditor::View *view)
{
  foreach (HighlightSelectionPluginView *pluginView, m_views) {
    if (pluginView->view() == view) {
      m_views.removeAll(pluginView);
      delete pluginView;
      break;
    }
  }
}
//END HighlightSelectionPlugin

//BEGIN HighlightSelectionPluginView
HighlightSelectionPluginView::HighlightSelectionPluginView( KTextEditor::View *view)
  : QObject( view )
//   , KXMLGUIClient( view ) // XMLGUI stuff not needed right now
{
  setObjectName("highlight-selection-plugin");

  m_view = view;

  // we don't need any XMLGUI stuff, so comment out
//  setComponentData( HighlightSelectionPluginFactory::componentData() );
//  setXMLFile( "ktexteditor_hlselectionui.rc" );

  connect(view, SIGNAL(selectionChanged(KTextEditor::View*)), this, SLOT(selectionChanged()));
  connect(view->document(), SIGNAL(aboutToReload(KTextEditor::Document*)), this, SLOT(clearHighlights()));
}

HighlightSelectionPluginView::~HighlightSelectionPluginView()
{
  clearHighlights();
}

KTextEditor::View* HighlightSelectionPluginView::view() const
{
  return m_view;
}

void HighlightSelectionPluginView::clearHighlights()
{
  qDeleteAll(m_ranges);
  m_ranges.clear();
  m_currentText.clear();
}

void HighlightSelectionPluginView::selectionChanged()
{
  QString text;
  // if text of selection is still the same, abort
  if (m_view->selection() && m_view->selectionRange().onSingleLine()) {
    text = m_view->selectionText();
    if (text == m_currentText) {
      return;
    }
  }

  // text changed: remove all highlights + create new ones
  // (do not call clearHighlights(), since this also resets the m_currentText
  qDeleteAll(m_ranges);
  m_ranges.clear();

  // do not highlight strings with leading and trailing spaces
  if (!text.isEmpty() && (text.at(0).isSpace() || text.at(text.length()-1).isSpace())) {
    return;
  }

  m_currentText = text;
  if (!m_currentText.isEmpty()) {
    createHighlights();
  }
}

void HighlightSelectionPluginView::createHighlights()
{
  m_currentText = m_view->selectionText();

  KTextEditor::SearchInterface* siface =
    qobject_cast<KTextEditor::SearchInterface*>(m_view->document());

  if (!siface) {
    return;
  }

  KTextEditor::MovingInterface* miface =
    qobject_cast<KTextEditor::MovingInterface*>(m_view->document());

  KTextEditor::Attribute::Ptr attr(new KTextEditor::Attribute());
  attr->setFontBold(true);
  attr->setBackground(Qt::yellow);

  KTextEditor::Cursor start(0, 0);
  KTextEditor::Range searchRange;

  QVector<KTextEditor::Range> matches;

  do {
    searchRange.setRange(start, m_view->document()->documentEnd());

    matches = siface->searchText(searchRange, m_currentText, KTextEditor::Search::WholeWords);

    if (matches.first().isValid()) {
      KTextEditor::MovingRange* mr = miface->newMovingRange(matches.first());
      mr->setAttribute(attr);
      mr->setView(m_view);
      mr->setZDepth(-90000.0); // Set the z-depth to slightly worse than the selection
      mr->setAttributeOnlyForViews(true);
      m_ranges.append(mr);
      start = matches.first().end();
    }
  } while (matches.first().isValid());
}
//END HighlightSelectionPluginView

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>#include <iostream>
#include <boost/numeric/odeint.hpp>
#include <vexcl/generator/symbolic.hpp>

namespace odeint = boost::numeric::odeint;

typedef double value_type;
typedef vex::generator::symbolic<value_type> state_type;

namespace boost { namespace numeric { namespace odeint {

template<>
struct is_resizeable< state_type > : boost::true_type { };

template<>
struct resize_impl< state_type , state_type >
{
    static void resize( state_type &x1 , const state_type &x2 )
    {
    }
};

template<>
struct same_size_impl< state_type , state_type >
{
    static bool same_size( const state_type &x1 , const state_type &x2 )
    {
        return true;
    }
};

} } }

void sys_func(const state_type &x, state_type &dxdt, value_type t) {
    dxdt = x;
}

int main() {
    state_type::set_output(std::cout);

    state_type x(false);

    odeint::runge_kutta4<
	    state_type , value_type , state_type , value_type ,
	    odeint::vector_space_algebra, odeint::default_operations
	    > stepper;

    odeint::integrate_const( stepper, sys_func, x , 0.0 , 0.1 , 0.1 );
}
<commit_msg>error in sys_func<commit_after>#include <iostream>
#include <boost/numeric/odeint.hpp>
#include <vexcl/generator/symbolic.hpp>

namespace odeint = boost::numeric::odeint;

typedef double value_type;
typedef vex::generator::symbolic<value_type> state_type;

namespace boost { namespace numeric { namespace odeint {

template<>
struct is_resizeable< state_type > : boost::true_type { };

template<>
struct resize_impl< state_type , state_type >
{
    static void resize( state_type &x1 , const state_type &x2 )
    {
    }
};

template<>
struct same_size_impl< state_type , state_type >
{
    static bool same_size( const state_type &x1 , const state_type &x2 )
    {
        return true;
    }
};

} } }

void sys_func(const state_type &x, state_type &dxdt, value_type t) {
    dxdt = 42 * x;
}

int main() {
    state_type::set_output(std::cout);

    state_type x(false);

    odeint::runge_kutta4<
	    state_type , value_type , state_type , value_type ,
	    odeint::vector_space_algebra, odeint::default_operations
	    > stepper;

    odeint::integrate_const( stepper, sys_func, x , 0.0 , 0.1 , 0.1 );
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "device.h"
#include "integrator.h"
#include "light.h"
#include "scene.h"
#include "sobol.h"

#include "util_foreach.h"
#include "util_hash.h"

CCL_NAMESPACE_BEGIN

Integrator::Integrator()
{
	min_bounce = 2;
	max_bounce = 7;

	max_diffuse_bounce = max_bounce;
	max_glossy_bounce = max_bounce;
	max_transmission_bounce = max_bounce;
	probalistic_termination = true;

	transparent_min_bounce = min_bounce;
	transparent_max_bounce = max_bounce;
	transparent_probalistic = true;
	transparent_shadows = false;

	no_caustics = false;
	filter_glossy = 0.0f;
	seed = 0;
	layer_flag = ~0;
	sample_clamp = 0.0f;
	motion_blur = false;

	diffuse_samples = 1;
	glossy_samples = 1;
	transmission_samples = 1;
	ao_samples = 1;
	mesh_light_samples = 1;
	progressive = true;

	need_update = true;
}

Integrator::~Integrator()
{
}

void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
	if(!need_update)
		return;

	device_free(device, dscene);

	KernelIntegrator *kintegrator = &dscene->data.integrator;

	/* integrator parameters */
	kintegrator->max_bounce = max_bounce + 1;
	if(probalistic_termination)
		kintegrator->min_bounce = min_bounce + 1;
	else
		kintegrator->min_bounce = kintegrator->max_bounce;

	kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
	kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
	kintegrator->max_transmission_bounce = max_transmission_bounce + 1;

	kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
	if(transparent_probalistic)
		kintegrator->transparent_min_bounce = transparent_min_bounce + 1;
	else
		kintegrator->transparent_min_bounce = kintegrator->transparent_max_bounce;

	kintegrator->transparent_shadows = transparent_shadows;

	kintegrator->no_caustics = no_caustics;
	kintegrator->filter_glossy = (filter_glossy == 0.0f)? FLT_MAX: 1.0f/filter_glossy;

	kintegrator->seed = hash_int(seed);
	kintegrator->layer_flag = layer_flag << PATH_RAY_LAYER_SHIFT;

	kintegrator->use_ambient_occlusion =
		((dscene->data.film.pass_flag & PASS_AO) || dscene->data.background.ao_factor != 0.0f);

	kintegrator->sample_clamp = (sample_clamp == 0.0f)? FLT_MAX: sample_clamp*3.0f;

	kintegrator->progressive = progressive;
	kintegrator->diffuse_samples = diffuse_samples;
	kintegrator->glossy_samples = glossy_samples;
	kintegrator->transmission_samples = transmission_samples;
	kintegrator->ao_samples = ao_samples;
	kintegrator->mesh_light_samples = mesh_light_samples;

	/* sobol directions table */
	int max_samples = 1;

	if(!progressive) {
		foreach(Light *light, scene->lights)
			max_samples = max(max_samples, light->samples);

		max_samples = max(max_samples, max(diffuse_samples, max(glossy_samples, transmission_samples)));
		max_samples = max(max_samples, max(ao_samples, mesh_light_samples));
	}

	max_samples *= (max_bounce + transparent_max_bounce + 2);

	int dimensions = PRNG_BASE_NUM + max_samples*PRNG_BOUNCE_NUM;
	uint *directions = dscene->sobol_directions.resize(SOBOL_BITS*dimensions);

	sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);

	device->tex_alloc("__sobol_directions", dscene->sobol_directions);

	need_update = false;
}

void Integrator::device_free(Device *device, DeviceScene *dscene)
{
	device->tex_free(dscene->sobol_directions);
	dscene->sobol_directions.clear();
}

bool Integrator::modified(const Integrator& integrator)
{
	return !(min_bounce == integrator.min_bounce &&
		max_bounce == integrator.max_bounce &&
		max_diffuse_bounce == integrator.max_diffuse_bounce &&
		max_glossy_bounce == integrator.max_glossy_bounce &&
		max_transmission_bounce == integrator.max_transmission_bounce &&
		probalistic_termination == integrator.probalistic_termination &&
		transparent_min_bounce == integrator.transparent_min_bounce &&
		transparent_max_bounce == integrator.transparent_max_bounce &&
		transparent_probalistic == integrator.transparent_probalistic &&
		transparent_shadows == integrator.transparent_shadows &&
		no_caustics == integrator.no_caustics &&
		filter_glossy == integrator.filter_glossy &&
		layer_flag == integrator.layer_flag &&
		seed == integrator.seed &&
		sample_clamp == integrator.sample_clamp &&
		progressive == integrator.progressive &&
		diffuse_samples == integrator.diffuse_samples &&
		glossy_samples == integrator.glossy_samples &&
		transmission_samples == integrator.transmission_samples &&
		ao_samples == integrator.ao_samples &&
		mesh_light_samples == integrator.mesh_light_samples &&
		motion_blur == integrator.motion_blur);
}

void Integrator::tag_update(Scene *scene)
{
	need_update = true;
}

CCL_NAMESPACE_END

<commit_msg>Fix #32018: non-progressive integrator crash.<commit_after>/*
 * Copyright 2011, Blender Foundation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "device.h"
#include "integrator.h"
#include "light.h"
#include "scene.h"
#include "sobol.h"

#include "util_foreach.h"
#include "util_hash.h"

CCL_NAMESPACE_BEGIN

Integrator::Integrator()
{
	min_bounce = 2;
	max_bounce = 7;

	max_diffuse_bounce = max_bounce;
	max_glossy_bounce = max_bounce;
	max_transmission_bounce = max_bounce;
	probalistic_termination = true;

	transparent_min_bounce = min_bounce;
	transparent_max_bounce = max_bounce;
	transparent_probalistic = true;
	transparent_shadows = false;

	no_caustics = false;
	filter_glossy = 0.0f;
	seed = 0;
	layer_flag = ~0;
	sample_clamp = 0.0f;
	motion_blur = false;

	diffuse_samples = 1;
	glossy_samples = 1;
	transmission_samples = 1;
	ao_samples = 1;
	mesh_light_samples = 1;
	progressive = true;

	need_update = true;
}

Integrator::~Integrator()
{
}

void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
	if(!need_update)
		return;

	device_free(device, dscene);

	KernelIntegrator *kintegrator = &dscene->data.integrator;

	/* integrator parameters */
	kintegrator->max_bounce = max_bounce + 1;
	if(probalistic_termination)
		kintegrator->min_bounce = min_bounce + 1;
	else
		kintegrator->min_bounce = kintegrator->max_bounce;

	kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
	kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
	kintegrator->max_transmission_bounce = max_transmission_bounce + 1;

	kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
	if(transparent_probalistic)
		kintegrator->transparent_min_bounce = transparent_min_bounce + 1;
	else
		kintegrator->transparent_min_bounce = kintegrator->transparent_max_bounce;

	kintegrator->transparent_shadows = transparent_shadows;

	kintegrator->no_caustics = no_caustics;
	kintegrator->filter_glossy = (filter_glossy == 0.0f)? FLT_MAX: 1.0f/filter_glossy;

	kintegrator->seed = hash_int(seed);
	kintegrator->layer_flag = layer_flag << PATH_RAY_LAYER_SHIFT;

	kintegrator->use_ambient_occlusion =
		((dscene->data.film.pass_flag & PASS_AO) || dscene->data.background.ao_factor != 0.0f);

	kintegrator->sample_clamp = (sample_clamp == 0.0f)? FLT_MAX: sample_clamp*3.0f;

	kintegrator->progressive = progressive;
	kintegrator->diffuse_samples = diffuse_samples;
	kintegrator->glossy_samples = glossy_samples;
	kintegrator->transmission_samples = transmission_samples;
	kintegrator->ao_samples = ao_samples;
	kintegrator->mesh_light_samples = mesh_light_samples;

	/* sobol directions table */
	int max_samples = 1;

	if(!progressive) {
		foreach(Light *light, scene->lights)
			max_samples = max(max_samples, light->samples);

		max_samples = max(max_samples, max(diffuse_samples, max(glossy_samples, transmission_samples)));
		max_samples = max(max_samples, max(ao_samples, mesh_light_samples));
	}

	max_samples *= (max_bounce + transparent_max_bounce + 2);

	int dimensions = PRNG_BASE_NUM + max_samples*PRNG_BOUNCE_NUM;
	dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);

	uint *directions = dscene->sobol_directions.resize(SOBOL_BITS*dimensions);

	sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);

	device->tex_alloc("__sobol_directions", dscene->sobol_directions);

	need_update = false;
}

void Integrator::device_free(Device *device, DeviceScene *dscene)
{
	device->tex_free(dscene->sobol_directions);
	dscene->sobol_directions.clear();
}

bool Integrator::modified(const Integrator& integrator)
{
	return !(min_bounce == integrator.min_bounce &&
		max_bounce == integrator.max_bounce &&
		max_diffuse_bounce == integrator.max_diffuse_bounce &&
		max_glossy_bounce == integrator.max_glossy_bounce &&
		max_transmission_bounce == integrator.max_transmission_bounce &&
		probalistic_termination == integrator.probalistic_termination &&
		transparent_min_bounce == integrator.transparent_min_bounce &&
		transparent_max_bounce == integrator.transparent_max_bounce &&
		transparent_probalistic == integrator.transparent_probalistic &&
		transparent_shadows == integrator.transparent_shadows &&
		no_caustics == integrator.no_caustics &&
		filter_glossy == integrator.filter_glossy &&
		layer_flag == integrator.layer_flag &&
		seed == integrator.seed &&
		sample_clamp == integrator.sample_clamp &&
		progressive == integrator.progressive &&
		diffuse_samples == integrator.diffuse_samples &&
		glossy_samples == integrator.glossy_samples &&
		transmission_samples == integrator.transmission_samples &&
		ao_samples == integrator.ao_samples &&
		mesh_light_samples == integrator.mesh_light_samples &&
		motion_blur == integrator.motion_blur);
}

void Integrator::tag_update(Scene *scene)
{
	need_update = true;
}

CCL_NAMESPACE_END

<|endoftext|>