<commit_before>/*
 * Open Source Movement Analysis Library
 * Copyright (C) 2016, Moveck Solution Inc., all rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *     * Neither the name(s) of the copyright holders nor the names
 *       of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written
 *       permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "openma/body/inversedynamicsmatrix.h"
#include "openma/body/inversedynamicsprocessor_p.h"

#include "openma/body/anchor.h"
#include "openma/body/chain.h"
#include "openma/body/inertialparameters.h"
#include "openma/body/joint.h"
#include "openma/body/model.h"
#include "openma/body/segment.h"
#include "openma/body/utils.h"
#include "openma/base/trial.h"
#include "openma/instrument/forceplate.h"
#include "openma/math.h"

// -------------------------------------------------------------------------- //
//                                 PRIVATE API                                //
// -------------------------------------------------------------------------- //

#ifndef DOXYGEN_SHOULD_SKIP_THIS

namespace ma
{
namespace body
{
  class InverseDynamicMatrixPrivate : public InverseDynamicProcessorPrivate
  {
    OPENMA_DECLARE_PINT_ACCESSOR(InverseDynamicMatrix)

  public:
    InverseDynamicMatrixPrivate(InverseDynamicMatrix* pint);
    ~InverseDynamicMatrixPrivate();
  };

  InverseDynamicMatrixPrivate::InverseDynamicMatrixPrivate(InverseDynamicMatrix* pint)
  : InverseDynamicProcessorPrivate(pint,"InverseDynamicMatrix")
  {};

  InverseDynamicMatrixPrivate::~InverseDynamicMatrixPrivate() = default;
};
};

#endif

// -------------------------------------------------------------------------- //
//                                 PUBLIC API                                 //
// -------------------------------------------------------------------------- //

OPENMA_INSTANCE_STATIC_TYPEID(ma::body::InverseDynamicMatrix);

namespace ma
{
namespace body
{
  /**
   * @class InverseDynamicMatrix openma/body/matrixinversedynamics.h
   * @brief Algorithm to compute joint kinetics expressed in the global frame
   *
   * @TODO Explain in details the required element to use this algorithm (model configure, external wrench, etc.).
   *
   * @ingroup openma_body
   */

  /**
   * Constructor
   */
  InverseDynamicMatrix::InverseDynamicMatrix(Node* parent)
  : InverseDynamicProcessor(*new InverseDynamicMatrixPrivate(this), parent)
  {};

  /**
   * Destructor
   */
  InverseDynamicMatrix::~InverseDynamicMatrix() _OPENMA_NOEXCEPT = default;

  /**
   * Internally this method is a combination of two algorithms published in the litterature [1,2].
   * Both of these algorithms are known to be less sensitive to noise [3]. The reason to use this is only to reduce computation time.
   *  - No need to convert to quaternion
   *  - No need to create sparse 6x6 matrices
   *  - Angular velocity and angular acceleration computed directly from rotation matrices
   *  - All the results are express in the inertial (global) coordinate system
   *
   * @par References
   *  1. Dumas et al., 2004, A 3D generic inverse dynamic method using wrench notation and quaternion algebra, Computer methods in Biomechanics and Biomedical Engineering, 7 (3), pp. 159-166
   *  2. Doriot & Chèze, 2004, A Three-Dimensional Kinematic and Dynamic Study of the Lower Limb During the Stance Phase of Gait Using an Homogeneous Matrix Approach, IEEE Transactions on Biomedical Engineering, 51 (1), pp. 21-27
   *  3. Dumas et al., 2007, Influence of the 3D Inverse Dynamic Method on the Joint Forces and Moments During Gait, ￼Journal of￼Biomechanical￼Engineering, 129, pp. 786-790
   */
  bool InverseDynamicMatrix::run(Node* inout)
  {
#if !defined(_MSC_VER)
#warning WE NEED TO MANAGE UNITS FOR FORCES AND MOMENTS
#endif

    auto models = inout->findChildren<Model*>({},{},false);
    for (auto& model : models)
    {
      auto chains = model->chains()->findChildren<Chain*>({},{},false);
      for (auto& chain : chains)
      {
        auto joints = chain->findChildren<Joint*>({},{},false);
        if (joints.empty())
        {
          warning("No joint found in the chain '%s'. Inverse dynamics for this chain aborted.", chain->name().c_str());
          continue;
        }
        // Properties check
        std::vector<TimeSequence*> tss(joints.size());
        unsigned inc = 0;
        for (const auto& joint : joints)
          tss[inc++] = joint->distalSegment()->pose();
        double rate = 0.0, start = 0.0;
        unsigned samples = 0;
        if (!compare_timesequences_properties(tss, rate, start, samples))
        {
          error("At least one segment's pose does not have the same sample rate, start time or number of samples in the chain '%s'.", chain->name().c_str());
          continue;
        }
        assert(rate > 0.);
        double dt = 1. / rate;
        double gres = 0.;
        math::Vector Fd, Md, pd;
        auto g = math::Map<const math::Vector>(1, model->gravity(), &gres).replicate(samples);
        // Iteration computation of joint kinetics
        for (auto itJ = joints.rbegin() ; itJ != joints.rend() ; ++itJ)
        {
          auto jnt = *itJ;
          auto seg = jnt->distalSegment();
          auto bsip = seg->findChild<InertialParameters*>();
          if (bsip == nullptr)
          {
            error("The segment '%s' does not have body segment inertial parameters. Inverse dynamics for the chain '%s' aborted.", seg->name().c_str(), chain->name().c_str());
            break;
          }

          // Internal variables used
          // -----------------------

          // - Pose of the segment
          auto pose = math::to_pose(seg->pose());
          // - Rotation component of the pose in the Inertial Coordinate System (ICS)
          auto R = pose.block<9>(0);
          // - Tensor of inertia expressed in the ICS
          math::Array<9> I = transform_relative_inertia(bsip, seg, pose);
          // - Centre of mass expressed in the ICS
          math::Position com = transform_relative_com(bsip, seg, pose);
          // - Mass of the segment
          double m = bsip->mass();
          // - Proximal end point of the segment
          auto pp = math::to_position(jnt->proximalAnchor()->position());
          if (!pp.isValid())
          {
            error("Unexpected error in the computation of proximal anchor position for the joint '%s'. Inverse dynamics for the chain '%s' aborted.", jnt->name().c_str(), chain->name().c_str());
            break;
          }
          // - Lever arm between the proximal end point and the centre of mass
          math::Position c = com - pp;

          // Derivatives computation
          // -----------------------
          // TODO Would it be possible to reduce the computation time by compute the angular velocity for the lower triangle only (same for the angular acceleration)

          // - Angular velocity of the segment in the ICS
          math::Array<3> omega = R.derivative<1>(dt).transform(R.transpose()).skewRedux();
          // - Angular acceleration of the segment in the ICS
          math::Array<3> alpha = R.derivative<2>(dt).transform(R.transpose()).skewRedux();
          // - Linear acceleration of the CoM in the ICS
          auto a = com.derivative<2>(dt);

          // Forces and moments computed at the proximal end point
          // -----------------------------------------------------

          // - External contact (ground, etc.)
          math::Vector Fext(samples); Fext.values().setZero(); Fext.residuals().setZero();
          math::Vector Mext(samples); Mext.values().setZero(); Mext.residuals().setZero();
          auto externals = seg->findChildren<const TimeSequence*>({}, {{"type", TimeSequence::Wrench}});
          for (const auto& external : externals)
          {
            auto wrench = math::to_wrench(external);
            if (!wrench.isValid())
            {
              warning("The external wrench '%s' is not valid or does not have the same sample rate, start time or number of sample than the rest of the chain '%s'.", external->name().c_str(), chain->name().c_str());
              continue;
            }
            Fext += wrench.block<3>(0);
            Mext += wrench.block<3>(3) + (wrench.block<3>(6) - pp).cross(wrench.block<3>(0));
          }
          // - Add the forces and moments of distal joint (if any)
          // NOTE: The opposite sign (-=) is because of the use of the action forces and moments computed for the previous segment. In the current segment, they represent reaction forces and moments.
          if (pd.isValid())
          {
            Fext -= Fd;
            Mext -= Md + (pd - pp).cross(Fd);
          }
          // - Weight
          auto Fwei = m * g / 1000.0;
          auto Mwei = c.cross(m * g / 1000.0);
          // - Dynamics
          auto Fdyn = m * a / 1000.0;
          auto Mdyn = (I.transform(alpha) + omega.cross(I.transform(omega))) / 1000.0 + c.cross(m * a / 1000.0);
          // - Proximal joint (result)
          math::Vector Fp = Fdyn - Fwei - Fext;
          math::Vector Mp = Mdyn - Mwei - Mext;
          math::to_timesequence(Fp, jnt->name() + ".Force", rate, start, TimeSequence::Force, "N", jnt);
          math::to_timesequence(Mp, jnt->name() + ".Moment", rate, start, TimeSequence::Moment, "Nmm" , jnt);

          // Set the next (reaction) distal joint variables
          Fd = Fp;
          Md = Mp;
          pd = pp;
        }
      }
    }
    return true;
  };

  /**
   * Create a deep copy of the object and return it as another object.
   */
  InverseDynamicMatrix* InverseDynamicMatrix::clone(Node* parent) const
  {
    auto dest = new InverseDynamicMatrix;
    dest->copy(this);
    dest->addParent(parent);
    return dest;
  };

  /**
   * Do a deep copy of the the given @a source. The previous content is replaced.
   */
  void InverseDynamicMatrix::copy(const Node* source) _OPENMA_NOEXCEPT
  {
    auto src = node_cast<const InverseDynamicMatrix*>(source);
    if (src == nullptr)
      return;
    this->InverseDynamicProcessor::copy(src);
  };

 };
};<commit_msg>Use type alias to simplify the reading of the code.<commit_after>/*
 * Open Source Movement Analysis Library
 * Copyright (C) 2016, Moveck Solution Inc., all rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *     * Neither the name(s) of the copyright holders nor the names
 *       of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written
 *       permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "openma/body/inversedynamicsmatrix.h"
#include "openma/body/inversedynamicsprocessor_p.h"

#include "openma/body/anchor.h"
#include "openma/body/chain.h"
#include "openma/body/inertialparameters.h"
#include "openma/body/joint.h"
#include "openma/body/model.h"
#include "openma/body/segment.h"
#include "openma/body/utils.h"
#include "openma/base/trial.h"
#include "openma/instrument/forceplate.h"
#include "openma/math.h"

// -------------------------------------------------------------------------- //
//                                 PRIVATE API                                //
// -------------------------------------------------------------------------- //

#ifndef DOXYGEN_SHOULD_SKIP_THIS

namespace ma
{
namespace body
{
  class InverseDynamicMatrixPrivate : public InverseDynamicProcessorPrivate
  {
    OPENMA_DECLARE_PINT_ACCESSOR(InverseDynamicMatrix)

  public:
    InverseDynamicMatrixPrivate(InverseDynamicMatrix* pint);
    ~InverseDynamicMatrixPrivate();
  };

  InverseDynamicMatrixPrivate::InverseDynamicMatrixPrivate(InverseDynamicMatrix* pint)
  : InverseDynamicProcessorPrivate(pint,"InverseDynamicMatrix")
  {};

  InverseDynamicMatrixPrivate::~InverseDynamicMatrixPrivate() = default;
};
};

#endif

// -------------------------------------------------------------------------- //
//                                 PUBLIC API                                 //
// -------------------------------------------------------------------------- //

OPENMA_INSTANCE_STATIC_TYPEID(ma::body::InverseDynamicMatrix);

namespace ma
{
namespace body
{
  /**
   * @class InverseDynamicMatrix openma/body/matrixinversedynamics.h
   * @brief Algorithm to compute joint kinetics expressed in the global frame
   *
   * @TODO Explain in details the required element to use this algorithm (model configure, external wrench, etc.).
   *
   * @ingroup openma_body
   */

  /**
   * Constructor
   */
  InverseDynamicMatrix::InverseDynamicMatrix(Node* parent)
  : InverseDynamicProcessor(*new InverseDynamicMatrixPrivate(this), parent)
  {};

  /**
   * Destructor
   */
  InverseDynamicMatrix::~InverseDynamicMatrix() _OPENMA_NOEXCEPT = default;

  /**
   * Internally this method is a combination of two algorithms published in the litterature [1,2].
   * Both of these algorithms are known to be less sensitive to noise [3]. The reason to use this is only to reduce computation time.
   *  - No need to convert to quaternion
   *  - No need to create sparse 6x6 matrices
   *  - Angular velocity and angular acceleration computed directly from rotation matrices
   *  - All the results are express in the inertial (global) coordinate system
   *
   * @par References
   *  1. Dumas et al., 2004, A 3D generic inverse dynamic method using wrench notation and quaternion algebra, Computer methods in Biomechanics and Biomedical Engineering, 7 (3), pp. 159-166
   *  2. Doriot & Chèze, 2004, A Three-Dimensional Kinematic and Dynamic Study of the Lower Limb During the Stance Phase of Gait Using an Homogeneous Matrix Approach, IEEE Transactions on Biomedical Engineering, 51 (1), pp. 21-27
   *  3. Dumas et al., 2007, Influence of the 3D Inverse Dynamic Method on the Joint Forces and Moments During Gait, ￼Journal of￼Biomechanical￼Engineering, 129, pp. 786-790
   */
  bool InverseDynamicMatrix::run(Node* inout)
  {
#if !defined(_MSC_VER)
#warning WE NEED TO MANAGE UNITS FOR FORCES AND MOMENTS
#endif

    auto models = inout->findChildren<Model*>({},{},false);
    for (auto& model : models)
    {
      auto chains = model->chains()->findChildren<Chain*>({},{},false);
      for (auto& chain : chains)
      {
        auto joints = chain->findChildren<Joint*>({},{},false);
        if (joints.empty())
        {
          warning("No joint found in the chain '%s'. Inverse dynamics for this chain aborted.", chain->name().c_str());
          continue;
        }
        // Properties check
        std::vector<TimeSequence*> tss(joints.size());
        unsigned inc = 0;
        for (const auto& joint : joints)
          tss[inc++] = joint->distalSegment()->pose();
        double rate = 0.0, start = 0.0;
        unsigned samples = 0;
        if (!compare_timesequences_properties(tss, rate, start, samples))
        {
          error("At least one segment's pose does not have the same sample rate, start time or number of samples in the chain '%s'.", chain->name().c_str());
          continue;
        }
        assert(rate > 0.);
        double dt = 1. / rate;
        double gres = 0.;
        math::Vector Fd, Md, pd;
        auto g = math::Map<const math::Vector>(1, model->gravity(), &gres).replicate(samples);
        // Iteration computation of joint kinetics
        for (auto itJ = joints.rbegin() ; itJ != joints.rend() ; ++itJ)
        {
          auto jnt = *itJ;
          auto seg = jnt->distalSegment();
          auto bsip = seg->findChild<InertialParameters*>();
          if (bsip == nullptr)
          {
            error("The segment '%s' does not have body segment inertial parameters. Inverse dynamics for the chain '%s' aborted.", seg->name().c_str(), chain->name().c_str());
            break;
          }

          // Internal variables used
          // -----------------------

          // - Pose of the segment
          auto pose = math::to_pose(seg->pose());
          // - Rotation component of the pose in the Inertial Coordinate System (ICS)
          auto R = pose.block<9>(0);
          // - Tensor of inertia expressed in the ICS
          math::Array<9> I = transform_relative_inertia(bsip, seg, pose);
          // - Centre of mass expressed in the ICS
          math::Position com = transform_relative_com(bsip, seg, pose);
          // - Mass of the segment
          double m = bsip->mass();
          // - Proximal end point of the segment
          auto pp = math::to_position(jnt->proximalAnchor()->position());
          if (!pp.isValid())
          {
            error("Unexpected error in the computation of proximal anchor position for the joint '%s'. Inverse dynamics for the chain '%s' aborted.", jnt->name().c_str(), chain->name().c_str());
            break;
          }
          // - Lever arm between the proximal end point and the centre of mass
          math::Position c = com - pp;

          // Derivatives computation
          // -----------------------
          // TODO Would it be possible to reduce the computation time by compute the angular velocity for the lower triangle only (same for the angular acceleration)

          // - Angular velocity of the segment in the ICS
          math::Vector omega = R.derivative<1>(dt).transform(R.transpose()).skewRedux();
          // - Angular acceleration of the segment in the ICS
          math::Vector alpha = R.derivative<2>(dt).transform(R.transpose()).skewRedux();
          // - Linear acceleration of the CoM in the ICS
          auto a = com.derivative<2>(dt);

          // Forces and moments computed at the proximal end point
          // -----------------------------------------------------

          // - External contact (ground, etc.)
          math::Vector Fext(samples); Fext.values().setZero(); Fext.residuals().setZero();
          math::Vector Mext(samples); Mext.values().setZero(); Mext.residuals().setZero();
          auto externals = seg->findChildren<const TimeSequence*>({}, {{"type", TimeSequence::Wrench}});
          for (const auto& external : externals)
          {
            auto wrench = math::to_wrench(external);
            if (!wrench.isValid())
            {
              warning("The external wrench '%s' is not valid or does not have the same sample rate, start time or number of sample than the rest of the chain '%s'.", external->name().c_str(), chain->name().c_str());
              continue;
            }
            Fext += wrench.block<3>(0);
            Mext += wrench.block<3>(3) + (wrench.block<3>(6) - pp).cross(wrench.block<3>(0));
          }
          // - Add the forces and moments of distal joint (if any)
          // NOTE: The opposite sign (-=) is because of the use of the action forces and moments computed for the previous segment. In the current segment, they represent reaction forces and moments.
          if (pd.isValid())
          {
            Fext -= Fd;
            Mext -= Md + (pd - pp).cross(Fd);
          }
          // - Weight
          auto Fwei = m * g / 1000.0;
          auto Mwei = c.cross(m * g / 1000.0);
          // - Dynamics
          auto Fdyn = m * a / 1000.0;
          auto Mdyn = (I.transform(alpha) + omega.cross(I.transform(omega))) / 1000.0 + c.cross(m * a / 1000.0);
          // - Proximal joint (result)
          math::Vector Fp = Fdyn - Fwei - Fext;
          math::Vector Mp = Mdyn - Mwei - Mext;
          math::to_timesequence(Fp, jnt->name() + ".Force", rate, start, TimeSequence::Force, "N", jnt);
          math::to_timesequence(Mp, jnt->name() + ".Moment", rate, start, TimeSequence::Moment, "Nmm" , jnt);

          // Set the next (reaction) distal joint variables
          Fd = Fp;
          Md = Mp;
          pd = pp;
        }
      }
    }
    return true;
  };

  /**
   * Create a deep copy of the object and return it as another object.
   */
  InverseDynamicMatrix* InverseDynamicMatrix::clone(Node* parent) const
  {
    auto dest = new InverseDynamicMatrix;
    dest->copy(this);
    dest->addParent(parent);
    return dest;
  };

  /**
   * Do a deep copy of the the given @a source. The previous content is replaced.
   */
  void InverseDynamicMatrix::copy(const Node* source) _OPENMA_NOEXCEPT
  {
    auto src = node_cast<const InverseDynamicMatrix*>(source);
    if (src == nullptr)
      return;
    this->InverseDynamicProcessor::copy(src);
  };

 };
};<|endoftext|>


