<commit_before>//===-- Local.cpp - Functions to perform local transformations ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This family of functions perform various local transformations to the
// program.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/MathExtras.h"
#include <cerrno>
#include <cmath>
using namespace llvm;

//===----------------------------------------------------------------------===//
//  Local constant propagation...
//

/// doConstantPropagation - If an instruction references constants, try to fold
/// them together...
///
bool llvm::doConstantPropagation(BasicBlock::iterator &II) {
  if (Constant *C = ConstantFoldInstruction(II)) {
    // Replaces all of the uses of a variable with uses of the constant.
    II->replaceAllUsesWith(C);

    // Remove the instruction from the basic block...
    II = II->getParent()->getInstList().erase(II);
    return true;
  }

  return false;
}

/// ConstantFoldInstruction - Attempt to constant fold the specified
/// instruction.  If successful, the constant result is returned, if not, null
/// is returned.  Note that this function can only fail when attempting to fold
/// instructions like loads and stores, which have no constant expression form.
///
Constant *llvm::ConstantFoldInstruction(Instruction *I) {
  if (PHINode *PN = dyn_cast<PHINode>(I)) {
    if (PN->getNumIncomingValues() == 0)
      return Constant::getNullValue(PN->getType());

    Constant *Result = dyn_cast<Constant>(PN->getIncomingValue(0));
    if (Result == 0) return 0;

    // Handle PHI nodes specially here...
    for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i)
      if (PN->getIncomingValue(i) != Result && PN->getIncomingValue(i) != PN)
        return 0;   // Not all the same incoming constants...

    // If we reach here, all incoming values are the same constant.
    return Result;
  } else if (CallInst *CI = dyn_cast<CallInst>(I)) {
    if (Function *F = CI->getCalledFunction())
      if (canConstantFoldCallTo(F)) {
        std::vector<Constant*> Args;
        for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i)
          if (Constant *Op = dyn_cast<Constant>(CI->getOperand(i)))
            Args.push_back(Op);
          else
            return 0;
        return ConstantFoldCall(F, Args);
      }
    return 0;
  }

  Constant *Op0 = 0, *Op1 = 0;
  switch (I->getNumOperands()) {
  default:
  case 2:
    Op1 = dyn_cast<Constant>(I->getOperand(1));
    if (Op1 == 0) return 0;        // Not a constant?, can't fold
  case 1:
    Op0 = dyn_cast<Constant>(I->getOperand(0));
    if (Op0 == 0) return 0;        // Not a constant?, can't fold
    break;
  case 0: return 0;
  }

  if (isa<BinaryOperator>(I) || isa<ShiftInst>(I))
    return ConstantExpr::get(I->getOpcode(), Op0, Op1);

  switch (I->getOpcode()) {
  default: return 0;
  case Instruction::Cast:
    return ConstantExpr::getCast(Op0, I->getType());
  case Instruction::Select:
    if (Constant *Op2 = dyn_cast<Constant>(I->getOperand(2)))
      return ConstantExpr::getSelect(Op0, Op1, Op2);
    return 0;
  case Instruction::ExtractElement:
    return ConstantExpr::getExtractElement(Op0, Op1);
  case Instruction::InsertElement:
    if (Constant *Op2 = dyn_cast<Constant>(I->getOperand(2)))
      return ConstantExpr::getInsertElement(Op0, Op1, Op2);
  case Instruction::GetElementPtr:
    std::vector<Constant*> IdxList;
    IdxList.reserve(I->getNumOperands()-1);
    if (Op1) IdxList.push_back(Op1);
    for (unsigned i = 2, e = I->getNumOperands(); i != e; ++i)
      if (Constant *C = dyn_cast<Constant>(I->getOperand(i)))
        IdxList.push_back(C);
      else
        return 0;  // Non-constant operand
    return ConstantExpr::getGetElementPtr(Op0, IdxList);
  }
}

// ConstantFoldTerminator - If a terminator instruction is predicated on a
// constant value, convert it into an unconditional branch to the constant
// destination.
//
bool llvm::ConstantFoldTerminator(BasicBlock *BB) {
  TerminatorInst *T = BB->getTerminator();

  // Branch - See if we are conditional jumping on constant
  if (BranchInst *BI = dyn_cast<BranchInst>(T)) {
    if (BI->isUnconditional()) return false;  // Can't optimize uncond branch
    BasicBlock *Dest1 = cast<BasicBlock>(BI->getOperand(0));
    BasicBlock *Dest2 = cast<BasicBlock>(BI->getOperand(1));

    if (ConstantBool *Cond = dyn_cast<ConstantBool>(BI->getCondition())) {
      // Are we branching on constant?
      // YES.  Change to unconditional branch...
      BasicBlock *Destination = Cond->getValue() ? Dest1 : Dest2;
      BasicBlock *OldDest     = Cond->getValue() ? Dest2 : Dest1;

      //cerr << "Function: " << T->getParent()->getParent()
      //     << "\nRemoving branch from " << T->getParent()
      //     << "\n\nTo: " << OldDest << endl;

      // Let the basic block know that we are letting go of it.  Based on this,
      // it will adjust it's PHI nodes.
      assert(BI->getParent() && "Terminator not inserted in block!");
      OldDest->removePredecessor(BI->getParent());

      // Set the unconditional destination, and change the insn to be an
      // unconditional branch.
      BI->setUnconditionalDest(Destination);
      return true;
    } else if (Dest2 == Dest1) {       // Conditional branch to same location?
      // This branch matches something like this:
      //     br bool %cond, label %Dest, label %Dest
      // and changes it into:  br label %Dest

      // Let the basic block know that we are letting go of one copy of it.
      assert(BI->getParent() && "Terminator not inserted in block!");
      Dest1->removePredecessor(BI->getParent());

      // Change a conditional branch to unconditional.
      BI->setUnconditionalDest(Dest1);
      return true;
    }
  } else if (SwitchInst *SI = dyn_cast<SwitchInst>(T)) {
    // If we are switching on a constant, we can convert the switch into a
    // single branch instruction!
    ConstantInt *CI = dyn_cast<ConstantInt>(SI->getCondition());
    BasicBlock *TheOnlyDest = SI->getSuccessor(0);  // The default dest
    BasicBlock *DefaultDest = TheOnlyDest;
    assert(TheOnlyDest == SI->getDefaultDest() &&
           "Default destination is not successor #0?");

    // Figure out which case it goes to...
    for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i) {
      // Found case matching a constant operand?
      if (SI->getSuccessorValue(i) == CI) {
        TheOnlyDest = SI->getSuccessor(i);
        break;
      }

      // Check to see if this branch is going to the same place as the default
      // dest.  If so, eliminate it as an explicit compare.
      if (SI->getSuccessor(i) == DefaultDest) {
        // Remove this entry...
        DefaultDest->removePredecessor(SI->getParent());
        SI->removeCase(i);
        --i; --e;  // Don't skip an entry...
        continue;
      }

      // Otherwise, check to see if the switch only branches to one destination.
      // We do this by reseting "TheOnlyDest" to null when we find two non-equal
      // destinations.
      if (SI->getSuccessor(i) != TheOnlyDest) TheOnlyDest = 0;
    }

    if (CI && !TheOnlyDest) {
      // Branching on a constant, but not any of the cases, go to the default
      // successor.
      TheOnlyDest = SI->getDefaultDest();
    }

    // If we found a single destination that we can fold the switch into, do so
    // now.
    if (TheOnlyDest) {
      // Insert the new branch..
      new BranchInst(TheOnlyDest, SI);
      BasicBlock *BB = SI->getParent();

      // Remove entries from PHI nodes which we no longer branch to...
      for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) {
        // Found case matching a constant operand?
        BasicBlock *Succ = SI->getSuccessor(i);
        if (Succ == TheOnlyDest)
          TheOnlyDest = 0;  // Don't modify the first branch to TheOnlyDest
        else
          Succ->removePredecessor(BB);
      }

      // Delete the old switch...
      BB->getInstList().erase(SI);
      return true;
    } else if (SI->getNumSuccessors() == 2) {
      // Otherwise, we can fold this switch into a conditional branch
      // instruction if it has only one non-default destination.
      Value *Cond = new SetCondInst(Instruction::SetEQ, SI->getCondition(),
                                    SI->getSuccessorValue(1), "cond", SI);
      // Insert the new branch...
      new BranchInst(SI->getSuccessor(1), SI->getSuccessor(0), Cond, SI);

      // Delete the old switch...
      SI->getParent()->getInstList().erase(SI);
      return true;
    }
  }
  return false;
}

/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
/// getelementptr constantexpr, return the constant value being addressed by the
/// constant expression, or null if something is funny and we can't decide.
Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C,
                                                       ConstantExpr *CE) {
  if (CE->getOperand(1) != Constant::getNullValue(CE->getOperand(1)->getType()))
    return 0;  // Do not allow stepping over the value!

  // Loop over all of the operands, tracking down which value we are
  // addressing...
  gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE);
  for (++I; I != E; ++I)
    if (const StructType *STy = dyn_cast<StructType>(*I)) {
      ConstantUInt *CU = cast<ConstantUInt>(I.getOperand());
      assert(CU->getValue() < STy->getNumElements() &&
             "Struct index out of range!");
      unsigned El = (unsigned)CU->getValue();
      if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C)) {
        C = CS->getOperand(El);
      } else if (isa<ConstantAggregateZero>(C)) {
        C = Constant::getNullValue(STy->getElementType(El));
      } else if (isa<UndefValue>(C)) {
        C = UndefValue::get(STy->getElementType(El));
      } else {
        return 0;
      }
    } else if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand())) {
      if (const ArrayType *ATy = dyn_cast<ArrayType>(*I)) {
        if ((uint64_t)CI->getRawValue() >= ATy->getNumElements()) return 0;
        if (ConstantArray *CA = dyn_cast<ConstantArray>(C))
          C = CA->getOperand((unsigned)CI->getRawValue());
        else if (isa<ConstantAggregateZero>(C))
          C = Constant::getNullValue(ATy->getElementType());
        else if (isa<UndefValue>(C))
          C = UndefValue::get(ATy->getElementType());
        else
          return 0;
      } else if (const PackedType *PTy = dyn_cast<PackedType>(*I)) {
        if ((uint64_t)CI->getRawValue() >= PTy->getNumElements()) return 0;
        if (ConstantPacked *CP = dyn_cast<ConstantPacked>(C))
          C = CP->getOperand((unsigned)CI->getRawValue());
        else if (isa<ConstantAggregateZero>(C))
          C = Constant::getNullValue(PTy->getElementType());
        else if (isa<UndefValue>(C))
          C = UndefValue::get(PTy->getElementType());
        else
          return 0;
      } else {
        return 0;
      }
    } else {
      return 0;
    }
  return C;
}

//===----------------------------------------------------------------------===//
//  Local dead code elimination...
//

bool llvm::isInstructionTriviallyDead(Instruction *I) {
  if (!I->use_empty() || isa<TerminatorInst>(I)) return false;

  if (!I->mayWriteToMemory()) return true;

  if (CallInst *CI = dyn_cast<CallInst>(I))
    if (Function *F = CI->getCalledFunction())
      switch (F->getIntrinsicID()) {
      default: break;
      case Intrinsic::returnaddress:
      case Intrinsic::frameaddress:
      case Intrinsic::stacksave:
      case Intrinsic::isunordered_f32:
      case Intrinsic::isunordered_f64:
      case Intrinsic::bswap_i16:
      case Intrinsic::bswap_i32:
      case Intrinsic::bswap_i64:
      case Intrinsic::ctpop_i8:
      case Intrinsic::ctpop_i16:
      case Intrinsic::ctpop_i32:
      case Intrinsic::ctpop_i64:
      case Intrinsic::ctlz_i8:
      case Intrinsic::ctlz_i16:
      case Intrinsic::ctlz_i32:
      case Intrinsic::ctlz_i64:
      case Intrinsic::cttz_i8:
      case Intrinsic::cttz_i16:
      case Intrinsic::cttz_i32:
      case Intrinsic::cttz_i64:
      case Intrinsic::sqrt_f32:
      case Intrinsic::sqrt_f64:
        return true;             // These intrinsics have no side effects.
      }
  return false;
}

// dceInstruction - Inspect the instruction at *BBI and figure out if it's
// [trivially] dead.  If so, remove the instruction and update the iterator
// to point to the instruction that immediately succeeded the original
// instruction.
//
bool llvm::dceInstruction(BasicBlock::iterator &BBI) {
  // Look for un"used" definitions...
  if (isInstructionTriviallyDead(BBI)) {
    BBI = BBI->getParent()->getInstList().erase(BBI);   // Bye bye
    return true;
  }
  return false;
}
<commit_msg>use autogenerated side-effect information<commit_after>//===-- Local.cpp - Functions to perform local transformations ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This family of functions perform various local transformations to the
// program.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/MathExtras.h"
#include <cerrno>
#include <cmath>
using namespace llvm;

