<commit_before>//===- MemoryDependenceAnalysis.cpp - Mem Deps Implementation  --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the Owen Anderson and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements an analysis that determines, for a given memory
// operation, what preceding memory operations it depends on.  It builds on
// alias analysis information, and tries to provide a lazy, caching interface to
// a common kind of alias information query.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetData.h"

using namespace llvm;

char MemoryDependenceAnalysis::ID = 0;

const Instruction* MemoryDependenceAnalysis::NonLocal = (Instruction*)-3;
const Instruction* MemoryDependenceAnalysis::None = (Instruction*)-4;

// Register this pass...
static RegisterPass<MemoryDependenceAnalysis> X("memdep",
                                                "Memory Dependence Analysis");

/// getAnalysisUsage - Does not modify anything.  It uses Alias Analysis.
///
void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequiredTransitive<AliasAnalysis>();
  AU.addRequiredTransitive<TargetData>();
}

// Find the dependency of a CallSite
const Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C,
                                                           Instruction* start,
                                                            BasicBlock* block) {

  AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
  TargetData& TD = getAnalysis<TargetData>();
  BasicBlock::iterator blockBegin = C.getInstruction()->getParent()->begin();
  BasicBlock::iterator QI = C.getInstruction();

  if (start) {
    QI = start;
    blockBegin = start->getParent()->end();
  } else if (!start && block) {
    QI = block->end();
    blockBegin = block->end();
  }

  while (QI != blockBegin) {
    --QI;

    // If this inst is a memory op, get the pointer it accessed
    Value* pointer = 0;
    uint64_t pointerSize = 0;
    if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
      pointer = S->getPointerOperand();
      pointerSize = TD.getTypeSize(S->getOperand(0)->getType());
    } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
      pointer = L->getPointerOperand();
      pointerSize = TD.getTypeSize(L->getType());
    } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) {
      pointer = AI;
      if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize()))
        pointerSize = C->getZExtValue() * \
                      TD.getTypeSize(AI->getAllocatedType());
      else
        pointerSize = ~0UL;
    } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) {
      pointer = V->getOperand(0);
      pointerSize = TD.getTypeSize(V->getType());
    } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
      pointer = F->getPointerOperand();

      // FreeInsts erase the entire structure
      pointerSize = ~0UL;
    } else if (CallSite::get(QI).getInstruction() != 0) {
      if (AA.getModRefInfo(C, CallSite::get(QI)) != AliasAnalysis::NoModRef) {
        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(C.getInstruction(),
                                              std::make_pair(QI, true)));
          reverseDep[QI].insert(C.getInstruction());
        }
        return QI;
      } else {
        continue;
      }
    } else
      continue;

    if (AA.getModRefInfo(C, pointer, pointerSize) != AliasAnalysis::NoModRef) {
      if (!start && !block) {
        depGraphLocal.insert(std::make_pair(C.getInstruction(),
                                            std::make_pair(QI, true)));
        reverseDep[QI].insert(C.getInstruction());
      }
      return QI;
    }
  }

  // No dependence found
  depGraphLocal.insert(std::make_pair(C.getInstruction(),
                                      std::make_pair(NonLocal, true)));
  reverseDep[NonLocal].insert(C.getInstruction());
  return NonLocal;
}

void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
                                              BasicBlock* block,
                                         DenseMap<BasicBlock*, Value*>& resp) {
  SmallPtrSet<BasicBlock*, 4> visited;
  SmallVector<BasicBlock*, 4> stack;
  stack.push_back(block);

  while (!stack.empty()) {
    BasicBlock* BB = stack.back();

    if (visited.count(BB)) {
      stack.pop_back();
      continue;
    }

    if (BB != block) {
      visited.insert(BB);

      const Instruction* localDep = getDependency(query, 0, BB);
      if (localDep != NonLocal) {
        resp.insert(std::make_pair(BB, const_cast<Instruction*>(localDep)));
        stack.pop_back();

        continue;
      }
    } else if (BB == block && stack.size() > 1) {
      visited.insert(BB);

      const Instruction* localDep = getDependency(query, 0, BB);
      if (localDep != query)
        resp.insert(std::make_pair(BB, const_cast<Instruction*>(localDep)));

      stack.pop_back();

      continue;
    }

    bool predOnStack = false;
    bool inserted = false;
    for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
         PI != PE; ++PI)
      if (!visited.count(*PI)) {
        stack.push_back(*PI);
        inserted = true;
      } else
        predOnStack = true;

    if (inserted)
      continue;
    else if (!inserted && !predOnStack) {
      resp.insert(std::make_pair(BB, const_cast<Instruction*>(None)));
    } else if (!inserted && predOnStack){
      resp.insert(std::make_pair(BB, const_cast<Instruction*>(NonLocal)));
    }

    stack.pop_back();
  }
}

/// getNonLocalDependency - Fills the passed-in map with the non-local
/// dependencies of the queries.  The map will contain NonLocal for
/// blocks between the query and its dependencies.
void MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
                                         DenseMap<BasicBlock*, Value*>& resp) {
  const Instruction* localDep = getDependency(query);
  if (localDep != NonLocal) {
    resp.insert(std::make_pair(query->getParent(),
                               const_cast<Instruction*>(localDep)));
    return;
  }

  nonLocalHelper(query, query->getParent(), resp);
}

/// getDependency - Return the instruction on which a memory operation
/// depends.  The local paramter indicates if the query should only
/// evaluate dependencies within the same basic block.
const Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
                                                     Instruction* start,
                                                     BasicBlock* block) {
  // Start looking for dependencies with the queried inst
  BasicBlock::iterator QI = query;

  // Check for a cached result
  std::pair<const Instruction*, bool> cachedResult = depGraphLocal[query];
  // If we have a _confirmed_ cached entry, return it
  if (cachedResult.second)
    return cachedResult.first;
  else if (cachedResult.first && cachedResult.first != NonLocal)
  // If we have an unconfirmed cached entry, we can start our search from there
    QI = const_cast<Instruction*>(cachedResult.first);

  if (start)
    QI = start;
  else if (!start && block)
    QI = block->end();

  AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
  TargetData& TD = getAnalysis<TargetData>();

  // Get the pointer value for which dependence will be determined
  Value* dependee = 0;
  uint64_t dependeeSize = 0;
  bool queryIsVolatile = false;
  if (StoreInst* S = dyn_cast<StoreInst>(query)) {
    dependee = S->getPointerOperand();
    dependeeSize = TD.getTypeSize(S->getOperand(0)->getType());
    queryIsVolatile = S->isVolatile();
  } else if (LoadInst* L = dyn_cast<LoadInst>(query)) {
    dependee = L->getPointerOperand();
    dependeeSize = TD.getTypeSize(L->getType());
    queryIsVolatile = L->isVolatile();
  } else if (VAArgInst* V = dyn_cast<VAArgInst>(query)) {
    dependee = V->getOperand(0);
    dependeeSize = TD.getTypeSize(V->getType());
  } else if (FreeInst* F = dyn_cast<FreeInst>(query)) {
    dependee = F->getPointerOperand();

    // FreeInsts erase the entire structure, not just a field
    dependeeSize = ~0UL;
  } else if (CallSite::get(query).getInstruction() != 0)
    return getCallSiteDependency(CallSite::get(query), start, block);
  else if (isa<AllocationInst>(query))
    return None;
  else
    return None;

  BasicBlock::iterator blockBegin = block ? block->begin()
                                          : query->getParent()->begin();

  while (QI != blockBegin) {
    --QI;

    // If this inst is a memory op, get the pointer it accessed
    Value* pointer = 0;
    uint64_t pointerSize = 0;
    if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
      // All volatile loads/stores depend on each other
      if (queryIsVolatile && S->isVolatile()) {
        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(query, std::make_pair(S, true)));
          reverseDep[S].insert(query);
        }

        return S;
      }

      pointer = S->getPointerOperand();
      pointerSize = TD.getTypeSize(S->getOperand(0)->getType());
    } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
      // All volatile loads/stores depend on each other
      if (queryIsVolatile && L->isVolatile()) {
        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(query, std::make_pair(L, true)));
          reverseDep[L].insert(query);
        }

        return L;
      }

      pointer = L->getPointerOperand();
      pointerSize = TD.getTypeSize(L->getType());
    } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) {
      pointer = AI;
      if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize()))
        pointerSize = C->getZExtValue() * \
                      TD.getTypeSize(AI->getAllocatedType());
      else
        pointerSize = ~0UL;
    } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) {
      pointer = V->getOperand(0);
      pointerSize = TD.getTypeSize(V->getType());
    } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
      pointer = F->getPointerOperand();

      // FreeInsts erase the entire structure
      pointerSize = ~0UL;
    } else if (CallSite::get(QI).getInstruction() != 0) {
      // Call insts need special handling. Check if they can modify our pointer
      AliasAnalysis::ModRefResult MR = AA.getModRefInfo(CallSite::get(QI),
                                                      dependee, dependeeSize);

      if (MR != AliasAnalysis::NoModRef) {
        // Loads don't depend on read-only calls
        if (isa<LoadInst>(query) && MR == AliasAnalysis::Ref)
          continue;

        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(query,
                                              std::make_pair(QI, true)));
          reverseDep[QI].insert(query);
        }

        return QI;
      } else {
        continue;
      }
    }

    // If we found a pointer, check if it could be the same as our pointer
    if (pointer) {
      AliasAnalysis::AliasResult R = AA.alias(pointer, pointerSize,
                                              dependee, dependeeSize);

      if (R != AliasAnalysis::NoAlias) {
        // May-alias loads don't depend on each other
        if (isa<LoadInst>(query) && isa<LoadInst>(QI) &&
            R == AliasAnalysis::MayAlias)
          continue;

        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(query,
                                              std::make_pair(QI, true)));
          reverseDep[QI].insert(query);
        }

        return QI;
      }
    }
  }

  // If we found nothing, return the non-local flag
  if (!start && !block) {
    depGraphLocal.insert(std::make_pair(query,
                                        std::make_pair(NonLocal, true)));
    reverseDep[NonLocal].insert(query);
  }

  return NonLocal;
}