<commit_before>/*
Copyright (c) 2018 - present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <hip/hip_runtime.h>

#include "hip_internal.hpp"

hipError_t hipDeviceGet(hipDevice_t *device, int deviceId) {
  HIP_INIT_API(device, deviceId);

  if (device != nullptr) {
    *device = deviceId;
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipSuccess);
};

hipError_t hipFuncSetCacheConfig (const void* func, hipFuncCache_t cacheConfig) {

  HIP_INIT_API(cacheConfig);

  // No way to set cache config yet.

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceTotalMem (size_t *bytes, hipDevice_t device) {

  HIP_INIT_API(bytes, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (bytes == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();

  *bytes = info.globalMemSize_;

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceComputeCapability(int *major, int *minor, hipDevice_t device) {

  HIP_INIT_API(major, minor, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (major == nullptr || minor == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();
  *major = info.gfxipVersion_ / 100;
  *minor = info.gfxipVersion_ % 100;

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceGetCount(int* count) {
  HIP_INIT_API(count);

  HIP_RETURN(ihipDeviceGetCount(count));
}

hipError_t ihipDeviceGetCount(int* count) {
  if (count == nullptr) {
    return hipErrorInvalidValue;
  }

  // Get all available devices
  *count = g_devices.size();

  return hipSuccess;
}

hipError_t hipDeviceGetName(char *name, int len, hipDevice_t device) {

  HIP_INIT_API((void*)name, len, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (name == nullptr || len <= 0) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();
  const auto nameLen = ::strlen(info.boardName_);

  if (nameLen > (cl_uint)len) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  ::strncpy(name, info.boardName_, nameLen);

  HIP_RETURN(hipSuccess);
}

hipError_t hipGetDeviceProperties ( hipDeviceProp_t* props, hipDevice_t device ) {
  HIP_INIT_API(props, device);

  if (props == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  if (unsigned(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }
  auto* deviceHandle = g_devices[device]->devices()[0];

  hipDeviceProp_t deviceProps = {0};

  const auto& info = deviceHandle->info();
  ::strncpy(deviceProps.name, info.boardName_, 128);
  deviceProps.totalGlobalMem = info.globalMemSize_;
  deviceProps.sharedMemPerBlock = info.localMemSizePerCU_;
  deviceProps.regsPerBlock = info.availableSGPRs_;
  deviceProps.warpSize = info.wavefrontWidth_;
  deviceProps.maxThreadsPerBlock = info.maxWorkGroupSize_;
  deviceProps.maxThreadsDim[0] = info.maxWorkItemSizes_[0];
  deviceProps.maxThreadsDim[1] = info.maxWorkItemSizes_[1];
  deviceProps.maxThreadsDim[2] = info.maxWorkItemSizes_[2];
  deviceProps.maxGridSize[0] = INT32_MAX;
  deviceProps.maxGridSize[1] = INT32_MAX;
  deviceProps.maxGridSize[2] = INT32_MAX;
  deviceProps.clockRate = info.maxEngineClockFrequency_ * 1000;
  deviceProps.memoryClockRate = info.maxMemoryClockFrequency_ * 1000;
  deviceProps.memoryBusWidth = info.globalMemChannels_ * 32;
  deviceProps.totalConstMem = info.maxConstantBufferSize_;
  deviceProps.major = info.gfxipVersion_ / 100;
  deviceProps.minor = info.gfxipVersion_ % 100;
  deviceProps.multiProcessorCount = info.maxComputeUnits_;
  deviceProps.l2CacheSize = info.l2CacheSize_;
  deviceProps.maxThreadsPerMultiProcessor = info.maxThreadsPerCU_;
  deviceProps.computeMode = 0;
  deviceProps.clockInstructionRate = info.timeStampFrequency_;
  deviceProps.arch.hasGlobalInt32Atomics       = 1;
  deviceProps.arch.hasGlobalFloatAtomicExch    = 1;
  deviceProps.arch.hasSharedInt32Atomics       = 1;
  deviceProps.arch.hasSharedFloatAtomicExch    = 1;
  deviceProps.arch.hasFloatAtomicAdd           = 0;
  deviceProps.arch.hasGlobalInt64Atomics       = 1;
  deviceProps.arch.hasSharedInt64Atomics       = 1;
  deviceProps.arch.hasDoubles                  = 1;
  deviceProps.arch.hasWarpVote                 = 0;
  deviceProps.arch.hasWarpBallot               = 0;
  deviceProps.arch.hasWarpShuffle              = 0;
  deviceProps.arch.hasFunnelShift              = 0;
  deviceProps.arch.hasThreadFenceSystem        = 1;
  deviceProps.arch.hasSyncThreadsExt           = 0;
  deviceProps.arch.hasSurfaceFuncs             = 0;
  deviceProps.arch.has3dGrid                   = 1;
  deviceProps.arch.hasDynamicParallelism       = 0;
  deviceProps.concurrentKernels = 1;
  deviceProps.pciDomainID = info.deviceTopology_.pcie.function;
  deviceProps.pciBusID = info.deviceTopology_.pcie.bus;
  deviceProps.pciDeviceID = info.deviceTopology_.pcie.device;
  deviceProps.maxSharedMemoryPerMultiProcessor = info.localMemSizePerCU_;
  //deviceProps.isMultiGpuBoard = info.;
  deviceProps.canMapHostMemory = 1;
  deviceProps.gcnArch = info.gfxipVersion_;

  *props = deviceProps;
  HIP_RETURN(hipSuccess);
}

hipError_t hipHccGetAccelerator(int deviceId, hc::accelerator* acc) {
  HIP_INIT_API(deviceId, acc);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorUnknown);
}

hipError_t hipHccGetAcceleratorView(hipStream_t stream, hc::accelerator_view** av) {
  HIP_INIT_API(stream, av);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorUnknown);
}
<commit_msg>P4 to Git Change 1772349 by mshivama@mshivama_tf on 2019/04/20 07:35:24<commit_after>/*
Copyright (c) 2018 - present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <hip/hip_runtime.h>

#include "hip_internal.hpp"

hipError_t hipDeviceGet(hipDevice_t *device, int deviceId) {
  HIP_INIT_API(device, deviceId);

  if (device != nullptr) {
    *device = deviceId;
  } else {
    HIP_RETURN(hipErrorInvalidValue);
  }

  HIP_RETURN(hipSuccess);
};

hipError_t hipFuncSetCacheConfig (const void* func, hipFuncCache_t cacheConfig) {

  HIP_INIT_API(cacheConfig);

  // No way to set cache config yet.

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceTotalMem (size_t *bytes, hipDevice_t device) {

  HIP_INIT_API(bytes, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (bytes == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();

  *bytes = info.globalMemSize_;

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceComputeCapability(int *major, int *minor, hipDevice_t device) {

  HIP_INIT_API(major, minor, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (major == nullptr || minor == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();
  *major = info.gfxipVersion_ / 100;
  *minor = info.gfxipVersion_ % 100;

  HIP_RETURN(hipSuccess);
}

hipError_t hipDeviceGetCount(int* count) {
  HIP_INIT_API(count);

  HIP_RETURN(ihipDeviceGetCount(count));
}

hipError_t ihipDeviceGetCount(int* count) {
  if (count == nullptr) {
    return hipErrorInvalidValue;
  }

  // Get all available devices
  *count = g_devices.size();

  return hipSuccess;
}

hipError_t hipDeviceGetName(char *name, int len, hipDevice_t device) {

  HIP_INIT_API((void*)name, len, device);

  if (device < 0 || static_cast<size_t>(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }

  if (name == nullptr || len <= 0) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  auto* deviceHandle = g_devices[device]->devices()[0];
  const auto& info = deviceHandle->info();
  const auto nameLen = ::strlen(info.boardName_);

  // Make sure that the size of `dest` is big enough to hold `src` including
  // trailing zero byte
  if (nameLen > (cl_uint)(len - 1)) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  ::strncpy(name, info.boardName_, (nameLen + 1));

  HIP_RETURN(hipSuccess);
}

hipError_t hipGetDeviceProperties ( hipDeviceProp_t* props, hipDevice_t device ) {
  HIP_INIT_API(props, device);

  if (props == nullptr) {
    HIP_RETURN(hipErrorInvalidValue);
  }

  if (unsigned(device) >= g_devices.size()) {
    HIP_RETURN(hipErrorInvalidDevice);
  }
  auto* deviceHandle = g_devices[device]->devices()[0];

  hipDeviceProp_t deviceProps = {0};

  const auto& info = deviceHandle->info();
  ::strncpy(deviceProps.name, info.boardName_, 128);
  deviceProps.totalGlobalMem = info.globalMemSize_;
  deviceProps.sharedMemPerBlock = info.localMemSizePerCU_;
  deviceProps.regsPerBlock = info.availableSGPRs_;
  deviceProps.warpSize = info.wavefrontWidth_;
  deviceProps.maxThreadsPerBlock = info.maxWorkGroupSize_;
  deviceProps.maxThreadsDim[0] = info.maxWorkItemSizes_[0];
  deviceProps.maxThreadsDim[1] = info.maxWorkItemSizes_[1];
  deviceProps.maxThreadsDim[2] = info.maxWorkItemSizes_[2];
  deviceProps.maxGridSize[0] = INT32_MAX;
  deviceProps.maxGridSize[1] = INT32_MAX;
  deviceProps.maxGridSize[2] = INT32_MAX;
  deviceProps.clockRate = info.maxEngineClockFrequency_ * 1000;
  deviceProps.memoryClockRate = info.maxMemoryClockFrequency_ * 1000;
  deviceProps.memoryBusWidth = info.globalMemChannels_ * 32;
  deviceProps.totalConstMem = info.maxConstantBufferSize_;
  deviceProps.major = info.gfxipVersion_ / 100;
  deviceProps.minor = info.gfxipVersion_ % 100;
  deviceProps.multiProcessorCount = info.maxComputeUnits_;
  deviceProps.l2CacheSize = info.l2CacheSize_;
  deviceProps.maxThreadsPerMultiProcessor = info.maxThreadsPerCU_;
  deviceProps.computeMode = 0;
  deviceProps.clockInstructionRate = info.timeStampFrequency_;
  deviceProps.arch.hasGlobalInt32Atomics       = 1;
  deviceProps.arch.hasGlobalFloatAtomicExch    = 1;
  deviceProps.arch.hasSharedInt32Atomics       = 1;
  deviceProps.arch.hasSharedFloatAtomicExch    = 1;
  deviceProps.arch.hasFloatAtomicAdd           = 0;
  deviceProps.arch.hasGlobalInt64Atomics       = 1;
  deviceProps.arch.hasSharedInt64Atomics       = 1;
  deviceProps.arch.hasDoubles                  = 1;
  deviceProps.arch.hasWarpVote                 = 0;
  deviceProps.arch.hasWarpBallot               = 0;
  deviceProps.arch.hasWarpShuffle              = 0;
  deviceProps.arch.hasFunnelShift              = 0;
  deviceProps.arch.hasThreadFenceSystem        = 1;
  deviceProps.arch.hasSyncThreadsExt           = 0;
  deviceProps.arch.hasSurfaceFuncs             = 0;
  deviceProps.arch.has3dGrid                   = 1;
  deviceProps.arch.hasDynamicParallelism       = 0;
  deviceProps.concurrentKernels = 1;
  deviceProps.pciDomainID = info.deviceTopology_.pcie.function;
  deviceProps.pciBusID = info.deviceTopology_.pcie.bus;
  deviceProps.pciDeviceID = info.deviceTopology_.pcie.device;
  deviceProps.maxSharedMemoryPerMultiProcessor = info.localMemSizePerCU_;
  //deviceProps.isMultiGpuBoard = info.;
  deviceProps.canMapHostMemory = 1;
  deviceProps.gcnArch = info.gfxipVersion_;

  *props = deviceProps;
  HIP_RETURN(hipSuccess);
}

hipError_t hipHccGetAccelerator(int deviceId, hc::accelerator* acc) {
  HIP_INIT_API(deviceId, acc);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorUnknown);
}

hipError_t hipHccGetAcceleratorView(hipStream_t stream, hc::accelerator_view** av) {
  HIP_INIT_API(stream, av);

  assert(0 && "Unimplemented");

  HIP_RETURN(hipErrorUnknown);
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2008-2010 NVIDIA Corporation
 *
 *  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.
 */