//===----------------------------------------------------------------------===//
//  Local constant propagation...
//

/// doConstantPropagation - If an instruction references constants, try to fold
/// them together...
///
bool llvm::doConstantPropagation(BasicBlock::iterator &II) {
  if (Constant *C = ConstantFoldInstruction(II)) {
    // Replaces all of the uses of a variable with uses of the constant.
    II->replaceAllUsesWith(C);

    // Remove the instruction from the basic block...
    II = II->getParent()->getInstList().erase(II);
    return true;
  }

  return false;
}

/// ConstantFoldInstruction - Attempt to constant fold the specified
/// instruction.  If successful, the constant result is returned, if not, null
/// is returned.  Note that this function can only fail when attempting to fold
/// instructions like loads and stores, which have no constant expression form.
///
Constant *llvm::ConstantFoldInstruction(Instruction *I) {
  if (PHINode *PN = dyn_cast<PHINode>(I)) {
    if (PN->getNumIncomingValues() == 0)
      return Constant::getNullValue(PN->getType());

    Constant *Result = dyn_cast<Constant>(PN->getIncomingValue(0));
    if (Result == 0) return 0;

    // Handle PHI nodes specially here...
    for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i)
      if (PN->getIncomingValue(i) != Result && PN->getIncomingValue(i) != PN)
        return 0;   // Not all the same incoming constants...

    // If we reach here, all incoming values are the same constant.
    return Result;
  } else if (CallInst *CI = dyn_cast<CallInst>(I)) {
    if (Function *F = CI->getCalledFunction())
      if (canConstantFoldCallTo(F)) {
        std::vector<Constant*> Args;
        for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i)
          if (Constant *Op = dyn_cast<Constant>(CI->getOperand(i)))
            Args.push_back(Op);
          else
            return 0;
        return ConstantFoldCall(F, Args);
      }
    return 0;
  }

  Constant *Op0 = 0, *Op1 = 0;
  switch (I->getNumOperands()) {
  default:
  case 2:
    Op1 = dyn_cast<Constant>(I->getOperand(1));
    if (Op1 == 0) return 0;        // Not a constant?, can't fold
  case 1:
    Op0 = dyn_cast<Constant>(I->getOperand(0));
    if (Op0 == 0) return 0;        // Not a constant?, can't fold
    break;
  case 0: return 0;
  }

  if (isa<BinaryOperator>(I) || isa<ShiftInst>(I))
    return ConstantExpr::get(I->getOpcode(), Op0, Op1);

  switch (I->getOpcode()) {
  default: return 0;
  case Instruction::Cast:
    return ConstantExpr::getCast(Op0, I->getType());
  case Instruction::Select:
    if (Constant *Op2 = dyn_cast<Constant>(I->getOperand(2)))
      return ConstantExpr::getSelect(Op0, Op1, Op2);
    return 0;
  case Instruction::ExtractElement:
    return ConstantExpr::getExtractElement(Op0, Op1);
  case Instruction::InsertElement:
    if (Constant *Op2 = dyn_cast<Constant>(I->getOperand(2)))
      return ConstantExpr::getInsertElement(Op0, Op1, Op2);
  case Instruction::GetElementPtr:
    std::vector<Constant*> IdxList;
    IdxList.reserve(I->getNumOperands()-1);
    if (Op1) IdxList.push_back(Op1);
    for (unsigned i = 2, e = I->getNumOperands(); i != e; ++i)
      if (Constant *C = dyn_cast<Constant>(I->getOperand(i)))
        IdxList.push_back(C);
      else
        return 0;  // Non-constant operand
    return ConstantExpr::getGetElementPtr(Op0, IdxList);
  }
}

// ConstantFoldTerminator - If a terminator instruction is predicated on a
// constant value, convert it into an unconditional branch to the constant
// destination.
//
bool llvm::ConstantFoldTerminator(BasicBlock *BB) {
  TerminatorInst *T = BB->getTerminator();

  // Branch - See if we are conditional jumping on constant
  if (BranchInst *BI = dyn_cast<BranchInst>(T)) {
    if (BI->isUnconditional()) return false;  // Can't optimize uncond branch
    BasicBlock *Dest1 = cast<BasicBlock>(BI->getOperand(0));
    BasicBlock *Dest2 = cast<BasicBlock>(BI->getOperand(1));

    if (ConstantBool *Cond = dyn_cast<ConstantBool>(BI->getCondition())) {
      // Are we branching on constant?
      // YES.  Change to unconditional branch...
      BasicBlock *Destination = Cond->getValue() ? Dest1 : Dest2;
      BasicBlock *OldDest     = Cond->getValue() ? Dest2 : Dest1;

      //cerr << "Function: " << T->getParent()->getParent()
      //     << "\nRemoving branch from " << T->getParent()
      //     << "\n\nTo: " << OldDest << endl;

      // Let the basic block know that we are letting go of it.  Based on this,
      // it will adjust it's PHI nodes.
      assert(BI->getParent() && "Terminator not inserted in block!");
      OldDest->removePredecessor(BI->getParent());

      // Set the unconditional destination, and change the insn to be an
      // unconditional branch.
      BI->setUnconditionalDest(Destination);
      return true;
    } else if (Dest2 == Dest1) {       // Conditional branch to same location?
      // This branch matches something like this:
      //     br bool %cond, label %Dest, label %Dest
      // and changes it into:  br label %Dest

      // Let the basic block know that we are letting go of one copy of it.
      assert(BI->getParent() && "Terminator not inserted in block!");
      Dest1->removePredecessor(BI->getParent());

      // Change a conditional branch to unconditional.
      BI->setUnconditionalDest(Dest1);
      return true;
    }
  } else if (SwitchInst *SI = dyn_cast<SwitchInst>(T)) {
    // If we are switching on a constant, we can convert the switch into a
    // single branch instruction!
    ConstantInt *CI = dyn_cast<ConstantInt>(SI->getCondition());
    BasicBlock *TheOnlyDest = SI->getSuccessor(0);  // The default dest
    BasicBlock *DefaultDest = TheOnlyDest;
    assert(TheOnlyDest == SI->getDefaultDest() &&
           "Default destination is not successor #0?");

    // Figure out which case it goes to...
    for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i) {
      // Found case matching a constant operand?
      if (SI->getSuccessorValue(i) == CI) {
        TheOnlyDest = SI->getSuccessor(i);
        break;
      }

      // Check to see if this branch is going to the same place as the default
      // dest.  If so, eliminate it as an explicit compare.
      if (SI->getSuccessor(i) == DefaultDest) {
        // Remove this entry...
        DefaultDest->removePredecessor(SI->getParent());
        SI->removeCase(i);
        --i; --e;  // Don't skip an entry...
        continue;
      }

      // Otherwise, check to see if the switch only branches to one destination.
      // We do this by reseting "TheOnlyDest" to null when we find two non-equal
      // destinations.
      if (SI->getSuccessor(i) != TheOnlyDest) TheOnlyDest = 0;
    }

    if (CI && !TheOnlyDest) {
      // Branching on a constant, but not any of the cases, go to the default
      // successor.
      TheOnlyDest = SI->getDefaultDest();
    }

    // If we found a single destination that we can fold the switch into, do so
    // now.
    if (TheOnlyDest) {
      // Insert the new branch..
      new BranchInst(TheOnlyDest, SI);
      BasicBlock *BB = SI->getParent();

      // Remove entries from PHI nodes which we no longer branch to...
      for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) {
        // Found case matching a constant operand?
        BasicBlock *Succ = SI->getSuccessor(i);
        if (Succ == TheOnlyDest)
          TheOnlyDest = 0;  // Don't modify the first branch to TheOnlyDest
        else
          Succ->removePredecessor(BB);
      }

      // Delete the old switch...
      BB->getInstList().erase(SI);
      return true;
    } else if (SI->getNumSuccessors() == 2) {
      // Otherwise, we can fold this switch into a conditional branch
      // instruction if it has only one non-default destination.
      Value *Cond = new SetCondInst(Instruction::SetEQ, SI->getCondition(),
                                    SI->getSuccessorValue(1), "cond", SI);
      // Insert the new branch...
      new BranchInst(SI->getSuccessor(1), SI->getSuccessor(0), Cond, SI);

      // Delete the old switch...
      SI->getParent()->getInstList().erase(SI);
      return true;
    }
  }
  return false;
}

/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
/// getelementptr constantexpr, return the constant value being addressed by the
/// constant expression, or null if something is funny and we can't decide.
Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C,
                                                       ConstantExpr *CE) {
  if (CE->getOperand(1) != Constant::getNullValue(CE->getOperand(1)->getType()))
    return 0;  // Do not allow stepping over the value!

  // Loop over all of the operands, tracking down which value we are
  // addressing...
  gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE);
  for (++I; I != E; ++I)
    if (const StructType *STy = dyn_cast<StructType>(*I)) {
      ConstantUInt *CU = cast<ConstantUInt>(I.getOperand());
      assert(CU->getValue() < STy->getNumElements() &&
             "Struct index out of range!");
      unsigned El = (unsigned)CU->getValue();
      if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C)) {
        C = CS->getOperand(El);
      } else if (isa<ConstantAggregateZero>(C)) {
        C = Constant::getNullValue(STy->getElementType(El));
      } else if (isa<UndefValue>(C)) {
        C = UndefValue::get(STy->getElementType(El));
      } else {
        return 0;
      }
    } else if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand())) {
      if (const ArrayType *ATy = dyn_cast<ArrayType>(*I)) {
        if ((uint64_t)CI->getRawValue() >= ATy->getNumElements()) return 0;
        if (ConstantArray *CA = dyn_cast<ConstantArray>(C))
          C = CA->getOperand((unsigned)CI->getRawValue());
        else if (isa<ConstantAggregateZero>(C))
          C = Constant::getNullValue(ATy->getElementType());
        else if (isa<UndefValue>(C))
          C = UndefValue::get(ATy->getElementType());
        else
          return 0;
      } else if (const PackedType *PTy = dyn_cast<PackedType>(*I)) {
        if ((uint64_t)CI->getRawValue() >= PTy->getNumElements()) return 0;
        if (ConstantPacked *CP = dyn_cast<ConstantPacked>(C))
          C = CP->getOperand((unsigned)CI->getRawValue());
        else if (isa<ConstantAggregateZero>(C))
          C = Constant::getNullValue(PTy->getElementType());
        else if (isa<UndefValue>(C))
          C = UndefValue::get(PTy->getElementType());
        else
          return 0;
      } else {
        return 0;
      }
    } else {
      return 0;
    }
  return C;
}

//===----------------------------------------------------------------------===//
//  Local dead code elimination...
//

bool llvm::isInstructionTriviallyDead(Instruction *I) {
  if (!I->use_empty() || isa<TerminatorInst>(I)) return false;

  if (!I->mayWriteToMemory()) return true;

  if (CallInst *CI = dyn_cast<CallInst>(I))
    if (Function *F = CI->getCalledFunction()) {
#define GET_SIDE_EFFECT_INFO
#include "llvm/Intrinsics.gen"
#undef GET_SIDE_EFFECT_INFO
    }
  return false;
}

// dceInstruction - Inspect the instruction at *BBI and figure out if it's
// [trivially] dead.  If so, remove the instruction and update the iterator
// to point to the instruction that immediately succeeded the original
// instruction.
//
bool llvm::dceInstruction(BasicBlock::iterator &BBI) {
  // Look for un"used" definitions...
  if (isInstructionTriviallyDead(BBI)) {
    BBI = BBI->getParent()->getInstList().erase(BBI);   // Bye bye
    return true;
  }
  return false;
}
<|endoftext|>


<commit_before>#include <catch.hpp>
#include <rapidcheck-catch.h>

#include <numeric>

#include "util/Predictable.h"
#include "util/GenUtils.h"
#include "util/ArbitraryRandom.h"

#include "rapidcheck/newgen/detail/ExecRaw.h"
#include "rapidcheck/shrinkable/Operations.h"
#include "rapidcheck/seq/Operations.h"

using namespace rc;
using namespace rc::test;
using namespace rc::newgen::detail;

namespace {

template<int N>
Gen<std::pair<std::vector<int>, Recipe>> testExecGen()
{
    return execRaw(
        [=](const FixedCountdown<N> &n) {
            std::vector<int> values;
            values.push_back(n.value);
            while (values.size() < (n.value + 1))
                values.push_back(*genFixedCountdown(N));
            return values;
        });
}

} // namespace

