<commit_before>//===-- llvm/Target/TargetSchedule.cpp - Sched Machine Model ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a wrapper around MCSchedModel that allows the interface
// to benefit from information currently only available in TargetInstrInfo.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<bool> EnableSchedModel("schedmodel", cl::Hidden, cl::init(true),
  cl::desc("Use TargetSchedModel for latency lookup"));

static cl::opt<bool> EnableSchedItins("scheditins", cl::Hidden, cl::init(true),
  cl::desc("Use InstrItineraryData for latency lookup"));

bool TargetSchedModel::hasInstrSchedModel() const {
  return EnableSchedModel && SchedModel.hasInstrSchedModel();
}

bool TargetSchedModel::hasInstrItineraries() const {
  return EnableSchedItins && !InstrItins.isEmpty();
}

void TargetSchedModel::init(const MCSchedModel &sm,
                            const TargetSubtargetInfo *sti,
                            const TargetInstrInfo *tii) {
  SchedModel = sm;
  STI = sti;
  TII = tii;
  STI->initInstrItins(InstrItins);
}

unsigned TargetSchedModel::getNumMicroOps(MachineInstr *MI) const {
  if (hasInstrItineraries()) {
    int UOps = InstrItins.getNumMicroOps(MI->getDesc().getSchedClass());
    return (UOps >= 0) ? UOps : TII->getNumMicroOps(&InstrItins, MI);
  }
  if (hasInstrSchedModel())
    return resolveSchedClass(MI)->NumMicroOps;

  return 1;
}

/// If we can determine the operand latency from the def only, without machine
/// model or itinerary lookup, do so. Otherwise return -1.
int TargetSchedModel::getDefLatency(const MachineInstr *DefMI,
                                    bool FindMin) const {

  // Return a latency based on the itinerary properties and defining instruction
  // if possible. Some common subtargets don't require per-operand latency,
  // especially for minimum latencies.
  if (FindMin) {
    // If MinLatency is invalid, then use the itinerary for MinLatency. If no
    // itinerary exists either, then use single cycle latency.
    if (SchedModel.MinLatency < 0 && !hasInstrItineraries()) {
      return 1;
    }
    return SchedModel.MinLatency;
  }
  else if (!hasInstrSchedModel() && !hasInstrItineraries()) {
    return TII->defaultDefLatency(&SchedModel, DefMI);
  }
  // ...operand lookup required
  return -1;
}

/// Return the MCSchedClassDesc for this instruction. Some SchedClasses require
/// evaluation of predicates that depend on instruction operands or flags.
const MCSchedClassDesc *TargetSchedModel::
resolveSchedClass(const MachineInstr *MI) const {

  // Get the definition's scheduling class descriptor from this machine model.
  unsigned SchedClass = MI->getDesc().getSchedClass();
  const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SchedClass);

#ifndef NDEBUG
  unsigned NIter = 0;
#endif
  while (SCDesc->isVariant()) {
    assert(++NIter < 6 && "Variants are nested deeper than the magic number");

    SchedClass = STI->resolveSchedClass(SchedClass, MI, this);
    SCDesc = SchedModel.getSchedClassDesc(SchedClass);
  }
  return SCDesc;
}

/// Find the def index of this operand. This index maps to the machine model and
/// is independent of use operands. Def operands may be reordered with uses or
/// merged with uses without affecting the def index (e.g. before/after
/// regalloc). However, an instruction's def operands must never be reordered
/// with respect to each other.
static unsigned findDefIdx(const MachineInstr *MI, unsigned DefOperIdx) {
  unsigned DefIdx = 0;
  for (unsigned i = 0; i != DefOperIdx; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (MO.isReg() && MO.isDef())
      ++DefIdx;
  }
  return DefIdx;
}

/// Find the use index of this operand. This is independent of the instruction's
/// def operands.
///
/// Note that uses are not determined by the operand's isUse property, which
/// is simply the inverse of isDef. Here we consider any readsReg operand to be
/// a "use". The machine model allows an operand to be both a Def and Use.
static unsigned findUseIdx(const MachineInstr *MI, unsigned UseOperIdx) {
  unsigned UseIdx = 0;
  for (unsigned i = 0; i != UseOperIdx; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (MO.isReg() && MO.readsReg())
      ++UseIdx;
  }
  return UseIdx;
}

// Top-level API for clients that know the operand indices.
unsigned TargetSchedModel::computeOperandLatency(
  const MachineInstr *DefMI, unsigned DefOperIdx,
  const MachineInstr *UseMI, unsigned UseOperIdx,
  bool FindMin) const {

  int DefLatency = getDefLatency(DefMI, FindMin);
  if (DefLatency >= 0)
    return DefLatency;

  if (hasInstrItineraries()) {
    int OperLatency = 0;
    if (UseMI) {
      OperLatency =
        TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx, UseMI, UseOperIdx);
    }
    else {
      unsigned DefClass = DefMI->getDesc().getSchedClass();
      OperLatency = InstrItins.getOperandCycle(DefClass, DefOperIdx);
    }
    if (OperLatency >= 0)
      return OperLatency;

    // No operand latency was found.
    unsigned InstrLatency = TII->getInstrLatency(&InstrItins, DefMI);

    // Expected latency is the max of the stage latency and itinerary props.
    // Rather than directly querying InstrItins stage latency, we call a TII
    // hook to allow subtargets to specialize latency. This hook is only
    // applicable to the InstrItins model. InstrSchedModel should model all
    // special cases without TII hooks.
    if (!FindMin)
      InstrLatency = std::max(InstrLatency,
                              TII->defaultDefLatency(&SchedModel, DefMI));
    return InstrLatency;
  }
  assert(!FindMin && hasInstrSchedModel() &&
         "Expected a SchedModel for this cpu");
  const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
  unsigned DefIdx = findDefIdx(DefMI, DefOperIdx);
  if (DefIdx < SCDesc->NumWriteLatencyEntries) {
    // Lookup the definition's write latency in SubtargetInfo.
    const MCWriteLatencyEntry *WLEntry =
      STI->getWriteLatencyEntry(SCDesc, DefIdx);
    unsigned WriteID = WLEntry->WriteResourceID;
    unsigned Latency = WLEntry->Cycles;
    if (!UseMI)
      return Latency;

    // Lookup the use's latency adjustment in SubtargetInfo.
    const MCSchedClassDesc *UseDesc = resolveSchedClass(UseMI);
    if (UseDesc->NumReadAdvanceEntries == 0)
      return Latency;
    unsigned UseIdx = findUseIdx(UseMI, UseOperIdx);
    return Latency - STI->getReadAdvanceCycles(UseDesc, UseIdx, WriteID);
  }
  // If DefIdx does not exist in the model (e.g. implicit defs), then return
  // unit latency (defaultDefLatency may be too conservative).
#ifndef NDEBUG
  if (SCDesc->isValid() && !DefMI->getOperand(DefOperIdx).isImplicit()
      && !DefMI->getDesc().OpInfo[DefOperIdx].isOptionalDef()) {
    std::string Err;
    raw_string_ostream ss(Err);
    ss << "DefIdx " << DefIdx << " exceeds machine model writes for "
       << *DefMI;
    report_fatal_error(ss.str());
  }
#endif
  return 1;
}

unsigned TargetSchedModel::computeInstrLatency(const MachineInstr *MI) const {
  if (hasInstrItineraries()) {
    // For the itinerary model, fall back to the old subtarget hook.
    return TII->getInstrLatency(&InstrItins, MI);
  }
  if (hasInstrSchedModel()) {
    unsigned Latency = 0;
    const MCSchedClassDesc *SCDesc = resolveSchedClass(MI);
    for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
         DefIdx != DefEnd; ++DefIdx) {
      // Lookup the definition's write latency in SubtargetInfo.
      const MCWriteLatencyEntry *WLEntry =
        STI->getWriteLatencyEntry(SCDesc, DefIdx);
      Latency = std::max(Latency, WLEntry->Cycles);
    }
    return Latency;
  }
  return TII->defaultDefLatency(&SchedModel, MI);
}

unsigned TargetSchedModel::
computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
                     const MachineInstr *DepMI) const {
  // MinLatency == -1 is for in-order processors that always have unit
  // MinLatency. MinLatency > 0 is for in-order processors with varying min
  // latencies, but since this is not a RAW dep, we always use unit latency.
  if (SchedModel.MinLatency != 0)
    return 1;

  // MinLatency == 0 indicates an out-of-order processor that can dispatch
  // WAW dependencies in the same cycle.

  // Treat predication as a data dependency for out-of-order cpus. In-order
  // cpus do not need to treat predicated writes specially.
  //
  // TODO: The following hack exists because predication passes do not
  // correctly append imp-use operands, and readsReg() strangely returns false
  // for predicated defs.
  unsigned Reg = DefMI->getOperand(DefOperIdx).getReg();
  const MachineFunction &MF = *DefMI->getParent()->getParent();
  const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
  if (!DepMI->readsRegister(Reg, TRI) && TII->isPredicated(DepMI))
    return computeInstrLatency(DefMI);

  // If we have a per operand scheduling model, check if this def is writing
  // an unbuffered resource. If so, it treated like an in-order cpu.
  if (hasInstrSchedModel()) {
    const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
    for (const MCWriteProcResEntry *PRI = STI->getWriteProcResBegin(SCDesc),
           *PRE = STI->getWriteProcResEnd(SCDesc); PRI != PRE; ++PRI) {
      if (!SchedModel.getProcResource(PRI->ProcResourceIdx)->IsBuffered)
        return 1;
    }
  }
  return 0;
}
<commit_msg>misched: fall-back to a target hook for instr bundles.<commit_after>//===-- llvm/Target/TargetSchedule.cpp - Sched Machine Model ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a wrapper around MCSchedModel that allows the interface
// to benefit from information currently only available in TargetInstrInfo.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

static cl::opt<bool> EnableSchedModel("schedmodel", cl::Hidden, cl::init(true),
  cl::desc("Use TargetSchedModel for latency lookup"));

static cl::opt<bool> EnableSchedItins("scheditins", cl::Hidden, cl::init(true),
  cl::desc("Use InstrItineraryData for latency lookup"));

bool TargetSchedModel::hasInstrSchedModel() const {
  return EnableSchedModel && SchedModel.hasInstrSchedModel();
}

bool TargetSchedModel::hasInstrItineraries() const {
  return EnableSchedItins && !InstrItins.isEmpty();
}

void TargetSchedModel::init(const MCSchedModel &sm,
                            const TargetSubtargetInfo *sti,
                            const TargetInstrInfo *tii) {
  SchedModel = sm;
  STI = sti;
  TII = tii;
  STI->initInstrItins(InstrItins);
}

unsigned TargetSchedModel::getNumMicroOps(MachineInstr *MI) const {
  if (hasInstrItineraries()) {
    int UOps = InstrItins.getNumMicroOps(MI->getDesc().getSchedClass());
    return (UOps >= 0) ? UOps : TII->getNumMicroOps(&InstrItins, MI);
  }
  if (hasInstrSchedModel())
    return resolveSchedClass(MI)->NumMicroOps;

  return 1;
}