#pragma once

#include <thrust/detail/type_traits.h>
#include <thrust/iterator/iterator_categories.h>
#include <thrust/iterator/iterator_traits.h>
#include <thrust/iterator/detail/backend_iterator_spaces.h>
#include <thrust/iterator/detail/backend_iterator_categories.h>
#include <thrust/iterator/detail/is_iterator_category.h>

namespace thrust
{

namespace experimental
{

namespace detail
{

// adapted from http://www.boost.org/doc/libs/1_37_0/libs/iterator/doc/iterator_facade.html#iterator-category
//
// iterator-category(T,V,R) :=
//   if(T is convertible to input_host_iterator_tag
//      || T is convertible to output_host_iterator_tag
//      || T is convertible to input_device_iterator_tag
//      || T is convertible to output_device_iterator_tag
//   )
//     return T
//
//   else if (T is not convertible to incrementable_traversal_tag)
//     the program is ill-formed
//
//   else return a type X satisfying the following two constraints:
//
//     1. X is convertible to X1, and not to any more-derived
//        type, where X1 is defined by:
//
//        if (R is a reference type
//            && T is convertible to forward_traversal_tag)
//        {
//          if (T is convertible to random_access_traversal_tag)
//            X1 = random_access_host_iterator_tag
//          else if (T is convertible to bidirectional_traversal_tag)
//            X1 = bidirectional_host_iterator_tag
//          else
//            X1 = forward_host_iterator_tag
//        }
//        else
//        {
//          if (T is convertible to single_pass_traversal_tag
//              && R is convertible to V)
//            X1 = input_host_iterator_tag
//          else
//            X1 = T
//        }
//
//     2. category-to-traversal(X) is convertible to the most
//        derived traversal tag type to which X is also convertible,
//        and not to any more-derived traversal tag type.

template<typename Space, typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category;

//
// Convert an iterator_facade's traversal category, Value parameter,
// and ::reference type to an appropriate old-style category.
//
// If writability has been disabled per the above metafunction, the
// result will not be convertible to output_iterator_tag.
//
// Otherwise, if Traversal == single_pass_traversal_tag, the following
// conditions will result in a tag that is convertible both to
// input_iterator_tag and output_iterator_tag:
//
//    1. Reference is a reference to non-const
//    2. Reference is not a reference and is convertible to Value
//

// this is the function for host space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_host :
    thrust::detail::eval_if<
      thrust::detail::and_<
        thrust::detail::is_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,
      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::random_access_host_iterator_tag>,
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::bidirectional_host_iterator_tag>,
          thrust::detail::identity_<thrust::forward_host_iterator_tag>
        >
      >,
      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::input_host_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_host

// this is the function for generic device space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_device :
    thrust::detail::eval_if<
      thrust::detail::and_<
        thrust::detail::is_device_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,
      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::random_access_device_iterator_tag>,
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::bidirectional_device_iterator_tag>,
          thrust::detail::identity_<thrust::forward_device_iterator_tag>
        >
      >,
      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::input_device_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_device

// this is the function for cuda device space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_cuda_device :
    thrust::detail::eval_if<
      thrust::detail::and_<
        thrust::detail::is_device_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,
      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::detail::random_access_cuda_device_iterator_tag>,
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::detail::bidirectional_cuda_device_iterator_tag>,
          thrust::detail::identity_<thrust::detail::forward_cuda_device_iterator_tag>
        >
      >,
      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::detail::input_cuda_device_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_device

// this is the function for omp device space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_omp_device :
    thrust::detail::eval_if<
      thrust::detail::and_<
        thrust::detail::is_device_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,
      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::detail::random_access_omp_device_iterator_tag>,
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::detail::bidirectional_omp_device_iterator_tag>,
          thrust::detail::identity_<thrust::detail::forward_omp_device_iterator_tag>
        >
      >,
      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::detail::input_omp_device_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_device

// this is the function for any space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_any :
    thrust::detail::eval_if<

