<commit_before>/*=============================================================================
  NiftyLink:  A software library to facilitate communication over OpenIGTLink.

  Copyright (c) University College London (UCL). All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.

  See LICENSE.txt in the top level directory for details.
=============================================================================*/
#include "NiftyLinkUtils.h"
#include <NiftyLinkTrackingDataMessageHelpers.h>
#include <NiftyLinkTransformMessageHelpers.h>
#include <NiftyLinkImageMessageHelpers.h>

#include <igtlTrackingDataMessage.h>
#include <igtlTransformMessage.h>
#include <igtlStringMessage.h>
#include <igtlStatusMessage.h>
#include <igtlImageMessage.h>

#include <QsLog.h>
#include <QsLogDest.h>

#include <QUrl>
#include <QHostInfo>
#include <QHostAddress>
#include <QStringList>
#include <QNetworkConfigurationManager>
#include <QNetworkInterface>
#include <QNetworkSession>
#include <QDesktopServices>
#include <QDir>

#include <cmath>
#include <cassert>

namespace niftk
{

//-----------------------------------------------------------------------------
void InitializeWinTimers()
{
  // Typedef functions to hold what is in the DLL
  FunctionPtr_SETRES _NtSetTimerResolution;
  FunctionPtr_GETRES _NtQueryTimerResolution;

  // Use LoadLibrary used to load ntdll
  HINSTANCE hInstLibrary = LoadLibrary("ntdll.dll");

  if (hInstLibrary)
  {
    // the DLL is loaded and ready to go.
    _NtSetTimerResolution = (FunctionPtr_SETRES)GetProcAddress(hInstLibrary, "NtSetTimerResolution");
    _NtQueryTimerResolution = (FunctionPtr_GETRES)GetProcAddress(hInstLibrary, "NtQueryTimerResolution");

    if (_NtSetTimerResolution)
    {
      uint desiredResolution = 5000;
      bool setResolution = true;
      ULONG minResolution = 0;
      ULONG maxResolution = 0;
      ULONG currentResolution = 0;

      NTSTATUS status;

      status = _NtQueryTimerResolution(&minResolution, &maxResolution, &currentResolution);
      QLOG_INFO() <<"Current Clock Resolution - Before: " << currentResolution;

      status = _NtSetTimerResolution(maxResolution, setResolution, &currentResolution);

      status = _NtQueryTimerResolution(&minResolution, &maxResolution, &currentResolution);
      QLOG_INFO() <<"Current Clock Resolution - After: " << currentResolution;
    }
  }
  else
  {
    QLOG_ERROR() << "Failed to load ntdll.dll to set timer resolution.";
  }
}

//-----------------------------------------------------------------------------
bool ValidateIp(const QString &inputIP)
{
  QStringList nums = inputIP.split(".");

  if (nums.count() != 4)
  {
    return false;
  }

  for (int i = 0; i < 4; i++)
  {
    bool ok = false;
    int frag = nums.at(i).toInt(&ok, 10);

    if (!ok)
    {
      return false;
    }
    else if (frag < 0 || frag > 255)
    {
      return false;
    }
  }

  return true;
}

//-----------------------------------------------------------------------------
QString ResolveHostName(const QString &input)
{
  if (ValidateIp(input))
  {
    return input;
  }

  QHostInfo info = QHostInfo::fromName(input);
  QList<QHostAddress> addresses = info.addresses();

  for (int i = 0; i < addresses.count(); i++)
  {
    if ( ValidateIp(addresses.at(i).toString()) == true )
    {
      return addresses.at(i).toString();
    }
  }

  return QString("UNKNOWN");

}

//-----------------------------------------------------------------------------
QString GetLocalHostAddress(void)
{
  QNetworkConfigurationManager mgr;
  QNetworkConfiguration nconfig = mgr.defaultConfiguration();
  QNetworkSession session ( nconfig );
  QNetworkInterface ninter = session.interface();

  // this provides more than one ip addresses
  QList<QNetworkAddressEntry> laddr = ninter.addressEntries();
  for ( QList<QNetworkAddressEntry> ::const_iterator it = laddr.begin(); it != laddr.end(); ++it )
  {
    QString ipstr = it->ip().toString();
    if (ValidateIp(ipstr))
    {
      // Need to return the one which is valid and not 'localhost'
      if (ipstr != QString("127.0.0.1"))
      {
        return ipstr;
      }
    }
  }

  return QString("UNKNOWN");
}

//-----------------------------------------------------------------------------
void CreateRandomTransformMatrix(igtl::Matrix4x4& matrix)
{
  float position[3];
  float orientation[4];

  // random position
  static float phi = 0.2;
  position[0] = 50.0 * cos(phi);
  position[1] = 50.0 * sin(phi);
  position[2] = 50.0 * cos(phi);
  phi = phi + 0.2;

  // random orientation
  static float theta = 0.0;
  orientation[0] = 0.0;
  orientation[1] = 0.6666666666 * cos(theta);
  orientation[2] = 0.577350269189626;
  orientation[3] = 0.6666666666 * sin(theta);
  theta = theta + 0.1;

  //igtl::Matrix4x4 matrix;
  igtl::QuaternionToMatrix(orientation, matrix);

  matrix[0][3] = position[0];
  matrix[1][3] = position[1];
  matrix[2][3] = position[2];

  //igtl::PrintMatrix(matrix);
}

//-----------------------------------------------------------------------------
igtlUint64 GetDifferenceInNanoSeconds(igtl::TimeStamp* timeA, igtl::TimeStamp* timeB)
{
  assert(timeA);
  assert(timeB);

  igtlUint64 a = timeA->GetTimeStampInNanoseconds();
  igtlUint64 b = timeB->GetTimeStampInNanoseconds();
  igtlUint64 d;

  if (a > b)
  {
    d = a - b;
  }
  else if (b > a)
  {
    d = b - a;
  }
  else
  {
    d = 0;
  }

  return d;
}

//-----------------------------------------------------------------------------
double CalculateMean(const QList<igtlUint64>& list)
{
  double mean = 0;
  foreach(igtlUint64 item, list)
  {
    mean += static_cast<double>(item);
  }
  if (list.size() > 1)
  {
    mean /= static_cast<double>(list.size());
  }
  return mean;
}

//-----------------------------------------------------------------------------
double CalculateStdDev(const QList<igtlUint64>& list)
{
  double stdDev = 0;
  double mean = CalculateMean(list);
  foreach(igtlUint64 item, list)
  {
    stdDev += ((item-mean)*(item-mean));
  }
  if (list.size() > 1)
  {
    stdDev /= static_cast<double>(list.size());
  }
  stdDev = sqrt(stdDev);
  return stdDev;
}

//-----------------------------------------------------------------------------
igtlUint64 CalculateMax(const QList<igtlUint64>& list)
{
  igtlUint64 max = 0;
  foreach(igtlUint64 item, list)
  {
    if (item > max)
    {
      max = item;
    }
  }
  return max;
}

//-----------------------------------------------------------------------------
NiftyLinkMessageContainer::Pointer CreateTestTrackingDataMessage(igtl::TimeStamp::Pointer& timeStamp, int matricesPerMessage)
{
  igtl::Matrix4x4 matrix;

  igtl::TrackingDataMessage::Pointer msg = igtl::TrackingDataMessage::New();
  msg->SetDeviceName("NiftyLinkUtils");

  for (int i = 0; i < matricesPerMessage; i++)
  {
    niftk::CreateRandomTransformMatrix(matrix);

    igtl::TrackingDataElement::Pointer element = igtl::TrackingDataElement::New();
    element->SetMatrix(matrix);

    msg->AddTrackingDataElement(element);
  }

  timeStamp->GetTime();
  msg->SetTimeStamp(timeStamp);
  msg->Pack();

  NiftyLinkMessageContainer::Pointer m = (NiftyLinkMessageContainer::Pointer(new NiftyLinkMessageContainer()));
  m->SetMessage(msg.GetPointer());
  m->SetOwnerName("CreateTestTrackingDataMessage");
  m->SetSenderHostName("123.456.789.012");
  m->SetSenderPortNumber(1234);

  return m;
}

//-----------------------------------------------------------------------------
void CopyMatrix(double *input, igtl::Matrix4x4& output)
{
  assert(input);

  for (unsigned int r = 0; r < 4; r++)
  {
    for (unsigned int c = 0; c < 4; c++)
    {
      output[r][c] = input[r*4+c];
    }
  }
}

//-----------------------------------------------------------------------------
QString GetWritableDirectoryPath(const QString& fileName)
{
  QString result;
  QDir directory;

  QString path = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
  directory.setPath(path);

  if (!directory.exists())
  {
    path = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = QDesktopServices::storageLocation(QDesktopServices::TempLocation);
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = QDir::currentPath();
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = "";
  }

  result = path;

  if (fileName.length() > 0)
  {
    if (result.length() > 0)
    {
      result = result + QDir::separator() + fileName;
    }
    else
    {
      result = fileName;
    }
  }
  return result;
}

//-----------------------------------------------------------------------------
QString AppendPathSeparator(const QString& path)
{
  return path.right(1) == "/" ? path : path + "/";
}

//-----------------------------------------------------------------------------
void ExtractTextBasedMessage(const NiftyLinkMessageContainer::Pointer& message, QString& output)
{
  if (message.data() != NULL)
  {
    igtl::MessageBase::Pointer msg = dynamic_cast<igtl::MessageBase*>(message->GetMessage().GetPointer());
    if (msg.IsNotNull())
    {
      if (QString(msg->GetDeviceType()) == QString("STRING"))
      {
        igtl::StringMessage::Pointer m = dynamic_cast<igtl::StringMessage*>(msg.GetPointer());
        output = QString(m->GetString());
      }
      if (QString(msg->GetDeviceType()) == QString("STATUS"))
      {
        igtl::StatusMessage::Pointer m = dynamic_cast<igtl::StatusMessage*>(msg.GetPointer());
        output = QString(m->GetStatusString());
      }
      if (QString(msg->GetDeviceType()) == QString("TRANSFORM"))
      {
        igtl::TransformMessage::Pointer m = dynamic_cast<igtl::TransformMessage*>(msg.GetPointer());
        output = GetMatrixAsString(m);
      }
      if (QString(msg->GetDeviceType()) == QString("TDATA"))
      {
        igtl::TrackingDataMessage::Pointer m = dynamic_cast<igtl::TrackingDataMessage*>(msg.GetPointer());
        output = GetMatrixAsString(m,0);
      }
    }
  }
}

//-----------------------------------------------------------------------------
void ExtractImageMessage(const NiftyLinkMessageContainer::Pointer& message, QImage& image)
{
  if (message.data() != NULL)
  {
    igtl::ImageMessage::Pointer msg = dynamic_cast<igtl::ImageMessage*>(message->GetMessage().GetPointer());
    if (msg.IsNotNull())
    {
      GetQImage(msg, image);
    }
  }
}

} // end namespace niftk