TEST_CASE("execRaw") {
    SECTION("uses correct arbitrary instance for arguments") {
        auto values = execRaw([](
            const Predictable &a,
            const Predictable &b,
            const Predictable &c)
        {
            return std::make_tuple(a, b, c);
        })(Random(), 0).value().first;

        REQUIRE(isArbitraryPredictable(std::get<0>(values)));
        REQUIRE(isArbitraryPredictable(std::get<1>(values)));
        REQUIRE(isArbitraryPredictable(std::get<2>(values)));
    }

    SECTION("shrinks arguments like a tuple") {
        typedef std::tuple<FixedCountdown<1>,
                           FixedCountdown<2>,
                           FixedCountdown<3>> TupleT;

        auto execShrinkable = execRaw([](
            const FixedCountdown<1> &a,
            const FixedCountdown<2> &b,
            const FixedCountdown<3> &c)
        {
            return std::make_tuple(a, b, c);
        })(Random(), 0);

        auto tupleShrinkable = newgen::tuple(
            newgen::arbitrary<FixedCountdown<1>>(),
            newgen::arbitrary<FixedCountdown<2>>(),
            newgen::arbitrary<FixedCountdown<3>>())(Random(), 0);

        auto mappedShrinkable = shrinkable::map(
            execShrinkable,
            [](std::pair<TupleT, Recipe> &&x) {
                return std::move(x.first);
            });

        REQUIRE(mappedShrinkable == tupleShrinkable);
    }

    prop("traversing a random path through the shrink tree yields the expected"
         " values",
         []{
             const auto shrinkable = testExecGen<5>()(Random(), 0);
             const auto path = *gen::collection<std::vector<bool>>(
                 gen::arbitrary<bool>());

             std::vector<int> accepted = shrinkable.value().first;
             auto acceptedShrinkable = shrinkable;
             auto shrinks = shrinkable.shrinks();
             int i = 0;
             int x = 5;
             for (bool accept : path) {
                 if (i >= accepted.size()) {
                     RC_ASSERT(!shrinks.next());
                     break;
                 }

                 auto shrink = *shrinks.next();
                 auto actual = shrink.value().first;

                 auto expected = accepted;
                 expected[i] = --x;
                 // First element determines the size
                 expected.resize(expected[0] + 1);
                 RC_ASSERT(actual == expected);
                 if (accept) {
                     accepted = expected;
                     acceptedShrinkable = shrink;
                     shrinks = shrink.shrinks();
                 }

                 if (x == 0) {
                     x = 5;
                     i++;
                 }
             }
         });

    prop("the number of shrinks is never never more than the sum of the number"
         " of shrinks for the requested values",
         []{
             const auto shrinkable = testExecGen<5>()(Random(), 0);

             int i = *gen::ranged<int>(0, 5);
             const auto shrink = *seq::at(shrinkable.shrinks(), i);
             const auto value = shrink.value().first;
             int maxShrinks =
                 std::accumulate(begin(value), end(value), 0);
             RC_ASSERT(seq::length(shrink.shrinks()) <= maxShrinks);
         });

    prop("passes on the correct size",
         [] {
             int expectedSize = *gen::nonNegative<int>();
             int n = *gen::ranged<int>(1, 10);
             auto shrinkable = execRaw([=](const PassedSize &sz) {
                 *genFixedCountdown(3); // Force some shrinks
                 std::vector<int> sizes;
                 sizes.push_back(sz.value);
                 while (sizes.size() < n)
                     sizes.push_back(*genSize());
                 return sizes;
             })(Random(), expectedSize);

             auto valueShrinkable = shrinkable::map(
                 shrinkable,
                 [](std::pair<std::vector<int>, Recipe> &&x) {
                     return std::move(x.first);
                 });

             RC_ASSERT(
                 shrinkable::all(
                     valueShrinkable,
                     [=](const Shrinkable<std::vector<int>> &x) {
                         auto sizes = x.value();
                         return std::all_of(
                             begin(sizes), end(sizes),
                             [=](int sz) { return sz == expectedSize; });
                     }));
         });

    prop("passes on sequentially split generators",
         [](const Random &initial) {
             int n = *gen::ranged<int>(1, 10);
             auto shrinkable = execRaw([=](const PassedRandom &rnd) {
                 std::vector<Random> randoms;
                 randoms.push_back(rnd.value);
                 while (randoms.size() < n)
                     randoms.push_back(*genRandom());
                 // Force some shrinks, must be last because it will steal a
                 // random split otherwise
                 *genFixedCountdown(3);
                 return randoms;
             })(initial, 0);

             Random r(initial);
             std::vector<Random> expected;
             // The arguments are generated as a tuple so we want the same
             // splitting behavior
             expected.push_back(
                 std::get<0>(newgen::tuple(genRandom())(r.split(), 0).value()));
             while (expected.size() < n)
                 expected.push_back(r.split());

             auto valueShrinkable = shrinkable::map(
                 shrinkable,
                 [](std::pair<std::vector<Random>, Recipe> &&x) {
                     return std::move(x.first);
                 });

             RC_ASSERT(
                 shrinkable::all(
                     valueShrinkable,
                     [=](const Shrinkable<std::vector<Random>> &x) {
                         return x.value() == expected;
                     }));
         });

    SECTION("the ingredients of the recipe exactly match the generated value") {
        REQUIRE(
            shrinkable::all(
                testExecGen<3>()(Random(), 0),
                [](const Shrinkable<std::pair<std::vector<int>, Recipe>> &x) {
                    typedef std::tuple<FixedCountdown<3>> ArgTuple;
                    const auto pair = x.value();
                    const auto recipe = pair.second;

                    std::vector<int> actual;

                    auto argTuple =
                        recipe.ingredients.front().value().get<ArgTuple>();
                    actual.push_back(std::get<0>(argTuple).value);

                    auto it = recipe.ingredients.begin() + 1;
                    for (; it != end(recipe.ingredients); it++)
                        actual.push_back(it->value().get<int>());

                    return actual == pair.first;
                }));
    }

    SECTION("works with non-copyable types") {
        auto shrinkable = execRaw([=](NonCopyable nc) {
            return std::move(nc);
        })(Random(), 0);
        REQUIRE(isArbitraryPredictable(shrinkable.value().first));
    }

    // TODO shrink tests?
}
<commit_msg>Move ExecRawTests to new framework<commit_after>#include <catch.hpp>
#include <rapidcheck-catch.h>

#include <numeric>

#include "util/Predictable.h"
#include "util/GenUtils.h"
#include "util/ArbitraryRandom.h"

#include "rapidcheck/newgen/detail/ExecRaw.h"
#include "rapidcheck/shrinkable/Operations.h"
#include "rapidcheck/seq/Operations.h"

using namespace rc;
using namespace rc::test;
using namespace rc::newgen::detail;

namespace {

template<int N>
Gen<std::pair<std::vector<int>, Recipe>> testExecGen()
{
    return execRaw(
        [=](const FixedCountdown<N> &n) {
            std::vector<int> values;
            values.push_back(n.value);
            while (values.size() < (n.value + 1))
                values.push_back(*genFixedCountdown(N));
            return values;
        });
}

} // namespace

TEST_CASE("execRaw") {
    SECTION("uses correct arbitrary instance for arguments") {
        auto values = execRaw([](
            const Predictable &a,
            const Predictable &b,
            const Predictable &c)
        {
            return std::make_tuple(a, b, c);
        })(Random(), 0).value().first;

        REQUIRE(isArbitraryPredictable(std::get<0>(values)));
        REQUIRE(isArbitraryPredictable(std::get<1>(values)));
        REQUIRE(isArbitraryPredictable(std::get<2>(values)));
    }

    SECTION("shrinks arguments like a tuple") {
        typedef std::tuple<FixedCountdown<1>,
                           FixedCountdown<2>,
                           FixedCountdown<3>> TupleT;

        auto execShrinkable = execRaw([](
            const FixedCountdown<1> &a,
            const FixedCountdown<2> &b,
            const FixedCountdown<3> &c)
        {
            return std::make_tuple(a, b, c);
        })(Random(), 0);

        auto tupleShrinkable = newgen::tuple(
            newgen::arbitrary<FixedCountdown<1>>(),
            newgen::arbitrary<FixedCountdown<2>>(),
            newgen::arbitrary<FixedCountdown<3>>())(Random(), 0);

        auto mappedShrinkable = shrinkable::map(
            execShrinkable,
            [](std::pair<TupleT, Recipe> &&x) {
                return std::move(x.first);
            });

        REQUIRE(mappedShrinkable == tupleShrinkable);
    }

    newprop(
        "traversing a random path through the shrink tree yields the expected"
        " values",
        []{
            const auto shrinkable = testExecGen<5>()(Random(), 0);
            const auto path = *newgen::container<std::vector<bool>>(
                newgen::arbitrary<bool>());

            std::vector<int> accepted = shrinkable.value().first;
            auto acceptedShrinkable = shrinkable;
            auto shrinks = shrinkable.shrinks();
            int i = 0;
            int x = 5;
            for (bool accept : path) {
                if (i >= accepted.size()) {
                    RC_ASSERT(!shrinks.next());
                    break;
                }

                auto shrink = *shrinks.next();
                auto actual = shrink.value().first;

                auto expected = accepted;
                expected[i] = --x;
                // First element determines the size
                expected.resize(expected[0] + 1);
                RC_ASSERT(actual == expected);
                if (accept) {
                    accepted = expected;
                    acceptedShrinkable = shrink;
                    shrinks = shrink.shrinks();
                }

                if (x == 0) {
                    x = 5;
                    i++;
                }
            }
        });

    newprop(
        "the number of shrinks is never never more than the sum of the number"
        " of shrinks for the requested values",
        []{
            const auto shrinkable = testExecGen<5>()(Random(), 0);

            int i = *newgen::inRange<int>(0, 5);
            const auto shrink = *seq::at(shrinkable.shrinks(), i);
            const auto value = shrink.value().first;
            int maxShrinks =
                std::accumulate(begin(value), end(value), 0);
            RC_ASSERT(seq::length(shrink.shrinks()) <= maxShrinks);
        });

    newprop(
        "passes on the correct size",
        [] {
            int expectedSize = *newgen::nonNegative<int>();
            int n = *newgen::inRange<int>(1, 10);
            auto shrinkable = execRaw([=](const PassedSize &sz) {
                *genFixedCountdown(3); // Force some shrinks
                std::vector<int> sizes;
                sizes.push_back(sz.value);
                while (sizes.size() < n)
                    sizes.push_back(*genSize());
                return sizes;
            })(Random(), expectedSize);

            auto valueShrinkable = shrinkable::map(
                shrinkable,
                [](std::pair<std::vector<int>, Recipe> &&x) {
                    return std::move(x.first);
                });

            RC_ASSERT(
                shrinkable::all(
                    valueShrinkable,
                    [=](const Shrinkable<std::vector<int>> &x) {
                        auto sizes = x.value();
                        return std::all_of(
                            begin(sizes), end(sizes),
                            [=](int sz) { return sz == expectedSize; });
                    }));
        });

    newprop(
        "passes on sequentially split generators",
        [](const Random &initial) {
            int n = *newgen::inRange<int>(1, 10);
            auto shrinkable = execRaw([=](const PassedRandom &rnd) {
                std::vector<Random> randoms;
                randoms.push_back(rnd.value);
                while (randoms.size() < n)
                    randoms.push_back(*genRandom());
                // Force some shrinks, must be last because it will steal a
                // random split otherwise
                *genFixedCountdown(3);
                return randoms;
            })(initial, 0);

            Random r(initial);
            std::vector<Random> expected;
            // The arguments are generated as a tuple so we want the same
            // splitting behavior
            expected.push_back(
                std::get<0>(newgen::tuple(genRandom())(r.split(), 0).value()));
            while (expected.size() < n)
                expected.push_back(r.split());

            auto valueShrinkable = shrinkable::map(
                shrinkable,
                [](std::pair<std::vector<Random>, Recipe> &&x) {
                    return std::move(x.first);
                });

            RC_ASSERT(
                shrinkable::all(
                    valueShrinkable,
                    [=](const Shrinkable<std::vector<Random>> &x) {
                        return x.value() == expected;
                    }));
        });

    SECTION("the ingredients of the recipe exactly match the generated value") {
        REQUIRE(
            shrinkable::all(
                testExecGen<3>()(Random(), 0),
                [](const Shrinkable<std::pair<std::vector<int>, Recipe>> &x) {
                    typedef std::tuple<FixedCountdown<3>> ArgTuple;
                    const auto pair = x.value();
                    const auto recipe = pair.second;

                    std::vector<int> actual;

                    auto argTuple =
                        recipe.ingredients.front().value().get<ArgTuple>();
                    actual.push_back(std::get<0>(argTuple).value);

                    auto it = recipe.ingredients.begin() + 1;
                    for (; it != end(recipe.ingredients); it++)
                        actual.push_back(it->value().get<int>());

                    return actual == pair.first;
                }));
    }

    SECTION("works with non-copyable types") {
        auto shrinkable = execRaw([=](NonCopyable nc) {
            return std::move(nc);
        })(Random(), 0);
        REQUIRE(isArbitraryPredictable(shrinkable.value().first));
    }

    // TODO shrink tests?
}
<|endoftext|>