/// If we can determine the operand latency from the def only, without machine
/// model or itinerary lookup, do so. Otherwise return -1.
int TargetSchedModel::getDefLatency(const MachineInstr *DefMI,
                                    bool FindMin) const {

  // Return a latency based on the itinerary properties and defining instruction
  // if possible. Some common subtargets don't require per-operand latency,
  // especially for minimum latencies.
  if (FindMin) {
    // If MinLatency is invalid, then use the itinerary for MinLatency. If no
    // itinerary exists either, then use single cycle latency.
    if (SchedModel.MinLatency < 0 && !hasInstrItineraries()) {
      return 1;
    }
    return SchedModel.MinLatency;
  }
  else if (!hasInstrSchedModel() && !hasInstrItineraries()) {
    return TII->defaultDefLatency(&SchedModel, DefMI);
  }
  // ...operand lookup required
  return -1;
}

/// Return the MCSchedClassDesc for this instruction. Some SchedClasses require
/// evaluation of predicates that depend on instruction operands or flags.
const MCSchedClassDesc *TargetSchedModel::
resolveSchedClass(const MachineInstr *MI) const {

  // Get the definition's scheduling class descriptor from this machine model.
  unsigned SchedClass = MI->getDesc().getSchedClass();
  const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SchedClass);

#ifndef NDEBUG
  unsigned NIter = 0;
#endif
  while (SCDesc->isVariant()) {
    assert(++NIter < 6 && "Variants are nested deeper than the magic number");

    SchedClass = STI->resolveSchedClass(SchedClass, MI, this);
    SCDesc = SchedModel.getSchedClassDesc(SchedClass);
  }
  return SCDesc;
}

/// Find the def index of this operand. This index maps to the machine model and
/// is independent of use operands. Def operands may be reordered with uses or
/// merged with uses without affecting the def index (e.g. before/after
/// regalloc). However, an instruction's def operands must never be reordered
/// with respect to each other.
static unsigned findDefIdx(const MachineInstr *MI, unsigned DefOperIdx) {
  unsigned DefIdx = 0;
  for (unsigned i = 0; i != DefOperIdx; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (MO.isReg() && MO.isDef())
      ++DefIdx;
  }
  return DefIdx;
}

/// Find the use index of this operand. This is independent of the instruction's
/// def operands.
///
/// Note that uses are not determined by the operand's isUse property, which
/// is simply the inverse of isDef. Here we consider any readsReg operand to be
/// a "use". The machine model allows an operand to be both a Def and Use.
static unsigned findUseIdx(const MachineInstr *MI, unsigned UseOperIdx) {
  unsigned UseIdx = 0;
  for (unsigned i = 0; i != UseOperIdx; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (MO.isReg() && MO.readsReg())
      ++UseIdx;
  }
  return UseIdx;
}

// Top-level API for clients that know the operand indices.
unsigned TargetSchedModel::computeOperandLatency(
  const MachineInstr *DefMI, unsigned DefOperIdx,
  const MachineInstr *UseMI, unsigned UseOperIdx,
  bool FindMin) const {

  int DefLatency = getDefLatency(DefMI, FindMin);
  if (DefLatency >= 0)
    return DefLatency;

  if (hasInstrItineraries()) {
    int OperLatency = 0;
    if (UseMI) {
      OperLatency =
        TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx, UseMI, UseOperIdx);
    }
    else {
      unsigned DefClass = DefMI->getDesc().getSchedClass();
      OperLatency = InstrItins.getOperandCycle(DefClass, DefOperIdx);
    }
    if (OperLatency >= 0)
      return OperLatency;

    // No operand latency was found.
    unsigned InstrLatency = TII->getInstrLatency(&InstrItins, DefMI);

    // Expected latency is the max of the stage latency and itinerary props.
    // Rather than directly querying InstrItins stage latency, we call a TII
    // hook to allow subtargets to specialize latency. This hook is only
    // applicable to the InstrItins model. InstrSchedModel should model all
    // special cases without TII hooks.
    if (!FindMin)
      InstrLatency = std::max(InstrLatency,
                              TII->defaultDefLatency(&SchedModel, DefMI));
    return InstrLatency;
  }
  assert(!FindMin && hasInstrSchedModel() &&
         "Expected a SchedModel for this cpu");
  const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
  unsigned DefIdx = findDefIdx(DefMI, DefOperIdx);
  if (DefIdx < SCDesc->NumWriteLatencyEntries) {
    // Lookup the definition's write latency in SubtargetInfo.
    const MCWriteLatencyEntry *WLEntry =
      STI->getWriteLatencyEntry(SCDesc, DefIdx);
    unsigned WriteID = WLEntry->WriteResourceID;
    unsigned Latency = WLEntry->Cycles;
    if (!UseMI)
      return Latency;

    // Lookup the use's latency adjustment in SubtargetInfo.
    const MCSchedClassDesc *UseDesc = resolveSchedClass(UseMI);
    if (UseDesc->NumReadAdvanceEntries == 0)
      return Latency;
    unsigned UseIdx = findUseIdx(UseMI, UseOperIdx);
    return Latency - STI->getReadAdvanceCycles(UseDesc, UseIdx, WriteID);
  }
  // If DefIdx does not exist in the model (e.g. implicit defs), then return
  // unit latency (defaultDefLatency may be too conservative).
#ifndef NDEBUG
  if (SCDesc->isValid() && !DefMI->getOperand(DefOperIdx).isImplicit()
      && !DefMI->getDesc().OpInfo[DefOperIdx].isOptionalDef()) {
    std::string Err;
    raw_string_ostream ss(Err);
    ss << "DefIdx " << DefIdx << " exceeds machine model writes for "
       << *DefMI;
    report_fatal_error(ss.str());
  }
#endif
  return 1;
}

unsigned TargetSchedModel::computeInstrLatency(const MachineInstr *MI) const {
  // For the itinerary model, fall back to the old subtarget hook.
  // Allow subtargets to compute Bundle latencies outside the machine model.
  if (hasInstrItineraries() || MI->isBundle())
    return TII->getInstrLatency(&InstrItins, MI);

  if (hasInstrSchedModel()) {
    unsigned Latency = 0;
    const MCSchedClassDesc *SCDesc = resolveSchedClass(MI);
    for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
         DefIdx != DefEnd; ++DefIdx) {
      // Lookup the definition's write latency in SubtargetInfo.
      const MCWriteLatencyEntry *WLEntry =
        STI->getWriteLatencyEntry(SCDesc, DefIdx);
      Latency = std::max(Latency, WLEntry->Cycles);
    }
    return Latency;
  }
  return TII->defaultDefLatency(&SchedModel, MI);
}

unsigned TargetSchedModel::
computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
                     const MachineInstr *DepMI) const {
  // MinLatency == -1 is for in-order processors that always have unit
  // MinLatency. MinLatency > 0 is for in-order processors with varying min
  // latencies, but since this is not a RAW dep, we always use unit latency.
  if (SchedModel.MinLatency != 0)
    return 1;

  // MinLatency == 0 indicates an out-of-order processor that can dispatch
  // WAW dependencies in the same cycle.

  // Treat predication as a data dependency for out-of-order cpus. In-order
  // cpus do not need to treat predicated writes specially.
  //
  // TODO: The following hack exists because predication passes do not
  // correctly append imp-use operands, and readsReg() strangely returns false
  // for predicated defs.
  unsigned Reg = DefMI->getOperand(DefOperIdx).getReg();
  const MachineFunction &MF = *DefMI->getParent()->getParent();
  const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
  if (!DepMI->readsRegister(Reg, TRI) && TII->isPredicated(DepMI))
    return computeInstrLatency(DefMI);

  // If we have a per operand scheduling model, check if this def is writing
  // an unbuffered resource. If so, it treated like an in-order cpu.
  if (hasInstrSchedModel()) {
    const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
    for (const MCWriteProcResEntry *PRI = STI->getWriteProcResBegin(SCDesc),
           *PRE = STI->getWriteProcResEnd(SCDesc); PRI != PRE; ++PRI) {
      if (!SchedModel.getProcResource(PRI->ProcResourceIdx)->IsBuffered)
        return 1;
    }
  }
  return 0;
}
<|endoftext|>


<commit_before>#include "cameramanager.h"

CameraManager::CameraManager( Ogre::Camera* cam )
{
    setCamera( cam );
    setMode( CM_BLENDER );
}

CameraManager::~CameraManager()
{}

void CameraManager::setCamera(Ogre::Camera* cam)
{
    mCamera = cam;
    mCameraNode = mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode();
    mCamera->detachFromParent();
    mCameraNode->attachObject(mCamera);
    mCamera->setPosition(Ogre::Vector3(0, 5, 15));
    mCamera->lookAt(Ogre::Vector3(0, 0, 0));
    mCamera->setNearClipDistance(1.f);
    mCamera->setFarClipDistance(10000.0f);
    mCamera->setAutoAspectRatio(true);
}

void CameraManager::setTarget(Ogre::SceneNode* target)
{
    if (target != mTarget)
    {
        mTarget = target;
        if (target)
        {
            setYawPitchDist(Ogre::Degree(0), Ogre::Degree(15), 150);
        }
        else
        {
            mCamera->setAutoTracking(false);
        }
    }
}

void CameraManager::manualStop()
{
    if (mMode == CM_FLY)
    {
        mGoingForward = false;
        mGoingBack = false;
        mGoingLeft = false;
        mGoingRight = false;
        mGoingUp = false;
        mGoingDown = false;
        mVelocity = Ogre::Vector3::ZERO;
    }
}

void CameraManager::setYawPitchDist(Ogre::Radian yaw, Ogre::Radian pitch, Ogre::Real dist)
{
    mCamera->setPosition(mTarget->_getDerivedPositionUpdated());
    mCamera->setOrientation(mTarget->_getDerivedOrientationUpdated());
    mCamera->yaw(yaw);
    mCamera->pitch(-pitch);
    mCamera->moveRelative(Ogre::Vector3(0, 0, dist));
}

void CameraManager::setMode(CameraMode mode)
{
    if (mMode != CM_BLENDER && mode == CM_BLENDER)
    {
        //qDebug() << "Target=" << (void*)mTarget;
        setTarget(mTarget ? mTarget : mCamera->getSceneManager()->getRootSceneNode());
        setYawPitchDist(Ogre::Degree(0), Ogre::Degree(15), 150);
    }
    else if (mMode != CM_FLY && mode == CM_FLY)
    {
        mCamera->setAutoTracking(false);
        mCamera->setFixedYawAxis(true);
    }

    if (mTarget == nullptr)
    {
        setTarget(mTarget ? mTarget : mCamera->getSceneManager()->getRootSceneNode());
    }
    mMode = mode;
}

void CameraManager::setProjectionType(Ogre::ProjectionType pt)
{
    if (pt == Ogre::PT_ORTHOGRAPHIC)
    {
        /// @todo: Make orthographic projection work properly.
    }
    else if (pt == Ogre::PT_PERSPECTIVE)
    {
        mCamera->setCustomProjectionMatrix(false);
    }
    mCamera->setProjectionType(pt);
}