/// removeInstruction - Remove an instruction from the dependence analysis,
/// updating the dependence of instructions that previously depended on it.
void MemoryDependenceAnalysis::removeInstruction(Instruction* rem) {
  // Figure out the new dep for things that currently depend on rem
  const Instruction* newDep = NonLocal;

  depMapType::iterator depGraphEntry = depGraphLocal.find(rem);
  // We assume here that it's not in the reverse map if it's not in
  // the dep map.  Checking it could be expensive, so don't do it.

  if (depGraphEntry != depGraphLocal.end()) {
    if (depGraphEntry->second.first != NonLocal &&
        depGraphEntry->second.second) {
      // If we have dep info for rem, set them to it
      BasicBlock::iterator RI =
                         const_cast<Instruction*>(depGraphEntry->second.first);
      RI++;
      newDep = RI;
    } else if (depGraphEntry->second.first == NonLocal &&
               depGraphEntry->second.second ) {
      // If we have a confirmed non-local flag, use it
      newDep = NonLocal;
    } else {
      // Otherwise, use the immediate successor of rem
      // NOTE: This is because, when getDependence is called, it will first
      // check the immediate predecessor of what is in the cache.
      BasicBlock::iterator RI = rem;
      RI++;
      newDep = RI;
    }

    SmallPtrSet<Instruction*, 4>& set = reverseDep[rem];
    for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
         I != E; ++I) {
      // Insert the new dependencies
      // Mark it as unconfirmed as long as it is not the non-local flag
      depGraphLocal[*I] = std::make_pair(newDep, !newDep);
    }
    reverseDep.erase(rem);
  }

  getAnalysis<AliasAnalysis>().deleteValue(rem);
}
<commit_msg>Add more comments to memdep.<commit_after>//===- MemoryDependenceAnalysis.cpp - Mem Deps Implementation  --*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the Owen Anderson and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements an analysis that determines, for a given memory
// operation, what preceding memory operations it depends on.  It builds on
// alias analysis information, and tries to provide a lazy, caching interface to
// a common kind of alias information query.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/MemoryDependenceAnalysis.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Function.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetData.h"

using namespace llvm;

char MemoryDependenceAnalysis::ID = 0;

const Instruction* MemoryDependenceAnalysis::NonLocal = (Instruction*)-3;
const Instruction* MemoryDependenceAnalysis::None = (Instruction*)-4;

// Register this pass...
static RegisterPass<MemoryDependenceAnalysis> X("memdep",
                                                "Memory Dependence Analysis");

/// getAnalysisUsage - Does not modify anything.  It uses Alias Analysis.
///
void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequiredTransitive<AliasAnalysis>();
  AU.addRequiredTransitive<TargetData>();
}

/// getCallSiteDependency - Private helper for finding the local dependencies
/// of a call site.
const Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C,
                                                           Instruction* start,
                                                            BasicBlock* block) {

  AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
  TargetData& TD = getAnalysis<TargetData>();
  BasicBlock::iterator blockBegin = C.getInstruction()->getParent()->begin();
  BasicBlock::iterator QI = C.getInstruction();

  // If the starting point was specifiy, use it
  if (start) {
    QI = start;
    blockBegin = start->getParent()->end();
  // If the starting point wasn't specified, but the block was, use it
  } else if (!start && block) {
    QI = block->end();
    blockBegin = block->end();
  }

  // Walk backwards through the block, looking for dependencies
  while (QI != blockBegin) {
    --QI;

    // If this inst is a memory op, get the pointer it accessed
    Value* pointer = 0;
    uint64_t pointerSize = 0;
    if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
      pointer = S->getPointerOperand();
      pointerSize = TD.getTypeSize(S->getOperand(0)->getType());
    } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
      pointer = L->getPointerOperand();
      pointerSize = TD.getTypeSize(L->getType());
    } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) {
      pointer = AI;
      if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize()))
        pointerSize = C->getZExtValue() * \
                      TD.getTypeSize(AI->getAllocatedType());
      else
        pointerSize = ~0UL;
    } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) {
      pointer = V->getOperand(0);
      pointerSize = TD.getTypeSize(V->getType());
    } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
      pointer = F->getPointerOperand();

      // FreeInsts erase the entire structure
      pointerSize = ~0UL;
    } else if (CallSite::get(QI).getInstruction() != 0) {
      if (AA.getModRefInfo(C, CallSite::get(QI)) != AliasAnalysis::NoModRef) {
        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(C.getInstruction(),
                                              std::make_pair(QI, true)));
          reverseDep[QI].insert(C.getInstruction());
        }
        return QI;
      } else {
        continue;
      }
    } else
      continue;

    if (AA.getModRefInfo(C, pointer, pointerSize) != AliasAnalysis::NoModRef) {
      if (!start && !block) {
        depGraphLocal.insert(std::make_pair(C.getInstruction(),
                                            std::make_pair(QI, true)));
        reverseDep[QI].insert(C.getInstruction());
      }
      return QI;
    }
  }

  // No dependence found
  depGraphLocal.insert(std::make_pair(C.getInstruction(),
                                      std::make_pair(NonLocal, true)));
  reverseDep[NonLocal].insert(C.getInstruction());
  return NonLocal;
}