<commit_msg>Bug #3609: Fix build linux/mac<commit_after>/*=============================================================================
  NiftyLink:  A software library to facilitate communication over OpenIGTLink.

  Copyright (c) University College London (UCL). All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.

  See LICENSE.txt in the top level directory for details.
=============================================================================*/
#include "NiftyLinkUtils.h"
#include <NiftyLinkTrackingDataMessageHelpers.h>
#include <NiftyLinkTransformMessageHelpers.h>
#include <NiftyLinkImageMessageHelpers.h>

#include <igtlTrackingDataMessage.h>
#include <igtlTransformMessage.h>
#include <igtlStringMessage.h>
#include <igtlStatusMessage.h>
#include <igtlImageMessage.h>

#include <QsLog.h>
#include <QsLogDest.h>

#include <QUrl>
#include <QHostInfo>
#include <QHostAddress>
#include <QStringList>
#include <QNetworkConfigurationManager>
#include <QNetworkInterface>
#include <QNetworkSession>
#include <QDesktopServices>
#include <QDir>

#include <cmath>
#include <cassert>

namespace niftk
{

#if defined(_WIN32) && !defined(__CYGWIN__)
//-----------------------------------------------------------------------------
void InitializeWinTimers()
{
  // Typedef functions to hold what is in the DLL
  FunctionPtr_SETRES _NtSetTimerResolution;
  FunctionPtr_GETRES _NtQueryTimerResolution;

  // Use LoadLibrary used to load ntdll
  HINSTANCE hInstLibrary = LoadLibrary("ntdll.dll");

  if (hInstLibrary)
  {
    // the DLL is loaded and ready to go.
    _NtSetTimerResolution = (FunctionPtr_SETRES)GetProcAddress(hInstLibrary, "NtSetTimerResolution");
    _NtQueryTimerResolution = (FunctionPtr_GETRES)GetProcAddress(hInstLibrary, "NtQueryTimerResolution");

    if (_NtSetTimerResolution)
    {
      uint desiredResolution = 5000;
      bool setResolution = true;
      ULONG minResolution = 0;
      ULONG maxResolution = 0;
      ULONG currentResolution = 0;

      NTSTATUS status;

      status = _NtQueryTimerResolution(&minResolution, &maxResolution, &currentResolution);
      QLOG_INFO() <<"Current Clock Resolution - Before: " << currentResolution;

      status = _NtSetTimerResolution(maxResolution, setResolution, &currentResolution);

      status = _NtQueryTimerResolution(&minResolution, &maxResolution, &currentResolution);
      QLOG_INFO() <<"Current Clock Resolution - After: " << currentResolution;
    }
  }
  else
  {
    QLOG_ERROR() << "Failed to load ntdll.dll to set timer resolution.";
  }
}
#endif

//-----------------------------------------------------------------------------
bool ValidateIp(const QString &inputIP)
{
  QStringList nums = inputIP.split(".");

  if (nums.count() != 4)
  {
    return false;
  }

  for (int i = 0; i < 4; i++)
  {
    bool ok = false;
    int frag = nums.at(i).toInt(&ok, 10);

    if (!ok)
    {
      return false;
    }
    else if (frag < 0 || frag > 255)
    {
      return false;
    }
  }

  return true;
}

//-----------------------------------------------------------------------------
QString ResolveHostName(const QString &input)
{
  if (ValidateIp(input))
  {
    return input;
  }

  QHostInfo info = QHostInfo::fromName(input);
  QList<QHostAddress> addresses = info.addresses();

  for (int i = 0; i < addresses.count(); i++)
  {
    if ( ValidateIp(addresses.at(i).toString()) == true )
    {
      return addresses.at(i).toString();
    }
  }

  return QString("UNKNOWN");

}

//-----------------------------------------------------------------------------
QString GetLocalHostAddress(void)
{
  QNetworkConfigurationManager mgr;
  QNetworkConfiguration nconfig = mgr.defaultConfiguration();
  QNetworkSession session ( nconfig );
  QNetworkInterface ninter = session.interface();

  // this provides more than one ip addresses
  QList<QNetworkAddressEntry> laddr = ninter.addressEntries();
  for ( QList<QNetworkAddressEntry> ::const_iterator it = laddr.begin(); it != laddr.end(); ++it )
  {
    QString ipstr = it->ip().toString();
    if (ValidateIp(ipstr))
    {
      // Need to return the one which is valid and not 'localhost'
      if (ipstr != QString("127.0.0.1"))
      {
        return ipstr;
      }
    }
  }

  return QString("UNKNOWN");
}

//-----------------------------------------------------------------------------
void CreateRandomTransformMatrix(igtl::Matrix4x4& matrix)
{
  float position[3];
  float orientation[4];

  // random position
  static float phi = 0.2;
  position[0] = 50.0 * cos(phi);
  position[1] = 50.0 * sin(phi);
  position[2] = 50.0 * cos(phi);
  phi = phi + 0.2;

  // random orientation
  static float theta = 0.0;
  orientation[0] = 0.0;
  orientation[1] = 0.6666666666 * cos(theta);
  orientation[2] = 0.577350269189626;
  orientation[3] = 0.6666666666 * sin(theta);
  theta = theta + 0.1;

  //igtl::Matrix4x4 matrix;
  igtl::QuaternionToMatrix(orientation, matrix);

  matrix[0][3] = position[0];
  matrix[1][3] = position[1];
  matrix[2][3] = position[2];

  //igtl::PrintMatrix(matrix);
}

//-----------------------------------------------------------------------------
igtlUint64 GetDifferenceInNanoSeconds(igtl::TimeStamp* timeA, igtl::TimeStamp* timeB)
{
  assert(timeA);
  assert(timeB);

  igtlUint64 a = timeA->GetTimeStampInNanoseconds();
  igtlUint64 b = timeB->GetTimeStampInNanoseconds();
  igtlUint64 d;

  if (a > b)
  {
    d = a - b;
  }
  else if (b > a)
  {
    d = b - a;
  }
  else
  {
    d = 0;
  }

  return d;
}

//-----------------------------------------------------------------------------
double CalculateMean(const QList<igtlUint64>& list)
{
  double mean = 0;
  foreach(igtlUint64 item, list)
  {
    mean += static_cast<double>(item);
  }
  if (list.size() > 1)
  {
    mean /= static_cast<double>(list.size());
  }
  return mean;
}

//-----------------------------------------------------------------------------
double CalculateStdDev(const QList<igtlUint64>& list)
{
  double stdDev = 0;
  double mean = CalculateMean(list);
  foreach(igtlUint64 item, list)
  {
    stdDev += ((item-mean)*(item-mean));
  }
  if (list.size() > 1)
  {
    stdDev /= static_cast<double>(list.size());
  }
  stdDev = sqrt(stdDev);
  return stdDev;
}

//-----------------------------------------------------------------------------
igtlUint64 CalculateMax(const QList<igtlUint64>& list)
{
  igtlUint64 max = 0;
  foreach(igtlUint64 item, list)
  {
    if (item > max)
    {
      max = item;
    }
  }
  return max;
}

//-----------------------------------------------------------------------------
NiftyLinkMessageContainer::Pointer CreateTestTrackingDataMessage(igtl::TimeStamp::Pointer& timeStamp, int matricesPerMessage)
{
  igtl::Matrix4x4 matrix;

  igtl::TrackingDataMessage::Pointer msg = igtl::TrackingDataMessage::New();
  msg->SetDeviceName("NiftyLinkUtils");

  for (int i = 0; i < matricesPerMessage; i++)
  {
    niftk::CreateRandomTransformMatrix(matrix);

    igtl::TrackingDataElement::Pointer element = igtl::TrackingDataElement::New();
    element->SetMatrix(matrix);

    msg->AddTrackingDataElement(element);
  }

  timeStamp->GetTime();
  msg->SetTimeStamp(timeStamp);
  msg->Pack();

  NiftyLinkMessageContainer::Pointer m = (NiftyLinkMessageContainer::Pointer(new NiftyLinkMessageContainer()));
  m->SetMessage(msg.GetPointer());
  m->SetOwnerName("CreateTestTrackingDataMessage");
  m->SetSenderHostName("123.456.789.012");
  m->SetSenderPortNumber(1234);

  return m;
}

//-----------------------------------------------------------------------------
void CopyMatrix(double *input, igtl::Matrix4x4& output)
{
  assert(input);

  for (unsigned int r = 0; r < 4; r++)
  {
    for (unsigned int c = 0; c < 4; c++)
    {
      output[r][c] = input[r*4+c];
    }
  }
}

//-----------------------------------------------------------------------------
QString GetWritableDirectoryPath(const QString& fileName)
{
  QString result;
  QDir directory;

  QString path = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
  directory.setPath(path);

  if (!directory.exists())
  {
    path = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = QDesktopServices::storageLocation(QDesktopServices::TempLocation);
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = QDir::currentPath();
    directory.setPath(path);
  }
  if (!directory.exists())
  {
    path = "";
  }

  result = path;

  if (fileName.length() > 0)
  {
    if (result.length() > 0)
    {
      result = result + QDir::separator() + fileName;
    }
    else
    {
      result = fileName;
    }
  }
  return result;
}

//-----------------------------------------------------------------------------
QString AppendPathSeparator(const QString& path)
{
  return path.right(1) == "/" ? path : path + "/";
}

//-----------------------------------------------------------------------------
void ExtractTextBasedMessage(const NiftyLinkMessageContainer::Pointer& message, QString& output)
{
  if (message.data() != NULL)
  {
    igtl::MessageBase::Pointer msg = dynamic_cast<igtl::MessageBase*>(message->GetMessage().GetPointer());
    if (msg.IsNotNull())
    {
      if (QString(msg->GetDeviceType()) == QString("STRING"))
      {
        igtl::StringMessage::Pointer m = dynamic_cast<igtl::StringMessage*>(msg.GetPointer());
        output = QString(m->GetString());
      }
      if (QString(msg->GetDeviceType()) == QString("STATUS"))
      {
        igtl::StatusMessage::Pointer m = dynamic_cast<igtl::StatusMessage*>(msg.GetPointer());
        output = QString(m->GetStatusString());
      }
      if (QString(msg->GetDeviceType()) == QString("TRANSFORM"))
      {
        igtl::TransformMessage::Pointer m = dynamic_cast<igtl::TransformMessage*>(msg.GetPointer());
        output = GetMatrixAsString(m);
      }
      if (QString(msg->GetDeviceType()) == QString("TDATA"))
      {
        igtl::TrackingDataMessage::Pointer m = dynamic_cast<igtl::TrackingDataMessage*>(msg.GetPointer());
        output = GetMatrixAsString(m,0);
      }
    }
  }
}

//-----------------------------------------------------------------------------
void ExtractImageMessage(const NiftyLinkMessageContainer::Pointer& message, QImage& image)
{
  if (message.data() != NULL)
  {
    igtl::ImageMessage::Pointer msg = dynamic_cast<igtl::ImageMessage*>(message->GetMessage().GetPointer());
    if (msg.IsNotNull())
    {
      GetQImage(msg, image);
    }
  }
}

} // end namespace niftk

