<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "AudioMenu.h"

/* system implementation headers */
#include <string>
#include <vector>

/* common implementation headers */
#include "TextUtils.h"

/* local implementation headers */
#include "MainMenu.h"
#include "sound.h"

AudioMenu::AudioMenu()
{
  // add controls
  std::vector<HUDuiControl*>& list = getControls();
  std::string currentDriver = BZDB.get("audioDriver");

  HUDuiLabel* label = new HUDuiLabel;
  label->setFont(MainMenu::getFont());
  label->setString("Audio Setting");
  list.push_back(label);

  HUDuiList* option = new HUDuiList;

  option = new HUDuiList;
  std::vector<std::string>* options;

  option = new HUDuiList;
  option->setFont(MainMenu::getFont());
  option->setLabel("Sound Volume:");
  option->setCallback(callback, (void*)"s");
  options = &option->getList();
  if (isSoundOpen()) {
    options->push_back(std::string("Off"));
    options->push_back(std::string("1"));
    options->push_back(std::string("2"));
    options->push_back(std::string("3"));
    options->push_back(std::string("4"));
    options->push_back(std::string("5"));
    options->push_back(std::string("6"));
    options->push_back(std::string("7"));
    options->push_back(std::string("8"));
    options->push_back(std::string("9"));
    options->push_back(std::string("10"));
  }
  else {
    options->push_back(std::string("Unavailable"));
  }
  option->update();
  list.push_back(option);

  driver = new HUDuiTypeIn;
  driver->setFont(MainMenu::getFont());
  driver->setLabel("Driver:");
  driver->setMaxLength(10);
  driver->setString(currentDriver);
  list.push_back(driver);

  initNavigation(list, 1,list.size()-1);
}

AudioMenu::~AudioMenu()
{
}

void			AudioMenu::execute()
{
  HUDuiControl* focus = HUDui::getFocus();
  if (focus == driver) {
    BZDB.set("audioDriver", driver->getString().c_str());
  }
}

void			AudioMenu::resize(int width, int height)
{
  HUDDialog::resize(width, height);
  int i;

  // use a big font for title, smaller font for the rest
  const float titleFontWidth = (float)height / 10.0f;
  const float titleFontHeight = (float)height / 10.0f;
  const float fontWidth = (float)height / 30.0f;
  const float fontHeight = (float)height / 30.0f;

  // reposition title
  std::vector<HUDuiControl*>& list = getControls();
  HUDuiLabel* title = (HUDuiLabel*)list[0];
  title->setFontSize(titleFontWidth, titleFontHeight);
  const OpenGLTexFont& titleFont = title->getFont();
  const float titleWidth = titleFont.getWidth(title->getString());
  float x = 0.5f * ((float)width - titleWidth);
  float y = (float)height - titleFont.getHeight();
  title->setPosition(x, y);

  // reposition options
  x = 0.5f * ((float)width + 0.5f * titleWidth);
  y -= 0.6f * titleFont.getHeight();
  const int count = list.size();
  for (i = 1; i < count; i++) {
    list[i]->setFontSize(fontWidth, fontHeight);
    list[i]->setPosition(x, y);
    y -= 1.0f * list[i]->getFont().getHeight();
  }

  i = 1;
  // sound
  ((HUDuiList*)list[i++])->setIndex(getSoundVolume());
}

void			AudioMenu::callback(HUDuiControl* w, void* data) {
  HUDuiList* list = (HUDuiList*)w;
  std::vector<std::string> *options = &list->getList();
  std::string selectedOption = (*options)[list->getIndex()];
  switch (((const char*)data)[0]) {
    case 's':
      BZDB.set("volume", string_util::format("%d", list->getIndex()));
      setSoundVolume(list->getIndex());
      break;

  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>Use a slider (and "off") for volume control<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "AudioMenu.h"

/* system implementation headers */
#include <string>
#include <vector>

/* common implementation headers */
#include "TextUtils.h"

/* local implementation headers */
#include "MainMenu.h"
#include "sound.h"

AudioMenu::AudioMenu()
{
  // add controls
  std::vector<HUDuiControl*>& list = getControls();
  std::string currentDriver = BZDB.get("audioDriver");

  HUDuiLabel* label = new HUDuiLabel;
  label->setFont(MainMenu::getFont());
  label->setString("Audio Setting");
  list.push_back(label);

  HUDuiList* option = new HUDuiList;

  option = new HUDuiList;
  std::vector<std::string>* options;

  option = new HUDuiList;
  option->setFont(MainMenu::getFont());
  option->setLabel("Sound Volume:");
  option->setCallback(callback, (void*)"s");
  options = &option->getList();
  if (isSoundOpen()) {
    options->push_back(std::string("Off"));
    option->createSlider(10);
  }
  else {
    options->push_back(std::string("Unavailable"));
  }
  option->update();
  list.push_back(option);

  driver = new HUDuiTypeIn;
  driver->setFont(MainMenu::getFont());
  driver->setLabel("Driver:");
  driver->setMaxLength(10);
  driver->setString(currentDriver);
  list.push_back(driver);

  initNavigation(list, 1,list.size()-1);
}

AudioMenu::~AudioMenu()
{
}

void			AudioMenu::execute()
{
  HUDuiControl* focus = HUDui::getFocus();
  if (focus == driver) {
    BZDB.set("audioDriver", driver->getString().c_str());
  }
}

void			AudioMenu::resize(int width, int height)
{
  HUDDialog::resize(width, height);
  int i;

  // use a big font for title, smaller font for the rest
  const float titleFontWidth = (float)height / 10.0f;
  const float titleFontHeight = (float)height / 10.0f;
  const float fontWidth = (float)height / 30.0f;
  const float fontHeight = (float)height / 30.0f;

  // reposition title
  std::vector<HUDuiControl*>& list = getControls();
  HUDuiLabel* title = (HUDuiLabel*)list[0];
  title->setFontSize(titleFontWidth, titleFontHeight);
  const OpenGLTexFont& titleFont = title->getFont();
  const float titleWidth = titleFont.getWidth(title->getString());
  float x = 0.5f * ((float)width - titleWidth);
  float y = (float)height - titleFont.getHeight();
  title->setPosition(x, y);

  // reposition options
  x = 0.5f * ((float)width + 0.5f * titleWidth);
  y -= 0.6f * titleFont.getHeight();
  const int count = list.size();
  for (i = 1; i < count; i++) {
    list[i]->setFontSize(fontWidth, fontHeight);
    list[i]->setPosition(x, y);
    y -= 1.0f * list[i]->getFont().getHeight();
  }

  i = 1;
  // sound
  ((HUDuiList*)list[i++])->setIndex(getSoundVolume());
}

void			AudioMenu::callback(HUDuiControl* w, void* data) {
  HUDuiList* list = (HUDuiList*)w;
  std::vector<std::string> *options = &list->getList();
  std::string selectedOption = (*options)[list->getIndex()];
  switch (((const char*)data)[0]) {
    case 's':
      BZDB.set("volume", string_util::format("%d", list->getIndex()));
      setSoundVolume(list->getIndex());
      break;

  }
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#include <QDateTime>
#include <QList>
#include <QDebug>

#include "qamqptable.h"
#include "qamqpglobal.h"
#include "qamqpframe_p.h"

QReadWriteLock QAmqpFrame::lock_;
int QAmqpFrame::writeTimeout_ = 1000;

QAmqpFrame::QAmqpFrame(FrameType type)
    : size_(0),
      type_(type),
      channel_(0)
{
}

QAmqpFrame::FrameType QAmqpFrame::type() const
{
    return static_cast<QAmqpFrame::FrameType>(type_);
}

QAmqpFrame::~QAmqpFrame()
{
}

void QAmqpFrame::setChannel(quint16 channel)
{
    channel_ = channel;
}

int QAmqpFrame::writeTimeout()
{
    QReadLocker locker(&lock_);
    return writeTimeout_;
}

void QAmqpFrame::setWriteTimeout(int msecs)
{
    QWriteLocker locker(&lock_);
    writeTimeout_ = msecs;
}

quint16 QAmqpFrame::channel() const
{
    return channel_;
}

qint32 QAmqpFrame::size() const
{
    return 0;
}

/*
void QAmqpFrame::readEnd(QDataStream &stream)
{
    unsigned char end_  = 0;
    stream.readRawData(reinterpret_cast<char*>(&end_), sizeof(end_));
    if (end_ != FRAME_END)
        qAmqpDebug("Wrong end of frame");
}
*/

QDataStream &operator<<(QDataStream &stream, const QAmqpFrame &frame)
{
    // write header
    stream << frame.type_;
    stream << frame.channel_;
    stream << frame.size();

    frame.writePayload(stream);

    // write end
    stream << qint8(QAmqpFrame::FRAME_END);
    stream.device()->waitForBytesWritten(QAmqpFrame::writeTimeout());
    return stream;
}

QDataStream &operator>>(QDataStream &stream, QAmqpFrame &frame)
{
    stream >> frame.type_;
    stream >> frame.channel_;
    stream >> frame.size_;
    frame.readPayload(stream);
    return stream;
}

//////////////////////////////////////////////////////////////////////////

QAmqpMethodFrame::QAmqpMethodFrame()
    : QAmqpFrame(QAmqpFrame::Method),
      methodClass_(0),
      id_(0)
{
}

QAmqpMethodFrame::QAmqpMethodFrame(MethodClass methodClass, qint16 id)
    : QAmqpFrame(QAmqpFrame::Method),
      methodClass_(methodClass),
      id_(id)
{
}

QAmqpFrame::MethodClass QAmqpMethodFrame::methodClass() const
{
    return MethodClass(methodClass_);
}

qint16 QAmqpMethodFrame::id() const
{
    return id_;
}

qint32 QAmqpMethodFrame::size() const
{
    return sizeof(id_) + sizeof(methodClass_) + arguments_.size();
}

void QAmqpMethodFrame::setArguments(const QByteArray &data)
{
    arguments_ = data;
}

QByteArray QAmqpMethodFrame::arguments() const
{
    return arguments_;
}

void QAmqpMethodFrame::readPayload(QDataStream &stream)
{
    stream >> methodClass_;
    stream >> id_;

    arguments_.resize(size_ - (sizeof(id_) + sizeof(methodClass_)));
    stream.readRawData(arguments_.data(), arguments_.size());
}

void QAmqpMethodFrame::writePayload(QDataStream &stream) const
{
    stream << quint16(methodClass_);
    stream << quint16(id_);
    stream.writeRawData(arguments_.data(), arguments_.size());
}

//////////////////////////////////////////////////////////////////////////

QVariant QAmqpFrame::readAmqpField(QDataStream &s, QAmqpMetaType::ValueType type)
{
    switch (type) {
    case QAmqpMetaType::Boolean:
    {
        quint8 octet = 0;
        s >> octet;
        return QVariant::fromValue<bool>(octet > 0);
    }
    case QAmqpMetaType::ShortShortUint:
    {
        quint8 octet = 0;
        s >> octet;
        return QVariant::fromValue<int>(octet);
    }
    case QAmqpMetaType::ShortUint:
    {
        quint16 tmp_value = 0;
        s >> tmp_value;
        return QVariant::fromValue<uint>(tmp_value);
    }
    case QAmqpMetaType::LongUint:
    {
        quint32 tmp_value = 0;
        s >> tmp_value;
        return QVariant::fromValue<uint>(tmp_value);
    }
    case QAmqpMetaType::LongLongUint:
    {
        qulonglong v = 0 ;
        s >> v;
        return v;
    }
    case QAmqpMetaType::ShortString:
    {
        qint8 size = 0;
        QByteArray buffer;

        s >> size;
        buffer.resize(size);
        s.readRawData(buffer.data(), buffer.size());
        return QString::fromLatin1(buffer.data(), size);
    }
    case QAmqpMetaType::LongString:
    {
        quint32 size = 0;
        QByteArray buffer;

        s >> size;
        buffer.resize(size);
        s.readRawData(buffer.data(), buffer.size());
        return QString::fromUtf8(buffer.data(), buffer.size());
    }
    case QAmqpMetaType::Timestamp:
    {
        qulonglong tmp_value;
        s >> tmp_value;
        return QDateTime::fromMSecsSinceEpoch(tmp_value);
    }
    case QAmqpMetaType::Hash:
    {
        QAmqpTable table;
        s >> table;
        return table;
    }
    case QAmqpMetaType::Void:
        return QVariant();
    default:
        qAmqpDebug() << Q_FUNC_INFO << "unsupported value type: " << type;
    }

    return QVariant();
}

void QAmqpFrame::writeAmqpField(QDataStream &s, QAmqpMetaType::ValueType type, const QVariant &value)
{
    switch (type) {
    case QAmqpMetaType::Boolean:
        s << (value.toBool() ? qint8(1) : qint8(0));
        break;
    case QAmqpMetaType::ShortShortUint:
        s << qint8(value.toUInt());
        break;
    case QAmqpMetaType::ShortUint:
        s << quint16(value.toUInt());
        break;
    case QAmqpMetaType::LongUint:
        s << quint32(value.toUInt());
        break;
    case QAmqpMetaType::LongLongUint:
        s << qulonglong(value.toULongLong());
        break;
    case QAmqpMetaType::ShortString:
    {
        QString str = value.toString();
        if (str.length() >= 256) {
            qAmqpDebug() << Q_FUNC_INFO << "invalid shortstr length: " << str.length();
        }

        s << quint8(str.length());
        s.writeRawData(str.toUtf8().data(), str.length());
    }
        break;
    case QAmqpMetaType::LongString:
    {
        QString str = value.toString();
        s << quint32(str.length());
        s.writeRawData(str.toLatin1().data(), str.length());
    }
        break;
    case QAmqpMetaType::Timestamp:
        s << qulonglong(value.toDateTime().toMSecsSinceEpoch());
        break;
    case QAmqpMetaType::Hash:
    {
        QAmqpTable table(value.toHash());
        s << table;
    }
        break;
    default:
        qAmqpDebug() << Q_FUNC_INFO << "unsupported value type: " << type;
    }
}

//////////////////////////////////////////////////////////////////////////

QAmqpContentFrame::QAmqpContentFrame()
    : QAmqpFrame(QAmqpFrame::Header)
{
}

QAmqpContentFrame::QAmqpContentFrame(QAmqpFrame::MethodClass methodClass)
    : QAmqpFrame(QAmqpFrame::Header)
{
    methodClass_ = methodClass;
}

QAmqpFrame::MethodClass QAmqpContentFrame::methodClass() const
{
    return MethodClass(methodClass_);
}

qint32 QAmqpContentFrame::size() const
{
    QDataStream out(&buffer_, QIODevice::WriteOnly);
    buffer_.clear();
    out << qint16(methodClass_);
    out << qint16(0); //weight
    out << qlonglong(bodySize_);

    qint16 prop_ = 0;
    foreach (int p, properties_.keys())
        prop_ |= p;
    out << prop_;

    if (prop_ & QAmqpMessage::ContentType)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::ContentType]);

    if (prop_ & QAmqpMessage::ContentEncoding)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::ContentEncoding]);

    if (prop_ & QAmqpMessage::Headers)
        writeAmqpField(out, QAmqpMetaType::Hash, properties_[QAmqpMessage::Headers]);

    if (prop_ & QAmqpMessage::DeliveryMode)
        writeAmqpField(out, QAmqpMetaType::ShortShortUint, properties_[QAmqpMessage::DeliveryMode]);

    if (prop_ & QAmqpMessage::Priority)
        writeAmqpField(out, QAmqpMetaType::ShortShortUint, properties_[QAmqpMessage::Priority]);

    if (prop_ & QAmqpMessage::CorrelationId)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::CorrelationId]);

    if (prop_ & QAmqpMessage::ReplyTo)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::ReplyTo]);

    if (prop_ & QAmqpMessage::Expiration)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::Expiration]);

    if (prop_ & QAmqpMessage::MessageId)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::MessageId]);

    if (prop_ & QAmqpMessage::Timestamp)
        writeAmqpField(out, QAmqpMetaType::Timestamp, properties_[QAmqpMessage::Timestamp]);

    if (prop_ & QAmqpMessage::Type)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::Type]);

    if (prop_ & QAmqpMessage::UserId)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::UserId]);

    if (prop_ & QAmqpMessage::AppId)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::AppId]);

    if (prop_ & QAmqpMessage::ClusterID)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::ClusterID]);

    return buffer_.size();
}