/// nonLocalHelper - Private helper used to calculate non-local dependencies
/// by doing DFS on the predecessors of a block to find its dependencies
void MemoryDependenceAnalysis::nonLocalHelper(Instruction* query,
                                              BasicBlock* block,
                                         DenseMap<BasicBlock*, Value*>& resp) {
  // Set of blocks that we've already visited in our DFS
  SmallPtrSet<BasicBlock*, 4> visited;
  // Current stack of the DFS
  SmallVector<BasicBlock*, 4> stack;
  stack.push_back(block);

  // Do a basic DFS
  while (!stack.empty()) {
    BasicBlock* BB = stack.back();

    // If we've already visited this block, no need to revist
    if (visited.count(BB)) {
      stack.pop_back();
      continue;
    }

    // If we find a new block with a local dependency for query,
    // then we insert the new dependency and backtrack.
    if (BB != block) {
      visited.insert(BB);

      const Instruction* localDep = getDependency(query, 0, BB);
      if (localDep != NonLocal) {
        resp.insert(std::make_pair(BB, const_cast<Instruction*>(localDep)));
        stack.pop_back();

        continue;
      }
    // If we re-encounter the starting block, we still need to search it
    // because there might be a dependency in the starting block AFTER
    // the position of the query.  This is necessary to get loops right.
    } else if (BB == block && stack.size() > 1) {
      visited.insert(BB);

      const Instruction* localDep = getDependency(query, 0, BB);
      if (localDep != query)
        resp.insert(std::make_pair(BB, const_cast<Instruction*>(localDep)));

      stack.pop_back();

      continue;
    }

    // If we didn't find anything, recurse on the precessors of this block
    bool predOnStack = false;
    bool inserted = false;
    for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
         PI != PE; ++PI)
      if (!visited.count(*PI)) {
        stack.push_back(*PI);
        inserted = true;
      } else
        predOnStack = true;

    // If we inserted a new predecessor, then we'll come back to this block
    if (inserted)
      continue;
    // If we didn't insert because we have no predecessors, then this
    // query has no dependency at all.
    else if (!inserted && !predOnStack) {
      resp.insert(std::make_pair(BB, const_cast<Instruction*>(None)));
    // If we didn't insert because our predecessors are already on the stack,
    // then we might still have a dependency, but it will be discovered during
    // backtracking.
    } else if (!inserted && predOnStack){
      resp.insert(std::make_pair(BB, const_cast<Instruction*>(NonLocal)));
    }

    stack.pop_back();
  }
}

/// getNonLocalDependency - Fills the passed-in map with the non-local
/// dependencies of the queries.  The map will contain NonLocal for
/// blocks between the query and its dependencies.
void MemoryDependenceAnalysis::getNonLocalDependency(Instruction* query,
                                         DenseMap<BasicBlock*, Value*>& resp) {
  // First check that we don't actually have a local dependency.
  const Instruction* localDep = getDependency(query);
  if (localDep != NonLocal) {
    resp.insert(std::make_pair(query->getParent(),
                               const_cast<Instruction*>(localDep)));
    return;
  }

  // If not, go ahead and search for non-local ones.
  nonLocalHelper(query, query->getParent(), resp);
}

/// getDependency - Return the instruction on which a memory operation
/// depends.  The local paramter indicates if the query should only
/// evaluate dependencies within the same basic block.
const Instruction* MemoryDependenceAnalysis::getDependency(Instruction* query,
                                                     Instruction* start,
                                                     BasicBlock* block) {
  // Start looking for dependencies with the queried inst
  BasicBlock::iterator QI = query;

  // Check for a cached result
  std::pair<const Instruction*, bool> cachedResult = depGraphLocal[query];
  // If we have a _confirmed_ cached entry, return it
  if (cachedResult.second)
    return cachedResult.first;
  else if (cachedResult.first && cachedResult.first != NonLocal)
  // If we have an unconfirmed cached entry, we can start our search from there
    QI = const_cast<Instruction*>(cachedResult.first);

  if (start)
    QI = start;
  else if (!start && block)
    QI = block->end();

  AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
  TargetData& TD = getAnalysis<TargetData>();

  // Get the pointer value for which dependence will be determined
  Value* dependee = 0;
  uint64_t dependeeSize = 0;
  bool queryIsVolatile = false;
  if (StoreInst* S = dyn_cast<StoreInst>(query)) {
    dependee = S->getPointerOperand();
    dependeeSize = TD.getTypeSize(S->getOperand(0)->getType());
    queryIsVolatile = S->isVolatile();
  } else if (LoadInst* L = dyn_cast<LoadInst>(query)) {
    dependee = L->getPointerOperand();
    dependeeSize = TD.getTypeSize(L->getType());
    queryIsVolatile = L->isVolatile();
  } else if (VAArgInst* V = dyn_cast<VAArgInst>(query)) {
    dependee = V->getOperand(0);
    dependeeSize = TD.getTypeSize(V->getType());
  } else if (FreeInst* F = dyn_cast<FreeInst>(query)) {
    dependee = F->getPointerOperand();

    // FreeInsts erase the entire structure, not just a field
    dependeeSize = ~0UL;
  } else if (CallSite::get(query).getInstruction() != 0)
    return getCallSiteDependency(CallSite::get(query), start, block);
  else if (isa<AllocationInst>(query))
    return None;
  else
    return None;

  BasicBlock::iterator blockBegin = block ? block->begin()
                                          : query->getParent()->begin();

  // Walk backwards through the basic block, looking for dependencies
  while (QI != blockBegin) {
    --QI;

    // If this inst is a memory op, get the pointer it accessed
    Value* pointer = 0;
    uint64_t pointerSize = 0;
    if (StoreInst* S = dyn_cast<StoreInst>(QI)) {
      // All volatile loads/stores depend on each other
      if (queryIsVolatile && S->isVolatile()) {
        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(query, std::make_pair(S, true)));
          reverseDep[S].insert(query);
        }

        return S;
      }

      pointer = S->getPointerOperand();
      pointerSize = TD.getTypeSize(S->getOperand(0)->getType());
    } else if (LoadInst* L = dyn_cast<LoadInst>(QI)) {
      // All volatile loads/stores depend on each other
      if (queryIsVolatile && L->isVolatile()) {
        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(query, std::make_pair(L, true)));
          reverseDep[L].insert(query);
        }

        return L;
      }

      pointer = L->getPointerOperand();
      pointerSize = TD.getTypeSize(L->getType());
    } else if (AllocationInst* AI = dyn_cast<AllocationInst>(QI)) {
      pointer = AI;
      if (ConstantInt* C = dyn_cast<ConstantInt>(AI->getArraySize()))
        pointerSize = C->getZExtValue() * \
                      TD.getTypeSize(AI->getAllocatedType());
      else
        pointerSize = ~0UL;
    } else if (VAArgInst* V = dyn_cast<VAArgInst>(QI)) {
      pointer = V->getOperand(0);
      pointerSize = TD.getTypeSize(V->getType());
    } else if (FreeInst* F = dyn_cast<FreeInst>(QI)) {
      pointer = F->getPointerOperand();

      // FreeInsts erase the entire structure
      pointerSize = ~0UL;
    } else if (CallSite::get(QI).getInstruction() != 0) {
      // Call insts need special handling. Check if they can modify our pointer
      AliasAnalysis::ModRefResult MR = AA.getModRefInfo(CallSite::get(QI),
                                                      dependee, dependeeSize);

      if (MR != AliasAnalysis::NoModRef) {
        // Loads don't depend on read-only calls
        if (isa<LoadInst>(query) && MR == AliasAnalysis::Ref)
          continue;

        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(query,
                                              std::make_pair(QI, true)));
          reverseDep[QI].insert(query);
        }

        return QI;
      } else {
        continue;
      }
    }

    // If we found a pointer, check if it could be the same as our pointer
    if (pointer) {
      AliasAnalysis::AliasResult R = AA.alias(pointer, pointerSize,
                                              dependee, dependeeSize);

      if (R != AliasAnalysis::NoAlias) {
        // May-alias loads don't depend on each other
        if (isa<LoadInst>(query) && isa<LoadInst>(QI) &&
            R == AliasAnalysis::MayAlias)
          continue;

        if (!start && !block) {
          depGraphLocal.insert(std::make_pair(query,
                                              std::make_pair(QI, true)));
          reverseDep[QI].insert(query);
        }

        return QI;
      }
    }
  }

  // If we found nothing, return the non-local flag
  if (!start && !block) {
    depGraphLocal.insert(std::make_pair(query,
                                        std::make_pair(NonLocal, true)));
    reverseDep[NonLocal].insert(query);
  }

  return NonLocal;
}