void CameraManager::setView(View newView)
{
    switch (newView)
    {
    case VI_TOP:
        mCameraNode->setOrientation(sqrt(0.5), -sqrt(0.5), 0, 0);
        break;
    case VI_BOTTOM:
        mCameraNode->setOrientation(sqrt(0.5), sqrt(0.5), 0, 0);
        break;
    case VI_LEFT:
        mCameraNode->setOrientation(sqrt(0.5), 0, -sqrt(0.5), 0);
        break;
    case VI_RIGHT:
        mCameraNode->setOrientation(sqrt(0.5), 0, sqrt(0.5), 0);
        break;
    case VI_FRONT:
        mCameraNode->setOrientation(1, 0, 0, 0);
        break;
    case VI_BACK:
        setView(VI_FRONT); // Recursion
        mCameraNode->setOrientation(0, 0, 1, 0);
    }
    mCurrentView = newView;
}

void CameraManager::rotatePerspective(Direction dir)
{
    Ogre::Radian amount = Ogre::Radian(Ogre::Degree(15));
    switch (dir)
    {
    case DR_FORWARD:
        mCameraNode->rotate(Ogre::Vector3(1, 0, 0), -amount);
        break;
    case DR_BACKWARD:
        mCameraNode->rotate(Ogre::Vector3(1, 0, 0), amount);
        break;
    case DR_LEFT:
        mCameraNode->rotate(Ogre::Vector3(0, 1, 0), -amount, Ogre::Node::TS_WORLD);
        break;
    case DR_RIGHT:
        mCameraNode->rotate(Ogre::Vector3(0, 1, 0), amount, Ogre::Node::TS_WORLD);
        break;
    }
}

void CameraManager::numpadViewSwitch(const QKeyEvent* evt)
{
    bool ctrl = evt->modifiers().testFlag(Qt::ControlModifier);
    bool numpad = evt->modifiers().testFlag(Qt::KeypadModifier);
    if (numpad)
    {
        switch (evt->key())
        {
        case Qt::Key_1:
            setView(ctrl ? VI_BACK : VI_FRONT);
            break;
        case Qt::Key_2:
            rotatePerspective(DR_BACKWARD);
            break;
        case Qt::Key_3:
            setView(ctrl ? VI_LEFT : VI_RIGHT);
            break;
        case Qt::Key_4:
            rotatePerspective(DR_LEFT);
            break;
        case Qt::Key_5:
            setProjectionType((mCamera->getProjectionType() == Ogre::PT_PERSPECTIVE) ? Ogre::PT_ORTHOGRAPHIC : Ogre::PT_PERSPECTIVE);
            break;
        case Qt::Key_6:
            rotatePerspective(DR_RIGHT);
            break;
        case Qt::Key_7:
            setView(ctrl ? VI_BOTTOM : VI_TOP);
            break;
        case Qt::Key_8:
            rotatePerspective(DR_FORWARD);
            break;
        }
    }
}
<commit_msg>extend far plane again<commit_after>#include "cameramanager.h"

CameraManager::CameraManager( Ogre::Camera* cam )
{
    setCamera( cam );
    setMode( CM_BLENDER );
}

CameraManager::~CameraManager()
{}

void CameraManager::setCamera(Ogre::Camera* cam)
{
    mCamera = cam;
    mCameraNode = mCamera->getSceneManager()->getRootSceneNode()->createChildSceneNode();
    mCamera->detachFromParent();
    mCameraNode->attachObject(mCamera);
    mCamera->setPosition(Ogre::Vector3(0, 5, 15));
    mCamera->lookAt(Ogre::Vector3(0, 0, 0));
    mCamera->setNearClipDistance(2.f);
    mCamera->setFarClipDistance(15000.0f);
    mCamera->setAutoAspectRatio(true);
}

void CameraManager::setTarget(Ogre::SceneNode* target)
{
    if (target != mTarget)
    {
        mTarget = target;
        if (target)
        {
            setYawPitchDist(Ogre::Degree(0), Ogre::Degree(15), 150);
        }
        else
        {
            mCamera->setAutoTracking(false);
        }
    }
}

void CameraManager::manualStop()
{
    if (mMode == CM_FLY)
    {
        mGoingForward = false;
        mGoingBack = false;
        mGoingLeft = false;
        mGoingRight = false;
        mGoingUp = false;
        mGoingDown = false;
        mVelocity = Ogre::Vector3::ZERO;
    }
}

void CameraManager::setYawPitchDist(Ogre::Radian yaw, Ogre::Radian pitch, Ogre::Real dist)
{
    mCamera->setPosition(mTarget->_getDerivedPositionUpdated());
    mCamera->setOrientation(mTarget->_getDerivedOrientationUpdated());
    mCamera->yaw(yaw);
    mCamera->pitch(-pitch);
    mCamera->moveRelative(Ogre::Vector3(0, 0, dist));
}

void CameraManager::setMode(CameraMode mode)
{
    if (mMode != CM_BLENDER && mode == CM_BLENDER)
    {
        //qDebug() << "Target=" << (void*)mTarget;
        setTarget(mTarget ? mTarget : mCamera->getSceneManager()->getRootSceneNode());
        setYawPitchDist(Ogre::Degree(0), Ogre::Degree(15), 150);
    }
    else if (mMode != CM_FLY && mode == CM_FLY)
    {
        mCamera->setAutoTracking(false);
        mCamera->setFixedYawAxis(true);
    }

    if (mTarget == nullptr)
    {
        setTarget(mTarget ? mTarget : mCamera->getSceneManager()->getRootSceneNode());
    }
    mMode = mode;
}

void CameraManager::setProjectionType(Ogre::ProjectionType pt)
{
    if (pt == Ogre::PT_ORTHOGRAPHIC)
    {
        /// @todo: Make orthographic projection work properly.
    }
    else if (pt == Ogre::PT_PERSPECTIVE)
    {
        mCamera->setCustomProjectionMatrix(false);
    }
    mCamera->setProjectionType(pt);
}

void CameraManager::setView(View newView)
{
    switch (newView)
    {
    case VI_TOP:
        mCameraNode->setOrientation(sqrt(0.5), -sqrt(0.5), 0, 0);
        break;
    case VI_BOTTOM:
        mCameraNode->setOrientation(sqrt(0.5), sqrt(0.5), 0, 0);
        break;
    case VI_LEFT:
        mCameraNode->setOrientation(sqrt(0.5), 0, -sqrt(0.5), 0);
        break;
    case VI_RIGHT:
        mCameraNode->setOrientation(sqrt(0.5), 0, sqrt(0.5), 0);
        break;
    case VI_FRONT:
        mCameraNode->setOrientation(1, 0, 0, 0);
        break;
    case VI_BACK:
        setView(VI_FRONT); // Recursion
        mCameraNode->setOrientation(0, 0, 1, 0);
    }
    mCurrentView = newView;
}

void CameraManager::rotatePerspective(Direction dir)
{
    Ogre::Radian amount = Ogre::Radian(Ogre::Degree(15));
    switch (dir)
    {
    case DR_FORWARD:
        mCameraNode->rotate(Ogre::Vector3(1, 0, 0), -amount);
        break;
    case DR_BACKWARD:
        mCameraNode->rotate(Ogre::Vector3(1, 0, 0), amount);
        break;
    case DR_LEFT:
        mCameraNode->rotate(Ogre::Vector3(0, 1, 0), -amount, Ogre::Node::TS_WORLD);
        break;
    case DR_RIGHT:
        mCameraNode->rotate(Ogre::Vector3(0, 1, 0), amount, Ogre::Node::TS_WORLD);
        break;
    }
}