      thrust::detail::and_<
        thrust::detail::is_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,

      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::random_access_universal_iterator_tag>,

        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::bidirectional_universal_iterator_tag,
          thrust::forward_universal_iterator_tag
        >
      >,

      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::input_universal_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_any

template<typename Space, typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category
      // check for any space
    : thrust::detail::eval_if<
        thrust::detail::is_convertible<Space, thrust::any_space_tag>::value,
        iterator_facade_default_category_any<Traversal, ValueParam, Reference>,

        // check for host space
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Space, thrust::host_space_tag>::value,
          iterator_facade_default_category_host<Traversal, ValueParam, Reference>,

          // check for cuda device space
          thrust::detail::eval_if<
            thrust::detail::is_convertible<Space, thrust::detail::cuda_device_space_tag>::value,
            iterator_facade_default_category_cuda_device<Traversal, ValueParam, Reference>,

            // check for omp device space
            thrust::detail::eval_if<
              thrust::detail::is_convertible<Space, thrust::detail::omp_device_space_tag>::value,
              iterator_facade_default_category_omp_device<Traversal, ValueParam, Reference>,

              // check for device space
              thrust::detail::eval_if<
                thrust::detail::is_convertible<Space, thrust::device_space_tag>::value,
                iterator_facade_default_category_device<Traversal, ValueParam, Reference>,