qlonglong QAmqpContentFrame::bodySize() const
{
    return bodySize_;
}

void QAmqpContentFrame::setBodySize(qlonglong size)
{
    bodySize_ = size;
}

void QAmqpContentFrame::setProperty(QAmqpMessage::Property prop, const QVariant &value)
{
    properties_[prop] = value;
}

QVariant QAmqpContentFrame::property(QAmqpMessage::Property prop) const
{
    return properties_.value(prop);
}

void QAmqpContentFrame::writePayload(QDataStream &out) const
{
    out.writeRawData(buffer_.data(), buffer_.size());
}

void QAmqpContentFrame::readPayload(QDataStream &in)
{
    in >> methodClass_;
    in.skipRawData(2); //weight
    in >> bodySize_;
    qint16 flags_ = 0;
    in >> flags_;
    if (flags_ & QAmqpMessage::ContentType)
        properties_[QAmqpMessage::ContentType] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::ContentEncoding)
        properties_[QAmqpMessage::ContentEncoding] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::Headers)
        properties_[QAmqpMessage::Headers] = readAmqpField(in, QAmqpMetaType::Hash);

    if (flags_ & QAmqpMessage::DeliveryMode)
        properties_[QAmqpMessage::DeliveryMode] = readAmqpField(in, QAmqpMetaType::ShortShortUint);

    if (flags_ & QAmqpMessage::Priority)
        properties_[QAmqpMessage::Priority] = readAmqpField(in, QAmqpMetaType::ShortShortUint);

    if (flags_ & QAmqpMessage::CorrelationId)
        properties_[QAmqpMessage::CorrelationId] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::ReplyTo)
        properties_[QAmqpMessage::ReplyTo] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::Expiration)
        properties_[QAmqpMessage::Expiration] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::MessageId)
        properties_[QAmqpMessage::MessageId] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::Timestamp)
        properties_[QAmqpMessage::Timestamp] = readAmqpField(in, QAmqpMetaType::Timestamp);

    if (flags_ & QAmqpMessage::Type)
        properties_[QAmqpMessage::Type] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::UserId)
        properties_[QAmqpMessage::UserId] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::AppId)
        properties_[QAmqpMessage::AppId] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::ClusterID)
        properties_[QAmqpMessage::ClusterID] = readAmqpField(in, QAmqpMetaType::ShortString);
}

//////////////////////////////////////////////////////////////////////////

QAmqpContentBodyFrame::QAmqpContentBodyFrame()
    : QAmqpFrame(QAmqpFrame::Body)
{
}

void QAmqpContentBodyFrame::setBody(const QByteArray &data)
{
    body_ = data;
}

QByteArray QAmqpContentBodyFrame::body() const
{
    return body_;
}

void QAmqpContentBodyFrame::writePayload(QDataStream &out) const
{
    out.writeRawData(body_.data(), body_.size());
}

void QAmqpContentBodyFrame::readPayload(QDataStream &in)
{
    body_.resize(size_);
    in.readRawData(body_.data(), body_.size());
}

qint32 QAmqpContentBodyFrame::size() const
{
    return body_.size();
}

//////////////////////////////////////////////////////////////////////////

QAmqpHeartbeatFrame::QAmqpHeartbeatFrame()
    : QAmqpFrame(QAmqpFrame::Heartbeat)
{
}

void QAmqpHeartbeatFrame::readPayload(QDataStream &stream)
{
    Q_UNUSED(stream)
}

void QAmqpHeartbeatFrame::writePayload(QDataStream &stream) const
{
    Q_UNUSED(stream)
}
<commit_msg>timestamp in AMQP-0-9-1 should be seconds since 1970-01-01 other than miliseconds<commit_after>#include <QDateTime>
#include <QList>
#include <QDebug>

#include "qamqptable.h"
#include "qamqpglobal.h"
#include "qamqpframe_p.h"

QReadWriteLock QAmqpFrame::lock_;
int QAmqpFrame::writeTimeout_ = 1000;

QAmqpFrame::QAmqpFrame(FrameType type)
    : size_(0),
      type_(type),
      channel_(0)
{
}

QAmqpFrame::FrameType QAmqpFrame::type() const
{
    return static_cast<QAmqpFrame::FrameType>(type_);
}

QAmqpFrame::~QAmqpFrame()
{
}

void QAmqpFrame::setChannel(quint16 channel)
{
    channel_ = channel;
}

int QAmqpFrame::writeTimeout()
{
    QReadLocker locker(&lock_);
    return writeTimeout_;
}