void CameraManager::numpadViewSwitch(const QKeyEvent* evt)
{
    bool ctrl = evt->modifiers().testFlag(Qt::ControlModifier);
    bool numpad = evt->modifiers().testFlag(Qt::KeypadModifier);
    if (numpad)
    {
        switch (evt->key())
        {
        case Qt::Key_1:
            setView(ctrl ? VI_BACK : VI_FRONT);
            break;
        case Qt::Key_2:
            rotatePerspective(DR_BACKWARD);
            break;
        case Qt::Key_3:
            setView(ctrl ? VI_LEFT : VI_RIGHT);
            break;
        case Qt::Key_4:
            rotatePerspective(DR_LEFT);
            break;
        case Qt::Key_5:
            setProjectionType((mCamera->getProjectionType() == Ogre::PT_PERSPECTIVE) ? Ogre::PT_ORTHOGRAPHIC : Ogre::PT_PERSPECTIVE);
            break;
        case Qt::Key_6:
            rotatePerspective(DR_RIGHT);
            break;
        case Qt::Key_7:
            setView(ctrl ? VI_BOTTOM : VI_TOP);
            break;
        case Qt::Key_8:
            rotatePerspective(DR_FORWARD);
            break;
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Fixed: Memory corruption on SAP Space radix sort context deallocation fixed (thanks to Michiel Roza)<commit_after><|endoftext|>


<commit_before>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

                Copyright (c) 2003-2019, Cauldron Development LLC
                   Copyright (c) 2003-2017, Stanford University
                               All rights reserved.

         The C! library is free software: you can redistribute it and/or
        modify it under the terms of the GNU Lesser General Public License
       as published by the Free Software Foundation, either version 2.1 of
               the License, or (at your option) any later version.

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

         You should have received a copy of the GNU Lesser General Public
                 License along with the C! library.  If not, see
                         <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
           You may request written permission by emailing the authors.

                  For information regarding this software email:
                                 Joseph Coffland
                          joseph@cauldrondevelopment.com

\******************************************************************************/

#include "Tar.h"

#include <cbang/Exception.h>

#include <algorithm>

using namespace std;
using namespace cb;

const char Tar::zero_block[512] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

namespace {
  streamsize compute_padding(streamsize size) {
    return (size & 511) ? 512 - (size & 511) : 0;
  }
}

unsigned Tar::writeFile(const string &filename, ostream &dst, istream &src,
                        uint32_t mode) {
  // Get stream size
  src.seekg(0, ios::end);
  streampos size = src.tellg();
  src.seekg(0, ios::beg);

  // Write header
  setFilename(filename);
  setSize(size);
  setType(TarHeader::NORMAL_FILE);
  setMode(mode);
  writeHeader(dst);

  // Write data
  return writeFileData(dst, src, (streamsize)size);
}

unsigned Tar::writeFile(const string &filename, ostream &dst, const char *data,
                        streamsize size, uint32_t mode) {
  // Write header
  setFilename(filename);
  setSize(size);
  setType(TarHeader::NORMAL_FILE);
  setMode(mode);
  writeHeader(dst);

  // Write data
  return writeFileData(dst, data, size);
}

unsigned Tar::writeFileData(std::ostream &dst, std::istream &src,
                            streamsize size) {
  char buf[4096];
  streamsize n;

  while (true) {
    src.read(buf, 4096);
    n = src.gcount();
    if (n) dst.write(buf, n);
    else break;
  }

  // Pad with zeros
  streamsize padding = compute_padding(size);
  if (padding) dst.write(zero_block, padding);

  return size + padding;
}

unsigned Tar::writeFileData(std::ostream &dst, const char *data,
                            streamsize size) {
  dst.write(data, size);

  // Pad with zeros
  streamsize padding = compute_padding(size);
  if (padding) dst.write(zero_block, padding);

  return size + padding;
}

unsigned Tar::writeDir(const string &name, ostream &dst, uint32_t mode) {
  if (!name.length() || name[name.length() - 1] != '/')
    setFilename(name + '/');
  else setFilename(name);

  setSize(0);
  setType(TarHeader::DIRECTORY);
  setMode(mode);
  writeHeader(dst);

  return 512;
}

unsigned Tar::writeFooter(ostream &dst) {
  dst.write(zero_block, 512);
  dst.write(zero_block, 512);

  return 1024;
}

void Tar::readFile(ostream &dst, istream &src) {
  char buf[4096];
  streamsize size = getSize();
  streamsize padding = compute_padding(size);
  streamsize n;

  while (size) {
    src.read(buf, min((int)size, 4096));
    if (!(n = src.gcount())) THROW("Error reading tar file");

    size -= n;

    dst.write(buf, n);
    if (dst.fail()) THROW(string("Failed to write '") + getFilename() + "'");
  }

  src.ignore(padding);
}

void Tar::skipFile(istream &src) {
  src.ignore(getSize() + compute_padding(getSize()));
}
<commit_msg>Increase tar buffer size<commit_after>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

                Copyright (c) 2003-2019, Cauldron Development LLC
                   Copyright (c) 2003-2017, Stanford University
                               All rights reserved.

         The C! library is free software: you can redistribute it and/or
        modify it under the terms of the GNU Lesser General Public License
       as published by the Free Software Foundation, either version 2.1 of
               the License, or (at your option) any later version.

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

         You should have received a copy of the GNU Lesser General Public
                 License along with the C! library.  If not, see
                         <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
           You may request written permission by emailing the authors.

                  For information regarding this software email:
                                 Joseph Coffland
                          joseph@cauldrondevelopment.com

\******************************************************************************/

#include "Tar.h"

#include <cbang/Exception.h>

#include <algorithm>

using namespace std;
using namespace cb;

#define TAR_BUFFER_SIZE (4096 * 1024)

const char Tar::zero_block[512] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

namespace {
  streamsize compute_padding(streamsize size) {
    return (size & 511) ? 512 - (size & 511) : 0;
  }
}

unsigned Tar::writeFile(const string &filename, ostream &dst, istream &src,
                        uint32_t mode) {
  // Get stream size
  src.seekg(0, ios::end);
  streampos size = src.tellg();
  src.seekg(0, ios::beg);

  // Write header
  setFilename(filename);
  setSize(size);
  setType(TarHeader::NORMAL_FILE);
  setMode(mode);
  writeHeader(dst);

  // Write data
  return writeFileData(dst, src, (streamsize)size);
}

unsigned Tar::writeFile(const string &filename, ostream &dst, const char *data,
                        streamsize size, uint32_t mode) {
  // Write header
  setFilename(filename);
  setSize(size);
  setType(TarHeader::NORMAL_FILE);
  setMode(mode);
  writeHeader(dst);

  // Write data
  return writeFileData(dst, data, size);
}

unsigned Tar::writeFileData(std::ostream &dst, std::istream &src,
                            streamsize size) {
  char buf[TAR_BUFFER_SIZE];
  streamsize n;

  while (true) {
    src.read(buf, TAR_BUFFER_SIZE);
    n = src.gcount();
    if (n) dst.write(buf, n);
    else break;
  }

  // Pad with zeros
  streamsize padding = compute_padding(size);
  if (padding) dst.write(zero_block, padding);

  return size + padding;
}

unsigned Tar::writeFileData(std::ostream &dst, const char *data,
                            streamsize size) {
  dst.write(data, size);

  // Pad with zeros
  streamsize padding = compute_padding(size);
  if (padding) dst.write(zero_block, padding);

  return size + padding;
}

unsigned Tar::writeDir(const string &name, ostream &dst, uint32_t mode) {
  if (!name.length() || name[name.length() - 1] != '/')
    setFilename(name + '/');
  else setFilename(name);

  setSize(0);
  setType(TarHeader::DIRECTORY);
  setMode(mode);
  writeHeader(dst);

  return 512;
}

unsigned Tar::writeFooter(ostream &dst) {
  dst.write(zero_block, 512);
  dst.write(zero_block, 512);

  return 1024;
}

void Tar::readFile(ostream &dst, istream &src) {
  char buf[TAR_BUFFER_SIZE];
  streamsize size = getSize();
  streamsize padding = compute_padding(size);
  streamsize n;

  while (size) {
    src.read(buf, min((int)size, TAR_BUFFER_SIZE));
    if (!(n = src.gcount())) THROW("Error reading tar file");

    size -= n;

    dst.write(buf, n);
    if (dst.fail()) THROW(string("Failed to write '") + getFilename() + "'");
  }

  src.ignore(padding);
}

void Tar::skipFile(istream &src) {
  src.ignore(getSize() + compute_padding(getSize()));
}
<|endoftext|>


<commit_before><commit_msg>CWS-TOOLING: integrate CWS vcl113<commit_after><|endoftext|>


<commit_before>#include "base_container.h"

namespace kagami {
  Message IteratorStepForward(ObjectMap &p) {
    auto &it = p[kStrObject].Cast<IteratorPackage>();
    it.StepForward();
    return Message();
  }

  Message IteratorStepBack(ObjectMap &p) {
    auto &it = p[kStrObject].Cast<IteratorPackage>();
    it.StepBack();
    return Message();
  }

  Message IteratorOperatorCompare(ObjectMap &p) {
    EXPECT_TYPE(p, kStrRightHandSide, kTypeIdIterator);
    auto &rhs = p[kStrRightHandSide].Cast<IteratorPackage>();
    auto &lhs = p[kStrObject].Cast<IteratorPackage>();
    return Message(util::MakeBoolean(lhs.Compare(rhs)));
  }

  Message IteratorGet(ObjectMap &p) {
    auto &it = p[kStrObject].Cast<IteratorPackage>();
    return Message().SetObject(Object().CreateRef(it.Deref()));
  }

  Message ArrayConstructor(ObjectMap &p) {
    shared_ptr<ObjectArray> base(make_shared<ObjectArray>());

    if (!p["size"].Null()) {
      size_t size = stol(p.Cast<string>("size"));
      EXPECT(size > 0, "Illegal array size.");

      Object obj;
      obj.CloneFrom(p["init_value"]);

      base->reserve(size);
      auto type_id = obj.GetTypeId();

      for (auto count = 0; count < size; count++) {
        base->emplace_back(Object(management::type::GetObjectCopy(obj), type_id));
      }
    }

    return Message().SetObject(Object(base, kTypeIdArray).SetConstructorFlag());
  }

  Message ArrayGetElement(ObjectMap &p) {
    EXPECT_TYPE(p, "index", kTypeIdRawString);

    ObjectArray &base = p.Cast<ObjectArray>(kStrObject);
    //DEBUG_EVENT("(ArrayGetElement Interface)Index:" + p.Cast<string>("index"));
    size_t idx = stol(p.Cast<string>("index"));
    size_t size = base.size();

    EXPECT(idx < size, "Subscript is out of range. - " + to_string(idx));

    return Message().SetObject(Object().CreateRef(base[idx]));
  }

  Message ArrayGetSize(ObjectMap &p) {
    auto &obj = p[kStrObject];
    return Message(to_string(obj.Cast<ObjectArray>().size()));
  }

  Message ArrayEmpty(ObjectMap &p) {
    return Message(
      util::MakeBoolean(p[kStrObject].Cast<ObjectArray>().empty())
    );
  }

  Message ArrayPush(ObjectMap &p) {
    ObjectArray &base = p.Cast<ObjectArray>(kStrObject);

    base.emplace_back(p["object"]);

    return Message();
  }

  Message ArrayPop(ObjectMap &p) {
    ObjectArray &base = p.Cast<ObjectArray>(kStrObject);

    if (!base.empty()) base.pop_back();

    return Message().SetObject(util::MakeBoolean(base.empty()));
  }

  Message ArrayPrint(ObjectMap &p) {
    Message result;
    ObjectMap obj_map;

    auto &base = p.Cast<ObjectArray>(kStrObject);
    auto interface = management::Order("print", kTypeIdNull, -1);

    for (auto &unit : base) {
      obj_map.insert(NamedObject(kStrObject, unit));
      result = interface.Start(obj_map);
      obj_map.clear();
    }

    return result;
  }

  Message ArrayBegin(ObjectMap &p) {
    auto &base = p[kStrObject].Cast<ObjectArray>();
    shared_ptr<IteratorPackage> pkg(
      new IteratorPackage(base.begin(), kContainerObjectArray)
    );
    return Message().SetObject(
      Object(pkg, kTypeIdIterator)
    );
  }

  Message ArrayEnd(ObjectMap &p) {
    auto &base = p[kStrObject].Cast<ObjectArray>();
    shared_ptr<IteratorPackage> pkg(
      new IteratorPackage(base.end(), kContainerObjectArray)
    );
    return Message().SetObject(
      Object(pkg, kTypeIdIterator)
    );
  }

  void InitContainerComponents() {
    using management::type::NewTypeSetup;

    NewTypeSetup(kTypeIdArray, [](shared_ptr<void> source) -> shared_ptr<void> {
      auto &src_base = *static_pointer_cast<ObjectArray>(source);
      shared_ptr<ObjectArray> dest_base = make_shared<ObjectArray>();

      dest_base->reserve(src_base.size());

      for (auto &unit : src_base) {
        dest_base->emplace_back(Object(management::type::GetObjectCopy(unit), unit.GetTypeId()));
      }

      return dest_base;
    })
      .InitConstructor(
        Interface(ArrayConstructor, "size|init_value", "array", kCodeAutoFill)
      )
      .InitMethods(
        {
          Interface(ArrayGetElement, "index", "__at"),
          Interface(ArrayPrint, "", "__print"),
          Interface(ArrayGetSize, "", "size"),
          Interface(ArrayPush, "object", "push"),
          Interface(ArrayPop, "object", "pop"),
          Interface(ArrayEmpty, "", "empty"),
          Interface(ArrayBegin, "", "head"),
          Interface(ArrayEnd, "", "tail")
        }
    );

    NewTypeSetup(kTypeIdIterator, SimpleSharedPtrCopy<IteratorPackage>)
      .InitMethods(
        {
          Interface(IteratorGet, "", "get"),
          Interface(IteratorStepForward, "", "step_forward"),
          Interface(IteratorStepBack, "", "step_back"),
          Interface(IteratorOperatorCompare, kStrRightHandSide, kStrCompare)
        }
    );
  }
}<commit_msg>Add compare function<commit_after>#include "base_container.h"

namespace kagami {
  Message IteratorStepForward(ObjectMap &p) {
    auto &it = p[kStrObject].Cast<IteratorPackage>();
    it.StepForward();
    return Message();
  }

  Message IteratorStepBack(ObjectMap &p) {
    auto &it = p[kStrObject].Cast<IteratorPackage>();
    it.StepBack();
    return Message();
  }

  Message IteratorOperatorCompare(ObjectMap &p) {
    EXPECT_TYPE(p, kStrRightHandSide, kTypeIdIterator);
    auto &rhs = p[kStrRightHandSide].Cast<IteratorPackage>();
    auto &lhs = p[kStrObject].Cast<IteratorPackage>();
    return Message(util::MakeBoolean(lhs.Compare(rhs)));
  }

  Message IteratorGet(ObjectMap &p) {
    auto &it = p[kStrObject].Cast<IteratorPackage>();
    return Message().SetObject(Object().CreateRef(it.Deref()));
  }

  Message ArrayConstructor(ObjectMap &p) {
    shared_ptr<ObjectArray> base(make_shared<ObjectArray>());

    if (!p["size"].Null()) {
      size_t size = stol(p.Cast<string>("size"));
      EXPECT(size > 0, "Illegal array size.");

      Object obj;
      obj.CloneFrom(p["init_value"]);

      base->reserve(size);
      auto type_id = obj.GetTypeId();

      for (auto count = 0; count < size; count++) {
        base->emplace_back(Object(management::type::GetObjectCopy(obj), type_id));
      }
    }

    return Message().SetObject(Object(base, kTypeIdArray).SetConstructorFlag());
  }

  Message ArrayGetElement(ObjectMap &p) {
    EXPECT_TYPE(p, "index", kTypeIdRawString);

    ObjectArray &base = p.Cast<ObjectArray>(kStrObject);
    //DEBUG_EVENT("(ArrayGetElement Interface)Index:" + p.Cast<string>("index"));
    size_t idx = stol(p.Cast<string>("index"));
    size_t size = base.size();

    EXPECT(idx < size, "Subscript is out of range. - " + to_string(idx));

    return Message().SetObject(Object().CreateRef(base[idx]));
  }

  Message ArrayGetSize(ObjectMap &p) {
    auto &obj = p[kStrObject];
    return Message(to_string(obj.Cast<ObjectArray>().size()));
  }

  Message ArrayEmpty(ObjectMap &p) {
    return Message(
      util::MakeBoolean(p[kStrObject].Cast<ObjectArray>().empty())
    );
  }

  Message ArrayPush(ObjectMap &p) {
    ObjectArray &base = p.Cast<ObjectArray>(kStrObject);

    base.emplace_back(p["object"]);

    return Message();
  }

  Message ArrayPop(ObjectMap &p) {
    ObjectArray &base = p.Cast<ObjectArray>(kStrObject);

    if (!base.empty()) base.pop_back();

    return Message().SetObject(util::MakeBoolean(base.empty()));
  }

  Message ArrayPrint(ObjectMap &p) {
    Message result;
    ObjectMap obj_map;

    auto &base = p.Cast<ObjectArray>(kStrObject);
    auto interface = management::Order("print", kTypeIdNull, -1);

    for (auto &unit : base) {
      obj_map.insert(NamedObject(kStrObject, unit));
      result = interface.Start(obj_map);
      obj_map.clear();
    }

    return result;
  }

  Message ArrayBegin(ObjectMap &p) {
    auto &base = p[kStrObject].Cast<ObjectArray>();
    shared_ptr<IteratorPackage> pkg(
      new IteratorPackage(base.begin(), kContainerObjectArray)
    );
    return Message().SetObject(
      Object(pkg, kTypeIdIterator)
    );
  }

  Message ArrayEnd(ObjectMap &p) {
    auto &base = p[kStrObject].Cast<ObjectArray>();
    shared_ptr<IteratorPackage> pkg(
      new IteratorPackage(base.end(), kContainerObjectArray)
    );
    return Message().SetObject(
      Object(pkg, kTypeIdIterator)
    );
  }

  Message ArrayCompare(ObjectMap &p) {
    auto &rhs = p[kStrRightHandSide];
    auto &lhs = p[kStrObject].Cast<ObjectArray>();
    bool result = false;

    if (rhs.GetTypeId() == kTypeIdArray) {
      auto &rhs_objarray = rhs.Cast<ObjectArray>();
      result = (lhs == rhs_objarray);
    }

    return Message(util::MakeBoolean(result));
  }

  void InitContainerComponents() {
    using management::type::NewTypeSetup;

    NewTypeSetup(kTypeIdArray, [](shared_ptr<void> source) -> shared_ptr<void> {
      auto &src_base = *static_pointer_cast<ObjectArray>(source);
      shared_ptr<ObjectArray> dest_base = make_shared<ObjectArray>();

      dest_base->reserve(src_base.size());

      for (auto &unit : src_base) {
        dest_base->emplace_back(Object(management::type::GetObjectCopy(unit), unit.GetTypeId()));
      }

      return dest_base;
    })
      .InitConstructor(
        Interface(ArrayConstructor, "size|init_value", "array", kCodeAutoFill)
      )
      .InitMethods(
        {
          Interface(ArrayGetElement, "index", "__at"),
          Interface(ArrayPrint, "", "__print"),
          Interface(ArrayGetSize, "", "size"),
          Interface(ArrayPush, "object", "push"),
          Interface(ArrayPop, "object", "pop"),
          Interface(ArrayEmpty, "", "empty"),
          Interface(ArrayBegin, "", "head"),
          Interface(ArrayEnd, "", "tail")
        }
    );

    NewTypeSetup(kTypeIdIterator, SimpleSharedPtrCopy<IteratorPackage>)
      .InitMethods(
        {
          Interface(IteratorGet, "", "get"),
          Interface(IteratorStepForward, "", "step_forward"),
          Interface(IteratorStepBack, "", "step_back"),
          Interface(IteratorOperatorCompare, kStrRightHandSide, kStrCompare)
        }
    );
  }
}<|endoftext|>


<commit_before><commit_msg>Session::{get,set}IdleTimeout<commit_after><|endoftext|>


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

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

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

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

#include "tensorflow/core/framework/logging.h"

#include <iostream>

#include "tensorflow/core/lib/strings/str_util.h"

namespace tensorflow {

namespace logging {

typedef std::vector<void (*)(const char*)> Listeners;

Listeners* GetListeners() {
  static Listeners* listeners = new Listeners;
  return listeners;
}

bool RegisterListener(void (*listener)(const char*)) {
  GetListeners()->push_back(listener);
  return true;
}

bool LogToListeners(string msg, string end) {
  auto listeners = logging::GetListeners();
  if (listeners->empty()) {
    return false;
  }

  string ended_msg = strings::StrCat(msg, end);

  for (auto& listener : *listeners) {
    listener(ended_msg.c_str());
  }

  return true;
}

}  // end namespace logging

}  // end namespace tensorflow
<commit_msg>Include missing header file in logging.cc.<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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

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

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

#include "tensorflow/core/framework/logging.h"

#include <iostream>

#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/lib/strings/strcat.h"

namespace tensorflow {

namespace logging {

typedef std::vector<void (*)(const char*)> Listeners;

Listeners* GetListeners() {
  static Listeners* listeners = new Listeners;
  return listeners;
}

bool RegisterListener(void (*listener)(const char*)) {
  GetListeners()->push_back(listener);
  return true;
}

bool LogToListeners(string msg, string end) {
  auto listeners = logging::GetListeners();
  if (listeners->empty()) {
    return false;
  }

  string ended_msg = strings::StrCat(msg, end);

  for (auto& listener : *listeners) {
    listener(ended_msg.c_str());
  }

  return true;
}

}  // end namespace logging

}  // end namespace tensorflow
<|endoftext|>


<commit_before><commit_msg>set the zoom only once, prevents infinite loop, fdo#51040<commit_after><|endoftext|>


<commit_before>/* Copyright (c) 2012-2014 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * \file
 * This is a basic latency/bandwidth benchmark of LogCabin.
 */

#include <cassert>
#include <ctime>
#include <getopt.h>
#include <iostream>
#include <thread>

#include "Client/Client.h"

namespace {

using LogCabin::Client::Cluster;
using LogCabin::Client::Result;
using LogCabin::Client::Status;
using LogCabin::Client::Tree;

/**
 * Parses argv for the main function.
 */
class OptionParser {
  public:
    OptionParser(int& argc, char**& argv)
        : argc(argc)
        , argv(argv)
        , cluster("logcabin:61023")
        , size(1024)
        , writers(1)
        , totalWrites(1000)
    {
        while (true) {
            static struct option longOptions[] = {
               {"cluster",  required_argument, NULL, 'c'},
               {"help",  no_argument, NULL, 'h'},
               {"size",  required_argument, NULL, 's'},
               {"threads",  required_argument, NULL, 't'},
               {"writes",  required_argument, NULL, 'w'},
               {0, 0, 0, 0}
            };
            int c = getopt_long(argc, argv, "c:hs:t:w:", longOptions, NULL);

            // Detect the end of the options.
            if (c == -1)
                break;

            switch (c) {
                case 'c':
                    cluster = optarg;
                    break;
                case 'h':
                    usage();
                    exit(0);
                case 's':
                    size = uint64_t(atol(optarg));
                    break;
                case 't':
                    writers = uint64_t(atol(optarg));
                    break;
                case 'w':
                    totalWrites = uint64_t(atol(optarg));
                    break;
                case '?':
                default:
                    // getopt_long already printed an error message.
                    usage();
                    exit(1);
            }
        }
    }

    void usage() {
        std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
        std::cout << "Options: " << std::endl;
        std::cout << "  -c, --cluster <address> "
                  << "The network address of the LogCabin cluster "
                  << "(default: logcabin:61023)" << std::endl;
        std::cout << "  -h, --help              "
                  << "Print this usage information" << std::endl;
        std::cout << "  --size <bytes>          "
                  << "Size of value in each write [default: 1024]"
                  << std::endl;
        std::cout << "  --threads <num>         "
                  << "Number of concurrent writers [default: 1]"
                  << std::endl;
        std::cout << "  --writes <num>          "
                  << "Number of total writes [default: 1000]"
                  << std::endl;
    }

    int& argc;
    char**& argv;
    std::string cluster;
    uint64_t size;
    uint64_t writers;
    uint64_t totalWrites;
};

void
writeThreadMain(uint64_t id,
                const OptionParser& options,
                Tree tree,
                const std::string& key,
                const std::string& value)
{
    uint64_t numWrites = options.totalWrites / options.writers;
    if (id == 0) { // thread 0 takes any odd leftover writes
        numWrites = options.totalWrites - numWrites * (options.writers - 1);
    }
    for (uint64_t i = 0; i < numWrites; ++i) {
        tree.writeEx(key, value);
    }
}

uint64_t timeNanos()
{
    struct timespec now;
    int r = clock_gettime(CLOCK_REALTIME, &now);
    assert(r == 0);
    return uint64_t(now.tv_sec) * 1000 * 1000 * 1000 + now.tv_nsec;
}

} // anonymous namespace

int
main(int argc, char** argv)
{
    OptionParser options(argc, argv);
    Cluster cluster = Cluster(options.cluster);
    Tree tree = cluster.getTree();

    std::string key("/bench");
    std::string value(options.size, 'v');

    uint64_t startNanos = timeNanos();
    std::vector<std::thread> threads;
    for (uint64_t i = 0; i < options.writers; ++i) {
        threads.emplace_back(writeThreadMain, i, std::ref(options),
                             tree, std::ref(key), std::ref(value));
    }
    for (uint64_t i = 0; i < options.writers; ++i) {
        threads.at(i).join();
    }
    uint64_t endNanos = timeNanos();

    tree.removeFile(key);
    std::cout << "Benchmark took "
              << static_cast<double>(endNanos - startNanos) / 1e6 << " ms"
              << std::endl;
    return 0;
}
<commit_msg>Benchmark: assign odd writes to threads more evenly<commit_after>/* Copyright (c) 2012-2014 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * \file
 * This is a basic latency/bandwidth benchmark of LogCabin.
 */

#include <cassert>
#include <ctime>
#include <getopt.h>
#include <iostream>
#include <thread>

#include "Client/Client.h"

namespace {

using LogCabin::Client::Cluster;
using LogCabin::Client::Result;
using LogCabin::Client::Status;
using LogCabin::Client::Tree;

/**
 * Parses argv for the main function.
 */
class OptionParser {
  public:
    OptionParser(int& argc, char**& argv)
        : argc(argc)
        , argv(argv)
        , cluster("logcabin:61023")
        , size(1024)
        , writers(1)
        , totalWrites(1000)
    {
        while (true) {
            static struct option longOptions[] = {
               {"cluster",  required_argument, NULL, 'c'},
               {"help",  no_argument, NULL, 'h'},
               {"size",  required_argument, NULL, 's'},
               {"threads",  required_argument, NULL, 't'},
               {"writes",  required_argument, NULL, 'w'},
               {0, 0, 0, 0}
            };
            int c = getopt_long(argc, argv, "c:hs:t:w:", longOptions, NULL);

            // Detect the end of the options.
            if (c == -1)
                break;

            switch (c) {
                case 'c':
                    cluster = optarg;
                    break;
                case 'h':
                    usage();
                    exit(0);
                case 's':
                    size = uint64_t(atol(optarg));
                    break;
                case 't':
                    writers = uint64_t(atol(optarg));
                    break;
                case 'w':
                    totalWrites = uint64_t(atol(optarg));
                    break;
                case '?':
                default:
                    // getopt_long already printed an error message.
                    usage();
                    exit(1);
            }
        }
    }

    void usage() {
        std::cout << "Usage: " << argv[0] << " [options]" << std::endl;
        std::cout << "Options: " << std::endl;
        std::cout << "  -c, --cluster <address> "
                  << "The network address of the LogCabin cluster "
                  << "(default: logcabin:61023)" << std::endl;
        std::cout << "  -h, --help              "
                  << "Print this usage information" << std::endl;
        std::cout << "  --size <bytes>          "
                  << "Size of value in each write [default: 1024]"
                  << std::endl;
        std::cout << "  --threads <num>         "
                  << "Number of concurrent writers [default: 1]"
                  << std::endl;
        std::cout << "  --writes <num>          "
                  << "Number of total writes [default: 1000]"
                  << std::endl;
    }

    int& argc;
    char**& argv;
    std::string cluster;
    uint64_t size;
    uint64_t writers;
    uint64_t totalWrites;
};

void
writeThreadMain(uint64_t id,
                const OptionParser& options,
                Tree tree,
                const std::string& key,
                const std::string& value)
{
    uint64_t numWrites = options.totalWrites / options.writers;
    // assign any odd leftover writes in a balanced way
    if (options.totalWrites - numWrites * options.writers > id)
        numWrites += 1;
    for (uint64_t i = 0; i < numWrites; ++i) {
        tree.writeEx(key, value);
    }
}

uint64_t timeNanos()
{
    struct timespec now;
    int r = clock_gettime(CLOCK_REALTIME, &now);
    assert(r == 0);
    return uint64_t(now.tv_sec) * 1000 * 1000 * 1000 + now.tv_nsec;
}

} // anonymous namespace

int
main(int argc, char** argv)
{
    OptionParser options(argc, argv);
    Cluster cluster = Cluster(options.cluster);
    Tree tree = cluster.getTree();

    std::string key("/bench");
    std::string value(options.size, 'v');

    uint64_t startNanos = timeNanos();
    std::vector<std::thread> threads;
    for (uint64_t i = 0; i < options.writers; ++i) {
        threads.emplace_back(writeThreadMain, i, std::ref(options),
                             tree, std::ref(key), std::ref(value));
    }
    for (uint64_t i = 0; i < options.writers; ++i) {
        threads.at(i).join();
    }
    uint64_t endNanos = timeNanos();

    tree.removeFile(key);
    std::cout << "Benchmark took "
              << static_cast<double>(endNanos - startNanos) / 1e6 << " ms"
              << std::endl;
    return 0;
}
<|endoftext|>


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

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

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

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

#include "absl/container/flat_hash_map.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/op_requires.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/platform/errors.h"
#include "tensorflow/core/platform/types.h"

namespace tensorflow {

template <class T>
using BatchedMap = std::vector<absl::flat_hash_map<int64_t, T>>;

namespace {
// TODO(momernick): Extend this function to work with outputs of rank > 2.
template <class T>
Status OutputSparse(const BatchedMap<T>& per_batch_counts, int num_values,
                    bool is_1d, OpKernelContext* context) {
  int total_values = 0;
  int num_batches = per_batch_counts.size();
  for (const auto& per_batch_count : per_batch_counts) {
    total_values += per_batch_count.size();
  }

  Tensor* indices;
  int inner_dim = is_1d ? 1 : 2;
  TF_RETURN_IF_ERROR(context->allocate_output(
      0, TensorShape({total_values, inner_dim}), &indices));

  Tensor* values;
  TF_RETURN_IF_ERROR(
      context->allocate_output(1, TensorShape({total_values}), &values));

  auto output_indices = indices->matrix<int64_t>();
  auto output_values = values->flat<T>();
  int64_t value_loc = 0;
  for (int b = 0; b < num_batches; ++b) {
    const auto& per_batch_count = per_batch_counts[b];
    std::vector<std::pair<int, T>> pairs(per_batch_count.begin(),
                                         per_batch_count.end());
    std::sort(pairs.begin(), pairs.end());
    for (const auto& x : pairs) {
      if (is_1d) {
        output_indices(value_loc, 0) = x.first;
      } else {
        output_indices(value_loc, 0) = b;
        output_indices(value_loc, 1) = x.first;
      }
      output_values(value_loc) = x.second;
      ++value_loc;
    }
  }
  Tensor* dense_shape;
  if (is_1d) {
    TF_RETURN_IF_ERROR(
        context->allocate_output(2, TensorShape({1}), &dense_shape));
    dense_shape->flat<int64_t>().data()[0] = num_values;
  } else {
    TF_RETURN_IF_ERROR(
        context->allocate_output(2, TensorShape({2}), &dense_shape));
    dense_shape->flat<int64_t>().data()[0] = num_batches;
    dense_shape->flat<int64_t>().data()[1] = num_values;
  }

  return Status::OK();
}

int GetOutputSize(int max_seen, int max_length, int min_length) {
  return max_length > 0 ? max_length : std::max((max_seen + 1), min_length);
}

}  // namespace

template <class T, class W>
class DenseCount : public OpKernel {
 public:
  explicit DenseCount(OpKernelConstruction* context) : OpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("minlength", &minlength_));
    OP_REQUIRES_OK(context, context->GetAttr("maxlength", &maxlength_));
    OP_REQUIRES_OK(context, context->GetAttr("binary_output", &binary_output_));
  }

  void Compute(OpKernelContext* context) override {
    const Tensor& data = context->input(0);
    const Tensor& weights = context->input(1);
    bool use_weights = weights.NumElements() > 0;

    OP_REQUIRES(context,
                TensorShapeUtils::IsVector(data.shape()) ||
                    TensorShapeUtils::IsMatrix(data.shape()),
                errors::InvalidArgument(
                    "Input must be a 1 or 2-dimensional tensor. Got: ",
                    data.shape().DebugString()));

    if (use_weights) {
      OP_REQUIRES(
          context, weights.shape() == data.shape(),
          errors::InvalidArgument(
              "Weights and data must have the same shape. Weight shape: ",
              weights.shape().DebugString(),
              "; data shape: ", data.shape().DebugString()));
    }

    bool is_1d = TensorShapeUtils::IsVector(data.shape());
    int negative_valued_axis = -1;
    int num_batch_dimensions = (data.shape().dims() + negative_valued_axis);

    int num_batch_elements = 1;
    for (int i = 0; i < num_batch_dimensions; ++i) {
      OP_REQUIRES(context, data.shape().dim_size(i) != 0,
                  errors::InvalidArgument(
                      "Invalid input: Shapes dimension cannot be 0."));
      num_batch_elements *= data.shape().dim_size(i);
    }
    int num_value_elements = data.shape().num_elements() / num_batch_elements;
    auto per_batch_counts = BatchedMap<W>(num_batch_elements);

    T max_value = 0;

    const auto data_values = data.flat<T>();
    const auto weight_values = weights.flat<W>();
    int i = 0;
    for (int b = 0; b < num_batch_elements; ++b) {
      for (int v = 0; v < num_value_elements; ++v) {
        const auto& value = data_values(i);
        if (value >= 0 && (maxlength_ <= 0 || value < maxlength_)) {
          if (binary_output_) {
            per_batch_counts[b][value] = 1;
          } else if (use_weights) {
            per_batch_counts[b][value] += weight_values(i);
          } else {
            per_batch_counts[b][value]++;
          }
          if (value > max_value) {
            max_value = value;
          }
        }
        ++i;
      }
    }

    int num_output_values = GetOutputSize(max_value, maxlength_, minlength_);
    OP_REQUIRES_OK(context, OutputSparse<W>(per_batch_counts, num_output_values,
                                            is_1d, context));
  }

 private:
  int maxlength_;
  int minlength_;
  bool binary_output_;
};

template <class T, class W>
class SparseCount : public OpKernel {
 public:
  explicit SparseCount(OpKernelConstruction* context) : OpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("minlength", &minlength_));
    OP_REQUIRES_OK(context, context->GetAttr("maxlength", &maxlength_));
    OP_REQUIRES_OK(context, context->GetAttr("binary_output", &binary_output_));
  }

  void Compute(OpKernelContext* context) override {
    const Tensor& indices = context->input(0);
    const Tensor& values = context->input(1);
    const Tensor& shape = context->input(2);
    const Tensor& weights = context->input(3);
    bool use_weights = weights.NumElements() > 0;

    OP_REQUIRES(context, TensorShapeUtils::IsMatrix(indices.shape()),
                errors::InvalidArgument(
                    "Input indices must be a 2-dimensional tensor. Got: ",
                    indices.shape().DebugString()));
    OP_REQUIRES(context, TensorShapeUtils::IsVector(values.shape()),
                errors::InvalidArgument("Input values must be a vector. Got: ",
                                        values.shape().DebugString()));
    OP_REQUIRES(context, TensorShapeUtils::IsVector(shape.shape()),
                errors::InvalidArgument("Input shape must be a vector. Got: ",
                                        shape.shape().DebugString()));
    OP_REQUIRES(context,
                values.shape().dim_size(0) == indices.shape().dim_size(0),
                errors::InvalidArgument(
                    "Number of values must match first dimension of indices.",
                    "Got ", values.shape().dim_size(0),
                    " values, indices shape: ", indices.shape().DebugString()));
    OP_REQUIRES(
        context, shape.shape().dim_size(0) == indices.shape().dim_size(1),
        errors::InvalidArgument(
            "Number of dimensions must match second dimension of indices.",
            "Got ", shape.shape().dim_size(0),
            " dimensions, indices shape: ", indices.shape().DebugString()));
    OP_REQUIRES(context, shape.NumElements() > 0,
                errors::InvalidArgument(
                    "The shape argument requires at least one element."));

    if (use_weights) {
      OP_REQUIRES(
          context, weights.shape() == values.shape(),
          errors::InvalidArgument(
              "Weights and values must have the same shape. Weight shape: ",
              weights.shape().DebugString(),
              "; values shape: ", values.shape().DebugString()));
    }

    bool is_1d = shape.NumElements() == 1;
    auto shape_vector = shape.flat<int64_t>();
    int num_batches = is_1d ? 1 : shape_vector(0);
    int num_values = values.NumElements();

    const auto indices_values = indices.matrix<int64_t>();
    const auto values_values = values.flat<T>();
    const auto weight_values = weights.flat<W>();

    auto per_batch_counts = BatchedMap<W>(num_batches);

    T max_value = 0;

    for (int idx = 0; idx < num_values; ++idx) {
      int batch = is_1d ? 0 : indices_values(idx, 0);
      if (batch >= num_batches) {
        OP_REQUIRES(context, batch < num_batches,
                    errors::InvalidArgument(
                        "Indices value along the first dimension must be ",
                        "lower than the first index of the shape.", "Got ",
                        batch, " as batch and ", num_batches,
                        " as the first dimension of the shape."));
      }
      const auto& value = values_values(idx);
      if (value >= 0 && (maxlength_ <= 0 || value < maxlength_)) {
        if (binary_output_) {
          per_batch_counts[batch][value] = 1;
        } else if (use_weights) {
          per_batch_counts[batch][value] += weight_values(idx);
        } else {
          per_batch_counts[batch][value]++;
        }
        if (value > max_value) {
          max_value = value;
        }
      }
    }

    int num_output_values = GetOutputSize(max_value, maxlength_, minlength_);
    OP_REQUIRES_OK(context, OutputSparse<W>(per_batch_counts, num_output_values,
                                            is_1d, context));
  }

 private:
  int maxlength_;
  int minlength_;
  bool binary_output_;
  bool validate_;
};