                // on failure, return Traversal
                thrust::detail::identity_<Traversal>
              >
            >
          >
        >
      >
{};

template<typename Category, typename Space, typename Traversal>
  struct iterator_category_with_space_and_traversal
    : Category, Space, Traversal
{
}; // end iterator_category_with_space_and_traversal

template<typename Space, typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_category_impl
{
  typedef typename iterator_facade_default_category<
    Space,Traversal,ValueParam,Reference
  >::type category;

  // we must be able to deduce both Traversal & Space from category
  // otherwise, munge them all together
  typedef typename thrust::detail::eval_if<
    thrust::detail::and_<
      thrust::detail::is_same<
        Traversal,
        typename thrust::detail::iterator_category_to_traversal<category>::type
      >,
      thrust::detail::is_same<
        Space,
        typename thrust::detail::iterator_category_to_space<category>::type
      >
    >::value,
    thrust::detail::identity_<category>,
    thrust::detail::identity_<iterator_category_with_space_and_traversal<category,Space,Traversal> >
  >::type type;
}; // end iterator_facade_category_impl

template<typename CategoryOrSpace,
         typename CategoryOrTraversal,
         typename ValueParam,
         typename Reference>
  struct iterator_facade_category
{
  typedef typename
  thrust::detail::eval_if<
    thrust::detail::is_iterator_category<CategoryOrTraversal>::value,
    thrust::detail::identity_<CategoryOrTraversal>, // categories are fine as-is
    iterator_facade_category_impl<CategoryOrSpace, CategoryOrTraversal, ValueParam, Reference>
  >::type type;
}; // end iterator_facade_category

template<typename ValueParam,
         typename CategoryOrSpace,
         typename CategoryOrTraversal,
         typename Reference,
         typename Difference>
  struct iterator_facade_types
{
  typedef typename iterator_facade_category<
    CategoryOrSpace, CategoryOrTraversal, ValueParam, Reference
  >::type iterator_category;

  typedef typename thrust::detail::remove_const<ValueParam>::type value_type;
}; // end iterator_facade_types

} // end detail

} // end experimental

} // end thrust

<commit_msg>Fix the implementation of iterator_facade_default_category_any, which only showed up in Thrust-NUMA<commit_after>/*
 *  Copyright 2008-2010 NVIDIA Corporation
 *
 *  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.
 */

#pragma once

#include <thrust/detail/type_traits.h>
#include <thrust/iterator/iterator_categories.h>
#include <thrust/iterator/iterator_traits.h>
#include <thrust/iterator/detail/backend_iterator_spaces.h>
#include <thrust/iterator/detail/backend_iterator_categories.h>
#include <thrust/iterator/detail/is_iterator_category.h>

namespace thrust
{

namespace experimental
{

namespace detail
{

// adapted from http://www.boost.org/doc/libs/1_37_0/libs/iterator/doc/iterator_facade.html#iterator-category
//
// iterator-category(T,V,R) :=
//   if(T is convertible to input_host_iterator_tag
//      || T is convertible to output_host_iterator_tag
//      || T is convertible to input_device_iterator_tag
//      || T is convertible to output_device_iterator_tag
//   )
//     return T
//
//   else if (T is not convertible to incrementable_traversal_tag)
//     the program is ill-formed
//
//   else return a type X satisfying the following two constraints:
//
//     1. X is convertible to X1, and not to any more-derived
//        type, where X1 is defined by:
//
//        if (R is a reference type
//            && T is convertible to forward_traversal_tag)
//        {
//          if (T is convertible to random_access_traversal_tag)
//            X1 = random_access_host_iterator_tag
//          else if (T is convertible to bidirectional_traversal_tag)
//            X1 = bidirectional_host_iterator_tag
//          else
//            X1 = forward_host_iterator_tag
//        }
//        else
//        {
//          if (T is convertible to single_pass_traversal_tag
//              && R is convertible to V)
//            X1 = input_host_iterator_tag
//          else
//            X1 = T
//        }
//
//     2. category-to-traversal(X) is convertible to the most
//        derived traversal tag type to which X is also convertible,
//        and not to any more-derived traversal tag type.

template<typename Space, typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category;

//
// Convert an iterator_facade's traversal category, Value parameter,
// and ::reference type to an appropriate old-style category.
//
// If writability has been disabled per the above metafunction, the
// result will not be convertible to output_iterator_tag.
//
// Otherwise, if Traversal == single_pass_traversal_tag, the following
// conditions will result in a tag that is convertible both to
// input_iterator_tag and output_iterator_tag:
//
//    1. Reference is a reference to non-const
//    2. Reference is not a reference and is convertible to Value
//

// this is the function for host space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_host :
    thrust::detail::eval_if<
      thrust::detail::and_<
        thrust::detail::is_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,
      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::random_access_host_iterator_tag>,
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::bidirectional_host_iterator_tag>,
          thrust::detail::identity_<thrust::forward_host_iterator_tag>
        >
      >,
      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::input_host_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_host

// this is the function for generic device space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_device :
    thrust::detail::eval_if<
      thrust::detail::and_<
        thrust::detail::is_device_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,
      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::random_access_device_iterator_tag>,
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::bidirectional_device_iterator_tag>,
          thrust::detail::identity_<thrust::forward_device_iterator_tag>
        >
      >,
      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::input_device_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_device

// this is the function for cuda device space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_cuda_device :
    thrust::detail::eval_if<
      thrust::detail::and_<
        thrust::detail::is_device_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,
      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::detail::random_access_cuda_device_iterator_tag>,
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::detail::bidirectional_cuda_device_iterator_tag>,
          thrust::detail::identity_<thrust::detail::forward_cuda_device_iterator_tag>
        >
      >,
      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::detail::input_cuda_device_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_device

// this is the function for omp device space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_omp_device :
    thrust::detail::eval_if<
      thrust::detail::and_<
        thrust::detail::is_device_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,
      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::detail::random_access_omp_device_iterator_tag>,
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::detail::bidirectional_omp_device_iterator_tag>,
          thrust::detail::identity_<thrust::detail::forward_omp_device_iterator_tag>
        >
      >,
      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::detail::input_omp_device_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_device

// this is the function for any space iterators
template<typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category_any :
    thrust::detail::eval_if<

      thrust::detail::and_<
        thrust::detail::is_reference<Reference>,
        thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>
      >::value,

      thrust::detail::eval_if<
        thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value,
        thrust::detail::identity_<thrust::random_access_universal_iterator_tag>,

        thrust::detail::eval_if<
          thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value,
          thrust::detail::identity_<thrust::bidirectional_universal_iterator_tag>,
          thrust::detail::identity_<thrust::forward_universal_iterator_tag>
        >
      >,

      thrust::detail::eval_if<
        thrust::detail::and_<
          thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>,
          thrust::detail::is_convertible<Reference, ValueParam>
        >::value,
        thrust::detail::identity_<thrust::input_universal_iterator_tag>,
        thrust::detail::identity_<Traversal>
      >
    >
{
}; // end iterator_facade_default_category_any

template<typename Space, typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_default_category
      // check for any space
    : thrust::detail::eval_if<
        thrust::detail::is_convertible<Space, thrust::any_space_tag>::value,
        iterator_facade_default_category_any<Traversal, ValueParam, Reference>,

        // check for host space
        thrust::detail::eval_if<
          thrust::detail::is_convertible<Space, thrust::host_space_tag>::value,
          iterator_facade_default_category_host<Traversal, ValueParam, Reference>,

          // check for cuda device space
          thrust::detail::eval_if<
            thrust::detail::is_convertible<Space, thrust::detail::cuda_device_space_tag>::value,
            iterator_facade_default_category_cuda_device<Traversal, ValueParam, Reference>,

            // check for omp device space
            thrust::detail::eval_if<
              thrust::detail::is_convertible<Space, thrust::detail::omp_device_space_tag>::value,
              iterator_facade_default_category_omp_device<Traversal, ValueParam, Reference>,

              // check for device space
              thrust::detail::eval_if<
                thrust::detail::is_convertible<Space, thrust::device_space_tag>::value,
                iterator_facade_default_category_device<Traversal, ValueParam, Reference>,

                // on failure, return Traversal
                thrust::detail::identity_<Traversal>
              >
            >
          >
        >
      >
{};

template<typename Category, typename Space, typename Traversal>
  struct iterator_category_with_space_and_traversal
    : Category, Space, Traversal
{
}; // end iterator_category_with_space_and_traversal

template<typename Space, typename Traversal, typename ValueParam, typename Reference>
  struct iterator_facade_category_impl
{
  typedef typename iterator_facade_default_category<
    Space,Traversal,ValueParam,Reference
  >::type category;