/// removeInstruction - Remove an instruction from the dependence analysis,
/// updating the dependence of instructions that previously depended on it.
/// This method attempts to keep the cache coherent using the reverse map.
void MemoryDependenceAnalysis::removeInstruction(Instruction* rem) {
  // Figure out the new dep for things that currently depend on rem
  const Instruction* newDep = NonLocal;

  depMapType::iterator depGraphEntry = depGraphLocal.find(rem);
  // We assume here that it's not in the reverse map if it's not in
  // the dep map.  Checking it could be expensive, so don't do it.

  if (depGraphEntry != depGraphLocal.end()) {
    if (depGraphEntry->second.first != NonLocal &&
        depGraphEntry->second.second) {
      // If we have dep info for rem, set them to it
      BasicBlock::iterator RI =
                         const_cast<Instruction*>(depGraphEntry->second.first);
      RI++;
      newDep = RI;
    } else if (depGraphEntry->second.first == NonLocal &&
               depGraphEntry->second.second ) {
      // If we have a confirmed non-local flag, use it
      newDep = NonLocal;
    } else {
      // Otherwise, use the immediate successor of rem
      // NOTE: This is because, when getDependence is called, it will first
      // check the immediate predecessor of what is in the cache.
      BasicBlock::iterator RI = rem;
      RI++;
      newDep = RI;
    }

    SmallPtrSet<Instruction*, 4>& set = reverseDep[rem];
    for (SmallPtrSet<Instruction*, 4>::iterator I = set.begin(), E = set.end();
         I != E; ++I) {
      // Insert the new dependencies
      // Mark it as unconfirmed as long as it is not the non-local flag
      depGraphLocal[*I] = std::make_pair(newDep, !newDep);
    }
    reverseDep.erase(rem);
  }

  getAnalysis<AliasAnalysis>().deleteValue(rem);
}
<|endoftext|>


<commit_before>/****************************************************************************
*
* NAME: smbPitchShift.cpp
* VERSION: 1.2
* HOME URL: http://blogs.zynaptiq.com/bernsee
* KNOWN BUGS: none
*
* SYNOPSIS: Routine for doing pitch shifting while maintaining
* duration using the Short Time Fourier Transform.
*
* DESCRIPTION: The routine takes a pitchShift factor value which is between 0.5
* (one octave down) and 2. (one octave up). A value of exactly 1 does not change
* the pitch. numSampsToProcess tells the routine how many samples in indata[0...
* numSampsToProcess-1] should be pitch shifted and moved to outdata[0 ...
* numSampsToProcess-1]. The two buffers can be identical (ie. it can process the
* data in-place). fftFrameSize defines the FFT frame size used for the
* processing. Typical values are 1024, 2048 and 4096. It MUST be a power of 2.
* oversamp is the STFT oversampling factor which also determines the overlap
* between adjacent STFT frames. It should at least be 4 for moderate scaling
* ratios. A value of 32 is recommended for best quality. sampleRate takes the
* sample rate for the signal in unit Hz, ie. 44100 for 44.1 kHz audio. The data
* passed to the routine in indata[] should be in the range [-1.0, 1.0), which is
* also the output range for the data, make sure you scale the data accordingly
* (for 16bit signed integers you would have to divide (and multiply) by 32768).
*
* COPYRIGHT 1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
*
* 						The Wide Open License (WOL)
*
* Permission to use, copy, modify, distribute and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice and this license appear in all source copies.
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
* ANY KIND. See http://www.dspguru.com/wol.htm for more information.
*
*****************************************************************************/

#ifndef SMBPITCHSHIFT_HPP
#define SMBPITCHSHIFT_HPP

#include <algorithm>
#include <cmath>
#include <cstdint>

namespace smb
{
    namespace
    {
        constexpr float pi = 3.14159265358979323846F;

        // Use own implementation because std::complex has a poor performance
        template <class T>
        struct Complex final
        {
            constexpr Complex<T> operator+(const Complex& other) const noexcept
            {
                return Complex{real + other.real, imag + other.imag};
            }

            constexpr Complex<T>& operator+=(const Complex& other)
            {
                real += other.real;
                imag += other.imag;
                return *this;
            }

            constexpr Complex<T> operator-(const Complex& other) const noexcept
            {
                return Complex{real - other.real, imag - other.imag};
            }

            constexpr Complex<T> operator-() const noexcept
            {
                return Complex{-real, -imag};
            }

            constexpr Complex<T>& operator-=(const Complex& other) noexcept
            {
                real -= other.real;
                imag -= other.imag;
                return *this;
            }

            constexpr Complex<T> operator*(const Complex& other) const noexcept
            {
                return Complex{real * other.real - imag * other.imag, real * other.imag + imag * other.real};
            }

            constexpr Complex<T>& operator*=(const Complex& other) noexcept
            {
                float tempReal = real;
                real = tempReal * other.real - imag * other.imag;
                imag = tempReal * other.imag + imag * other.real;
                return *this;
            }

            inline T magnitude() const noexcept
            {
                return sqrt(real * real + imag * imag);
            }

            T real;
            T imag;
        };

        template <int32_t sign, uint32_t fftFrameSize>
        void fft(Complex<float>* fftBuffer) noexcept
        {
            // Bit-reversal permutation applied to a sequence of fftFrameSize items
            for (uint32_t i = 1; i < fftFrameSize - 1; i++)
            {
                uint32_t j = 0;

                for (uint32_t bitm = 1; bitm < fftFrameSize; bitm <<= 1)
                {
                    if (i & bitm) j++;
                    j <<= 1;
                }
                j >>= 1;

                if (i < j)
                    std::swap(fftBuffer[i], fftBuffer[j]);
            }

            // Iterative form of Danielson-Lanczos lemma
            uint32_t step = 2;
            for (uint32_t i = 1; i < fftFrameSize; i <<= 1, step <<= 1)
            {
                const uint32_t step2 = step >> 1;
                const float arg = pi / step2;

                const Complex<float> w{std::cos(arg), std::sin(arg) * sign};
                Complex<float> u{1.0F, 0.0F};
                for (uint32_t j = 0; j < step2; j++)
                {
                    for (uint32_t k = j; k < fftFrameSize; k += step)
                    {
                        const Complex<float> temp = fftBuffer[k + step2] * u;
                        fftBuffer[k + step2] = fftBuffer[k] - temp;
                        fftBuffer[k] += temp;
                    }

                    u *= w;
                }
            }
        }
    }

    template <uint32_t fftFrameSize, uint32_t oversamp>
    class PitchShift final
    {
    public:
        PitchShift()
        {
            // Hann window
            for (uint32_t k = 0; k < fftFrameSize; k++)
                window[k] = 0.5F * (1.0F + std::cos(2.0F * pi * static_cast<float>(k) / static_cast<float>(fftFrameSize)));
        }