template <class T, class W>
class RaggedCount : public OpKernel {
 public:
  explicit RaggedCount(OpKernelConstruction* context) : OpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("minlength", &minlength_));
    OP_REQUIRES_OK(context, context->GetAttr("maxlength", &maxlength_));
    OP_REQUIRES_OK(context, context->GetAttr("binary_output", &binary_output_));
  }

  void Compute(OpKernelContext* context) override {
    const Tensor& splits = context->input(0);
    const Tensor& values = context->input(1);
    const Tensor& weights = context->input(2);
    bool use_weights = weights.NumElements() > 0;
    bool is_1d = false;

    if (use_weights) {
      OP_REQUIRES(
          context, weights.shape() == values.shape(),
          errors::InvalidArgument(
              "Weights and values must have the same shape. Weight shape: ",
              weights.shape().DebugString(),
              "; values shape: ", values.shape().DebugString()));
    }

    const auto splits_values = splits.flat<int64_t>();
    const auto values_values = values.flat<T>();
    const auto weight_values = weights.flat<W>();
    int num_batches = splits.NumElements() - 1;
    int num_values = values.NumElements();

    OP_REQUIRES(
        context, num_batches > 0,
        errors::InvalidArgument(
            "Must provide at least 2 elements for the splits argument"));
    OP_REQUIRES(context, splits_values(0) == 0,
                errors::InvalidArgument("Splits must start with 0, not with ",
                                        splits_values(0)));
    OP_REQUIRES(context, splits_values(num_batches) == num_values,
                errors::InvalidArgument(
                    "Splits must end with the number of values, got ",
                    splits_values(num_batches), " instead of ", num_values));

    auto per_batch_counts = BatchedMap<W>(num_batches);
    T max_value = 0;
    int batch_idx = 0;

    for (int idx = 0; idx < num_values; ++idx) {
      while (idx >= splits_values(batch_idx)) {
        batch_idx++;
      }
      const auto& value = values_values(idx);
      if (value >= 0 && (maxlength_ <= 0 || value < maxlength_)) {
        if (binary_output_) {
          per_batch_counts[batch_idx - 1][value] = 1;
        } else if (use_weights) {
          per_batch_counts[batch_idx - 1][value] += weight_values(idx);
        } else {
          per_batch_counts[batch_idx - 1][value]++;
        }
        if (value > max_value) {
          max_value = value;
        }
      }
    }

    int num_output_values = GetOutputSize(max_value, maxlength_, minlength_);
    OP_REQUIRES_OK(context, OutputSparse<W>(per_batch_counts, num_output_values,
                                            is_1d, context));
  }

 private:
  int maxlength_;
  int minlength_;
  bool binary_output_;
  bool validate_;
};