void QAmqpFrame::setWriteTimeout(int msecs)
{
    QWriteLocker locker(&lock_);
    writeTimeout_ = msecs;
}

quint16 QAmqpFrame::channel() const
{
    return channel_;
}

qint32 QAmqpFrame::size() const
{
    return 0;
}

/*
void QAmqpFrame::readEnd(QDataStream &stream)
{
    unsigned char end_  = 0;
    stream.readRawData(reinterpret_cast<char*>(&end_), sizeof(end_));
    if (end_ != FRAME_END)
        qAmqpDebug("Wrong end of frame");
}
*/

QDataStream &operator<<(QDataStream &stream, const QAmqpFrame &frame)
{
    // write header
    stream << frame.type_;
    stream << frame.channel_;
    stream << frame.size();

    frame.writePayload(stream);

    // write end
    stream << qint8(QAmqpFrame::FRAME_END);
    stream.device()->waitForBytesWritten(QAmqpFrame::writeTimeout());
    return stream;
}

QDataStream &operator>>(QDataStream &stream, QAmqpFrame &frame)
{
    stream >> frame.type_;
    stream >> frame.channel_;
    stream >> frame.size_;
    frame.readPayload(stream);
    return stream;
}

//////////////////////////////////////////////////////////////////////////

QAmqpMethodFrame::QAmqpMethodFrame()
    : QAmqpFrame(QAmqpFrame::Method),
      methodClass_(0),
      id_(0)
{
}

QAmqpMethodFrame::QAmqpMethodFrame(MethodClass methodClass, qint16 id)
    : QAmqpFrame(QAmqpFrame::Method),
      methodClass_(methodClass),
      id_(id)
{
}

QAmqpFrame::MethodClass QAmqpMethodFrame::methodClass() const
{
    return MethodClass(methodClass_);
}

qint16 QAmqpMethodFrame::id() const
{
    return id_;
}

qint32 QAmqpMethodFrame::size() const
{
    return sizeof(id_) + sizeof(methodClass_) + arguments_.size();
}

void QAmqpMethodFrame::setArguments(const QByteArray &data)
{
    arguments_ = data;
}

QByteArray QAmqpMethodFrame::arguments() const
{
    return arguments_;
}

void QAmqpMethodFrame::readPayload(QDataStream &stream)
{
    stream >> methodClass_;
    stream >> id_;

    arguments_.resize(size_ - (sizeof(id_) + sizeof(methodClass_)));
    stream.readRawData(arguments_.data(), arguments_.size());
}

void QAmqpMethodFrame::writePayload(QDataStream &stream) const
{
    stream << quint16(methodClass_);
    stream << quint16(id_);
    stream.writeRawData(arguments_.data(), arguments_.size());
}

//////////////////////////////////////////////////////////////////////////

QVariant QAmqpFrame::readAmqpField(QDataStream &s, QAmqpMetaType::ValueType type)
{
    switch (type) {
    case QAmqpMetaType::Boolean:
    {
        quint8 octet = 0;
        s >> octet;
        return QVariant::fromValue<bool>(octet > 0);
    }
    case QAmqpMetaType::ShortShortUint:
    {
        quint8 octet = 0;
        s >> octet;
        return QVariant::fromValue<int>(octet);
    }
    case QAmqpMetaType::ShortUint:
    {
        quint16 tmp_value = 0;
        s >> tmp_value;
        return QVariant::fromValue<uint>(tmp_value);
    }
    case QAmqpMetaType::LongUint:
    {
        quint32 tmp_value = 0;
        s >> tmp_value;
        return QVariant::fromValue<uint>(tmp_value);
    }
    case QAmqpMetaType::LongLongUint:
    {
        qulonglong v = 0 ;
        s >> v;
        return v;
    }
    case QAmqpMetaType::ShortString:
    {
        qint8 size = 0;
        QByteArray buffer;

        s >> size;
        buffer.resize(size);
        s.readRawData(buffer.data(), buffer.size());
        return QString::fromLatin1(buffer.data(), size);
    }
    case QAmqpMetaType::LongString:
    {
        quint32 size = 0;
        QByteArray buffer;

        s >> size;
        buffer.resize(size);
        s.readRawData(buffer.data(), buffer.size());
        return QString::fromUtf8(buffer.data(), buffer.size());
    }
    case QAmqpMetaType::Timestamp:
    {
        qulonglong tmp_value;
        s >> tmp_value;
        return QDateTime::fromTime_t(tmp_value);
    }
    case QAmqpMetaType::Hash:
    {
        QAmqpTable table;
        s >> table;
        return table;
    }
    case QAmqpMetaType::Void:
        return QVariant();
    default:
        qAmqpDebug() << Q_FUNC_INFO << "unsupported value type: " << type;
    }

    return QVariant();
}

void QAmqpFrame::writeAmqpField(QDataStream &s, QAmqpMetaType::ValueType type, const QVariant &value)
{
    switch (type) {
    case QAmqpMetaType::Boolean:
        s << (value.toBool() ? qint8(1) : qint8(0));
        break;
    case QAmqpMetaType::ShortShortUint:
        s << qint8(value.toUInt());
        break;
    case QAmqpMetaType::ShortUint:
        s << quint16(value.toUInt());
        break;
    case QAmqpMetaType::LongUint:
        s << quint32(value.toUInt());
        break;
    case QAmqpMetaType::LongLongUint:
        s << qulonglong(value.toULongLong());
        break;
    case QAmqpMetaType::ShortString:
    {
        QString str = value.toString();
        if (str.length() >= 256) {
            qAmqpDebug() << Q_FUNC_INFO << "invalid shortstr length: " << str.length();
        }

        s << quint8(str.length());
        s.writeRawData(str.toUtf8().data(), str.length());
    }
        break;
    case QAmqpMetaType::LongString:
    {
        QString str = value.toString();
        s << quint32(str.length());
        s.writeRawData(str.toLatin1().data(), str.length());
    }
        break;
    case QAmqpMetaType::Timestamp:
        s << qulonglong(value.toDateTime().toTime_t());
        break;
    case QAmqpMetaType::Hash:
    {
        QAmqpTable table(value.toHash());
        s << table;
    }
        break;
    default:
        qAmqpDebug() << Q_FUNC_INFO << "unsupported value type: " << type;
    }
}

//////////////////////////////////////////////////////////////////////////

QAmqpContentFrame::QAmqpContentFrame()
    : QAmqpFrame(QAmqpFrame::Header)
{
}

QAmqpContentFrame::QAmqpContentFrame(QAmqpFrame::MethodClass methodClass)
    : QAmqpFrame(QAmqpFrame::Header)
{
    methodClass_ = methodClass;
}

QAmqpFrame::MethodClass QAmqpContentFrame::methodClass() const
{
    return MethodClass(methodClass_);
}

qint32 QAmqpContentFrame::size() const
{
    QDataStream out(&buffer_, QIODevice::WriteOnly);
    buffer_.clear();
    out << qint16(methodClass_);
    out << qint16(0); //weight
    out << qlonglong(bodySize_);

    qint16 prop_ = 0;
    foreach (int p, properties_.keys())
        prop_ |= p;
    out << prop_;

    if (prop_ & QAmqpMessage::ContentType)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::ContentType]);

    if (prop_ & QAmqpMessage::ContentEncoding)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::ContentEncoding]);

    if (prop_ & QAmqpMessage::Headers)
        writeAmqpField(out, QAmqpMetaType::Hash, properties_[QAmqpMessage::Headers]);

    if (prop_ & QAmqpMessage::DeliveryMode)
        writeAmqpField(out, QAmqpMetaType::ShortShortUint, properties_[QAmqpMessage::DeliveryMode]);

    if (prop_ & QAmqpMessage::Priority)
        writeAmqpField(out, QAmqpMetaType::ShortShortUint, properties_[QAmqpMessage::Priority]);

    if (prop_ & QAmqpMessage::CorrelationId)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::CorrelationId]);

    if (prop_ & QAmqpMessage::ReplyTo)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::ReplyTo]);

    if (prop_ & QAmqpMessage::Expiration)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::Expiration]);

    if (prop_ & QAmqpMessage::MessageId)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::MessageId]);

    if (prop_ & QAmqpMessage::Timestamp)
        writeAmqpField(out, QAmqpMetaType::Timestamp, properties_[QAmqpMessage::Timestamp]);

    if (prop_ & QAmqpMessage::Type)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::Type]);

    if (prop_ & QAmqpMessage::UserId)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::UserId]);

    if (prop_ & QAmqpMessage::AppId)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::AppId]);

    if (prop_ & QAmqpMessage::ClusterID)
        writeAmqpField(out, QAmqpMetaType::ShortString, properties_[QAmqpMessage::ClusterID]);

    return buffer_.size();
}

qlonglong QAmqpContentFrame::bodySize() const
{
    return bodySize_;
}

void QAmqpContentFrame::setBodySize(qlonglong size)
{
    bodySize_ = size;
}

void QAmqpContentFrame::setProperty(QAmqpMessage::Property prop, const QVariant &value)
{
    properties_[prop] = value;
}

QVariant QAmqpContentFrame::property(QAmqpMessage::Property prop) const
{
    return properties_.value(prop);
}

void QAmqpContentFrame::writePayload(QDataStream &out) const
{
    out.writeRawData(buffer_.data(), buffer_.size());
}

void QAmqpContentFrame::readPayload(QDataStream &in)
{
    in >> methodClass_;
    in.skipRawData(2); //weight
    in >> bodySize_;
    qint16 flags_ = 0;
    in >> flags_;
    if (flags_ & QAmqpMessage::ContentType)
        properties_[QAmqpMessage::ContentType] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::ContentEncoding)
        properties_[QAmqpMessage::ContentEncoding] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::Headers)
        properties_[QAmqpMessage::Headers] = readAmqpField(in, QAmqpMetaType::Hash);

    if (flags_ & QAmqpMessage::DeliveryMode)
        properties_[QAmqpMessage::DeliveryMode] = readAmqpField(in, QAmqpMetaType::ShortShortUint);

    if (flags_ & QAmqpMessage::Priority)
        properties_[QAmqpMessage::Priority] = readAmqpField(in, QAmqpMetaType::ShortShortUint);

    if (flags_ & QAmqpMessage::CorrelationId)
        properties_[QAmqpMessage::CorrelationId] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::ReplyTo)
        properties_[QAmqpMessage::ReplyTo] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::Expiration)
        properties_[QAmqpMessage::Expiration] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::MessageId)
        properties_[QAmqpMessage::MessageId] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::Timestamp)
        properties_[QAmqpMessage::Timestamp] = readAmqpField(in, QAmqpMetaType::Timestamp);

    if (flags_ & QAmqpMessage::Type)
        properties_[QAmqpMessage::Type] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::UserId)
        properties_[QAmqpMessage::UserId] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::AppId)
        properties_[QAmqpMessage::AppId] = readAmqpField(in, QAmqpMetaType::ShortString);

    if (flags_ & QAmqpMessage::ClusterID)
        properties_[QAmqpMessage::ClusterID] = readAmqpField(in, QAmqpMetaType::ShortString);
}