<commit_before>#include "Halide.h"
#include <cstdio>
#include <cstdint>
#include "benchmark.h"

using namespace Halide;

template<typename T>
bool test(int w, bool div) {
    Func f, g, h;
    Var x, y;

    size_t bits = sizeof(T)*8;
    bool is_signed = (T)(-1) < (T)(0);

    printf("%sInt(%2d, %2d)    ",
           is_signed ? " " : "U",
           (int)bits, w);

    int min_val = 2, num_vals = 254;

    if (bits <= 8 && is_signed) {
        // There are two types of integer division that cause runtime crashes:
        // 1) Division by zero
        // 2) Division of the smallest negative number by -1 (because
        // the result overflows)
        // In either case, let's avoid overflows to dodge such errors.
        num_vals = 126;
    }

    Image<T> input(w, num_vals);

    for (int y = 0; y < num_vals; y++) {
        for (int x = 0; x < input.width(); x++) {
            uint32_t bits = rand() ^ (rand() << 16);
            input(x, y) = (T)bits;
        }
    }

    if (div) {
        // Test div
        f(x, y) = input(x, y) / cast<T>(y + min_val);

        // Reference good version
        g(x, y) = input(x, y) / cast<T>(y + min_val);

        // Version that uses fast_integer_divide
        h(x, y) = Halide::fast_integer_divide(input(x, y), cast<uint8_t>(y + min_val));
    } else {
        // Test mod
        f(x, y) = input(x, y) % cast<T>(y + min_val);

        // Reference good version
        g(x, y) = input(x, y) % cast<T>(y + min_val);

        // Version that uses fast_integer_modulo
        h(x, y) = Halide::fast_integer_modulo(input(x, y), cast<uint8_t>(y + min_val));
    }

    // Try dividing by all the known constants using vectors
    f.bound(y, 0, num_vals).bound(x, 0, input.width()).unroll(y);
    h.bound(x, 0, input.width());
    if (w > 1) {
        f.vectorize(x);
        h.vectorize(x);
    }

    f.compile_jit();
    g.compile_jit();
    h.compile_jit();

    Image<T> correct = g.realize(input.width(), num_vals);
    double t_correct = benchmark(5, 200, [&]() { g.realize(correct); });

    Image<T> fast = f.realize(input.width(), num_vals);
    double t_fast = benchmark(5, 200, [&]() { f.realize(fast); });

    Image<T> fast_dynamic = h.realize(input.width(), num_vals);
    double t_fast_dynamic = benchmark(10, 200, [&]() { h.realize(fast_dynamic); });

    printf("%6.3f                  %6.3f\n", t_correct / t_fast, t_correct / t_fast_dynamic);

    for (int y = 0; y < num_vals; y++) {
        for (int x = 0; x < input.width(); x++) {
            if (fast(x, y) != correct(x, y)) {
                printf("fast(%d, %d) = %lld instead of %lld (%lld/%d)\n",
                       x, y,
                       (long long int)fast(x, y),
                       (long long int)correct(x, y),
                       (long long int)input(x, y),
                       (T)(y + min_val));
                return false;
            }
        }
    }

    return true;

}

int main(int argc, char **argv) {

    srand(time(nullptr));

    bool success = true;
    for (int i = 0; i < 2; i++) {
        const char *name = (i == 0 ? "divisor" : "modulus");
        printf("type            const-%s speed-up  runtime-%s speed-up\n", name, name);
        // Scalar
        success = success && test<int32_t>(1, i == 0);
        success = success && test<int16_t>(1, i == 0);
        success = success && test<int8_t>(1, i == 0);
        success = success && test<uint32_t>(1, i == 0);
        success = success && test<uint16_t>(1, i == 0);
        success = success && test<uint8_t>(1, i == 0);
        // Vector
        success = success && test<int32_t>(8, i == 0);
        success = success && test<int16_t>(16, i == 0);
        success = success && test<int8_t>(32, i == 0);
        success = success && test<uint32_t>(8, i == 0);
        success = success && test<uint16_t>(16, i == 0);
        success = success && test<uint8_t>(32, i == 0);
    }

    if (success) {
        printf("Success!\n");
        return 0;
    } else {
        return -1;
    }
}
<commit_msg>Fix mismatched iteration count<commit_after>#include "Halide.h"
#include <cstdio>
#include <cstdint>
#include "benchmark.h"

using namespace Halide;

template<typename T>
bool test(int w, bool div) {
    Func f, g, h;
    Var x, y;

    size_t bits = sizeof(T)*8;
    bool is_signed = (T)(-1) < (T)(0);

    printf("%sInt(%2d, %2d)    ",
           is_signed ? " " : "U",
           (int)bits, w);

    int min_val = 2, num_vals = 254;

    if (bits <= 8 && is_signed) {
        // There are two types of integer division that cause runtime crashes:
        // 1) Division by zero
        // 2) Division of the smallest negative number by -1 (because
        // the result overflows)
        // In either case, let's avoid overflows to dodge such errors.
        num_vals = 126;
    }

    Image<T> input(w, num_vals);

    for (int y = 0; y < num_vals; y++) {
        for (int x = 0; x < input.width(); x++) {
            uint32_t bits = rand() ^ (rand() << 16);
            input(x, y) = (T)bits;
        }
    }

    if (div) {
        // Test div
        f(x, y) = input(x, y) / cast<T>(y + min_val);

        // Reference good version
        g(x, y) = input(x, y) / cast<T>(y + min_val);

        // Version that uses fast_integer_divide
        h(x, y) = Halide::fast_integer_divide(input(x, y), cast<uint8_t>(y + min_val));
    } else {
        // Test mod
        f(x, y) = input(x, y) % cast<T>(y + min_val);

        // Reference good version
        g(x, y) = input(x, y) % cast<T>(y + min_val);

        // Version that uses fast_integer_modulo
        h(x, y) = Halide::fast_integer_modulo(input(x, y), cast<uint8_t>(y + min_val));
    }

    // Try dividing by all the known constants using vectors
    f.bound(y, 0, num_vals).bound(x, 0, input.width()).unroll(y);
    h.bound(x, 0, input.width());
    if (w > 1) {
        f.vectorize(x);
        h.vectorize(x);
    }

    f.compile_jit();
    g.compile_jit();
    h.compile_jit();

    Image<T> correct = g.realize(input.width(), num_vals);
    double t_correct = benchmark(5, 200, [&]() { g.realize(correct); });

    Image<T> fast = f.realize(input.width(), num_vals);
    double t_fast = benchmark(5, 200, [&]() { f.realize(fast); });

    Image<T> fast_dynamic = h.realize(input.width(), num_vals);
    double t_fast_dynamic = benchmark(5, 200, [&]() { h.realize(fast_dynamic); });

    printf("%6.3f                  %6.3f\n", t_correct / t_fast, t_correct / t_fast_dynamic);

    for (int y = 0; y < num_vals; y++) {
        for (int x = 0; x < input.width(); x++) {
            if (fast(x, y) != correct(x, y)) {
                printf("fast(%d, %d) = %lld instead of %lld (%lld/%d)\n",
                       x, y,
                       (long long int)fast(x, y),
                       (long long int)correct(x, y),
                       (long long int)input(x, y),
                       (T)(y + min_val));
                return false;
            }
        }
    }

    return true;

}

int main(int argc, char **argv) {

    srand(time(nullptr));

    bool success = true;
    for (int i = 0; i < 2; i++) {
        const char *name = (i == 0 ? "divisor" : "modulus");
        printf("type            const-%s speed-up  runtime-%s speed-up\n", name, name);
        // Scalar
        success = success && test<int32_t>(1, i == 0);
        success = success && test<int16_t>(1, i == 0);
        success = success && test<int8_t>(1, i == 0);
        success = success && test<uint32_t>(1, i == 0);
        success = success && test<uint16_t>(1, i == 0);
        success = success && test<uint8_t>(1, i == 0);
        // Vector
        success = success && test<int32_t>(8, i == 0);
        success = success && test<int16_t>(16, i == 0);
        success = success && test<int8_t>(32, i == 0);
        success = success && test<uint32_t>(8, i == 0);
        success = success && test<uint16_t>(16, i == 0);
        success = success && test<uint8_t>(32, i == 0);
    }

    if (success) {
        printf("Success!\n");
        return 0;
    } else {
        return -1;
    }
}
<|endoftext|>


<commit_before>/*
 The class for calculating the global (not detector specific) quality assurance.
 It reuses the following TLists from its base class
    AliQADataMaker::fRecPointsQAList (for keeping the track residuals)
    AliQADataMaker::fESDsQAList      (for keeping global ESD QA data)
*/

#include <TPDGCode.h>
#include <TH1F.h>

#include "AliGlobalQADataMaker.h"
#include "AliGeomManager.h"
#include "AliESDEvent.h"
#include "AliESDv0.h"

ClassImp(AliGlobalQADataMaker)

void AliGlobalQADataMaker::InitRecPoints() {
  //------------------------------------------------------
  // This function books the histograms of *track*residuals*
  // as a part of global QA
  //------------------------------------------------------
  Char_t *name[]={
    "SPD1 residuals Y","SPD1 residuals Z",
    "SPD2 residuals Y","SPD2 residuals Z",
    "SDD1 residuals Y","SDD1 residuals Z",
    "SDD2 residuals Y","SDD2 residuals Z",
    "SSD1 residuals Y","SSD1 residuals Z",
    "SSD2 residuals Y","SSD2 residuals Z",

    "TPC1 residuals Y","TPC1 residuals Z",
    "TPC2 residuals Y","TPC2 residuals Z",

    "TRD1 residuals Y","TRD1 residuals Z",
    "TRD2 residuals Y","TRD2 residuals Z",
    "TRD3 residuals Y","TRD3 residuals Z",
    "TRD4 residuals Y","TRD4 residuals Z",
    "TRD5 residuals Y","TRD5 residuals Z",
    "TRD6 residuals Y","TRD6 residuals Z",

    "TOF residuals Y","TOF residuals Z",

    "PHOS1 residuals Y","PHOS1 residuals Z",
    "PHOS2 residuals Y","PHOS2 residuals Z",

    "HMPID residuals Y","HMPID residuals Z",

    "MUON residuals Y","MUON residuals Z",

    "EMCAL residuals Y","EMCAL residuals Z"
  };

  for (Int_t m=1; m<AliGeomManager::kLastLayer; m++) {
    Int_t i=2*m-2;
    TH1F *h=new TH1F(name[i],name[i],100,-5.,5.);
    Add2RecPointsList(h,i);
    h=new TH1F(name[i+1],name[i+1],100,-5.,5.);
    Add2RecPointsList(h,i+1);
  }
}

void AliGlobalQADataMaker::InitESDs() {
  //------------------------------------------------------
  // This function books the ESD QA histograms
  // as a part of global QA
  //------------------------------------------------------

  {// Cluster related QA
  Char_t *name[]={
    "Fraction of the assigned clusters in ITS",
    "Fraction of the assigned clusters in TPC",
    "Fraction of the assigned clusters in TRD"
  };
  Add2ESDsList(new TH1F(name[0],name[0],100,0.,2.),kClr0);
  Add2ESDsList(new TH1F(name[1],name[1],100,0.,2.),kClr1);
  Add2ESDsList(new TH1F(name[2],name[2],100,0.,2.),kClr2);
  }

  {// Track related QA
  Char_t *name[]={
    "Track azimuthal distribution (rad)",                   // kTrk0
    "Track pseudo-rapidity distribution",                   // kTrk1
    "TPC: track momentum distribution (GeV)",               // kTrk2
    "TPC-ITS matched: track momentum distribution (GeV)",   // kTrk3
    "TPC-TOF matched: track momentum distribution (GeV)",   // kTrk4
    "TPC-ITS track-matching probability",                   // kTrk5
    "TPC-TOF track-matching probability"                    // kTrk6
  };
  Add2ESDsList(new TH1F(name[0],name[0],100,-0.02,6.30),kTrk0);
  Add2ESDsList(new TH1F(name[1],name[1],100,-2.00,2.00),kTrk1);
  Add2ESDsList(new TH1F(name[2],name[2],50,  0.20,5.00),kTrk2);
  Add2ESDsList(new TH1F(name[3],name[3],50,  0.20,5.00),kTrk3);
  Add2ESDsList(new TH1F(name[4],name[4],50,  0.20,5.00),kTrk4);
  Add2ESDsList(new TH1F(name[5],name[5],50,  0.20,5.00),kTrk5);
  Add2ESDsList(new TH1F(name[6],name[6],50,  0.20,5.00),kTrk6);
  }

  {// V0 related QA
  Char_t *name[]={
    "K0s mass (GeV)",
    "Lambda0 + Lambda0Bar mass (GeV)"
  };
  Add2ESDsList(new TH1F(name[0],name[0],50,  0.4477,0.5477),kV0s0);
  Add2ESDsList(new TH1F(name[1],name[1],50,  1.0657,1.1657),kV0s1);
  }

  {// PID related QA
  Char_t *name[]={
    "ITS: dEdx (ADC) for particles with momentum 0.4 - 0.5 (GeV)",
    "TPC: dEdx (ADC) for particles with momentum 0.4 - 0.5 (GeV)",
    "TOF: tracking - measured (ps)"
  };
  Add2ESDsList(new TH1F(name[0],name[0],50,0.00,200.),kPid0);
  Add2ESDsList(new TH1F(name[1],name[1],50,0.00,100.),kPid1);
  Add2ESDsList(new TH1F(name[2],name[2],50,-3500.,3500.),kPid2);
  }

}