#define REGISTER_W(W_TYPE) \
  REGISTER(int32, W_TYPE)  \
  REGISTER(int64_t, W_TYPE)

#define REGISTER(I_TYPE, W_TYPE)                                     \
                                                                     \
  REGISTER_KERNEL_BUILDER(Name("DenseCountSparseOutput")             \
                              .TypeConstraint<I_TYPE>("T")           \
                              .TypeConstraint<W_TYPE>("output_type") \
                              .Device(DEVICE_CPU),                   \
                          DenseCount<I_TYPE, W_TYPE>)                \
                                                                     \
  REGISTER_KERNEL_BUILDER(Name("SparseCountSparseOutput")            \
                              .TypeConstraint<I_TYPE>("T")           \
                              .TypeConstraint<W_TYPE>("output_type") \
                              .Device(DEVICE_CPU),                   \
                          SparseCount<I_TYPE, W_TYPE>)               \
                                                                     \
  REGISTER_KERNEL_BUILDER(Name("RaggedCountSparseOutput")            \
                              .TypeConstraint<I_TYPE>("T")           \
                              .TypeConstraint<W_TYPE>("output_type") \
                              .Device(DEVICE_CPU),                   \
                          RaggedCount<I_TYPE, W_TYPE>)

TF_CALL_INTEGRAL_TYPES(REGISTER_W);
TF_CALL_float(REGISTER_W);
TF_CALL_double(REGISTER_W);