//////////////////////////////////////////////////////////////////////////

QAmqpContentBodyFrame::QAmqpContentBodyFrame()
    : QAmqpFrame(QAmqpFrame::Body)
{
}

void QAmqpContentBodyFrame::setBody(const QByteArray &data)
{
    body_ = data;
}

QByteArray QAmqpContentBodyFrame::body() const
{
    return body_;
}

void QAmqpContentBodyFrame::writePayload(QDataStream &out) const
{
    out.writeRawData(body_.data(), body_.size());
}

void QAmqpContentBodyFrame::readPayload(QDataStream &in)
{
    body_.resize(size_);
    in.readRawData(body_.data(), body_.size());
}

qint32 QAmqpContentBodyFrame::size() const
{
    return body_.size();
}

//////////////////////////////////////////////////////////////////////////

QAmqpHeartbeatFrame::QAmqpHeartbeatFrame()
    : QAmqpFrame(QAmqpFrame::Heartbeat)
{
}

void QAmqpHeartbeatFrame::readPayload(QDataStream &stream)
{
    Q_UNUSED(stream)
}

void QAmqpHeartbeatFrame::writePayload(QDataStream &stream) const
{
    Q_UNUSED(stream)
}
<|endoftext|>


<commit_before>/******************************************************************************
** Copyright (c) 2013-2015, Intel Corporation                                **
** All rights reserved.                                                      **
**                                                                           **
** Redistribution and use in source and binary forms, with or without        **
** modification, are permitted provided that the following conditions        **
** are met:                                                                  **
** 1. Redistributions of source code must retain the above copyright         **
**    notice, this list of conditions and the following disclaimer.          **
** 2. 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.   **
** 3. Neither the name of the copyright holder 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      **
** HOLDER 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.              **
******************************************************************************/
/* Hans Pabst (Intel Corp.)
******************************************************************************/
#include <libxsmm.h>

#if defined(LIBXSMM_OFFLOAD)
# pragma offload_attribute(push,target(mic))
#endif

#include <algorithm>
#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <vector>
#include <cmath>

#if defined(_OPENMP)
# include <omp.h>
#endif

#if defined(LIBXSMM_OFFLOAD)
# pragma offload_attribute(pop)
#endif

#if (0 < (LIBXSMM_ALIGNED_STORES))
# define SMM_ALIGNMENT LIBXSMM_ALIGNED_STORES
#else
# define SMM_ALIGNMENT LIBXSMM_ALIGNMENT
#endif

// make sure that stacksize is covering the problem size
#define SMM_MAX_PROBLEM_SIZE (1 * LIBXSMM_MAX_MNK)

#define SMM_SCHEDULE dynamic
#define SMM_CHECK

template<typename T>
LIBXSMM_TARGET(mic) void nrand(T& a)
{
  static const double scale = 1.0 / RAND_MAX;
  a = static_cast<T>(scale * (2 * std::rand() - RAND_MAX));
}

template<typename T>
LIBXSMM_TARGET(mic) void add(T *LIBXSMM_RESTRICT dst, const T *LIBXSMM_RESTRICT c, int m, int n, int ldc)
{
#if (0 < LIBXSMM_ALIGNED_STORES)
  LIBXSMM_ASSUME_ALIGNED(c, SMM_ALIGNMENT);
#endif
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
#if (0 != LIBXSMM_ROW_MAJOR)
      const T value = c[i*ldc+j];
#else
      const T value = c[j*ldc+i];
#endif
#if defined(_OPENMP)
#     pragma omp atomic
#endif
#if (0 != LIBXSMM_ROW_MAJOR)
      dst[i*n+j] += value;
#else
      dst[j*m+i] += value;
#endif
    }
  }
}

template<typename T>
LIBXSMM_TARGET(mic) double max_diff(const T *LIBXSMM_RESTRICT result, const T *LIBXSMM_RESTRICT expect, int m, int n, int ldc)
{
  double diff = 0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
#if (0 != LIBXSMM_ROW_MAJOR)
      const int k = i * ldc + j;
#else
      const int k = j * ldc + i;
#endif
      diff = std::max(diff, std::abs(static_cast<double>(result[k]) - static_cast<double>(expect[k])));
    }
  }
  return diff;
}