void AliGlobalQADataMaker::MakeESDs(AliESDEvent * event) {
  //-----------------------------------------------------------
  // This function fills the ESD QA histograms
  // as a part of global QA
  //-----------------------------------------------------------
  const AliESDEvent *esd=event;

  Int_t ntrk=esd->GetNumberOfTracks() ;
  for (Int_t i=0; i<ntrk; i++) {
    const AliESDtrack *track=esd->GetTrack(i);

    // Cluster related QA
    if (track->IsOn(AliESDtrack::kITSrefit)) {
      Int_t n=track->GetITSclusters(0);
      GetESDsData(kClr0)->Fill(Float_t(n)/6.); //6 is the number of ITS layers
    }

    if (track->IsOn(AliESDtrack::kTPCrefit)) {
      Int_t n =track->GetTPCNcls();
      Int_t nf=track->GetTPCNclsF();      // number of crossed TPC pad rows
      GetESDsData(kClr1)->Fill(Float_t(n)/nf);
    }

    if (track->IsOn(AliESDtrack::kTRDrefit)) {
      Int_t n=track->GetTRDclusters(0);
      GetESDsData(kClr2)->Fill(Float_t(n)/(6*24));//(6*24) is the number of TRD time bins
    }

    Double_t p=track->GetP();

    // Track related QA
    if (track->IsOn(AliESDtrack::kTPCrefit)) {
      Float_t dz[2];
      track->GetDZ(0.,0.,0.,esd->GetMagneticField(),dz);
      if ((TMath::Abs(dz[0])<3.) && (TMath::Abs(dz[1])<3.)) { // beam pipe
        Double_t phi=track->Phi();
	GetESDsData(kTrk0)->Fill(phi);
	Double_t y=track->Y();
	GetESDsData(kTrk1)->Fill(y);

        if (TMath::Abs(y)<0.9) {
	   GetESDsData(kTrk2)->Fill(p);
	   if (track->IsOn(AliESDtrack::kITSrefit)) GetESDsData(kTrk3)->Fill(p);
	   if (track->IsOn(AliESDtrack::kTOFout)) GetESDsData(kTrk4)->Fill(p);
	}
      }
    }

    // PID related QA
    if ((p>0.4) && (p<0.5)) {
      if (track->IsOn(AliESDtrack::kITSpid)) {
	Double_t dedx=track->GetITSsignal();
        GetESDsData(kPid0)->Fill(dedx);
      }
      if (track->IsOn(AliESDtrack::kTPCpid)) {
	Double_t dedx=track->GetTPCsignal();
        GetESDsData(kPid1)->Fill(dedx);
      }
    }
    if (p>1.0) {
      if (track->IsOn(AliESDtrack::kTOFpid)) {
        Double_t times[10];
        track->GetIntegratedTimes(times);
        Double_t tof=track->GetTOFsignal();
        GetESDsData(kPid2)->Fill(times[2]-tof);
      }
    }
  }

  TH1 *tpc=GetESDsData(kTrk2); tpc->Sumw2();
  TH1 *its=GetESDsData(kTrk3); its->Sumw2();
  TH1 *tof=GetESDsData(kTrk4); tof->Sumw2();
  GetESDsData(kTrk5)->Divide(its,tpc,1,1.,"b");
  GetESDsData(kTrk6)->Divide(tof,tpc,1,1.,"b");

  // V0 related QA
  Int_t nV0=esd->GetNumberOfV0s();
  for (Int_t i=0; i<nV0; i++) {
    Double_t mass;
    AliESDv0 v0(*esd->GetV0(i));

    v0.ChangeMassHypothesis(kK0Short);
    mass=v0.GetEffMass();
    GetESDsData(kV0s0)->Fill(mass);

    v0.ChangeMassHypothesis(kLambda0);
    mass=v0.GetEffMass();
    GetESDsData(kV0s1)->Fill(mass);

    v0.ChangeMassHypothesis(kLambda0Bar);
    mass=v0.GetEffMass();
    GetESDsData(kV0s1)->Fill(mass);
  }

}
<commit_msg>Using pseudo-rapidity getter.<commit_after>/*
 The class for calculating the global (not detector specific) quality assurance.
 It reuses the following TLists from its base class
    AliQADataMaker::fRecPointsQAList (for keeping the track residuals)
    AliQADataMaker::fESDsQAList      (for keeping global ESD QA data)
*/

#include <TPDGCode.h>
#include <TH1F.h>

#include "AliGlobalQADataMaker.h"
#include "AliGeomManager.h"
#include "AliESDEvent.h"
#include "AliESDv0.h"

ClassImp(AliGlobalQADataMaker)

void AliGlobalQADataMaker::InitRecPoints() {
  //------------------------------------------------------
  // This function books the histograms of *track*residuals*
  // as a part of global QA
  //------------------------------------------------------
  Char_t *name[]={
    "SPD1 residuals Y","SPD1 residuals Z",
    "SPD2 residuals Y","SPD2 residuals Z",
    "SDD1 residuals Y","SDD1 residuals Z",
    "SDD2 residuals Y","SDD2 residuals Z",
    "SSD1 residuals Y","SSD1 residuals Z",
    "SSD2 residuals Y","SSD2 residuals Z",

    "TPC1 residuals Y","TPC1 residuals Z",
    "TPC2 residuals Y","TPC2 residuals Z",

    "TRD1 residuals Y","TRD1 residuals Z",
    "TRD2 residuals Y","TRD2 residuals Z",
    "TRD3 residuals Y","TRD3 residuals Z",
    "TRD4 residuals Y","TRD4 residuals Z",
    "TRD5 residuals Y","TRD5 residuals Z",
    "TRD6 residuals Y","TRD6 residuals Z",

    "TOF residuals Y","TOF residuals Z",

    "PHOS1 residuals Y","PHOS1 residuals Z",
    "PHOS2 residuals Y","PHOS2 residuals Z",

    "HMPID residuals Y","HMPID residuals Z",

    "MUON residuals Y","MUON residuals Z",

    "EMCAL residuals Y","EMCAL residuals Z"
  };

  for (Int_t m=1; m<AliGeomManager::kLastLayer; m++) {
    Int_t i=2*m-2;
    TH1F *h=new TH1F(name[i],name[i],100,-5.,5.);
    Add2RecPointsList(h,i);
    h=new TH1F(name[i+1],name[i+1],100,-5.,5.);
    Add2RecPointsList(h,i+1);
  }
}

void AliGlobalQADataMaker::InitESDs() {
  //------------------------------------------------------
  // This function books the ESD QA histograms
  // as a part of global QA
  //------------------------------------------------------

  {// Cluster related QA
  Char_t *name[]={
    "Fraction of the assigned clusters in ITS",
    "Fraction of the assigned clusters in TPC",
    "Fraction of the assigned clusters in TRD"
  };
  Add2ESDsList(new TH1F(name[0],name[0],100,0.,2.),kClr0);
  Add2ESDsList(new TH1F(name[1],name[1],100,0.,2.),kClr1);
  Add2ESDsList(new TH1F(name[2],name[2],100,0.,2.),kClr2);
  }

  {// Track related QA
  Char_t *name[]={
    "Track azimuthal distribution (rad)",                   // kTrk0
    "Track pseudo-rapidity distribution",                   // kTrk1
    "TPC: track momentum distribution (GeV)",               // kTrk2
    "TPC-ITS matched: track momentum distribution (GeV)",   // kTrk3
    "TPC-TOF matched: track momentum distribution (GeV)",   // kTrk4
    "TPC-ITS track-matching probability",                   // kTrk5
    "TPC-TOF track-matching probability"                    // kTrk6
  };
  Add2ESDsList(new TH1F(name[0],name[0],100,-0.02,6.30),kTrk0);
  Add2ESDsList(new TH1F(name[1],name[1],100,-2.00,2.00),kTrk1);
  Add2ESDsList(new TH1F(name[2],name[2],50,  0.20,5.00),kTrk2);
  Add2ESDsList(new TH1F(name[3],name[3],50,  0.20,5.00),kTrk3);
  Add2ESDsList(new TH1F(name[4],name[4],50,  0.20,5.00),kTrk4);
  Add2ESDsList(new TH1F(name[5],name[5],50,  0.20,5.00),kTrk5);
  Add2ESDsList(new TH1F(name[6],name[6],50,  0.20,5.00),kTrk6);
  }

  {// V0 related QA
  Char_t *name[]={
    "K0s mass (GeV)",
    "Lambda0 + Lambda0Bar mass (GeV)"
  };
  Add2ESDsList(new TH1F(name[0],name[0],50,  0.4477,0.5477),kV0s0);
  Add2ESDsList(new TH1F(name[1],name[1],50,  1.0657,1.1657),kV0s1);
  }

  {// PID related QA
  Char_t *name[]={
    "ITS: dEdx (ADC) for particles with momentum 0.4 - 0.5 (GeV)",
    "TPC: dEdx (ADC) for particles with momentum 0.4 - 0.5 (GeV)",
    "TOF: tracking - measured (ps)"
  };
  Add2ESDsList(new TH1F(name[0],name[0],50,0.00,200.),kPid0);
  Add2ESDsList(new TH1F(name[1],name[1],50,0.00,100.),kPid1);
  Add2ESDsList(new TH1F(name[2],name[2],50,-3500.,3500.),kPid2);
  }

}

void AliGlobalQADataMaker::MakeESDs(AliESDEvent * event) {
  //-----------------------------------------------------------
  // This function fills the ESD QA histograms
  // as a part of global QA
  //-----------------------------------------------------------
  const AliESDEvent *esd=event;

  Int_t ntrk=esd->GetNumberOfTracks() ;
  for (Int_t i=0; i<ntrk; i++) {
    const AliESDtrack *track=esd->GetTrack(i);

    // Cluster related QA
    if (track->IsOn(AliESDtrack::kITSrefit)) {
      Int_t n=track->GetITSclusters(0);
      GetESDsData(kClr0)->Fill(Float_t(n)/6.); //6 is the number of ITS layers
    }

    if (track->IsOn(AliESDtrack::kTPCrefit)) {
      Int_t n =track->GetTPCNcls();
      Int_t nf=track->GetTPCNclsF();      // number of crossed TPC pad rows
      GetESDsData(kClr1)->Fill(Float_t(n)/nf);
    }

    if (track->IsOn(AliESDtrack::kTRDrefit)) {
      Int_t n=track->GetTRDclusters(0);
      GetESDsData(kClr2)->Fill(Float_t(n)/(6*24));//(6*24) is the number of TRD time bins
    }

    Double_t p=track->GetP();

    // Track related QA
    if (track->IsOn(AliESDtrack::kTPCrefit)) {
      Float_t dz[2];
      track->GetDZ(0.,0.,0.,esd->GetMagneticField(),dz);
      if ((TMath::Abs(dz[0])<3.) && (TMath::Abs(dz[1])<3.)) { // beam pipe
        Double_t phi=track->Phi();
	GetESDsData(kTrk0)->Fill(phi);
	Double_t y=track->Eta();
	GetESDsData(kTrk1)->Fill(y);

        if (TMath::Abs(y)<0.9) {
	   GetESDsData(kTrk2)->Fill(p);
	   if (track->IsOn(AliESDtrack::kITSrefit)) GetESDsData(kTrk3)->Fill(p);
	   if (track->IsOn(AliESDtrack::kTOFout)) GetESDsData(kTrk4)->Fill(p);
	}
      }
    }

    // PID related QA
    if ((p>0.4) && (p<0.5)) {
      if (track->IsOn(AliESDtrack::kITSpid)) {
	Double_t dedx=track->GetITSsignal();
        GetESDsData(kPid0)->Fill(dedx);
      }
      if (track->IsOn(AliESDtrack::kTPCpid)) {
	Double_t dedx=track->GetTPCsignal();
        GetESDsData(kPid1)->Fill(dedx);
      }
    }
    if (p>1.0) {
      if (track->IsOn(AliESDtrack::kTOFpid)) {
        Double_t times[10];
        track->GetIntegratedTimes(times);
        Double_t tof=track->GetTOFsignal();
        GetESDsData(kPid2)->Fill(times[2]-tof);
      }
    }
  }

  TH1 *tpc=GetESDsData(kTrk2); tpc->Sumw2();
  TH1 *its=GetESDsData(kTrk3); its->Sumw2();
  TH1 *tof=GetESDsData(kTrk4); tof->Sumw2();
  GetESDsData(kTrk5)->Divide(its,tpc,1,1.,"b");
  GetESDsData(kTrk6)->Divide(tof,tpc,1,1.,"b");

  // V0 related QA
  Int_t nV0=esd->GetNumberOfV0s();
  for (Int_t i=0; i<nV0; i++) {
    Double_t mass;
    AliESDv0 v0(*esd->GetV0(i));

    v0.ChangeMassHypothesis(kK0Short);
    mass=v0.GetEffMass();
    GetESDsData(kV0s0)->Fill(mass);

    v0.ChangeMassHypothesis(kLambda0);
    mass=v0.GetEffMass();
    GetESDsData(kV0s1)->Fill(mass);

    v0.ChangeMassHypothesis(kLambda0Bar);
    mass=v0.GetEffMass();
    GetESDsData(kV0s1)->Fill(mass);
  }

}
<|endoftext|>