        /*
            Routine process(). See top of file for explanation
            Purpose: doing pitch shifting while maintaining duration using the Short
            Time Fourier Transform.
            Author: (c)1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
        */
        void process(const float pitchShift, const uint32_t numSampsToProcess,
                     const uint32_t sampleRate, const float* indata, float* outdata) noexcept
        {
            // set up some handy variables
            const uint32_t fftFrameSizeHalf = fftFrameSize / 2;
            const uint32_t stepSize = fftFrameSize / oversamp;
            const float freqPerBin = static_cast<float>(sampleRate) / static_cast<float>(fftFrameSize);
            const float expected = 2.0F * pi * static_cast<float>(stepSize) / static_cast<float>(fftFrameSize);
            const uint32_t inFifoLatency = fftFrameSize - stepSize;
            if (rover == 0) rover = inFifoLatency;

            // main processing loop
            for (uint32_t i = 0; i < numSampsToProcess; i++)
            {
                // As long as we have not yet collected enough data just read in
                inFifo[rover] = indata[i];
                outdata[i] = outFifo[rover - inFifoLatency];
                rover++;

                // now we have enough data for processing
                if (rover >= fftFrameSize)
                {
                    rover = inFifoLatency;

                    // do windowing
                    for (uint32_t k = 0; k < fftFrameSize; k++)
                    {
                        fftWorksp[k].real = inFifo[k] * window[k];
                        fftWorksp[k].imag = 0.0F;
                    }

                    // ***************** ANALYSIS *******************
                    // do transform
                    fft<-1, fftFrameSize>(fftWorksp);

                    // this is the analysis step
                    for (uint32_t k = 0; k <= fftFrameSizeHalf; k++)
                    {
                        const Complex<float>& current = fftWorksp[k];

                        // compute magnitude and phase
                        const float magn = 2.0F * current.magnitude();
                        const float signx = (current.imag > 0.0F) ? 1.0F : -1.0F;
                        const float phase = (current.imag == 0.0F) ? 0.0F :
                            (current.real == 0.0F) ? signx * pi / 2.0F :
                            std::atan2(current.imag, current.real);

                        // compute phase difference
                        float tmp = phase - lastPhase[k];
                        lastPhase[k] = phase;

                        // subtract expected phase difference
                        tmp -= static_cast<float>(k) * expected;

                        // map delta phase into +/- Pi interval
                        int32_t qpd = static_cast<int32_t>(tmp / pi);
                        if (qpd >= 0) qpd += qpd & 1;
                        else qpd -= qpd & 1;
                        tmp -= pi * static_cast<float>(qpd);

                        // get deviation from bin frequency from the +/- Pi interval
                        tmp = oversamp * tmp / (2.0F * pi);

                        // compute the k-th partials' true frequency
                        tmp = static_cast<float>(k) * freqPerBin + tmp * freqPerBin;

                        // store magnitude and true frequency in analysis arrays
                        anaMagn[k] = magn;
                        anaFreq[k] = tmp;
                    }

                    // ***************** PROCESSING *******************
                    // this does the actual pitch shifting
                    std::fill(std::begin(synMagn), std::begin(synMagn) + fftFrameSize, 0.0F);
                    std::fill(std::begin(synFreq), std::begin(synFreq) + fftFrameSize, 0.0F);
                    for (uint32_t k = 0; k <= fftFrameSizeHalf; k++)
                    {
                        const uint32_t index = static_cast<uint32_t>(k * pitchShift);
                        if (index > fftFrameSizeHalf) break;
                        synMagn[index] += anaMagn[k];
                        synFreq[index] = anaFreq[k] * pitchShift;
                    }

                    // ***************** SYNTHESIS *******************
                    // this is the synthesis step
                    for (uint32_t k = 0; k <= fftFrameSizeHalf; k++)
                    {
                        // get magnitude and true frequency from synthesis arrays
                        const float magn = synMagn[k];
                        float tmp = synFreq[k];

                        // subtract bin mid frequency
                        tmp -= static_cast<float>(k) * freqPerBin;

                        // get bin deviation from freq deviation
                        tmp /= freqPerBin;

                        // take oversampling factor into account
                        tmp = 2.0F * pi * tmp / oversamp;

                        // add the overlap phase advance back in
                        tmp += static_cast<float>(k) * expected;

                        // accumulate delta phase to get bin phase
                        sumPhase[k] += tmp;
                        const float phase = sumPhase[k];

                        // get real and imag part and re-interleave
                        fftWorksp[k].real = magn * std::cos(phase);
                        fftWorksp[k].imag = magn * std::sin(phase);
                    }

                    // zero negative frequencies
                    for (uint32_t k = fftFrameSize + 1; k < fftFrameSize; k++)
                        fftWorksp[k] = {0.0F, 0.0F};

                    // do inverse transform
                    fft<1, fftFrameSize>(fftWorksp);

                    // do windowing and add to output accumulator
                    for (uint32_t k = 0; k < fftFrameSize; k++)
                        outputAccum[k] += 2.0F * window[k] * fftWorksp[k].real / (fftFrameSizeHalf * oversamp);

                    uint32_t k;
                    for (k = 0 ; k < stepSize; k++)
                        outFifo[k] = outputAccum[k];
                    // shift accumulator
                    uint32_t j;
                    for (j = 0; k < fftFrameSize; k++, j++)
                        outputAccum[j] = outputAccum[k];
                    for (; j < fftFrameSize; j++)
                        outputAccum[j] = 0.0;

                    // move input FIFO
                    for (k = 0; k < inFifoLatency; k++)
                        inFifo[k] = inFifo[k + stepSize];
                }
            }
        }

    private:
        float window[fftFrameSize]; // the windowing function
        float inFifo[fftFrameSize]{0.0F};
        float outFifo[fftFrameSize]{0.0F};
        Complex<float> fftWorksp[fftFrameSize]{{0.0F, 0.0F}};
        float lastPhase[fftFrameSize / 2 + 1]{0.0F};
        float sumPhase[fftFrameSize / 2 + 1]{0.0F};
        float outputAccum[2 * fftFrameSize]{0.0F};
        float anaFreq[fftFrameSize]{0.0F};
        float anaMagn[fftFrameSize]{0.0F};
        float synFreq[fftFrameSize]{0.0F};
        float synMagn[fftFrameSize]{0.0F};
        uint32_t rover = 0;
    };
}

#endif
<commit_msg>Refactor the for loops to indicate that iteration is being done to fftFrameSizeHalf + 1<commit_after>/****************************************************************************
*
* NAME: smbPitchShift.cpp
* VERSION: 1.2
* HOME URL: http://blogs.zynaptiq.com/bernsee
* KNOWN BUGS: none
*
* SYNOPSIS: Routine for doing pitch shifting while maintaining
* duration using the Short Time Fourier Transform.
*
* DESCRIPTION: The routine takes a pitchShift factor value which is between 0.5
* (one octave down) and 2. (one octave up). A value of exactly 1 does not change
* the pitch. numSampsToProcess tells the routine how many samples in indata[0...
* numSampsToProcess-1] should be pitch shifted and moved to outdata[0 ...
* numSampsToProcess-1]. The two buffers can be identical (ie. it can process the
* data in-place). fftFrameSize defines the FFT frame size used for the
* processing. Typical values are 1024, 2048 and 4096. It MUST be a power of 2.
* oversamp is the STFT oversampling factor which also determines the overlap
* between adjacent STFT frames. It should at least be 4 for moderate scaling
* ratios. A value of 32 is recommended for best quality. sampleRate takes the
* sample rate for the signal in unit Hz, ie. 44100 for 44.1 kHz audio. The data
* passed to the routine in indata[] should be in the range [-1.0, 1.0), which is
* also the output range for the data, make sure you scale the data accordingly
* (for 16bit signed integers you would have to divide (and multiply) by 32768).
*
* COPYRIGHT 1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
*
* 						The Wide Open License (WOL)
*
* Permission to use, copy, modify, distribute and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice and this license appear in all source copies.
* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
* ANY KIND. See http://www.dspguru.com/wol.htm for more information.
*
*****************************************************************************/

#ifndef SMBPITCHSHIFT_HPP
#define SMBPITCHSHIFT_HPP

#include <algorithm>
#include <cmath>
#include <cstdint>

namespace smb
{
    namespace
    {
        constexpr float pi = 3.14159265358979323846F;

        // Use own implementation because std::complex has a poor performance
        template <class T>
        struct Complex final
        {
            constexpr Complex<T> operator+(const Complex& other) const noexcept
            {
                return Complex{real + other.real, imag + other.imag};
            }

            constexpr Complex<T>& operator+=(const Complex& other)
            {
                real += other.real;
                imag += other.imag;
                return *this;
            }

            constexpr Complex<T> operator-(const Complex& other) const noexcept
            {
                return Complex{real - other.real, imag - other.imag};
            }

            constexpr Complex<T> operator-() const noexcept
            {
                return Complex{-real, -imag};
            }

            constexpr Complex<T>& operator-=(const Complex& other) noexcept
            {
                real -= other.real;
                imag -= other.imag;
                return *this;
            }

            constexpr Complex<T> operator*(const Complex& other) const noexcept
            {
                return Complex{real * other.real - imag * other.imag, real * other.imag + imag * other.real};
            }

            constexpr Complex<T>& operator*=(const Complex& other) noexcept
            {
                float tempReal = real;
                real = tempReal * other.real - imag * other.imag;
                imag = tempReal * other.imag + imag * other.real;
                return *this;
            }

            inline T magnitude() const noexcept
            {
                return sqrt(real * real + imag * imag);
            }

            T real;
            T imag;
        };