<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/include/usr/fapi2/plat_error_scope.H $                    */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2016                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 * @file plat_error_scope.H
 * @brief platform definitions which create a scope for automatic error handling
 */

#ifndef __FAPI2_PLAT_ERROR_SCOPE__
#define __FAPI2_PLAT_ERROR_SCOPE__

/// @cond
#define PLAT_FAPI_TRY_NO_TRACE( __operation__ )                         \
    if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \
    {                                                                   \
        goto fapi_try_exit;                                             \
    }

#define PLAT_FAPI_TRY_TRACE( __operation__, ... )                       \
    if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \
    {                                                                   \
        FAPI_ERR(__VA_ARGS__);                                          \
        goto fapi_try_exit;                                             \
    }

///
/// @brief Assert a conditional is true.
/// If it is not, the FFDC gathering function is called and the
/// trace is output as a FAPI error trace. A platform error is
/// created and commited.
/// @param[in] __conditional__ the condition to assert
/// @param[in] __ffdc__ the FFDC gathering function
/// @param[in] ... varargs, as input to FAPI_ERR
///
/// @note: Plat error is stored in RC object
///
#define PLAT_FAPI_ASSERT( __conditional__, __ffdc__, ... )      \
    if (! (__conditional__))                                    \
    {                                                           \
        (__ffdc__).execute();                                   \
        FAPI_ERR(__VA_ARGS__);                                  \
        goto fapi_try_exit;                                     \
    }

///
/// @brief Assert a conditional is true.
/// If it is not, the FFDC gathering function is called and the
/// trace is output as a FAPI error trace. A platform error is
/// created but will not be committed.
/// @param[in] __conditional__ the condition to assert
/// @param[in] __ffdc__ the FFDC gathering function
/// @param[in] ... varargs, as input to FAPI_ERR
///
/// @note: Plat error, if supported, is stored in RC object. In
///        addition, this assert does not cause a branch to the
///        fapi_try_exit lable.
///
#define PLAT_FAPI_ASSERT_NOEXIT( __conditional__, __ffdc__, ... ) \
    if (! (__conditional__))                                    \
    {                                                           \
        __ffdc__.execute(                                       \
                fapi2::FAPI2_ERRL_SEV_UNDEFINED, false);    \
        FAPI_ERR(__VA_ARGS__);                                  \
    }                                                           \

/// @endcond

#endif
<commit_msg>Unable to add ffdc to RC after FAPI_ASSERT<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/include/usr/fapi2/plat_error_scope.H $                    */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2016                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 * @file plat_error_scope.H
 * @brief platform definitions which create a scope for automatic error handling
 */

#ifndef __FAPI2_PLAT_ERROR_SCOPE__
#define __FAPI2_PLAT_ERROR_SCOPE__

/// @cond
#define PLAT_FAPI_TRY_NO_TRACE( __operation__ )                         \
    if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \
    {                                                                   \
        goto fapi_try_exit;                                             \
    }

#define PLAT_FAPI_TRY_TRACE( __operation__, ... )                       \
    if ((fapi2::current_err = (__operation__)) != fapi2::FAPI2_RC_SUCCESS) \
    {                                                                   \
        FAPI_ERR(__VA_ARGS__);                                          \
        goto fapi_try_exit;                                             \
    }

///
/// @brief Assert a conditional is true.
/// If it is not, the FFDC gathering function is called and
/// the text in varargs is sent to the hostboot trace
/// as a FAPI_ERR trace.
/// fapi2::current_err will be set to a failing return code
/// as determined by the __ffdc__ class passed in.
///
/// Note: see the generated file hwp_ffdc_classes.H for
///       details on the __ffdc__ functions
///
/// @param[in] __conditional__ the condition to assert
/// @param[in] __ffdc__ the FFDC gathering function
/// @param[in] ... varargs, as input to FAPI_ERR
///
///
#define PLAT_FAPI_ASSERT( __conditional__, __ffdc__, ... )      \
    if (! (__conditional__))                                    \
    {                                                           \
        (__ffdc__).execute();                                   \
        FAPI_ERR(__VA_ARGS__);                                  \
        goto fapi_try_exit;                                     \
    }

///
/// @brief Assert a conditional is true.
/// If it is not, the FFDC gathering function is called, A
/// platform error is created and committed.
/// fapi2::current_err will be set to fapi2::FAPI2_RC_SUCCESS
/// and the text in varargs is sent to the hostboot trace as a
/// FAPI_ERR trace.
///
/// @param[in] __conditional__ the condition to assert
/// @param[in] __ffdc__ the FFDC gathering function
/// @param[in] ... varargs, as input to FAPI_ERR
///
/// @note: This assert does not cause a branch to the
///        fapi_try_exit label.
///
#define PLAT_FAPI_ASSERT_NOEXIT( __conditional__, __ffdc__, ... ) \
    if (! (__conditional__))                                    \
    {                                                           \
        __ffdc__.execute(                                       \
                fapi2::FAPI2_ERRL_SEV_UNDEFINED, true);         \
        fapi2::current_err =  fapi2::FAPI2_RC_SUCCESS;          \
        FAPI_ERR(__VA_ARGS__);                                  \
    }                                                           \

/// @endcond

#endif
<|endoftext|>


<commit_before>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2021                                                               *
 *                                                                                *
 * 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 <openspace/interaction/joystickcamerastates.h>

#include <openspace/engine/globals.h>
#include <openspace/interaction/inputstate.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/misc/exception.h>
#include <cmath>
#include <utility>