  // we must be able to deduce both Traversal & Space from category
  // otherwise, munge them all together
  typedef typename thrust::detail::eval_if<
    thrust::detail::and_<
      thrust::detail::is_same<
        Traversal,
        typename thrust::detail::iterator_category_to_traversal<category>::type
      >,
      thrust::detail::is_same<
        Space,
        typename thrust::detail::iterator_category_to_space<category>::type
      >
    >::value,
    thrust::detail::identity_<category>,
    thrust::detail::identity_<iterator_category_with_space_and_traversal<category,Space,Traversal> >
  >::type type;
}; // end iterator_facade_category_impl

template<typename CategoryOrSpace,
         typename CategoryOrTraversal,
         typename ValueParam,
         typename Reference>
  struct iterator_facade_category
{
  typedef typename
  thrust::detail::eval_if<
    thrust::detail::is_iterator_category<CategoryOrTraversal>::value,
    thrust::detail::identity_<CategoryOrTraversal>, // categories are fine as-is
    iterator_facade_category_impl<CategoryOrSpace, CategoryOrTraversal, ValueParam, Reference>
  >::type type;
}; // end iterator_facade_category

template<typename ValueParam,
         typename CategoryOrSpace,
         typename CategoryOrTraversal,
         typename Reference,
         typename Difference>
  struct iterator_facade_types
{
  typedef typename iterator_facade_category<
    CategoryOrSpace, CategoryOrTraversal, ValueParam, Reference
  >::type iterator_category;

  typedef typename thrust::detail::remove_const<ValueParam>::type value_type;
}; // end iterator_facade_types

} // end detail

} // end experimental

} // end thrust

<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2018 The Apollo 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 <fstream>
#include <string>
#include <vector>

#include "gflags/gflags.h"
#include "ros/include/ros/ros.h"
#include "ros/include/rosbag/bag.h"
#include "ros/include/rosbag/view.h"

#include "modules/common/adapters/adapter_manager.h"
#include "modules/common/log.h"
#include "modules/common/util/file.h"
#include "modules/common/util/string_util.h"

DEFINE_string(adapter_config_filename,
              "/apollo/modules/data/conf/event_collector_adapter.conf",
              "Path for adapter configuration.");

DEFINE_string(events_filename, "events.txt", "File to save event list.");

DEFINE_string(events_related_bags_filename, "events_related_bags.txt",
              "File to save events related bags list.");

DEFINE_double(event_time_backtrack_seconds, 20,
              "Backtrack from the event time to consider bags as related.");

namespace apollo {
namespace data {
namespace {
using apollo::common::adapter::AdapterManager;
using apollo::canbus::Chassis;

void OnSigInt(int32_t signal_num) {
  // only response for ctrl + c
  if (signal_num != SIGINT) {
    return;
  }
  AINFO << "EventCollector got signal: " << signal_num;

  // Only stop once.
  static bool is_stopping = false;
  if (!is_stopping) {
    is_stopping = true;
    ros::shutdown();
  }
}

class EventCollector {
 public:
  void Init(int32_t argc, char **argv) {
    signal(SIGINT, OnSigInt);

    ros::init(argc, argv, "EventCollector");
    AdapterManager::Init(FLAGS_adapter_config_filename);
  }

  void Start() {
    AdapterManager::AddDriveEventCallback(&EventCollector::OnDriveEvent, this);
    AdapterManager::AddChassisCallback(&EventCollector::OnChassis, this);
    AdapterManager::AddMonitorCallback(&EventCollector::OnMonitorMessage, this);
    AINFO << "Start spining...";
    ros::spin();
  }

  void Stop() {
    // Save events_related_bags.
    std::ofstream fout(FLAGS_events_related_bags_filename);
    if (!fout) {
      AERROR << "Failed to write " << FLAGS_events_related_bags_filename;
      return;
    }
    AINFO << "Saving info to " << FLAGS_events_related_bags_filename << "...";
    fout << std::fixed << std::setprecision(1);

    sort(events_.begin(), events_.end());
    for (const std::string& bag_filename :
         apollo::common::util::ListSubPaths("./", DT_REG)) {
      if (!apollo::common::util::EndWith(bag_filename, ".bag")) {
        continue;
      }

      rosbag::Bag bag(bag_filename);
      rosbag::View view(bag);
      const double begin_time = view.getBeginTime().toSec();
      const double end_time =
          view.getEndTime().toSec() + FLAGS_event_time_backtrack_seconds;

      bool started_line = false;
      const std::tuple<double, std::string> key(begin_time, "");
      for (auto iter = std::lower_bound(events_.begin(), events_.end(), key);
           iter != events_.end() && std::get<0>(*iter) < end_time; ++iter) {
        // event_time = std::get<0>(*iter)
        // event_message = std::get<1>(*iter)
        if (!started_line) {
          started_line = true;
          fout << bag_filename << "\n";
        }
        fout << "  Offset = " << std::get<0>(*iter) - begin_time << ", "
             << std::get<1>(*iter) << "\n";
      }
    }
  }

 private:
  // Event time and message.
  std::vector<std::tuple<double, std::string>> events_;
  Chassis::DrivingMode current_driving_mode_;

  void OnDriveEvent(const apollo::common::DriveEvent& event) {
    // The header time is the real event time.
    SaveEvent(event.header().timestamp_sec(), "DriveEvent", event.event());
  }

  void OnChassis(const Chassis& chassis) {
    // Save event when driving_mode changes from COMPLETE_AUTO_DRIVE to
    // EMERGENCY_MODE which is taken as a disengagement.
    if (current_driving_mode_ == Chassis::COMPLETE_AUTO_DRIVE &&
        chassis.driving_mode() == Chassis::EMERGENCY_MODE) {
      SaveEvent(chassis.header().timestamp_sec(), "Disengagement");
    }
    current_driving_mode_ = chassis.driving_mode();
  }

  void OnMonitorMessage(
      const apollo::common::monitor::MonitorMessage& monitor_msg) {
    using apollo::common::monitor::MonitorMessageItem;
    // Save all ERROR and FATAL monitor logs.
    const double time_sec = monitor_msg.header().timestamp_sec();
    for (const auto& item : monitor_msg.item()) {
      if (item.log_level() == MonitorMessageItem::ERROR ||
          item.log_level() == MonitorMessageItem::FATAL) {
        SaveEvent(time_sec, "MonitorErrorLog", item.msg());
      }
    }
  }

  void SaveEvent(const double timestamp_sec, const std::string type,
                 const std::string description = "") {
    const auto msg = apollo::common::util::StrCat(
        timestamp_sec, " [", type, "] ", description);

    AINFO << "SaveEvent: " << msg;
    events_.emplace_back(timestamp_sec, msg);

    // Append new event and flush.
    std::ofstream fout(FLAGS_events_filename, std::ofstream::app);
    if (fout) {
      fout << msg << std::endl;
    } else {
      AERROR << "Failed to write to " << FLAGS_events_filename;
    }
  }
};

}  // namespace
}  // namespace data
}  // namespace apollo

int main(int32_t argc, char **argv) {
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);

  apollo::data::EventCollector event_collector;
  event_collector.Init(argc, argv);
  event_collector.Start();
  event_collector.Stop();

  return 0;
}
<commit_msg>Data: Rename to last_driving_mode_ to make it clear.<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo 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 <fstream>
#include <string>
#include <vector>

#include "gflags/gflags.h"
#include "ros/include/ros/ros.h"
#include "ros/include/rosbag/bag.h"
#include "ros/include/rosbag/view.h"

#include "modules/common/adapters/adapter_manager.h"
#include "modules/common/log.h"
#include "modules/common/util/file.h"
#include "modules/common/util/string_util.h"

DEFINE_string(adapter_config_filename,
              "/apollo/modules/data/conf/event_collector_adapter.conf",
              "Path for adapter configuration.");

DEFINE_string(events_filename, "events.txt", "File to save event list.");

DEFINE_string(events_related_bags_filename, "events_related_bags.txt",
              "File to save events related bags list.");

DEFINE_double(event_time_backtrack_seconds, 20,
              "Backtrack from the event time to consider bags as related.");

namespace apollo {
namespace data {
namespace {
using apollo::common::adapter::AdapterManager;
using apollo::canbus::Chassis;

void OnSigInt(int32_t signal_num) {
  // only response for ctrl + c
  if (signal_num != SIGINT) {
    return;
  }
  AINFO << "EventCollector got signal: " << signal_num;

  // Only stop once.
  static bool is_stopping = false;
  if (!is_stopping) {
    is_stopping = true;
    ros::shutdown();
  }
}

class EventCollector {
 public:
  void Init(int32_t argc, char **argv) {
    signal(SIGINT, OnSigInt);

    ros::init(argc, argv, "EventCollector");
    AdapterManager::Init(FLAGS_adapter_config_filename);
  }

  void Start() {
    AdapterManager::AddDriveEventCallback(&EventCollector::OnDriveEvent, this);
    AdapterManager::AddChassisCallback(&EventCollector::OnChassis, this);
    AdapterManager::AddMonitorCallback(&EventCollector::OnMonitorMessage, this);
    AINFO << "Start spining...";
    ros::spin();
  }