<commit_before>#include <vector>
#include <Poco/Exception.h>

#include "service/GatewayService.h"
#include "server/AccessLevel.h"
#include "dao/GatewayDao.h"
#include "dao/RoleInPlaceDao.h"
#include "dao/PlaceDao.h"
#include "dao/IdentityDao.h"
#include "dao/VerifiedIdentityDao.h"
#include "policy/GatewayAccessPolicy.h"

BEEEON_OBJECT(GatewayService, BeeeOn::GatewayService)

using namespace std;
using namespace Poco;
using namespace BeeeOn;

GatewayService::GatewayService():
	m_gatewayDao(&NullGatewayDao::instance()),
	m_roleInPlaceDao(&NullRoleInPlaceDao::instance()),
	m_placeDao(&NullPlaceDao::instance()),
	m_identityDao(&NullIdentityDao::instance()),
	m_rpc(&NullGatewayRPC::instance()),
	m_accessPolicy(&NullGatewayAccessPolicy::instance())
{
	injector<GatewayService, GatewayDao>("gatewayDao",
			&GatewayService::setGatewayDao);
	injector<GatewayService, RoleInPlaceDao>("roleInPlaceDao",
			&GatewayService::setRoleInPlaceDao);
	injector<GatewayService, PlaceDao>("placeDao",
			&GatewayService::setPlaceDao);
	injector<GatewayService, IdentityDao>("identityDao",
			&GatewayService::setIdentityDao);
	injector<GatewayService, VerifiedIdentityDao>("verifiedIdentityDao",
			&GatewayService::setVerifiedIdentityDao);
	injector<GatewayService, GatewayRPC>("gatewayRPC",
			&GatewayService::setGatewayRPC);
	injector<GatewayService, GatewayAccessPolicy>("accessPolicy",
			&GatewayService::setAccessPolicy);
}

void GatewayService::setGatewayDao(GatewayDao *dao)
{
	m_gatewayDao = dao? dao : &NullGatewayDao::instance();
}

void GatewayService::setRoleInPlaceDao(RoleInPlaceDao *dao)
{
	m_roleInPlaceDao = dao? dao :&NullRoleInPlaceDao::instance();
}

void GatewayService::setPlaceDao(PlaceDao *dao)
{
	m_placeDao = dao? dao : &NullPlaceDao::instance();
}

void GatewayService::setIdentityDao(IdentityDao *dao)
{
	m_identityDao = dao? dao :&NullIdentityDao::instance();
}

void GatewayService::setVerifiedIdentityDao(VerifiedIdentityDao *dao)
{
	m_verifiedIdentityDao = dao? dao :
			&NullVerifiedIdentityDao::instance();
}

void GatewayService::setGatewayRPC(GatewayRPC *rpc)
{
	m_rpc = rpc? rpc : &NullGatewayRPC::instance();
}

void GatewayService::setAccessPolicy(GatewayAccessPolicy *policy)
{
	m_accessPolicy = policy? policy :
		&NullGatewayAccessPolicy::instance();
}

bool GatewayService::registerGateway(SingleWithData<Gateway> &input,
		const VerifiedIdentity &verifiedIdentity)
{
	VerifiedIdentity tmp(verifiedIdentity);

	if (!m_verifiedIdentityDao->fetch(tmp))
		throw InvalidArgumentException("invalid verified identity");

	Gateway &gateway = input.target();

	if (!m_gatewayDao->fetch(gateway))
		throw NotFoundException("gateway was not found");

	if (gateway.hasPlace()) {
		const AccessLevel &level = m_roleInPlaceDao->
			fetchAccessLevel(gateway.place(), tmp.user());

		if (level <= AccessLevel::admin()) // is owner
			throw ExistsException("gateway is already assigned");

		throw NotFoundException("gateway is owned by somebody else");
	}

	vector<Place> places;
	m_roleInPlaceDao->fetchAccessiblePlaces(
			places, tmp.user(), AccessLevel::admin());

	if (places.size() > 1)
		throw IllegalStateException("too many places, incompatible");

	if (places.size() == 0) {
		Place place;
		createImplicitPlace(place, tmp.identity());
		places.push_back(place);
	}

	m_accessPolicy->assureAssignGateway(input, places.front());

	input.data().full(gateway);
	return m_gatewayDao->assignAndUpdate(gateway, places.front());
}

void GatewayService::createImplicitPlace(Place &place, const Identity &identity)
{
	place.setName("Implicit");

	m_placeDao->create(place);

	RoleInPlace role;
	role.setPlace(place);
	role.setIdentity(identity);
	role.setLevel(AccessLevel::admin());

	m_roleInPlaceDao->create(role);
}

bool GatewayService::fetch(Single<Gateway> &input)
{
	m_accessPolicy->assureGet(input, input.target());

	return m_gatewayDao->fetch(input.target());
}

bool GatewayService::fetchFromPlace(Relation<Gateway, Place> &input)
{
	m_accessPolicy->assureGet(input, input.target());

	return m_gatewayDao->fetchFromPlace(input.target(), input.base());
}

void GatewayService::fetchAccessible(Relation<vector<Gateway>, User> &input)
{
	m_gatewayDao->fetchAccessible(input.target(), input.base());
}

bool GatewayService::update(SingleWithData<Gateway> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureUpdate(input, gateway);

	if (!m_gatewayDao->fetch(gateway))
		throw NotFoundException("gateway does not exist");

	input.data().partial(gateway);
	return m_gatewayDao->update(gateway);
}

bool GatewayService::updateInPlace(RelationWithData<Gateway, Place> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureUpdate(input, gateway);

	if (!m_gatewayDao->fetchFromPlace(gateway, input.base()))
		throw NotFoundException("gateway does not exist");

	input.data().partial(gateway);

	return m_gatewayDao->update(gateway);
}

bool GatewayService::assignAndUpdate(
		RelationWithData<Gateway, Place> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureAssignGateway(input, input.base());

	if (!m_gatewayDao->fetch(gateway))
		throw NotFoundException("gateway does not exist");

	if (gateway.hasPlace()) // do not leak it exists
		throw NotFoundException("gateway is already assigned");

	input.data().partial(gateway);

	return m_gatewayDao->assignAndUpdate(gateway, input.base());
}

bool GatewayService::unassign(Relation<Gateway, Place> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureUnassign(input, input.target());

	if (!m_gatewayDao->fetchFromPlace(gateway, input.base()))
		return false;

	return m_gatewayDao->unassign(gateway);
}

bool GatewayService::unassign(Relation<Gateway, User> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureUnassign(input, input.target());

	if (!m_gatewayDao->fetch(gateway))
		throw NotFoundException("gateway does not exist");

	if (!gateway.hasPlace()) // do not leak that this gateway exists
		throw NotFoundException("gateway is not assigned");

	return m_gatewayDao->unassign(gateway);
}

void GatewayService::scanDevices(Single<Gateway> &input)
{
	m_accessPolicy->assureScanDevices(input, input.target());

	m_rpc->sendListen(input.target());
}

void GatewayService::unpairDevice(Single<Gateway> &input, Device &device)
{
	m_rpc->unpairDevice(input.target(), device);
}

void GatewayService::pingGateway(Single<Gateway> &input)
{
	m_rpc->pingGateway(input.target());
}
<commit_msg>GatewayService: always create an implicit place on register<commit_after>#include <vector>
#include <Poco/Exception.h>

#include "service/GatewayService.h"
#include "server/AccessLevel.h"
#include "dao/GatewayDao.h"
#include "dao/RoleInPlaceDao.h"
#include "dao/PlaceDao.h"
#include "dao/IdentityDao.h"
#include "dao/VerifiedIdentityDao.h"
#include "policy/GatewayAccessPolicy.h"

BEEEON_OBJECT(GatewayService, BeeeOn::GatewayService)

using namespace std;
using namespace Poco;
using namespace BeeeOn;

GatewayService::GatewayService():
	m_gatewayDao(&NullGatewayDao::instance()),
	m_roleInPlaceDao(&NullRoleInPlaceDao::instance()),
	m_placeDao(&NullPlaceDao::instance()),
	m_identityDao(&NullIdentityDao::instance()),
	m_rpc(&NullGatewayRPC::instance()),
	m_accessPolicy(&NullGatewayAccessPolicy::instance())
{
	injector<GatewayService, GatewayDao>("gatewayDao",
			&GatewayService::setGatewayDao);
	injector<GatewayService, RoleInPlaceDao>("roleInPlaceDao",
			&GatewayService::setRoleInPlaceDao);
	injector<GatewayService, PlaceDao>("placeDao",
			&GatewayService::setPlaceDao);
	injector<GatewayService, IdentityDao>("identityDao",
			&GatewayService::setIdentityDao);
	injector<GatewayService, VerifiedIdentityDao>("verifiedIdentityDao",
			&GatewayService::setVerifiedIdentityDao);
	injector<GatewayService, GatewayRPC>("gatewayRPC",
			&GatewayService::setGatewayRPC);
	injector<GatewayService, GatewayAccessPolicy>("accessPolicy",
			&GatewayService::setAccessPolicy);
}

void GatewayService::setGatewayDao(GatewayDao *dao)
{
	m_gatewayDao = dao? dao : &NullGatewayDao::instance();
}

void GatewayService::setRoleInPlaceDao(RoleInPlaceDao *dao)
{
	m_roleInPlaceDao = dao? dao :&NullRoleInPlaceDao::instance();
}

void GatewayService::setPlaceDao(PlaceDao *dao)
{
	m_placeDao = dao? dao : &NullPlaceDao::instance();
}

void GatewayService::setIdentityDao(IdentityDao *dao)
{
	m_identityDao = dao? dao :&NullIdentityDao::instance();
}

void GatewayService::setVerifiedIdentityDao(VerifiedIdentityDao *dao)
{
	m_verifiedIdentityDao = dao? dao :
			&NullVerifiedIdentityDao::instance();
}

void GatewayService::setGatewayRPC(GatewayRPC *rpc)
{
	m_rpc = rpc? rpc : &NullGatewayRPC::instance();
}

void GatewayService::setAccessPolicy(GatewayAccessPolicy *policy)
{
	m_accessPolicy = policy? policy :
		&NullGatewayAccessPolicy::instance();
}

bool GatewayService::registerGateway(SingleWithData<Gateway> &input,
		const VerifiedIdentity &verifiedIdentity)
{
	VerifiedIdentity tmp(verifiedIdentity);

	if (!m_verifiedIdentityDao->fetch(tmp))
		throw InvalidArgumentException("invalid verified identity");

	Gateway &gateway = input.target();

	if (!m_gatewayDao->fetch(gateway))
		throw NotFoundException("gateway was not found");

	if (gateway.hasPlace()) {
		const AccessLevel &level = m_roleInPlaceDao->
			fetchAccessLevel(gateway.place(), tmp.user());

		if (level <= AccessLevel::admin()) // is owner
			throw ExistsException("gateway is already assigned");

		throw NotFoundException("gateway is owned by somebody else");
	}

	Place place;
	createImplicitPlace(place, tmp.identity());

	m_accessPolicy->assureAssignGateway(input, place);

	input.data().full(gateway);
	return m_gatewayDao->assignAndUpdate(gateway, place);
}

void GatewayService::createImplicitPlace(Place &place, const Identity &identity)
{
	place.setName("Implicit");

	m_placeDao->create(place);

	RoleInPlace role;
	role.setPlace(place);
	role.setIdentity(identity);
	role.setLevel(AccessLevel::admin());

	m_roleInPlaceDao->create(role);
}