namespace openspace::interaction {

JoystickCameraStates::JoystickCameraStates(double sensitivity, double velocityScaleFactor)
    : CameraInteractionStates(sensitivity, velocityScaleFactor)
{}

void JoystickCameraStates::updateStateFromInput(const InputState& inputState,
                                                double deltaTime)
{
    std::pair<bool, glm::dvec2> globalRotation = { false, glm::dvec2(0.0) };
    std::pair<bool, double> zoom = { false, 0.0 };
    std::pair<bool, glm::dvec2> localRoll = { false, glm::dvec2(0.0) };
    std::pair<bool, glm::dvec2> globalRoll = { false, glm::dvec2(0.0) };
    std::pair<bool, glm::dvec2> localRotation = { false, glm::dvec2(0.0) };

    for (int i = 0; i < JoystickInputState::MaxAxes; ++i) {
        AxisInformation t = _axisMapping[i];
        if (t.type == AxisType::None) {
            continue;
        }

        float rawValue = inputState.joystickAxis(i);
        float value = rawValue;

        if (t.isStatic) {
            value = rawValue - _prevAxisValues[i];
            _prevAxisValues[i] = rawValue;
        }

        if (std::fabs(value) <= t.deadzone) {
            continue;
        }

        if (t.normalize) {
            value = (value + 1.f) / 2.f;
        }

        if (t.invert) {
            value *= -1.f;
        }

        if (std::fabs(t.sensitivity) > std::numeric_limits<double>().epsilon()) {
            value = static_cast<float>(value * t.sensitivity);
        }
        else {
            value = static_cast<float>(value * _sensitivity);
        }

        switch (t.type) {
            case AxisType::None:
                break;
            case AxisType::OrbitX:
                globalRotation.first = true;
                globalRotation.second.x = value;
                break;
            case AxisType::OrbitY:
                globalRotation.first = true;
                globalRotation.second.y = value;
                break;
            case AxisType::Zoom:
            case AxisType::ZoomIn:
                zoom.first = true;
                zoom.second += value;
                break;
            case AxisType::ZoomOut:
                zoom.first = true;
                zoom.second -= value;
                break;
            case AxisType::LocalRollX:
                localRoll.first = true;
                localRoll.second.x = value;
                break;
            case AxisType::LocalRollY:
                localRoll.first = true;
                localRoll.second.y = value;
                break;
            case AxisType::GlobalRollX:
                globalRoll.first = true;
                globalRoll.second.x = value;
                break;
            case AxisType::GlobalRollY:
                globalRoll.first = true;
                globalRoll.second.y = value;
                break;
            case AxisType::PanX:
                localRotation.first = true;
                localRotation.second.x = value;
                break;
            case AxisType::PanY:
                localRotation.first = true;
                localRotation.second.y = value;
                break;
        }
    }

    if (globalRotation.first) {
        _globalRotationState.velocity.set(globalRotation.second, deltaTime);
    }
    else {
        _globalRotationState.velocity.decelerate(deltaTime);
    }

    if (zoom.first) {
        _truckMovementState.velocity.set(glm::dvec2(zoom.second), deltaTime);
    }
    else {
        _truckMovementState.velocity.decelerate(deltaTime);
    }

    if (localRoll.first) {
        _localRollState.velocity.set(localRoll.second, deltaTime);
    }
    else {
        _localRollState.velocity.decelerate(deltaTime);
    }

    if (globalRoll.first) {
        _globalRollState.velocity.set(globalRoll.second, deltaTime);
    }
    else {
        _globalRollState.velocity.decelerate(deltaTime);
    }

    if (localRotation.first) {
        _localRotationState.velocity.set(localRotation.second, deltaTime);
    }
    else {
        _localRotationState.velocity.decelerate(deltaTime);
    }

    for (int i = 0; i < JoystickInputState::MaxButtons; ++i) {
        auto itRange = _buttonMapping.equal_range(i);
        for (auto it = itRange.first; it != itRange.second; ++it) {
            bool active = global::joystickInputStates->button(i, it->second.action);

            if (active) {
                global::scriptEngine->queueScript(
                    it->second.command,
                    scripting::ScriptEngine::RemoteScripting(it->second.synchronization)
                );
            }
        }
    }
}

void JoystickCameraStates::setAxisMapping(int axis, AxisType mapping,
                                          AxisInvert shouldInvert,
                                          AxisNormalize shouldNormalize,
                                          bool isStatic,
                                          double sensitivity)
{
    ghoul_assert(axis < JoystickInputState::MaxAxes, "axis must be < MaxAxes");

    _axisMapping[axis].type = mapping;
    _axisMapping[axis].invert = shouldInvert;
    _axisMapping[axis].normalize = shouldNormalize;
    _axisMapping[axis].isStatic = isStatic;
    _axisMapping[axis].sensitivity = sensitivity;

    if (isStatic) {
        global::joystickInputStates->at(axis).isStatic = true;
    }

    _prevAxisValues[axis] = 0.f;
}

JoystickCameraStates::AxisInformation JoystickCameraStates::axisMapping(int axis) const {
    return _axisMapping[axis];
}

void JoystickCameraStates::setDeadzone(int axis, float deadzone) {
    _axisMapping[axis].deadzone = deadzone;
}

float JoystickCameraStates::deadzone(int axis) const {
    return _axisMapping[axis].deadzone;
}

void JoystickCameraStates::bindButtonCommand(int button, std::string command,
                                             JoystickAction action,
                                             ButtonCommandRemote remote,
                                             std::string documentation)
{
    _buttonMapping.insert({
        button,
        { std::move(command), action, remote, std::move(documentation) }
    });
}

void JoystickCameraStates::clearButtonCommand(int button) {
    for (auto it = _buttonMapping.begin(); it != _buttonMapping.end();) {
        // If the current iterator is the button that we are looking for, delete it
        // (std::multimap::erase will return the iterator to the next element for us)
        if (it->first == button) {
            it = _buttonMapping.erase(it);
        }
        else {
            ++it;
        }
    }
}

std::vector<std::string> JoystickCameraStates::buttonCommand(int button) const {
    std::vector<std::string> result;
    auto itRange = _buttonMapping.equal_range(button);
    for (auto it = itRange.first; it != itRange.second; ++it) {
        result.push_back(it->second.command);
    }
    return result;
}

} // namespace openspace::interaction
<commit_msg>Make SpaceMouse respond to sensitivity slider<commit_after>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2021                                                               *
 *                                                                                *
 * 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 <openspace/interaction/joystickcamerastates.h>

#include <openspace/engine/globals.h>
#include <openspace/interaction/inputstate.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/misc/exception.h>
#include <cmath>
#include <utility>

namespace openspace::interaction {

JoystickCameraStates::JoystickCameraStates(double sensitivity, double velocityScaleFactor)
    : CameraInteractionStates(sensitivity, velocityScaleFactor)
{}

void JoystickCameraStates::updateStateFromInput(const InputState& inputState,
                                                double deltaTime)
{
    std::pair<bool, glm::dvec2> globalRotation = { false, glm::dvec2(0.0) };
    std::pair<bool, double> zoom = { false, 0.0 };
    std::pair<bool, glm::dvec2> localRoll = { false, glm::dvec2(0.0) };
    std::pair<bool, glm::dvec2> globalRoll = { false, glm::dvec2(0.0) };
    std::pair<bool, glm::dvec2> localRotation = { false, glm::dvec2(0.0) };

    for (int i = 0; i < JoystickInputState::MaxAxes; ++i) {
        AxisInformation t = _axisMapping[i];
        if (t.type == AxisType::None) {
            continue;
        }

        float rawValue = inputState.joystickAxis(i);
        float value = rawValue;

        if (t.isStatic) {
            value = rawValue - _prevAxisValues[i];
            _prevAxisValues[i] = rawValue;
        }

        if (std::fabs(value) <= t.deadzone) {
            continue;
        }

        if (t.normalize) {
            value = (value + 1.f) / 2.f;
        }

        if (t.invert) {
            value *= -1.f;
        }

        if (std::fabs(t.sensitivity) > std::numeric_limits<double>().epsilon()) {
            value = static_cast<float>(value * t.sensitivity * _sensitivity);
        }
        else {
            value = static_cast<float>(value * _sensitivity);
        }

        switch (t.type) {
            case AxisType::None:
                break;
            case AxisType::OrbitX:
                globalRotation.first = true;
                globalRotation.second.x = value;
                break;
            case AxisType::OrbitY:
                globalRotation.first = true;
                globalRotation.second.y = value;
                break;
            case AxisType::Zoom:
            case AxisType::ZoomIn:
                zoom.first = true;
                zoom.second += value;
                break;
            case AxisType::ZoomOut:
                zoom.first = true;
                zoom.second -= value;
                break;
            case AxisType::LocalRollX:
                localRoll.first = true;
                localRoll.second.x = value;
                break;
            case AxisType::LocalRollY:
                localRoll.first = true;
                localRoll.second.y = value;
                break;
            case AxisType::GlobalRollX:
                globalRoll.first = true;
                globalRoll.second.x = value;
                break;
            case AxisType::GlobalRollY:
                globalRoll.first = true;
                globalRoll.second.y = value;
                break;
            case AxisType::PanX:
                localRotation.first = true;
                localRotation.second.x = value;
                break;
            case AxisType::PanY:
                localRotation.first = true;
                localRotation.second.y = value;
                break;
        }
    }

    if (globalRotation.first) {
        _globalRotationState.velocity.set(globalRotation.second, deltaTime);
    }
    else {
        _globalRotationState.velocity.decelerate(deltaTime);
    }

    if (zoom.first) {
        _truckMovementState.velocity.set(glm::dvec2(zoom.second), deltaTime);
    }
    else {
        _truckMovementState.velocity.decelerate(deltaTime);
    }

    if (localRoll.first) {
        _localRollState.velocity.set(localRoll.second, deltaTime);
    }
    else {
        _localRollState.velocity.decelerate(deltaTime);
    }

    if (globalRoll.first) {
        _globalRollState.velocity.set(globalRoll.second, deltaTime);
    }
    else {
        _globalRollState.velocity.decelerate(deltaTime);
    }

    if (localRotation.first) {
        _localRotationState.velocity.set(localRotation.second, deltaTime);
    }
    else {
        _localRotationState.velocity.decelerate(deltaTime);
    }

    for (int i = 0; i < JoystickInputState::MaxButtons; ++i) {
        auto itRange = _buttonMapping.equal_range(i);
        for (auto it = itRange.first; it != itRange.second; ++it) {
            bool active = global::joystickInputStates->button(i, it->second.action);

            if (active) {
                global::scriptEngine->queueScript(
                    it->second.command,
                    scripting::ScriptEngine::RemoteScripting(it->second.synchronization)
                );
            }
        }
    }
}

void JoystickCameraStates::setAxisMapping(int axis, AxisType mapping,
                                          AxisInvert shouldInvert,
                                          AxisNormalize shouldNormalize,
                                          bool isStatic,
                                          double sensitivity)
{
    ghoul_assert(axis < JoystickInputState::MaxAxes, "axis must be < MaxAxes");

    _axisMapping[axis].type = mapping;
    _axisMapping[axis].invert = shouldInvert;
    _axisMapping[axis].normalize = shouldNormalize;
    _axisMapping[axis].isStatic = isStatic;
    _axisMapping[axis].sensitivity = sensitivity;

    if (isStatic) {
        global::joystickInputStates->at(axis).isStatic = true;
    }

    _prevAxisValues[axis] = 0.f;
}

JoystickCameraStates::AxisInformation JoystickCameraStates::axisMapping(int axis) const {
    return _axisMapping[axis];
}

void JoystickCameraStates::setDeadzone(int axis, float deadzone) {
    _axisMapping[axis].deadzone = deadzone;
}

float JoystickCameraStates::deadzone(int axis) const {
    return _axisMapping[axis].deadzone;
}

void JoystickCameraStates::bindButtonCommand(int button, std::string command,
                                             JoystickAction action,
                                             ButtonCommandRemote remote,
                                             std::string documentation)
{
    _buttonMapping.insert({
        button,
        { std::move(command), action, remote, std::move(documentation) }
    });
}

void JoystickCameraStates::clearButtonCommand(int button) {
    for (auto it = _buttonMapping.begin(); it != _buttonMapping.end();) {
        // If the current iterator is the button that we are looking for, delete it
        // (std::multimap::erase will return the iterator to the next element for us)
        if (it->first == button) {
            it = _buttonMapping.erase(it);
        }
        else {
            ++it;
        }
    }
}

std::vector<std::string> JoystickCameraStates::buttonCommand(int button) const {
    std::vector<std::string> result;
    auto itRange = _buttonMapping.equal_range(button);
    for (auto it = itRange.first; it != itRange.second; ++it) {
        result.push_back(it->second.command);
    }
    return result;
}

} // namespace openspace::interaction
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

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

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

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