#undef REGISTER_W
#undef REGISTER

}  // namespace tensorflow
<commit_msg>Further validate sparse tensor for `SparseCount`: indices must be valid within dense shape.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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

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

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

#include "absl/container/flat_hash_map.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/op_requires.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/platform/errors.h"
#include "tensorflow/core/platform/types.h"

namespace tensorflow {

template <class T>
using BatchedMap = std::vector<absl::flat_hash_map<int64_t, T>>;

namespace {
// TODO(momernick): Extend this function to work with outputs of rank > 2.
template <class T>
Status OutputSparse(const BatchedMap<T>& per_batch_counts, int num_values,
                    bool is_1d, OpKernelContext* context) {
  int total_values = 0;
  int num_batches = per_batch_counts.size();
  for (const auto& per_batch_count : per_batch_counts) {
    total_values += per_batch_count.size();
  }

  Tensor* indices;
  int inner_dim = is_1d ? 1 : 2;
  TF_RETURN_IF_ERROR(context->allocate_output(
      0, TensorShape({total_values, inner_dim}), &indices));

  Tensor* values;
  TF_RETURN_IF_ERROR(
      context->allocate_output(1, TensorShape({total_values}), &values));

  auto output_indices = indices->matrix<int64_t>();
  auto output_values = values->flat<T>();
  int64_t value_loc = 0;
  for (int b = 0; b < num_batches; ++b) {
    const auto& per_batch_count = per_batch_counts[b];
    std::vector<std::pair<int, T>> pairs(per_batch_count.begin(),
                                         per_batch_count.end());
    std::sort(pairs.begin(), pairs.end());
    for (const auto& x : pairs) {
      if (is_1d) {
        output_indices(value_loc, 0) = x.first;
      } else {
        output_indices(value_loc, 0) = b;
        output_indices(value_loc, 1) = x.first;
      }
      output_values(value_loc) = x.second;
      ++value_loc;
    }
  }
  Tensor* dense_shape;
  if (is_1d) {
    TF_RETURN_IF_ERROR(
        context->allocate_output(2, TensorShape({1}), &dense_shape));
    dense_shape->flat<int64_t>().data()[0] = num_values;
  } else {
    TF_RETURN_IF_ERROR(
        context->allocate_output(2, TensorShape({2}), &dense_shape));
    dense_shape->flat<int64_t>().data()[0] = num_batches;
    dense_shape->flat<int64_t>().data()[1] = num_values;
  }

  return Status::OK();
}

int GetOutputSize(int max_seen, int max_length, int min_length) {
  return max_length > 0 ? max_length : std::max((max_seen + 1), min_length);
}

}  // namespace

template <class T, class W>
class DenseCount : public OpKernel {
 public:
  explicit DenseCount(OpKernelConstruction* context) : OpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("minlength", &minlength_));
    OP_REQUIRES_OK(context, context->GetAttr("maxlength", &maxlength_));
    OP_REQUIRES_OK(context, context->GetAttr("binary_output", &binary_output_));
  }

  void Compute(OpKernelContext* context) override {
    const Tensor& data = context->input(0);
    const Tensor& weights = context->input(1);
    bool use_weights = weights.NumElements() > 0;

    OP_REQUIRES(context,
                TensorShapeUtils::IsVector(data.shape()) ||
                    TensorShapeUtils::IsMatrix(data.shape()),
                errors::InvalidArgument(
                    "Input must be a 1 or 2-dimensional tensor. Got: ",
                    data.shape().DebugString()));

    if (use_weights) {
      OP_REQUIRES(
          context, weights.shape() == data.shape(),
          errors::InvalidArgument(
              "Weights and data must have the same shape. Weight shape: ",
              weights.shape().DebugString(),
              "; data shape: ", data.shape().DebugString()));
    }

    bool is_1d = TensorShapeUtils::IsVector(data.shape());
    int negative_valued_axis = -1;
    int num_batch_dimensions = (data.shape().dims() + negative_valued_axis);

    int num_batch_elements = 1;
    for (int i = 0; i < num_batch_dimensions; ++i) {
      OP_REQUIRES(context, data.shape().dim_size(i) != 0,
                  errors::InvalidArgument(
                      "Invalid input: Shapes dimension cannot be 0."));
      num_batch_elements *= data.shape().dim_size(i);
    }
    int num_value_elements = data.shape().num_elements() / num_batch_elements;
    auto per_batch_counts = BatchedMap<W>(num_batch_elements);

    T max_value = 0;

    const auto data_values = data.flat<T>();
    const auto weight_values = weights.flat<W>();
    int i = 0;
    for (int b = 0; b < num_batch_elements; ++b) {
      for (int v = 0; v < num_value_elements; ++v) {
        const auto& value = data_values(i);
        if (value >= 0 && (maxlength_ <= 0 || value < maxlength_)) {
          if (binary_output_) {
            per_batch_counts[b][value] = 1;
          } else if (use_weights) {
            per_batch_counts[b][value] += weight_values(i);
          } else {
            per_batch_counts[b][value]++;
          }
          if (value > max_value) {
            max_value = value;
          }
        }
        ++i;
      }
    }

    int num_output_values = GetOutputSize(max_value, maxlength_, minlength_);
    OP_REQUIRES_OK(context, OutputSparse<W>(per_batch_counts, num_output_values,
                                            is_1d, context));
  }

 private:
  int maxlength_;
  int minlength_;
  bool binary_output_;
};