        template <int32_t sign, uint32_t fftFrameSize>
        void fft(Complex<float>* fftBuffer) noexcept
        {
            // Bit-reversal permutation applied to a sequence of fftFrameSize items
            for (uint32_t i = 1; i < fftFrameSize - 1; i++)
            {
                uint32_t j = 0;

                for (uint32_t bitm = 1; bitm < fftFrameSize; bitm <<= 1)
                {
                    if (i & bitm) j++;
                    j <<= 1;
                }
                j >>= 1;

                if (i < j)
                    std::swap(fftBuffer[i], fftBuffer[j]);
            }

            // Iterative form of Danielson-Lanczos lemma
            uint32_t step = 2;
            for (uint32_t i = 1; i < fftFrameSize; i <<= 1, step <<= 1)
            {
                const uint32_t step2 = step >> 1;
                const float arg = pi / step2;

                const Complex<float> w{std::cos(arg), std::sin(arg) * sign};
                Complex<float> u{1.0F, 0.0F};
                for (uint32_t j = 0; j < step2; j++)
                {
                    for (uint32_t k = j; k < fftFrameSize; k += step)
                    {
                        const Complex<float> temp = fftBuffer[k + step2] * u;
                        fftBuffer[k + step2] = fftBuffer[k] - temp;
                        fftBuffer[k] += temp;
                    }

                    u *= w;
                }
            }
        }
    }

    template <uint32_t fftFrameSize, uint32_t oversamp>
    class PitchShift final
    {
    public:
        PitchShift()
        {
            // Hann window
            for (uint32_t k = 0; k < fftFrameSize; k++)
                window[k] = 0.5F * (1.0F + std::cos(2.0F * pi * static_cast<float>(k) / static_cast<float>(fftFrameSize)));
        }

        /*
            Routine process(). See top of file for explanation
            Purpose: doing pitch shifting while maintaining duration using the Short
            Time Fourier Transform.
            Author: (c)1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
        */
        void process(const float pitchShift, const uint32_t numSampsToProcess,
                     const uint32_t sampleRate, const float* indata, float* outdata) noexcept
        {
            // set up some handy variables
            const uint32_t fftFrameSizeHalf = fftFrameSize / 2;
            const uint32_t stepSize = fftFrameSize / oversamp;
            const float freqPerBin = static_cast<float>(sampleRate) / static_cast<float>(fftFrameSize);
            const float expected = 2.0F * pi * static_cast<float>(stepSize) / static_cast<float>(fftFrameSize);
            const uint32_t inFifoLatency = fftFrameSize - stepSize;
            if (rover == 0) rover = inFifoLatency;

            // main processing loop
            for (uint32_t i = 0; i < numSampsToProcess; i++)
            {
                // As long as we have not yet collected enough data just read in
                inFifo[rover] = indata[i];
                outdata[i] = outFifo[rover - inFifoLatency];
                rover++;

                // now we have enough data for processing
                if (rover >= fftFrameSize)
                {
                    rover = inFifoLatency;

                    // do windowing
                    for (uint32_t k = 0; k < fftFrameSize; k++)
                    {
                        fftWorksp[k].real = inFifo[k] * window[k];
                        fftWorksp[k].imag = 0.0F;
                    }

                    // ***************** ANALYSIS *******************
                    // do transform
                    fft<-1, fftFrameSize>(fftWorksp);

                    // this is the analysis step
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; k++)
                    {
                        const Complex<float>& current = fftWorksp[k];

                        // compute magnitude and phase
                        const float magn = 2.0F * current.magnitude();
                        const float signx = (current.imag > 0.0F) ? 1.0F : -1.0F;
                        const float phase = (current.imag == 0.0F) ? 0.0F :
                            (current.real == 0.0F) ? signx * pi / 2.0F :
                            std::atan2(current.imag, current.real);

                        // compute phase difference
                        float tmp = phase - lastPhase[k];
                        lastPhase[k] = phase;

                        // subtract expected phase difference
                        tmp -= static_cast<float>(k) * expected;

                        // map delta phase into +/- Pi interval
                        int32_t qpd = static_cast<int32_t>(tmp / pi);
                        if (qpd >= 0) qpd += qpd & 1;
                        else qpd -= qpd & 1;
                        tmp -= pi * static_cast<float>(qpd);

                        // get deviation from bin frequency from the +/- Pi interval
                        tmp = oversamp * tmp / (2.0F * pi);

                        // compute the k-th partials' true frequency
                        tmp = static_cast<float>(k) * freqPerBin + tmp * freqPerBin;

                        // store magnitude and true frequency in analysis arrays
                        anaMagn[k] = magn;
                        anaFreq[k] = tmp;
                    }

                    // ***************** PROCESSING *******************
                    // this does the actual pitch shifting
                    std::fill(std::begin(synMagn), std::begin(synMagn) + fftFrameSize, 0.0F);
                    std::fill(std::begin(synFreq), std::begin(synFreq) + fftFrameSize, 0.0F);
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; k++)
                    {
                        const uint32_t index = static_cast<uint32_t>(k * pitchShift);
                        if (index > fftFrameSizeHalf) break;
                        synMagn[index] += anaMagn[k];
                        synFreq[index] = anaFreq[k] * pitchShift;
                    }

                    // ***************** SYNTHESIS *******************
                    // this is the synthesis step
                    for (uint32_t k = 0; k < fftFrameSizeHalf + 1; k++)
                    {
                        // get magnitude and true frequency from synthesis arrays
                        const float magn = synMagn[k];
                        float tmp = synFreq[k];

                        // subtract bin mid frequency
                        tmp -= static_cast<float>(k) * freqPerBin;

                        // get bin deviation from freq deviation
                        tmp /= freqPerBin;

                        // take oversampling factor into account
                        tmp = 2.0F * pi * tmp / oversamp;

                        // add the overlap phase advance back in
                        tmp += static_cast<float>(k) * expected;

                        // accumulate delta phase to get bin phase
                        sumPhase[k] += tmp;
                        const float phase = sumPhase[k];

                        // get real and imag part and re-interleave
                        fftWorksp[k].real = magn * std::cos(phase);
                        fftWorksp[k].imag = magn * std::sin(phase);
                    }

                    // zero negative frequencies
                    for (uint32_t k = fftFrameSize + 1; k < fftFrameSize; k++)
                        fftWorksp[k] = {0.0F, 0.0F};

                    // do inverse transform
                    fft<1, fftFrameSize>(fftWorksp);

                    // do windowing and add to output accumulator
                    for (uint32_t k = 0; k < fftFrameSize; k++)
                        outputAccum[k] += 2.0F * window[k] * fftWorksp[k].real / (fftFrameSizeHalf * oversamp);

                    uint32_t k;
                    for (k = 0 ; k < stepSize; k++)
                        outFifo[k] = outputAccum[k];
                    // shift accumulator
                    uint32_t j;
                    for (j = 0; k < fftFrameSize; k++, j++)
                        outputAccum[j] = outputAccum[k];
                    for (; j < fftFrameSize; j++)
                        outputAccum[j] = 0.0;

                    // move input FIFO
                    for (k = 0; k < inFifoLatency; k++)
                        inFifo[k] = inFifo[k + stepSize];
                }
            }
        }

    private:
        float window[fftFrameSize]; // the windowing function
        float inFifo[fftFrameSize]{0.0F};
        float outFifo[fftFrameSize]{0.0F};
        Complex<float> fftWorksp[fftFrameSize]{{0.0F, 0.0F}};
        float lastPhase[fftFrameSize / 2 + 1]{0.0F};
        float sumPhase[fftFrameSize / 2 + 1]{0.0F};
        float outputAccum[2 * fftFrameSize]{0.0F};
        float anaFreq[fftFrameSize]{0.0F};
        float anaMagn[fftFrameSize]{0.0F};
        float synFreq[fftFrameSize]{0.0F};
        float synMagn[fftFrameSize]{0.0F};
        uint32_t rover = 0;
    };
}

#endif
<|endoftext|>