#include <iostream>
#include "mkldnn.hpp"
#include "paddle/fluid/operators/softmax_op.h"
#include "paddle/fluid/platform/mkldnn_helper.h"

namespace paddle {
namespace operators {

using paddle::framework::Tensor;
using paddle::platform::MKLDNNDeviceContext;
using paddle::platform::MKLDNNMemDesc;

using mkldnn::memory;  // Note: paddle has also "memory" namespace
using mkldnn::primitive;
using mkldnn::softmax_forward;
using mkldnn::softmax_backward;
using mkldnn::prop_kind;
using mkldnn::stream;
using platform::to_void_cast;

class SoftmaxMKLDNNHandler : public platform::MKLDNNHandler {
 public:
  SoftmaxMKLDNNHandler(
      std::shared_ptr<mkldnn::softmax_forward::primitive_desc> softmax_pd,
      const platform::MKLDNNDeviceContext& dev_ctx, mkldnn::engine engine,
      const std::string& base_key)
      : platform::MKLDNNHandler(dev_ctx, engine, base_key),
        softmax_pd_(softmax_pd) {}

  SoftmaxMKLDNNHandler(
      std::shared_ptr<mkldnn::softmax_forward::primitive_desc> softmax_pd,
      std::shared_ptr<mkldnn::softmax_backward::primitive_desc> softmax_bwd_pd,
      const platform::MKLDNNDeviceContext& dev_ctx, mkldnn::engine engine,
      const std::string& base_key)
      : platform::MKLDNNHandler(dev_ctx, engine, base_key),
        softmax_pd_(softmax_pd),
        softmax_bwd_pd_(softmax_bwd_pd) {
    // If we are in Grad operatgor then update a key with BWD suffix to
    // distinguish from FWD memory primitives
    key_ += "-BWD";
  }

  std::shared_ptr<mkldnn::softmax_forward> AcquireSoftmax(
      std::shared_ptr<mkldnn::memory> dst_memory_p,
      std::shared_ptr<mkldnn::memory> src_memory_p) {
    /*Generate key*/
    auto prim_key = key_ + "@softmax_p";

    auto softmax_p = std::static_pointer_cast<mkldnn::softmax_forward>(
        dev_ctx_.GetBlob(prim_key));
    PADDLE_ENFORCE((softmax_p != nullptr) || (is_reusing_ == false),
                   "Fail to find softmax primitive in device context");
    if (softmax_p == nullptr) {
      softmax_p = std::make_shared<mkldnn::softmax_forward>(
          *(softmax_pd_.get()),
          *(static_cast<mkldnn::memory*>(src_memory_p.get())),
          *(static_cast<mkldnn::memory*>(dst_memory_p.get())));
      dev_ctx_.SetBlob(prim_key, softmax_p);
    } else {
      is_reusing_ = true;
    }

    return softmax_p;
  }

  std::shared_ptr<mkldnn::softmax_backward> AcquireSoftmaxBackward(
      std::shared_ptr<mkldnn::memory> dst_memory_p,
      std::shared_ptr<mkldnn::memory> diff_dst_memory_p,
      std::shared_ptr<mkldnn::memory> diff_src_memory_p) {
    auto prim_key = key_ + "@softmax_bwd_p";
    auto softmax_bwd_p = std::static_pointer_cast<mkldnn::softmax_backward>(
        dev_ctx_.GetBlob(prim_key));
    PADDLE_ENFORCE((softmax_bwd_p != nullptr) || (is_reusing_ == false),
                   "Fail to find softmax backward primitive in device context");
    if (softmax_bwd_p == nullptr) {
      softmax_bwd_p = std::make_shared<mkldnn::softmax_backward>(
          *softmax_bwd_pd_, *(dst_memory_p.get()), *(diff_dst_memory_p.get()),
          *(diff_src_memory_p.get()));
      dev_ctx_.SetBlob(prim_key, softmax_bwd_p);
    } else {
      is_reusing_ = true;
    }

    return softmax_bwd_p;
  }