bool GatewayService::fetch(Single<Gateway> &input)
{
	m_accessPolicy->assureGet(input, input.target());

	return m_gatewayDao->fetch(input.target());
}

bool GatewayService::fetchFromPlace(Relation<Gateway, Place> &input)
{
	m_accessPolicy->assureGet(input, input.target());

	return m_gatewayDao->fetchFromPlace(input.target(), input.base());
}

void GatewayService::fetchAccessible(Relation<vector<Gateway>, User> &input)
{
	m_gatewayDao->fetchAccessible(input.target(), input.base());
}

bool GatewayService::update(SingleWithData<Gateway> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureUpdate(input, gateway);

	if (!m_gatewayDao->fetch(gateway))
		throw NotFoundException("gateway does not exist");

	input.data().partial(gateway);
	return m_gatewayDao->update(gateway);
}

bool GatewayService::updateInPlace(RelationWithData<Gateway, Place> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureUpdate(input, gateway);

	if (!m_gatewayDao->fetchFromPlace(gateway, input.base()))
		throw NotFoundException("gateway does not exist");

	input.data().partial(gateway);

	return m_gatewayDao->update(gateway);
}

bool GatewayService::assignAndUpdate(
		RelationWithData<Gateway, Place> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureAssignGateway(input, input.base());

	if (!m_gatewayDao->fetch(gateway))
		throw NotFoundException("gateway does not exist");

	if (gateway.hasPlace()) // do not leak it exists
		throw NotFoundException("gateway is already assigned");

	input.data().partial(gateway);

	return m_gatewayDao->assignAndUpdate(gateway, input.base());
}

bool GatewayService::unassign(Relation<Gateway, Place> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureUnassign(input, input.target());

	if (!m_gatewayDao->fetchFromPlace(gateway, input.base()))
		return false;

	return m_gatewayDao->unassign(gateway);
}

bool GatewayService::unassign(Relation<Gateway, User> &input)
{
	Gateway &gateway = input.target();

	m_accessPolicy->assureUnassign(input, input.target());

	if (!m_gatewayDao->fetch(gateway))
		throw NotFoundException("gateway does not exist");

	if (!gateway.hasPlace()) // do not leak that this gateway exists
		throw NotFoundException("gateway is not assigned");

	return m_gatewayDao->unassign(gateway);
}

void GatewayService::scanDevices(Single<Gateway> &input)
{
	m_accessPolicy->assureScanDevices(input, input.target());

	m_rpc->sendListen(input.target());
}

void GatewayService::unpairDevice(Single<Gateway> &input, Device &device)
{
	m_rpc->unpairDevice(input.target(), device);
}

void GatewayService::pingGateway(Single<Gateway> &input)
{
	m_rpc->pingGateway(input.target());
}
<|endoftext|>


<commit_before>#include "mex.h"
#include "matrix.h"
#include <cmath>
#include <cstdint>
#include <thread>
#include <emmintrin.h>

/*
 * compilation, at matlab prompt: (adjust NUM_THREADS as appropriate)
 *
 * == windows ==
 *
 * mex OPTIMFLAGS="/O2" -largeArrayDims -DNUM_THREADS=4 dmsm.cpp
 *
 * == linux ==
 *
 * mex OPTIMFLAGS="-O3" -largeArrayDims -DNUM_THREADS=4 -v CXXFLAGS='$CXXFLAGS -std=c++0x -fPIC' dmsm.cpp
 */

#define DENSE_MATRIX_PARAMETER_IN     prhs[0]
#define SPARSE_MATRIX_PARAMETER_IN    prhs[1]
#define DIAG_VECTOR_PARAMETER_IN      prhs[2]
#define START_PARAMETER_IN            prhs[3]
#define END_PARAMETER_IN              prhs[4]

// X = D*S => X' = S'*D'

template<typename scalar>
static void
sparsetic_times_densetic (int nrhs, const mxArray* prhs[], mxArray* plhs[], size_t start, size_t end)
{
  mwIndex* ir = mxGetIr(SPARSE_MATRIX_PARAMETER_IN);  /* Row indexing      */
  mwIndex* jc = mxGetJc(SPARSE_MATRIX_PARAMETER_IN);  /* Column count      */
  double* s  = mxGetPr(SPARSE_MATRIX_PARAMETER_IN);   /* Non-zero elements */
  scalar* Btic = (scalar*) mxGetData(DENSE_MATRIX_PARAMETER_IN);
  mwSize Bcol = mxGetM(DENSE_MATRIX_PARAMETER_IN);
  scalar* Xtic = (scalar*) mxGetData(plhs[0]);
  mwSize Xcol = mxGetM(plhs[0]);

  size_t off = 0;

  if (nrhs > 3) {
    off = mxGetScalar(START_PARAMETER_IN) - 1;
  }

  if (nrhs == 2) {
    for (size_t i=start; i<end; ++i) {            /* Loop through rows of A (and X) */
      mwIndex stop = jc[off+i+1];
      for (mwIndex k=jc[off+i]; k<stop; ++k) {    /* Loop through non-zeros in ith row of A */
        double sk = s[k];
        scalar* Bticrow = Btic + ir[k] * Bcol;
        scalar* Xticrow = Xtic + i * Xcol;
        for (mwSize j=0; j<Xcol; ++j) {
          Xticrow[j] += sk * Bticrow[j];
        }
      }
    }
  }
  else {
    double* w = mxGetPr(DIAG_VECTOR_PARAMETER_IN);

    for (size_t i=start; i<end; ++i) {            /* Loop through rows of A (and X) */
      double wi = w[off+i];
      mwIndex stop = jc[off+i+1];
      for (mwIndex k=jc[off+i]; k<stop; ++k) {    /* Loop through non-zeros in ith row of A */
        double sk = wi * s[k];
        scalar* Bticrow = Btic + ir[k] * Bcol;
        scalar* Xticrow = Xtic + i * Xcol;
        for (mwSize j=0; j<Xcol; ++j) {
          Xticrow[j] += sk * Bticrow[j];
        }
      }
    }
  }
}

static int first = 1;

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray*prhs[] ) {
  if (first) {
    mexPrintf("dmsm using NUM_THREADS=%u\n",NUM_THREADS);
    first=0;
  }

  switch (nrhs) {
    case 5:
      if (mxGetM(END_PARAMETER_IN) != 1 || mxGetN(END_PARAMETER_IN) != 1) {
        mexErrMsgTxt("End must be a scalar. Fail.");
        return;
      }

      // fall through

    case 4:
      if (mxGetM(START_PARAMETER_IN) != 1 || mxGetN(START_PARAMETER_IN) != 1) {
        mexErrMsgTxt("Start must be a scalar. Fail.");
        return;
      }

      // fall through

    case 3:
      if (mxIsSparse(DIAG_VECTOR_PARAMETER_IN)) {
        mexErrMsgTxt("Scale must be dense. Fail.");
        return;
      }

      if (mxGetM(DIAG_VECTOR_PARAMETER_IN) != 1 ||
          mxGetN(DIAG_VECTOR_PARAMETER_IN) != mxGetN(SPARSE_MATRIX_PARAMETER_IN)) {
        mexErrMsgTxt("Scale has incompatible shape. Fail.");
        return;
      }

      // fall through

    case 2:
      if (! mxIsSparse(SPARSE_MATRIX_PARAMETER_IN) || mxIsSparse(DENSE_MATRIX_PARAMETER_IN)) {
        mexErrMsgTxt("Require one sparse and one dense argument. Fail.");
        return;
      }
      if (mxGetM(SPARSE_MATRIX_PARAMETER_IN) != mxGetN(DENSE_MATRIX_PARAMETER_IN)) {
        mexErrMsgTxt("Arguments have incompatible shape. Fail.");
        return;
      }

      if (! mxIsSingle(DENSE_MATRIX_PARAMETER_IN) &&
          ! mxIsDouble(DENSE_MATRIX_PARAMETER_IN)) {
        mexErrMsgTxt("Dense argument must be double or single. Fail.");
        return;
      }

      break;
    default:
      mexErrMsgTxt("Wrong number of arguments. Fail.");
      return;
  }

  bool singlePrec = mxIsSingle(DENSE_MATRIX_PARAMETER_IN);

  void* Btic = mxGetData(DENSE_MATRIX_PARAMETER_IN);
  size_t Bcol = mxGetM(DENSE_MATRIX_PARAMETER_IN);

  size_t Arow = mxGetN(SPARSE_MATRIX_PARAMETER_IN);
  size_t start = 1;
  size_t end = Arow;

  switch (nrhs)
    {
      case 5:
        end = mxGetScalar(END_PARAMETER_IN);

        if (end > Arow) {
          mexErrMsgTxt("End is invalid.  Fail.");
          return;
        }

        // fall through
      case 4:
        start = mxGetScalar(START_PARAMETER_IN);

        if (start < 1) {
          mexErrMsgTxt("Start is invalid.  Fail.");
          return;
        }

        break;

      default:
        break;
    }

  plhs[0] = mxCreateNumericMatrix(Bcol, 1+end-start, (singlePrec) ? mxSINGLE_CLASS : mxDOUBLE_CLASS, mxREAL);

  std::thread t[NUM_THREADS];
  size_t quot = (1+end-start)/NUM_THREADS;

  for (size_t i = 0; i + 1 < NUM_THREADS; ++i) {
    if (singlePrec) {
      t[i] = std::thread(sparsetic_times_densetic<float>,
                         nrhs,
                         prhs,
                         plhs,
                         i * quot,
                         (i + 1) * quot);
    }
    else {
      t[i] = std::thread(sparsetic_times_densetic<double>,
                         nrhs,
                         prhs,
                         plhs,
                         i * quot,
                         (i + 1) * quot);
    }
  }

  if (singlePrec) {
    sparsetic_times_densetic<float> (nrhs, prhs, plhs, (NUM_THREADS - 1) * quot, 1 + end - start);
  }
  else {
    sparsetic_times_densetic<double> (nrhs, prhs, plhs, (NUM_THREADS - 1) * quot, 1 + end - start);
  }

  for (int i = 0; i + 1 < NUM_THREADS; ++i) {
    t[i].join ();
  }

  return;
}
<commit_msg>dmsm single precision weights<commit_after>#include "mex.h"
#include "matrix.h"
#include <cmath>
#include <cstdint>
#include <thread>
#include <emmintrin.h>

/* % dense matrix times sparse matrix
 * >> A=sprandn(100,100,0.1); W=ones(1,100); B=randn(5,100); Z=B*diag(W)*A; ZZ=dmsm(B,A,W); disp(norm(Z-ZZ))
 *      0
 * % dense matrix times scaled sparse matrix
 * >> A=sprandn(100,100,0.1); W=randn(1,100); B=randn(5,100); Z=B*A*diag(W); ZZ=dmsm(B,A,W); disp(norm(Z-ZZ))
      9.1859e-15
 */

/*
 * compilation, at matlab prompt: (adjust NUM_THREADS as appropriate)
 *
 * == windows ==
 *
 * mex OPTIMFLAGS="/O2" -largeArrayDims -DNUM_THREADS=4 dmsm.cpp
 *
 * == linux ==
 *
 * mex OPTIMFLAGS="-O3" -largeArrayDims -DNUM_THREADS=4 -v CXXFLAGS='$CXXFLAGS -std=c++0x -fPIC' dmsm.cpp
 */

#define DENSE_MATRIX_PARAMETER_IN     prhs[0]
#define SPARSE_MATRIX_PARAMETER_IN    prhs[1]
#define DIAG_VECTOR_PARAMETER_IN      prhs[2]
#define START_PARAMETER_IN            prhs[3]
#define END_PARAMETER_IN              prhs[4]

// X = D*S => X' = S'*D'