<commit_before>/* Copyright 2017 R. Thomas
 * Copyright 2017 Quarkslab
 *
 * 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 <iterator>
#include <iostream>
#include "LIEF/iostream.hpp"

namespace LIEF {
vector_iostream::vector_iostream(bool endian_swap) : endian_swap_{endian_swap} {}

size_t vector_iostream::uleb128_size(uint64_t value) {
  size_t size = 0;
  do {
    value >>= 7;
    size += sizeof(int8_t);
  } while(value);
  return size;
}

size_t vector_iostream::sleb128_size(int64_t value) {
  size_t size = 0;
  int sign = value >> (8 * sizeof(value) - 1);
  bool is_more;
  do {
    size_t byte = value & 0x7F;
    value >>= 7;
    is_more = value != sign or ((byte ^ sign) & 0x40) != 0;
    size += sizeof(int8_t);
  } while (is_more);
  return size;
}

void vector_iostream::reserve(size_t size) {
  this->raw_.reserve(size);
}
vector_iostream& vector_iostream::put(uint8_t c) {

  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + 1)) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + 1);
  }
  this->raw_[this->tellp()] = c;
  this->current_pos_ += 1;
  return *this;
}
vector_iostream& vector_iostream::write(const uint8_t* s, std::streamsize n) {
  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + n)) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + n);
  }

  auto&& it = std::begin(this->raw_);
  std::advance(it, static_cast<size_t>(this->tellp()));
  std::copy(s, s + n, it);

  this->current_pos_ += n;
  return *this;
}

vector_iostream& vector_iostream::write(const std::vector<uint8_t>& s) {
  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + s.size())) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + s.size());
  }
  auto&& it = std::begin(this->raw_);
  std::advance(it, static_cast<size_t>(this->tellp()));
  std::copy(std::begin(s), std::end(s), it);

  this->current_pos_ += s.size();
  return *this;
}

vector_iostream& vector_iostream::write(std::vector<uint8_t>&& s) {
  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + s.size())) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + s.size());
  }
  auto&& it = std::begin(this->raw_);
  std::advance(it, static_cast<size_t>(this->tellp()));
  std::move(
      std::begin(s),
      std::end(s), it);

  this->current_pos_ += s.size();
  return *this;
}

vector_iostream& vector_iostream::write(const std::string& s) {
  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + s.size() + 1)) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + s.size() + 1);
  }

  auto&& it = std::begin(this->raw_);
  std::advance(it, static_cast<size_t>(this->tellp()));
  std::copy(std::begin(s), std::end(s), it);

  this->current_pos_ += s.size() + 1;
  return *this;
}

vector_iostream& vector_iostream::write_uleb128(uint64_t value) {
  uint8_t byte;
	do {
    byte = value & 0x7F;
		value &= ~0x7F;
		if (value != 0) {
		  byte |= 0x80;
    }
    this->write<uint8_t>(byte);
		value = value >> 7;
	} while (byte >= 0x80);

  return *this;
}

vector_iostream& vector_iostream::write_sleb128(int64_t value) {

  bool is_neg = (value < 0);
	uint8_t byte;
	bool more;
	do {
	  byte = value & 0x7F;
		value = value >> 7;

    if (is_neg) {
		  more = ((value != -1) || ((byte & 0x40) == 0));
    } else {
		  more = ((value != 0) || ((byte & 0x40) != 0));
    }
		if (more) {
		  byte |= 0x80;
      this->write<uint8_t>(byte);
    }
	} while (more);

  return *this;
}

vector_iostream& vector_iostream::get(std::vector<uint8_t>& c) {
  c = this->raw_;
  return *this;
}

vector_iostream& vector_iostream::flush() {
  return *this;
}

const std::vector<uint8_t>& vector_iostream::raw(void) const {
  return this->raw_;
}

size_t vector_iostream::size(void) const {
  return this->raw_.size();
}

// seeks:
vector_iostream::pos_type vector_iostream::tellp(void) {
  return this->current_pos_;
}
vector_iostream& vector_iostream::seekp(vector_iostream::pos_type p) {
  this->current_pos_ = p;
  return *this;
}
vector_iostream& vector_iostream::seekp(vector_iostream::off_type p, std::ios_base::seekdir dir) {
  switch (dir) {
    case std::ios_base::beg:
      {
        this->current_pos_ = p;
        break;
      }

    case std::ios_base::end:
      {
        //this->current_pos_ = p;
        break;
      }

    case std::ios_base::cur:
      {
        this->current_pos_ += p;
        break;
      }

    default:
      {
        break;
      }
  }

  return *this;
}

vector_iostream& vector_iostream::align(size_t alignment, uint8_t fill) {
  if (this->raw_.size() % alignment == 0) {
    return *this;
  }

  while (this->raw_.size() % alignment != 0) {
    this->write<uint8_t>(fill);
  }

  return *this;
}

void vector_iostream::set_endian_swap(bool swap) {
  this->endian_swap_ = swap;
}

// Prefixbuf
prefixbuf::prefixbuf(std::string const& prefix, std::streambuf* sbuf) :
  prefix{prefix},
  sbuf{sbuf},
  need_prefix{true}
{}

int prefixbuf::sync() {
  return this->sbuf->pubsync();
}
int prefixbuf::overflow(int c) {
  if (c != std::char_traits<char>::eof()) {
    if (this->need_prefix and not this->prefix.empty() and
        this->prefix.size() != this->sbuf->sputn(&this->prefix[0], this->prefix.size())) {
      return std::char_traits<char>::eof();
    }

    this->need_prefix = c == '\n';
  }

  return this->sbuf->sputc(c);
}

oprefixstream::oprefixstream(std::string const& prefix, std::ostream& out) :
  prefixbuf(prefix, out.rdbuf()),
  std::ios(static_cast<std::streambuf*>(this)),
  std::ostream(static_cast<std::streambuf*>(this))
{}

}

<commit_msg>Fix bug<commit_after>/* Copyright 2017 R. Thomas
 * Copyright 2017 Quarkslab
 *
 * 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 <iterator>
#include <iostream>
#include "LIEF/iostream.hpp"

namespace LIEF {
vector_iostream::vector_iostream(bool endian_swap) : endian_swap_{endian_swap} {}

size_t vector_iostream::uleb128_size(uint64_t value) {
  size_t size = 0;
  do {
    value >>= 7;
    size += sizeof(int8_t);
  } while(value);
  return size;
}

size_t vector_iostream::sleb128_size(int64_t value) {
  size_t size = 0;
  int sign = value >> (8 * sizeof(value) - 1);
  bool is_more;
  do {
    size_t byte = value & 0x7F;
    value >>= 7;
    is_more = value != sign or ((byte ^ sign) & 0x40) != 0;
    size += sizeof(int8_t);
  } while (is_more);
  return size;
}

void vector_iostream::reserve(size_t size) {
  this->raw_.reserve(size);
}
vector_iostream& vector_iostream::put(uint8_t c) {

  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + 1)) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + 1);
  }
  this->raw_[this->tellp()] = c;
  this->current_pos_ += 1;
  return *this;
}
vector_iostream& vector_iostream::write(const uint8_t* s, std::streamsize n) {
  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + n)) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + n);
  }

  auto&& it = std::begin(this->raw_);
  std::advance(it, static_cast<size_t>(this->tellp()));
  std::copy(s, s + n, it);

  this->current_pos_ += n;
  return *this;
}

vector_iostream& vector_iostream::write(const std::vector<uint8_t>& s) {
  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + s.size())) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + s.size());
  }
  auto&& it = std::begin(this->raw_);
  std::advance(it, static_cast<size_t>(this->tellp()));
  std::copy(std::begin(s), std::end(s), it);

  this->current_pos_ += s.size();
  return *this;
}

vector_iostream& vector_iostream::write(std::vector<uint8_t>&& s) {
  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + s.size())) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + s.size());
  }
  auto&& it = std::begin(this->raw_);
  std::advance(it, static_cast<size_t>(this->tellp()));
  std::move(
      std::begin(s),
      std::end(s), it);

  this->current_pos_ += s.size();
  return *this;
}

vector_iostream& vector_iostream::write(const std::string& s) {
  if (this->raw_.size() < (static_cast<size_t>(this->tellp()) + s.size() + 1)) {
    this->raw_.resize(static_cast<size_t>(this->tellp()) + s.size() + 1);
  }

  auto&& it = std::begin(this->raw_);
  std::advance(it, static_cast<size_t>(this->tellp()));
  std::copy(std::begin(s), std::end(s), it);

  this->current_pos_ += s.size() + 1;
  return *this;
}

vector_iostream& vector_iostream::write_uleb128(uint64_t value) {
  uint8_t byte;
	do {
    byte = value & 0x7F;
		value &= ~0x7F;
		if (value != 0) {
		  byte |= 0x80;
    }
    this->write<uint8_t>(byte);
		value = value >> 7;
	} while (byte >= 0x80);

  return *this;
}

vector_iostream& vector_iostream::write_sleb128(int64_t value) {

  bool is_neg = (value < 0);
	uint8_t byte;
	bool more;
	do {
	  byte = value & 0x7F;
		value = value >> 7;

    if (is_neg) {
		  more = ((value != -1) || ((byte & 0x40) == 0));
    } else {
		  more = ((value != 0) || ((byte & 0x40) != 0));
    }
		if (more) {
		  byte |= 0x80;
    }
    this->write<uint8_t>(byte);
	} while (more);

  return *this;
}

vector_iostream& vector_iostream::get(std::vector<uint8_t>& c) {
  c = this->raw_;
  return *this;
}

vector_iostream& vector_iostream::flush() {
  return *this;
}

const std::vector<uint8_t>& vector_iostream::raw(void) const {
  return this->raw_;
}

size_t vector_iostream::size(void) const {
  return this->raw_.size();
}

// seeks:
vector_iostream::pos_type vector_iostream::tellp(void) {
  return this->current_pos_;
}
vector_iostream& vector_iostream::seekp(vector_iostream::pos_type p) {
  this->current_pos_ = p;
  return *this;
}
vector_iostream& vector_iostream::seekp(vector_iostream::off_type p, std::ios_base::seekdir dir) {
  switch (dir) {
    case std::ios_base::beg:
      {
        this->current_pos_ = p;
        break;
      }

    case std::ios_base::end:
      {
        //this->current_pos_ = p;
        break;
      }

    case std::ios_base::cur:
      {
        this->current_pos_ += p;
        break;
      }

    default:
      {
        break;
      }
  }

  return *this;
}

vector_iostream& vector_iostream::align(size_t alignment, uint8_t fill) {
  if (this->raw_.size() % alignment == 0) {
    return *this;
  }

  while (this->raw_.size() % alignment != 0) {
    this->write<uint8_t>(fill);
  }

  return *this;
}

void vector_iostream::set_endian_swap(bool swap) {
  this->endian_swap_ = swap;
}

// Prefixbuf
prefixbuf::prefixbuf(std::string const& prefix, std::streambuf* sbuf) :
  prefix{prefix},
  sbuf{sbuf},
  need_prefix{true}
{}

int prefixbuf::sync() {
  return this->sbuf->pubsync();
}
int prefixbuf::overflow(int c) {
  if (c != std::char_traits<char>::eof()) {
    if (this->need_prefix and not this->prefix.empty() and
        this->prefix.size() != this->sbuf->sputn(&this->prefix[0], this->prefix.size())) {
      return std::char_traits<char>::eof();
    }

    this->need_prefix = c == '\n';
  }

  return this->sbuf->sputc(c);
}

oprefixstream::oprefixstream(std::string const& prefix, std::ostream& out) :
  prefixbuf(prefix, out.rdbuf()),
  std::ios(static_cast<std::streambuf*>(this)),
  std::ostream(static_cast<std::streambuf*>(this))
{}

}

<|endoftext|>


<commit_before>#include "CartoOfflineVectorTileLayer.h"
#include "datasources/PackageManagerTileDataSource.h"
#include "packagemanager/CartoPackageManager.h"
#include "utils/AssetPackage.h"
#include "utils/Log.h"

namespace carto {

    CartoOfflineVectorTileLayer::CartoOfflineVectorTileLayer(const std::shared_ptr<CartoPackageManager>& packageManager, CartoBaseMapStyle::CartoBaseMapStyle style) :
        CartoVectorTileLayer(std::make_shared<PackageManagerTileDataSource>(packageManager), style)
    {
    }

    CartoOfflineVectorTileLayer::CartoOfflineVectorTileLayer(const std::shared_ptr<CartoPackageManager>& packageManager, const std::shared_ptr<AssetPackage>& styleAssetPackage) :
        CartoVectorTileLayer(std::make_shared<PackageManagerTileDataSource>(packageManager), styleAssetPackage)
    {
    }

    CartoOfflineVectorTileLayer::~CartoOfflineVectorTileLayer() {
    }

}
<commit_msg>Enable tile preloading by default for CartoOfflineVectorTileLayer<commit_after>#include "CartoOfflineVectorTileLayer.h"
#include "datasources/PackageManagerTileDataSource.h"
#include "packagemanager/CartoPackageManager.h"
#include "utils/AssetPackage.h"
#include "utils/Log.h"

namespace carto {

    CartoOfflineVectorTileLayer::CartoOfflineVectorTileLayer(const std::shared_ptr<CartoPackageManager>& packageManager, CartoBaseMapStyle::CartoBaseMapStyle style) :
        CartoVectorTileLayer(std::make_shared<PackageManagerTileDataSource>(packageManager), style)
    {
        _preloading = true; // turn preloading on by default
    }

    CartoOfflineVectorTileLayer::CartoOfflineVectorTileLayer(const std::shared_ptr<CartoPackageManager>& packageManager, const std::shared_ptr<AssetPackage>& styleAssetPackage) :
        CartoVectorTileLayer(std::make_shared<PackageManagerTileDataSource>(packageManager), styleAssetPackage)
    {
        _preloading = true; // turn preloading on by default
    }

    CartoOfflineVectorTileLayer::~CartoOfflineVectorTileLayer() {
    }

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: breakiterator_th.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: khong $ $Date: 2002-05-03 19:09:09 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _I18N_BREAKITERATOR_TH_HXX_
#define _I18N_BREAKITERATOR_TH_HXX_

#include <breakiterator_ctl.hxx>
#include <xdictionary.hxx>

namespace com { namespace sun { namespace star { namespace i18n {

//  ----------------------------------------------------
//  class BreakIterator_th
//  ----------------------------------------------------
class BreakIterator_th : public BreakIterator_CTL
{
public:
    BreakIterator_th();
    ~BreakIterator_th();

protected:
    void SAL_CALL makeIndex(const rtl::OUString& text, sal_Int32 pos) throw(com::sun::star::uno::RuntimeException);
};

} } } }

#endif // _I18N_BREAKITERATOR_TH_HXX_
<commit_msg>INTEGRATION: CWS i18n13 (1.3.164); FILE MERGED 2004/06/08 21:08:43 khong 1.3.164.1: #i29548# Fix Thai word breakiterator problem<commit_after>/*************************************************************************
 *
 *  $RCSfile: breakiterator_th.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2004-07-30 14:36:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _I18N_BREAKITERATOR_TH_HXX_
#define _I18N_BREAKITERATOR_TH_HXX_

#include <breakiterator_ctl.hxx>

namespace com { namespace sun { namespace star { namespace i18n {

//  ----------------------------------------------------
//  class BreakIterator_th
//  ----------------------------------------------------
class BreakIterator_th : public BreakIterator_CTL
{
public:
    BreakIterator_th();
    ~BreakIterator_th();

protected:
    void SAL_CALL makeIndex(const rtl::OUString& text, sal_Int32 pos) throw(com::sun::star::uno::RuntimeException);
    icu::BreakIterator* SAL_CALL loadICUWordBreakIterator(const rtl::OUString& Text, sal_Int32 nStartPos, const com::sun::star::lang::Locale& rLocale,
    sal_Int16 rWordType) throw( com::sun::star::uno::RuntimeException);
};

} } } }

#endif // _I18N_BREAKITERATOR_TH_HXX_
<|endoftext|>