 private:
  std::shared_ptr<mkldnn::softmax_forward::primitive_desc> softmax_pd_;
  std::shared_ptr<mkldnn::softmax_backward::primitive_desc> softmax_bwd_pd_;
};

template <typename T>
class SoftmaxMKLDNNKernel : public paddle::framework::OpKernel<T> {
 public:
  void Compute(const paddle::framework::ExecutionContext& ctx) const override {
    PADDLE_ENFORCE(paddle::platform::is_cpu_place(ctx.GetPlace()),
                   "It must use CPUPlace.");
    auto& dev_ctx = ctx.template device_context<MKLDNNDeviceContext>();
    auto mkldnn_engine = dev_ctx.GetEngine();
    const Tensor* input = ctx.Input<Tensor>("X");
    Tensor* output = ctx.Output<Tensor>("Out");
    PADDLE_ENFORCE(input->dims().size() == 2UL,
                   "The input of softmax op must be a 2D matrix.");
    const T* input_data = input->data<T>();
    // allocate memory for output
    T* output_data = output->mutable_data<T>(ctx.GetPlace());
    std::vector<int> src_tz = paddle::framework::vectorize2int(input->dims());
    std::vector<int> dst_tz = paddle::framework::vectorize2int(output->dims());
    // MKL-DNN does support softmax over selected axis. Having 2D Tensor,
    // we will make normalization after final eg. axis: 1
    PADDLE_ENFORCE(((src_tz[0] == dst_tz[0]) && (src_tz[1] == dst_tz[1])),
                   "Softmax input and output dimensions should match");
    // Same memory descriptor to be used for input and output
    memory::dims softmax_tz = {src_tz[0], src_tz[1]};
    // Generate keys for storing/retriving primitives for this operator
    const std::string key =
        platform::MKLDNNHandler::GetHash(softmax_tz, ctx.op().Output("Out"));
    const std::string key_softmax_pd = key + "@softmax_pd";

    // Currently only NC data format is supported
    auto softmax_md = MKLDNNMemDesc(
        {softmax_tz}, platform::MKLDNNGetDataType<T>(), memory::format::nc);
    // Normalization is made after innermost dimension eg. C out of NC
    auto softmax_desc = softmax_forward::desc(prop_kind::forward_scoring,
                                              softmax_md, 1 /*dim: C*/);
    auto softmax_pd = std::make_shared<mkldnn::softmax_forward::primitive_desc>(
        softmax_desc, mkldnn_engine);
    dev_ctx.SetBlob(key_softmax_pd, softmax_pd);

    SoftmaxMKLDNNHandler handler(softmax_pd, dev_ctx, mkldnn_engine, key);
    auto softmax_src_memory_p =
        handler.AcquireSrcMemory(softmax_md, to_void_cast<T>(input_data));
    auto softmax_dst_memory_p =
        handler.AcquireDstMemory(softmax_md, to_void_cast<T>(output_data));
    auto softmax_p =
        handler.AcquireSoftmax(softmax_dst_memory_p, softmax_src_memory_p);

    std::vector<primitive> pipeline{
        *(static_cast<softmax_forward::primitive*>(softmax_p.get()))};
    stream(stream::kind::eager).submit(pipeline).wait();

    const bool is_test = ctx.Attr<bool>("is_test");
    if (!is_test) {
      T threshold = exp(-64);
      for (int i = 0; i < dst_tz[0] * dst_tz[1]; ++i) {
        output_data[i] =
            output_data[i] < threshold ? threshold : output_data[i];
      }
    }
  }
};

template <typename T>
class SoftmaxMKLDNNGradKernel : public paddle::framework::OpKernel<T> {
 public:
  void Compute(const paddle::framework::ExecutionContext& ctx) const override {
    PADDLE_ENFORCE(paddle::platform::is_cpu_place(ctx.GetPlace()),
                   "It must use CPUPlace.");

    auto& dev_ctx = ctx.template device_context<MKLDNNDeviceContext>();
    auto mkldnn_engine = dev_ctx.GetEngine();
    const Tensor* output = ctx.Input<Tensor>("Out");
    const T* dst_data = output->data<T>();

    auto* dout = ctx.template Input<Tensor>(framework::GradVarName("Out"));
    const auto* diff_dst_ptr = dout->template data<T>();

    auto* dx =
        ctx.template Output<framework::Tensor>(framework::GradVarName("X"));
    T* diff_src_ptr = dx->template mutable_data<T>(ctx.GetPlace());

    std::vector<int> dst_tz = paddle::framework::vectorize2int(output->dims());
    std::vector<int> src_tz(dst_tz);
    PADDLE_ENFORCE(output->dims().size() == 2UL,
                   "The input of softmax op must be a 2D matrix.");
    // MKL-DNN does support softmax over selected axis. Having 2D Tensor,
    // we will make normalization after final eg. axis: 1
    PADDLE_ENFORCE(((src_tz[0] == dst_tz[0]) && (src_tz[1] == dst_tz[1])),
                   "Softmax input and output dimensions should match");
    // Same memory descriptor to be used for input and output
    memory::dims softmax_tz = {src_tz[0], src_tz[1]};
    // Currently only supports NC data format
    // retrieve eltwise primitive desc from device context
    const std::string key =
        platform::MKLDNNHandler::GetHash(softmax_tz, ctx.op().Input("Out"));
    const std::string key_softmax_pd = key + "@softmax_pd";

    auto softmax_pd =
        std::static_pointer_cast<mkldnn::softmax_forward::primitive_desc>(
            dev_ctx.GetBlob(key_softmax_pd));
    PADDLE_ENFORCE(softmax_pd != nullptr,
                   "Fail to find softmax_pd in device context");

    // TODO(jczaja): Add layouts support when there is a need to do so
    // Two dimensional softmax does support NC format
    auto data_softmax_md = MKLDNNMemDesc(
        {softmax_tz}, platform::MKLDNNGetDataType<T>(), memory::format::nc);
    auto diff_softmax_md = MKLDNNMemDesc(
        {softmax_tz}, platform::MKLDNNGetDataType<T>(), memory::format::nc);
    // Normalization is made after innermost dimension eg. C out of NC
    auto softmax_bwd_desc =
        softmax_backward::desc(diff_softmax_md, data_softmax_md, 1 /* dim: C*/);
    auto softmax_bwd_pd =
        std::make_shared<mkldnn::softmax_backward::primitive_desc>(
            softmax_bwd_desc, mkldnn_engine, *softmax_pd);

    SoftmaxMKLDNNHandler handler(softmax_pd, softmax_bwd_pd, dev_ctx,
                                 mkldnn_engine, key);
    auto dst_memory_p =
        handler.AcquireDstMemory(data_softmax_md, to_void_cast<T>(dst_data));
    auto diff_dst_memory_p = handler.AcquireDiffDstMemory(
        diff_softmax_md, to_void_cast<T>(diff_dst_ptr));
    auto diff_src_memory_p = handler.AcquireDiffSrcMemory(
        diff_softmax_md, to_void_cast<T>(diff_src_ptr));

    // Get primitve from device context
    auto softmax_bwd_p = handler.AcquireSoftmaxBackward(
        dst_memory_p, diff_dst_memory_p, diff_src_memory_p);

    std::vector<primitive> pipeline{*softmax_bwd_p};
    stream(stream::kind::eager).submit(pipeline).wait();
  }
};
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OP_KERNEL(softmax, MKLDNN, ::paddle::platform::CPUPlace,
                   ops::SoftmaxMKLDNNKernel<float>);
REGISTER_OP_KERNEL(softmax_grad, MKLDNN, ::paddle::platform::CPUPlace,
                   ops::SoftmaxMKLDNNGradKernel<float>);
<commit_msg>update softmax_mkldnn_op<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

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

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

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

#include <iostream>
#include "mkldnn.hpp"
#include "paddle/fluid/operators/softmax_op.h"
#include "paddle/fluid/platform/mkldnn_helper.h"

namespace paddle {
namespace operators {

using paddle::framework::Tensor;
using paddle::platform::MKLDNNDeviceContext;
using paddle::platform::MKLDNNMemDesc;

using mkldnn::memory;  // Note: paddle has also "memory" namespace
using mkldnn::primitive;
using mkldnn::prop_kind;
using mkldnn::softmax_backward;
using mkldnn::softmax_forward;
using mkldnn::stream;
using platform::to_void_cast;

class SoftmaxMKLDNNHandler : public platform::MKLDNNHandler {
 public:
  SoftmaxMKLDNNHandler(
      std::shared_ptr<mkldnn::softmax_forward::primitive_desc> softmax_pd,
      const platform::MKLDNNDeviceContext& dev_ctx, mkldnn::engine engine,
      const std::string& base_key)
      : platform::MKLDNNHandler(dev_ctx, engine, base_key),
        softmax_pd_(softmax_pd) {}

  SoftmaxMKLDNNHandler(
      std::shared_ptr<mkldnn::softmax_forward::primitive_desc> softmax_pd,
      std::shared_ptr<mkldnn::softmax_backward::primitive_desc> softmax_bwd_pd,
      const platform::MKLDNNDeviceContext& dev_ctx, mkldnn::engine engine,
      const std::string& base_key)
      : platform::MKLDNNHandler(dev_ctx, engine, base_key),
        softmax_pd_(softmax_pd),
        softmax_bwd_pd_(softmax_bwd_pd) {
    // If we are in Grad operatgor then update a key with BWD suffix to
    // distinguish from FWD memory primitives
    key_ += "-BWD";
  }

  std::shared_ptr<mkldnn::softmax_forward> AcquireSoftmax(
      std::shared_ptr<mkldnn::memory> dst_memory_p,
      std::shared_ptr<mkldnn::memory> src_memory_p) {
    /*Generate key*/
    auto prim_key = key_ + "@softmax_p";

    auto softmax_p = std::static_pointer_cast<mkldnn::softmax_forward>(
        dev_ctx_.GetBlob(prim_key));
    PADDLE_ENFORCE((softmax_p != nullptr) || (is_reusing_ == false),
                   "Fail to find softmax primitive in device context");
    if (softmax_p == nullptr) {
      softmax_p = std::make_shared<mkldnn::softmax_forward>(
          *(softmax_pd_.get()),
          *(static_cast<mkldnn::memory*>(src_memory_p.get())),
          *(static_cast<mkldnn::memory*>(dst_memory_p.get())));
      dev_ctx_.SetBlob(prim_key, softmax_p);
    } else {
      is_reusing_ = true;
    }

    return softmax_p;
  }

  std::shared_ptr<mkldnn::softmax_backward> AcquireSoftmaxBackward(
      std::shared_ptr<mkldnn::memory> dst_memory_p,
      std::shared_ptr<mkldnn::memory> diff_dst_memory_p,
      std::shared_ptr<mkldnn::memory> diff_src_memory_p) {
    auto prim_key = key_ + "@softmax_bwd_p";
    auto softmax_bwd_p = std::static_pointer_cast<mkldnn::softmax_backward>(
        dev_ctx_.GetBlob(prim_key));
    PADDLE_ENFORCE((softmax_bwd_p != nullptr) || (is_reusing_ == false),
                   "Fail to find softmax backward primitive in device context");
    if (softmax_bwd_p == nullptr) {
      softmax_bwd_p = std::make_shared<mkldnn::softmax_backward>(
          *softmax_bwd_pd_, *(dst_memory_p.get()), *(diff_dst_memory_p.get()),
          *(diff_src_memory_p.get()));
      dev_ctx_.SetBlob(prim_key, softmax_bwd_p);
    } else {
      is_reusing_ = true;
    }

    return softmax_bwd_p;
  }