int main(int argc, char* argv[])
{
  try {
    typedef double T;
    const int default_psize = 30000, default_batch = 1000;
    const int m = 1 < argc ? std::atoi(argv[1]) : 23;
    const int s = 2 < argc ? (0 < std::atoi(argv[2]) ? std::atoi(argv[2]) : ('+' == *argv[2]
      ? (default_psize << std::strlen(argv[2]))
      : (default_psize >> std::strlen(argv[2])))) : default_psize;
    const int t = 3 < argc ? (0 < std::atoi(argv[3]) ? std::atoi(argv[3]) : ('+' == *argv[3]
      ? (default_batch << std::strlen(argv[3]))
      : (default_batch >> std::strlen(argv[3])))) : default_batch;
    const int n = 4 < argc ? std::atoi(argv[4]) : m;
    const int k = 5 < argc ? std::atoi(argv[5]) : m;

    if ((SMM_MAX_PROBLEM_SIZE) < (m * n * k)) {
      throw std::runtime_error("The size M x N x K is exceeding SMM_MAX_PROBLEM_SIZE!");
    }

#if (0 != LIBXSMM_ROW_MAJOR)
# if (0 < LIBXSMM_ALIGNED_STORES)
    const int ldc = LIBXSMM_ALIGN_VALUE(int, T, n, LIBXSMM_ALIGNED_STORES);
# else
    const int ldc = n;
# endif
    const int csize = m * ldc;
#else
# if (0 < LIBXSMM_ALIGNED_STORES)
    const int ldc = LIBXSMM_ALIGN_VALUE(int, T, m, LIBXSMM_ALIGNED_STORES);
# else
    const int ldc = m;
# endif
    const int csize = n * ldc;
#endif

    const int asize = m * k, bsize = k * n;
    std::vector<T> va(s * asize), vb(s * bsize), vc(csize);
    std::for_each(va.begin(), va.end(), nrand<T>);
    std::for_each(vb.begin(), vb.end(), nrand<T>);
    const T *const a = &va[0], *const b = &vb[0];
    T * /*const*/ c = &vc[0];

#if defined(LIBXSMM_OFFLOAD)
#   pragma offload target(mic) in(a: length(s * asize)) in(b: length(s * bsize)) out(c: length(csize))
#endif
    {
      const double mbytes = 1.0 * s * (asize + bsize) * sizeof(T) / (1024 * 1024);
#if defined(_OPENMP)
      const double nbytes = 1.0 * s * (csize) * sizeof(T) / (1024 * 1024);
      const double gflops = 2.0 * s * m * n * k * 1E-9;
#endif
#if defined(SMM_CHECK)
      std::vector<T> expect(csize);
#endif
      fprintf(stdout, "m=%i n=%i k=%i ldc=%i size=%i batch=%i memory=%.1f MB\n", m, n, k, ldc, s, t, mbytes);

      { // LAPACK/BLAS3 (fallback)
        fprintf(stdout, "LAPACK/BLAS...\n");
        std::fill_n(c, csize, 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for schedule(SMM_SCHEDULE)
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_blasmm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(c, tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", (mbytes + nbytes) * 1E-3 / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        std::copy(c, c + csize, expect.begin());
#endif
      }

      { // inline an optimized implementation
        fprintf(stdout, "Inlined...\n");
        std::fill_n(c, csize, 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for schedule(SMM_SCHEDULE)
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_imm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(c, tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", (mbytes + nbytes) * 1E-3 / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(c, &expect[0], m, n, ldc));
#endif
      }

      { // auto-dispatched
        fprintf(stdout, "Dispatched...\n");
        std::fill_n(c, csize, 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for schedule(SMM_SCHEDULE)
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_mm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(c, tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", (mbytes + nbytes) * 1E-3 / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(c, &expect[0], m, n, ldc));
#endif
      }

      const libxsmm_mm_dispatch<T> xmm(m, n, k);
      if (xmm) { // specialized routine
        fprintf(stdout, "Specialized...\n");
        std::fill_n(c, csize, 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for schedule(SMM_SCHEDULE)
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            xmm(&a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(c, tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", (mbytes + nbytes) * 1E-3 / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(c, &expect[0], m, n, ldc));
#endif
      }

      fprintf(stdout, "Finished\n");
    }
  }
  catch(const std::exception& e) {
    fprintf(stderr, "Error: %s\n", e.what());
    return EXIT_FAILURE;
  }
  catch(...) {
    fprintf(stderr, "Error: unknown exception caught!\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<commit_msg>Fixed a corner case when processing the command line arguments of the sample/benchmark program.<commit_after>/******************************************************************************
** Copyright (c) 2013-2015, Intel Corporation                                **
** All rights reserved.                                                      **
**                                                                           **
** Redistribution and use in source and binary forms, with or without        **
** modification, are permitted provided that the following conditions        **
** are met:                                                                  **
** 1. Redistributions of source code must retain the above copyright         **
**    notice, this list of conditions and the following disclaimer.          **
** 2. 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.   **
** 3. Neither the name of the copyright holder 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      **
** HOLDER 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.              **
******************************************************************************/
/* Hans Pabst (Intel Corp.)
******************************************************************************/
#include <libxsmm.h>

#if defined(LIBXSMM_OFFLOAD)
# pragma offload_attribute(push,target(mic))
#endif

#include <algorithm>
#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <vector>
#include <cmath>

#if defined(_OPENMP)
# include <omp.h>
#endif

#if defined(LIBXSMM_OFFLOAD)
# pragma offload_attribute(pop)
#endif

#if (0 < (LIBXSMM_ALIGNED_STORES))
# define SMM_ALIGNMENT LIBXSMM_ALIGNED_STORES
#else
# define SMM_ALIGNMENT LIBXSMM_ALIGNMENT
#endif

// make sure that stacksize is covering the problem size
#define SMM_MAX_PROBLEM_SIZE (1 * LIBXSMM_MAX_MNK)

#define SMM_SCHEDULE dynamic
#define SMM_CHECK

template<typename T>
LIBXSMM_TARGET(mic) void nrand(T& a)
{
  static const double scale = 1.0 / RAND_MAX;
  a = static_cast<T>(scale * (2 * std::rand() - RAND_MAX));
}

template<typename T>
LIBXSMM_TARGET(mic) void add(T *LIBXSMM_RESTRICT dst, const T *LIBXSMM_RESTRICT c, int m, int n, int ldc)
{
#if (0 < LIBXSMM_ALIGNED_STORES)
  LIBXSMM_ASSUME_ALIGNED(c, SMM_ALIGNMENT);
#endif
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
#if (0 != LIBXSMM_ROW_MAJOR)
      const T value = c[i*ldc+j];
#else
      const T value = c[j*ldc+i];
#endif
#if defined(_OPENMP)
#     pragma omp atomic
#endif
#if (0 != LIBXSMM_ROW_MAJOR)
      dst[i*n+j] += value;
#else
      dst[j*m+i] += value;
#endif
    }
  }
}

template<typename T>
LIBXSMM_TARGET(mic) double max_diff(const T *LIBXSMM_RESTRICT result, const T *LIBXSMM_RESTRICT expect, int m, int n, int ldc)
{
  double diff = 0;
  for (int i = 0; i < m; ++i) {
    for (int j = 0; j < n; ++j) {
#if (0 != LIBXSMM_ROW_MAJOR)
      const int k = i * ldc + j;
#else
      const int k = j * ldc + i;
#endif
      diff = std::max(diff, std::abs(static_cast<double>(result[k]) - static_cast<double>(expect[k])));
    }
  }
  return diff;
}

int main(int argc, char* argv[])
{
  try {
    typedef double T;
    const int default_psize = 30000, default_batch = 1000;
    const int m = 1 < argc ? std::atoi(argv[1]) : 23;
    const int s = 2 < argc ? (0 < std::atoi(argv[2]) ? std::atoi(argv[2]) : ('+' == *argv[2]
      ? (default_psize << std::strlen(argv[2])) : ('-' == *argv[2]
      ? (default_psize >> std::strlen(argv[2])) : default_psize))) : default_psize;
    const int t = 3 < argc ? (0 < std::atoi(argv[3]) ? std::atoi(argv[3]) : ('+' == *argv[3]
      ? (default_batch << std::strlen(argv[3])) : ('-' == *argv[3]
      ? (default_batch >> std::strlen(argv[3])) : default_batch))) : default_batch;
    const int n = 4 < argc ? std::atoi(argv[4]) : m;
    const int k = 5 < argc ? std::atoi(argv[5]) : m;

    if ((SMM_MAX_PROBLEM_SIZE) < (m * n * k)) {
      throw std::runtime_error("The size M x N x K is exceeding SMM_MAX_PROBLEM_SIZE!");
    }

#if (0 != LIBXSMM_ROW_MAJOR)
# if (0 < LIBXSMM_ALIGNED_STORES)
    const int ldc = LIBXSMM_ALIGN_VALUE(int, T, n, LIBXSMM_ALIGNED_STORES);
# else
    const int ldc = n;
# endif
    const int csize = m * ldc;
#else
# if (0 < LIBXSMM_ALIGNED_STORES)
    const int ldc = LIBXSMM_ALIGN_VALUE(int, T, m, LIBXSMM_ALIGNED_STORES);
# else
    const int ldc = m;
# endif
    const int csize = n * ldc;
#endif

    const int asize = m * k, bsize = k * n;
    std::vector<T> va(s * asize), vb(s * bsize), vc(csize);
    std::for_each(va.begin(), va.end(), nrand<T>);
    std::for_each(vb.begin(), vb.end(), nrand<T>);
    const T *const a = &va[0], *const b = &vb[0];
    T * /*const*/ c = &vc[0];

#if defined(LIBXSMM_OFFLOAD)
#   pragma offload target(mic) in(a: length(s * asize)) in(b: length(s * bsize)) out(c: length(csize))
#endif
    {
      const double mbytes = 1.0 * s * (asize + bsize) * sizeof(T) / (1024 * 1024);
#if defined(_OPENMP)
      const double nbytes = 1.0 * s * (csize) * sizeof(T) / (1024 * 1024);
      const double gflops = 2.0 * s * m * n * k * 1E-9;
#endif
#if defined(SMM_CHECK)
      std::vector<T> expect(csize);
#endif
      fprintf(stdout, "m=%i n=%i k=%i ldc=%i size=%i batch=%i memory=%.1f MB\n", m, n, k, ldc, s, t, mbytes);

      { // LAPACK/BLAS3 (fallback)
        fprintf(stdout, "LAPACK/BLAS...\n");
        std::fill_n(c, csize, 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for schedule(SMM_SCHEDULE)
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_blasmm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(c, tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", (mbytes + nbytes) * 1E-3 / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        std::copy(c, c + csize, expect.begin());
#endif
      }

      { // inline an optimized implementation
        fprintf(stdout, "Inlined...\n");
        std::fill_n(c, csize, 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for schedule(SMM_SCHEDULE)
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_imm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(c, tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", (mbytes + nbytes) * 1E-3 / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(c, &expect[0], m, n, ldc));
#endif
      }

      { // auto-dispatched
        fprintf(stdout, "Dispatched...\n");
        std::fill_n(c, csize, 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for schedule(SMM_SCHEDULE)
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            libxsmm_mm(m, n, k, &a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(c, tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", (mbytes + nbytes) * 1E-3 / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(c, &expect[0], m, n, ldc));
#endif
      }

      const libxsmm_mm_dispatch<T> xmm(m, n, k);
      if (xmm) { // specialized routine
        fprintf(stdout, "Specialized...\n");
        std::fill_n(c, csize, 0);
#if defined(_OPENMP)
        const double start = omp_get_wtime();
#       pragma omp parallel for schedule(SMM_SCHEDULE)
#endif
        for (int i = 0; i < s; i += t) {
          LIBXSMM_ALIGNED(T tmp[SMM_MAX_PROBLEM_SIZE], SMM_ALIGNMENT);
          for (int j = 0; j < csize; ++j) tmp[j] = 0; // clear
          for (int j = 0; j < LIBXSMM_MIN(t, s - i); ++j) {
            xmm(&a[0] + (i + j) * asize, &b[0] + (i + j) * bsize, tmp);
          }
          add(c, tmp, m, n, ldc); // atomic
        }
#if defined(_OPENMP)
        const double duration = omp_get_wtime() - start;
        if (0 < duration) {
          fprintf(stdout, "\tperformance: %.1f GFLOPS/s\n", gflops / duration);
          fprintf(stdout, "\tbandwidth: %.1f GB/s\n", (mbytes + nbytes) * 1E-3 / duration);
        }
        fprintf(stdout, "\tduration: %.1f s\n", duration);
#endif
#if defined(SMM_CHECK)
        fprintf(stdout, "\tdiff=%f\n", max_diff(c, &expect[0], m, n, ldc));
#endif
      }

      fprintf(stdout, "Finished\n");
    }
  }
  catch(const std::exception& e) {
    fprintf(stderr, "Error: %s\n", e.what());
    return EXIT_FAILURE;
  }
  catch(...) {
    fprintf(stderr, "Error: unknown exception caught!\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright (C) 2015 sails Authors.
// All rights reserved.
//
// Official git repository and contact information can be found at
// https://github.com/sails/sails and http://www.sailsxu.com/.
//
// Filename: client_rpc_channel.cc
//
// Author: sailsxu <sailsxu@gmail.com>
// Created: 2015-04-23 16:03:07

#include "rpc_channel.h"
#include <stdio.h>
#include <assert.h>
#include <iostream>
#include <sstream>
#include "sails/net/connector.h"
#include "saf_packet.h"
#include "google/protobuf/message.h"
#include "google/protobuf/descriptor.h"

using namespace google::protobuf;  // NOLINT

namespace sails {

RpcChannelImp::RpcChannelImp(string ip, int port):
    ip(ip), port(port) {
  connector = new net::Connector();
  assert(connector->connect(this->ip.c_str(), this->port, true));
  sn = 0;
}
RpcChannelImp::~RpcChannelImp() {
  if (connector != NULL) {
    delete connector;
    connector = NULL;
  }
}
void RpcChannelImp::CallMethod(const MethodDescriptor* method,
                               RpcController *controller,
                               const Message *request,
                               Message *response,
                               Closure *done) {
  int ret = this->sync_call(method, controller, request, response);
  if (ret == 0 && done != NULL) {
    done->Run();
  }
}

net::PacketCommon* RpcChannelImp::parser(
    net::Connector *connector) {

  if (connector->readable() < sizeof(net::PacketCommon)) {
    return NULL;
  }
  net::PacketCommon *packet = (net::PacketCommon*)connector->peek();
  if (packet== NULL || packet->type.opcode >= net::PACKET_MAX) {
    // error, and empty all data
    connector->retrieve(connector->readable());
    return NULL;
  }
  if (packet != NULL) {
    uint32_t packetlen = packet->len;
    if (connector->readable() >= packetlen) {
      net::PacketCommon *item = (net::PacketCommon*)malloc(packetlen);
      memcpy(item, packet, packetlen);
      connector->retrieve(packetlen);
      return item;
    }
  }
  return NULL;
}

int RpcChannelImp::sync_call(const google::protobuf::MethodDescriptor *method,
                             google::protobuf::RpcController *controller,
                             const google::protobuf::Message *request,
                             google::protobuf::Message *response) {
  const string service_name = method->service()->name();
  string content = request->SerializeAsString();

  int len = sizeof(PacketRPCRequest)+content.length()-1;
  PacketRPCRequest *packet = reinterpret_cast<PacketRPCRequest*>(malloc(len));
  new(packet) PacketRPCRequest(len, sn++);
  if (sn > INT_MAX) {
    sn = 0;
  }
  packet->version = 1.0;  // client lib 版本号
  memcpy(packet->service_name, service_name.c_str(), service_name.length());
  packet->method_index = method->index();
  memcpy(packet->data, content.c_str(), content.length());

  connector->write(reinterpret_cast<char*>(packet), len);
  free(packet);
  if (len <= 1000) {
    connector->send();
  } else {
    printf("error len:%d\n", len);
  }

  int n = connector->read();
  if (n > 0) {
    bool continueParse = false;
    do {
      continueParse = false;
      net::PacketCommon *resp = RpcChannelImp::parser(connector);
      if (resp != NULL) {
        continueParse = true;
        char *body = (reinterpret_cast<PacketRPCResponse*>(resp))->data;
        string str_body(body, resp->len-sizeof(PacketRPCResponse)+1);
        if (strlen(body) > 0) {
          // protobuf message
          response->ParseFromString(str_body);
        }
        delete(resp);
      }
    } while (continueParse);
    //
  }

  return 0;
}

}  // namespace sails
<commit_msg>update<commit_after>// Copyright (C) 2015 sails Authors.
// All rights reserved.
//
// Official git repository and contact information can be found at
// https://github.com/sails/sails and http://www.sailsxu.com/.
//
// Filename: client_rpc_channel.cc
//
// Author: sailsxu <sailsxu@gmail.com>
// Created: 2015-04-23 16:03:07

#include "rpc_channel.h"
#include <stdio.h>
#include <limits.h>
#include <assert.h>
#include <iostream>
#include <sstream>
#include "sails/net/connector.h"
#include "saf_packet.h"
#include "google/protobuf/message.h"
#include "google/protobuf/descriptor.h"

using namespace google::protobuf;  // NOLINT

namespace sails {

RpcChannelImp::RpcChannelImp(string ip, int port):
    ip(ip), port(port) {
  connector = new net::Connector();
  assert(connector->connect(this->ip.c_str(), this->port, true));
  sn = 0;
}
RpcChannelImp::~RpcChannelImp() {
  if (connector != NULL) {
    delete connector;
    connector = NULL;
  }
}
void RpcChannelImp::CallMethod(const MethodDescriptor* method,
                               RpcController *controller,
                               const Message *request,
                               Message *response,
                               Closure *done) {
  int ret = this->sync_call(method, controller, request, response);
  if (ret == 0 && done != NULL) {
    done->Run();
  }
}

net::PacketCommon* RpcChannelImp::parser(
    net::Connector *connector) {

  if (connector->readable() < sizeof(net::PacketCommon)) {
    return NULL;
  }
  net::PacketCommon *packet = (net::PacketCommon*)connector->peek();
  if (packet== NULL || packet->type.opcode >= net::PACKET_MAX) {
    // error, and empty all data
    connector->retrieve(connector->readable());
    return NULL;
  }
  if (packet != NULL) {
    uint32_t packetlen = packet->len;
    if (connector->readable() >= packetlen) {
      net::PacketCommon *item = (net::PacketCommon*)malloc(packetlen);
      memcpy(item, packet, packetlen);
      connector->retrieve(packetlen);
      return item;
    }
  }
  return NULL;
}

int RpcChannelImp::sync_call(const google::protobuf::MethodDescriptor *method,
                             google::protobuf::RpcController *controller,
                             const google::protobuf::Message *request,
                             google::protobuf::Message *response) {
  const string service_name = method->service()->name();
  string content = request->SerializeAsString();

  int len = sizeof(PacketRPCRequest)+content.length()-1;
  PacketRPCRequest *packet = reinterpret_cast<PacketRPCRequest*>(malloc(len));
  new(packet) PacketRPCRequest(len, sn++);
  if (sn > INT_MAX) {
    sn = 0;
  }
  packet->version = 1.0;  // client lib 版本号
  memcpy(packet->service_name, service_name.c_str(), service_name.length());
  packet->method_index = method->index();
  memcpy(packet->data, content.c_str(), content.length());

  connector->write(reinterpret_cast<char*>(packet), len);
  free(packet);
  if (len <= 1000) {
    connector->send();
  } else {
    printf("error len:%d\n", len);
  }

  int n = connector->read();
  if (n > 0) {
    bool continueParse = false;
    do {
      continueParse = false;
      net::PacketCommon *resp = RpcChannelImp::parser(connector);
      if (resp != NULL) {
        continueParse = true;
        char *body = (reinterpret_cast<PacketRPCResponse*>(resp))->data;
        string str_body(body, resp->len-sizeof(PacketRPCResponse)+1);
        if (strlen(body) > 0) {
          // protobuf message
          response->ParseFromString(str_body);
        }
        delete(resp);
      }
    } while (continueParse);
    //
  }

  return 0;
}

}  // namespace sails
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of Intel Corporation may not 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 Intel Corporation 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.
//
//M*/

#include "precomp.hpp"

using namespace std;

namespace cv
{

/****************************************************************************************\
*                                 DescriptorExtractor                                    *
\****************************************************************************************/
/*
 *   DescriptorExtractor
 */
DescriptorExtractor::~DescriptorExtractor()
{}

void DescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const
{
    if( image.empty() || keypoints.empty() )
    {
        descriptors.release();
        return;
    }

    KeyPointsFilter::runByImageBorder( keypoints, image.size(), 0 );
    KeyPointsFilter::runByKeypointSize( keypoints, std::numeric_limits<float>::epsilon() );

    computeImpl( image, keypoints, descriptors );
}

void DescriptorExtractor::compute( const vector<Mat>& imageCollection, vector<vector<KeyPoint> >& pointCollection, vector<Mat>& descCollection ) const
{
    CV_Assert( imageCollection.size() == pointCollection.size() );
    descCollection.resize( imageCollection.size() );
    for( size_t i = 0; i < imageCollection.size(); i++ )
        compute( imageCollection[i], pointCollection[i], descCollection[i] );
}

/*void DescriptorExtractor::read( const FileNode& )
{}

void DescriptorExtractor::write( FileStorage& ) const
{}*/

bool DescriptorExtractor::empty() const
{
    return false;
}

void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& keypoints,
                                                 Size imageSize, int borderSize )
{
    KeyPointsFilter::runByImageBorder( keypoints, imageSize, borderSize );
}

Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)
{
    if( descriptorExtractorType.find("Opponent") == 0)
    {
        size_t pos = string("Opponent").size();
        return DescriptorExtractor::create(descriptorExtractorType.substr(pos));
    }

    return Algorithm::create<DescriptorExtractor>("Feature2D." + descriptorExtractorType);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/****************************************************************************************\
*                             OpponentColorDescriptorExtractor                           *
\****************************************************************************************/
OpponentColorDescriptorExtractor::OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& _descriptorExtractor ) :
        descriptorExtractor(_descriptorExtractor)
{
    CV_Assert( !descriptorExtractor.empty() );
}

void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, vector<Mat>& opponentChannels )
{
    if( bgrImage.type() != CV_8UC3 )
        CV_Error( CV_StsBadArg, "input image must be an BGR image of type CV_8UC3" );

    // Split image into RGB to allow conversion to Opponent Color Space.
    vector<Mat> bgrChannels(3);
    split( bgrImage, bgrChannels );

    // Prepare opponent color space storage matrices.
    opponentChannels.resize( 3 );
    opponentChannels[0] = cv::Mat(bgrImage.size(), CV_8UC1); // R-G RED-GREEN
    opponentChannels[1] = cv::Mat(bgrImage.size(), CV_8UC1); // R+G-2B YELLOW-BLUE
    opponentChannels[2] = cv::Mat(bgrImage.size(), CV_8UC1); // R+G+B

    // Calculate the channels of the opponent color space
    {
        // (R - G) / sqrt(2)
        MatConstIterator_<signed char> rIt = bgrChannels[2].begin<signed char>();
        MatConstIterator_<signed char> gIt = bgrChannels[1].begin<signed char>();
        MatIterator_<unsigned char> dstIt = opponentChannels[0].begin<unsigned char>();
        float factor = 1.f / sqrt(2.f);
        for( ; dstIt != opponentChannels[0].end<unsigned char>(); ++rIt, ++gIt, ++dstIt )
        {
            int value = static_cast<int>( static_cast<float>(static_cast<int>(*gIt)-static_cast<int>(*rIt)) * factor );
            if( value < 0 ) value = 0;
            if( value > 255 ) value = 255;
            (*dstIt) = static_cast<unsigned char>(value);
        }
    }
    {
        // (R + G - 2B)/sqrt(6)
        MatConstIterator_<signed char> rIt = bgrChannels[2].begin<signed char>();
        MatConstIterator_<signed char> gIt = bgrChannels[1].begin<signed char>();
        MatConstIterator_<signed char> bIt = bgrChannels[0].begin<signed char>();
        MatIterator_<unsigned char> dstIt = opponentChannels[1].begin<unsigned char>();
        float factor = 1.f / sqrt(6.f);
        for( ; dstIt != opponentChannels[1].end<unsigned char>(); ++rIt, ++gIt, ++bIt, ++dstIt )
        {
            int value = static_cast<int>( static_cast<float>(static_cast<int>(*rIt) + static_cast<int>(*gIt) - 2*static_cast<int>(*bIt)) *
                                          factor );
            if( value < 0 ) value = 0;
            if( value > 255 ) value = 255;
            (*dstIt) = static_cast<unsigned char>(value);
        }
    }
    {
        // (R + G + B)/sqrt(3)
        MatConstIterator_<signed char> rIt = bgrChannels[2].begin<signed char>();
        MatConstIterator_<signed char> gIt = bgrChannels[1].begin<signed char>();
        MatConstIterator_<signed char> bIt = bgrChannels[0].begin<signed char>();
        MatIterator_<unsigned char> dstIt = opponentChannels[2].begin<unsigned char>();
        float factor = 1.f / sqrt(3.f);
        for( ; dstIt != opponentChannels[2].end<unsigned char>(); ++rIt, ++gIt, ++bIt, ++dstIt )
        {
            int value = static_cast<int>( static_cast<float>(static_cast<int>(*rIt) + static_cast<int>(*gIt) + static_cast<int>(*bIt)) *
                                          factor );
            if( value < 0 ) value = 0;
            if( value > 255 ) value = 255;
            (*dstIt) = static_cast<unsigned char>(value);
        }
    }
}

struct KP_LessThan
{
    KP_LessThan(const vector<KeyPoint>& _kp) : kp(&_kp) {}
    bool operator()(int i, int j) const
    {
        return (*kp)[i].class_id < (*kp)[j].class_id;
    }
    const vector<KeyPoint>* kp;
};

void OpponentColorDescriptorExtractor::computeImpl( const Mat& bgrImage, vector<KeyPoint>& keypoints, Mat& descriptors ) const
{
    vector<Mat> opponentChannels;
    convertBGRImageToOpponentColorSpace( bgrImage, opponentChannels );

    const int N = 3; // channels count
    vector<KeyPoint> channelKeypoints[N];
    Mat channelDescriptors[N];
    vector<int> idxs[N];

    // Compute descriptors three times, once for each Opponent channel to concatenate into a single color descriptor
    int maxKeypointsCount = 0;
    for( int ci = 0; ci < N; ci++ )
    {
        channelKeypoints[ci].insert( channelKeypoints[ci].begin(), keypoints.begin(), keypoints.end() );
        // Use class_id member to get indices into initial keypoints vector
        for( size_t ki = 0; ki < channelKeypoints[ci].size(); ki++ )
            channelKeypoints[ci][ki].class_id = (int)ki;

        descriptorExtractor->compute( opponentChannels[ci], channelKeypoints[ci], channelDescriptors[ci] );
        idxs[ci].resize( channelKeypoints[ci].size() );
        for( size_t ki = 0; ki < channelKeypoints[ci].size(); ki++ )
        {
            idxs[ci][ki] = (int)ki;
        }
        std::sort( idxs[ci].begin(), idxs[ci].end(), KP_LessThan(channelKeypoints[ci]) );
        maxKeypointsCount = std::max( maxKeypointsCount, (int)channelKeypoints[ci].size());
    }

    vector<KeyPoint> outKeypoints;
    outKeypoints.reserve( keypoints.size() );

    int descriptorSize = descriptorExtractor->descriptorSize();
    Mat mergedDescriptors( maxKeypointsCount, 3*descriptorSize, descriptorExtractor->descriptorType() );
    int mergedCount = 0;
    // cp - current channel position
    size_t cp[] = {0, 0, 0};
    while( cp[0] < channelKeypoints[0].size() &&
           cp[1] < channelKeypoints[1].size() &&
           cp[2] < channelKeypoints[2].size() )
    {
        const int maxInitIdx = std::max( channelKeypoints[0][idxs[0][cp[0]]].class_id,
                                         std::max( channelKeypoints[1][idxs[1][cp[1]]].class_id,
                                                   channelKeypoints[2][idxs[2][cp[2]]].class_id ) );

        while( channelKeypoints[0][idxs[0][cp[0]]].class_id < maxInitIdx && cp[0] < channelKeypoints[0].size() ) { cp[0]++; }
        while( channelKeypoints[1][idxs[1][cp[1]]].class_id < maxInitIdx && cp[1] < channelKeypoints[1].size() ) { cp[1]++; }
        while( channelKeypoints[2][idxs[2][cp[2]]].class_id < maxInitIdx && cp[2] < channelKeypoints[2].size() ) { cp[2]++; }
        if( cp[0] >= channelKeypoints[0].size() || cp[1] >= channelKeypoints[1].size() || cp[2] >= channelKeypoints[2].size() )
            break;

        if( channelKeypoints[0][idxs[0][cp[0]]].class_id == maxInitIdx &&
            channelKeypoints[1][idxs[1][cp[1]]].class_id == maxInitIdx &&
            channelKeypoints[2][idxs[2][cp[2]]].class_id == maxInitIdx )
        {
            outKeypoints.push_back( keypoints[maxInitIdx] );
            // merge descriptors
            for( int ci = 0; ci < N; ci++ )
            {
                Mat dst = mergedDescriptors(Range(mergedCount, mergedCount+1), Range(ci*descriptorSize, (ci+1)*descriptorSize));
                channelDescriptors[ci].row( idxs[ci][cp[ci]] ).copyTo( dst );
                cp[ci]++;
            }
            mergedCount++;
        }
    }
    mergedDescriptors.rowRange(0, mergedCount).copyTo( descriptors );
    std::swap( outKeypoints, keypoints );
}

void OpponentColorDescriptorExtractor::read( const FileNode& fn )
{
    descriptorExtractor->read(fn);
}

void OpponentColorDescriptorExtractor::write( FileStorage& fs ) const
{
    descriptorExtractor->write(fs);
}

int OpponentColorDescriptorExtractor::descriptorSize() const
{
    return 3*descriptorExtractor->descriptorSize();
}

int OpponentColorDescriptorExtractor::descriptorType() const
{
    return descriptorExtractor->descriptorType();
}

bool OpponentColorDescriptorExtractor::empty() const
{
    return descriptorExtractor.empty() || (DescriptorExtractor*)(descriptorExtractor)->empty();
}

}
<commit_msg>fixed creation of opponent space descriptors (#1805)<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's 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.
//
//   * The name of Intel Corporation may not 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 Intel Corporation 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.
//
//M*/

#include "precomp.hpp"

using namespace std;

namespace cv
{

/****************************************************************************************\
*                                 DescriptorExtractor                                    *
\****************************************************************************************/
/*
 *   DescriptorExtractor
 */
DescriptorExtractor::~DescriptorExtractor()
{}

void DescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const
{
    if( image.empty() || keypoints.empty() )
    {
        descriptors.release();
        return;
    }

    KeyPointsFilter::runByImageBorder( keypoints, image.size(), 0 );
    KeyPointsFilter::runByKeypointSize( keypoints, std::numeric_limits<float>::epsilon() );

    computeImpl( image, keypoints, descriptors );
}

void DescriptorExtractor::compute( const vector<Mat>& imageCollection, vector<vector<KeyPoint> >& pointCollection, vector<Mat>& descCollection ) const
{
    CV_Assert( imageCollection.size() == pointCollection.size() );
    descCollection.resize( imageCollection.size() );
    for( size_t i = 0; i < imageCollection.size(); i++ )
        compute( imageCollection[i], pointCollection[i], descCollection[i] );
}

/*void DescriptorExtractor::read( const FileNode& )
{}

void DescriptorExtractor::write( FileStorage& ) const
{}*/

bool DescriptorExtractor::empty() const
{
    return false;
}

void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& keypoints,
                                                 Size imageSize, int borderSize )
{
    KeyPointsFilter::runByImageBorder( keypoints, imageSize, borderSize );
}

Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)
{
    if( descriptorExtractorType.find("Opponent") == 0 )
    {
        size_t pos = string("Opponent").size();
        string type = descriptorExtractorType.substr(pos);
        return new OpponentColorDescriptorExtractor(DescriptorExtractor::create(type));
    }

    return Algorithm::create<DescriptorExtractor>("Feature2D." + descriptorExtractorType);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/****************************************************************************************\
*                             OpponentColorDescriptorExtractor                           *
\****************************************************************************************/
OpponentColorDescriptorExtractor::OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& _descriptorExtractor ) :
        descriptorExtractor(_descriptorExtractor)
{
    CV_Assert( !descriptorExtractor.empty() );
}

void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, vector<Mat>& opponentChannels )
{
    if( bgrImage.type() != CV_8UC3 )
        CV_Error( CV_StsBadArg, "input image must be an BGR image of type CV_8UC3" );

    // Split image into RGB to allow conversion to Opponent Color Space.
    vector<Mat> bgrChannels(3);
    split( bgrImage, bgrChannels );

    // Prepare opponent color space storage matrices.
    opponentChannels.resize( 3 );
    opponentChannels[0] = cv::Mat(bgrImage.size(), CV_8UC1); // R-G RED-GREEN
    opponentChannels[1] = cv::Mat(bgrImage.size(), CV_8UC1); // R+G-2B YELLOW-BLUE
    opponentChannels[2] = cv::Mat(bgrImage.size(), CV_8UC1); // R+G+B

    // Calculate the channels of the opponent color space
    {
        // (R - G) / sqrt(2)
        MatConstIterator_<signed char> rIt = bgrChannels[2].begin<signed char>();
        MatConstIterator_<signed char> gIt = bgrChannels[1].begin<signed char>();
        MatIterator_<unsigned char> dstIt = opponentChannels[0].begin<unsigned char>();
        float factor = 1.f / sqrt(2.f);
        for( ; dstIt != opponentChannels[0].end<unsigned char>(); ++rIt, ++gIt, ++dstIt )
        {
            int value = static_cast<int>( static_cast<float>(static_cast<int>(*gIt)-static_cast<int>(*rIt)) * factor );
            if( value < 0 ) value = 0;
            if( value > 255 ) value = 255;
            (*dstIt) = static_cast<unsigned char>(value);
        }
    }
    {
        // (R + G - 2B)/sqrt(6)
        MatConstIterator_<signed char> rIt = bgrChannels[2].begin<signed char>();
        MatConstIterator_<signed char> gIt = bgrChannels[1].begin<signed char>();
        MatConstIterator_<signed char> bIt = bgrChannels[0].begin<signed char>();
        MatIterator_<unsigned char> dstIt = opponentChannels[1].begin<unsigned char>();
        float factor = 1.f / sqrt(6.f);
        for( ; dstIt != opponentChannels[1].end<unsigned char>(); ++rIt, ++gIt, ++bIt, ++dstIt )
        {
            int value = static_cast<int>( static_cast<float>(static_cast<int>(*rIt) + static_cast<int>(*gIt) - 2*static_cast<int>(*bIt)) *
                                          factor );
            if( value < 0 ) value = 0;
            if( value > 255 ) value = 255;
            (*dstIt) = static_cast<unsigned char>(value);
        }
    }
    {
        // (R + G + B)/sqrt(3)
        MatConstIterator_<signed char> rIt = bgrChannels[2].begin<signed char>();
        MatConstIterator_<signed char> gIt = bgrChannels[1].begin<signed char>();
        MatConstIterator_<signed char> bIt = bgrChannels[0].begin<signed char>();
        MatIterator_<unsigned char> dstIt = opponentChannels[2].begin<unsigned char>();
        float factor = 1.f / sqrt(3.f);
        for( ; dstIt != opponentChannels[2].end<unsigned char>(); ++rIt, ++gIt, ++bIt, ++dstIt )
        {
            int value = static_cast<int>( static_cast<float>(static_cast<int>(*rIt) + static_cast<int>(*gIt) + static_cast<int>(*bIt)) *
                                          factor );
            if( value < 0 ) value = 0;
            if( value > 255 ) value = 255;
            (*dstIt) = static_cast<unsigned char>(value);
        }
    }
}

struct KP_LessThan
{
    KP_LessThan(const vector<KeyPoint>& _kp) : kp(&_kp) {}
    bool operator()(int i, int j) const
    {
        return (*kp)[i].class_id < (*kp)[j].class_id;
    }
    const vector<KeyPoint>* kp;
};

void OpponentColorDescriptorExtractor::computeImpl( const Mat& bgrImage, vector<KeyPoint>& keypoints, Mat& descriptors ) const
{
    vector<Mat> opponentChannels;
    convertBGRImageToOpponentColorSpace( bgrImage, opponentChannels );

    const int N = 3; // channels count
    vector<KeyPoint> channelKeypoints[N];
    Mat channelDescriptors[N];
    vector<int> idxs[N];

    // Compute descriptors three times, once for each Opponent channel to concatenate into a single color descriptor
    int maxKeypointsCount = 0;
    for( int ci = 0; ci < N; ci++ )
    {
        channelKeypoints[ci].insert( channelKeypoints[ci].begin(), keypoints.begin(), keypoints.end() );
        // Use class_id member to get indices into initial keypoints vector
        for( size_t ki = 0; ki < channelKeypoints[ci].size(); ki++ )
            channelKeypoints[ci][ki].class_id = (int)ki;

        descriptorExtractor->compute( opponentChannels[ci], channelKeypoints[ci], channelDescriptors[ci] );
        idxs[ci].resize( channelKeypoints[ci].size() );
        for( size_t ki = 0; ki < channelKeypoints[ci].size(); ki++ )
        {
            idxs[ci][ki] = (int)ki;
        }
        std::sort( idxs[ci].begin(), idxs[ci].end(), KP_LessThan(channelKeypoints[ci]) );
        maxKeypointsCount = std::max( maxKeypointsCount, (int)channelKeypoints[ci].size());
    }

    vector<KeyPoint> outKeypoints;
    outKeypoints.reserve( keypoints.size() );

    int descriptorSize = descriptorExtractor->descriptorSize();
    Mat mergedDescriptors( maxKeypointsCount, 3*descriptorSize, descriptorExtractor->descriptorType() );
    int mergedCount = 0;
    // cp - current channel position
    size_t cp[] = {0, 0, 0};
    while( cp[0] < channelKeypoints[0].size() &&
           cp[1] < channelKeypoints[1].size() &&
           cp[2] < channelKeypoints[2].size() )
    {
        const int maxInitIdx = std::max( channelKeypoints[0][idxs[0][cp[0]]].class_id,
                                         std::max( channelKeypoints[1][idxs[1][cp[1]]].class_id,
                                                   channelKeypoints[2][idxs[2][cp[2]]].class_id ) );

        while( channelKeypoints[0][idxs[0][cp[0]]].class_id < maxInitIdx && cp[0] < channelKeypoints[0].size() ) { cp[0]++; }
        while( channelKeypoints[1][idxs[1][cp[1]]].class_id < maxInitIdx && cp[1] < channelKeypoints[1].size() ) { cp[1]++; }
        while( channelKeypoints[2][idxs[2][cp[2]]].class_id < maxInitIdx && cp[2] < channelKeypoints[2].size() ) { cp[2]++; }
        if( cp[0] >= channelKeypoints[0].size() || cp[1] >= channelKeypoints[1].size() || cp[2] >= channelKeypoints[2].size() )
            break;

        if( channelKeypoints[0][idxs[0][cp[0]]].class_id == maxInitIdx &&
            channelKeypoints[1][idxs[1][cp[1]]].class_id == maxInitIdx &&
            channelKeypoints[2][idxs[2][cp[2]]].class_id == maxInitIdx )
        {
            outKeypoints.push_back( keypoints[maxInitIdx] );
            // merge descriptors
            for( int ci = 0; ci < N; ci++ )
            {
                Mat dst = mergedDescriptors(Range(mergedCount, mergedCount+1), Range(ci*descriptorSize, (ci+1)*descriptorSize));
                channelDescriptors[ci].row( idxs[ci][cp[ci]] ).copyTo( dst );
                cp[ci]++;
            }
            mergedCount++;
        }
    }
    mergedDescriptors.rowRange(0, mergedCount).copyTo( descriptors );
    std::swap( outKeypoints, keypoints );
}

void OpponentColorDescriptorExtractor::read( const FileNode& fn )
{
    descriptorExtractor->read(fn);
}

void OpponentColorDescriptorExtractor::write( FileStorage& fs ) const
{
    descriptorExtractor->write(fs);
}

int OpponentColorDescriptorExtractor::descriptorSize() const
{
    return 3*descriptorExtractor->descriptorSize();
}

int OpponentColorDescriptorExtractor::descriptorType() const
{
    return descriptorExtractor->descriptorType();
}

bool OpponentColorDescriptorExtractor::empty() const
{
    return descriptorExtractor.empty() || (DescriptorExtractor*)(descriptorExtractor)->empty();
}

}
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * 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.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 *
 * --------------------------------------------------------------------
 *
 * This file was copied and slightly adapted from the KaleidoscopeJIT.h
 * unter the following licencse:
 *
 * ===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===
 *
 *                     The LLVM Compiler Infrastructure
 *
 * This file is distributed under the University of Illinois Open Source
 * License. See LICENSE.TXT for details.
 *
 */

#pragma once

#include <llvm/ExecutionEngine/Orc/IRCompileLayer.h>
#include <llvm/ExecutionEngine/Orc/JITSymbol.h>
#include <llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/Mangler.h>

#include <crossbow/singleton.hpp>

#include <memory>

namespace llvm {
class Module;
class TargetMachine;
} // namespace llvm

namespace tell {
namespace store {

/**
 * @brief Singleton for initializing and configuring the LLVM infrastructure
 *
 * Initializes the native target and sets up the TargetMachine with the features available on the host the application
 * is running.
 */
class LLVMCompilerT {
public:
    LLVMCompilerT();

    ~LLVMCompilerT();

    llvm::TargetMachine* targetMachine() {
        return mTargetMachine.get();
    }

private:
    std::unique_ptr<llvm::TargetMachine> mTargetMachine;
};

using LLVMCompiler = crossbow::singleton<LLVMCompilerT>;

extern LLVMCompiler llvmCompiler;

/**
 * @brief JIT based on LLVM
 */
class LLVMJIT {
public:
    using ObjectLayer = llvm::orc::ObjectLinkingLayer<>;
    using CompileLayer = llvm::orc::IRCompileLayer<ObjectLayer>;
    using ModuleHandle = CompileLayer::ModuleSetHandleT;

    LLVMJIT();

    llvm::TargetMachine* getTargetMachine() {
        return mTargetMachine;
    }

    /**
     * @brief Compile the given module through the JIT
     *
     * The compiled functions can then be retrieved through the LLVMJIT::findSymbol function. Afterwards the module can
     * be destroyed.
     */
    ModuleHandle addModule(llvm::Module* module);

    void removeModule(ModuleHandle handle) {
        mCompileLayer.removeModuleSet(handle);
    }

    llvm::orc::JITSymbol findSymbol(const std::string& name) {
        return mCompileLayer.findSymbol(mangle(name), true);
    }

private:
    std::string mangle(const std::string& name) {
        std::string mangledName;
        {
            llvm::raw_string_ostream mangledNameStream(mangledName);
            llvm::Mangler::getNameWithPrefix(mangledNameStream, name, mDataLayout);
        }
        return mangledName;
    }

    llvm::TargetMachine* mTargetMachine;
    llvm::DataLayout mDataLayout;
    ObjectLayer mObjectLayer;
    CompileLayer mCompileLayer;
};

} // namespace store
} // namespace tell
<commit_msg>Add findFunction and make LLVM Jit non copyable<commit_after>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * 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.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 *
 * --------------------------------------------------------------------
 *
 * This file was copied and slightly adapted from the KaleidoscopeJIT.h
 * unter the following licencse:
 *
 * ===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===
 *
 *                     The LLVM Compiler Infrastructure
 *
 * This file is distributed under the University of Illinois Open Source
 * License. See LICENSE.TXT for details.
 *
 */

#pragma once

#include <llvm/ExecutionEngine/Orc/IRCompileLayer.h>
#include <llvm/ExecutionEngine/Orc/JITSymbol.h>
#include <llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/Mangler.h>

#include <crossbow/non_copyable.hpp>
#include <crossbow/singleton.hpp>

#include <memory>

namespace llvm {
class Module;
class TargetMachine;
} // namespace llvm

namespace tell {
namespace store {

/**
 * @brief Singleton for initializing and configuring the LLVM infrastructure
 *
 * Initializes the native target and sets up the TargetMachine with the features available on the host the application
 * is running.
 */
class LLVMCompilerT {
public:
    LLVMCompilerT();

    ~LLVMCompilerT();

    llvm::TargetMachine* targetMachine() {
        return mTargetMachine.get();
    }

private:
    std::unique_ptr<llvm::TargetMachine> mTargetMachine;
};

using LLVMCompiler = crossbow::singleton<LLVMCompilerT>;

extern LLVMCompiler llvmCompiler;

/**
 * @brief JIT based on LLVM
 */
class LLVMJIT : crossbow::non_copyable, crossbow::non_movable {
public:
    using ObjectLayer = llvm::orc::ObjectLinkingLayer<>;
    using CompileLayer = llvm::orc::IRCompileLayer<ObjectLayer>;
    using ModuleHandle = CompileLayer::ModuleSetHandleT;

    LLVMJIT();

    llvm::TargetMachine* getTargetMachine() {
        return mTargetMachine;
    }

    /**
     * @brief Compile the given module through the JIT
     *
     * The compiled functions can then be retrieved through the LLVMJIT::findSymbol function. Afterwards the module can
     * be destroyed.
     */
    ModuleHandle addModule(llvm::Module* module);

    void removeModule(ModuleHandle handle) {
        mCompileLayer.removeModuleSet(handle);
    }

    llvm::orc::JITSymbol findSymbol(const std::string& name) {
        return mCompileLayer.findSymbol(mangle(name), true);
    }

    template <typename Func>
    Func findFunction(const std::string& name) {
        auto func = mCompileLayer.findSymbol(mangle(name), true);
        if (!func) {
            throw std::runtime_error("Unknown symbol");
        }
        return reinterpret_cast<Func>(func.getAddress());
    }

private:
    std::string mangle(const std::string& name) {
        std::string mangledName;
        {
            llvm::raw_string_ostream mangledNameStream(mangledName);
            llvm::Mangler::getNameWithPrefix(mangledNameStream, name, mDataLayout);
        }
        return mangledName;
    }

    llvm::TargetMachine* mTargetMachine;
    llvm::DataLayout mDataLayout;
    ObjectLayer mObjectLayer;
    CompileLayer mCompileLayer;
};

} // namespace store
} // namespace tell
<|endoftext|>