template <class T, class W>
class SparseCount : public OpKernel {
 public:
  explicit SparseCount(OpKernelConstruction* context) : OpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("minlength", &minlength_));
    OP_REQUIRES_OK(context, context->GetAttr("maxlength", &maxlength_));
    OP_REQUIRES_OK(context, context->GetAttr("binary_output", &binary_output_));
  }

  void Compute(OpKernelContext* context) override {
    const Tensor& indices = context->input(0);
    const Tensor& values = context->input(1);
    const Tensor& shape = context->input(2);
    const Tensor& weights = context->input(3);
    bool use_weights = weights.NumElements() > 0;

    OP_REQUIRES(context, TensorShapeUtils::IsMatrix(indices.shape()),
                errors::InvalidArgument(
                    "Input indices must be a 2-dimensional tensor. Got: ",
                    indices.shape().DebugString()));
    OP_REQUIRES(context, TensorShapeUtils::IsVector(values.shape()),
                errors::InvalidArgument("Input values must be a vector. Got: ",
                                        values.shape().DebugString()));
    OP_REQUIRES(context, TensorShapeUtils::IsVector(shape.shape()),
                errors::InvalidArgument("Input shape must be a vector. Got: ",
                                        shape.shape().DebugString()));
    OP_REQUIRES(context,
                values.shape().dim_size(0) == indices.shape().dim_size(0),
                errors::InvalidArgument(
                    "Number of values must match first dimension of indices.",
                    "Got ", values.shape().dim_size(0),
                    " values, indices shape: ", indices.shape().DebugString()));
    OP_REQUIRES(
        context, shape.shape().dim_size(0) == indices.shape().dim_size(1),
        errors::InvalidArgument(
            "Number of dimensions must match second dimension of indices.",
            "Got ", shape.shape().dim_size(0),
            " dimensions, indices shape: ", indices.shape().DebugString()));
    OP_REQUIRES(context, shape.NumElements() > 0,
                errors::InvalidArgument(
                    "The shape argument requires at least one element."));
    // Validate indices: each index must be valid for the corresponding
    // dimension. This could be possibly done better.
    const auto indices_values = indices.matrix<int64_t>();
    const auto shape_vector = shape.vec<int64_t>();
    int num_values = values.NumElements();  // same as first dim of indices
    int rank = indices.shape().dim_size(1);
    for (int i = 0; i < num_values; ++i) {
      for (int j = 0; j < rank; ++j) {
        OP_REQUIRES(
            context,
            indices_values(i, j) >= 0 && indices_values(i, j) < shape_vector(j),
            errors::InvalidArgument(
                "Invalid index value at ", i, ": dimension ", j, " has value ",
                indices_values(i, j), " which is not in [0, ", shape_vector(j),
                ") (as given by dense shape ", shape.DebugString()));
      }
    }

    if (use_weights) {
      OP_REQUIRES(
          context, weights.shape() == values.shape(),
          errors::InvalidArgument(
              "Weights and values must have the same shape. Weight shape: ",
              weights.shape().DebugString(),
              "; values shape: ", values.shape().DebugString()));
    }

    bool is_1d = shape.NumElements() == 1;
    int num_batches = is_1d ? 1 : shape_vector(0);

    const auto values_values = values.flat<T>();
    const auto weight_values = weights.flat<W>();

    auto per_batch_counts = BatchedMap<W>(num_batches);

    T max_value = 0;

    for (int idx = 0; idx < num_values; ++idx) {
      int batch = is_1d ? 0 : indices_values(idx, 0);
      if (batch >= num_batches) {
        OP_REQUIRES(context, batch < num_batches,
                    errors::InvalidArgument(
                        "Indices value along the first dimension must be ",
                        "lower than the first index of the shape.", "Got ",
                        batch, " as batch and ", num_batches,
                        " as the first dimension of the shape."));
      }
      const auto& value = values_values(idx);
      if (value >= 0 && (maxlength_ <= 0 || value < maxlength_)) {
        if (binary_output_) {
          per_batch_counts[batch][value] = 1;
        } else if (use_weights) {
          per_batch_counts[batch][value] += weight_values(idx);
        } else {
          per_batch_counts[batch][value]++;
        }
        if (value > max_value) {
          max_value = value;
        }
      }
    }

    int num_output_values = GetOutputSize(max_value, maxlength_, minlength_);
    OP_REQUIRES_OK(context, OutputSparse<W>(per_batch_counts, num_output_values,
                                            is_1d, context));
  }

 private:
  int maxlength_;
  int minlength_;
  bool binary_output_;
  bool validate_;
};

template <class T, class W>
class RaggedCount : public OpKernel {
 public:
  explicit RaggedCount(OpKernelConstruction* context) : OpKernel(context) {
    OP_REQUIRES_OK(context, context->GetAttr("minlength", &minlength_));
    OP_REQUIRES_OK(context, context->GetAttr("maxlength", &maxlength_));
    OP_REQUIRES_OK(context, context->GetAttr("binary_output", &binary_output_));
  }

  void Compute(OpKernelContext* context) override {
    const Tensor& splits = context->input(0);
    const Tensor& values = context->input(1);
    const Tensor& weights = context->input(2);
    bool use_weights = weights.NumElements() > 0;
    bool is_1d = false;

    if (use_weights) {
      OP_REQUIRES(
          context, weights.shape() == values.shape(),
          errors::InvalidArgument(
              "Weights and values must have the same shape. Weight shape: ",
              weights.shape().DebugString(),
              "; values shape: ", values.shape().DebugString()));
    }

    const auto splits_values = splits.flat<int64_t>();
    const auto values_values = values.flat<T>();
    const auto weight_values = weights.flat<W>();
    int num_batches = splits.NumElements() - 1;
    int num_values = values.NumElements();

    OP_REQUIRES(
        context, num_batches > 0,
        errors::InvalidArgument(
            "Must provide at least 2 elements for the splits argument"));
    OP_REQUIRES(context, splits_values(0) == 0,
                errors::InvalidArgument("Splits must start with 0, not with ",
                                        splits_values(0)));
    OP_REQUIRES(context, splits_values(num_batches) == num_values,
                errors::InvalidArgument(
                    "Splits must end with the number of values, got ",
                    splits_values(num_batches), " instead of ", num_values));

    auto per_batch_counts = BatchedMap<W>(num_batches);
    T max_value = 0;
    int batch_idx = 0;

    for (int idx = 0; idx < num_values; ++idx) {
      while (idx >= splits_values(batch_idx)) {
        batch_idx++;
      }
      const auto& value = values_values(idx);
      if (value >= 0 && (maxlength_ <= 0 || value < maxlength_)) {
        if (binary_output_) {
          per_batch_counts[batch_idx - 1][value] = 1;
        } else if (use_weights) {
          per_batch_counts[batch_idx - 1][value] += weight_values(idx);
        } else {
          per_batch_counts[batch_idx - 1][value]++;
        }
        if (value > max_value) {
          max_value = value;
        }
      }
    }

    int num_output_values = GetOutputSize(max_value, maxlength_, minlength_);
    OP_REQUIRES_OK(context, OutputSparse<W>(per_batch_counts, num_output_values,
                                            is_1d, context));
  }

 private:
  int maxlength_;
  int minlength_;
  bool binary_output_;
  bool validate_;
};

#define REGISTER_W(W_TYPE) \
  REGISTER(int32, W_TYPE)  \
  REGISTER(int64_t, W_TYPE)

#define REGISTER(I_TYPE, W_TYPE)                                     \
                                                                     \
  REGISTER_KERNEL_BUILDER(Name("DenseCountSparseOutput")             \
                              .TypeConstraint<I_TYPE>("T")           \
                              .TypeConstraint<W_TYPE>("output_type") \
                              .Device(DEVICE_CPU),                   \
                          DenseCount<I_TYPE, W_TYPE>)                \
                                                                     \
  REGISTER_KERNEL_BUILDER(Name("SparseCountSparseOutput")            \
                              .TypeConstraint<I_TYPE>("T")           \
                              .TypeConstraint<W_TYPE>("output_type") \
                              .Device(DEVICE_CPU),                   \
                          SparseCount<I_TYPE, W_TYPE>)               \
                                                                     \
  REGISTER_KERNEL_BUILDER(Name("RaggedCountSparseOutput")            \
                              .TypeConstraint<I_TYPE>("T")           \
                              .TypeConstraint<W_TYPE>("output_type") \
                              .Device(DEVICE_CPU),                   \
                          RaggedCount<I_TYPE, W_TYPE>)

TF_CALL_INTEGRAL_TYPES(REGISTER_W);
TF_CALL_float(REGISTER_W);
TF_CALL_double(REGISTER_W);

#undef REGISTER_W
#undef REGISTER

}  // namespace tensorflow
<|endoftext|>


<commit_before>//=====================================================================//
/*!	@file
	@brief	R8C LED 点滅 @n
			LED は、P1_0(20)、P1_1(19)に接続（吸い込み点灯）@n
			※M120AN(20)
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2021 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include "system.hpp"
#include "clock.hpp"
#include "port.hpp"
#include "common/vect.h"
#include "common/delay.hpp"
#include "common/port_map.hpp"

namespace {

	typedef device::PORT<device::PORT1, device::bitpos::B0> LED0;
	typedef device::PORT<device::PORT1, device::bitpos::B1> LED1;

}

int main(int argc, char *argv[])
{
	using namespace device;

// クロック関係レジスタ・プロテクト解除
	PRCR.PRC0 = 1;

// 高速オンチップオシレーターへ切り替え
	OCOCR.HOCOE = 1;
	utils::delay::micro_second(1);  // >=30us(125KHz)
	SCKCR.HSCKSEL = 1;
	CKSTPR.SCKSEL = 1;

	// LED 設定
	{
		LED0::DIR = 1;
		LED1::DIR = 1;
	}

	// LED 点滅メイン
	while(1) {
		LED0::P = 0;
		LED1::P = 1;
		// 250ms (0.25s)
		utils::delay::milli_second(250);
		LED0::P = 1;
		LED1::P = 0;
		// 250ms (0.25s)
		utils::delay::milli_second(250);
	}
}
<commit_msg>Update: cleanup<commit_after>//=====================================================================//
/*!	@file
	@brief	R8C LED 点滅 @n
			LED は、P1_0(20)、P1_1(19)に接続（吸い込み点灯）@n
			※M120AN(20)
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2021 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include "system.hpp"
#include "clock.hpp"
#include "port.hpp"
#include "common/vect.h"
#include "common/delay.hpp"
#include "common/port_map.hpp"

namespace {

	// LED は '0' で点灯、'1' で消灯するように接続するので、LED クラスの論理を反転して定義する
	typedef device::PORT<device::PORT1, device::bitpos::B0, false> LED0;
	typedef device::PORT<device::PORT1, device::bitpos::B1, false> LED1;

}

int main(int argc, char *argv[])
{
	using namespace device;

// クロック関係レジスタ・プロテクト解除
	PRCR.PRC0 = 1;

// 高速オンチップオシレーターへ切り替え
	OCOCR.HOCOE = 1;
	utils::delay::micro_second(1);  // >=30us(125KHz)
	SCKCR.HSCKSEL = 1;
	CKSTPR.SCKSEL = 1;

	// LED 設定
	{
		LED0::DIR = 1;
		LED1::DIR = 1;
	}

	// LED 点滅メイン
	while(1) {
		LED0::P = 0;
		LED1::P = 1;
		// 250ms (0.25s)
		utils::delay::milli_second(250);
		LED0::P = 1;
		LED1::P = 0;
		// 250ms (0.25s)
		utils::delay::milli_second(250);
	}
}
<|endoftext|>