 private:
  std::shared_ptr<mkldnn::softmax_forward::primitive_desc> softmax_pd_;
  std::shared_ptr<mkldnn::softmax_backward::primitive_desc> softmax_bwd_pd_;
};

template <typename T>
class SoftmaxMKLDNNKernel : public paddle::framework::OpKernel<T> {
 public:
  void Compute(const paddle::framework::ExecutionContext& ctx) const override {
    PADDLE_ENFORCE(paddle::platform::is_cpu_place(ctx.GetPlace()),
                   "It must use CPUPlace.");
    auto& dev_ctx = ctx.template device_context<MKLDNNDeviceContext>();
    auto mkldnn_engine = dev_ctx.GetEngine();
    const Tensor* input = ctx.Input<Tensor>("X");
    Tensor* output = ctx.Output<Tensor>("Out");
    PADDLE_ENFORCE_EQ(
        input->dims(), output->dims(),
        "The shape of softmax's input and output must be identical.");

    // make sure 'output' holds memory, which will be shared by
    // 'flattened_output' later.
    output->mutable_data<T>(ctx.GetPlace());

    // flatten input and output to 2-D matrixs
    auto dims = input->dims();  // input and output share the same shape
    auto flattened_dims = framework::flatten_to_2d(dims, dims.size() - 1);
    framework::Tensor flattened_input;
    framework::Tensor flattened_output;
    flattened_input.ShareDataWith(*input).Resize(flattened_dims);
    flattened_output.ShareDataWith(*output).Resize(flattened_dims);

    const T* input_data = flattened_input.data<T>();
    T* output_data = flattened_output.mutable_data<T>(ctx.GetPlace());

    std::vector<int> src_tz = paddle::framework::vectorize2int(flattened_dims);
    std::vector<int> dst_tz = src_tz;
    // Same memory descriptor to be used for input and output
    memory::dims softmax_tz = {src_tz[0], src_tz[1]};
    // Generate keys for storing/retriving primitives for this operator
    const std::string key =
        platform::MKLDNNHandler::GetHash(softmax_tz, ctx.op().Output("Out"));
    const std::string key_softmax_pd = key + "@softmax_pd";

    // Currently only NC data format is supported
    auto softmax_md = MKLDNNMemDesc(
        {softmax_tz}, platform::MKLDNNGetDataType<T>(), memory::format::nc);
    // Normalization is made after innermost dimension eg. C out of NC
    auto softmax_desc = softmax_forward::desc(prop_kind::forward_scoring,
                                              softmax_md, 1 /*dim: C*/);
    auto softmax_pd = std::make_shared<mkldnn::softmax_forward::primitive_desc>(
        softmax_desc, mkldnn_engine);
    dev_ctx.SetBlob(key_softmax_pd, softmax_pd);

    SoftmaxMKLDNNHandler handler(softmax_pd, dev_ctx, mkldnn_engine, key);
    auto softmax_src_memory_p =
        handler.AcquireSrcMemory(softmax_md, to_void_cast<T>(input_data));
    auto softmax_dst_memory_p =
        handler.AcquireDstMemory(softmax_md, to_void_cast<T>(output_data));
    auto softmax_p =
        handler.AcquireSoftmax(softmax_dst_memory_p, softmax_src_memory_p);

    std::vector<primitive> pipeline{
        *(static_cast<softmax_forward::primitive*>(softmax_p.get()))};
    stream(stream::kind::eager).submit(pipeline).wait();

    const bool is_test = ctx.Attr<bool>("is_test");
    if (!is_test) {
      T threshold = exp(-64);
      for (int i = 0; i < dst_tz[0] * dst_tz[1]; ++i) {
        output_data[i] =
            output_data[i] < threshold ? threshold : output_data[i];
      }
    }
  }
};

template <typename T>
class SoftmaxMKLDNNGradKernel : public paddle::framework::OpKernel<T> {
 public:
  void Compute(const paddle::framework::ExecutionContext& ctx) const override {
    PADDLE_ENFORCE(paddle::platform::is_cpu_place(ctx.GetPlace()),
                   "It must use CPUPlace.");

    auto& dev_ctx = ctx.template device_context<MKLDNNDeviceContext>();
    auto mkldnn_engine = dev_ctx.GetEngine();
    const Tensor* output = ctx.Input<Tensor>("Out");
    auto* dout = ctx.template Input<Tensor>(framework::GradVarName("Out"));
    auto* dx =
        ctx.template Output<framework::Tensor>(framework::GradVarName("X"));

    PADDLE_ENFORCE_EQ(
        dout->dims(), dx->dims(),
        "The shape of softmax_grad's input and output must be identical.");

    // make sure 'dx' holds memory, which will be shared by 'flattened_dx'
    // later.
    dx->template mutable_data<T>(ctx.GetPlace());

    auto dims = dout->dims();  // input and output share the same shape
    auto flattened_dims = framework::flatten_to_2d(dims, dims.size() - 1);
    framework::Tensor flattened_output;
    framework::Tensor flattened_dout;
    framework::Tensor flattened_dx;
    flattened_output.ShareDataWith(*output).Resize(flattened_dims);
    flattened_dout.ShareDataWith(*dout).Resize(flattened_dims);
    flattened_dx.ShareDataWith(*dx).Resize(flattened_dims);

    const T* dst_data = flattened_output.data<T>();
    const T* diff_dst_ptr = flattened_dout.template data<T>();
    T* diff_src_ptr = flattened_dx.template mutable_data<T>(ctx.GetPlace());

    std::vector<int> dst_tz = paddle::framework::vectorize2int(flattened_dims);
    std::vector<int> src_tz(dst_tz);

    // Same memory descriptor to be used for input and output
    memory::dims softmax_tz = {src_tz[0], src_tz[1]};
    // Currently only supports NC data format
    // retrieve eltwise primitive desc from device context
    const std::string key =
        platform::MKLDNNHandler::GetHash(softmax_tz, ctx.op().Input("Out"));
    const std::string key_softmax_pd = key + "@softmax_pd";

    auto softmax_pd =
        std::static_pointer_cast<mkldnn::softmax_forward::primitive_desc>(
            dev_ctx.GetBlob(key_softmax_pd));
    PADDLE_ENFORCE(softmax_pd != nullptr,
                   "Fail to find softmax_pd in device context");

    // TODO(jczaja): Add layouts support when there is a need to do so
    // Two dimensional softmax does support NC format
    auto data_softmax_md = MKLDNNMemDesc(
        {softmax_tz}, platform::MKLDNNGetDataType<T>(), memory::format::nc);
    auto diff_softmax_md = MKLDNNMemDesc(
        {softmax_tz}, platform::MKLDNNGetDataType<T>(), memory::format::nc);
    // Normalization is made after innermost dimension eg. C out of NC
    auto softmax_bwd_desc =
        softmax_backward::desc(diff_softmax_md, data_softmax_md, 1 /* dim: C*/);
    auto softmax_bwd_pd =
        std::make_shared<mkldnn::softmax_backward::primitive_desc>(
            softmax_bwd_desc, mkldnn_engine, *softmax_pd);

    SoftmaxMKLDNNHandler handler(softmax_pd, softmax_bwd_pd, dev_ctx,
                                 mkldnn_engine, key);
    auto dst_memory_p =
        handler.AcquireDstMemory(data_softmax_md, to_void_cast<T>(dst_data));
    auto diff_dst_memory_p = handler.AcquireDiffDstMemory(
        diff_softmax_md, to_void_cast<T>(diff_dst_ptr));
    auto diff_src_memory_p = handler.AcquireDiffSrcMemory(
        diff_softmax_md, to_void_cast<T>(diff_src_ptr));

    // Get primitve from device context
    auto softmax_bwd_p = handler.AcquireSoftmaxBackward(
        dst_memory_p, diff_dst_memory_p, diff_src_memory_p);

    std::vector<primitive> pipeline{*softmax_bwd_p};
    stream(stream::kind::eager).submit(pipeline).wait();
  }
};
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

REGISTER_OP_KERNEL(softmax, MKLDNN, ::paddle::platform::CPUPlace,
                   ops::SoftmaxMKLDNNKernel<float>);
REGISTER_OP_KERNEL(softmax_grad, MKLDNN, ::paddle::platform::CPUPlace,
                   ops::SoftmaxMKLDNNGradKernel<float>);
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  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.txt
 *
 *  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 "itkOpenCLEventList.h"
#include "itkOpenCLMacro.h"
#include "itkOpenCLContext.h"

namespace itk
{
OpenCLEventList::OpenCLEventList( const OpenCLEvent & event )
{
  cl_event id = event.GetEventId();

  if( id )
  {
    clRetainEvent( id );
    this->m_Events.push_back( id );
  }
}

//------------------------------------------------------------------------------
OpenCLEventList::OpenCLEventList( const OpenCLEventList & other ) :
  m_Events( other.m_Events )
{
  for( std::size_t index = 0; index < this->m_Events.size(); ++index )
  {
    clRetainEvent( this->m_Events[ index ] );
  }
}

//------------------------------------------------------------------------------
OpenCLEventList::~OpenCLEventList()
{
  for( std::size_t index = 0; index < this->m_Events.size(); ++index )
  {
    clReleaseEvent( this->m_Events[ index ] );
  }
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator=( const OpenCLEventList & other )
{
  if( this != &other )
  {
    for( std::size_t index = 0; index < this->m_Events.size(); ++index )
    {
      clReleaseEvent( this->m_Events[ index ] );
    }
    this->m_Events = other.m_Events;
    for( std::size_t index = 0; index < this->m_Events.size(); ++index )
    {
      clRetainEvent( this->m_Events[ index ] );
    }
  }
  return *this;
}

//------------------------------------------------------------------------------
void
OpenCLEventList::Append( const OpenCLEvent & event )
{
  cl_event id = event.GetEventId();

  if( id )
  {
    clRetainEvent( id );
    this->m_Events.push_back( id );
  }
}

//------------------------------------------------------------------------------
void
OpenCLEventList::Append( const OpenCLEventList & other )
{
  for( std::size_t index = 0; index < other.m_Events.size(); ++index )
  {
    cl_event id = other.m_Events[ index ];
    clRetainEvent( id );
    this->m_Events.push_back( id );
  }
}

//------------------------------------------------------------------------------
void
OpenCLEventList::Remove( const OpenCLEvent & event )
{
  OpenCLEventListArrayType::iterator it;

  for( it = this->m_Events.begin(); it < this->m_Events.end(); ++it )
  {
    if( *it == event.GetEventId() )
    {
      clReleaseEvent( *it );
      this->m_Events.erase( it );
    }
  }
}

//------------------------------------------------------------------------------
OpenCLEvent
OpenCLEventList::Get( const std::size_t index ) const
{
  if( index < this->m_Events.size() )
  {
    cl_event id = this->m_Events[ index ];
    clRetainEvent( id );
    return OpenCLEvent( id );
  }
  else
  {
    return OpenCLEvent();
  }
}

//------------------------------------------------------------------------------
bool
OpenCLEventList::Contains( const OpenCLEvent & event ) const
{
  OpenCLEventListArrayType::const_iterator it;

  for( it = this->m_Events.begin(); it < this->m_Events.end(); ++it )
  {
    if( *it == event.GetEventId() )
    {
      return true;
    }
  }
  return false;
}

//------------------------------------------------------------------------------
const cl_event *
OpenCLEventList::GetEventData() const
{
  return this->m_Events.empty() ? 0 : &this->m_Events[ 0 ];
}

//------------------------------------------------------------------------------
const OpenCLEventList::OpenCLEventListArrayType &
OpenCLEventList::GetEventArray() const
{
  return this->m_Events;
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator+=( const OpenCLEvent & event )
{
  this->Append( event );
  return *this;
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator+=( const OpenCLEventList & other )
{
  this->Append( other );
  return *this;
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator<<( const OpenCLEvent & event )
{
  this->Append( event );
  return *this;
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator<<( const OpenCLEventList & other )
{
  this->Append( other );
  return *this;
}

//------------------------------------------------------------------------------
cl_int
OpenCLEventList::WaitForFinished()
{
  if( this->m_Events.empty() )
  {
    return 0;
  }

  const cl_int error = clWaitForEvents( this->GetSize(), this->GetEventData() );
  if( error != CL_SUCCESS )
  {
    itkOpenCLErrorMacroGeneric( << "OpenCLEventList::WaitForFinished:"
                                << OpenCLContext::GetErrorName( error ) );
  }
  return error;
}

//------------------------------------------------------------------------------
//! Operator ==
bool
operator==( const OpenCLEventList & lhs, const OpenCLEventList & rhs )
{
  if( &rhs == &lhs )
  {
    return true;
  }

  const OpenCLEventList::OpenCLEventListArrayType & eventsArrayLHS = lhs.GetEventArray();
  const OpenCLEventList::OpenCLEventListArrayType & eventsArrayRHS = rhs.GetEventArray();

  if( eventsArrayLHS.size() != eventsArrayRHS.size() )
  {
    return false;
  }

  OpenCLEventList::OpenCLEventListArrayType::const_iterator ilhs;
  OpenCLEventList::OpenCLEventListArrayType::const_iterator irhs;
  for( ilhs = eventsArrayLHS.begin(), irhs = eventsArrayRHS.begin();
    ilhs < eventsArrayLHS.end() && irhs < eventsArrayRHS.end();
    ++ilhs, ++irhs )
  {
    if( *ilhs != *irhs )
    {
      return false;
    }
  }

  return true;
}

//------------------------------------------------------------------------------
//! Operator !=
bool
operator!=( const OpenCLEventList & lhs, const OpenCLEventList & rhs )
{
  return !( lhs == rhs );
}

} // namespace itk
<commit_msg>BUG: The potential bug has been found by the cppcheck software (http://cppcheck.sourceforge.net/). After the event has been erased we just have to stop iterating.<commit_after>/*=========================================================================
 *
 *  Copyright UMC Utrecht and contributors
 *
 *  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.txt
 *
 *  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 "itkOpenCLEventList.h"
#include "itkOpenCLMacro.h"
#include "itkOpenCLContext.h"

namespace itk
{
OpenCLEventList::OpenCLEventList( const OpenCLEvent & event )
{
  cl_event id = event.GetEventId();

  if( id )
  {
    clRetainEvent( id );
    this->m_Events.push_back( id );
  }
}

//------------------------------------------------------------------------------
OpenCLEventList::OpenCLEventList( const OpenCLEventList & other ) :
  m_Events( other.m_Events )
{
  for( std::size_t index = 0; index < this->m_Events.size(); ++index )
  {
    clRetainEvent( this->m_Events[ index ] );
  }
}

//------------------------------------------------------------------------------
OpenCLEventList::~OpenCLEventList()
{
  for( std::size_t index = 0; index < this->m_Events.size(); ++index )
  {
    clReleaseEvent( this->m_Events[ index ] );
  }
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator=( const OpenCLEventList & other )
{
  if( this != &other )
  {
    for( std::size_t index = 0; index < this->m_Events.size(); ++index )
    {
      clReleaseEvent( this->m_Events[ index ] );
    }
    this->m_Events = other.m_Events;
    for( std::size_t index = 0; index < this->m_Events.size(); ++index )
    {
      clRetainEvent( this->m_Events[ index ] );
    }
  }
  return *this;
}

//------------------------------------------------------------------------------
void
OpenCLEventList::Append( const OpenCLEvent & event )
{
  cl_event id = event.GetEventId();

  if( id )
  {
    clRetainEvent( id );
    this->m_Events.push_back( id );
  }
}

//------------------------------------------------------------------------------
void
OpenCLEventList::Append( const OpenCLEventList & other )
{
  for( std::size_t index = 0; index < other.m_Events.size(); ++index )
  {
    cl_event id = other.m_Events[ index ];
    clRetainEvent( id );
    this->m_Events.push_back( id );
  }
}

//------------------------------------------------------------------------------
void
OpenCLEventList::Remove( const OpenCLEvent & event )
{
  OpenCLEventListArrayType::iterator it;

  for( it = this->m_Events.begin(); it < this->m_Events.end(); ++it )
  {
    if( *it == event.GetEventId() )
    {
      clReleaseEvent( *it );
      this->m_Events.erase( it );
      break;
    }
  }
}

//------------------------------------------------------------------------------
OpenCLEvent
OpenCLEventList::Get( const std::size_t index ) const
{
  if( index < this->m_Events.size() )
  {
    cl_event id = this->m_Events[ index ];
    clRetainEvent( id );
    return OpenCLEvent( id );
  }
  else
  {
    return OpenCLEvent();
  }
}

//------------------------------------------------------------------------------
bool
OpenCLEventList::Contains( const OpenCLEvent & event ) const
{
  OpenCLEventListArrayType::const_iterator it;

  for( it = this->m_Events.begin(); it < this->m_Events.end(); ++it )
  {
    if( *it == event.GetEventId() )
    {
      return true;
    }
  }
  return false;
}

//------------------------------------------------------------------------------
const cl_event *
OpenCLEventList::GetEventData() const
{
  return this->m_Events.empty() ? 0 : &this->m_Events[ 0 ];
}

//------------------------------------------------------------------------------
const OpenCLEventList::OpenCLEventListArrayType &
OpenCLEventList::GetEventArray() const
{
  return this->m_Events;
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator+=( const OpenCLEvent & event )
{
  this->Append( event );
  return *this;
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator+=( const OpenCLEventList & other )
{
  this->Append( other );
  return *this;
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator<<( const OpenCLEvent & event )
{
  this->Append( event );
  return *this;
}

//------------------------------------------------------------------------------
OpenCLEventList &
OpenCLEventList::operator<<( const OpenCLEventList & other )
{
  this->Append( other );
  return *this;
}

//------------------------------------------------------------------------------
cl_int
OpenCLEventList::WaitForFinished()
{
  if( this->m_Events.empty() )
  {
    return 0;
  }

  const cl_int error = clWaitForEvents( this->GetSize(), this->GetEventData() );
  if( error != CL_SUCCESS )
  {
    itkOpenCLErrorMacroGeneric( << "OpenCLEventList::WaitForFinished:"
                                << OpenCLContext::GetErrorName( error ) );
  }
  return error;
}

//------------------------------------------------------------------------------
//! Operator ==
bool
operator==( const OpenCLEventList & lhs, const OpenCLEventList & rhs )
{
  if( &rhs == &lhs )
  {
    return true;
  }

  const OpenCLEventList::OpenCLEventListArrayType & eventsArrayLHS = lhs.GetEventArray();
  const OpenCLEventList::OpenCLEventListArrayType & eventsArrayRHS = rhs.GetEventArray();

  if( eventsArrayLHS.size() != eventsArrayRHS.size() )
  {
    return false;
  }

  OpenCLEventList::OpenCLEventListArrayType::const_iterator ilhs;
  OpenCLEventList::OpenCLEventListArrayType::const_iterator irhs;
  for( ilhs = eventsArrayLHS.begin(), irhs = eventsArrayRHS.begin();
    ilhs < eventsArrayLHS.end() && irhs < eventsArrayRHS.end();
    ++ilhs, ++irhs )
  {
    if( *ilhs != *irhs )
    {
      return false;
    }
  }

  return true;
}

//------------------------------------------------------------------------------
//! Operator !=
bool
operator!=( const OpenCLEventList & lhs, const OpenCLEventList & rhs )
{
  return !( lhs == rhs );
}

} // namespace itk
<|endoftext|>