static void
sparsetic_times_densetic (int nrhs, const mxArray* prhs[], mxArray* plhs[], size_t start, size_t end)
{
  mwIndex* ir = mxGetIr(SPARSE_MATRIX_PARAMETER_IN);  /* Row indexing      */
  mwIndex* jc = mxGetJc(SPARSE_MATRIX_PARAMETER_IN);  /* Column count      */
  double* s  = mxGetPr(SPARSE_MATRIX_PARAMETER_IN);   /* Non-zero elements */
  void* Btic = mxGetData(DENSE_MATRIX_PARAMETER_IN);
  mwSize Bcol = mxGetM(DENSE_MATRIX_PARAMETER_IN);
  void* Xtic = mxGetData(plhs[0]);
  mwSize Xcol = mxGetM(plhs[0]);

  bool singlePrec = mxIsSingle(DENSE_MATRIX_PARAMETER_IN);

  size_t off = 0;

  if (nrhs > 3) {
    off = mxGetScalar(START_PARAMETER_IN) - 1;
  }

  if (nrhs == 2) {
    if (singlePrec) {
      for (size_t i=start; i<end; ++i) {            /* Loop through rows of A (and X) */
        mwIndex stop = jc[off+i+1];
        for (mwIndex k=jc[off+i]; k<stop; ++k) {    /* Loop through non-zeros in ith row of A */
          double sk = s[k];
          float* Bticrow = ((float*)Btic) + ir[k] * Bcol;
          float* Xticrow = ((float*)Xtic) + i * Xcol;
          for (mwSize j=0; j<Xcol; ++j) {
            Xticrow[j] += sk * Bticrow[j];
          }
        }
      }
    }
    else {
      for (size_t i=start; i<end; ++i) {            /* Loop through rows of A (and X) */
        mwIndex stop = jc[off+i+1];
        for (mwIndex k=jc[off+i]; k<stop; ++k) {    /* Loop through non-zeros in ith row of A */
          double sk = s[k];
          double* Bticrow = ((double*)Btic) + ir[k] * Bcol;
          double* Xticrow = ((double*)Xtic) + i * Xcol;
          for (mwSize j=0; j<Xcol; ++j) {
            Xticrow[j] += sk * Bticrow[j];
          }
        }
      }
    }
  }
  else {
    bool diagsinglePrec = mxIsSingle(DIAG_VECTOR_PARAMETER_IN);
    float* wf = (float*) mxGetPr(DIAG_VECTOR_PARAMETER_IN);
    double* wd = (double*) mxGetPr(DIAG_VECTOR_PARAMETER_IN);

    if (singlePrec) {
      for (size_t i=start; i<end; ++i) {            /* Loop through rows of A (and X) */
        double wi = diagsinglePrec ? wf[off+i] : wd[off+i];
        mwIndex stop = jc[off+i+1];
        for (mwIndex k=jc[off+i]; k<stop; ++k) {    /* Loop through non-zeros in ith row of A */
          double sk = wi * s[k];
          float* Bticrow = ((float*)Btic) + ir[k] * Bcol;
          float* Xticrow = ((float*)Xtic) + i * Xcol;
          for (mwSize j=0; j<Xcol; ++j) {
            Xticrow[j] += sk * Bticrow[j];
          }
        }
      }
    }
    else {
      for (size_t i=start; i<end; ++i) {            /* Loop through rows of A (and X) */
        double wi = diagsinglePrec ? wf[off+i] : wd[off+i];
        mwIndex stop = jc[off+i+1];
        for (mwIndex k=jc[off+i]; k<stop; ++k) {    /* Loop through non-zeros in ith row of A */
          double sk = wi * s[k];
          double* Bticrow = ((double*)Btic) + ir[k] * Bcol;
          double* Xticrow = ((double*)Xtic) + i * Xcol;
          for (mwSize j=0; j<Xcol; ++j) {
            Xticrow[j] += sk * Bticrow[j];
          }
        }
      }
    }
  }
}

static int first = 1;

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray*prhs[] ) {
  if (first) {
    mexPrintf("dmsm using NUM_THREADS=%u\n",NUM_THREADS);
    first=0;
  }

  switch (nrhs) {
    case 5:
      if (mxGetM(END_PARAMETER_IN) != 1 || mxGetN(END_PARAMETER_IN) != 1) {
        mexErrMsgTxt("End must be a scalar. Fail.");
        return;
      }

      // fall through

    case 4:
      if (mxGetM(START_PARAMETER_IN) != 1 || mxGetN(START_PARAMETER_IN) != 1) {
        mexErrMsgTxt("Start must be a scalar. Fail.");
        return;
      }

      // fall through

    case 3:
      if (mxIsSparse(DIAG_VECTOR_PARAMETER_IN)) {
        mexErrMsgTxt("Scale must be dense. Fail.");
        return;
      }

      if (! mxIsSingle(DIAG_VECTOR_PARAMETER_IN) &&
          ! mxIsDouble(DIAG_VECTOR_PARAMETER_IN)) {
        mexErrMsgTxt("Scale must be double or single. Fail.");
        return;
      }

      if (mxGetM(DIAG_VECTOR_PARAMETER_IN) != 1 ||
          mxGetN(DIAG_VECTOR_PARAMETER_IN) != mxGetN(SPARSE_MATRIX_PARAMETER_IN)) {
        mexErrMsgTxt("Scale has incompatible shape. Fail.");
        return;
      }

      // fall through

    case 2:
      if (! mxIsSparse(SPARSE_MATRIX_PARAMETER_IN) || mxIsSparse(DENSE_MATRIX_PARAMETER_IN)) {
        mexErrMsgTxt("Require one sparse and one dense argument. Fail.");
        return;
      }
      if (mxGetM(SPARSE_MATRIX_PARAMETER_IN) != mxGetN(DENSE_MATRIX_PARAMETER_IN)) {
        mexErrMsgTxt("Arguments have incompatible shape. Fail.");
        return;
      }

      if (! mxIsSingle(DENSE_MATRIX_PARAMETER_IN) &&
          ! mxIsDouble(DENSE_MATRIX_PARAMETER_IN)) {
        mexErrMsgTxt("Dense argument must be double or single. Fail.");
        return;
      }

      break;
    default:
      mexErrMsgTxt("Wrong number of arguments. Fail.");
      return;
  }

  size_t Bcol = mxGetM(DENSE_MATRIX_PARAMETER_IN);

  size_t Arow = mxGetN(SPARSE_MATRIX_PARAMETER_IN);
  size_t start = 1;
  size_t end = Arow;

  switch (nrhs)
    {
      case 5:
        end = mxGetScalar(END_PARAMETER_IN);

        if (end > Arow) {
          mexErrMsgTxt("End is invalid.  Fail.");
          return;
        }

        // fall through
      case 4:
        start = mxGetScalar(START_PARAMETER_IN);

        if (start < 1) {
          mexErrMsgTxt("Start is invalid.  Fail.");
          return;
        }

        break;

      default:
        break;
    }

  bool singlePrec = mxIsSingle(DENSE_MATRIX_PARAMETER_IN);
  plhs[0] = mxCreateNumericMatrix(Bcol, 1+end-start, (singlePrec) ? mxSINGLE_CLASS : mxDOUBLE_CLASS, mxREAL);

  std::thread t[NUM_THREADS];
  size_t quot = (1+end-start)/NUM_THREADS;

  for (size_t i = 0; i + 1 < NUM_THREADS; ++i) {
    t[i] = std::thread(sparsetic_times_densetic,
                       nrhs,
                       prhs,
                       plhs,
                       i * quot,
                       (i + 1) * quot);
  }

  sparsetic_times_densetic (nrhs, prhs, plhs, (NUM_THREADS - 1) * quot, 1 + end - start);

  for (int i = 0; i + 1 < NUM_THREADS; ++i) {
    t[i].join ();
  }

  return;
}
<|endoftext|>


<commit_before>/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
 *
 * Copyright 2012 Matthew McCormick
 * Copyright 2015 Pawel 'l0ner' Soltys
 *
 * 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 <sstream>

#include "memory.h"
#include "luts.h"
#include "conversions.h"
#include "powerline.h"

std::string mem_string( const MemoryStatus & mem_status,
  MEMORY_MODE mode,
  bool use_colors,
  bool use_powerline_left,
  bool use_powerline_right )
{
  std::ostringstream oss;
  // Change the percision for floats, for a pretty output
  oss.precision( 2 );
  oss.setf( std::ios::fixed | std::ios::right );

  unsigned int color = static_cast< unsigned int >((100 * mem_status.used_mem) / mem_status.total_mem);
  if( use_colors )
  {
    if( use_powerline_right )
    {
      oss << "#[bg=default]";
      powerline( oss, mem_lut[color], POWERLINE_RIGHT );
      oss << ' ';
    }
    else if( use_powerline_left )
    {
      //powerline( oss, mem_lut[color], POWERLINE_LEFT );
      // We do not know how to invert the default background color
      powerline( oss, mem_lut[color], NONE );
      oss << ' ';
    }
    else
    {
      powerline( oss, mem_lut[color], NONE );
    }
  }

  switch( mode )
  {
  case MEMORY_MODE_FREE_MEMORY: // Show free memory in MB or GB
    {
    const float free_mem = mem_status.total_mem - mem_status.used_mem;
    const float free_mem_in_gigabytes = convert_unit( free_mem, GIGABYTES, MEGABYTES );

    // if free memory is less than 1 GB, use MB instead
    if(  free_mem_in_gigabytes < 1.0f )
    {
      oss << free_mem << "MB";
    }
    else
    {
      oss << free_mem_in_gigabytes << "GB";
    }
    break;
    }
  case MEMORY_MODE_USAGE_PERCENTAGE:
    {
    // Calculate the percentage of used memory
    const float percentage_mem = mem_status.used_mem /
      static_cast<float>( mem_status.total_mem ) * 100.0;

    oss << percentage_mem << '%';
    break;
    }
  default: // Default mode, just show the used/total memory in MB
    if(mem_status.used_mem>10000 && mem_status.total_mem>10000)
      oss<<static_cast<unsigned int>(mem_status.used_mem/1024)<<"/"<<static_cast<unsigned int>(mem_status.total_mem/1024)<<"GB";
    else if(mem_status.used_mem<10000 && mem_status.total_mem>10000)
      oss<<static_cast<unsigned int>(mem_status.used_mem)<<"MB/"<<static_cast<unsigned int>(mem_status.total_mem/1024)<<"GB";
    else
      oss<<static_cast<unsigned int>(mem_status.used_mem)<<"/"<<static_cast<unsigned int>(mem_status.total_mem)<<"MB";
  }

  if( use_colors )
  {
    if( use_powerline_left )
    {
      powerline( oss, mem_lut[color], POWERLINE_LEFT, true );
    }
    else if( !use_powerline_right )
    {
      oss << "#[fg=default,bg=default]";
    }
  }

  return oss.str();
}

<commit_msg>Undefined references to std::string in aarch64 build<commit_after>/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
 *
 * Copyright 2012 Matthew McCormick
 * Copyright 2015 Pawel 'l0ner' Soltys
 *
 * 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 <sstream>
#include <string>

#include "memory.h"
#include "luts.h"
#include "conversions.h"
#include "powerline.h"

std::string mem_string( const MemoryStatus & mem_status,
  MEMORY_MODE mode,
  bool use_colors,
  bool use_powerline_left,
  bool use_powerline_right )
{
  std::ostringstream oss;
  // Change the percision for floats, for a pretty output
  oss.precision( 2 );
  oss.setf( std::ios::fixed | std::ios::right );

  unsigned int color = static_cast< unsigned int >((100 * mem_status.used_mem) / mem_status.total_mem);
  if( use_colors )
  {
    if( use_powerline_right )
    {
      oss << "#[bg=default]";
      powerline( oss, mem_lut[color], POWERLINE_RIGHT );
      oss << ' ';
    }
    else if( use_powerline_left )
    {
      //powerline( oss, mem_lut[color], POWERLINE_LEFT );
      // We do not know how to invert the default background color
      powerline( oss, mem_lut[color], NONE );
      oss << ' ';
    }
    else
    {
      powerline( oss, mem_lut[color], NONE );
    }
  }

  switch( mode )
  {
  case MEMORY_MODE_FREE_MEMORY: // Show free memory in MB or GB
    {
    const float free_mem = mem_status.total_mem - mem_status.used_mem;
    const float free_mem_in_gigabytes = convert_unit( free_mem, GIGABYTES, MEGABYTES );

    // if free memory is less than 1 GB, use MB instead
    if(  free_mem_in_gigabytes < 1.0f )
    {
      oss << free_mem << "MB";
    }
    else
    {
      oss << free_mem_in_gigabytes << "GB";
    }
    break;
    }
  case MEMORY_MODE_USAGE_PERCENTAGE:
    {
    // Calculate the percentage of used memory
    const float percentage_mem = mem_status.used_mem /
      static_cast<float>( mem_status.total_mem ) * 100.0;

    oss << percentage_mem << '%';
    break;
    }
  default: // Default mode, just show the used/total memory in MB
    if(mem_status.used_mem>10000 && mem_status.total_mem>10000)
      oss<<static_cast<unsigned int>(mem_status.used_mem/1024)<<"/"<<static_cast<unsigned int>(mem_status.total_mem/1024)<<"GB";
    else if(mem_status.used_mem<10000 && mem_status.total_mem>10000)
      oss<<static_cast<unsigned int>(mem_status.used_mem)<<"MB/"<<static_cast<unsigned int>(mem_status.total_mem/1024)<<"GB";
    else
      oss<<static_cast<unsigned int>(mem_status.used_mem)<<"/"<<static_cast<unsigned int>(mem_status.total_mem)<<"MB";
  }

  if( use_colors )
  {
    if( use_powerline_left )
    {
      powerline( oss, mem_lut[color], POWERLINE_LEFT, true );
    }
    else if( !use_powerline_right )
    {
      oss << "#[fg=default,bg=default]";
    }
  }

  return oss.str();
}

<|endoftext|>