  void Stop() {
    // Save events_related_bags.
    std::ofstream fout(FLAGS_events_related_bags_filename);
    if (!fout) {
      AERROR << "Failed to write " << FLAGS_events_related_bags_filename;
      return;
    }
    AINFO << "Saving info to " << FLAGS_events_related_bags_filename << "...";
    fout << std::fixed << std::setprecision(1);

    sort(events_.begin(), events_.end());
    for (const std::string& bag_filename :
         apollo::common::util::ListSubPaths("./", DT_REG)) {
      if (!apollo::common::util::EndWith(bag_filename, ".bag")) {
        continue;
      }

      rosbag::Bag bag(bag_filename);
      rosbag::View view(bag);
      const double begin_time = view.getBeginTime().toSec();
      const double end_time =
          view.getEndTime().toSec() + FLAGS_event_time_backtrack_seconds;

      bool started_line = false;
      const std::tuple<double, std::string> key(begin_time, "");
      for (auto iter = std::lower_bound(events_.begin(), events_.end(), key);
           iter != events_.end() && std::get<0>(*iter) < end_time; ++iter) {
        // event_time = std::get<0>(*iter)
        // event_message = std::get<1>(*iter)
        if (!started_line) {
          started_line = true;
          fout << bag_filename << "\n";
        }
        fout << "  Offset = " << std::get<0>(*iter) - begin_time << ", "
             << std::get<1>(*iter) << "\n";
      }
    }
  }

 private:
  // Event time and message.
  std::vector<std::tuple<double, std::string>> events_;
  Chassis::DrivingMode last_driving_mode_;

  void OnDriveEvent(const apollo::common::DriveEvent& event) {
    // The header time is the real event time.
    SaveEvent(event.header().timestamp_sec(), "DriveEvent", event.event());
  }

  void OnChassis(const Chassis& chassis) {
    // Save event when driving_mode changes from COMPLETE_AUTO_DRIVE to
    // EMERGENCY_MODE which is taken as a disengagement.
    if (last_driving_mode_ == Chassis::COMPLETE_AUTO_DRIVE &&
        chassis.driving_mode() == Chassis::EMERGENCY_MODE) {
      SaveEvent(chassis.header().timestamp_sec(), "Disengagement");
    }
    last_driving_mode_ = chassis.driving_mode();
  }

  void OnMonitorMessage(
      const apollo::common::monitor::MonitorMessage& monitor_msg) {
    using apollo::common::monitor::MonitorMessageItem;
    // Save all ERROR and FATAL monitor logs.
    const double time_sec = monitor_msg.header().timestamp_sec();
    for (const auto& item : monitor_msg.item()) {
      if (item.log_level() == MonitorMessageItem::ERROR ||
          item.log_level() == MonitorMessageItem::FATAL) {
        SaveEvent(time_sec, "MonitorErrorLog", item.msg());
      }
    }
  }

  void SaveEvent(const double timestamp_sec, const std::string type,
                 const std::string description = "") {
    const auto msg = apollo::common::util::StrCat(
        timestamp_sec, " [", type, "] ", description);

    AINFO << "SaveEvent: " << msg;
    events_.emplace_back(timestamp_sec, msg);

    // Append new event and flush.
    std::ofstream fout(FLAGS_events_filename, std::ofstream::app);
    if (fout) {
      fout << msg << std::endl;
    } else {
      AERROR << "Failed to write to " << FLAGS_events_filename;
    }
  }
};

}  // namespace
}  // namespace data
}  // namespace apollo

int main(int32_t argc, char **argv) {
  google::InitGoogleLogging(argv[0]);
  google::ParseCommandLineFlags(&argc, &argv, true);

  apollo::data::EventCollector event_collector;
  event_collector.Init(argc, argv);
  event_collector.Start();
  event_collector.Stop();

  return 0;
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <hip/hip_runtime.h>
#include "hip_internal.hpp"
#include "hip_event.hpp"
#include "thread/monitor.hpp"

static amd::Monitor streamSetLock("Guards global stream set");
static std::unordered_set<amd::HostQueue*> streamSet;

namespace hip {

void syncStreams() {
  amd::ScopedLock lock(streamSetLock);

  for (const auto& it : streamSet) {
    it->finish();
  }
}

};

static hipError_t ihipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
  amd::Device* device = hip::getCurrentContext()->devices()[0];

  amd::HostQueue* queue = new amd::HostQueue(*hip::getCurrentContext(), *device, 0,
                                             amd::CommandQueue::RealTimeDisabled,
                                             amd::CommandQueue::Priority::Normal);

  if (queue == nullptr || !queue->create()) {
    return hipErrorOutOfMemory;
  }

  if (!(flags & hipStreamNonBlocking)) {
    hip::syncStreams();

    {
      amd::ScopedLock lock(streamSetLock);
      streamSet.insert(queue);
    }
  }

  *stream = reinterpret_cast<hipStream_t>(as_cl(queue));

  return hipSuccess;
}

hipError_t hipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
  HIP_INIT_API(stream, flags);

  return ihipStreamCreateWithFlags(stream, flags);
}

hipError_t hipStreamCreate(hipStream_t *stream) {
  HIP_INIT_API(stream);

  return ihipStreamCreateWithFlags(stream, hipStreamDefault);
}

hipError_t hipStreamGetFlags(hipStream_t stream, unsigned int *flags) {
  HIP_INIT_API(stream, flags);

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  auto it = streamSet.find(hostQueue);

  if(flags != nullptr) {
    *flags = (it == streamSet.end()) ? hipStreamNonBlocking : hipStreamDefault;
  } else {
    return hipErrorInvalidValue;
  }

  return hipSuccess;
}

hipError_t hipStreamSynchronize(hipStream_t stream) {
  HIP_INIT_API(stream);

  amd::HostQueue* hostQueue;

  if (stream == nullptr) {
    hip::syncStreams();

    hostQueue = hip::getNullStream();
  } else {
    hip::getNullStream()->finish();

    hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  }

  if (hostQueue == nullptr) {
    return hipErrorUnknown;
  }

  hostQueue->finish();

  return hipSuccess;
}

hipError_t hipStreamDestroy(hipStream_t stream) {
  HIP_INIT_API(stream);

  if (stream == nullptr) {
    return hipErrorInvalidResourceHandle;
  }

  amd::ScopedLock lock(streamSetLock);

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  hostQueue->release();
  streamSet.erase(hostQueue);

  return hipSuccess;
}

hipError_t hipStreamWaitEvent(hipStream_t stream, hipEvent_t event, unsigned int flags) {
  HIP_INIT_API(stream, event, flags);

  if (stream == nullptr || event == nullptr) {
    return hipErrorInvalidResourceHandle;
  }

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  hip::Event* e = reinterpret_cast<hip::Event*>(event);
  cl_event clEvent = as_cl(e->event_);

  amd::Command::EventWaitList eventWaitList;
  cl_int err = amd::clSetEventWaitList(eventWaitList, hostQueue->context(), 1,
                                       &clEvent);
  if (err != CL_SUCCESS) {
    return hipErrorUnknown;
  }

  amd::Command* command = new amd::Marker(*hostQueue, true, eventWaitList);
  if (command == NULL) {
    return hipErrorOutOfMemory;
  }
  command->enqueue();
  command->release();

  return hipSuccess;
}

hipError_t hipStreamQuery(hipStream_t stream) {
  HIP_INIT_API(stream);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipStreamAddCallback(hipStream_t stream, hipStreamCallback_t callback, void* userData,
                                unsigned int flags) {
  HIP_INIT_API(stream, callback, userData, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

<commit_msg>P4 to Git Change 1562507 by skudchad@skudchad_test2_win_opencl on 2018/05/31 18:10:39<commit_after>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <hip/hip_runtime.h>
#include "hip_internal.hpp"
#include "hip_event.hpp"
#include "thread/monitor.hpp"

static amd::Monitor streamSetLock("Guards global stream set");
static std::unordered_set<amd::HostQueue*> streamSet;

namespace hip {

void syncStreams() {
  amd::ScopedLock lock(streamSetLock);

  for (const auto& it : streamSet) {
    it->finish();
  }
}

};

static hipError_t ihipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
  amd::Device* device = hip::getCurrentContext()->devices()[0];

  amd::HostQueue* queue = new amd::HostQueue(*hip::getCurrentContext(), *device, 0,
                                             amd::CommandQueue::RealTimeDisabled,
                                             amd::CommandQueue::Priority::Normal);

  if (queue == nullptr || !queue->create()) {
    return hipErrorOutOfMemory;
  }

  if (!(flags & hipStreamNonBlocking)) {
    hip::syncStreams();

    {
      amd::ScopedLock lock(streamSetLock);
      streamSet.insert(queue);
    }
  }

  *stream = reinterpret_cast<hipStream_t>(as_cl(queue));

  return hipSuccess;
}

hipError_t hipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
  HIP_INIT_API(stream, flags);

  return ihipStreamCreateWithFlags(stream, flags);
}

hipError_t hipStreamCreate(hipStream_t *stream) {
  HIP_INIT_API(stream);

  return ihipStreamCreateWithFlags(stream, hipStreamDefault);
}

hipError_t hipStreamGetFlags(hipStream_t stream, unsigned int *flags) {
  HIP_INIT_API(stream, flags);

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  auto it = streamSet.find(hostQueue);

  if(flags != nullptr) {
    *flags = (it == streamSet.end()) ? hipStreamNonBlocking : hipStreamDefault;
  } else {
    return hipErrorInvalidValue;
  }

  return hipSuccess;
}

hipError_t hipStreamSynchronize(hipStream_t stream) {
  HIP_INIT_API(stream);

  amd::HostQueue* hostQueue;

  if (stream == nullptr) {
    hip::syncStreams();

    hostQueue = hip::getNullStream();
  } else {
    hip::getNullStream()->finish();

    hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  }

  if (hostQueue == nullptr) {
    return hipErrorUnknown;
  }

  hostQueue->finish();

  return hipSuccess;
}

hipError_t hipStreamDestroy(hipStream_t stream) {
  HIP_INIT_API(stream);

  if (stream == nullptr) {
    return hipErrorInvalidResourceHandle;
  }

  amd::ScopedLock lock(streamSetLock);

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  hostQueue->release();
  streamSet.erase(hostQueue);

  return hipSuccess;
}

hipError_t hipStreamWaitEvent(hipStream_t stream, hipEvent_t event, unsigned int flags) {
  HIP_INIT_API(stream, event, flags);

  if (stream == nullptr || event == nullptr) {
    return hipErrorInvalidResourceHandle;
  }

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  hip::Event* e = reinterpret_cast<hip::Event*>(event);
  cl_event clEvent = as_cl(e->event_);

  amd::Command::EventWaitList eventWaitList;
  cl_int err = amd::clSetEventWaitList(eventWaitList, *hostQueue, 1, &clEvent);
  if (err != CL_SUCCESS) {
    return hipErrorUnknown;
  }

  amd::Command* command = new amd::Marker(*hostQueue, true, eventWaitList);
  if (command == NULL) {
    return hipErrorOutOfMemory;
  }
  command->enqueue();
  command->release();

  return hipSuccess;
}

hipError_t hipStreamQuery(hipStream_t stream) {
  HIP_INIT_API(stream);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipStreamAddCallback(hipStream_t stream, hipStreamCallback_t callback, void* userData,
                                unsigned int flags) {
  HIP_INIT_API(stream, callback, userData, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/histogram.h"
#include "base/message_loop.h"
#include "chrome/common/render_messages.h"
#include "chrome/renderer/audio_message_filter.h"
#include "ipc/ipc_logging.h"

namespace {

void RecordReceiveLatency(base::TimeDelta latency) {
  static ThreadSafeHistogram histogram("Audio.IPC_Renderer_ReceiveLatency",
                                       1, 500, 100);
  histogram.AddTime(latency);
}

void RecordProcessTime(base::TimeDelta latency) {
  static ThreadSafeHistogram histogram("Audio.IPC_Renderer_ProcessTime",
                                       1, 100, 100);
  histogram.AddTime(latency);
}

}  // namespace

AudioMessageFilter::AudioMessageFilter(int32 route_id)
    : channel_(NULL),
      route_id_(route_id),
      message_loop_(NULL) {
}

AudioMessageFilter::~AudioMessageFilter() {
}

// Called on the IPC thread.
bool AudioMessageFilter::Send(IPC::Message* message) {
  if (!channel_) {
    delete message;
    return false;
  }
  message->set_routing_id(route_id_);
  return channel_->Send(message);
}

bool AudioMessageFilter::OnMessageReceived(const IPC::Message& message) {
  if (message.routing_id() != route_id_)
    return false;

  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(AudioMessageFilter, message)
    IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestPacket)
    IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnStreamCreated)
    IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged,
                        OnStreamStateChanged)
    IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnStreamVolume)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void AudioMessageFilter::OnFilterAdded(IPC::Channel* channel) {
  // Captures the message loop for IPC.
  message_loop_ = MessageLoop::current();
  channel_ = channel;
}

void AudioMessageFilter::OnFilterRemoved() {
  channel_ = NULL;
}

void AudioMessageFilter::OnChannelClosing() {
  channel_ = NULL;
}

void AudioMessageFilter::OnRequestPacket(const IPC::Message& msg,
                                         int stream_id,
                                         size_t bytes_in_buffer,
                                         int64 message_timestamp) {
  Delegate* delegate = delegates_.Lookup(stream_id);
  if (!delegate) {
    DLOG(WARNING) << "Got audio packet request for a non-existent or removed"
        " audio renderer.";
    return;
  }

#ifdef IPC_MESSAGE_LOG_ENABLED
  IPC::Logging* logger = IPC::Logging::current();
  if (logger->Enabled()) {
    RecordReceiveLatency(base::Time::FromInternalValue(msg.received_time()) -
                         base::Time::FromInternalValue(msg.sent_time()));
  }
#endif

  delegate->OnRequestPacket(bytes_in_buffer,
                            base::Time::FromInternalValue(message_timestamp));

#ifdef IPC_MESSAGE_LOG_ENABLED
  if (logger->Enabled()) {
    RecordProcessTime(base::Time::Now() -
                      base::Time::FromInternalValue(msg.received_time()));
  }
#endif
}

void AudioMessageFilter::OnStreamCreated(int stream_id,
                                         base::SharedMemoryHandle handle,
                                         int length) {
  Delegate* delegate = delegates_.Lookup(stream_id);
  if (!delegate) {
    DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
        " audio renderer.";
    return;
  }
  delegate->OnCreated(handle, length);
}

void AudioMessageFilter::OnStreamStateChanged(int stream_id,
                                              ViewMsg_AudioStreamState state) {
  Delegate* delegate = delegates_.Lookup(stream_id);
  if (!delegate) {
    DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
        " audio renderer.";
    return;
  }
  delegate->OnStateChanged(state);
}

void AudioMessageFilter::OnStreamVolume(int stream_id,
                                        double left, double right) {
  Delegate* delegate = delegates_.Lookup(stream_id);
  if (!delegate) {
    DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
        " audio renderer.";
    return;
  }
  delegate->OnVolume(left, right);
}

int32 AudioMessageFilter::AddDelegate(Delegate* delegate) {
  return delegates_.Add(delegate);
}

void AudioMessageFilter::RemoveDelegate(int32 id) {
  delegates_.Remove(id);
}
<commit_msg>Remove the use of histogram in AudioMessageFilter<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/message_loop.h"
#include "chrome/common/render_messages.h"
#include "chrome/renderer/audio_message_filter.h"
#include "ipc/ipc_logging.h"

AudioMessageFilter::AudioMessageFilter(int32 route_id)
    : channel_(NULL),
      route_id_(route_id),
      message_loop_(NULL) {
}

AudioMessageFilter::~AudioMessageFilter() {
}

// Called on the IPC thread.
bool AudioMessageFilter::Send(IPC::Message* message) {
  if (!channel_) {
    delete message;
    return false;
  }
  message->set_routing_id(route_id_);
  return channel_->Send(message);
}

bool AudioMessageFilter::OnMessageReceived(const IPC::Message& message) {
  if (message.routing_id() != route_id_)
    return false;

  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(AudioMessageFilter, message)
    IPC_MESSAGE_HANDLER(ViewMsg_RequestAudioPacket, OnRequestPacket)
    IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamCreated, OnStreamCreated)
    IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamStateChanged,
                        OnStreamStateChanged)
    IPC_MESSAGE_HANDLER(ViewMsg_NotifyAudioStreamVolume, OnStreamVolume)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void AudioMessageFilter::OnFilterAdded(IPC::Channel* channel) {
  // Captures the message loop for IPC.
  message_loop_ = MessageLoop::current();
  channel_ = channel;
}

void AudioMessageFilter::OnFilterRemoved() {
  channel_ = NULL;
}

void AudioMessageFilter::OnChannelClosing() {
  channel_ = NULL;
}

void AudioMessageFilter::OnRequestPacket(const IPC::Message& msg,
                                         int stream_id,
                                         size_t bytes_in_buffer,
                                         int64 message_timestamp) {
  Delegate* delegate = delegates_.Lookup(stream_id);
  if (!delegate) {
    DLOG(WARNING) << "Got audio packet request for a non-existent or removed"
        " audio renderer.";
    return;
  }

  delegate->OnRequestPacket(bytes_in_buffer,
                            base::Time::FromInternalValue(message_timestamp));
}

void AudioMessageFilter::OnStreamCreated(int stream_id,
                                         base::SharedMemoryHandle handle,
                                         int length) {
  Delegate* delegate = delegates_.Lookup(stream_id);
  if (!delegate) {
    DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
        " audio renderer.";
    return;
  }
  delegate->OnCreated(handle, length);
}

void AudioMessageFilter::OnStreamStateChanged(int stream_id,
                                              ViewMsg_AudioStreamState state) {
  Delegate* delegate = delegates_.Lookup(stream_id);
  if (!delegate) {
    DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
        " audio renderer.";
    return;
  }
  delegate->OnStateChanged(state);
}

void AudioMessageFilter::OnStreamVolume(int stream_id,
                                        double left, double right) {
  Delegate* delegate = delegates_.Lookup(stream_id);
  if (!delegate) {
    DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
        " audio renderer.";
    return;
  }
  delegate->OnVolume(left, right);
}

int32 AudioMessageFilter::AddDelegate(Delegate* delegate) {
  return delegates_.Add(delegate);
}

void AudioMessageFilter::RemoveDelegate(int32 id) {
  delegates_.Remove(id);
}
<|endoftext|>